pax_global_header 0000666 0000000 0000000 00000000064 14517531055 0014520 g ustar 00root root 0000000 0000000 52 comment=d84532d32d940f9cbadaf54f0b98fe8b3950518e
optlang-1.8.1/ 0000775 0000000 0000000 00000000000 14517531055 0013173 5 ustar 00root root 0000000 0000000 optlang-1.8.1/.gitattributes 0000664 0000000 0000000 00000000106 14517531055 0016063 0 ustar 00root root 0000000 0000000 optlang/_version.py export-subst
src/optlang/_version.py export-subst
optlang-1.8.1/.github/ 0000775 0000000 0000000 00000000000 14517531055 0014533 5 ustar 00root root 0000000 0000000 optlang-1.8.1/.github/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000012225 14517531055 0017334 0 ustar 00root root 0000000 0000000
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[niko.sonnenschein@gmail.com](mailto:niko.sonnenschein@gmail.com).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
optlang-1.8.1/.github/CONTRIBUTING.rst 0000664 0000000 0000000 00000006502 14517531055 0017177 0 ustar 00root root 0000000 0000000 ============
Contributing
============
Contributions are welcome, and they are greatly appreciated! Every
little bit helps, and credit will always be given.
You can contribute in many ways:
Report Bugs
===========
Report bugs at https://github.com/opencobra/optlang/issues.
If you are reporting a bug, please follow the template guidelines. The more
detailed your report, the easier and thus faster we can help you.
Fix Bugs
========
Look through the GitHub issues for bugs. Anything tagged with "bug"
and "help wanted" is open to whoever wants to implement it.
Implement Features
==================
Look through the GitHub issues for features. Anything tagged with "enhancement"
and "help wanted" is open to whoever wants to implement it.
Write Documentation
===================
optlang could always use more documentation, whether as part of the
official documentation, in docstrings, or even on the web in blog posts,
articles, and such.
Submit Feedback
===============
The best way to send feedback is to file an issue at
https://github.com/opencobra/optlang/issues.
If you are proposing a feature:
* Explain in detail how it would work.
* Keep the scope as narrow as possible, to make it easier to implement.
* Remember that this is a volunteer-driven project, and that contributions
are welcome :)
Get Started!
============
Ready to contribute? Here's how to set up optlang for
local development.
1. Fork the https://github.com/opencobra/optlang
repository on GitHub.
2. Clone your fork locally
.. code-block:: console
git clone git@github.com:your_name_here/optlang.git
3. Install your local copy into a a Python virtual environment.
You can `read this guide to learn more
`_
about them and how to create one. Alternatively, particularly if you are a
Windows or Mac user, you can also use
`Anaconda `_. Assuming you have
virtualenvwrapper installed, this is how you set up your fork for local development
.. code-block:: console
mkvirtualenv my-env
cd optlang/
pip install -e .[development]
4. Create a branch for local development using the ``devel`` branch as a
starting point. Use ``fix`` or ``feat`` as a prefix
.. code-block:: console
git checkout devel
git checkout -b fix-name-of-your-bugfix
Now you can make your changes locally.
5. When you're done making changes, apply the quality assurance tools and check
that your changes pass our test suite. This is all included with tox
.. code-block:: console
make qa
tox
6. Commit your changes and push your branch to GitHub. Please use `semantic
commit messages `_.
.. code-block:: console
git add .
git commit -m "fix: Your summary of changes"
git push origin fix-name-of-your-bugfix
7. Open the link displayed in the message when pushing your new branch
in order to submit a pull request.
Pull Request Guidelines
=======================
Before you submit a pull request, check that it meets these guidelines:
1. The pull request should include tests.
2. If the pull request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring.
optlang-1.8.1/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 14517531055 0016716 5 ustar 00root root 0000000 0000000 optlang-1.8.1/.github/ISSUE_TEMPLATE/01-bug-report.md 0000664 0000000 0000000 00000001764 14517531055 0021554 0 ustar 00root root 0000000 0000000 ---
name: Bug report
about: Report a bug to help improve this project
---
#### Problem description
Please explain:
* **what** you tried to achieve,
* **how** you went about it (referring to the code sample), and
* **why** the current behaviour is a problem and what output
you expected instead.
#### Code Sample
Create a [minimal, complete, verifiable example](https://stackoverflow.com/help/mcve).
```python
```
```
```
### Context
```
```
optlang-1.8.1/.github/ISSUE_TEMPLATE/02-question.md 0000664 0000000 0000000 00000001000 14517531055 0021315 0 ustar 00root root 0000000 0000000 ---
name: Question
about: Ask a question
---
### Checklist
- [ ] I searched the [documentation](https://optlang.readthedocs.io).
- [ ] I looked through [similar issues on GitHub](https://github.com/opencobra/optlang/issues).
- [ ] I looked up "How to do ... in optlang" on a search engine.
### Question
optlang-1.8.1/.github/ISSUE_TEMPLATE/03-feature-request.md 0000664 0000000 0000000 00000001745 14517531055 0022610 0 ustar 00root root 0000000 0000000 ---
name: Feature request
about: Suggest an idea for this project
---
### Checklist
- [ ] There are [no similar issues or pull requests](https://github.com/opencobra/optlang/issues) for this yet.
### Is your feature related to a problem? Please describe it.
## Describe the solution you would like.
## Describe alternatives you considered
## Additional context
optlang-1.8.1/.github/PULL_REQUEST_TEMPLATE.md 0000664 0000000 0000000 00000000217 14517531055 0020334 0 ustar 00root root 0000000 0000000 * [ ] fix #(issue number)
* [ ] description of feature/fix
* [ ] tests added/passed
* [ ] add an entry to the [next release](../CHANGELOG.rst)
optlang-1.8.1/.github/SUPPORT.rst 0000664 0000000 0000000 00000000131 14517531055 0016434 0 ustar 00root root 0000000 0000000 =======
Support
=======
* optlang `gitter chat `_
optlang-1.8.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14517531055 0016570 5 ustar 00root root 0000000 0000000 optlang-1.8.1/.github/workflows/main.yml 0000664 0000000 0000000 00000004506 14517531055 0020244 0 ustar 00root root 0000000 0000000 name: CI-CD
on:
push:
branches:
- master
- devel
tags:
- '[0-9]+.[0-9]+.[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+rc[0-9]+'
pull_request:
branches:
- master
- devel
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
python -m pip install tox tox-gh-actions
- name: Test with tox
run: tox -- --cover-xml
env:
CI: true
- name: Report coverage
shell: bash
run: bash <(curl -s https://codecov.io/bash)
release:
needs: test
if: startsWith(github.ref, 'refs/tags')
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
python-version: [3.8]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Get tag
id: tag
run: echo "::set-output name=version::${GITHUB_REF#refs/tags/}"
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
python -m pip install twine
- name: Build package
run: python setup.py sdist bdist_wheel
- name: Check the package
run: twine check dist/*
- name: Publish to PyPI
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run:
twine upload --skip-existing --non-interactive dist/*
- name: Create GitHub release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
body: >
Please see
https://github.com/${{ github.repository }}/blob/${{ steps.tag.outputs.version }}/CHANGELOG.rst
for the full release notes.
draft: false
prerelease: false
optlang-1.8.1/.gitignore 0000664 0000000 0000000 00000000673 14517531055 0015171 0 ustar 00root root 0000000 0000000 tests/coverage/
tests/data/netlib_reference_results/*.txt.gz
optlang.sublime-workspace
*.log
*.py[cod]
# C extensions
*.so
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
__pycache__
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
.coveralls.yml
.idea
MANIFEST optlang-1.8.1/CHANGELOG.rst 0000664 0000000 0000000 00000004232 14517531055 0015215 0 ustar 00root root 0000000 0000000 =======
Next Release
-----
1.8.0
-----
* add a generic matrix interface to allow easy addition of new solvers
that expect an immutable problem in standard form as input
* replace the OSQP interface with a hybrid interface that uses HIGHS for (MI)LPs and
OSQP for QPs
* `osqp_interface` is now deprecated, will import the hybrid interface when used, and
will be removed entirely soon
1.7.0
-----
* remove deprecated numpy type casts
* The symbolics module now has consistent exports
* When sympy is used the internal Symbol class now derives from sympy.core.Dummy. This
circumvents the hack in place to make Symbols unique and makes optlang work with
sympy>=1.12 again.
* Updated the scipy and the jsonschema tests to work with newer versions of those packages.
* Package version dependencies are now more specific.
* Tests are run for sympy and symengine now.
* Updated support Python versions to >=3.8.
1.6.1
-----
* fix the Gurobi version check to allow 10.0
1.6.0
-----
* fixes problem scaling for GLPK
* fixes scaling output in GLPK that could not be turned off
* Major performance improvements in the Gurobi interface when getting primals,
shadow prices and reduced costs
* Now only supports gurobipy>=9.5
* Tests are now run with the Gurobi and CPLEX community editions
* Drop support for Python 2 and add support for Python 3.10
1.5.2
-----
* Gurobi can now serialize its configuration correctly. This also fixes pickling of Gurobi models.
* Fix the shim for integrality tolerance in OSQP which makes it easier to clone OSQP Models to other solvers.
* Fix an issue where one could not rename variables in Gurobi version 9.
1.5.1
-----
* GLPK now respects `Configuration.tolerances.integrality` again
1.5.0
-----
* removed support for Python 3.5
* added support for Python 3.9
* enabled code coverage in tox
* support symengine 0.7.0
* add [OSQP](https://github.com/oxfordcontrol/osqp) as additional solver
* add [cbc](https://github.com/coin-or/python-mip) as additional solver
1.4.7
-----
* fix: except AttributeError when setting tolerance on cloned Configuration
* enable cloning models between solver interfaces that do not support the same set of tolerance parameters
optlang-1.8.1/LICENSE 0000664 0000000 0000000 00000026075 14517531055 0014212 0 ustar 00root root 0000000 0000000 Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) 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. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
optlang-1.8.1/MANIFEST.in 0000664 0000000 0000000 00000000170 14517531055 0014727 0 ustar 00root root 0000000 0000000 include LICENSE
include README.rst
include versioneer.py
include src/optlang/_version.py
recursive-exclude slow_tests *
optlang-1.8.1/README.rst 0000664 0000000 0000000 00000015075 14517531055 0014672 0 ustar 00root root 0000000 0000000 optlang
=======
*Sympy based mathematical programming language*
|PyPI| |Python Versions| |License| |Code of Conduct| |GitHub Actions| |Coverage Status| |Documentation Status| |Gitter| |JOSS| |DOI|
Optlang is a Python package for solving mathematical optimization
problems, i.e. maximizing or minimizing an objective function over a set
of variables subject to a number of constraints. Optlang provides a
common interface to a series of optimization tools, so different solver
backends can be changed in a transparent way.
Optlang's object-oriented API takes advantage of the symbolic math library
`sympy `__ to allow objective functions
and constraints to be easily formulated from symbolic expressions of
variables (see examples).
Show us some love by staring this repo if you find optlang useful!
Also, please use the GitHub `issue tracker `_
to let us know about bugs or feature requests, or our `gitter channel `_ if you have problems or questions regarding optlang.
Installation
~~~~~~~~~~~~
Install using pip
::
pip install optlang
This will also install `swiglpk `_, an interface to the open source (mixed integer) LP solver `GLPK `_.
Quadratic programming (and MIQP) is supported through additional optional solvers (see below).
Dependencies
~~~~~~~~~~~~
The following dependencies are needed.
- `sympy >= 1.0.0 `__
- `six >= 1.9.0 `__
- `swiglpk >= 1.4.3 `__
The following are optional dependencies that allow other solvers to be used.
- `cplex `__ (LP, MILP, QP, MIQP)
- `gurobipy `__ (LP, MILP, QP, MIQP)
- `scipy `__ (LP)
- `osqp `__ (LP, QP)
Example
~~~~~~~
Formulating and solving the problem is straightforward (example taken
from `GLPK documentation `__):
.. code-block:: python
from __future__ import print_function
from optlang import Model, Variable, Constraint, Objective
# All the (symbolic) variables are declared, with a name and optionally a lower and/or upper bound.
x1 = Variable('x1', lb=0)
x2 = Variable('x2', lb=0)
x3 = Variable('x3', lb=0)
# A constraint is constructed from an expression of variables and a lower and/or upper bound (lb and ub).
c1 = Constraint(x1 + x2 + x3, ub=100)
c2 = Constraint(10 * x1 + 4 * x2 + 5 * x3, ub=600)
c3 = Constraint(2 * x1 + 2 * x2 + 6 * x3, ub=300)
# An objective can be formulated
obj = Objective(10 * x1 + 6 * x2 + 4 * x3, direction='max')
# Variables, constraints and objective are combined in a Model object, which can subsequently be optimized.
model = Model(name='Simple model')
model.objective = obj
model.add([c1, c2, c3])
status = model.optimize()
print("status:", model.status)
print("objective value:", model.objective.value)
print("----------")
for var_name, var in model.variables.iteritems():
print(var_name, "=", var.primal)
The example will produce the following output:
::
status: optimal
objective value: 733.333333333
----------
x2 = 66.6666666667
x3 = 0.0
x1 = 33.3333333333
Using a particular solver
-------------------------
If you have more than one solver installed, it's also possible to specify which one to use, by importing directly from the
respective solver interface, e.g. :code:`from optlang.glpk_interface import Model, Variable, Constraint, Objective`
Documentation
~~~~~~~~~~~~~
Documentation for optlang is provided at
`readthedocs.org `__.
Citation
~~~~~~~~
Please cite |JOSS| if you use optlang in a scientific publication. In case you would like to reference a specific version of of optlang you can also include the respective Zenodo DOI (|DOI| points to the latest version).
Contributing
~~~~~~~~~~~~
Please read ``__.
Funding
~~~~~~~
The development of optlang was partly support by the Novo Nordisk Foundation.
Future outlook
~~~~~~~~~~~~~~
- `Mosek `__ interface (provides academic
licenses)
- `GAMS `__ output (support non-linear problem
formulation)
- `DEAP `__ (support for heuristic
optimization)
- Interface to `NEOS `__ optimization
server (for testing purposes and solver evaluation)
- Automatically handle fractional and absolute value problems when
dealing with LP/MILP/QP solvers (like GLPK,
`CPLEX `__
etc.)
.. |PyPI| image:: https://img.shields.io/pypi/v/optlang.svg
:target: https://pypi.org/project/optlang/
:alt: Current PyPI Version
.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/optlang.svg
:target: https://pypi.org/project/optlang/
:alt: Supported Python Versions
.. |License| image:: https://img.shields.io/pypi/l/optlang.svg
:target: https://www.apache.org/licenses/LICENSE-2.0
:alt: Apache Software License Version 2.0
.. |Code of Conduct| image:: https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg
:target: .github/CODE_OF_CONDUCT.md
:alt: Code of Conduct
.. |GitHub Actions| image:: https://github.com/opencobra/optlang/workflows/CI-CD/badge.svg
:target: https://github.com/opencobra/optlang/workflows/CI-CD
:alt: GitHub Actions
.. |Coverage Status| image:: https://codecov.io/gh/opencobra/optlang/branch/master/graph/badge.svg
:target: https://codecov.io/gh/opencobra/optlang
:alt: Codecov
.. |Documentation Status| image:: https://readthedocs.org/projects/optlang/badge/?version=latest
:target: https://readthedocs.org/projects/optlang/?badge=latest
:alt: Documentation Status
.. |JOSS| image:: http://joss.theoj.org/papers/cd848071a664d696e214a3950c840e15/status.svg
:target: http://joss.theoj.org/papers/cd848071a664d696e214a3950c840e15
:alt: Publication
.. |DOI| image:: https://zenodo.org/badge/5031/biosustain/optlang.svg
:target: https://zenodo.org/badge/latestdoi/5031/biosustain/optlang
:alt: Zenodo Source Code
.. |Gitter| image:: https://badges.gitter.im/biosustain/optlang.svg
:target: https://gitter.im/biosustain/optlang?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
:alt: Join the chat at https://gitter.im/biosustain/optlang
optlang-1.8.1/docs/ 0000775 0000000 0000000 00000000000 14517531055 0014123 5 ustar 00root root 0000000 0000000 optlang-1.8.1/docs/Makefile 0000664 0000000 0000000 00000012711 14517531055 0015565 0 ustar 00root root 0000000 0000000 # Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make ' where is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/optlang.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/optlang.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/optlang"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/optlang"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
optlang-1.8.1/docs/make.bat 0000664 0000000 0000000 00000011763 14517531055 0015540 0 ustar 00root root 0000000 0000000 @ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
set I18NSPHINXOPTS=%SPHINXOPTS% source
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^` where ^ is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\optlang.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\optlang.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end
optlang-1.8.1/docs/source/ 0000775 0000000 0000000 00000000000 14517531055 0015423 5 ustar 00root root 0000000 0000000 optlang-1.8.1/docs/source/API.rst 0000664 0000000 0000000 00000000154 14517531055 0016566 0 ustar 00root root 0000000 0000000 API reference
=============
.. toctree::
Model
Variable
Constraint
Objective
Configuration
optlang-1.8.1/docs/source/Configuration.rst 0000664 0000000 0000000 00000000334 14517531055 0020764 0 ustar 00root root 0000000 0000000 Configuration
=============
Optlang provides high-level solver configuration via :attr:`interface.Model.configuration`.
.. autoclass:: optlang.interface.Configuration
:members:
:undoc-members:
:show-inheritance:
optlang-1.8.1/docs/source/Constraint.rst 0000664 0000000 0000000 00000000166 14517531055 0020304 0 ustar 00root root 0000000 0000000 Constraint
==========
.. autoclass:: optlang.interface.Constraint
:members:
:undoc-members:
:show-inheritance:
optlang-1.8.1/docs/source/Model.rst 0000664 0000000 0000000 00000001262 14517531055 0017216 0 ustar 00root root 0000000 0000000 Model
=====
The model object represents an optimization problem and contains the variables, constraints an objective that make up the problem. Variables and constraints can be added and removed using the :code:`.add` and :code:`.remove` methods, while the objective can be changed by setting the objective attribute, e.g. :code:`model.objective = Objective(expr, direction="max")`.
Once the problem has been formulated the optimization can be performed by calling the :code:`.optimize` method. This will return the status of the optimization, most commonly 'optimal', 'infeasible' or 'unbounded'.
.. autoclass:: optlang.interface.Model
:members:
:undoc-members:
:show-inheritance:
optlang-1.8.1/docs/source/Objective.rst 0000664 0000000 0000000 00000000163 14517531055 0020067 0 ustar 00root root 0000000 0000000 Objective
=========
.. autoclass:: optlang.interface.Objective
:members:
:undoc-members:
:show-inheritance:
optlang-1.8.1/docs/source/Variable.rst 0000664 0000000 0000000 00000001775 14517531055 0017714 0 ustar 00root root 0000000 0000000 Variable
========
Variable objects are used to represents each variable of the optimization problem. When the optimization is performed, the combination of variable values that optimizes the objective function, while not violating any constraints will be identified.
The type of a variable ('continuous', 'integer' or 'binary') can be set using the :code:`type` keyword of the constructor or it can be changed after initialization by :code:`var.type = 'binary'`.
The variable class subclasses the :code:`sympy.Symbol` class, which means that symbolic expressions of variables can be constructed by using regular python syntax, e.g. :code:`my_expression = 2 * var1 + 3 * var2 ** 2`. Expressions like this are used when constructing Constraint and Objective objects.
Once a problem has been optimized, the primal and dual values of a variable can be accessed from the :code:`primal` and :code:`dual` attributes, respectively.
.. autoclass:: optlang.interface.Variable
:members:
:undoc-members:
:show-inheritance:
optlang-1.8.1/docs/source/conf.py 0000664 0000000 0000000 00000020537 14517531055 0016731 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
#
# optlang documentation build configuration file, created by
# sphinx-quickstart on Thu Nov 28 09:54:22 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
import sys
import sphinx_rtd_theme
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('../../'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', 'sphinx.ext.coverage',
'sphinx.ext.mathjax', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', 'sphinx.ext.napoleon']
mathjax_path = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'optlang'
copyright = u'2013, Niko Sonnenschein'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
sys.path.insert(0, '.')
sys.path.insert(0, '../') # to get the versioneer module
import versioneer
versioneer.VCS = 'git'
versioneer.versionfile_source = '../cameo/_version.py'
versioneer.versionfile_build = '../cameo/_version.py'
versioneer.tag_prefix = '' # tags are like 1.2.0
versioneer.parentdir_prefix = 'myproject-' # dirname like 'myproject-1.2.0'
release = versioneer.get_version()
version = release
sys.path.pop(0)
sys.path.pop(0)
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}
# If false, no module index is generated.
# html_domain_indices = True
# If false, no index is generated.
# html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'optlangdoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
# 'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'optlang.tex', u'optlang Documentation',
u'Niko Sonnenschein', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
# If true, show page references after internal links.
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
# latex_appendices = []
# If false, no module index is generated.
# latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'optlang', u'optlang Documentation',
[u'Niko Sonnenschein'], 1)
]
# If true, show URL addresses after external links.
# man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'optlang', u'optlang Documentation',
u'Niko Sonnenschein', 'optlang', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
# texinfo_appendices = []
# If false, no module index is generated.
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
# texinfo_show_urls = 'footnote'
optlang-1.8.1/docs/source/developers.rst 0000664 0000000 0000000 00000003372 14517531055 0020332 0 ustar 00root root 0000000 0000000 Contribute
==========
Contributions to optlang are very welcome. Fork optlang at `github
`_, implement your feature and send us
a pull request. Also, please use the GitHub `issue tracker `_
to let us know about bugs or feature requests, or if you have problems or questions regarding optlang.
Add solver interface
--------------------
Put your interface for new solver *XYZ* into a python module with the
name xyz_interface.py. Please use the existing solver interfaces as a reference
for how to wrap a solver. For example, start by subclassing :class:`interface.Model`.
.. code-block:: python
class Model(interface.Model):
def __init__(self, problem=None, *args, **kwargs):
super(Model, self).__init__(*args, **kwargs)
Then you can override the abstract methods defined in :class:`interface.Model`. For
example, override :func:`~interface.Model._add_constraints`.
.. code-block:: python
def _add_constraint(self, constraint):
# Check that constraint is actually supported by XYZ
if not constraint.is_Linear:
raise ValueError("XYZ only supports linear constraints. %s is not linear." % constraint)
# Add the constraint to the user level interface
super(Model, self)._add_constraint(constraint)
# Add variables that are not yet in the model ...
for var in constraint.variables:
if var.name not in self.variables:
self._add_variable(var)
# Link the model to the constraint
constraint.problem = self
# Add solver specific code ...
xyz_add_rows(self.problem, 1)
index = xyz_get_num_rows(self.problem)
xyz_set_row_name(self.problem, index, constraint.name)
...
optlang-1.8.1/docs/source/index.rst 0000664 0000000 0000000 00000017524 14517531055 0017275 0 ustar 00root root 0000000 0000000 optlang
*******
Optlang is a Python package implementing a modeling language for solving mathematical optimization problems, i.e. maximizing or minimizing an objective function over a set of variables subject to a number of constraints.
Optlang provides a common interface to a series of optimization tools, so different solver backends can be changed in a transparent way.
In constrast to e.g. the commonly used General Algebraic Modeling System (GAMS), optlang has a simple and intuitive interface using native Python algebra syntax, and is free and open-source.
Optlang takes advantage of the symbolic math library `SymPy `_ to allow objective functions and constraints to be easily formulated from symbolic expressions of variables (see examples).
Scientists can thus use optlang to formulate their optimization problems using mathematical expressions derived from domain knowledge.
Currently supported solvers are:
* `GLPK `_ (LP/MILP; via `swiglpk `_)
* `CPLEX `_ (LP/MILP/QP)
* `Gurobi `_ (LP/MILP/QP)
* `inspyred `_ (heuristic optimization; experimental)
* `OSQP `_ (LP/QP) OSQP is an efficient open source solver for Quadratic Programs. Alternatively, optlang can use cuOSQP which provides an experimental cuda-enabled implementation.
* `Cbc `_ (LP/MILP)
Support for the following solvers is in the works:
* `GAMS `_ (LP/MILP/QP/NLP; will include support for solving problems on `neos-server.org `_)
* `SOPLEX `_ (exact LP)
* `MOSEK `_, (LP/MILP/QP)
Quick start
===========
Consider the following linear programming optimization problem (example taken from `GLPK documentation `_):
.. math::
\begin{aligned}
Max~ & ~ 10 x_1 + 6 x_2 + 4 x_3 \\
s.t.~ & ~ x_1 + x_2 + x_3 <= 100 \\
~ & ~ 10 x_1 + 4 x_2 + 5 x_3 <= 600 \\
~ & ~ 2 x_1 + 2 x_2 + 6 x_3 <= 300 \\
~ & ~ x_1 \geq 0, x_2 \geq 0, x_3 \geq 0
\end{aligned}
Formulating and solving the problem is straightforward
.. code-block:: python
from optlang import Model, Variable, Constraint, Objective
# All the (symbolic) variables are declared, with a name and optionally a lower and/or upper bound.
x1 = Variable('x1', lb=0)
x2 = Variable('x2', lb=0)
x3 = Variable('x3', lb=0)
# A constraint is constructed from an expression of variables and a lower and/or upper bound (lb and ub).
c1 = Constraint(x1 + x2 + x3, ub=100)
c2 = Constraint(10 * x1 + 4 * x2 + 5 * x3, ub=600)
c3 = Constraint(2 * x1 + 2 * x2 + 6 * x3, ub=300)
# An objective can be formulated
obj = Objective(10 * x1 + 6 * x2 + 4 * x3, direction='max')
# Variables, constraints and objective are combined in a Model object, which can subsequently be optimized.
model = Model(name='Simple model')
model.objective = obj
model.add([c1, c2, c3])
status = model.optimize()
print("status:", model.status)
print("objective value:", model.objective.value)
print("----------")
for var_name, var in model.variables.items():
print(var_name, "=", var.primal)
You should see the following output::
status: optimal
objective value: 733.333333333
----------
x2 = 66.6666666667
x3 = 0.0
x1 = 33.3333333333
Using a particular solver
----------
If you have more than one solver installed, it's also possible to specify which one to use, by importing directly from the
respective solver interface, e.g. :code:`from optlang.glpk_interface import Model, Variable, Constraint, Objective`
Quadratic programming
----------
A QP problem can be generated in the same way by creating an objective with a quadratic expression. In the above example
the objective could be :code:`obj = Objective(x1 ** 2 + x2 ** 2 - 10 * x1, direction="min")` to specify a quadratic minimization
problem.
Integer programming
----------
Integer (or mixed integer) problems can be specified by assigning the type of one or more variables to 'integer' or 'binary'.
If the solver supports integer problems it will automatically use the relevant optimization algorithm and return an integer solution.
Example
============
The GAMS example (http://www.gams.com/docs/example.htm) can be formulated and solved in optlang like this:
.. code-block:: python
from optlang import Variable, Constraint, Objective, Model
# Define problem parameters
# Note this can be done using any of Python's data types. Here we have chosen dictionaries
supply = {"Seattle": 350, "San_Diego": 600}
demand = {"New_York": 325, "Chicago": 300, "Topeka": 275}
distances = { # Distances between locations in thousands of miles
"Seattle": {"New_York": 2.5, "Chicago": 1.7, "Topeka": 1.8},
"San_Diego": {"New_York": 2.5, "Chicago": 1.8, "Topeka": 1.4}
}
freight_cost = 9 # Cost per case per thousand miles
# Define variables
variables = {}
for origin in supply:
variables[origin] = {}
for destination in demand:
# Construct a variable with a name, bounds and type
var = Variable(name="{}_to_{}".format(origin, destination), lb=0, type="integer")
variables[origin][destination] = var
# Define constraints
constraints = []
for origin in supply:
const = Constraint(
sum(variables[origin].values()),
ub=supply[origin],
name="{}_supply".format(origin)
)
constraints.append(const)
for destination in demand:
const = Constraint(
sum(row[destination] for row in variables.values()),
lb=demand[destination],
name="{}_demand".format(destination)
)
constraints.append(const)
# Define the objective
obj = Objective(
sum(freight_cost * distances[ori][dest] * variables[ori][dest] for ori in supply for dest in demand),
direction="min"
)
# We can print the objective and constraints
print(obj)
print("")
for const in constraints:
print(const)
print("")
# Put everything together in a Model
model = Model()
model.add(constraints) # Variables are added implicitly
model.objective = obj
# Optimize and print the solution
status = model.optimize()
print("Status:", status)
print("Objective value:", model.objective.value)
print("")
for var in model.variables:
print(var.name, ":", var.primal)
Outputting the following::
Minimize
16.2*San_Diego_to_Chicago + 22.5*San_Diego_to_New_York + 12.6*San_Diego_to_Topeka + 15.3*Seattle_to_Chicago + 22.5*Seattle_to_New_York + 16.2*Seattle_to_Topeka
Seattle_supply: Seattle_to_Chicago + Seattle_to_New_York + Seattle_to_Topeka <= 350
San_Diego_supply: San_Diego_to_Chicago + San_Diego_to_New_York + San_Diego_to_Topeka <= 600
Chicago_demand: 300 <= San_Diego_to_Chicago + Seattle_to_Chicago
Topeka_demand: 275 <= San_Diego_to_Topeka + Seattle_to_Topeka
New_York_demand: 325 <= San_Diego_to_New_York + Seattle_to_New_York
Status: optimal
Objective value: 15367.5
Seattle_to_New_York : 50
Seattle_to_Chicago : 300
Seattle_to_Topeka : 0
San_Diego_to_Chicago : 0
San_Diego_to_Topeka : 275
San_Diego_to_New_York : 275
Here we forced all variables to have integer values. To allow non-integer values, leave out :code:`type="integer"` in the Variable constructor (defaults to :code:`'continuous'`).
Users's guide
=============
.. toctree::
installation
developers
API
.. problem_formulation
.. optimization_and_solution_retrieval
.. solver_parameters
.. logging
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
optlang-1.8.1/docs/source/installation.rst 0000664 0000000 0000000 00000004310 14517531055 0020654 0 ustar 00root root 0000000 0000000 Installation
============
Install optlang using pip::
pip install optlang
Solvers
----------
To solve optimization problems, at least one supported solver must be installed.
Installing optlang using :code:`pip` will also automatically install GLPK. To use other solvers (e.g. commercial solvers) it is necessary
to install them manually. Optlang interfaces with all solvers through importable python modules. If the python module corresponding
to the solver can be imported without errors the solver interface should be available as an optlang submodule (e.g.
:code:`optlang.glpk_interface`).
The required python modules for the currently supported solvers are:
- GLPK: :code:`swiglpk` (automatically installed by :code:`pip install optlang`)
- GLPK is an open source Linear Programming library. Swiglpk can be installed from binary wheels or from source. Installing from source requires swig and GLPK.
- Cplex: :code:`cplex`
- Cplex is a very efficient commercial linear and quadratic mixed-integer solver from IBM. Academic licenses are available for students and researchers.
- Gurobi: :code:`gurobipy`
- Gurobi is a very efficient commercial linear and quadratic mixed-integer solver. Academic licenses are available for students and researchers.
- SciPy: :code:`scipy.optimize.linprog`
- The SciPy linprog function is a very basic implementation of the simplex algorithm for solving linear optimization problems. Linprog is included in all recent versions of SciPy.
- OSQP: :code:`osqp | cuosqp`
- OSQP is an efficient open source solver for Quadratic Programs. It is self-contained and can be installed via pip. Alternatively, cuOSQP provides an experimental cuda-enabled implementation.
- Cbc: :code:`mip`
- Cbc (Coin-or branch and cut) is an open-source mixed integer linear programming solver written in C++. It can be installed via mip (python3 only).
After importing optlang you can check :code:`optlang.available_solvers` to verify that a solver is recognized.
Issues
------
Local installations like
::
python setup.py install
might fail installing the dependencies (unresolved issue with
``easy_install``). Running
::
pip install -r requirements.txt
beforehand should fix this issue.
optlang-1.8.1/docs/source/logging.rst 0000664 0000000 0000000 00000000024 14517531055 0017577 0 ustar 00root root 0000000 0000000 Logging
=======
... optlang-1.8.1/docs/source/optimization_and_solution_retrieval.rst 0000664 0000000 0000000 00000000114 14517531055 0025532 0 ustar 00root root 0000000 0000000 Optimization and solution retrieval
===================================
... optlang-1.8.1/docs/source/problem_formulation.rst 0000664 0000000 0000000 00000000054 14517531055 0022233 0 ustar 00root root 0000000 0000000 Problem formulation
===================
... optlang-1.8.1/docs/source/solver_parameters.rst 0000664 0000000 0000000 00000000131 14517531055 0021705 0 ustar 00root root 0000000 0000000 Solver configuration
====================
`Model.configuration` provides the means for
optlang-1.8.1/examples/ 0000775 0000000 0000000 00000000000 14517531055 0015011 5 ustar 00root root 0000000 0000000 optlang-1.8.1/examples/simple.py 0000664 0000000 0000000 00000002376 14517531055 0016664 0 ustar 00root root 0000000 0000000 # Copyright 2013 Novo Nordisk Foundation Center for Biosustainability,
# Technical University of Denmark.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import six
from optlang import Model, Variable, Constraint, Objective
x1 = Variable('x1', lb=0)
x2 = Variable('x2', lb=0)
x3 = Variable('x3', lb=0)
c1 = Constraint(x1 + x2 + x3, ub=100)
c2 = Constraint(10 * x1 + 4 * x2 + 5 * x3, ub=600)
c3 = Constraint(2 * x1 + 2 * x2 + 6 * x3, ub=300)
obj = Objective(10 * x1 + 6 * x2 + 4 * x3, direction='max')
model = Model(name='Simple model')
model.objective = obj
model.add([c1, c2, c3])
status = model.optimize()
print("status:", model.status)
print("objective value:", model.objective.value)
for var_name, var in six.iteritems(model.variables):
print(var_name, "=", var.primal)
optlang-1.8.1/examples/simple_numpy.py 0000664 0000000 0000000 00000001430 14517531055 0020102 0 ustar 00root root 0000000 0000000 import numpy as np
from optlang import Model, Variable, Constraint, Objective
# All the (symbolic) variables are declared, with a name and optionally a lower
# and/or upper bound.
x = np.array([Variable('x{}'.format(i), lb=0) for i in range(1, 4)])
bounds = [100, 600, 300]
A = np.array([[1, 1, 1],
[10, 4, 5],
[2, 2, 6]])
w = np.array([10, 6, 4])
obj = Objective(w.dot(x), direction='max')
c = np.array([Constraint(row, ub=bound) for row, bound in zip(A.dot(x), bounds)])
model = Model(name='Numpy model')
model.objective = obj
model.add(c)
status = model.optimize()
print("status:", model.status)
print("objective value:", model.objective.value)
print("----------")
for var_name, var in model.variables.iteritems():
print(var_name, "=", var.primal)
optlang-1.8.1/optlang.ipynb 0000664 0000000 0000000 00000043723 14517531055 0015713 0 ustar 00root root 0000000 0000000 {
"metadata": {
"name": "",
"signature": "sha256:5793db1e64fac3e9dae0f1e877064c1145c0068b0584d0e2d8bb06b7b3d16ab0"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "code",
"collapsed": false,
"input": [
"import optlang"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Cplex interface"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from cplex import Cplex\n",
"from optlang.cplex_interface import Model"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"cplex_problem = Cplex()\n",
"cplex_problem.read(\"./tests/data/model.lp\")\n",
"solver = Model(problem=cplex_problem)\n",
"print solver"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\\ENCODING=ISO-8859-1\n",
"\\Problem name: ./tests/data/model.lp\n",
"\n",
"Maximize\n",
" obj: R_Biomass_Ecoli_core_w_GAM\n",
"Subject To\n",
" M_13dpg_c: R_PGK + R_GAPD = 0\n",
" M_2pg_c: - R_PGM - R_ENO = 0\n",
" M_3pg_c: - 1.496 R_Biomass_Ecoli_core_w_GAM - R_PGK + R_PGM = 0\n",
" M_6pgc_c: R_PGL - R_GND = 0\n",
" M_6pgl_c: - R_PGL + R_G6PDH2r = 0\n",
" M_ac_c: R_ACt2r - R_ACKr = 0\n",
" M_ac_e: - R_ACt2r - R_EX_ac_e = 0\n",
" M_acald_c: R_ALCD2x + R_ACALDt - R_ACALD = 0\n",
" M_acald_e: - R_ACALDt - R_EX_acald_e = 0\n",
" M_accoa_c: - 3.7478 R_Biomass_Ecoli_core_w_GAM + R_ACALD - R_PTAr + R_PFL\n",
" + R_PDH - R_MALS - R_CS = 0\n",
" M_acon_C_c: - R_ACONTb + R_ACONTa = 0\n",
" M_actp_c: R_ACKr + R_PTAr = 0\n",
" M_adp_c: 59.81 R_Biomass_Ecoli_core_w_GAM + R_PGK + R_ACKr + R_SUCOAS\n",
" - R_PYK + R_PPCK + R_PFK + R_GLNabc + R_GLNS - R_ATPS4r + R_ATPM\n",
" + 2 R_ADK1 = 0\n",
" M_akg_c: 4.1182 R_Biomass_Ecoli_core_w_GAM + R_ICDHyr - R_GLUSy + R_GLUDy\n",
" + R_AKGt2r - R_AKGDH = 0\n",
" M_akg_e: - R_AKGt2r - R_EX_akg_e = 0\n",
" M_amp_c: - R_ADK1 + R_PPS = 0\n",
" M_atp_c: - 59.81 R_Biomass_Ecoli_core_w_GAM - R_PGK - R_ACKr - R_SUCOAS\n",
" + R_PYK - R_PPCK - R_PFK - R_GLNabc - R_GLNS + R_ATPS4r - R_ATPM\n",
" - R_ADK1 - R_PPS = 0\n",
" M_cit_c: R_CS - R_ACONTa = 0\n",
" M_co2_c: R_GND + R_PDH + R_PPCK + R_ICDHyr + R_AKGDH - R_PPC + R_ME2\n",
" + R_ME1 + R_CO2t = 0\n",
" M_co2_e: - R_CO2t - R_EX_co2_e = 0\n",
" M_coa_c: 3.7478 R_Biomass_Ecoli_core_w_GAM - R_ACALD + R_PTAr - R_PFL\n",
" - R_PDH + R_MALS + R_CS - R_SUCOAS - R_AKGDH = 0\n",
" M_dhap_c: - R_TPI + R_FBA = 0\n",
" M_e4p_c: - 0.361 R_Biomass_Ecoli_core_w_GAM - R_TKT2 + R_TALA = 0\n",
" M_etoh_c: - R_ALCD2x + R_ETOHt2r = 0\n",
" M_etoh_e: - R_ETOHt2r - R_EX_etoh_e = 0\n",
" M_f6p_c: - 0.0709 R_Biomass_Ecoli_core_w_GAM - R_PFK + R_TKT2 + R_TALA\n",
" + R_PGI + R_FRUpts2 + R_FBP = 0\n",
" M_fdp_c: R_PFK - R_FBA - R_FBP = 0\n",
" M_for_c: R_PFL - R_FORti + R_FORt2 = 0\n",
" M_for_e: R_FORti - R_FORt2 - R_EX_for_e = 0\n",
" M_fru_e: - R_FRUpts2 - R_EX_fru_e = 0\n",
" M_fum_c: R_SUCDi + R_FUMt2_2 - R_FUM - R_FRD7 = 0\n",
" M_fum_e: - R_FUMt2_2 - R_EX_fum_e = 0\n",
" M_g3p_c: - 0.129 R_Biomass_Ecoli_core_w_GAM - R_GAPD + R_TPI + R_FBA\n",
" + R_TKT2 - R_TALA + R_TKT1 = 0\n",
" M_g6p_c: - 0.205 R_Biomass_Ecoli_core_w_GAM - R_G6PDH2r - R_PGI + R_GLCpts\n",
" = 0\n",
" M_glc_D_e: - R_GLCpts - R_EX_glc_e = 0\n",
" M_gln_L_c: - 0.2557 R_Biomass_Ecoli_core_w_GAM + R_GLNabc + R_GLNS - R_GLUSy\n",
" - R_GLUN = 0\n",
" M_gln_L_e: - R_GLNabc - R_EX_gln_L_e = 0\n",
" M_glu_L_c: - 4.9414 R_Biomass_Ecoli_core_w_GAM - R_GLNS + 2 R_GLUSy - R_GLUDy\n",
" + R_GLUN + R_GLUt2r = 0\n",
" M_glu_L_e: - R_GLUt2r - R_EX_glu_L_e = 0\n",
" M_glx_c: - R_MALS + R_ICL = 0\n",
" M_h2o_c: - 59.81 R_Biomass_Ecoli_core_w_GAM + R_ENO - R_PGL - R_MALS - R_CS\n",
" - R_ACONTb + R_ACONTa - R_GLNabc + R_ATPS4r - R_ATPM - R_GLUDy\n",
" - R_PPS - R_PPC - R_FBP - R_FUM - R_GLUN + R_H2Ot + R_CYTBD = 0\n",
" M_h2o_e: - R_H2Ot - R_EX_h2o_e = 0\n",
" M_h_c: 59.81 R_Biomass_Ecoli_core_w_GAM + R_GAPD + R_PGL + R_G6PDH2r\n",
" + R_ACt2r + R_ALCD2x + R_ACALD + R_MALS + R_CS - R_PYK + R_PFK\n",
" + R_GLNabc + R_GLNS + 3 R_ATPS4r + R_ATPM - R_GLUSy + R_GLUDy\n",
" + R_AKGt2r + 2 R_PPS + R_PPC + R_ETOHt2r + R_FORt2 + 2 R_FUMt2_2\n",
" + R_GLUt2r - 2 R_CYTBD + 2 R_THD2 + R_SUCCt3 + 2 R_SUCCt2_2\n",
" + R_PYRt2r + R_PIt2r - 4 R_NADH16 + R_MDH + 2 R_MALt2_2 + R_LDH_D\n",
" + R_D_LACt2 = 0\n",
" M_h_e: - R_ACt2r - 4 R_ATPS4r - R_AKGt2r - R_ETOHt2r - R_FORt2\n",
" - 2 R_FUMt2_2 - R_GLUt2r + 2 R_CYTBD - 2 R_THD2 - R_SUCCt3\n",
" - 2 R_SUCCt2_2 - R_PYRt2r - R_PIt2r + 3 R_NADH16 - 2 R_MALt2_2\n",
" - R_D_LACt2 - R_EX_h_e = 0\n",
" M_icit_c: R_ACONTb - R_ICDHyr - R_ICL = 0\n",
" M_lac_D_c: - R_LDH_D + R_D_LACt2 = 0\n",
" M_lac_D_e: - R_D_LACt2 - R_EX_lac_D_e = 0\n",
" M_mal_L_c: R_MALS - R_ME2 - R_ME1 + R_FUM - R_MDH + R_MALt2_2 = 0\n",
" M_mal_L_e: - R_MALt2_2 - R_EX_mal_L_e = 0\n",
" M_nad_c: - 3.547 R_Biomass_Ecoli_core_w_GAM - R_GAPD - R_ALCD2x - R_ACALD\n",
" - R_PDH - R_AKGDH - R_ME1 + R_THD2 + R_NADH16 - R_MDH - R_LDH_D\n",
" - R_NADTRHD = 0\n",
" M_nadh_c: 3.547 R_Biomass_Ecoli_core_w_GAM + R_GAPD + R_ALCD2x + R_ACALD\n",
" + R_PDH + R_AKGDH + R_ME1 - R_THD2 - R_NADH16 + R_MDH + R_LDH_D\n",
" + R_NADTRHD = 0\n",
" M_nadp_c: 13.0279 R_Biomass_Ecoli_core_w_GAM - R_GND - R_G6PDH2r - R_ICDHyr\n",
" + R_GLUSy - R_GLUDy - R_ME2 - R_THD2 + R_NADTRHD = 0\n",
" M_nadph_c: - 13.0279 R_Biomass_Ecoli_core_w_GAM + R_GND + R_G6PDH2r\n",
" + R_ICDHyr - R_GLUSy + R_GLUDy + R_ME2 + R_THD2 - R_NADTRHD = 0\n",
" M_nh4_c: - R_GLNS + R_GLUDy + R_GLUN + R_NH4t = 0\n",
" M_nh4_e: - R_NH4t - R_EX_nh4_e = 0\n",
" M_o2_c: - 0.5 R_CYTBD + R_O2t = 0\n",
" M_o2_e: - R_O2t - R_EX_o2_e = 0\n",
" M_oaa_c: - 1.7867 R_Biomass_Ecoli_core_w_GAM - R_CS - R_PPCK + R_PPC\n",
" + R_MDH = 0\n",
" M_pep_c: - 0.5191 R_Biomass_Ecoli_core_w_GAM + R_ENO - R_PYK + R_PPCK\n",
" + R_PPS - R_PPC - R_FRUpts2 - R_GLCpts = 0\n",
" M_pi_c: 59.81 R_Biomass_Ecoli_core_w_GAM - R_GAPD - R_PTAr + R_SUCOAS\n",
" + R_GLNabc + R_GLNS - R_ATPS4r + R_ATPM + R_PPS + R_PPC + R_FBP\n",
" + R_PIt2r = 0\n",
" M_pi_e: - R_PIt2r - R_EX_pi_e = 0\n",
" M_pyr_c: - 2.8328 R_Biomass_Ecoli_core_w_GAM - R_PFL - R_PDH + R_PYK\n",
" - R_PPS + R_ME2 + R_ME1 + R_FRUpts2 + R_GLCpts + R_PYRt2r\n",
" + R_LDH_D = 0\n",
" M_pyr_e: - R_PYRt2r - R_EX_pyr_e = 0\n",
" M_q8_c: - R_SUCDi + R_FRD7 + R_CYTBD - R_NADH16 = 0\n",
" M_q8h2_c: R_SUCDi - R_FRD7 - R_CYTBD + R_NADH16 = 0\n",
" M_r5p_c: - 0.8977 R_Biomass_Ecoli_core_w_GAM - R_TKT1 - R_RPI = 0\n",
" M_ru5p_D_c: R_GND + R_RPI - R_RPE = 0\n",
" M_s7p_c: - R_TALA + R_TKT1 = 0\n",
" M_succ_c: - R_SUCOAS - R_SUCDi + R_FRD7 + R_ICL - R_SUCCt3 + R_SUCCt2_2 = 0\n",
" M_succ_e: R_SUCCt3 - R_SUCCt2_2 - R_EX_succ_e = 0\n",
" M_succoa_c: R_SUCOAS + R_AKGDH = 0\n",
" M_xu5p_D_c: - R_TKT2 - R_TKT1 + R_RPE = 0\n",
"Bounds\n",
" 0 <= R_Biomass_Ecoli_core_w_GAM <= 10000000\n",
"-10000000 <= R_PGK <= 10000000\n",
"-10000000 <= R_GAPD <= 10000000\n",
"-10000000 <= R_PGM <= 10000000\n",
"-10000000 <= R_ENO <= 10000000\n",
" 0 <= R_PGL <= 10000000\n",
" 0 <= R_GND <= 10000000\n",
"-10000000 <= R_G6PDH2r <= 10000000\n",
"-10000000 <= R_ACt2r <= 10000000\n",
"-10000000 <= R_ACKr <= 10000000\n",
" 0 <= R_EX_ac_e <= 10000000\n",
"-10000000 <= R_ALCD2x <= 10000000\n",
"-10000000 <= R_ACALDt <= 10000000\n",
"-10000000 <= R_ACALD <= 10000000\n",
" 0 <= R_EX_acald_e <= 10000000\n",
"-10000000 <= R_PTAr <= 10000000\n",
" 0 <= R_PFL <= 10000000\n",
" 0 <= R_PDH <= 10000000\n",
" 0 <= R_MALS <= 10000000\n",
" 0 <= R_CS <= 10000000\n",
"-10000000 <= R_ACONTb <= 10000000\n",
"-10000000 <= R_ACONTa <= 10000000\n",
"-10000000 <= R_SUCOAS <= 10000000\n",
" 0 <= R_PYK <= 10000000\n",
" 0 <= R_PPCK <= 10000000\n",
" 0 <= R_PFK <= 10000000\n",
" 0 <= R_GLNabc <= 10000000\n",
" 0 <= R_GLNS <= 10000000\n",
"-10000000 <= R_ATPS4r <= 10000000\n",
" 8.39 <= R_ATPM <= 10000000\n",
"-10000000 <= R_ADK1 <= 10000000\n",
"-10000000 <= R_ICDHyr <= 10000000\n",
" 0 <= R_GLUSy <= 10000000\n",
"-10000000 <= R_GLUDy <= 10000000\n",
"-10000000 <= R_AKGt2r <= 10000000\n",
" 0 <= R_AKGDH <= 10000000\n",
" 0 <= R_EX_akg_e <= 10000000\n",
" 0 <= R_PPS <= 10000000\n",
" 0 <= R_PPC <= 10000000\n",
" 0 <= R_ME2 <= 10000000\n",
" 0 <= R_ME1 <= 10000000\n",
"-10000000 <= R_CO2t <= 10000000\n",
"-10000000 <= R_EX_co2_e <= 10000000\n",
"-10000000 <= R_TPI <= 10000000\n",
"-10000000 <= R_FBA <= 10000000\n",
"-10000000 <= R_TKT2 <= 10000000\n",
"-10000000 <= R_TALA <= 10000000\n",
"-10000000 <= R_ETOHt2r <= 10000000\n",
" 0 <= R_EX_etoh_e <= 10000000\n",
"-10000000 <= R_PGI <= 10000000\n",
" 0 <= R_FRUpts2 <= 10000000\n",
" 0 <= R_FBP <= 10000000\n",
" 0 <= R_FORti <= 10000000\n",
" 0 <= R_FORt2 <= 10000000\n",
" 0 <= R_EX_for_e <= 10000000\n",
" 0 <= R_EX_fru_e <= 10000000\n",
" 0 <= R_SUCDi <= 10000000\n",
" 0 <= R_FUMt2_2 <= 10000000\n",
"-10000000 <= R_FUM <= 10000000\n",
" 0 <= R_FRD7 <= 10000000\n",
" 0 <= R_EX_fum_e <= 10000000\n",
"-10000000 <= R_TKT1 <= 10000000\n",
" 0 <= R_GLCpts <= 10000000\n",
"-10 <= R_EX_glc_e <= 10000000\n",
" 0 <= R_GLUN <= 10000000\n",
" 0 <= R_EX_gln_L_e <= 10000000\n",
"-10000000 <= R_GLUt2r <= 10000000\n",
" 0 <= R_EX_glu_L_e <= 10000000\n",
" 0 <= R_ICL <= 10000000\n",
"-10000000 <= R_H2Ot <= 10000000\n",
" 0 <= R_CYTBD <= 10000000\n",
"-10000000 <= R_EX_h2o_e <= 10000000\n",
" 0 <= R_THD2 <= 10000000\n",
" 0 <= R_SUCCt3 <= 10000000\n",
" 0 <= R_SUCCt2_2 <= 10000000\n",
"-10000000 <= R_PYRt2r <= 10000000\n",
"-10000000 <= R_PIt2r <= 10000000\n",
" 0 <= R_NADH16 <= 10000000\n",
"-10000000 <= R_MDH <= 10000000\n",
" 0 <= R_MALt2_2 <= 10000000\n",
"-10000000 <= R_LDH_D <= 10000000\n",
"-10000000 <= R_D_LACt2 <= 10000000\n",
"-10000000 <= R_EX_h_e <= 10000000\n",
" 0 <= R_EX_lac_D_e <= 10000000\n",
" 0 <= R_EX_mal_L_e <= 10000000\n",
" 0 <= R_NADTRHD <= 10000000\n",
"-10000000 <= R_NH4t <= 10000000\n",
"-10000000 <= R_EX_nh4_e <= 10000000\n",
"-10000000 <= R_O2t <= 10000000\n",
"-10000000 <= R_EX_o2_e <= 10000000\n",
"-10000000 <= R_EX_pi_e <= 10000000\n",
" 0 <= R_EX_pyr_e <= 10000000\n",
"-10000000 <= R_RPI <= 10000000\n",
"-10000000 <= R_RPE <= 10000000\n",
" 0 <= R_EX_succ_e <= 10000000\n",
"End\n",
"\n"
]
}
],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"solver.optimize()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Tried aggregator 1 time.\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"LP Presolve eliminated 23 rows and 25 columns.\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Aggregator did 17 substitutions.\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Reduced LP has 32 rows, 53 columns, and 215 nonzeros.\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Presolve time = 0.00 sec. (0.08 ticks)\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Initializing dual steep norms . . .\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"Iteration log . . .\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Iteration: 1 Dual objective = 8250995.276305\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 4,
"text": [
"'optimal'"
]
}
],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"c = solver.constraints.values()[0]"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 6
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"c.expression.as_terms()"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 12,
"text": [
"([(1.0*R_PGK, ((1.0, 0.0), (1, 0), ())),\n",
" (1.0*R_Biomass_Ecoli_core_w_GAM, ((1.0, 0.0), (0, 1), ()))],\n",
" [-10000000.0 <= R_PGK <= 10000000.0,\n",
" 0.0 <= R_Biomass_Ecoli_core_w_GAM <= 10000000.0])"
]
}
],
"prompt_number": 12
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"solver.constraints"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 6,
"text": [
"OrderedDict([('M_13dpg_c', M_13dpg_c: x == 0.0), ('M_2pg_c', M_2pg_c: x == 0.0), ('M_3pg_c', M_3pg_c: x == 0.0), ('M_6pgc_c', M_6pgc_c: x == 0.0), ('M_6pgl_c', M_6pgl_c: x == 0.0), ('M_ac_c', M_ac_c: x == 0.0), ('M_ac_e', M_ac_e: x == 0.0), ('M_acald_c', M_acald_c: x == 0.0), ('M_acald_e', M_acald_e: x == 0.0), ('M_accoa_c', M_accoa_c: x == 0.0), ('M_acon_C_c', M_acon_C_c: x == 0.0), ('M_actp_c', M_actp_c: x == 0.0), ('M_adp_c', M_adp_c: x == 0.0), ('M_akg_c', M_akg_c: x == 0.0), ('M_akg_e', M_akg_e: x == 0.0), ('M_amp_c', M_amp_c: x == 0.0), ('M_atp_c', M_atp_c: x == 0.0), ('M_cit_c', M_cit_c: x == 0.0), ('M_co2_c', M_co2_c: x == 0.0), ('M_co2_e', M_co2_e: x == 0.0), ('M_coa_c', M_coa_c: x == 0.0), ('M_dhap_c', M_dhap_c: x == 0.0), ('M_e4p_c', M_e4p_c: x == 0.0), ('M_etoh_c', M_etoh_c: x == 0.0), ('M_etoh_e', M_etoh_e: x == 0.0), ('M_f6p_c', M_f6p_c: x == 0.0), ('M_fdp_c', M_fdp_c: x == 0.0), ('M_for_c', M_for_c: x == 0.0), ('M_for_e', M_for_e: x == 0.0), ('M_fru_e', M_fru_e: x == 0.0), ('M_fum_c', M_fum_c: x == 0.0), ('M_fum_e', M_fum_e: x == 0.0), ('M_g3p_c', M_g3p_c: x == 0.0), ('M_g6p_c', M_g6p_c: x == 0.0), ('M_glc_D_e', M_glc_D_e: x == 0.0), ('M_gln_L_c', M_gln_L_c: x == 0.0), ('M_gln_L_e', M_gln_L_e: x == 0.0), ('M_glu_L_c', M_glu_L_c: x == 0.0), ('M_glu_L_e', M_glu_L_e: x == 0.0), ('M_glx_c', M_glx_c: x == 0.0), ('M_h2o_c', M_h2o_c: x == 0.0), ('M_h2o_e', M_h2o_e: x == 0.0), ('M_h_c', M_h_c: x == 0.0), ('M_h_e', M_h_e: x == 0.0), ('M_icit_c', M_icit_c: x == 0.0), ('M_lac_D_c', M_lac_D_c: x == 0.0), ('M_lac_D_e', M_lac_D_e: x == 0.0), ('M_mal_L_c', M_mal_L_c: x == 0.0), ('M_mal_L_e', M_mal_L_e: x == 0.0), ('M_nad_c', M_nad_c: x == 0.0), ('M_nadh_c', M_nadh_c: x == 0.0), ('M_nadp_c', M_nadp_c: x == 0.0), ('M_nadph_c', M_nadph_c: x == 0.0), ('M_nh4_c', M_nh4_c: x == 0.0), ('M_nh4_e', M_nh4_e: x == 0.0), ('M_o2_c', M_o2_c: x == 0.0), ('M_o2_e', M_o2_e: x == 0.0), ('M_oaa_c', M_oaa_c: x == 0.0), ('M_pep_c', M_pep_c: x == 0.0), ('M_pi_c', M_pi_c: x == 0.0), ('M_pi_e', M_pi_e: x == 0.0), ('M_pyr_c', M_pyr_c: x == 0.0), ('M_pyr_e', M_pyr_e: x == 0.0), ('M_q8_c', M_q8_c: x == 0.0), ('M_q8h2_c', M_q8h2_c: x == 0.0), ('M_r5p_c', M_r5p_c: x == 0.0), ('M_ru5p_D_c', M_ru5p_D_c: x == 0.0), ('M_s7p_c', M_s7p_c: x == 0.0), ('M_succ_c', M_succ_c: x == 0.0), ('M_succ_e', M_succ_e: x == 0.0), ('M_succoa_c', M_succoa_c: x == 0.0), ('M_xu5p_D_c', M_xu5p_D_c: x == 0.0)])"
]
}
],
"prompt_number": 6
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"?cplex_problem.quadratic_constraints.add"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 12
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
} optlang-1.8.1/paper/ 0000775 0000000 0000000 00000000000 14517531055 0014302 5 ustar 00root root 0000000 0000000 optlang-1.8.1/paper/paper.bib 0000664 0000000 0000000 00000000353 14517531055 0016070 0 ustar 00root root 0000000 0000000 @online{Sympy,
title = {SymPy: Python library for symbolic mathematics},
author = {{SymPy Development Team}},
year = {2016},
url = {http://www.sympy.org},
doi = {10.5281/zenodo.47274),
urldate = {2016-11-24}
}
optlang-1.8.1/paper/paper.md 0000664 0000000 0000000 00000002755 14517531055 0015744 0 ustar 00root root 0000000 0000000 ---
title: 'Optlang: An algebraic modeling language for mathematical optimization'
tags:
- Mathematical optimization
- Linear programming
- Object-oriented API
authors:
- name: Kristian Jensen
orcid: 0000-0002-2796-805X
affiliation: 1
- name: Joao G.R. Cardoso
orcid: 0000-0001-8173-2673
affiliation: 1
- name: Nikolaus Sonnenschein
orcid: 0000-0002-7581-4936
affiliation: 1
affiliations:
- name: The Novo Nordisk Foundation Center for Biosustainability, Technical University of Denmark
index: 1
date: 6 December 2016
bibliography: paper.bib
---
# Summary
Optlang is a Python package implementing a modeling language for solving mathematical optimization problems, i.e.,
maximizing or minimizing an objective function over a set of variables subject to a number of constraints. It provides
a common native Python interface to a series of optimization tools, so different solver backends can be used and
changed in a transparent way.
Optlang's object-oriented API takes advantage of the symbolic math library SymPy [@Sympy] to allow objective functions
and constraints to be easily formulated algebraically from symbolic expressions of variables. Optlang targets
scientists who can thus focus on formulating optimization problems based on mathematical equations derived from domain
knowledge.
Solver interfaces can be added by subclassing the four main classes of the optlang API (Variable, Constraint, Objective,
and Model) and implementing the relevant API functions.
# References
optlang-1.8.1/requirements_rtd.txt 0000664 0000000 0000000 00000000027 14517531055 0017327 0 ustar 00root root 0000000 0000000 sphinx-rtd-theme>=0.1.6 optlang-1.8.1/setup.cfg 0000664 0000000 0000000 00000003616 14517531055 0015022 0 ustar 00root root 0000000 0000000 [metadata]
name = optlang
url = https://github.com/opencobra/optlang
download_url = https://pypi.org/project/optlang/
project_urls =
Source Code = https://github.com/opencobra/optlang
Documentation = https://optlang.readthedocs.io
Bug Tracker = https://github.com/opencobra/optlang/issues
author = Nikolaus Sonnenschein
author_email = niko.sonnenschein@gmail.com
# Please consult https://pypi.org/classifiers/ for a full list.
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Science/Research
License :: OSI Approved :: Apache Software License
Natural Language :: English
Operating System :: OS Independent
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Topic :: Scientific/Engineering :: Mathematics
license = Apache-2.0
description = Formulate optimization problems using sympy expressions and solve them using interfaces to third-party optimization software (e.g. GLPK).
long_description = file: README.rst
long_description_content_type = text/x-rst
keywords =
optimization
mathematical programming
heuristic optimization
sympy
[options]
zip_safe = True
install_requires =
six >=1.9
swiglpk >=5.0.8
sympy >=1.12.0
python_requires = >=3.8
tests_require =
tox
packages = find:
package_dir =
= src
[options.packages.find]
where = src
[options.extras_require]
development =
black
isort
tox
[bdist_wheel]
universal = 1
# See the docstring in versioneer.py for instructions. Note that you must
# re-run 'versioneer.py setup' after changing this section, and commit the
# resulting files.
[versioneer]
VCS = git
style = pep440
versionfile_source = src/optlang/_version.py
versionfile_build = optlang/_version.py
tag_prefix =
parentdir_prefix = optlang-
optlang-1.8.1/setup.py 0000664 0000000 0000000 00000001535 14517531055 0014711 0 ustar 00root root 0000000 0000000 # Copyright 2013 Novo Nordisk Foundation Center for Biosustainability,
# Technical University of Denmark.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Set up the optlang package."""
import versioneer
from setuptools import setup
# All other arguments are defined in `setup.cfg`.
setup(version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass())
optlang-1.8.1/slow_tests/ 0000775 0000000 0000000 00000000000 14517531055 0015401 5 ustar 00root root 0000000 0000000 optlang-1.8.1/slow_tests/README.md 0000664 0000000 0000000 00000000267 14517531055 0016665 0 ustar 00root root 0000000 0000000 This directory contains long-running tests that should not
be packaged with optlang. `data/miplib2003` contains all
benchmark problems that can be solved <1 h with commercial
solvers. optlang-1.8.1/slow_tests/__init__.py 0000664 0000000 0000000 00000000000 14517531055 0017500 0 ustar 00root root 0000000 0000000 optlang-1.8.1/slow_tests/data/ 0000775 0000000 0000000 00000000000 14517531055 0016312 5 ustar 00root root 0000000 0000000 optlang-1.8.1/slow_tests/data/miplib2003.json 0000664 0000000 0000000 00000002361 14517531055 0020770 0 ustar 00root root 0000000 0000000 {
"10teams": {
"status": "optimal",
"solution": 924.0
},
"aflow30a": {
"status": "optimal",
"solution": 1158.0
},
"air05": {
"status": "optimal",
"solution": 26374.0
},
"arki001": {
"status": "optimal",
"solution": 7580810.0
},
"danoint": {
"status": "optimal",
"solution": 65.67
},
"disctom": {
"status": "optimal",
"solution": -5000.0
},
"fiber": {
"status": "optimal",
"solution": 405935.18
},
"fixnet6": {
"status": "optimal",
"solution": 3983.0
},
"gesa2": {
"status": "optimal",
"solution": 25779856.3719999976
},
"gesa2-o": {
"status": "optimal",
"solution": 25779856.3719999976
},
"glass4": {
"status": "optimal",
"solution": 1200010000.0
},
"harp2": {
"status": "optimal",
"solution": -73899800.0
},
"markshare1": {
"status": "optimal",
"solution": 1.0
},
"mas74": {
"status": "optimal",
"solution": 11801.2
},
"mas76": {
"status": "optimal",
"solution": 40005.1
},
"misc07": {
"status": "optimal",
"solution": 2810.0
},
"modglob": {
"status": "optimal",
"solution": 20740500.0
},
"momentum2": {
"status": "optimal",
"solution": 12314.2
}
} optlang-1.8.1/slow_tests/data/miplib2003/ 0000775 0000000 0000000 00000000000 14517531055 0020073 5 ustar 00root root 0000000 0000000 optlang-1.8.1/slow_tests/data/miplib2003/10teams.mps.gz 0000664 0000000 0000000 00000120145 14517531055 0022510 0 ustar 00root root 0000000 0000000 ‹p :?10teams.mps ¥½O“-1vÜ·ç§è·]ø%mѶB"å ¤°·Ö³#lGHް¼ÐÇ÷ðU ¾éÊÌ>9+>ÎÍéʃ*d÷wÿñïþáï?ö®Ïÿïÿøßþóý›úwÿË¿ÿ›üøøÏÿ×ùþÓÿýññ7ÿöãã×uêþG:ÿ‘Ï”óõüG;ÿÑÏŒóóüÇõyþã:ÿ‘ÎäóåüG=ÿÑÎôóãüÇ<žWÎ+Hç¤ó
Òy鼂t^A:¯ WÎ+Èçäó
òyù¼‚|^A>¯ ŸWÏ+Èçäó
Êy异r^A9¯ œWPÎ+(ç”ó
Êy异z^A=¯ žWPÏ+¨çÔó
êyõ¼‚z^A=¯ WÐÎ+hç´ó
Úyí¼‚v^A;¯ WÐÎ+èçôó
úyý¼‚~^A?¯ ŸWÐÏ+èçôó
Æy㼂q^Á8¯`œW0Î+çŒó
Æy㼂y^Á<¯`žW0Ï+˜çÌç
þþŸÿÑÎôóãüÇ<þq}~žÿ¸Î¤óùüG9ÿQÏ´óýüÇ8ÿ1\ç\ç\ç\ç\ç\ç\ç\ç\ç\ç¤ó
Òy鼂t^A:¯ WÎ+Hç¤ó
Òyù¼‚|^A>¯ ŸWÏ+Èçäó
òyù¼‚|^A9¯ œWPÎ+(ç”ó
Êy异r^A9¯ œWPÏ+¨çÔó
êyõ¼‚z^A=¯ žWPÏ+¨ç´ó
Úyí¼‚v^A;¯ WÐÎ+hç´ó
Úyý¼‚~^A?¯ ŸWÐÏ+èçôó
úyý¼‚~^Á8¯`œW0Î+çŒó
Æy㼂q^Á8¯`œW0Ï+˜çÌó
æyó¼‚y^Á<¯`žW0Ï+˜Ç¤sNL眘Î91sb:çÄtΉéœÓ9'¦sNL眘Î91sb:çÄtΉéœÓ9'¦sNL眘Î91sb:çÄtΉéœÓ9'¦sNL眘Î91sb:çÄtΉékNüïÿÝ¿ýÿðYÂÿå?ÿízV÷Ïbþ_üçŸ/ì×õñ×ÿ¹þP?«¾ù¡½Ãê¯Fû×êë›ÿÝ¿RÚwJÐÞ?Ë~µw{ɲ·Õ_K‡oì}[¡ØËÖè-õ÷5 ö¶úkÅò£Ñ;Ôï5(Ð^ùØ™ªC£·Õ_k½ïFor5½ÊoN0zuW0`ïP¶Þ¡~¯Aã7'xöšeïTç?{M±×¡½ú±ß'@uèæÜê9ßnÎ6¸ÜœCxöÞGoì
¶ŸÛ;ÔŸýÇ7çù·_k0Æ0-{‡ú*?¾9§bïúä4æOÇÞ¡NŸ?ž9Ï¿ýnïBöÚÇ~Õ±U˵oÎ7{½s5xö®Ä§°(KûOì¥moü|Q¶Õ ™N-àÙ[꘽¼Ÿ½úãgïP{…·upŲWö³wýüÙ+Š½Ê§–÷¾·Ô1{uÛk?î{‡ØkÈ^ÿØ/é¡:6µ´ýì½Þh\¦–NgN4µôõ'"¡o{óçSËVƒ:s¢©eXöÆžZÚϧ–¡Ø›N Z꘽¹Ÿ½ôó©e
öÒ'Ÿ9ߟ½¥ÙKǪ¥ÿxj9ÔÀÞEgN°jI—eo¯ZòõãUË¡öàªåŸK÷+ƒLÖ»–cÕòvsÎÊÕèUR¦ÌœKý}
˜½cÕòùã™óPƒÚЛ²bÙÛ뎫ÿüMYQìU¾¤X-{Ǫ%ÿxæ<ÔÀ^ã̜Ͳ·W-iü|ælнNš9»eo¯;rúùÌÙ{ƒ70zò·×¹þxÍy¨=¸j™ûÔ TÇÃ^w|¾<{_;MX^ÂÒ¾‡^¯•C´õ¾®ëç/á÷Šé½ù¢}4†¥ŽÙÛëŽkü¸1l5²—x ˜,{{Õ’ÊÃV#{ÙyK³eo¯;ÒüqcØjd¯Ð¾C.–½½îÈùÇa«‘½Êû½jÙÛëŽÜ~ܶÙk´ïÄ›eo¯;òøqbØjdZ~¯ã¿oi¨Ÿ‘?³w¼ky™ZPKÛïy¾Ëú_´£¾7,{Ç»–ôó¾7{“¶uÔ÷¦eo¯Z®ùó¾7{å“ÇY°;þéØ+Ç»–úã¾·ÕÈß!}¯\–½ã]ËçûÞV#{|‡ô½’,{{Õ’ËûÞV#{|‡ô½¥ŽÙÛ«–ÜÜ÷¶Ùã;D ï-uÌÞ±j™?î{[ìñ"÷–:fo¯ZÊçóÞV#{/ÊÞCÙ;DéÅ^ûÔ‘#sEÙ!*>{Øë–½¥Ž™ÛjdoX£·VßÖ€ÙÛ«–À‘¹C
j0yÞKT½¥™SÞµÔOÞÞG¯ëŽŸÛ;Ô‘#s[ý^ƒzÑ›<{õ²ìïZ~~dîP{»–þAÕ¡›s«#G檲CTù»tsgKö¶:pdîPƒ§1ÔbÙ;vˆ~~dîP{ü]˜9kµì;D??2w¨=á\°gZêq®åçG檲j©ü\zöŽ÷{Ç»–Ÿ™;Ô ü\zö†eïx×òó#s‡ØÎµ€›sZöŽs-??2w¨ßí5á\Ë{ßkŸŽ½v¬y~~dîP{}S–€½Ë™ZÚq÷çGæšr·%>s¾?{m¯¡çZ~~dîPƒd:s‚©¥eËÞq®åçGæ5°Wœ@ÔŠeï8ûó#s‡Ø«|æÏ^µì«–Ÿ™;ÔÀžð®Œ^³ì;D??2w¨½N·P2°g½kiǪåçGæšò®¥
ÞÀԲϵDì«–Ÿ™kʹ–6ic@3ç´ì;D??2w¨ßíõOžÖßoÎþéØëǪåçGæ5°wñÆð>sö˲w¼©ùù‘¹C
ì%þ¦Œ^²ì;D??2w¨½Ì½lÙ;vˆ~~d®+§q;ZµÜG2°WœÆ°Õ‘#s½¡WÚ÷@cèû\K ouäÈ\WεôFûh½Yööº#pd®+çZz§}5†nÙÛ«–À‘¹Fö†ó–ºËÞ^wŽÌm5²ÇwˆPc˜–½½î™Ûj`o;Dï£7>{[927”Ó¸ƒïÄ0.ËÞq®åçGæ†rw UËïéúû–ö‡úW‰Ø;ÞµüüÈÜPεŒLÛ:è{#[öŽw-??27”s-£Ð¶úÞ(–½c‡èçGæ†r®eTÚÖAßÕ²w¼kùù‘¹¡œk|‡ô½Ñ,{Ç»–Ÿ™ÛjdOØ!£×-{Çwˆ~~dn(§qß!B}oXöŽïýüÈÜPNã¾C„úÞ´ì«–Ÿ™ÊiÜÉwˆ@Þ›ŸŽ½Ž™›ÊiÜyñÑ{osïå7{SPGŽÌMe‡hòÓ¸ØK–½}®%pdn*çZf¶Fo¾³wœkùù‘¹C
jÀ¿ù|媎ÞRGŽÌMå]Ëäß|F£w|(`o«Gæ5¨ÿæ3zöšeïx×òó#s‡ØÞµŒªŽÝœû4nàÈÜTvˆ&ׂn΃™°wœÆýù‘¹C
j0Æ0-{ÇQ€27{ë4Ø|~Ÿ9—:dïP‡(sŸŠ½‹å½„ì]Ƴ·Õ!ÊÜR#Ô³íû>µ€go©¿¯µ—–½ en«Q
2›Z²—-{y={ÊÜV#{…M-ðÙ+–½²ž½ en«‘½J§–ñAÕA{uÙPæ¶ÙkìMYBöš5µ´õì(sK
§–ÎfN8µôçO„C_ö”¹F5læ„S˰ì5µ(s[ìM#-uÐÞ\Ï^€2·ÕÀÞõIgNðì=꘽k¯Z~~dîP#{›9Ѫåº,{kÕ82w¨‘½Ä¶P2²—œ™óÚ«–Ÿ™Ûj4s^™54s>êïk@ííUËÏÌjTƒÂš9uÐÞZwŽÌjd¯Ò´ŽnÎjÙÛ«–Ÿ™;ÔÈ^£ÍœÍ²·V-#s‡Ùët^·ìuGàÈÜ¡Fömhô†eo;Gæ5²V-÷ÑŒìM«1¬uGàÈÜVC&ü'í{`æ|Ôß×€Ù[êÈ‘¹F5Hë{¨1<ê ½µî™Ûjh/±¾‡Ã£Ú[«–À‘¹†ö²ñ–z©ƒöÖº#pdn«¡½Âúj©XöÖº#pdn«¡½Jû½jÙ[ëŽÀ‘¹†öë{(1¤fÙ[ëŽÀ‘¹†öÀªåwäø¾¥ý¡þUBöö»–Ÿ™Ûjpt`ö@[GaXöö»–Ÿ™Ûjho²¶ûÞ´ìUKàÈÜV#{ù“µuÔ÷uÌ^ÞïZ~~dn«¡=ºC„ú^¾,{û]ËÏÌm5´GwˆPßËɲ·V-#s[
íÑ"Ô÷uÐÞZµŽÌm5´GwˆPß{ÔA{{Õòó#s[
íÑ"”÷uÐÞZµŽÌm5´×ØèÐòÚ!*/öúÔ¡fÍÊQîìÙ›È^·ì=êÈ‘¹†ö†5zÏÊáÛP{kÕ82w¨Q
&Í{僪ƒ£÷¨#Gæ¶^ùd7'½²Ö{[82w¨Ñϼ]ìæDÏ^¹,{û]ËÏÌjd¿kS{IÎ͹ԑ#s[
oNú®Þœ{—&bo©Gæ5ªAqC)–½½CT7gQìÑw-hæ,Õ²·wˆGæ¶ÙãçZ=kÕRö¹–À‘¹¢¬Z
=ן½µrÙÛïZGæ¶Õ€žkÏÞ°ìíw-#s[ìñs-èæœ–½}®%òìS°Wù¹Ð÷ê§c¯îw-‘fýTì]ìMYBö.gj©û4nàÈ\UNãÖÄfN4µÔµrˆ4†ºÏµŽÌm5ªAf3'šZj¶ìís-#s[ì'ÕbÙÛ§qGæ¶Ù«tæDÏ^µìíUKàÈÜV#{ô]ZµÔfÙÛ;D#s[ìuº…‚ìYïZê^µŽÌUå]K¬1À™sk ÙÛ«–À‘¹ªœk©“58sNËÞÞ!
™Ûj`¯}Ò´nÎöéØk{Õ82·ÕÈÞE˜9ÛeÙ[«–È‘¹FöÝBA£—,{{‡(pdn«‘½L½lÙÛ;D#sM9ÛÀªå>:‘½â4†¥™[jÔZe}5†¶ÎµDÚúR‡ŽÌ5å\Kk¬ï¡ÆÐšeo;"Gæšr®¥uÖ÷`cè–½µj‰™[jho8o©Û°ìuGäÈÜRC{t‡6†iÙ[ëŽÈ‘¹¥Fö:Ý!B¡:ö–:td®+§q;Ý!B‰¡_–½}®%pd®+§q;úQ~mi¨•½ý®%pd®+çZzfmõ½ž-{û]KàÈ\WεôÂÚ:ê{½XööQàÈ\WεôÊÚ:ê{½Zöö»–À‘¹®œkét‡õ½Þ,{û]KàÈÜRC{t‡õ½Þ-{û;D#s]9Ûéì{ò·¿C82וӸîÁ¾7-{{Õ82וӸƒî¡¼7>{cŸŠ ™ÊiÜq±Ñ« 1ŒµCT_ì.¨CG憲C4èiÜë󃪃öÖ¹–È‘¹¡œkÙ½}2%bo«Gæ¶Õ€~óùªT½G:27”w-ƒ~óŽÞZw„ì-uäÈÜñ·A
ø7ŸÑ³×,{û]KàÈÜñ·=ú®%!{ݺ9×iÜÈ‘¹¡ì
ú®Þœû}GÄÞ>82·Õ¨ÓjÓ²·wˆGæ¶Ø›ô]š9ç§coZ”¹©Pæ&?ׂìY«–iQ榲j™ô\zöæZ9„ìY”¹©Pæ&=ׂž½™-{en*”¹Éϵ ›³Xö,ÊÜT(s“žkA}oVËžE™›
en6ö¦,#{ÍšZ,ÊÜTNãÎÎfN8µ¬¢Pc°(sS¡ÌÍAß”¡Ñ–=‹27ÊÜœN šÓ²gQæ¦@™KÛÉÔ²Ô!{éÓ¡Ìjd¾k«–¥Ús(s‡ÙKl%#{λ–ôéPæ¶Ìœ ±qïÆ fÎ¥þ¾ÔžC™;Ô¨…n¡ g¯XöÊÜ¡Fö*mèæ¬–=‡2w¨‘½F·PÐè5ËžC™;ÔÈ^§^·ì9”¹Cì
º…‚FoXöÊÜ¡Fö¯å>:€ìM«18”¹F±qヌÃâÓ–H[¿ÊÜV£ 6îÝ÷PcX|Ú˜=‡2·ÕÐeã¢Æ°Ù¸!{en«¡=ÊÆEañicöÊÜVC{t‡5†Å§Ùs(s[
íÑ"ÔŸ6fÏ¡Ìm5´GwˆPbX|Ú˜=‡2·ÕÐz×R^[Úê_5dÏ¡Ìm58:÷në°ï
ËžC™Ûjho²¶ûÞ´ì9”¹Fö ÷b}oñiCö’C™ÛjhïÑ[|Ú˜=‡2·ÕÐÝ!B}oñicöÊÜVC{t‡õ½Å§Ùs(s[
íÑ"Ô÷Ÿ6fÏ¡Ìm5´GwˆPÞ[|Ú˜=‡2·Õïöþáïþéß|~þóûÞ¿ýçÿóïÿéoÿêƒû¯ÿñ?ü»úÿöùE«œß}ò}rñl¿ég·¡š58b—¸:] fô ²×-{•îâjhoX£÷¬4¾µ'Pé’ F5àç`®ªŽ§ÒµO®F£—9ߌަáFìeJ—5¨déföìmnÈž@¥»5²GW9Wû êØÍ™*Ýäjxsò_ @£·Ép{•.)Ô 8aÓpCö*Ý¥üm`¯ÒÆ fÎMÃ
ÙãT:ôXUÅ=“=kÕ’*ÝàjøìñoJ£›s¯"ö*]Ô¨ô;GðÙ–=Jw jdoÒ¶ŽnÎiÙãT:ôìMÁdéfÖ÷Ï6d¯Tº)¨‘½‹½8LÈÞåL-E Òu®FSbé~½YÏÞæÙFC¨tIP£Ð%4µ,žmÌž@¥»5²ÇOï‚©eñlcö8•L-[ìq–.zöªeO ÒMAìÑw-hÕ²y¶!{•njdí(Ý_FEö¬w-E Ò5®†3'ÝQ‚3ç:²'Pé’ F5 ¿¶gÎiÙ¨t— ö*ÿÝ"ps.žmÈ^åT:0sn5²Ç©t`æ\<Û˜=J75²—Xc@3çâÙÆì Tº!¨‘½L½lÙ¨t]P#{èôî½£„ì§1TJW¹5ÄÒ½èkÜų͑¶^*]âjXƒÆúj‹g³'Pé.®†ö(K6†nÙãT:Ôºbç={ò'Pé&WC{œJ‡FoZö*Ýàjd¯Ñ"Ô6K7b¯ TºÎÕÐÝ!B‰a³tCö*]ãjh½k™¯-íõ¯²'Pé
W§ô~±t/ºC´x¶1{•.q5´WX[G}o³tCö*ÝÅÕÐ^¥qݜղǩt ïm–.²GwˆPß[<Û˜=J7¹Úã|4zݲ'PéWC{œJ‡FoXö*]çjhîÁ¾7-{•®q5²×éÊ{‹g²×*]åjhZ~ŸœO 1,žmI/öÚ%¨CG溲CÔé/ td/Yö*ÝÅÕÐ^¶FïY9|[jO Ò%AjÀ©tèé)Öèq*hë]y×Ò9ßÞ^wDì Tº$¨Q
»9á³×,{•îÔÈå»\àôôfé†ì TºÉÕðæ¤T:xsî³%{•. jTƒi5†iÙ¨t— ö K·°™sÓp#ö§ÒÇj«‘=t®%ÝkžªŽ={C Ò
®FÏÞ ß”FÏÞæÙ†ì Tº$¨Q
èwŽÐ³7²eO Ò]‚Ù£¿
Ÿ½bÙãT:ôìÅ^¥Sè{£Zö*ÝÔÈz×r/©‘½fM-•®s5œZ:9ѳ·V¡Æ Pé’ F5 ¿¶§–aÙ¨t— Fö8•M-Ӳǩthj™‚=¥ž½ÍÒØ›•n
jd¿k£·y¶!{•njdZnƲg½k™•®q5š9K÷¢ïZÏ6‡ì Tº$¨Q
è¯-¢™sñlcö*Ý%¨‘=þ»Eèæ¬–=N¥3çV#{”JgÎfÙ¨tSP#{¾)C£×-{•njdoÐÆ€FoXö*]ÔÈ:{3&½i5JW¹4†ŒXº{›7K7ÐÖ·:rdn«A
2bé^ì5nÞ,Ý=Jwq5´GYº 1,uЧҽ7††ö²ñ–:o–nÈž@¥›\
íq*½bÙ¨tƒ«¡=¾C„F¯Zö*]çjhîe4zͲ'PéWC{`ÕòûÕø÷-íõ¯²'Pé
Wƒ£±t/¶C´ÔA{•.q5´7Y[‡}oZö*ÝÅÕÈdé²¢¼Yº{§Ò¾w}*öèê{›¥²'Pé&WC{|‡^²ì TºÁÕÐÝ!B}o³tCö*]çjh·Yº!{•®q5´Gwˆ2½jÙ¨t•«¡=´j¹<‚ưYºùÅ^ÿÔ‘#s[zÿE` {ݲçPæ¶ÚÖè=+‡ok@í9”¹Cj€vˆî¯H媎žC™Ûj4z‰þn½MÃØKeîPƒ –î}s¢gï áFì9”¹Cìq^Ëø êØÍ™ÊÜVÛ“òZà͹™){eîP£§1lnÈžC™;ÔÈçµ€™sÓpCöÊÜ¡Föè7Ÿ²gZ’C™Ë
7'úÍgøì•CÈžC™;Ô¨ô›ÏðÙ–=‡2w¨‘=ÎÆE7ç´ì9”¹C
ì l\Ð÷Ÿ6d/;”¹Cì¡w-÷»‘½Ë™Z²C™Ûj4µ 6î=s¢©eói#!;”¹Cj@mM-‹O³çPæ5²Wœ@´ø´1{eîP#{ôw‹àÔR-{eîP#{ô]Zµl>mÈžC™;ÔÈZµÜqÙ³Þµd‡2—³ò®±q/ú®eñisÈžC™;Ô¨ô×áÌ9-{eîP{…ÿn¸9Ÿ6d¯8”¹Cì]´1€™sñicöÊÜ¡Fökhæ\|Ú˜=‡2w¨‘½L½lÙs(s‡ÙC§qïWIÈ^qCq(s[bã^ô5îâÓæH[/en«a
ë{¨1,>mÌžC™Ûjh¯³¾C·ì9”¹†ö†ó–z³qCöÊÜVC{t‡6†iÙs(s[ìUºC„ÃfãFìU‡2·ÕÐÝ!B‰a³qCöÊÜVC{`ÕòûõÜ÷-íõ¯²çPæ¶@lÜ‹î->mÌžC™Ûjh²qQßÛlÜ=‡2·ÕÐg㢛³ZöÊÜVC{t‡õ½Å§Ùs(s[
íÑ"Ô÷Ÿ6fÏ¡Ìm5´Gwˆ`ß–=‡2·ÕÐÝ!‚}oZöÊÜV#{œ‹òÞâÓ†ì5‡2·ÕÐZµÜ¿SÃâÓ–òfo
êБ¹¦ì!6î}\u"{ɲçPæ¶ÚËÖè=+‡ok@í9”¹Cj€V-÷W¤ÊUGÏ¡Ìm5½ÊnN8zû?¨:hÏ¡Ìm5´7¬ÑÛ'S"öÊÜ¡F5@«–¯
~PupôÊÜV£ÑClÜûæD£·é¶{—C™;Ô ˆûÅŒ ÏÞ¦Û†ì9”¹CìQ^KBö’ss^en«áÍIy-ðæÜï;"öÊÜ¡F5(NcØ|Ú=‡2w¨‘=Îk3çæÓ†ì9”¹CìÑo>'dÏZµ\e®(lÜrÑo>ÃgoBöÊÜ¡F5àß|FÏÞ°ì9”¹Cìq6.º9§eÏ¡Ìj`³qQß[|Ú½äPæ5²‡ÞµÜß Cö.gjIen«ÑÔÙ¸•M-‹O›#!9”¹CjÙ̉¦–ŧÙs(s‡Ù+N Z|Ú˜=‡2w¨‘½ÊfN8µTËžC™;ÔÈ}ׂV-‹O³çPæ5²‡V-7u Ù³Þµ$‡2·Õpæ¬1À™sk Ùs(s‡Õ`²Æ gÎiÙs(s‡ØClÜ¯Æ nÎŧ
ÙËeîP#{khæ\|Ú˜=‡2w¨‘½D½dÙs(s‡Ùˬ1 5çâÓÆì9”¹CìUËmÙ+NcÈen«Qc@lÜ‹¾Æ]|ÚiëÙ¡Ìm5¬Ac}5†Å§Ùs(s[
íuÚ÷ÐÔÒ-{en«¡½á¼¥^|Ú˜=‡2·ÕÐÝ!‚aZöÊÜV#{…î¡Æ°ø´!{Å¡Ìm5´GwˆPbX|Ú˜=‡2·ÕТÌå×–ö‡úW
Ùs(s[Ž 6n¢;D‹O³çPæ¶Ú£l\Ô÷Ÿ6fÏ¡Ìm5´GÙ¸¨ï->mÌžC™Ûjhï¡Ñk–=‡2·ÕÐÝ!B}oñicöÊÜVC{t‡ö½aÙs(s[
íÑ"Ø÷¦eÏ¡Ìm5²ÇÙ¸(ï->mÈ^u(s[
í¡UË}ô½Å§-׋½š582ǯü/½Ô€ý²—,{e.q5´—Ñ{VßÖ€Ú(sYP£pÊÜõAÕÁÑ(sWÃÑãçZÐèí·%{e.jTƒÆnNøì5Ëž@™K‚ÙãDÿöAÕÁ›“Sæú'WÛ“Ræà͹Io{e.jTƒi5†iÙ(sIP{[ØÌ¹é¶{M Ì]‚Ù£ß|NÈžµjienr5zö=‹ž½ƒO±'Pæ² F5 ß!BÏÞâÓÆì ”¹$¨‘=ú›ÏðÙ+–=2w jd¯Ò©ô½Å§Ùã”94kTÅ^coʲ׬©E Ì
®†SKg3'œZÖÊ!ÔÊ\Ô¨t‡N-ò'Pæ’ Fö8eM-Ó²'Pæ.A
ìuú®M-‹O²×9eL-[ìÑw-hÕ²ù´!{en
jdíýþæsFö¬w-] Ìu®F3g§¿C„fÎŧÍ!{e.jTƒÂš9Ÿ6fO Ì%AìUº¤F7gµì ”¹KP#{œ2‡fÎfÙã”94s6Å^gΜݲ'Pæ¦ Fömhô†eO Ì
Aì!ÊÜýC=ÈÞ´ƒ@™k\bãÞ}5†Å§Í‘¶>Ê\æjTÄÆ½ûj‹O³'PæWC{‰"0µ,>mÌž@™»¸Úãß!ÏÞfã†ìqÊh#+ö8e^±ì ”¹ÉÕÐÝ!Ba³qCöÊÜàjhî¡Ä°Ù¸!{e®s5´‡(sãµ¥ý¡þUBöÊ\åê”ÞÏÕ!6îÝÖaß–=2—¹Ú›¬Ã¾7-{e.q5²Ù¸“õ½Å§
Ù›eîâjh·ø´1{œ2úÞfã"{œ×‚F/YöÊÜäjhSæÐèeËž@™\
íÑ"Ô÷Ÿ6fO Ìu®†öèÊ{‹O³'PæWC{hÕrŸÆañi¿9Ò}_`K‚:tdn*;D“ý;²×-{e.q5´7¬Ñ{VßÖ€Ú(sYP£pʺÀiž@™»¸Œ^ý¤¿CF¯tÛŸÛ;Ô#s‡ú½±q#{—eO Ì%Aìq¢ÿ êÐ͹Ց#s[
oNJ™ƒ7ç>[±'Pæ²ò·A
ŠÑê¦Û†ì ”¹¤üm`¯²gïBX-{eîRþ6°G¿ùœÐ6ëÙ(s“«á³G=>{û}GÄž@™Ë‚Õ€~‡>{ò'Pæ’ Föèo>ÃgoZöÊÜ%¨=ÈÆ¬ï]ŸŽ½‹SæÀ¬±ÕÈXµÜ?7‘½Ë™Z.27¸M-ÛÙÔ²ù´‘Æp ”¹,¨Q
2›9ÑÔ²Ù¸!{e. jdSæÐËž@™»5²G‡N-Õ²Ç)shj©Š=þ®]`³ì ”¹)¨‘=´Côû5nFØ™S Ìu®†3'ý"8s®s-!{e.jTƒÉœ9§eO Ì%A
ì!6îWZ¸ø´!{I Ì]‚Ù£”94s.>m̧̙s«‘½Dß”¡L–=275²—ic@£—-{enjdQæîêAöŠÓ’@™k\bãÞ}5†ÍÆ´õ$Pæ2WÃ4Ö÷PcØlÜ=2—¸Úë¬ïÁÆÐ-{eîâjho8o©77dSæPcŠ=N™C8-{enr5²—ù½ÍÆØËenp5´GwˆPbØlÜ=2×¹ÚCß!š¯-íõ¯²'Pæ*Wƒ£±qï¶ŽúÞâÓÆì ”¹ÌÕÐ^amõ½ÍÆ
Ù(s‰«¡½ÊÚ:ê{›²'Pæ.®†ö8͜ͲÇ)s ïm6.²ÇwˆÐvËž@™›\
íÑ"Ø÷†eO Ì
®†öèì{Ó²'Pæ:W#{…·Ù¸{E Ì5®†öЪ厳 1l6n~±×/A92·Õ¨÷JôÈ^²ì9”¹†ö²5zÏÊáÛP{eîP£ ¢ûû{ùƒªƒ£çPæ¶Žý"8zû[@{eîP£4vsÂg¯YöÊÜ¡Fö8Ñ|Puðæt(s[
oÎÁž=xsnfJÄžC™;Ô¨ÓjÓ²çPæ5°Ù¸Íœ›n±WÊÜ¡FöÐÑý* Ù³V-Õ¡ÌU…[+ýõDôìm>mÈžC™;Ô¨™M-èÙ[|Ú˜=‡2w¨‘=þ›Ïèæ,–=‡2w¨‘½J§Ð÷Ÿ6fÏ¡ÌjdíÝ™ÙkÖÔâPæ¶N-ÍœpjY+‡Pcp(s‡Õ`°™N-òçPæ5²7@´ø´1{eîP{þšZŸ6d¯9”¹CìÑw-hÕ²ù´!{eîP#{h‡èþr)²g½kie®6å]K£¿C„fÎŧÍ!{eîP£ÖÐ̹ø´1{eîP#{•¦utsVËžC™;ÔÈ^£ÍœÍ²çPæ5²×Yc€3g·ì9”¹Cì
ÚÐè
ËžC™;ÔÈâµÜPdoZÁ¡Ìm5jˆûÕ÷À̹ø´9ÒÖ»C™ÛjTÄÆ½ûj‹O³çPæ¶ÚK¬ï¡Æ°ø´1{en«¡½ì¼¥ÞlÜ=‡2·ÕÐÝ!Ba³qCöÊÜVC{t‡5†ÍÆ
Ùs(s[
íÑ"”67dÏ¡Ìm5´V-¿Ó|ßÒþPÿ*!{en«ÑÑÄÆýjë¨1ËžC™Ûjho²¶ûÞ´ì9”¹Fö ÷b}oñiCö†C™Ûjh·ø´1{en«¡=ºC„úÞâÓÆì9”¹†öèê{‹O³çPæ¶Ú£;D¨ï->mÌžC™Ûjh·ø´1{en«¡=´j¹w4†Å§-åÅÞøÔ¡#sCÙ!BlÜ›ð8‘½nÙs(s[
í
kôž•÷5 öÊÜ¡F5@;D7U¼|PupôÊÜV£ÑƒlÜO6z›n±7-ÊÜT(sˆ{ßœèÙÛtÛ=‹27ÊÜäDÿùAÕ±›sZ”¹©ìMJô‡7çÞ¥‰Ø³(sS¡ÌÍâ4†M·
Ù³(sS¡ÌMþ›Ï`æÜtÛ=‹27ÊÜ俞ˆìY«–iQæ6nô×á³·V!{en*”¹I=>{ògQæ¦B™›ü×ÑÍ9-{en
”¹öÉ=ñ½ï-uÈ^ût(s‡ÙC;DwZGö.cjÙêÈ‘¹SKƒlÜI¦–¶ù´3bÏ¡ÌjTƒÌfΉìeËžC™;ÔÈ^1ÑRí9”¹CìU:s¢g¯ZöÊÜ¡Föè»–„F¯YöÊÜ¡Föeî>èìukæt(s[
gÎÁœ9×¹–=‡2w¨Q
&kp朖=‡2w¨=ÄÆýJëàæ\|ڽˡÌjdï¢Ìœ‹O³çPæ5²—Xc@3çâÓÆì9”¹CìeÚÐèeËžC™;ÔÈâµÜ_Ó@öŠÓ.‡2·Õ¨1 6îÝ÷PcX|Úië—C™ÛjXƒÆúj‹O³çPæ¶Úë¬ïÁÆÐ-{en«¡½a¼¥n›²çPæ¶Ú£;D°1LËžC™Ûjd/Ñ"Ô67b/9”¹†öèJ›²çPæ¶Ú«–ß)ìû–ö‡úW Ùs(s[
Ž4ÄÆýúÝYП6fÏ¡Ìm5´WX[G}o³qCöÊÜVC{•µuÔ÷Ÿ6fÏ¡Ìm5´GwˆPß[|Ú˜=‡2·ÕÐÝ!B}oñicöÊÜVC{t‡ö½aÙs(s[
íÑ"Ø÷¦eÏ¡Ìm5²—éÊ{‹O²—ÊÜVC{hÕò»ïUП¶Ô7{SPGŽÌm5êýˆûõƒ¨þɲçPæ¶ÚËÖèí“){eîP£ ¢›*^?¨:8zen«áèUvsÂÑ[ëŽ=‡2w¨Q
»9á³×,{eîP#{”蟽nÝœen«áÍI‰þðæÜï;"öÊÜ¡F5˜Vc˜–=‡2w¨½B‰þhæÜ|Úˆ½âPæ5²Ç=Ù³V-Å¡Ì5…Û
ýõDôìm>mÈžC™;Ô¨ô×ѳ·ø´1{eîP#{ü×ÑÍY,{eîP#{ô×Qß[|Ú˜=‡2w¨‘=´Ctÿ¼ ²×¬©Å¡Ìm5œZ:›9áÔ²vˆBÁ¡ÌjTƒÁfN8µËžC™;ÔÈÞtÑâÓÆì9”¹C
ì!6î×ï1€Ñ[|Ú½êPæ5²Gßµ UËâÓÆì9”¹Cì!ÊÜýåRdÏz×RÊÜV£™±qïÆ€fÎŧÍ!{eîP£ÖÐ̹ø´1{eîP#{•6tsVËžC™;ÔÈ^cΜͲçPæ5²×ic@£×-{eîP#{ƒ5´æ\|Ú˜=‡2w¨‘=Äk¹¿¦ìM«18”¹F±qヌÃâÓ–H[oen«Q
÷î{¨1,>mÌžC™Ûjh/Ѿ¦–ÍÆ
Ùs(s[
íeç-õâÓÆì9”¹†öèj‹O³çPæ¶Ú£;D¨1,>mÌžC™Ûjhî¡Ä°ø´1{en«¡=D™K¯-íõ¯²çPæ¶@lܻþ7,{en«¡½ÉÚ:ì{Ó²çPæ¶ÙƒlÜÌúÞâÓ†ìu‡2·ÕÐß!£·ø´1{en«¡=ºC„úÞâÓÆì9”¹†öèê{‹O³çPæ¶Ú£;D¨ï->mÌžC™Ûjh·ø´1{en«¡=´j¹ÁÍ ï->m¹^ìÕ"¨Á‘9~åéý ”èß½nÙ(s™«¡½aÞ³rø¶Ôž@™+‚Õ€Sæ®ªŽž@™K\Foðß!£·é¶{C ÌA
j€Ø¸÷͉ž½M·
Ù(sYP#{tÕrµªŽÝœC Ì]\
oNJ™ƒ7çZw´ˆ=2W5ªAqÃ¦Û†ì ”¹,¨‘½J˜97Ý6dO Ì%Aìñ_ODö¬UËà”¹ñÉÕðÙ£§qá³·W{e®jTú"øì
Ëž@™Ë‚Ù£¿ùŸ½iÙ(sIP{ˆû5µ€¾·ø´!{S Ì]‚ÙCïZnä=²w9SË(s“«ÑԂظ_¿Ç ž½Í§4†)PæŠ F5 ;DhjY|Ú˜=2—5²Ç)s`jY|Ú˜=2—5²G‡N-Õ²'Pæ.AìÑw-hÕ²ù´!{œ2‡&ŦØël%#{Ö»–)PæWÙs°Æ gÎu®%dO ÌAj0Yc€3ç´ì ”¹,¨ßíuÄÆýZR¿ßœK²×?Ê\Ôȧ̵ªÚ(s— Fök ^²ìqÊÜûÌy¨‘½L½lÙ(sSP#{`Õ’ïo¡ {Åh[
ŽÌu®¡#6nb¯q—úûP{e®p5¬Ac}¯!{Ͳ'Pæ2WC{"4µtËž@™K\
íñï¡goXöÊÜÅÕЧ̡ћ–=N™Ca
ö.ºC„ÃfãFì]enr5´Gwˆ@b蛲'PæWC{ˆ2×_[Úê_%dO Ì5®N©¾(³¶ŽúÞâÓÆì ”¹ÂÕÐ^amõ½ÍÆ
Ù(s™«¡=ÊÆE}oñicöÊ\âjh·ø´1{eîâjhóZÐèu˧̾·Ù¸È§Ì¡Ñ–=27¹Ú£;D°ïMËž@™\ì%ºC„òÞâÓ†ì%2×¹ÚC«–›ðÃâÓ–ôb¯eA92·Õ¨÷'JôïÈ^²ì ”¹ÌÕÐ^¶FïY9|[jO ÌAjÀ)s郪ƒ£'PæWÃÑ£¿CGo¯;"öÊ\ԨݜðÙk–=2—5²‡V-7È«Puðæ(sWÛ“Ræà͹Io{e®(Ô`ZaZöÊ\Vþö»=ÈÆmlæÜtÛˆ½,Pæ’ò·=þë‰ÈžµjÉœ2CVV-;س·ù´!{e®jTú"ôìålÙ(sYP#{ô7Ÿá³W,{e. jd¯Ò©ô½\-{eîÔÈz×r/©‘½fM-enr5œZ:9ѳ·V¡Æ PæŠ F5læ„SË°ì ”¹,¨‘=N™CSË´ì ”¹$¨½B‡M-›±WÊÜ%¨‘=þ®ŒÞæÓ†ìqʘ·ÙC;D÷ÏM {Ö»–"PæW£™±q}ײø´9dO ÌAjPXc@3çâÓÆì ”¹,¨‘½JÓ:º9«eO Ì%AìQÊœ9›eO Ì]‚ÙëôM½nÙã”94svÅÞ Þ°ì ”¹)¨‘=°jÉ73Ù›Vc(s«Qc@lÜL_ãn6n¤W2W¸Õ ±q}»Ù¸!{e.s5´—XßCañicöÊ\âjh/;o©77dO Ì]\
íqʽbÙã”9ÐjQìñ"4zÕ²'Pæ&WC{t‡%†ÍÆ
Ù(sƒ«¡=D™¯-íõ¯²'PæW££ˆ›éÑâÓÆì ”¹ÂÕÐÞdmö½iÙ(s™«‘=ÎÆE}o³q#öš@™K\
íÑ"Ô÷67dO Ì]\
íñ"4zɲÇ)s ï5å4n£;D¨ïm6nÈž@™›\
íÑ"Ô÷67dO Ì
®†öèÊ{›²'Pæ:WC{hÕrÿî,h››_ìõ$¨CGæš²CÔ(Ñ {ݲçPæ¶ÚÖè=+‡ok@í9”¹Cj€vˆî“ðèé™Öè9”¹F£×éï¡ÑÛtÛˆ½îPæ5¨bãÞ7'zöºmÄžC™;ÔÈZµÜ_.T»9»C™ÛjxsföìÁ›sŸ-‰Øs(s‡Õ 8aÓmCöÊÜ¡Fö*{öÐ̹é¶!{eîP#{ôײgZºC™ë
·#6î=µÀgoBöÊÜ¡F5ljÏÞ°ì9”¹Cìñß|F7ç´ì9”¹C
ìA6ng}oñiCö†C™;ÔÈz×rÙ»œ©e8”¹FSbã~ýî,xö6Ÿ6Ò†C™;Ô¨™ÍœhjY|Ú˜=‡2w¨‘½â¢Å§Ùs(s‡Ù£¿C§–jÙs(s‡Ù£ïZЪeóiCöÊÜ¡FöÐÑg‘=ë]Ëp(s}(ïZ7Ñw-‹O›CöÊÜ¡F5˜¬1À™sZöÊÜ¡ö÷+ƒ›sñiCö¦E™›
e±q¿˜9Ÿ6fÏ¢ÌM…2‡Ø¸_?ÌŠF/Yö,ÊÜT(sˆûAל‹O³gQæ¦r±qóý* Ù+Nc˜en*ß|FlÜL_ã.>mŽ´õiQæ¦r®±q}»ø´1{en*çZ 7ÓÆÐ-{en*”9ÄÆåo©77dÏ¢ÌM…27élÓ²gQæ¦@™Ÿt‡4†±Ù¸{[92·ÕÐÝ!‰al6nÈžC™Ûjh}‡h¾¶´?Ô¿JÈžC™Ûjpt` 6nf;DK´çPæ¶Ú+¬d¯XöÊÜVC{•µõݜղçPæ¶Ú£;Dš9›eÏ¡Ìm5´Gwˆ½nÙs(s[
íÑ"Ø÷†eÏ¡Ìm5´Gwˆ`ß›–=‡2·ÕÈÞEwˆ@Þ[꘽ˡÌm5´‡V-÷IxП¶”{ãÔ‘#s[z?bãþþï~Md/YöÊÜVC{Ù½gåðm
¨=‡2w¨Q
ÐÑ}¾|PupôÊÜVÃÑ«ìæ„£·ÏÓFì9”¹CjÐØÍ Ÿ½fÙs(s‡ÙCïZn$Æü êàÍéPæ¶Þœƒ={ðæÜ»4{eîP£L«1LËžC™;ÔÀdã6snºmÄ^r(s‡ÙCçZîo¡ {Öª%9”¹¡°qbãÞSzö6Ÿ6dÏ¡ÌjTƒÌ¦ôì->mÌžC™;ÔÈ^aS|öŠeÏ¡Ìjd¯Ò©ô½Å§Ùs(s‡ÙCïZîïï!{ÍšZÊÜV饳™N-kåjeîP£6s©eXöÊÜ¡Fö¦ˆŸ6fÏ¡Ìj`±q¿fNðì->mÈ^v(s‡Ù£ïZЪeóiCöÊÜ¡FöÐÑïÑËÈžõ®%;”¹F3'bã&ú®eñisÈžC™;Ô¨…54s.>mÌžC™;ÔÈ^¥iݜղçPæ5²×hc@3g³ì9”¹CìuÖàÌÙ-{eîP#{ƒ64zòçPæ5²‡x-7u Ù›Vcp(s[bãfúwñis¤‡2·Õ¨ˆ›èkÜŧÙs(s[
í%Ö÷PcX|Ú˜=‡2·ÕÐ^vÞRo6nÈžC™Ûjhî¡Æ°Ù¸!{en«¡=ºC„Ãfã†ì9”¹†öèJ›²çPæ¶Ú«–òùÚÒþPÿ*!{en«ÑÑÄÆÍt‡hñicöÊÜVC{“µuØ÷¦eÏ¡Ìm5²‡Ø¸‰î->mÈ^u(s[
íÑ"Ô÷Ÿ6fÏ¡Ìm5´GwˆPß[|Ú˜=‡2·ÕÐÝ!B}oñicöÊÜVC{t‡õ½Å§Ùs(s[
íÑ"”÷Ÿ6fÏ¡Ìm5´‡V-¿«VП¶Ô{óSP‡ŽÌUe‡±qïE¾ÐvËžC™ÛjhoX£·O¦Dì9”¹Cj€vˆî“ðõƒªƒ£çPæ¶bãÞ7'½M·ØkeîPƒ 6î}s¢goÓmCöÊÜ¡FöЪåkrþ êØÍÙÊÜVÛ3³gÞœû}GÄžC™;Ô¨Åi›O²çPæ5²Wé³fÎͧ
Ùs(s‡ÙCçZîo¡ {Öª¥9”¹¡°qbãÞS|öÖÊ!dÏ¡ÌjTƒAÛ:ºÀaÙs(s‡Ù›tjA7ç´ì9”¹C
ì!6î=µ ¾·ø´!{Ý¡Ìjd½k¹ è/gjéen«ÑԂظ÷̉¦–ŧ͑ÆÐÊÜ¡F5ÈlæDSËâÓÆì9”¹Cì'->mÌžC™;ÔÈ^e3'œZªeÏ¡Ìjd¾kA«–ŧÙs(s‡ÙC”¹`‰ìYïZºC™Ûj8sÖà̹ε„ì9”¹Cj0Yc€3ç´ì9”¹C
ì!6îWc 7çâÓ†ì
‡2w¨‘½‹54s.>mÌžC™;ÔÈ^¢^²ì9”¹CìeÖКsñicöÊÜ¡Fö¯å÷ÍYЧ1‡2·Õ¨1 6n¦¯qŸ¶DÚúp(s[
kÐXßCañicöÊÜVC{ö=4µtËžC™Ûjho8o©Ÿ6fÏ¡Ìm5´Gwˆ`c˜–=‡2·ÕÈÞ¤;D¨1,>mÈÞ´(sS9;éJ‹O³gQæ¦r±qçý¾¥ý¡þUCö,ÊÜTε 6n¦;D‹O³gQæ¦r®²qéÑâÓÆìY”¹©œkAlÜDwˆŸ6fÏ¢ÌMå\Ëä;Dè›eÏ¢ÌM…27éê{‹O³gQæ¦rwÒ"Ø÷†eÏ¢ÌMå4î¤;D°ïMËžE™›ÂiÜùIwˆ@Þ[꽎™ÛjhZî¯'~|Põ¯r½Ø«UPƒ#süÊÿÒûA
(Ñ¿!{ɲ'Pæ
WC{Ù½gåðm
¨=2W5ª§Ì]T=2—¹Žÿ"4zûmIÄž@™«‚Õ ±›>{Ͳ'PæŠ FöèªåjT¼9Ê\âjxsRʼ9׺£Eì ”¹*¨Q
¦Õ¦eO ÌA
ìA6.97Ý6bï(sYP#{è\Ëý-dÏZµ\eîâjôì]ô4.zö>mÄž@™«‚Õ€~‡={‹O³'PæŠ Föèo>Ãg¯XöÊ\ÔÈ^¥Sè{‹O³'Pæ’ FöÀªåþ=†„ì5kjᔹùÉÕpjélæ„SËZ9„ƒ@™«‚Õ€îÁ©eXöÊ\Ôȧ̡©eZöÊ\ÔÀ^¢¿C„¦–ŧ
ÙKe. jd¾kA«–ͧ
Ù(s— Föeî† !{Ö»–$Pæ&W£™±q3]”->mÙ(sUP£ÖÐ̹ø´1{e®jd¯Ò%5º9«eO ÌeAìqÊš9›eO Ì%AìuÖàÌÙ-{eîÔÈÞ Þ°ìqÊšó‡b¬Zî£Ù›Vc(sƒ«Qc@lÜL—Ô‹O›#m=”¹ÊÕ¨ˆ›é’zñicöÊ\ájh/Ñ@¦–ŧÙ(s™«¡=þ"ðìm6nÈž@™K\
íqʽbÙ(sWC{t‡5†ÍÆ
Ùã”9ÐrUìÑ"”67dO ÌM®†öe®½¶´?Ô¿JÈž@™ë\R{ÿÐ`mö½aÙ(s•«¡=ÊÆ…}oZöÊ\ájd²qi Z|Ú½"Pæ2WC{t‡õ½Å§Ù(s‰«¡=ÎkA£—,{eîâjhSæÐèe˧̾·Ù¸ÈÝ!B}oñicöÊÜäjh·ø´1{enp5´‡V-÷×4@cX|Ú’^ìµ"¨CG抲CT(Ñ¿#{ݲ'Pæ
WC{ýgåðm
¨=2W5ª§Ì¥ªŽž@™Ë\F¯Òß!B£wÐmöª@™«‚Ô ±qï›={›n²'PæŠ FöЪåþ©þAÕ±›³
”¹ÄÕðæ¤”9xsnÒ[Äž@™«Êß5(NcØtÛ=2W”¿
ìUöì¡™sÓmCöÊ\Vþ6°‡¾CtߜȞµj©eîâjøìu6µÀgo¿ïˆØ(sUP£ÐïÁgoXöÊ\ÔÈýÍgøìMËž@™Ë‚ØClܯ©ô½öéØke. jdíÝϲw9SKã”9Ö›r²qi[ß|ÚHche®
jTƒÌfN4µl6nÈž@™+‚Ùã”90µl6nÈž@™Ë‚Ù£¿C§–jÙ(sIP#{ü]½fÙ(s— Föeîþj0²g½kienr5œ9mhjYçZBöÊ\Ô¨“58sNËž@™+‚ØClÜDe‹O²×Ê\Ôȥ̡™sñicöÊ\ÔÈ^¢oÊÐè%Ëž@™»5²—ic@£—-{œ2æü®œÆElÜrÿ²WœÆÐÊÜàjÔ7Ó%õfãFÚz(s•«a
ë{¨1l6nÈž@™+\
íuÖ÷`cè–=2—¹ÚÎ[êÍÆ
Ù(s‰«¡=N™C£7-{eîâjdoð"0z›±78e4†¡œÆt‡%†ÍÆ
Ù(s“«¡=D™ë¯-íõ¯²'Pæ:W££ˆ[h Z|Ú˜=2W¹Ú£l\Ô÷67dO Ì®†ö*kë¨ïm6nÈž@™Ë\
íÑ"Ô÷67dO Ì%®†öø½nÙ(sWC{t‡ö½aÙã”9Ô÷”Ó¸ƒîÁ¾7-{enr5²7éÊ{›±7ÊÜàjhZîßa³q󋽞uèÈÜTvˆ&%úd/Yö,ÊÜTε 6®0zÏÊáÛP{en*”9ÄÆ½îß[GX¬Ñ³(sSy×2éïÁÑÛߊس(sS¡Ì!6î}sÂg¯Yö,ÊÜT(s{ƒ›ÇUoN‹27•"ÈÆåSË>[±gQæ¦B™ãl\xsNËžE™›eîúü:Îõþì™s©CöuàÈÜ¡†ö®÷gï·½/ðŠ?{[92·ÕàÙûˇ™ZÀ³·Ôß×€ÛK½Ÿ™;Ô°™L-ÚË–½ü<{??2w¨¡½B¦üìË^yž½+òìÅ^eSËø ꨽úØûù‘¹C
íµ÷WI÷o€A{ÍšZÚóìýüÈÜVã©¥“™O-ýëOÄCìÍÈÔò¨a
™9ñÔ2,{ã™ZZdjнDKµ7Ÿg/E¦–)Ø»>Ù̉ž½/uÐÞµV-=0µ,5´w‘™®Z®Ë²÷¬ZGæ5´÷¾jÉ÷Ô/093çµV-??2·Õpæ¼2ipæüR_noZ>3çRÃÒàÌù¥ŽÚ{Ö#s‡Ú«,ì–½µjÉ™s©¡½Æœ9›eïYµŽÌjh¯“Æ€gÎnÙ{Ö#s‡Ú¬1ÀÑ–½gÝ82w¨¡½÷UK¹gNhoZáYwŽÌm5lé“õ=4s~©¿¯µ÷¨#Gæ¶Ö ]¤ïÁÆð¥ŽÚ{Ö#s[í%Ò÷`cøRGí=«–À‘¹Æörü-õRGí=ëŽÀ‘¹Æö
é{°1¤bÙ{Ö#s[íUÖ÷àèUËÞ³î™Ûjl¯‘¾Cj–½gÝ82·ÕØÞûªå72äû–ö‡úW‰Ù[ïZ~~dn«ÁÑ¿|h°¶Ã°ìw-??2·ÕØÞ$m÷½iÙ{V-#s[
íåOÒÖaßûRíåõ®åçGæ¶Ûc;D°ïå˲·ÞµüüÈÜVc{l‡ö½œ,{Ϫ%pdn«±=¶CûÞ—:jïYµŽÌm5¶Çvˆ`ßûRGíUËÏÌm5¶Çvˆ`ÞûRGí=«–À‘¹ÆöÀªåþÝYÔò³CT^ì$¨#Gæ¶öþÞµ”ßÚë–½/uäÈÜVc{ý¯•÷5àöžUKàÈÜ¡†5 ;D÷ï—ªŽŽÞ—:rdn«áè•OrsÂÑ+Ϻ#do©Gæ5ªA¹ÈÍ Ÿ½rYöÖ»–xö–Ú«–r÷žªÞœ:rdn«ñ͙ɳ‡oεK²÷¨Gæ5¬AqC)–½µCT"7gQìUòìÁ™³TËÞÚ!Š™[jhï}Õò;/þJОµj)ë\KäÈ\QV-¥“©?{ÏÊ!fo½k‰™[jXƒA¦üì
ËÞz×92·ÔÐÞ$S~ö¦eok‰™[jd¯~²©õ½ú騫ë]KäÈÜRC{`‡è÷è%hïr¦–ºNãFŽÌUå4nMdæ„SK}V¡ÆP×¹–È‘¹¥†5Èdæ„SKÍ–½u®%rdn©¡½â¢Z,{ë4näÈÜRC{•ÍœðÙ«–½µj‰™[jh½k«–Ú,{k‡(rdn©¡½÷UËï8ü+C{Ö»–ºV-‘#sUy×Rixæ|εÄìUKäÈ\UεÔIž9§eoíEŽÌ-5²×>YZG7gûtìµµj‰™[jhïbÍœí²ì=«–Б¹¥†öipælɲ·vˆ"Gæ–Úˬ1ÀÑË–½µC92×”Ó¸í}Õò{¶ÿ•¡½â4†G;2÷¨ach•ô=ØÚs®%ÔÖuìÈ\Sε´FúlYöžuGèÈ\Sε´Núnݲ÷¬ZBGæ5¶7œ·ÔmXöžuGèÈÜ£ÆöØnÓ²÷¬;BGæ5´×ÙlýÓ±÷¨cGæºr·³"˜úeÙ[çZ"Gæºr·¿¯ZÊ|mi¨•˜½õ®%rd®+çZz&mö½ž-{ë]KäÈ\WεôBÚ:ì{½XöÖQäÈ\WεôJÚ:ì{½ZöÖ»–È‘¹®œkél‡ö½Þ,{ë]KäÈÜ£ÆöØì{½[öÖwˆ"Gæºr·³"Ü÷†eo}‡(rd®+§q;Û!Â}oZöÖª%rd®+§qÛ!‚yo|:öÆ:927”Ó¸¼kùgý¯ŠÃxvˆê‹½y êØ‘¹¡ì
ð®¥ÞKŠªŽÚ{ε„ŽÌ
å\ËÈÖè“)!{K92·Ô°à›ÏŸ·úƒª££÷¥Ž™Ê»–QÉ͉GïYwÄì=êБ¹¥†5häæÄÏ^³ìw-‘#sK
íUK½'窎ޜÏiÜБ¹¡ìAž=|s®÷!{ë4näÈÜRÃL«1LËÞÚ!Š™[jdo~²gÍœóÓ±7-ÊÜT(sœkùm/A{ÖªeZ”¹©¬Zf"S|öæ³rˆÙ³(sS¡ÌÍÌÚ:zöf¶ìY”¹©PæfaS¼9‹eÏ¢ÌM…27+™Z`ߛղgQæ¦B™›`‡è÷èeh¯YS‹E™›ÊiÜÙÉ̉§–g‡(Ö,ÊÜT(ss™O-ògQæ¦B™›Ó DsZö,ÊÜ(s`ã^tIý¨cö®O‡2·ÕÐ{ׂV-:jÏ¡Ìm5´vˆ~ÛËОó®åút(sKfΰq3]”=êïkÀí9”¹†5(¤1\ðÙ+–=‡2·ÕÐ^eޜղçPæ¶Úk¤1à™³YöÊÜVC{58zݲçPæ¶Ú¤1d8zòçPæ¶Ú”¹ß£W ½i5‡2·Ô°1 6n¡KêGý}
¨½Ë¡Ì-5¬`ãfº¤~ÔQ{en©±½ÄúšZ7fÏ¡Ì-5¶—·Ô:jÏ¡Ì-5¶Çvˆ`cxø´A{en©±=¶CÃç
Ús(sKí±"˜>mОC™[jlï}Õòûۛ߷´?Ô¿jÌžC™[jttàlÜÂÑç
Ús(sKíMÒÖqß›–=‡2·ÔÐbãò@ôðicö’C™[jlî¡Ñ{ø´A{en©±=¶CûÞç
Ús(sKí±"Ø÷>mОC™[jlíÁ¾÷ðiƒöÊÜRc{l‡æ½‡O´çPæ–Ûß|¾óõ½‡O[®{µ jpdŽ_ù_z?ª#ú7h¯[ö8e®r5¶7¬ÑûZ9|[nSæš †5 ”9øôLkô8e®p5½L‡Þ¢Û†ìeN™k‚Õ °qï›>{‹n³Ç)sUPC{lÕrÁLÎÍ™9e.s5¾9eߜϺ£…ìqÊ\Ô°Åi‹n³Ç)sUPC{•54s.ºm̧ÌA
ís-_/>¨:úìqÊ\âjüì±Ó¸øÙ[+‡=N™k‚Ö€}‡?{òÇ)sUPC{“µuxsN˧ÌAì6î×Ô‚.ðáÓÆìN™Ë‚ÚïZ~ÛKð/gj)œ2wq5œZ ÷ž9áÔ²ø´¡ÆP8e® jX¶C§–‡O´Ç)sUPC{”2‡¦–‡O´Ç)sEPC{ìwˆðÔR-{œ2—5´ÇÞµÀUËâÓÆìqÊ\ÔÐø¢ûç& =ë]Ka”¹ôùÉÕxæ¤1à™ó9׳Ç)s«q
&ix朖=N™«\
í6î×’ÝœŸ6f¯rÊ\ájlRæà^–=N™Ë\í%ÒàÌùðiƒö8e.q5¶—Yc€˜-{œ2wq5¶(s7u ^`qC唹ÉÕ°1 6ná¯q>mµõÊ)s«q
é{°1<|Ú =N™«\íuˆàÔÒ-{œ2W¸Û£ß!‚8,{œ2—¹Û£”98zÓ²Ç)s‰«¡½Ævˆ`cXlܽÆ)sWc{l‡&†ÅÆÙc”9ØÒÚ¥Ø{_µÔúÚÒþPÿ*1{œ27¸:%p®°qß!zø´A{œ2׸Û+¤Ã¾·Ø¸1{œ2W¹Û«,Λ³Zö8e®p5¶Çvˆ`ß{ø´A{œ2—¹Û£¼8zݲÇ)s‰«±=J™ƒ8,{œ2wq5¶Çvˆpß›–=F™Ã}o
ö:Û!‚yïáÓÆìuN™›\íUËý«Á¨1<|Ú’^ìµ*¨cG溲CÔÑ¿C{ɲÇ)s•«±½lÞ×ÊáÛp{œ2×5¬¥Ì¥ªŽŽ§Ì®Æ£Ç~‡ÞZw„ìqÊ\Ô°ÜœøÙk–=N™«‚Ú«–v/Œ>¨:zsrÊ\æj|s2ʾ9é-dSæšò·Q
¦Õ¦eSæªò·=ÄÆtæ\tÛ½Á)sEùÛÈ8×’î5ÏUŸ½Á)s‰«á³Ø¸÷ÔŸ½Å§Ù㔹&¨a
Øwˆà³7²eSæª †öØo>ãg¯Xö8e®jh¯²©õ½Q-{œ2—5´ÞµÜKjh¯YS§Ì]\§–ÎfNøì=+‡Xcà”¹&¨a
™9ñÔ2,{œ2W5´G)spj™–=N™+‚Ù›ìwˆàԲظ!{“Sæ² †öè»4z‹O³Ç)sIPC{€2wÿÜ´g½k™Œ2_Nå]`ãfþ®åáÓæ˜=N™k\kPHc€3çç
Ú㔹ÊÕØ^eiޜղÇ)s…«±=F™Ã3g³ìqÊ\æjl¯³7epôºeSæWc{ƒ58zòÇ)sWc{ï«–›¶“¡½i5N™›\ClÜB_ã¦ÅÆ´õ¥™[jTƒØ¸™¾ÆM‹³Ç)s•«±½Dúj:jSæ
Wc{ÙxK7fSæ2Wc{”2G¯Xö8e.q5¶GwˆàèU˧Ì]\í±¢G¯Yöeµ´¥Æö e®½¶´?Ô¿J̧Ì
®FG`ãVºCô¨£ö8e®q5¶7I[Ç}oZö8e®r5´Ø¸™î¥ÅÆ
Ù»8e®p5¶Çvˆ`ß[lܘ=N™Ë\íÑ"8zɲÇ)s‰«±=¶CûÞbãÆìqÊÜÅÕØÛ!‚}o±qcöeö½«(öØQ†£W-{œ27¹Û«–û`¨1,6n~±×‹ ™[jØû/FôÐ^·ì9”¹¥Æö†5z_+‡okÀí9”¹†5 ;D÷ŸÈT=‡2·Ôpôû"8z‹n²—ÊÜV£ 6î}sÂgoÓmCöÊÜVC{`ÕrMc|PuðæLen©ñ͙ɳ‡oÎu¶$dÏ¡Ìm5¬AqÃ¢ÛÆì9”¹†ö*yöà̹è¶1{en«¡=p®åþö%´gZ’C™K
76î=µàgïY9Äì9”¹†5djÁÏÞ°ì9”¹†öèo>ÛsZöÊÜV#{€û5µ ¾÷ðicö²C™Ûjh¼k¹¿àí]ÎÔ’ÊÜRé°qï™N-‹OjÙ¡Ìm5¬A&3'œZ>mОC™Ûjh¯8èáÓí9”¹†öØïá©¥ZöÊÜVC{ì]\µ,>mÌžC™ÛjhPæî8íYïZ²C™KYyר¸™¿kyø´9fÏ¡Ì-5®Á$ϜӲçPæ–Úlܯ´Žn·O³WÊÜRc{khæ|ø´A{en©±½Dœ9>mОC™[jl/³Æ G/[öÊÜRc{ï«–z¿J‚öŠÓŠC™[jØ ·ð׸Ÿ6‡Úzq(sKkÐH߃ááÓí9”¹¥Æö:é{¸1tËžC™[jlo8o©7fϡ̥2{l‡7†iÙs(s©”¹TÙl‹²WÊ\ªÊiÜÊvˆ`bXlܘ=‡2—ªr°q"¿oi¨•˜=‡2·Ôðè `ãV¾CôðiƒöÊÜRc{…´uØ÷7fÏ¡Ì-5¶WI[‡}ïáÓí9”¹¥ÆöØì{Ÿ6hÏ¡Ì-5¶Çvˆ`ß{ø´A{en©±=¶C„ûÞ°ì9”¹¥ÆöØî{Ó²çPæ–Úkl‡æ½‡O³×ÊÜRc{€èÿî,jŸ¶”{#êØ‘¹¦ì6îï_ÚK–=‡2·ÔØ^¶Fïkåðm
¸=‡2·Õ°`‡è>*ŸžbžC™[jmОC™Ûjh¯©?{ŲçPæ¶Ú«ljA}ïáÓí9”¹†öÞW-åþ‚´×¬©Å¡Ì-5žZ:™9ñÔò¬bÁ¡Ìm5¬Á 3'žZ†eÏ¡Ìm5´7@ôðiƒöÊÜV#{€û5s¢gïáÓÆì
‡2·ÕÐ{×W-‹O³çPæ¶Ú”¹ß£—¡=ë]Ëp(sK
gNÀÆ-ü]ËçÍ1{en©q
ipæ|ø´A{en©±½ÊÒ:¼9«eÏ¡Ì-5¶×Xc€3g³ì9”¹¥Æö:ixæì–=‡2·ÔØÞ`ŽÞ°ì9”¹¥Æö eî÷Í™¡½i5‡2·Ô°1 6ná¯q>mµõiQæ¦r®°qûðiƒö,ÊÜTε 6îÝ÷`cxø´A{en*”9ÀÆÞR/6nÌžE™›
en²"Ø7fÏ¢ÌM…27Ùl‹³gQæ¦rw²"˜7fÏ¢ÌMå4.`ãÖñÚÒþPÿ*1{en*çZ ·ò¢‡O´gQæ¦r®°qß!Zlܘ=‹27…s-±qéÑ£ŽÙ[êБ¹¥ÆöØê{:jÏ¡Ì-5¶Çvˆ½dÙs(sKí±¢G/[öÊÜRc{l‡(ÃÑ+–=‡2·ÔØÛ!ÊpôªeÏ¡Ì-5¶V-÷/Ç~|Põ¯R_ìÍ$¨CGæ–õþظ×ý%›ÏªŽÚs(sKí
kôÖÉ”=‡2·Õ°`‡è>*^?¨::zen©áè6î}sÂÑ[t۽ˡÌm5ª`ãÞ7'|öÝ6fÏ¡Ìm5´V-÷Wƒ¡½äÜœ—C™[j|sfòìá›s½ïÙs(s[
kPœÆ°ø´1{en«¡½Êž=4s.>mÌžC™Ûjh|‡èþö%´gZ.‡2—6nlÜ{jÁÏÞ³rˆÙs(s[
k0X[‡ÏÞ°ì9”¹†ö&›ZàÍ9-{en«‘=ÄÆ½hß{ø´1{É¡Ìm5´vˆîïÎB{—3µ$‡2·ÔpjlÜ{æ„SËç͡ÆÊÜVÃd2s©åáÓí9”¹†öŠˆ>mОC™Ûjh¯’™O-Õ²çPæ¶ÚcïZàªåáÓí9”¹†ö eîfãB{Ö»–äPæ–Ïœƒ4çZböÊÜRãLÒðÌ9-{en©¡=ÀÆýjèæ|ø´1{Ù¡Ì-5¶w‘Æ g·O´çPæ–ÛK¬1ÀÑK–=‡2·ÔØ^&®9>mОC™[jlPæ~ßœÚ+NcÈen©ac lÜÂ_ã>|ÚjëÙ¡Ì-5®A#}6†‡O´çPæ–Ûë¬ïÁ©¥[öÊÜRc{ÃyKýðiƒöÊ\ÎC±Çvˆpc˜–=‡2—³@™Ë…íÁÆððicöŠC™ËåS±Çvˆ`bxø´A{e.—K±(sóµ¥ý¡þUcöÊÜRã€[ùÑç
Ús(sKíÒÖaß{ø´A{en©±½ÊÚ:¼9«eÏ¡Ì-5¶Gwˆàè5ËžC™[jlíÁ¾÷ðiƒöÊÜRc{l‡÷½aÙs(sKí±"Ü÷¦eÏ¡Ì-5´WÙÌ{Ÿ6f¯:”¹¥Æö ÷þ
ê{Ÿ¶\/öjÔàÈ¿ò_éB5`Dÿí%˧Ì5®Æö²5z_+‡okÀíqÊ\Ô°”2w}Putô8e®r5=ú;DpôÖÛ’=N™ë‚Ö ‘›?{ͲÇ)sMPC{lÕrµªŽÞœœ2W¸ßœŒ2‡oÎgÝÑBö8e®jXƒi5†iÙ㔹&¨‘=ÄÆtæ\tÛ½Æ)sUPC{à;D÷·/¡=kÕÒ8e.s5|ö;Ÿ½Í§
Ù㔹.¨a
Øwˆà³÷ðiƒö8e® jhýæ3~öŠeSæª †ö*›ZPß{ø´A{œ2W5´vˆî—ðÐ^³¦N™K\§–NfN<µ<+‡Xcà”¹.¨a
ØžZ†eSæš †ö(eN-Ó²Ç)sUP#{ýœZ>mÌ^甹"¨¡=ö®®ZŸ6fSæ² †öÀÑýåRhÏz×Ò9eîâj8s6îÝàÌùðişÌu®Æ5(¤1À™óáÓíqÊ\ãjl¯²%5¼9«eSæ*Wc{”2gÎfÙ㔹ÂÕØ^'ϜݲÇ)s™«±½Á½aÙ㔹ÄÕØ ÌÝ;DÐÞ´¥Ì]Ÿ\
`ãÞ}6†‡O›Cm}pÊ\çjXÀƽûlŸ6hSæWc{‰"4µ<|Ú =N™«\íÑï¡go±qcö8e®p5¶G)spôŠeSæ2Wc{l‡6†ÅÆÙ㔹ÄÕØÛ!‚‰a±qcö8eîâjlï}ÕÒÊkKûCý«ÄìqÊÜäê”À¹:ÀƽÛ:î{òÇ)s«±½IÚ:î{Ó²Ç)s«¡=ÄÆÍ´ï=|Ú˜½É)s•«±=¶CûÞç
Ú㔹ÂÕØåµÀÑK–=N™Ë\íQʽlÙ㔹ÄÕØÛ!‚}ïáÓíqÊÜÅÕØÛ!‚yïáÓíQÊêØ‹íUËýì¡ÆððiKz±×š Ž™›ÊÑdDÿíu˧Ì5®Æö†5z_+‡okÀíqÊ\Ô°”2‡œ.6nlô8e®r5½òÉ~‡^ÙtÛ€½Ž™ÛjPƒØ¸÷ÍÙ¡½Ë²Ç)sMPC{à]Ëý¦¬Puìæ\êБ¹¥Æ7'£Ìá›s‘ÞBö8e®+Õ ¡,ºm̧Ì5åo#{•<{hæ,‹n³Ç)sUùÛÈøÑM€öšõìqÊ\æjüìu2µàgo½ïÙ㔹.¨a
Øwˆð³7,{œ2×5´Ç~ó?{Ó²Ç)sUP#{€û5µ ¾w}:ö.N™+‚Ú;D÷o>C{—3µ\œ2—¸N-€û5s¢goñiCá┹.¨a
2™9áԲظ1{œ2×5´G)shjYlܘ=N™«‚Úc¿C„§–jÙ㔹"¨¡=ú®Ž^³ìqÊ\ÔÐø¢›íukæä”¹‹«ñÌ9Xc€SËs®%fSæ:WãLÒðÌ9-{œ2׸Úlܯ´Žn·O³—8e®r5¶Ç(spæ|ø´A{œ2W¸ÛKìM½dÙ㔹ÌÕØ^fŽ^¶ìqÊ\âjlPæî-h¯8!QÊØBYjØ ÷î{°1,6n¨'N™ë\kÐH߃a±qcö8e®q5¶×Ißá[ö8e®r5¶7œ·Ô‹³Ç)s…«±=J™ƒ£7-{œ2—¹ÚËt‡Þbã†ìeN™K\í±"˜7fSæ.®ÆöÞW-¿Ÿëï[Úê_%fSæ&W££°qï¶ûÞç
Ú㔹ÎÕØ^!mö½ÅÆÙ㔹ÆÕØ^%mö½ÅÆÙ㔹ÊÕØÛ!‚}o±qcö8e®p5¶Gwˆàèu˧Ìe®ÆöØî{òÇ)s‰«±=¶C„ûÞ´ìqÊÜÅÕÐ^a;D0ï-6nÈ^¡”9Ա˧b°qﯣưظùÅ^¯‚:tdn©aï/Œè? ½dÙs(sKíekô¾VßÖ€Ûs(s[
k vˆî¶ž?¨::zen©ñè±ß!£·¾²çPæ¶Ö ‘›?{ͲçPæ¶Ú«–¯•ÃUGoN‡2·ÔøæäÙÃ7ç:[²çPæ¶Ö`ZaZöÊÜV#{ˆûIgÎE·
Ù«en«¡=ð¢;C{Öª¥:”¹¢°q`ãÞS|öŸ6fÏ¡Ìm5¬A&S|ö>mОC™Ûjhþæ3¼9‹eÏ¡Ìm5´WÙÔ‚úÞç
Ús(s[
í¢û‹ÝÐ^³¦‡2·ÔxjédæÄS˳rˆ5‡2·Õ°ƒÌœxj–=‡2·ÕÐÞtÑç
Ús(s[ì5ö;Dpjyø´1{Í¡Ìm5´ÇÞµÀUËâÓÆì9”¹†ö eî÷Wƒ3´g½kie®4å]`ãÞΜŸ6Çì9”¹¥Æ5(¤1À™óáÓí9”¹¥Æö*Këðæ¬–=‡2·ÔØ^cΜͲçPæ–Ûë¤1à™³[öÊÜRc{ƒ58zòçPæ–Û¼–{Ú›Vcp(sK
`ã~õ=4s>|ÚjëÝ¡Ì-5¬`ãÞ}6†‡O´çPæ–ÛK¤ïÁÆððiƒöÊ\éI±—·Ô‹³çPæ–Ûc;D°1,6nÌžC™[jlíÁưظ1{en©±=¶CÃbãÆì9”¹¥Æö e®½¶´?Ô¿JÌžC™[jxt °q¿Ú:lòçPæ–Û›¤ã¾7-{en©¡=ÀƽÛ:ì{Ÿ6fo8”¹¥ÆöØì{Ÿ6hÏ¡Ì-5¶Çvˆ`ß{ø´A{en©±=¶CûÞç
Ús(sKí±"Ø÷>mОC™[jlíÁ¼÷ðiƒöÊÜRc{`Õrÿî,jŸ¶”{£êØ‘¹¡ì6îï9óׄöºeÏ¡Ì-5¶7¬ÑûZ9|[nÏ¡Ìm5¬Ø!ºÛ:¼ÀižC™[j8z€{ßœpôÝ6doZ”¹©Pæ ÷¾9á³·è¶1{en*”9ÀÆÍ÷o¡ÌªÞœÓ¢ÌMe‡±q+¿93%dÏ¢ÌM…2‡Ø¸¼1,ºmÌžE™›
e°q¯‹Îœ‹n³gQæ¦B™lÜ|-^ µj™eNaãÀƽ§üì=+‡˜=‹27Ê`ãÞS~ö†eÏ¢ÌM…2ظ÷Ô‚Ÿ½iÙ³(sS ÌUÄÆ½Xß{Ô1{õÓ¡Ìm5´vˆî/vC{—1µ,uèÈÜR£©¥"6îdSK]|Ú²çPæ¶Ö “™sB{Ù²çPæ¶Ú+F zÔQ{en«¡½ÊfNøìUËžC™Ûjh½kIð›eÏ¡Ìm5´(s¿¿œávkæt(sKgÎAž9Ÿs-1{en©q
&ix朖=‡2·ÔÐ`ã~¥utŸ6fïr(sKí]¬1 ™óáÓí9”¹¥Æöipæ|ø´A{en©±½Ì½lÙs(sKí½¯ZÚ½…í§1\en©ac lÜ»ïÁÆððis¨_en©q
é{°1<|Ú =‡2·ÔØ^'}7†nÙs(sõꊽa¼¥®‹³çPæ–Ûc;D¸1LËžC™[jh/±"Ø7d/9”¹¥ÆöØL‹³çPæ–Û”¹þÚÒþPÿ*1{en©ÑÑ
ظw[‡}ïáÓí9”¹¥Æö
ië°ï-6nÌžC™[jl¯’¶ûÞç
Ús(sKí±"Ø÷>mОC™[jlíÁ¾÷ðiƒöÊÜRc{l‡÷½aÙs(sKí±"Ü÷¦eÏ¡Ì-5´—ÙÌ{Ÿ6f/;”¹¥ÆöÀªå÷³WQcxø´¥¾Ø›YP‡ŽÌÕ¬ì6îuÏœŸTµçPæ–ÛËÖè“)!{en«a
ÀÑÝÖëUGGÏ¡Ì-5½JnN