diff --git a/.codecov.yml b/.codecov.yml
index 39efc7e8fd5..c61f2815a1b 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -14,6 +14,6 @@ coverage:
# - !ci.appveyor.com
codecov:
notify:
- # GHA: 18, Travis: 13, Jenkins: 6
- after_n_builds: 33
+ # GHA: 5, Travis: 13, Jenkins: 6
+ after_n_builds: 22 # all but 2
wait_for_ci: yes
diff --git a/.coin-or/projDesc.xml b/.coin-or/projDesc.xml
index 5ea18e58fff..7309508216c 100644
--- a/.coin-or/projDesc.xml
+++ b/.coin-or/projDesc.xml
@@ -227,8 +227,8 @@ Carl D. Laird, Chair, Pyomo Management Committee, cdlaird at sandia dot gov
Use explicit overrides to disable use of automated
version reporting.
-->
- 5.7.0
- 5.7.0
+ 5.7.1
+ 5.7.1
diff --git a/.github/workflows/pr_master_test.yml b/.github/workflows/pr_master_test.yml
index c0877043f0c..6dafcf96f1b 100644
--- a/.github/workflows/pr_master_test.yml
+++ b/.github/workflows/pr_master_test.yml
@@ -19,23 +19,28 @@ defaults:
env:
PYTHONWARNINGS: ignore::UserWarning
+ PYTHON_CORE_PKGS: wheel
+ PYTHON_REQUIRED_PKGS: >
+ ply six nose coverage
PYTHON_BASE_PKGS: >
- coverage cython dill ipython networkx nose openpyxl pathos
- pint pymysql pyro4 pyyaml sphinx_rtd_theme sympy xlrd wheel
+ dill ipython networkx openpyxl pathos
+ pint pymysql pyro4 pyyaml sphinx_rtd_theme sympy xlrd
+ python-louvain
PYTHON_NUMPY_PKGS: >
numpy scipy pyodbc pandas matplotlib seaborn
CACHE_VER: v2
jobs:
build:
- name: ${{ matrix.TARGET }}/${{ matrix.python }}${{ matrix.NAME }}
+ name: ${{ matrix.TARGET }}/${{ matrix.python }}${{ matrix.other }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python: [2.7, 3.5, 3.6, 3.7, 3.8, pypy2, pypy3]
- mpi: [0]
+ other: [""]
+
include:
- os: ubuntu-latest
TARGET: linux
@@ -52,12 +57,29 @@ jobs:
- os: ubuntu-latest
python: 3.7
+ other: /mpi
mpi: 3
skip_doctest: 1
TARGET: linux
PYENV: conda
- PACKAGES: mpi4py
- NAME: /mpi
+ PACKAGES: mpi4py openmpi
+
+ - os: ubuntu-latest
+ python: 3.9
+ other: /slim
+ slim: 1
+ skip_doctest: 1
+ TARGET: linux
+ PYENV: pip
+
+ - os: ubuntu-latest
+ python: 3.6
+ other: /cython
+ setup_options: --with-cython
+ skip_doctest: 1
+ TARGET: linux
+ PYENV: pip
+ PACKAGES: cython
exclude:
- {os: macos-latest, python: pypy2}
@@ -65,14 +87,32 @@ jobs:
- {os: windows-latest, python: pypy2}
- {os: windows-latest, python: pypy3}
-
steps:
- - uses: actions/checkout@v2
+ - name: Checkout Pyomo source
+ uses: actions/checkout@v2
- name: Configure job parameters
run: |
- JOB="${{matrix.TARGET}}/${{matrix.python}}${{matrix.NAME}}"
- echo "::set-env name=GHA_JOBNAME::"`echo "$JOB" | sed 's|/|_|g'`
+ JOB="${{matrix.TARGET}}/${{matrix.python}}${{matrix.other}}"
+ echo "GHA_JOBNAME=$JOB" | sed 's|/|_|g' >> $GITHUB_ENV
+ if test -z "${{matrix.other}}"; then
+ echo "GHA_JOBGROUP=${{matrix.TARGET}}" >> $GITHUB_ENV
+ else
+ echo "GHA_JOBGROUP=other" >> $GITHUB_ENV
+ fi
+ # Note: pandas 1.0.3 causes gams 29.1.0 import to fail in python 3.8
+ PYTHON_PACKAGES="${PYTHON_REQUIRED_PKGS}"
+ if test -z "${{matrix.slim}}"; then
+ PYTHON_PACKAGES="$PYTHON_PACKAGES ${PYTHON_BASE_PKGS}"
+ fi
+ if [[ ${{matrix.python}} != pypy* && ! "${{matrix.slim}}" ]]; then
+ # NumPy and derivatives either don't build under pypy, or if
+ # they do, the builds take forever.
+ PYTHON_PACKAGES="$PYTHON_PACKAGES ${PYTHON_NUMPY_PKGS}"
+ fi
+ PYTHON_PACKAGES="$PYTHON_PACKAGES ${{matrix.PACKAGES}}"
+ echo "PYTHON_PACKAGES=$PYTHON_PACKAGES" \
+ | tr '\n' ' ' | sed 's/ \+/ /g' >> $GITHUB_ENV
# Ideally we would cache the conda downloads; however, each cache is
# over 850MB, and with 5 python versions, that would consume 4.2 of
@@ -96,6 +136,7 @@ jobs:
- name: OS package cache
uses: actions/cache@v1
+ if: matrix.TARGET != 'osx'
id: os-cache
with:
path: cache/os
@@ -117,7 +158,7 @@ jobs:
)"
echo "$CURLRC" > ${GITHUB_WORKSPACE}/.curlrc
echo "$CURLRC" > ${GITHUB_WORKSPACE}/_curlrc
- echo "::set-env name=CURL_HOME::$GITHUB_WORKSPACE"
+ echo "CURL_HOME=$GITHUB_WORKSPACE" >> $GITHUB_ENV
- name: Update OSX
if: matrix.TARGET == 'osx'
@@ -155,7 +196,7 @@ jobs:
- name: Set up Miniconda Python ${{ matrix.python }}
if: matrix.PYENV == 'conda'
- uses: goanpeca/setup-miniconda@v1
+ uses: conda-incubator/setup-miniconda@v1
with:
auto-update-conda: true
python-version: ${{ matrix.python }}
@@ -182,21 +223,15 @@ jobs:
run: |
python -c 'import sys;print(sys.executable)'
python -m pip install --cache-dir cache/pip --upgrade pip
- # Note: pandas 1.0.3 causes gams 29.1.0 import to fail in python 3.8
- pip install --cache-dir cache/pip ${PYTHON_BASE_PKGS} \
- ${{matrix.PACKAGES}}
- if [[ ${{matrix.python}} != pypy* ]]; then
- # NumPy and derivatives either don't build under pypy, or if
- # they do, the builds take forever.
- pip install --cache-dir cache/pip ${PYTHON_NUMPY_PKGS}
- fi
+ pip install --cache-dir cache/pip ${PYTHON_CORE_PKGS}
+ pip install --cache-dir cache/pip ${PYTHON_PACKAGES}
pip install --cache-dir cache/pip cplex \
|| echo "WARNING: CPLEX Community Edition is not available"
pip install --cache-dir cache/pip xpress \
|| echo "WARNING: Xpress Community Edition is not available"
- python -c 'import sys; print("::set-env name=PYTHON_EXE::%s" \
- % (sys.executable,))'
- echo "::set-env name=NOSETESTS::"`which nosetests`
+ python -c 'import sys; print("PYTHON_EXE=%s" \
+ % (sys.executable,))' >> $GITHUB_ENV
+ echo "NOSETESTS="`which nosetests` >> $GITHUB_ENV
- name: Install Python packages (conda)
if: matrix.PYENV == 'conda'
@@ -208,17 +243,17 @@ jobs:
conda info
conda config --show-sources
conda list --show-channel-urls
- conda install -q -y -c conda-forge ${PYTHON_BASE_PKGS} \
- ${PYTHON_NUMPY_PKGS} ${{matrix.PACKAGES}}
+ conda install -q -y -c conda-forge ${PYTHON_CORE_PKGS}
+ conda install -q -y -c conda-forge ${PYTHON_PACKAGES}
# Note: CPLEX 12.9 (the last version in conda that supports
# Python 2.7) causes a seg fault in the tests.
conda install -q -y -c ibmdecisionoptimization cplex=12.10 \
|| echo "WARNING: CPLEX Community Edition is not available"
conda install -q -y -c fico-xpress xpress \
|| echo "WARNING: Xpress Community Edition is not available"
- python -c 'import sys; print("::set-env name=PYTHON_EXE::%s" \
- % (sys.executable,))'
- echo "::set-env name=NOSETESTS::"`which nosetests`
+ python -c 'import sys; print("PYTHON_EXE=%s" \
+ % (sys.executable,))' >> $GITHUB_ENV
+ echo "NOSETESTS="`which nosetests` >> $GITHUB_ENV
- name: Setup TPL package directories
run: |
@@ -226,13 +261,13 @@ jobs:
mkdir -p "$TPL_DIR"
DOWNLOAD_DIR="${GITHUB_WORKSPACE}/cache/download"
mkdir -p "$DOWNLOAD_DIR"
- echo "::set-env name=TPL_DIR::$TPL_DIR"
- echo "::set-env name=DOWNLOAD_DIR::$DOWNLOAD_DIR"
+ echo "TPL_DIR=$TPL_DIR" >> $GITHUB_ENV
+ echo "DOWNLOAD_DIR=$DOWNLOAD_DIR" >> $GITHUB_ENV
- name: Install Ipopt
run: |
IPOPT_DIR=$TPL_DIR/ipopt
- echo "::add-path::$IPOPT_DIR"
+ echo "$IPOPT_DIR" >> $GITHUB_PATH
mkdir -p $IPOPT_DIR
IPOPT_TAR=${DOWNLOAD_DIR}/ipopt.tar.gz
if test ! -e $IPOPT_TAR; then
@@ -260,9 +295,9 @@ jobs:
shell: pwsh
run: |
$GAMS_DIR="${env:TPL_DIR}/gams"
- echo "::add-path::$GAMS_DIR"
- echo "::set-env name=LD_LIBRARY_PATH::${env:LD_LIBRARY_PATH}:$GAMS_DIR"
- echo "::set-env name=DYLD_LIBRARY_PATH::${env:DYLD_LIBRARY_PATH}:$GAMS_DIR"
+ echo "$GAMS_DIR" >> $GITHUB_PATH
+ echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$GAMS_DIR" >> $GITHUB_ENV
+ echo "DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:$GAMS_DIR" >> $GITHUB_ENV
$INSTALLER="${env:DOWNLOAD_DIR}/gams_install.exe"
$URL="https://d37drm4t2jghv5.cloudfront.net/distributions/29.1.0"
if ( "${{matrix.TARGET}}" -eq "win" ) {
@@ -290,7 +325,7 @@ jobs:
- name: Install GAMS Python bindings
run: |
- GAMS_DIR="$TPL_DIR/gams"
+ GAMS_DIR="${env:TPL_DIR}/gams"
py_ver=$($PYTHON_EXE -c 'import sys;v="_%s%s" % sys.version_info[:2] \
;print(v if v != "_27" else "")')
if test -e $GAMS_DIR/apifiles/Python/api$py_ver; then
@@ -304,7 +339,7 @@ jobs:
shell: pwsh
run: |
$BARON_DIR="${env:TPL_DIR}/baron"
- echo "::add-path::$BARON_DIR"
+ echo "$BARON_DIR" >> $GITHUB_PATH
$URL="https://www.minlp.com/downloads/xecs/baron/current/"
if ( "${{matrix.TARGET}}" -eq "win" ) {
$INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.exe"
@@ -334,7 +369,7 @@ jobs:
if: matrix.TARGET != 'win'
run: |
GJH_DIR="$TPL_DIR/gjh"
- echo "::add-path::${GJH_DIR}"
+ echo "${GJH_DIR}" >> $GITHUB_PATH
INSTALL_DIR="${DOWNLOAD_DIR}/gjh"
if test ! -e "$INSTALL_DIR/bin"; then
mkdir -p "$INSTALL_DIR"
@@ -363,11 +398,11 @@ jobs:
echo ""
echo "Install Pyomo..."
echo ""
- $PYTHON_EXE setup.py develop
+ $PYTHON_EXE setup.py develop ${{matrix.setup_options}}
echo ""
echo "Set custom PYOMO_CONFIG_DIR"
echo ""
- echo "::set-env name=PYOMO_CONFIG_DIR::${GITHUB_WORKSPACE}/config"
+ echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV
- name: Set up coverage tracking
run: |
@@ -377,8 +412,8 @@ jobs:
COVERAGE_BASE=${GITHUB_WORKSPACE}/.cover
fi
COVERAGE_RC=${COVERAGE_BASE}_rc
- echo "::set-env name=COVERAGE_RCFILE::$COVERAGE_RC"
- echo "::set-env name=COVERAGE_PROCESS_START::$COVERAGE_RC"
+ echo "COVERAGE_RCFILE=$COVERAGE_RC" >> $GITHUB_ENV
+ echo "COVERAGE_PROCESS_START=$COVERAGE_RC" >> $GITHUB_ENV
cp ${GITHUB_WORKSPACE}/.coveragerc ${COVERAGE_RC}
echo "data_file=${COVERAGE_BASE}age" >> ${COVERAGE_RC}
SITE_PACKAGES=$($PYTHON_EXE -c "from distutils.sysconfig import \
@@ -427,16 +462,102 @@ jobs:
make -C doc/OnlineDocs doctest -d
- name: Process code coverage report
- env:
- CODECOV_NAME: ${{matrix.TARGET}}/${{matrix.python}}${{matrix.NAME}}
run: |
coverage combine
coverage report -i
coverage xml -i
+
+ - name: Record build artifacts
+ uses: actions/upload-artifact@v2
+ with:
+ name: ${{github.job}}_${{env.GHA_JOBGROUP}}-${{env.GHA_JOBNAME}}
+ path: |
+ .coverage
+ coverage.xml
+ # In general, do not record test results as artifacts to
+ # manage total artifact storage
+ # TEST-*.xml
+
+ cover:
+ name: process-coverage-${{ matrix.TARGET }}
+ needs: build
+ if: always() # run even if a build job fails
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-latest]
+
+ include:
+ - os: ubuntu-latest
+ TARGET: linux
+ - os: macos-latest
+ TARGET: osx
+ - os: windows-latest
+ TARGET: win
+
+ steps:
+ - name: Checkout Pyomo source
+ uses: actions/checkout@v2
+ # We need the source for .codecov.yml and running "coverage xml"
+
+ - name: Pip package cache
+ uses: actions/cache@v1
+ id: pip-cache
+ with:
+ path: cache/pip
+ key: pip-${{env.CACHE_VER}}.0-${{runner.os}}-3.8
+
+ - name: Download build artifacts
+ uses: actions/download-artifact@v2
+ with:
+ path: artifacts
+
+ - name: Set up Python 3.8
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.8
+
+ - name: Install Python Packages (pip)
+ shell: bash # DO NOT REMOVE: see note above
+ run: |
+ python -c 'import sys;print(sys.executable)'
+ python -m pip install --cache-dir cache/pip --upgrade pip
+ pip install --cache-dir cache/pip ${PYTHON_CORE_PKGS} \
+ ${PYTHON_REQUIRED_PKGS}
+ python -c 'import sys; print("PYTHON_EXE=%s" \
+ % (sys.executable,))' >> $GITHUB_ENV
+
+ - name: Install Pyomo and PyUtilib
+ run: |
+ echo ""
+ echo "Clone Pyomo-model-libraries..."
+ git clone https://github.com/Pyomo/pyomo-model-libraries.git
+ echo ""
+ echo "Install PyUtilib..."
+ echo ""
+ $PYTHON_EXE -m pip install git+https://github.com/PyUtilib/pyutilib
+ echo ""
+ echo "Install Pyomo..."
+ echo ""
+ $PYTHON_EXE setup.py develop ${{matrix.setup_options}}
+ echo ""
+ echo "Set custom PYOMO_CONFIG_DIR"
+ echo ""
+ echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV
+
+ - name: Generate parse_table_datacmds
+ run: |
+ # Manually invoke the DAT parser so that parse_table_datacmds.py
+ # is generated before running "coverage xml"
+ $PYTHON_EXE -c "from pyomo.dataportal.parse_datacmds import \
+ parse_data_commands; parse_data_commands(data='')"
+
+ - name: Update codecov uploader
+ run: |
set +e
- # Always attempt to update the codecov script, but fall back on
- # the previously cached script if it fails
- CODECOV="${GITHUB_WORKSPACE}/cache/download/codecov.sh"
+ CODECOV="${GITHUB_WORKSPACE}/codecov.sh"
+ echo "CODECOV=$CODECOV" >> $GITHUB_ENV
for i in `seq 3`; do
echo "Downloading current codecov script (attempt ${i})"
curl -L https://codecov.io/bash -o $CODECOV
@@ -447,54 +568,74 @@ jobs:
echo "Pausing $DELAY seconds before re-attempting download"
sleep $DELAY
done
- i=0
- while : ; do
- ((i+=1))
- echo "Uploading coverage to codecov (attempt ${i})"
- bash $CODECOV -Z -X gcov -X s3 -f coverage.xml
- if test $? == 0; then
- echo "PASS" > ${GITHUB_WORKSPACE}/codecov.result
- break
- elif test $i -ge 2; then
- # Do not fail the build just because the codecov upload fails
- echo "FAIL" > ${GITHUB_WORKSPACE}/codecov.result
- break
+ if test ! -e $CODECOV; then
+ echo "Failed to download codecov.sh"
+ exit 1
+ fi
+
+ - name: Upload codecov reports
+ run: |
+ set +e
+ function upload {
+ echo ""
+ echo "Build group: $1"
+ export CODECOV_NAME=$1
+ export TAG=$1
+ export GHA_OS_NAME=${{matrix.TARGET}}
+ shift
+ rm -vf .coverage coverage.xml
+ echo " $@" | sed 's/ /\n /'
+ coverage combine --debug=dataio $@
+ if test ! -e .coverage; then
+ echo "No coverage to upload."
+ return
fi
- DELAY=$(( RANDOM % 30 + 30))
- echo "Pausing $DELAY seconds before re-attempting upload"
- sleep $DELAY
+ coverage xml || coverage xml -i
+ i=0
+ while : ; do
+ ((i+=1))
+ echo "Uploading coverage to codecov (attempt ${i})"
+ bash $CODECOV -Z -e TAG,GHA_OS_NAME -X gcov -X s3 \
+ -f coverage.xml
+ if test $? == 0; then
+ echo "PASS $CODECOV_NAME" >> codecov.result
+ break
+ elif test $i -ge 2; then
+ # Do not fail the build (yet) just because the codecov
+ # upload fails
+ echo "FAIL $CODECOV_NAME" >> codecov.result
+ break
+ fi
+ DELAY=$(( RANDOM % 30 + 30))
+ echo "Pausing $DELAY seconds before re-attempting upload"
+ sleep $DELAY
+ done
+ }
+ for ARTIFACT in artifacts/*_*${{matrix.TARGET}}_*; do
+ NAME=`echo $ARTIFACT | cut -d/ -f2`
+ cp -v $ARTIFACT/.coverage .coverage-$NAME
done
+ upload ${{matrix.TARGET}} .coverage-*_${{matrix.TARGET}}-*
+ if compgen -G ".coverage-*" > /dev/null; then
+ upload ${{matrix.TARGET}}/other .coverage-*
+ fi
+ # Legacy builds that don't support coverage 5.x
+ if compgen -G ".coverage-*" > /dev/null; then
+ echo ""
+ echo "Installing coverage 4.x for legacy builds"
+ pip install 'coverage<5'
+ upload ${{matrix.TARGET}}/legacy .coverage-*
+ fi
- - name: Record build artifacts
- uses: actions/upload-artifact@v2
- with:
- name: ${{github.job}}_${{env.GHA_JOBNAME}}
- path: |
- codecov.result
- # In general, do not record test results as artifacts to
- # manage total artifact storage
- # TEST-*.xml
-
- post:
- name: post-build
- needs: build
- runs-on: ubuntu-latest
- steps:
- - name: Download build artifacts
- uses: actions/download-artifact@v2
- with:
- path: artifacts
-
- - name: Check codecov upload success
- run: |
- FAIL=`grep FAIL artifacts/*/codecov.result | wc -l`
- ALL=`ls -1 artifacts/*/codecov.result | wc -l`
- # Fail is more than 1/9 codecov uploads fail
- echo "$FAIL of $ALL codecov uploads failed"
- if test $FAIL -gt 0; then
- grep FAIL artifacts/*/codecov.result | sed 's/^/ /'
- if test $(( $FAIL * 9 )) -gt $ALL; then
- echo "More than 1/9 codecov uploads failed:"
- exit 1
- fi
- fi
+ - name: Check codecov upload success
+ run: |
+ FAIL=`grep FAIL codecov.result | wc -l`
+ ALL=`cat codecov.result | wc -l`
+ echo "$FAIL of $ALL codecov uploads failed"
+ if test $FAIL -gt 0; then
+ grep FAIL codecov.result | sed 's/^/ /'
+ if test $FAIL -gt 1; then
+ echo "More than 1 codecov upload failed."
+ exit 1
+ fi
+ fi
diff --git a/.github/workflows/push_branch_test.yml b/.github/workflows/push_branch_test.yml
index 1ff9c682e41..768e000314b 100644
--- a/.github/workflows/push_branch_test.yml
+++ b/.github/workflows/push_branch_test.yml
@@ -16,23 +16,28 @@ defaults:
env:
PYTHONWARNINGS: ignore::UserWarning
+ PYTHON_CORE_PKGS: wheel
+ PYTHON_REQUIRED_PKGS: >
+ ply six nose coverage
PYTHON_BASE_PKGS: >
- coverage cython dill ipython networkx nose openpyxl pathos
- pint pymysql pyro4 pyyaml sphinx_rtd_theme sympy xlrd wheel
+ dill ipython networkx openpyxl pathos
+ pint pymysql pyro4 pyyaml sphinx_rtd_theme sympy xlrd
+ python-louvain
PYTHON_NUMPY_PKGS: >
numpy scipy pyodbc pandas matplotlib seaborn
CACHE_VER: v2
jobs:
build:
- name: ${{ matrix.TARGET }}/${{ matrix.python }}${{ matrix.NAME }}
+ name: ${{ matrix.TARGET }}/${{ matrix.python }}${{ matrix.other }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
python: [3.8]
- mpi: [0]
+ other: [""]
+
include:
- os: ubuntu-latest
TARGET: linux
@@ -51,12 +56,29 @@ jobs:
- os: ubuntu-latest
python: 3.7
+ other: /mpi
mpi: 3
skip_doctest: 1
TARGET: linux
PYENV: conda
- PACKAGES: mpi4py
- NAME: /mpi
+ PACKAGES: mpi4py openmpi
+
+ - os: ubuntu-latest
+ python: 3.9
+ other: /slim
+ slim: 1
+ skip_doctest: 1
+ TARGET: linux
+ PYENV: pip
+
+ - os: ubuntu-latest
+ python: 3.6
+ other: /cython
+ setup_options: --with-cython
+ skip_doctest: 1
+ TARGET: linux
+ PYENV: pip
+ PACKAGES: cython
exclude:
- {os: macos-latest, python: pypy2}
@@ -64,14 +86,32 @@ jobs:
- {os: windows-latest, python: pypy2}
- {os: windows-latest, python: pypy3}
-
steps:
- - uses: actions/checkout@v2
+ - name: Checkout Pyomo source
+ uses: actions/checkout@v2
- name: Configure job parameters
run: |
- JOB="${{matrix.TARGET}}/${{matrix.python}}${{matrix.NAME}}"
- echo "::set-env name=GHA_JOBNAME::"`echo "$JOB" | sed 's|/|_|g'`
+ JOB="${{matrix.TARGET}}/${{matrix.python}}${{matrix.other}}"
+ echo "GHA_JOBNAME=$JOB" | sed 's|/|_|g' >> $GITHUB_ENV
+ if test -z "${{matrix.other}}"; then
+ echo "GHA_JOBGROUP=${{matrix.TARGET}}" >> $GITHUB_ENV
+ else
+ echo "GHA_JOBGROUP=other" >> $GITHUB_ENV
+ fi
+ # Note: pandas 1.0.3 causes gams 29.1.0 import to fail in python 3.8
+ PYTHON_PACKAGES="${PYTHON_REQUIRED_PKGS}"
+ if test -z "${{matrix.slim}}"; then
+ PYTHON_PACKAGES="$PYTHON_PACKAGES ${PYTHON_BASE_PKGS}"
+ fi
+ if [[ ${{matrix.python}} != pypy* && ! "${{matrix.slim}}" ]]; then
+ # NumPy and derivatives either don't build under pypy, or if
+ # they do, the builds take forever.
+ PYTHON_PACKAGES="$PYTHON_PACKAGES ${PYTHON_NUMPY_PKGS}"
+ fi
+ PYTHON_PACKAGES="$PYTHON_PACKAGES ${{matrix.PACKAGES}}"
+ echo "PYTHON_PACKAGES=$PYTHON_PACKAGES" \
+ | tr '\n' ' ' | sed 's/ \+/ /g' >> $GITHUB_ENV
# Ideally we would cache the conda downloads; however, each cache is
# over 850MB, and with 5 python versions, that would consume 4.2 of
@@ -95,6 +135,7 @@ jobs:
- name: OS package cache
uses: actions/cache@v1
+ if: matrix.TARGET != 'osx'
id: os-cache
with:
path: cache/os
@@ -116,7 +157,7 @@ jobs:
)"
echo "$CURLRC" > ${GITHUB_WORKSPACE}/.curlrc
echo "$CURLRC" > ${GITHUB_WORKSPACE}/_curlrc
- echo "::set-env name=CURL_HOME::$GITHUB_WORKSPACE"
+ echo "CURL_HOME=$GITHUB_WORKSPACE" >> $GITHUB_ENV
- name: Update OSX
if: matrix.TARGET == 'osx'
@@ -154,7 +195,7 @@ jobs:
- name: Set up Miniconda Python ${{ matrix.python }}
if: matrix.PYENV == 'conda'
- uses: goanpeca/setup-miniconda@v1
+ uses: conda-incubator/setup-miniconda@v1
with:
auto-update-conda: true
python-version: ${{ matrix.python }}
@@ -181,21 +222,15 @@ jobs:
run: |
python -c 'import sys;print(sys.executable)'
python -m pip install --cache-dir cache/pip --upgrade pip
- # Note: pandas 1.0.3 causes gams 29.1.0 import to fail in python 3.8
- pip install --cache-dir cache/pip ${PYTHON_BASE_PKGS} \
- ${{matrix.PACKAGES}}
- if [[ ${{matrix.python}} != pypy* ]]; then
- # NumPy and derivatives either don't build under pypy, or if
- # they do, the builds take forever.
- pip install --cache-dir cache/pip ${PYTHON_NUMPY_PKGS}
- fi
+ pip install --cache-dir cache/pip ${PYTHON_CORE_PKGS}
+ pip install --cache-dir cache/pip ${PYTHON_PACKAGES}
pip install --cache-dir cache/pip cplex \
|| echo "WARNING: CPLEX Community Edition is not available"
pip install --cache-dir cache/pip xpress \
|| echo "WARNING: Xpress Community Edition is not available"
- python -c 'import sys; print("::set-env name=PYTHON_EXE::%s" \
- % (sys.executable,))'
- echo "::set-env name=NOSETESTS::"`which nosetests`
+ python -c 'import sys; print("PYTHON_EXE=%s" \
+ % (sys.executable,))' >> $GITHUB_ENV
+ echo "NOSETESTS="`which nosetests` >> $GITHUB_ENV
- name: Install Python packages (conda)
if: matrix.PYENV == 'conda'
@@ -207,17 +242,17 @@ jobs:
conda info
conda config --show-sources
conda list --show-channel-urls
- conda install -q -y -c conda-forge ${PYTHON_BASE_PKGS} \
- ${PYTHON_NUMPY_PKGS} ${{matrix.PACKAGES}}
+ conda install -q -y -c conda-forge ${PYTHON_CORE_PKGS}
+ conda install -q -y -c conda-forge ${PYTHON_PACKAGES}
# Note: CPLEX 12.9 (the last version in conda that supports
# Python 2.7) causes a seg fault in the tests.
conda install -q -y -c ibmdecisionoptimization cplex=12.10 \
|| echo "WARNING: CPLEX Community Edition is not available"
conda install -q -y -c fico-xpress xpress \
|| echo "WARNING: Xpress Community Edition is not available"
- python -c 'import sys; print("::set-env name=PYTHON_EXE::%s" \
- % (sys.executable,))'
- echo "::set-env name=NOSETESTS::"`which nosetests`
+ python -c 'import sys; print("PYTHON_EXE=%s" \
+ % (sys.executable,))' >> $GITHUB_ENV
+ echo "NOSETESTS="`which nosetests` >> $GITHUB_ENV
- name: Setup TPL package directories
run: |
@@ -225,13 +260,13 @@ jobs:
mkdir -p "$TPL_DIR"
DOWNLOAD_DIR="${GITHUB_WORKSPACE}/cache/download"
mkdir -p "$DOWNLOAD_DIR"
- echo "::set-env name=TPL_DIR::$TPL_DIR"
- echo "::set-env name=DOWNLOAD_DIR::$DOWNLOAD_DIR"
+ echo "TPL_DIR=$TPL_DIR" >> $GITHUB_ENV
+ echo "DOWNLOAD_DIR=$DOWNLOAD_DIR" >> $GITHUB_ENV
- name: Install Ipopt
run: |
IPOPT_DIR=$TPL_DIR/ipopt
- echo "::add-path::$IPOPT_DIR"
+ echo "$IPOPT_DIR" >> $GITHUB_PATH
mkdir -p $IPOPT_DIR
IPOPT_TAR=${DOWNLOAD_DIR}/ipopt.tar.gz
if test ! -e $IPOPT_TAR; then
@@ -259,9 +294,9 @@ jobs:
shell: pwsh
run: |
$GAMS_DIR="${env:TPL_DIR}/gams"
- echo "::add-path::$GAMS_DIR"
- echo "::set-env name=LD_LIBRARY_PATH::${env:LD_LIBRARY_PATH}:$GAMS_DIR"
- echo "::set-env name=DYLD_LIBRARY_PATH::${env:DYLD_LIBRARY_PATH}:$GAMS_DIR"
+ echo "$GAMS_DIR" >> $GITHUB_PATH
+ echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$GAMS_DIR" >> $GITHUB_ENV
+ echo "DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:$GAMS_DIR" >> $GITHUB_ENV
$INSTALLER="${env:DOWNLOAD_DIR}/gams_install.exe"
$URL="https://d37drm4t2jghv5.cloudfront.net/distributions/29.1.0"
if ( "${{matrix.TARGET}}" -eq "win" ) {
@@ -289,7 +324,7 @@ jobs:
- name: Install GAMS Python bindings
run: |
- GAMS_DIR="$TPL_DIR/gams"
+ GAMS_DIR="${env:TPL_DIR}/gams"
py_ver=$($PYTHON_EXE -c 'import sys;v="_%s%s" % sys.version_info[:2] \
;print(v if v != "_27" else "")')
if test -e $GAMS_DIR/apifiles/Python/api$py_ver; then
@@ -303,7 +338,7 @@ jobs:
shell: pwsh
run: |
$BARON_DIR="${env:TPL_DIR}/baron"
- echo "::add-path::$BARON_DIR"
+ echo "$BARON_DIR" >> $GITHUB_PATH
$URL="https://www.minlp.com/downloads/xecs/baron/current/"
if ( "${{matrix.TARGET}}" -eq "win" ) {
$INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.exe"
@@ -333,7 +368,7 @@ jobs:
if: matrix.TARGET != 'win'
run: |
GJH_DIR="$TPL_DIR/gjh"
- echo "::add-path::${GJH_DIR}"
+ echo "${GJH_DIR}" >> $GITHUB_PATH
INSTALL_DIR="${DOWNLOAD_DIR}/gjh"
if test ! -e "$INSTALL_DIR/bin"; then
mkdir -p "$INSTALL_DIR"
@@ -362,11 +397,11 @@ jobs:
echo ""
echo "Install Pyomo..."
echo ""
- $PYTHON_EXE setup.py develop
+ $PYTHON_EXE setup.py develop ${{matrix.setup_options}}
echo ""
echo "Set custom PYOMO_CONFIG_DIR"
echo ""
- echo "::set-env name=PYOMO_CONFIG_DIR::${GITHUB_WORKSPACE}/config"
+ echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV
- name: Set up coverage tracking
run: |
@@ -376,8 +411,8 @@ jobs:
COVERAGE_BASE=${GITHUB_WORKSPACE}/.cover
fi
COVERAGE_RC=${COVERAGE_BASE}_rc
- echo "::set-env name=COVERAGE_RCFILE::$COVERAGE_RC"
- echo "::set-env name=COVERAGE_PROCESS_START::$COVERAGE_RC"
+ echo "COVERAGE_RCFILE=$COVERAGE_RC" >> $GITHUB_ENV
+ echo "COVERAGE_PROCESS_START=$COVERAGE_RC" >> $GITHUB_ENV
cp ${GITHUB_WORKSPACE}/.coveragerc ${COVERAGE_RC}
echo "data_file=${COVERAGE_BASE}age" >> ${COVERAGE_RC}
SITE_PACKAGES=$($PYTHON_EXE -c "from distutils.sysconfig import \
@@ -426,16 +461,102 @@ jobs:
make -C doc/OnlineDocs doctest -d
- name: Process code coverage report
- env:
- CODECOV_NAME: ${{matrix.TARGET}}/${{matrix.python}}${{matrix.NAME}}
run: |
coverage combine
coverage report -i
coverage xml -i
+
+ - name: Record build artifacts
+ uses: actions/upload-artifact@v2
+ with:
+ name: ${{github.job}}_${{env.GHA_JOBGROUP}}-${{env.GHA_JOBNAME}}
+ path: |
+ .coverage
+ coverage.xml
+ # In general, do not record test results as artifacts to
+ # manage total artifact storage
+ # TEST-*.xml
+
+ cover:
+ name: process-coverage-${{ matrix.TARGET }}
+ needs: build
+ if: always() # run even if a build job fails
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-latest]
+
+ include:
+ - os: ubuntu-latest
+ TARGET: linux
+ - os: macos-latest
+ TARGET: osx
+ - os: windows-latest
+ TARGET: win
+
+ steps:
+ - name: Checkout Pyomo source
+ uses: actions/checkout@v2
+ # We need the source for .codecov.yml and running "coverage xml"
+
+ - name: Pip package cache
+ uses: actions/cache@v1
+ id: pip-cache
+ with:
+ path: cache/pip
+ key: pip-${{env.CACHE_VER}}.0-${{runner.os}}-3.8
+
+ - name: Download build artifacts
+ uses: actions/download-artifact@v2
+ with:
+ path: artifacts
+
+ - name: Set up Python 3.8
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.8
+
+ - name: Install Python Packages (pip)
+ shell: bash # DO NOT REMOVE: see note above
+ run: |
+ python -c 'import sys;print(sys.executable)'
+ python -m pip install --cache-dir cache/pip --upgrade pip
+ pip install --cache-dir cache/pip ${PYTHON_CORE_PKGS} \
+ ${PYTHON_REQUIRED_PKGS}
+ python -c 'import sys; print("PYTHON_EXE=%s" \
+ % (sys.executable,))' >> $GITHUB_ENV
+
+ - name: Install Pyomo and PyUtilib
+ run: |
+ echo ""
+ echo "Clone Pyomo-model-libraries..."
+ git clone https://github.com/Pyomo/pyomo-model-libraries.git
+ echo ""
+ echo "Install PyUtilib..."
+ echo ""
+ $PYTHON_EXE -m pip install git+https://github.com/PyUtilib/pyutilib
+ echo ""
+ echo "Install Pyomo..."
+ echo ""
+ $PYTHON_EXE setup.py develop ${{matrix.setup_options}}
+ echo ""
+ echo "Set custom PYOMO_CONFIG_DIR"
+ echo ""
+ echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV
+
+ - name: Generate parse_table_datacmds
+ run: |
+ # Manually invoke the DAT parser so that parse_table_datacmds.py
+ # is generated before running "coverage xml"
+ $PYTHON_EXE -c "from pyomo.dataportal.parse_datacmds import \
+ parse_data_commands; parse_data_commands(data='')"
+
+ - name: Update codecov uploader
+ run: |
set +e
- # Always attempt to update the codecov script, but fall back on
- # the previously cached script if it fails
- CODECOV="${GITHUB_WORKSPACE}/cache/download/codecov.sh"
+ CODECOV="${GITHUB_WORKSPACE}/codecov.sh"
+ echo "CODECOV=$CODECOV" >> $GITHUB_ENV
for i in `seq 3`; do
echo "Downloading current codecov script (attempt ${i})"
curl -L https://codecov.io/bash -o $CODECOV
@@ -446,54 +567,74 @@ jobs:
echo "Pausing $DELAY seconds before re-attempting download"
sleep $DELAY
done
- i=0
- while : ; do
- ((i+=1))
- echo "Uploading coverage to codecov (attempt ${i})"
- bash $CODECOV -Z -X gcov -X s3 -f coverage.xml
- if test $? == 0; then
- echo "PASS" > ${GITHUB_WORKSPACE}/codecov.result
- break
- elif test $i -ge 2; then
- # Do not fail the build just because the codecov upload fails
- echo "FAIL" > ${GITHUB_WORKSPACE}/codecov.result
- break
+ if test ! -e $CODECOV; then
+ echo "Failed to download codecov.sh"
+ exit 1
+ fi
+
+ - name: Upload codecov reports
+ run: |
+ set +e
+ function upload {
+ echo ""
+ echo "Build group: $1"
+ export CODECOV_NAME=$1
+ export TAG=$1
+ export GHA_OS_NAME=${{matrix.TARGET}}
+ shift
+ rm -vf .coverage coverage.xml
+ echo " $@" | sed 's/ /\n /'
+ coverage combine --debug=dataio $@
+ if test ! -e .coverage; then
+ echo "No coverage to upload."
+ return
fi
- DELAY=$(( RANDOM % 30 + 30))
- echo "Pausing $DELAY seconds before re-attempting upload"
- sleep $DELAY
+ coverage xml || coverage xml -i
+ i=0
+ while : ; do
+ ((i+=1))
+ echo "Uploading coverage to codecov (attempt ${i})"
+ bash $CODECOV -Z -e TAG,GHA_OS_NAME -X gcov -X s3 \
+ -f coverage.xml
+ if test $? == 0; then
+ echo "PASS $CODECOV_NAME" >> codecov.result
+ break
+ elif test $i -ge 2; then
+ # Do not fail the build (yet) just because the codecov
+ # upload fails
+ echo "FAIL $CODECOV_NAME" >> codecov.result
+ break
+ fi
+ DELAY=$(( RANDOM % 30 + 30))
+ echo "Pausing $DELAY seconds before re-attempting upload"
+ sleep $DELAY
+ done
+ }
+ for ARTIFACT in artifacts/*_*${{matrix.TARGET}}_*; do
+ NAME=`echo $ARTIFACT | cut -d/ -f2`
+ cp -v $ARTIFACT/.coverage .coverage-$NAME
done
+ upload ${{matrix.TARGET}} .coverage-*_${{matrix.TARGET}}-*
+ if compgen -G ".coverage-*" > /dev/null; then
+ upload ${{matrix.TARGET}}/other .coverage-*
+ fi
+ # Legacy builds that don't support coverage 5.x
+ if compgen -G ".coverage-*" > /dev/null; then
+ echo ""
+ echo "Installing coverage 4.x for legacy builds"
+ pip install 'coverage<5'
+ upload ${{matrix.TARGET}}/legacy .coverage-*
+ fi
- - name: Record build artifacts
- uses: actions/upload-artifact@v2
- with:
- name: ${{github.job}}_${{env.GHA_JOBNAME}}
- path: |
- codecov.result
- # In general, do not record test results as artifacts to
- # manage total artifact storage
- # TEST-*.xml
-
- post:
- name: post-build
- needs: build
- runs-on: ubuntu-latest
- steps:
- - name: Download build artifacts
- uses: actions/download-artifact@v2
- with:
- path: artifacts
-
- - name: Check codecov upload success
- run: |
- FAIL=`grep FAIL artifacts/*/codecov.result | wc -l`
- ALL=`ls -1 artifacts/*/codecov.result | wc -l`
- # Fail is more than 1/9 codecov uploads fail
- echo "$FAIL of $ALL codecov uploads failed"
- if test $FAIL -gt 0; then
- grep FAIL artifacts/*/codecov.result | sed 's/^/ /'
- if test $(( $FAIL * 9 )) -gt $ALL; then
- echo "More than 1/9 codecov uploads failed:"
- exit 1
- fi
- fi
+ - name: Check codecov upload success
+ run: |
+ FAIL=`grep FAIL codecov.result | wc -l`
+ ALL=`cat codecov.result | wc -l`
+ echo "$FAIL of $ALL codecov uploads failed"
+ if test $FAIL -gt 0; then
+ grep FAIL codecov.result | sed 's/^/ /'
+ if test $FAIL -gt 1; then
+ echo "More than 1 codecov upload failed."
+ exit 1
+ fi
+ fi
diff --git a/.gitignore b/.gitignore
index 83a1ea0f817..f44c82598ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,7 @@
.idea
.spyder*
.ropeproject
-
+.vscode
# Python generates numerous files when byte compiling / installing packages
*.pyx
*.pyc
diff --git a/.jenkins.sh b/.jenkins.sh
index 7f716779c6b..7fea07351ac 100644
--- a/.jenkins.sh
+++ b/.jenkins.sh
@@ -25,6 +25,9 @@
#
# DISABLE_COVERAGE: if nonempty, then coverage analysis is disabled
#
+# PYOMO_SETUP_ARGS: passed to the 'python setup.py develop' command
+# (e.g., to specify --with-cython)
+#
# PYOMO_DOWNLOAD_ARGS: passed to the 'pyomo download-extensions" command
# (e.g., to set up local SSL certificate authorities)
#
@@ -52,16 +55,21 @@ MODE="$1"
if test -z "$MODE" -o "$MODE" == setup; then
# Clean old PYC files and remove any previous virtualenv
echo "#"
- echo "# Cleaning out old .pyc files"
+ echo "# Removing python virtual environment"
echo "#"
rm -rf ${WORKSPACE}/python
- find ${WORKSPACE}/pyomo -name \*.pyc -delete
- find ${WORKSPACE}/pyutilib -name \*.pyc -delete
+ echo "#"
+ echo "# Cleaning out old .pyc and cython files"
+ echo "#"
+ for EXT in pyc pyx pyd so dylib dll; do
+ find ${WORKSPACE}/pyomo -name \*.$EXT -delete
+ find ${WORKSPACE}/pyutilib -name \*.$EXT -delete
+ done
# Set up the local lpython
echo ""
echo "#"
- echo "# Setting up virutal environment"
+ echo "# Setting up virtual environment"
echo "#"
virtualenv python $VENV_SYSTEM_PACKAGES --clear
# Put the venv at the beginning of the PATH
@@ -81,7 +89,7 @@ if test -z "$MODE" -o "$MODE" == setup; then
python setup.py develop || exit 1
popd
pushd "$WORKSPACE/pyomo" || exit 1
- python setup.py develop || exit 1
+ python setup.py develop $PYOMO_SETUP_ARGS || exit 1
popd
#
# DO NOT install pyomo-model-libraries
@@ -187,7 +195,7 @@ if test -z "$MODE" -o "$MODE" == test; then
while /bin/true; do
i=$[$i+1]
echo "Uploading coverage to codecov (attempt $i)"
- codecov -X gcovcodecov -X gcov --no-color \
+ codecov -X gcovcodecov -X gcov -X s3 --no-color \
-t $CODECOV_TOKEN --root `pwd` -e OS,python \
--name $CODECOV_JOB_NAME $CODECOV_ARGS \
| tee .cover.upload
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 4500f279b28..2edf67bdeb0 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -2,6 +2,68 @@
Pyomo CHANGELOG
===============
+-------------------------------------------------------------------------------
+Pyomo 5.7.1 15 Sep 2020
+-------------------------------------------------------------------------------
+
+- General
+ - Add functions for checking the solver termination condition to environ (#1540)
+ - Remove appdirs dependency (#1558)
+ - Setting version number for new deprecation warnings (#1524)
+ - Add generic tarball creation to GitHub Actions Workflow for creating Wheels
+ (#1522)
+ - Deprecate pyomo install-extras (#1521)
+ - Add test to monitor 'import pyomo.environ' time (#1577)
+ - Move ComponentMap and ComponentSet to pyomo.common.collections (#1593)
+ - Fix issue when parsing /etc/os-release (#1603)
+ - Fix deprecation decorator tests (#1629)
+- Core
+ - Add a logical expression system (#1507)
+ - Resolve table formatting with unicode character data (#1530)
+ - Fix Model.compute_statistics method (#1553)
+ - Deprecate CUID targets in add_slack_variables transformation (#1563)
+ - Defer import of sympy in the cnf_walker (#1576)
+ - Minor fixes to units (#1582, #1584)
+ - Add IndexedSet.data method that was mistakenly removed (#1609)
+ - Add support for class method initializers (#1608)
+ - Rework constraint initialization (#1592)
+ - Remove truthiness assumption for sequence in TuplizeValuesInitializer (#1620)
+ - Add deprecated support for Var(within=RealSet) (#1619)
+ - Fix standard repn of external functions with fixed arguments (#1623)
+- Solver Interfaces
+ - Use Baron option to more consistently return duals (#1538)
+ - Add direct and persistent interfaces to Xpress (#1443)
+ - Augment persistent solver interfaces to support column generation (#1568)
+- DAE Updates
+ - Add options to solve_consistent_initial_conditions (#1534, #1606)
+ - Add find_nearest_index method to ContinuousSet (#1559)
+ - Allow flattening of ctypes other than Var (#1583)
+- GDP Updates
+ - Fix a couple bugs in GDP basic steps (#1532)
+ - Make key for calculated M values in bigM dictionary consistent (#1618)
+- Testing
+ - Fix to retry codecov upload if codecov.sh script fails (#1539)
+ - Update to GitHub Actions tests to fix an OSX Python environment failure (#1555)
+ - Allow failing codecov uploads on GitHub Actions tests (#1561)
+ - Add doctests to the GitHub Actions builds (#1542)
+ - Add manual job trigger for GitHub Actions Workflows (#1578)
+ - Rebuild GitHub Actions download caches (#1598)
+ - Disable OS package cache for OSX (#1625)
+- Documentation
+ - Clean up some old documentation on sparse sets (#1545)
+ - Remove OnlineDocs spy files from the repository (#1549)
+ - Resolve RTD documentation build warnings (#1552)
+ - Fix typo in code snippet (#1624)
+ - Update contribution guide (#1621)
+- Contributed Packages
+ - Defer the Z3 availability check in the satsolver (#1529)
+ - MindtPy: add configuration arguments, bug fixes (#1500)
+ - Parmest: fix solver options typo, update graphics module (#1531, #1622)
+ - PyNumero: Add scaling to Cyipopt interface, set AMPLFUNC before loading NL
+ files, improve MPI matvec performance (#1554, #1546, #1610)
+ - Fix bugs in sensitivity toolbox (#1536, #1574)
+ - Add integer arithmetic option to FME transformation (#1594)
+
-------------------------------------------------------------------------------
Pyomo 5.7.0 19 Jun 2020
-------------------------------------------------------------------------------
diff --git a/README.md b/README.md
index dea07ed9db3..62eae133fb2 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,6 @@
[![a COIN-OR project](https://www.coin-or.org/GitHub/coin-or-badge.png)](https://www.coin-or.org)
## Pyomo Overview
-
Pyomo is a Python-based open-source software package that supports a diverse set of optimization capabilities for formulating and analyzing optimization models. Pyomo can be used to define symbolic problems, create concrete problem instances, and solve these instances with standard solvers. Pyomo supports a wide range of problem types, including:
- Linear programming
diff --git a/RELEASE.txt b/RELEASE.txt
index 8225042e7ed..8cc5d3e7140 100644
--- a/RELEASE.txt
+++ b/RELEASE.txt
@@ -1,13 +1,15 @@
-We are pleased to announce the release of Pyomo 5.7.0. Pyomo is a collection
+We are pleased to announce the release of Pyomo 5.7.1. Pyomo is a collection
of Python software packages that supports a diverse set of optimization
capabilities for formulating and analyzing optimization models.
The following are highlights of the 5.7 release series:
+ - Adding a logical expression system
- Standardizing component initialization
- Distribution of Cythonized wheels
- Reimplementation of the core Set component
+ - Deprecating pyomo-extras
- Numerous bug fixes
A full list of updates and changes is available in the CHANGELOG.txt
diff --git a/doc/OnlineDocs/conf.py b/doc/OnlineDocs/conf.py
index 4d21cb2c1af..8022cd22579 100644
--- a/doc/OnlineDocs/conf.py
+++ b/doc/OnlineDocs/conf.py
@@ -213,8 +213,13 @@ def setup(app):
doctest_global_setup = '''
-import pyomo.opt
+from pyomo.common.dependencies import (
+ attempt_import, numpy_available, scipy_available, pandas_available,
+ yaml_available, networkx_available
+)
+pint_available = attempt_import('pint', defer_check=False)[1]
+import pyomo.opt
# Not using SolverFactory to check solver availability because
# as of June 2020 there is no way to supress warnings when
# solvers are not available
diff --git a/doc/OnlineDocs/contributed_packages/mindtpy.rst b/doc/OnlineDocs/contributed_packages/mindtpy.rst
index 3b05762b065..8c909ea5513 100644
--- a/doc/OnlineDocs/contributed_packages/mindtpy.rst
+++ b/doc/OnlineDocs/contributed_packages/mindtpy.rst
@@ -7,12 +7,13 @@ These decomposition algorithms usually rely on the solution of Mixed-Intger Line
(MILP) and Nonlinear Programs (NLP).
MindtPy currently implements the Outer Approximation (OA) algorithm originally described in
-`Duran & Grossmann, 1986`_. Usage and implementation
+`Duran & Grossmann, 1986`_ and the Extended Cutting Plane (ECP) algorithm originally described in `Westerlund & Petterson, 1995`_. Usage and implementation
details for MindtPy can be found in the PSE 2018 paper Bernal et al.,
(`ref `_,
`preprint `_).
.. _Duran & Grossmann, 1986: https://dx.doi.org/10.1007/BF02592064
+.. _Westerlund & Petterson, 1995: http://dx.doi.org/10.1016/0098-1354(95)87027-X
Usage of MindtPy to solve a Pyomo concrete model involves:
@@ -58,6 +59,20 @@ The solution may then be displayed by using the commands
>>> SolverFactory('mindtpy').solve(model, mip_solver='glpk', nlp_solver='ipopt', tee=True)
+MindtPy also supports setting options for mip solver and nlp solver.
+
+.. code::
+
+ >>> SolverFactory('mindtpy').solve(model,
+ strategy='OA',
+ time_limit=3600,
+ mip_solver='gams',
+ mip_solver_args=dict(solver='cplex', warmstart=True),
+ nlp_solver='ipopt',
+ tee=True)
+
+There are three initialization strategies in MindtPy: rNLP, initial_binary, max_binary. In OA and GOA strategies, the default initialization strategy is rNLP. In ECP strategy, the default initialization strategy is max_binary.
+
Single tree implementation
---------------------------------------------
diff --git a/doc/OnlineDocs/contributed_packages/parmest/datarec.rst b/doc/OnlineDocs/contributed_packages/parmest/datarec.rst
index 92c61412993..1877cd49caf 100644
--- a/doc/OnlineDocs/contributed_packages/parmest/datarec.rst
+++ b/doc/OnlineDocs/contributed_packages/parmest/datarec.rst
@@ -1,7 +1,7 @@
.. _datarecsection:
Data Reconciliation
-=================================
+====================
The method :class:`~pyomo.contrib.parmest.parmest.Estimator.theta_est`
can optionally return model values. This feature can be used to return
@@ -17,6 +17,8 @@ reconciliation. The functions
:class:`~pyomo.contrib.parmest.graphics.grouped_violinplot` can be used
to visually compare the original and reconciled data.
+Here's a stylized code snippet showing how box plots might be created:
+
.. doctest::
:skipif: True
@@ -24,3 +26,33 @@ to visually compare the original and reconciled data.
>>> pest = parmest.Estimator(model_function, data, [], objective_function)
>>> obj, theta, data_rec = pest.theta_est(return_values=['A', 'B'])
>>> parmest.grouped_boxplot(data, data_rec)
+
+Returned Values
+^^^^^^^^^^^^^^^
+
+Here's a full program that can be run to see returned values (in this case it
+is the response function that is defined in the model file):
+
+.. doctest::
+ :skipif: not ipopt_available or not pandas_available
+
+ >>> import pandas as pd
+ >>> import pyomo.contrib.parmest.parmest as parmest
+ >>> from pyomo.contrib.parmest.examples.rooney_biegler.rooney_biegler import rooney_biegler_model
+
+ >>> theta_names = ['asymptote', 'rate_constant']
+
+ >>> data = pd.DataFrame(data=[[1,8.3],[2,10.3],[3,19.0],
+ ... [4,16.0],[5,15.6],[7,19.8]],
+ ... columns=['hour', 'y'])
+
+ >>> def SSE(model, data):
+ ... expr = sum((data.y[i]\
+ ... - model.response_function[data.hour[i]])**2 for i in data.index)
+ ... return expr
+
+ >>> pest = parmest.Estimator(rooney_biegler_model, data, theta_names, SSE,
+ ... solver_options=None)
+ >>> obj, theta, var_values = pest.theta_est(return_values=['response_function'])
+ >>> #print(var_values)
+
diff --git a/doc/OnlineDocs/contribution_guide.rst b/doc/OnlineDocs/contribution_guide.rst
index 3439a96ff88..0ac25173f43 100644
--- a/doc/OnlineDocs/contribution_guide.rst
+++ b/doc/OnlineDocs/contribution_guide.rst
@@ -14,6 +14,10 @@ separated from functional changes. This simplifies the review process
and ensures that functional changes aren't obscured by large amounts of
non-functional changes.
+We do not squash and merge PRs so all commits in your branch will appear
+in the master history. In addition to well-documented PR descriptions,
+we encourage modular/targeted commits with descriptive commit messages.
+
Coding Standards
++++++++++++++++
@@ -36,20 +40,22 @@ and contributions to ``pyomo.contrib``.
Testing
+++++++
-Pyomo uses ``unittest``, TravisCI, and Appveyor for testing and
-continuous integration. Submitted code should include tests to establish
-the validity of its results and/or effects. Unit tests are preferred but
-we also accept integration tests. When test are run on a PR, we require
-at least 70% coverage of the lines modified in the PR and prefer
-coverage closer to 90%. We also require that all tests pass before a PR
-will be merged.
-
-The Pyomo master branch (as of `this commit `) provides a Github Action
-workflow that will test any changes pushed to a branch using Ubuntu with
-Python 3.7. For existing forks, fetch and merge your fork (and branches) with
-Pyomo's master. For new forks, you will need to enable Github Actions
-in the 'Actions' tab on your fork. Then the test will begin to run
-automatically with each push to your fork.
+Pyomo uses ``unittest``, TravisCI, and
+`GitHub workflows `_
+for testing and continuous integration. Submitted code should include
+tests to establish the validity of its results and/or effects. Unit
+tests are preferred but we also accept integration tests. We require
+at least 70% coverage of the lines modified in the PR and prefer coverage
+closer to 90%. We also require that all tests pass before a PR will be
+merged.
+
+The Pyomo master branch provides a Github Actions workflow (configured
+in the ``.github/`` directory) that will test any changes pushed to
+a branch on multiple virtual machines (ubuntu, mac-os, windows)
+and with multiple Python versions. For existing forks, fetch and merge
+your fork (and branches) with Pyomo's master. For new forks, you will
+need to enable Github Actions in the 'Actions' tab on your fork.
+Then the tests will begin to run automatically with each push to your fork.
At any point in the development cycle, a "work in progress" pull request
may be opened by including '[WIP]' at the beginning of the PR
diff --git a/doc/OnlineDocs/working_models.rst b/doc/OnlineDocs/working_models.rst
index 9bfcffb4ae4..df334aa0891 100644
--- a/doc/OnlineDocs/working_models.rst
+++ b/doc/OnlineDocs/working_models.rst
@@ -301,8 +301,8 @@ Note that
is equivalent to
- >>> instance.y.value = 2
- >>> instance.y.fixed = True
+ >>> instance.x.value = 2
+ >>> instance.x.fixed = True
and
>>> instance.x.fix()
@@ -614,7 +614,7 @@ snippet:
If multiple options are needed, then multiple dictionary entries should
be added.
-Sometime it is desirable to pass options as part of the call to the
+Sometimes it is desirable to pass options as part of the call to the
solve function as in this snippet:
.. literalinclude:: tests/scripting/spy4scripts_Add_multiple_options_to_solver.spy
diff --git a/examples/pysp/farmer/models/ReferenceModel.py b/examples/pysp/farmer/models/ReferenceModel.py
index 9620fe73916..973130af1b6 100644
--- a/examples/pysp/farmer/models/ReferenceModel.py
+++ b/examples/pysp/farmer/models/ReferenceModel.py
@@ -14,7 +14,9 @@
# Imports
#
-from pyomo.core import *
+from pyomo.core import (AbstractModel, Set, Param, Var, sum_product,
+ PositiveReals, NonNegativeReals, Constraint,
+ Objective, Expression, minimize)
#
# Model
diff --git a/pyomo/bilevel/__init__.py b/pyomo/bilevel/__init__.py
index 9259b8a1e6f..12986cf5f43 100644
--- a/pyomo/bilevel/__init__.py
+++ b/pyomo/bilevel/__init__.py
@@ -10,4 +10,5 @@
# Package files
-from pyomo.bilevel.components import *
+from pyomo.bilevel.components import (SubModel, ModelComponentFactory,
+ Component, SimpleBlock)
diff --git a/pyomo/bilevel/plugins/lcp.py b/pyomo/bilevel/plugins/lcp.py
index 158ebbb3174..11ab41e9e1c 100644
--- a/pyomo/bilevel/plugins/lcp.py
+++ b/pyomo/bilevel/plugins/lcp.py
@@ -15,7 +15,6 @@
from pyomo.repn import generate_standard_repn
from pyomo.mpec import ComplementarityList, complements
from pyomo.bilevel.plugins.transform import Base_BilevelTransformation
-from pyomo.bilevel.components import SubModel
logger = logging.getLogger('pyomo.core')
diff --git a/pyomo/bilevel/plugins/solver1.py b/pyomo/bilevel/plugins/solver1.py
index 7e77fa6b849..b6bab05da8d 100644
--- a/pyomo/bilevel/plugins/solver1.py
+++ b/pyomo/bilevel/plugins/solver1.py
@@ -12,7 +12,6 @@
import pyutilib.misc
from pyomo.core import TransformationFactory, Var, ComponentUID, Block, Objective, Set
import pyomo.opt
-from pyomo.bilevel.components import SubModel
import pyomo.common
diff --git a/pyomo/bilevel/plugins/solver2.py b/pyomo/bilevel/plugins/solver2.py
index 6a80ad633cd..86a2592b4c2 100644
--- a/pyomo/bilevel/plugins/solver2.py
+++ b/pyomo/bilevel/plugins/solver2.py
@@ -116,12 +116,6 @@ def _postsolve(self):
prob.number_of_continuous_variables = self._instance.statistics.number_of_continuous_variables
prob.number_of_objectives = self._instance.statistics.number_of_objectives
#
- from pyomo.core import maximize
- ##if self._instance.sense == maximize:
- ##prob.sense = pyomo.opt.ProblemSense.maximize
- ##else:
- ##prob.sense = pyomo.opt.ProblemSense.minimize
- #
# SOLUTION(S)
#
self._instance.solutions.store_to(results)
diff --git a/pyomo/bilevel/plugins/solver3.py b/pyomo/bilevel/plugins/solver3.py
index 21e5912c198..8442540094e 100644
--- a/pyomo/bilevel/plugins/solver3.py
+++ b/pyomo/bilevel/plugins/solver3.py
@@ -118,12 +118,6 @@ def _postsolve(self):
prob.number_of_continuous_variables = self._instance.statistics.number_of_continuous_variables
prob.number_of_objectives = self._instance.statistics.number_of_objectives
#
- from pyomo.core import maximize
- ##if self._instance.sense == maximize:
- ##prob.sense = pyomo.opt.ProblemSense.maximize
- ##else:
- ##prob.sense = pyomo.opt.ProblemSense.minimize
- #
# SOLUTION(S)
#
self._instance.solutions.store_to(results)
diff --git a/pyomo/bilevel/tests/test_blp.py b/pyomo/bilevel/tests/test_blp.py
index 6dd2ace5a74..c0f68b3331a 100644
--- a/pyomo/bilevel/tests/test_blp.py
+++ b/pyomo/bilevel/tests/test_blp.py
@@ -12,7 +12,6 @@
# Test transformations for bilevel linear programs
#
-import sys
import os
from os.path import abspath, dirname, normpath, join
currdir = dirname(abspath(__file__))
@@ -25,7 +24,7 @@
import pyomo.opt
import pyomo.scripting.pyomo_main as pyomo_main
from pyomo.scripting.util import cleanup
-from pyomo.environ import *
+from pyomo.environ import TransformationFactory
from six import iteritems
diff --git a/pyomo/bilevel/tests/test_linear_dual.py b/pyomo/bilevel/tests/test_linear_dual.py
index 35b29a0ccfd..05c0dc425a3 100644
--- a/pyomo/bilevel/tests/test_linear_dual.py
+++ b/pyomo/bilevel/tests/test_linear_dual.py
@@ -15,7 +15,7 @@
import os
from os.path import abspath, dirname, normpath, join
currdir = dirname(abspath(__file__))
-exdir = normpath(join(currdir,'..','..','..','examples','bilevel'))
+exdir = normpath(join(currdir, '..', '..', '..', 'examples', 'bilevel'))
import pyutilib.th as unittest
@@ -23,12 +23,13 @@
import pyomo.opt
import pyomo.scripting.pyomo_main as pyomo_main
from pyomo.scripting.util import cleanup
-from pyomo.environ import *
+import pyomo.environ
from six import iteritems
solvers = pyomo.opt.check_available_solvers('cplex', 'glpk')
+
class CommonTests:
solve = True
@@ -37,7 +38,7 @@ def run_bilevel(self, *_args, **kwds):
if self.solve:
args = ['solve']
if 'solver' in kwds:
- _solver = kwds.get('solver','glpk')
+ _solver = kwds.get('solver', 'glpk')
args.append('--solver=bilevel_ld')
args.append('--solver-options="solver=%s"' % _solver)
args.append('--save-results=result.yml')
@@ -45,7 +46,7 @@ def run_bilevel(self, *_args, **kwds):
else:
args = ['convert']
if 'preprocess' in kwds:
- #args.append('--solver=glpk')
+ # args.append('--solver=glpk')
pp = kwds['preprocess']
if pp == 'linear_dual':
args.append('--transform=bilevel.linear_dual')
@@ -55,8 +56,8 @@ def run_bilevel(self, *_args, **kwds):
# which now causes a helpful error message.
# I've manually inserted them into those tests that need them to pass
# (which is where they also get used)
- #args.append('--symbolic-solver-labels')
- #args.append('--file-determinism=2')
+ # args.append('--symbolic-solver-labels')
+ # args.append('--file-determinism=2')
if False:
args.append('--stream-solver')
@@ -68,7 +69,7 @@ def run_bilevel(self, *_args, **kwds):
os.chdir(currdir)
print('***')
- #print(' '.join(args))
+ # print(' '.join(args))
try:
output = pyomo_main.main(args)
except SystemExit:
@@ -99,17 +100,17 @@ def getObjective(self, fname):
def updateDocStrings(self):
for key in dir(self):
if key.startswith('test'):
- getattr(self,key).__doc__ = " (%s)" % getattr(self,key).__name__
+ getattr(self, key).__doc__ = " (%s)" % getattr(self, key).__name__
def test_t5(self):
- self.problem='test_t5'
- self.run_bilevel( join(exdir,'t5.py'))
- self.check( 't5', 'linear_dual' )
+ self.problem = 'test_t5'
+ self.run_bilevel(join(exdir, 't5.py'))
+ self.check('t5', 'linear_dual')
def test_t1(self):
- self.problem='test_t1'
- self.run_bilevel( join(exdir,'t1.py'))
- self.check( 't1', 'linear_dual' )
+ self.problem = 'test_t1'
+ self.run_bilevel(join(exdir, 't1.py'))
+ self.check('t1', 'linear_dual')
def Xtest_t2(self):
self.problem='test_t2'
@@ -122,8 +123,8 @@ class Reformulate(unittest.TestCase, CommonTests):
solve = False
def tearDown(self):
- if os.path.exists(os.path.join(currdir,'result.yml')):
- os.remove(os.path.join(currdir,'result.yml'))
+ if os.path.exists(os.path.join(currdir, 'result.yml')):
+ os.remove(os.path.join(currdir, 'result.yml'))
def run_bilevel(self, *args, **kwds):
args = list(args)
diff --git a/pyomo/checker/__init__.py b/pyomo/checker/__init__.py
index 4ef9ae55172..70c13420d65 100644
--- a/pyomo/checker/__init__.py
+++ b/pyomo/checker/__init__.py
@@ -11,18 +11,16 @@
from pyomo.common.plugin import PluginGlobals
PluginGlobals.add_env("pyomo")
-from pyomo.checker.checker import *
-from pyomo.checker.runner import *
-from pyomo.checker.script import *
-from pyomo.checker.hooks import *
+from pyomo.checker.checker import Interface, IModelChecker
+from pyomo.checker.runner import ExtensionPoint, CheckingNodeVisitor, ModelCheckRunner
+from pyomo.checker.script import ModelScript
+from pyomo.checker.hooks import IPreCheckHook, IPostCheckHook
# Modules
__all__ = []
# Checker classes
__all__.extend(['IModelChecker'])
-#__all__.extend(['ImmediateDataChecker', 'IterativeDataChecker'])
-#__all__.extend(['ImmediateTreeChecker', 'IterativeTreeChecker'])
# Other builtins
__all__.extend(['ModelCheckRunner', 'ModelScript'])
diff --git a/pyomo/checker/checker.py b/pyomo/checker/checker.py
index 18e1b9aede7..9ac55250c75 100644
--- a/pyomo/checker/checker.py
+++ b/pyomo/checker/checker.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.common.plugin import *
+from pyomo.common.plugin import Interface
class IModelChecker(Interface):
diff --git a/pyomo/checker/hooks.py b/pyomo/checker/hooks.py
index 03248d85f79..d80d31b7cab 100644
--- a/pyomo/checker/hooks.py
+++ b/pyomo/checker/hooks.py
@@ -10,7 +10,7 @@
__all__ = ['IPreCheckHook', 'IPostCheckHook']
-from pyomo.common.plugin import *
+from pyomo.common.plugin import Interface
class IPreCheckHook(Interface):
diff --git a/pyomo/checker/plugins/checker.py b/pyomo/checker/plugins/checker.py
index 70e69a00e5d..7694b40aefe 100644
--- a/pyomo/checker/plugins/checker.py
+++ b/pyomo/checker/plugins/checker.py
@@ -12,8 +12,8 @@
import re
import textwrap
-from pyomo.common.plugin import *
-from pyomo.checker import *
+from pyomo.common.plugin import SingletonPlugin, implements, ExtensionPoint
+from pyomo.checker import IModelChecker, IPreCheckHook, IPostCheckHook
class PyomoModelChecker(SingletonPlugin):
diff --git a/pyomo/checker/plugins/function.py b/pyomo/checker/plugins/function.py
index a6367a4f3f5..038844a45f4 100644
--- a/pyomo/checker/plugins/function.py
+++ b/pyomo/checker/plugins/function.py
@@ -10,8 +10,8 @@
import ast
-from pyomo.common.plugin import *
-from pyomo.checker.hooks import *
+from pyomo.common.plugin import SingletonPlugin, implements
+from pyomo.checker.hooks import IPreCheckHook, IPostCheckHook
class FunctionTrackerHook(SingletonPlugin):
diff --git a/pyomo/checker/plugins/model.py b/pyomo/checker/plugins/model.py
index 8edfa00baa0..33feae5ec77 100644
--- a/pyomo/checker/plugins/model.py
+++ b/pyomo/checker/plugins/model.py
@@ -10,8 +10,8 @@
import ast
-from pyomo.common.plugin import *
-from pyomo.checker.hooks import *
+from pyomo.common.plugin import SingletonPlugin, implements
+from pyomo.checker.hooks import IPreCheckHook
class ModelTrackerHook(SingletonPlugin):
diff --git a/pyomo/checker/runner.py b/pyomo/checker/runner.py
index 97ce4758465..08ad9288a4d 100644
--- a/pyomo/checker/runner.py
+++ b/pyomo/checker/runner.py
@@ -10,7 +10,8 @@
import ast
-from pyomo.checker.checker import *
+from pyomo.common.plugin import ExtensionPoint
+from pyomo.checker.checker import IModelChecker
from pyomo.checker.script import ModelScript
diff --git a/pyomo/checker/tests/examples/model/ArrayValue_nomodel.py b/pyomo/checker/tests/examples/model/ArrayValue_nomodel.py
index 3f223d78b7e..7add85414fe 100644
--- a/pyomo/checker/tests/examples/model/ArrayValue_nomodel.py
+++ b/pyomo/checker/tests/examples/model/ArrayValue_nomodel.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import Var
class Foo:
pass
diff --git a/pyomo/checker/tests/examples/model/ArrayValue_varonly.py b/pyomo/checker/tests/examples/model/ArrayValue_varonly.py
index 31ff0ff5cdd..b8bff298df6 100644
--- a/pyomo/checker/tests/examples/model/ArrayValue_varonly.py
+++ b/pyomo/checker/tests/examples/model/ArrayValue_varonly.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, NonNegativeReals
model = AbstractModel()
model.w = Var(within=NonNegativeReals)
diff --git a/pyomo/checker/tests/examples/model/ArrayValue_wrong.py b/pyomo/checker/tests/examples/model/ArrayValue_wrong.py
index 8b3099759d3..764cf553d67 100644
--- a/pyomo/checker/tests/examples/model/ArrayValue_wrong.py
+++ b/pyomo/checker/tests/examples/model/ArrayValue_wrong.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, RangeSet
model = AbstractModel()
model.y = Var([10])
diff --git a/pyomo/checker/tests/examples/model/Imports_wrong.py b/pyomo/checker/tests/examples/model/Imports_wrong.py
index 10366125b20..1baa986d60e 100644
--- a/pyomo/checker/tests/examples/model/Imports_wrong.py
+++ b/pyomo/checker/tests/examples/model/Imports_wrong.py
@@ -8,4 +8,3 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from os import *
diff --git a/pyomo/checker/tests/examples/model/ModelAccess_global.py b/pyomo/checker/tests/examples/model/ModelAccess_global.py
index 0f28c3a1992..7d45d172d3e 100644
--- a/pyomo/checker/tests/examples/model/ModelAccess_global.py
+++ b/pyomo/checker/tests/examples/model/ModelAccess_global.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Constraint
model = ConcreteModel()
model.X = Var()
diff --git a/pyomo/checker/tests/examples/model/ModelAccess_global2.py b/pyomo/checker/tests/examples/model/ModelAccess_global2.py
index 24398f14d2c..6f25e2b730a 100644
--- a/pyomo/checker/tests/examples/model/ModelAccess_global2.py
+++ b/pyomo/checker/tests/examples/model/ModelAccess_global2.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Constraint
model = ConcreteModel()
model.X = Var()
diff --git a/pyomo/checker/tests/examples/model/ModelArgument_firstarg.py b/pyomo/checker/tests/examples/model/ModelArgument_firstarg.py
index 80e9ba25cab..1a9bcc91b02 100644
--- a/pyomo/checker/tests/examples/model/ModelArgument_firstarg.py
+++ b/pyomo/checker/tests/examples/model/ModelArgument_firstarg.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, RangeSet, Var, Constraint
model = ConcreteModel()
model.S = RangeSet(10)
diff --git a/pyomo/checker/tests/examples/model/ModelArgument_lastarg.py b/pyomo/checker/tests/examples/model/ModelArgument_lastarg.py
index 22b5bc93ab3..66394ea813f 100644
--- a/pyomo/checker/tests/examples/model/ModelArgument_lastarg.py
+++ b/pyomo/checker/tests/examples/model/ModelArgument_lastarg.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, RangeSet, Var, Constraint
model = ConcreteModel()
model.S = RangeSet(10)
diff --git a/pyomo/checker/tests/examples/model/ModelArgument_norule.py b/pyomo/checker/tests/examples/model/ModelArgument_norule.py
index 5eb5f32677b..85c7c52df96 100644
--- a/pyomo/checker/tests/examples/model/ModelArgument_norule.py
+++ b/pyomo/checker/tests/examples/model/ModelArgument_norule.py
@@ -8,7 +8,6 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
def myAdd(a, b):
return a.val + b.val
diff --git a/pyomo/checker/tests/examples/model/ModelCreate_nocall.py b/pyomo/checker/tests/examples/model/ModelCreate_nocall.py
index 60c82d1a5db..eb1fccd0a6b 100644
--- a/pyomo/checker/tests/examples/model/ModelCreate_nocall.py
+++ b/pyomo/checker/tests/examples/model/ModelCreate_nocall.py
@@ -8,6 +8,6 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel
model = AbstractModel
diff --git a/pyomo/checker/tests/examples/model/ModelValue_globalif.py b/pyomo/checker/tests/examples/model/ModelValue_globalif.py
index 219452070b3..40636dc750d 100644
--- a/pyomo/checker/tests/examples/model/ModelValue_globalif.py
+++ b/pyomo/checker/tests/examples/model/ModelValue_globalif.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, value
model = AbstractModel()
model.X = Var()
diff --git a/pyomo/checker/tests/examples/model/ModelValue_globallistcomp.py b/pyomo/checker/tests/examples/model/ModelValue_globallistcomp.py
index 0506e224a31..52ec14ddefd 100644
--- a/pyomo/checker/tests/examples/model/ModelValue_globallistcomp.py
+++ b/pyomo/checker/tests/examples/model/ModelValue_globallistcomp.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, RangeSet, Var, value
model = AbstractModel()
model.S = RangeSet(10)
diff --git a/pyomo/checker/tests/examples/model/ModelValue_multiif.py b/pyomo/checker/tests/examples/model/ModelValue_multiif.py
index d3c798fa578..1c80615588a 100644
--- a/pyomo/checker/tests/examples/model/ModelValue_multiif.py
+++ b/pyomo/checker/tests/examples/model/ModelValue_multiif.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, Constraint, value
model = AbstractModel()
model.X = Var()
diff --git a/pyomo/checker/tests/examples/model/ModelValue_repeatif.py b/pyomo/checker/tests/examples/model/ModelValue_repeatif.py
index 2e1340f129a..6fc8e16d1ee 100644
--- a/pyomo/checker/tests/examples/model/ModelValue_repeatif.py
+++ b/pyomo/checker/tests/examples/model/ModelValue_repeatif.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, value
model = AbstractModel()
model.X = Var()
diff --git a/pyomo/checker/tests/examples/model/ModelValue_ruleif.py b/pyomo/checker/tests/examples/model/ModelValue_ruleif.py
index 3ec99c2171e..9e2a51eacf3 100644
--- a/pyomo/checker/tests/examples/model/ModelValue_ruleif.py
+++ b/pyomo/checker/tests/examples/model/ModelValue_ruleif.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, Constraint, value
model = AbstractModel()
model.X = Var()
diff --git a/pyomo/checker/tests/examples/model/ModelValue_rulelistcomp.py b/pyomo/checker/tests/examples/model/ModelValue_rulelistcomp.py
index febe1debaae..3810afee97c 100644
--- a/pyomo/checker/tests/examples/model/ModelValue_rulelistcomp.py
+++ b/pyomo/checker/tests/examples/model/ModelValue_rulelistcomp.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, RangeSet, Var, Constraint, value
model = AbstractModel()
model.S = RangeSet(10)
diff --git a/pyomo/checker/tests/examples/model/NoneReturn_wrong.py b/pyomo/checker/tests/examples/model/NoneReturn_wrong.py
index 7dfac33eb75..fcdb3de0b12 100644
--- a/pyomo/checker/tests/examples/model/NoneReturn_wrong.py
+++ b/pyomo/checker/tests/examples/model/NoneReturn_wrong.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, Constraint
model = AbstractModel()
model.X = Var()
diff --git a/pyomo/checker/tests/examples/py3k/XRange_1.py b/pyomo/checker/tests/examples/py3k/XRange_1.py
index 490cd315eef..318857a752f 100644
--- a/pyomo/checker/tests/examples/py3k/XRange_1.py
+++ b/pyomo/checker/tests/examples/py3k/XRange_1.py
@@ -8,4 +8,5 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
xrange(10)
diff --git a/pyomo/checker/tests/test_examples.py b/pyomo/checker/tests/test_examples.py
index 4f697ed45b9..f56177f7007 100644
--- a/pyomo/checker/tests/test_examples.py
+++ b/pyomo/checker/tests/test_examples.py
@@ -13,7 +13,7 @@
import pyutilib.th as unittest
-from pyomo.checker import *
+from pyomo.checker import ModelCheckRunner
from pyomo.checker.plugins.checker import PyomoModelChecker
from pyomo.common.dependencies import yaml, yaml_available, yaml_load_args
@@ -24,7 +24,6 @@
def createTestMethod(defs, package, checkerName, key):
def testMethod(obj, name):
import pyomo.environ
-
runner = ModelCheckRunner()
path = os.path.join(exdir, package, "{0}_{1}.py".format(checkerName, key))
runner.run(script = path, checkers = {package:[checkerName]})
diff --git a/pyomo/checker/tests/test_runner.py b/pyomo/checker/tests/test_runner.py
index b06ce3bc08d..33ecccbace0 100644
--- a/pyomo/checker/tests/test_runner.py
+++ b/pyomo/checker/tests/test_runner.py
@@ -12,8 +12,8 @@
import pyutilib.th as unittest
-from pyomo.checker import *
-from pyomo.checker.plugins.checker import *
+from pyomo.checker import ModelCheckRunner, ModelScript
+from pyomo.checker.plugins.checker import IModelChecker, ImmediateDataChecker, ImmediateTreeChecker, IterativeDataChecker, IterativeTreeChecker
currdir = os.path.dirname(os.path.abspath(__file__))
diff --git a/pyomo/checker/tests/test_script.py b/pyomo/checker/tests/test_script.py
index 601af2ff845..12681f07424 100644
--- a/pyomo/checker/tests/test_script.py
+++ b/pyomo/checker/tests/test_script.py
@@ -13,7 +13,7 @@
import pyutilib.th as unittest
-from pyomo.checker import *
+from pyomo.checker import ModelScript
currdir = os.path.dirname(os.path.abspath(__file__))
diff --git a/pyomo/common/dependencies.py b/pyomo/common/dependencies.py
index 37beece199f..1c32d324134 100644
--- a/pyomo/common/dependencies.py
+++ b/pyomo/common/dependencies.py
@@ -162,7 +162,14 @@ def __nonzero__(self):
return bool(self._a) or bool(self._b)
-def _check_version(module, min_version):
+def check_min_version(module, min_version):
+ if isinstance(module, DeferredImportModule):
+ indicator = module._indicator_flag
+ indicator.resolve()
+ if indicator._available:
+ module = indicator._module
+ else:
+ return False
try:
from packaging import version as _version
_parser = _version.parse
@@ -275,7 +282,8 @@ def attempt_import(name, error_message=None, only_catch_importerror=True,
module = importlib.import_module(name)
else:
module = importer()
- if minimum_version is None or _check_version(module, minimum_version):
+ if ( minimum_version is None
+ or check_min_version(module, minimum_version) ):
if callback is not None:
callback(module, True)
return module, True
diff --git a/pyomo/common/deprecation.py b/pyomo/common/deprecation.py
index 4ad44dc4a99..5a87756067d 100644
--- a/pyomo/common/deprecation.py
+++ b/pyomo/common/deprecation.py
@@ -76,7 +76,7 @@ def deprecated(msg=None, logger='pyomo.core', version=None, remove_in=None):
removed from the code.
"""
- if version is None: # or version in ('','tbd','TBD'):
+ if version is None: # or version in ('','tbd','TBD'):
raise DeveloperError("@deprecated missing initial version")
def wrap(func):
diff --git a/pyomo/common/download.py b/pyomo/common/download.py
index 12459114a1b..391d83c3593 100644
--- a/pyomo/common/download.py
+++ b/pyomo/common/download.py
@@ -333,7 +333,6 @@ def get_zip_archive(self, url, dirOffset=0):
% (self._fname,))
zip_file = zipfile.ZipFile(io.BytesIO(self.retrieve_url(url)))
# Simple sanity checks
- names = []
for info in zip_file.infolist():
f = info.filename
if f[0] in '\\/' or '..' in f:
diff --git a/pyomo/common/env.py b/pyomo/common/env.py
index 894f5a04d5b..b0b64e04680 100644
--- a/pyomo/common/env.py
+++ b/pyomo/common/env.py
@@ -42,12 +42,12 @@ def _attempt_ctypes_cdll(name):
return False
-def _load_dll(name, timeout=1):
+def _load_dll(name, timeout=10):
"""Load a DLL with a timeout
On some platforms and some DLLs (notably Windows GitHub Actions with
Python 3.5, 3.6, and 3.7 and the msvcr90.dll) we have observed
- behavior where the ctypes.CDLL() call hangs indefinitely. This uses
+ behavior where the ctypes.CDLL() call hangs indefinitely. This uses
multiprocessing to attempt the import in a subprocess (with a
timeout) and then only calls the import in the main process if the
subprocess succeeded.
@@ -55,9 +55,14 @@ def _load_dll(name, timeout=1):
Performance note: CtypesEnviron only ever attempts to load a DLL
once (the DLL reference is then held in a class attribute), and this
interface only spawns the subprocess if ctypes.util.find_library
- actually locates the target library. This will have a measurable
+ actually locates the target library. This will have a measurable
impact on Windows (where the DLLs exist), but not on other platforms.
+ The default timeout of 10 is arbitrary. For simple situations, 1
+ seems adequate. However, more complex examples have been observed
+ that needed timeout==5. Using a default of 10 is simply doubling
+ that observed case.
+
"""
if not ctypes.util.find_library(name):
return False, None
diff --git a/pyomo/common/tests/test_config.py b/pyomo/common/tests/test_config.py
index e21b6856d29..0def4dda08f 100644
--- a/pyomo/common/tests/test_config.py
+++ b/pyomo/common/tests/test_config.py
@@ -12,7 +12,7 @@
import pyutilib.th as unittest
from pyomo.common.config import (
- ConfigBlock, ConfigList, ConfigValue,
+ ConfigBlock, ConfigValue,
PositiveInt, NegativeInt, NonPositiveInt, NonNegativeInt,
PositiveFloat, NegativeFloat, NonPositiveFloat, NonNegativeFloat,
In, Path, PathList, ConfigEnum
diff --git a/pyomo/common/tests/test_dependencies.py b/pyomo/common/tests/test_dependencies.py
index 55e1d524c08..5d64042990e 100644
--- a/pyomo/common/tests/test_dependencies.py
+++ b/pyomo/common/tests/test_dependencies.py
@@ -17,12 +17,11 @@
from pyomo.common.dependencies import (
attempt_import, ModuleUnavailable, DeferredImportModule,
DeferredImportIndicator, DeferredImportError,
- _DeferredAnd, _DeferredOr
+ _DeferredAnd, _DeferredOr, check_min_version
)
import pyomo.common.tests.dep_mod as dep_mod
from pyomo.common.tests.dep_mod import (
- numpy, numpy_available,
bogus_nonexisting_module as bogus_nem,
bogus_nonexisting_module_available as has_bogus_nem,
)
@@ -79,6 +78,8 @@ def test_min_version(self):
defer_check=False)
self.assertTrue(avail)
self.assertTrue(inspect.ismodule(mod))
+ self.assertTrue(check_min_version(mod, '1.0'))
+ self.assertFalse(check_min_version(mod, '2.0'))
mod, avail = attempt_import('pyomo.common.tests.dep_mod',
minimum_version='2.0',
@@ -101,6 +102,16 @@ def test_min_version(self):
"\(version 1.5 does not satisfy the minimum version 2.0\)"):
mod.hello
+ # Verify check_min_version works with deferred imports
+
+ mod, avail = attempt_import('pyomo.common.tests.dep_mod',
+ defer_check=True)
+ self.assertTrue(check_min_version(mod, '1.0'))
+
+ mod, avail = attempt_import('pyomo.common.tests.dep_mod',
+ defer_check=True)
+ self.assertFalse(check_min_version(mod, '2.0'))
+
def test_and_or(self):
mod0, avail0 = attempt_import('pyutilib',
defer_check=True)
diff --git a/pyomo/common/tests/test_deprecated.py b/pyomo/common/tests/test_deprecated.py
index 83a4f8e1332..7a46f5ae592 100644
--- a/pyomo/common/tests/test_deprecated.py
+++ b/pyomo/common/tests/test_deprecated.py
@@ -43,7 +43,7 @@ def test_no_doc_string(self):
# Note: No docstring, else nose replaces the function name with
# the docstring in output.
#"""Test for deprecated function decorator."""
- @deprecated(version='')
+ @deprecated(version='test')
def foo(bar='yeah'):
logger.warning(bar)
@@ -79,7 +79,7 @@ def foo(bar='yeah'):
def test_with_doc_string(self):
- @deprecated(version='')
+ @deprecated(version='test')
def foo(bar='yeah'):
"""Show that I am a good person.
@@ -121,7 +121,7 @@ def foo(bar='yeah'):
def test_with_custom_message(self):
- @deprecated('This is a custom message, too.', version='')
+ @deprecated('This is a custom message, too.', version='test')
def foo(bar='yeah'):
"""Show that I am a good person.
@@ -163,7 +163,7 @@ def foo(bar='yeah'):
def test_with_custom_logger(self):
@deprecated('This is a custom message', logger='pyomo.common',
- version='')
+ version='test')
def foo(bar='yeah'):
"""Show that I am a good person.
@@ -205,7 +205,7 @@ def foo(bar='yeah'):
self.assertNotIn('DEPRECATED:', DEP_OUT.getvalue())
def test_with_class(self):
- @deprecated(version='')
+ @deprecated(version='test')
class foo(object):
def __init__(self):
logger.warning('yeah')
@@ -231,7 +231,7 @@ def test_with_method(self):
class foo(object):
def __init__(self):
pass
- @deprecated(version='')
+ @deprecated(version='test')
def bar(self):
logger.warning('yeah')
diff --git a/pyomo/common/tests/test_download.py b/pyomo/common/tests/test_download.py
index abdb275a93e..1d38ea103b1 100644
--- a/pyomo/common/tests/test_download.py
+++ b/pyomo/common/tests/test_download.py
@@ -8,7 +8,6 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import io
import os
import platform
import re
diff --git a/pyomo/common/tests/test_task.py b/pyomo/common/tests/test_task.py
index 3574746da64..a74e8b01435 100644
--- a/pyomo/common/tests/test_task.py
+++ b/pyomo/common/tests/test_task.py
@@ -9,9 +9,8 @@
# ___________________________________________________________________________
import pyutilib.th as unittest
-import pyutilib.misc
-from pyomo.common import *
+from pyomo.common import PyomoAPIData, pyomo_api, PyomoAPIFactory
from pyomo.common.log import LoggingIntercept
from six import StringIO
diff --git a/pyomo/contrib/benders/benders_cuts.py b/pyomo/contrib/benders/benders_cuts.py
index 205d10f65b5..91ea37f9bcc 100644
--- a/pyomo/contrib/benders/benders_cuts.py
+++ b/pyomo/contrib/benders/benders_cuts.py
@@ -1,5 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from pyomo.core.base.block import _BlockData, declare_custom_block
-import pyomo.environ as pe
+import pyomo.environ as pyo
from pyomo.solvers.plugins.solvers.persistent_solver import PersistentSolver
from pyomo.core.expr.visitor import identify_variables
from pyomo.common.collections import ComponentSet
@@ -103,35 +113,35 @@ def _setup_subproblem(b, master_vars, relax_subproblem_cons):
# first get the objective and turn it into a constraint
master_vars = ComponentSet(master_vars)
- objs = list(b.component_data_objects(pe.Objective, descend_into=False, active=True))
+ objs = list(b.component_data_objects(pyo.Objective, descend_into=False, active=True))
if len(objs) != 1:
raise ValueError('Subproblem must have exactly one objective')
orig_obj = objs[0]
orig_obj_expr = orig_obj.expr
b.del_component(orig_obj)
- b._z = pe.Var(bounds=(0, None))
- b.objective = pe.Objective(expr=b._z)
- b.dual = pe.Suffix(direction=pe.Suffix.IMPORT)
- b._eta = pe.Var()
+ b._z = pyo.Var(bounds=(0, None))
+ b.objective = pyo.Objective(expr=b._z)
+ b.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT)
+ b._eta = pyo.Var()
- b.aux_cons = pe.ConstraintList()
- for c in list(b.component_data_objects(pe.Constraint, descend_into=True, active=True, sort=True)):
+ b.aux_cons = pyo.ConstraintList()
+ for c in list(b.component_data_objects(pyo.Constraint, descend_into=True, active=True, sort=True)):
if not relax_subproblem_cons:
c_vars = ComponentSet(identify_variables(c.body, include_fixed=False))
if not _any_common_elements(master_vars, c_vars):
continue
if c.equality:
body = c.body
- rhs = pe.value(c.lower)
+ rhs = pyo.value(c.lower)
body -= rhs
b.aux_cons.add(body - b._z <= 0)
b.aux_cons.add(-body - b._z <= 0)
_del_con(c)
else:
body = c.body
- lower = pe.value(c.lower)
- upper = pe.value(c.upper)
+ lower = pyo.value(c.lower)
+ upper = pyo.value(c.upper)
if upper is not None:
body_upper = body - upper - b._z
b.aux_cons.add(body_upper <= 0)
@@ -142,7 +152,7 @@ def _setup_subproblem(b, master_vars, relax_subproblem_cons):
b.aux_cons.add(body_lower <= 0)
_del_con(c)
- b.obj_con = pe.Constraint(expr=orig_obj_expr - b._eta - b._z <= 0)
+ b.obj_con = pyo.Constraint(expr=orig_obj_expr - b._eta - b._z <= 0)
@declare_custom_block(name='BendersCutGenerator')
@@ -158,7 +168,7 @@ def __init__(self, component):
self.subproblems = list()
self.complicating_vars_maps = list()
self.master_vars = list()
- self.master_vars_indices = pe.ComponentMap()
+ self.master_vars_indices = pyo.ComponentMap()
self.master_etas = list()
self.cuts = None
self.subproblem_solvers = list()
@@ -190,12 +200,12 @@ def set_input(self, master_vars, tol=1e-6, comm = None):
self.comm = MPI.COMM_WORLD
self.num_subproblems_by_rank = np.zeros(self.comm.Get_size())
del self.cuts
- self.cuts = pe.ConstraintList()
+ self.cuts = pyo.ConstraintList()
self.subproblems = list()
self.master_etas = list()
self.complicating_vars_maps = list()
self.master_vars = list(master_vars)
- self.master_vars_indices = pe.ComponentMap()
+ self.master_vars_indices = pyo.ComponentMap()
for i, v in enumerate(self.master_vars):
self.master_vars_indices[v] = i
self.tol = tol
@@ -216,7 +226,7 @@ def add_subproblem(self, subproblem_fn, subproblem_fn_kwargs, master_eta, subpro
self._subproblem_ndx_map[len(self.subproblems) - 1] = self.global_num_subproblems() - 1
if isinstance(subproblem_solver, str):
- subproblem_solver = pe.SolverFactory(subproblem_solver)
+ subproblem_solver = pyo.SolverFactory(subproblem_solver)
self.subproblem_solvers.append(subproblem_solver)
if isinstance(subproblem_solver, PersistentSolver):
subproblem_solver.set_instance(subproblem)
@@ -233,15 +243,15 @@ def generate_cut(self):
master_eta = self.master_etas[local_subproblem_ndx]
coeff_ndx = global_subproblem_ndx * len(self.master_vars)
- subproblem.fix_complicating_vars = pe.ConstraintList()
- var_to_con_map = pe.ComponentMap()
+ subproblem.fix_complicating_vars = pyo.ConstraintList()
+ var_to_con_map = pyo.ComponentMap()
for master_var in self.master_vars:
if master_var in complicating_vars_map:
sub_var = complicating_vars_map[master_var]
sub_var.value = master_var.value
new_con = subproblem.fix_complicating_vars.add(sub_var - master_var.value == 0)
var_to_con_map[master_var] = new_con
- subproblem.fix_eta = pe.Constraint(expr=subproblem._eta - master_eta.value == 0)
+ subproblem.fix_eta = pyo.Constraint(expr=subproblem._eta - master_eta.value == 0)
subproblem._eta.value = master_eta.value
subproblem_solver = self.subproblem_solvers[local_subproblem_ndx]
@@ -254,22 +264,22 @@ def generate_cut(self):
subproblem_solver.add_constraint(c)
subproblem_solver.add_constraint(subproblem.fix_eta)
res = subproblem_solver.solve(tee=False, load_solutions=False, save_results=False)
- if res.solver.termination_condition != pe.TerminationCondition.optimal:
+ if res.solver.termination_condition != pyo.TerminationCondition.optimal:
raise RuntimeError('Unable to generate cut because subproblem failed to converge.')
subproblem_solver.load_vars()
subproblem_solver.load_duals()
else:
res = subproblem_solver.solve(subproblem, tee=False, load_solutions=False)
- if res.solver.termination_condition != pe.TerminationCondition.optimal:
+ if res.solver.termination_condition != pyo.TerminationCondition.optimal:
raise RuntimeError('Unable to generate cut because subproblem failed to converge.')
subproblem.solutions.load_from(res)
- constants[global_subproblem_ndx] = pe.value(subproblem._z)
- eta_coeffs[global_subproblem_ndx] = sign_convention * pe.value(subproblem.dual[subproblem.obj_con])
+ constants[global_subproblem_ndx] = pyo.value(subproblem._z)
+ eta_coeffs[global_subproblem_ndx] = sign_convention * pyo.value(subproblem.dual[subproblem.obj_con])
for master_var in self.master_vars:
if master_var in complicating_vars_map:
c = var_to_con_map[master_var]
- coefficients[coeff_ndx] = sign_convention * pe.value(subproblem.dual[c])
+ coefficients[coeff_ndx] = sign_convention * pyo.value(subproblem.dual[c])
coeff_ndx += 1
if isinstance(subproblem_solver, PersistentSolver):
diff --git a/pyomo/contrib/benders/examples/farmer.py b/pyomo/contrib/benders/examples/farmer.py
index 3fd402b2cae..925b66defd0 100644
--- a/pyomo/contrib/benders/examples/farmer.py
+++ b/pyomo/contrib/benders/examples/farmer.py
@@ -1,5 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from pyomo.contrib.benders.benders_cuts import BendersCutGenerator
-import pyomo.environ as pe
+import pyomo.environ as pyo
import time
from mpi4py import MPI
import sys
@@ -35,51 +45,51 @@ def __init__(self):
def create_master(farmer):
- m = pe.ConcreteModel()
+ m = pyo.ConcreteModel()
- m.crops = pe.Set(initialize=farmer.crops, ordered=True)
- m.scenarios = pe.Set(initialize=farmer.scenarios, ordered=True)
+ m.crops = pyo.Set(initialize=farmer.crops, ordered=True)
+ m.scenarios = pyo.Set(initialize=farmer.scenarios, ordered=True)
- m.devoted_acreage = pe.Var(m.crops, bounds=(0, farmer.total_acreage))
- m.eta = pe.Var(m.scenarios)
+ m.devoted_acreage = pyo.Var(m.crops, bounds=(0, farmer.total_acreage))
+ m.eta = pyo.Var(m.scenarios)
for s in m.scenarios:
m.eta[s].setlb(-432000 * farmer.scenario_probabilities[s])
- m.total_acreage_con = pe.Constraint(expr=sum(m.devoted_acreage.values()) <= farmer.total_acreage)
+ m.total_acreage_con = pyo.Constraint(expr=sum(m.devoted_acreage.values()) <= farmer.total_acreage)
- m.obj = pe.Objective(expr=sum(farmer.PlantingCostPerAcre[crop] * m.devoted_acreage[crop] for crop in m.crops) + sum(m.eta.values()))
+ m.obj = pyo.Objective(expr=sum(farmer.PlantingCostPerAcre[crop] * m.devoted_acreage[crop] for crop in m.crops) + sum(m.eta.values()))
return m
def create_subproblem(master, farmer, scenario):
- m = pe.ConcreteModel()
+ m = pyo.ConcreteModel()
- m.crops = pe.Set(initialize=farmer.crops, ordered=True)
+ m.crops = pyo.Set(initialize=farmer.crops, ordered=True)
- m.devoted_acreage = pe.Var(m.crops)
- m.QuantitySubQuotaSold = pe.Var(m.crops, bounds=(0.0, None))
- m.QuantitySuperQuotaSold = pe.Var(m.crops, bounds=(0.0, None))
- m.QuantityPurchased = pe.Var(m.crops, bounds=(0.0, None))
+ m.devoted_acreage = pyo.Var(m.crops)
+ m.QuantitySubQuotaSold = pyo.Var(m.crops, bounds=(0.0, None))
+ m.QuantitySuperQuotaSold = pyo.Var(m.crops, bounds=(0.0, None))
+ m.QuantityPurchased = pyo.Var(m.crops, bounds=(0.0, None))
def EnforceCattleFeedRequirement_rule(m, i):
return (farmer.CattleFeedRequirement[i] <= (farmer.crop_yield[scenario][i] * m.devoted_acreage[i]) +
m.QuantityPurchased[i] - m.QuantitySubQuotaSold[i] - m.QuantitySuperQuotaSold[i])
- m.EnforceCattleFeedRequirement = pe.Constraint(m.crops, rule=EnforceCattleFeedRequirement_rule)
+ m.EnforceCattleFeedRequirement = pyo.Constraint(m.crops, rule=EnforceCattleFeedRequirement_rule)
def LimitAmountSold_rule(m, i):
return m.QuantitySubQuotaSold[i] + m.QuantitySuperQuotaSold[i] - (farmer.crop_yield[scenario][i] * m.devoted_acreage[i]) <= 0.0
- m.LimitAmountSold = pe.Constraint(m.crops, rule=LimitAmountSold_rule)
+ m.LimitAmountSold = pyo.Constraint(m.crops, rule=LimitAmountSold_rule)
def EnforceQuotas_rule(m, i):
return (0.0, m.QuantitySubQuotaSold[i], farmer.PriceQuota[i])
- m.EnforceQuotas = pe.Constraint(m.crops, rule=EnforceQuotas_rule)
+ m.EnforceQuotas = pyo.Constraint(m.crops, rule=EnforceQuotas_rule)
obj_expr = sum(farmer.PurchasePrice[crop] * m.QuantityPurchased[crop] for crop in m.crops)
obj_expr -= sum(farmer.SubQuotaSellingPrice[crop] * m.QuantitySubQuotaSold[crop] for crop in m.crops)
obj_expr -= sum(farmer.SuperQuotaSellingPrice[crop] * m.QuantitySuperQuotaSold[crop] for crop in m.crops)
- m.obj = pe.Objective(expr=farmer.scenario_probabilities[scenario] * obj_expr)
+ m.obj = pyo.Objective(expr=farmer.scenario_probabilities[scenario] * obj_expr)
- complicating_vars_map = pe.ComponentMap()
+ complicating_vars_map = pyo.ComponentMap()
for crop in m.crops:
complicating_vars_map[master.devoted_acreage[crop]] = m.devoted_acreage[crop]
@@ -106,10 +116,14 @@ def main():
subproblem_fn_kwargs=subproblem_fn_kwargs,
master_eta=m.eta[s],
subproblem_solver='gurobi_persistent')
- opt = pe.SolverFactory('gurobi_persistent')
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
- print('{0:<15}{1:<15}{2:<15}{3:<15}{4:<15}'.format('# Cuts', 'Corn', 'Sugar Beets', 'Wheat', 'Time'))
+ print('{0:<15}{1:<15}{2:<15}{3:<15}{4:<15}'.format('# Cuts',
+ 'Corn',
+ 'Sugar Beets',
+ 'Wheat',
+ 'Time'))
for i in range(30):
res = opt.solve(tee=False, save_results=False)
cuts_added = m.benders.generate_cut()
diff --git a/pyomo/contrib/benders/examples/grothey_ex.py b/pyomo/contrib/benders/examples/grothey_ex.py
index 37aec2a6903..9628d2a02a0 100644
--- a/pyomo/contrib/benders/examples/grothey_ex.py
+++ b/pyomo/contrib/benders/examples/grothey_ex.py
@@ -1,25 +1,35 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from pyomo.contrib.benders.benders_cuts import BendersCutGenerator
-import pyomo.environ as pe
+import pyomo.environ as pyo
def create_master():
- m = pe.ConcreteModel()
- m.y = pe.Var(bounds=(1, None))
- m.eta = pe.Var(bounds=(-10, None))
- m.obj = pe.Objective(expr=m.y**2 + m.eta)
+ m = pyo.ConcreteModel()
+ m.y = pyo.Var(bounds=(1, None))
+ m.eta = pyo.Var(bounds=(-10, None))
+ m.obj = pyo.Objective(expr=m.y**2 + m.eta)
return m
def create_subproblem(master):
- m = pe.ConcreteModel()
- m.x1 = pe.Var()
- m.x2 = pe.Var()
- m.y = pe.Var()
- m.obj = pe.Objective(expr=-m.x2)
- m.c1 = pe.Constraint(expr=(m.x1 - 1)**2 + m.x2**2 <= pe.log(m.y))
- m.c2 = pe.Constraint(expr=(m.x1 + 1)**2 + m.x2**2 <= pe.log(m.y))
-
- complicating_vars_map = pe.ComponentMap()
+ m = pyo.ConcreteModel()
+ m.x1 = pyo.Var()
+ m.x2 = pyo.Var()
+ m.y = pyo.Var()
+ m.obj = pyo.Objective(expr=-m.x2)
+ m.c1 = pyo.Constraint(expr=(m.x1 - 1)**2 + m.x2**2 <= pyo.log(m.y))
+ m.c2 = pyo.Constraint(expr=(m.x1 + 1)**2 + m.x2**2 <= pyo.log(m.y))
+
+ complicating_vars_map = pyo.ComponentMap()
complicating_vars_map[master.y] = m.y
return m, complicating_vars_map
@@ -34,7 +44,7 @@ def main():
subproblem_fn_kwargs={'master': m},
master_eta=m.eta,
subproblem_solver='ipopt', )
- opt = pe.SolverFactory('gurobi_direct')
+ opt = pyo.SolverFactory('gurobi_direct')
for i in range(30):
res = opt.solve(m, tee=False)
diff --git a/pyomo/contrib/benders/tests/test_benders.py b/pyomo/contrib/benders/tests/test_benders.py
index c91b4e4f04b..437f5818966 100644
--- a/pyomo/contrib/benders/tests/test_benders.py
+++ b/pyomo/contrib/benders/tests/test_benders.py
@@ -1,6 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
from pyomo.contrib.benders.benders_cuts import BendersCutGenerator
-import pyomo.environ as pe
+import pyomo.environ as pyo
try:
import mpi4py
mpi4py_available = True
@@ -13,10 +23,10 @@
numpy_available = False
-ipopt_opt = pe.SolverFactory('ipopt')
+ipopt_opt = pyo.SolverFactory('ipopt')
ipopt_available = ipopt_opt.available(exception_flag=False)
-cplex_opt = pe.SolverFactory('cplex_direct')
+cplex_opt = pyo.SolverFactory('cplex_direct')
cplex_available = cplex_opt.available(exception_flag=False)
@@ -47,56 +57,56 @@ def __init__(self):
self.scenario_probabilities['AboveAverageScenario'] = 0.3333
def create_master(farmer):
- m = pe.ConcreteModel()
+ m = pyo.ConcreteModel()
- m.crops = pe.Set(initialize=farmer.crops, ordered=True)
- m.scenarios = pe.Set(initialize=farmer.scenarios, ordered=True)
+ m.crops = pyo.Set(initialize=farmer.crops, ordered=True)
+ m.scenarios = pyo.Set(initialize=farmer.scenarios, ordered=True)
- m.devoted_acreage = pe.Var(m.crops, bounds=(0, farmer.total_acreage))
- m.eta = pe.Var(m.scenarios)
+ m.devoted_acreage = pyo.Var(m.crops, bounds=(0, farmer.total_acreage))
+ m.eta = pyo.Var(m.scenarios)
for s in m.scenarios:
m.eta[s].setlb(-432000 * farmer.scenario_probabilities[s])
- m.total_acreage_con = pe.Constraint(expr=sum(m.devoted_acreage.values()) <= farmer.total_acreage)
+ m.total_acreage_con = pyo.Constraint(expr=sum(m.devoted_acreage.values()) <= farmer.total_acreage)
- m.obj = pe.Objective(
+ m.obj = pyo.Objective(
expr=sum(farmer.PlantingCostPerAcre[crop] * m.devoted_acreage[crop] for crop in m.crops) + sum(
m.eta.values()))
return m
def create_subproblem(master, farmer, scenario):
- m = pe.ConcreteModel()
+ m = pyo.ConcreteModel()
- m.crops = pe.Set(initialize=farmer.crops, ordered=True)
+ m.crops = pyo.Set(initialize=farmer.crops, ordered=True)
- m.devoted_acreage = pe.Var(m.crops)
- m.QuantitySubQuotaSold = pe.Var(m.crops, bounds=(0.0, None))
- m.QuantitySuperQuotaSold = pe.Var(m.crops, bounds=(0.0, None))
- m.QuantityPurchased = pe.Var(m.crops, bounds=(0.0, None))
+ m.devoted_acreage = pyo.Var(m.crops)
+ m.QuantitySubQuotaSold = pyo.Var(m.crops, bounds=(0.0, None))
+ m.QuantitySuperQuotaSold = pyo.Var(m.crops, bounds=(0.0, None))
+ m.QuantityPurchased = pyo.Var(m.crops, bounds=(0.0, None))
def EnforceCattleFeedRequirement_rule(m, i):
return (farmer.CattleFeedRequirement[i] <= (farmer.crop_yield[scenario][i] * m.devoted_acreage[i]) +
m.QuantityPurchased[i] - m.QuantitySubQuotaSold[i] - m.QuantitySuperQuotaSold[i])
- m.EnforceCattleFeedRequirement = pe.Constraint(m.crops, rule=EnforceCattleFeedRequirement_rule)
+ m.EnforceCattleFeedRequirement = pyo.Constraint(m.crops, rule=EnforceCattleFeedRequirement_rule)
def LimitAmountSold_rule(m, i):
return m.QuantitySubQuotaSold[i] + m.QuantitySuperQuotaSold[i] - (
farmer.crop_yield[scenario][i] * m.devoted_acreage[i]) <= 0.0
- m.LimitAmountSold = pe.Constraint(m.crops, rule=LimitAmountSold_rule)
+ m.LimitAmountSold = pyo.Constraint(m.crops, rule=LimitAmountSold_rule)
def EnforceQuotas_rule(m, i):
return (0.0, m.QuantitySubQuotaSold[i], farmer.PriceQuota[i])
- m.EnforceQuotas = pe.Constraint(m.crops, rule=EnforceQuotas_rule)
+ m.EnforceQuotas = pyo.Constraint(m.crops, rule=EnforceQuotas_rule)
obj_expr = sum(farmer.PurchasePrice[crop] * m.QuantityPurchased[crop] for crop in m.crops)
obj_expr -= sum(farmer.SubQuotaSellingPrice[crop] * m.QuantitySubQuotaSold[crop] for crop in m.crops)
obj_expr -= sum(farmer.SuperQuotaSellingPrice[crop] * m.QuantitySuperQuotaSold[crop] for crop in m.crops)
- m.obj = pe.Objective(expr=farmer.scenario_probabilities[scenario] * obj_expr)
+ m.obj = pyo.Objective(expr=farmer.scenario_probabilities[scenario] * obj_expr)
- complicating_vars_map = pe.ComponentMap()
+ complicating_vars_map = pyo.ComponentMap()
for crop in m.crops:
complicating_vars_map[master.devoted_acreage[crop]] = m.devoted_acreage[crop]
@@ -116,7 +126,7 @@ def EnforceQuotas_rule(m, i):
subproblem_fn_kwargs=subproblem_fn_kwargs,
master_eta=m.eta[s],
subproblem_solver='cplex_direct')
- opt = pe.SolverFactory('cplex_direct')
+ opt = pyo.SolverFactory('cplex_direct')
for i in range(30):
res = opt.solve(m, tee=False)
@@ -133,22 +143,22 @@ def EnforceQuotas_rule(m, i):
@unittest.skipIf(not ipopt_available, 'ipopt is not available.')
def test_grothey(self):
def create_master():
- m = pe.ConcreteModel()
- m.y = pe.Var(bounds=(1, None))
- m.eta = pe.Var(bounds=(-10, None))
- m.obj = pe.Objective(expr=m.y ** 2 + m.eta)
+ m = pyo.ConcreteModel()
+ m.y = pyo.Var(bounds=(1, None))
+ m.eta = pyo.Var(bounds=(-10, None))
+ m.obj = pyo.Objective(expr=m.y ** 2 + m.eta)
return m
def create_subproblem(master):
- m = pe.ConcreteModel()
- m.x1 = pe.Var()
- m.x2 = pe.Var()
- m.y = pe.Var()
- m.obj = pe.Objective(expr=-m.x2)
- m.c1 = pe.Constraint(expr=(m.x1 - 1) ** 2 + m.x2 ** 2 <= pe.log(m.y))
- m.c2 = pe.Constraint(expr=(m.x1 + 1) ** 2 + m.x2 ** 2 <= pe.log(m.y))
-
- complicating_vars_map = pe.ComponentMap()
+ m = pyo.ConcreteModel()
+ m.x1 = pyo.Var()
+ m.x2 = pyo.Var()
+ m.y = pyo.Var()
+ m.obj = pyo.Objective(expr=-m.x2)
+ m.c1 = pyo.Constraint(expr=(m.x1 - 1) ** 2 + m.x2 ** 2 <= pyo.log(m.y))
+ m.c2 = pyo.Constraint(expr=(m.x1 + 1) ** 2 + m.x2 ** 2 <= pyo.log(m.y))
+
+ complicating_vars_map = pyo.ComponentMap()
complicating_vars_map[master.y] = m.y
return m, complicating_vars_map
@@ -161,7 +171,7 @@ def create_subproblem(master):
subproblem_fn_kwargs={'master': m},
master_eta=m.eta,
subproblem_solver='ipopt', )
- opt = pe.SolverFactory('ipopt')
+ opt = pyo.SolverFactory('ipopt')
for i in range(30):
res = opt.solve(m, tee=False)
@@ -198,56 +208,56 @@ def __init__(self):
self.scenario_probabilities['Scenario4'] = 0.25
def create_master(farmer):
- m = pe.ConcreteModel()
+ m = pyo.ConcreteModel()
- m.crops = pe.Set(initialize=farmer.crops, ordered=True)
- m.scenarios = pe.Set(initialize=farmer.scenarios, ordered=True)
+ m.crops = pyo.Set(initialize=farmer.crops, ordered=True)
+ m.scenarios = pyo.Set(initialize=farmer.scenarios, ordered=True)
- m.devoted_acreage = pe.Var(m.crops, bounds=(0, farmer.total_acreage))
- m.eta = pe.Var(m.scenarios)
+ m.devoted_acreage = pyo.Var(m.crops, bounds=(0, farmer.total_acreage))
+ m.eta = pyo.Var(m.scenarios)
for s in m.scenarios:
m.eta[s].setlb(-432000 * farmer.scenario_probabilities[s])
- m.total_acreage_con = pe.Constraint(expr=sum(m.devoted_acreage.values()) <= farmer.total_acreage)
+ m.total_acreage_con = pyo.Constraint(expr=sum(m.devoted_acreage.values()) <= farmer.total_acreage)
- m.obj = pe.Objective(
+ m.obj = pyo.Objective(
expr=sum(farmer.PlantingCostPerAcre[crop] * m.devoted_acreage[crop] for crop in m.crops) + sum(
m.eta.values()))
return m
def create_subproblem(master, farmer, scenario):
- m = pe.ConcreteModel()
+ m = pyo.ConcreteModel()
- m.crops = pe.Set(initialize=farmer.crops, ordered=True)
+ m.crops = pyo.Set(initialize=farmer.crops, ordered=True)
- m.devoted_acreage = pe.Var(m.crops)
- m.QuantitySubQuotaSold = pe.Var(m.crops, bounds=(0.0, None))
- m.QuantitySuperQuotaSold = pe.Var(m.crops, bounds=(0.0, None))
- m.QuantityPurchased = pe.Var(m.crops, bounds=(0.0, None))
+ m.devoted_acreage = pyo.Var(m.crops)
+ m.QuantitySubQuotaSold = pyo.Var(m.crops, bounds=(0.0, None))
+ m.QuantitySuperQuotaSold = pyo.Var(m.crops, bounds=(0.0, None))
+ m.QuantityPurchased = pyo.Var(m.crops, bounds=(0.0, None))
def EnforceCattleFeedRequirement_rule(m, i):
return (farmer.CattleFeedRequirement[i] <= (farmer.crop_yield[scenario][i] * m.devoted_acreage[i]) +
m.QuantityPurchased[i] - m.QuantitySubQuotaSold[i] - m.QuantitySuperQuotaSold[i])
- m.EnforceCattleFeedRequirement = pe.Constraint(m.crops, rule=EnforceCattleFeedRequirement_rule)
+ m.EnforceCattleFeedRequirement = pyo.Constraint(m.crops, rule=EnforceCattleFeedRequirement_rule)
def LimitAmountSold_rule(m, i):
return m.QuantitySubQuotaSold[i] + m.QuantitySuperQuotaSold[i] - (
farmer.crop_yield[scenario][i] * m.devoted_acreage[i]) <= 0.0
- m.LimitAmountSold = pe.Constraint(m.crops, rule=LimitAmountSold_rule)
+ m.LimitAmountSold = pyo.Constraint(m.crops, rule=LimitAmountSold_rule)
def EnforceQuotas_rule(m, i):
return (0.0, m.QuantitySubQuotaSold[i], farmer.PriceQuota[i])
- m.EnforceQuotas = pe.Constraint(m.crops, rule=EnforceQuotas_rule)
+ m.EnforceQuotas = pyo.Constraint(m.crops, rule=EnforceQuotas_rule)
obj_expr = sum(farmer.PurchasePrice[crop] * m.QuantityPurchased[crop] for crop in m.crops)
obj_expr -= sum(farmer.SubQuotaSellingPrice[crop] * m.QuantitySubQuotaSold[crop] for crop in m.crops)
obj_expr -= sum(farmer.SuperQuotaSellingPrice[crop] * m.QuantitySuperQuotaSold[crop] for crop in m.crops)
- m.obj = pe.Objective(expr=farmer.scenario_probabilities[scenario] * obj_expr)
+ m.obj = pyo.Objective(expr=farmer.scenario_probabilities[scenario] * obj_expr)
- complicating_vars_map = pe.ComponentMap()
+ complicating_vars_map = pyo.ComponentMap()
for crop in m.crops:
complicating_vars_map[master.devoted_acreage[crop]] = m.devoted_acreage[crop]
@@ -267,7 +277,7 @@ def EnforceQuotas_rule(m, i):
subproblem_fn_kwargs=subproblem_fn_kwargs,
master_eta=m.eta[s],
subproblem_solver='cplex_direct')
- opt = pe.SolverFactory('cplex_direct')
+ opt = pyo.SolverFactory('cplex_direct')
for i in range(30):
res = opt.solve(m, tee=False)
diff --git a/pyomo/contrib/example/tests/test_example.py b/pyomo/contrib/example/tests/test_example.py
index 05b0f6b4dab..72614167c35 100644
--- a/pyomo/contrib/example/tests/test_example.py
+++ b/pyomo/contrib/example/tests/test_example.py
@@ -1,9 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
#
# Only run the tests in this package if the pyomo.contrib.example package
# has been successfully imported.
#
-import os
-import sys
+
import pyomo.contrib.example
import pyutilib.th as unittest
diff --git a/pyomo/contrib/fbbt/fbbt.py b/pyomo/contrib/fbbt/fbbt.py
index 30a60be11df..86f3c7622d7 100644
--- a/pyomo/contrib/fbbt/fbbt.py
+++ b/pyomo/contrib/fbbt/fbbt.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from pyomo.common.collections import ComponentMap, ComponentSet
import pyomo.core.expr.numeric_expr as numeric_expr
from pyomo.core.expr.visitor import ExpressionValueVisitor, identify_variables
diff --git a/pyomo/contrib/fbbt/interval.py b/pyomo/contrib/fbbt/interval.py
index df305cfde93..e9acd3b757b 100644
--- a/pyomo/contrib/fbbt/interval.py
+++ b/pyomo/contrib/fbbt/interval.py
@@ -1,5 +1,14 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import math
-import warnings
import logging
from pyomo.common.errors import DeveloperError, InfeasibleConstraintException, PyomoException
diff --git a/pyomo/contrib/fbbt/tests/test_fbbt.py b/pyomo/contrib/fbbt/tests/test_fbbt.py
index 8c96d26f10b..0f7fe1b140b 100644
--- a/pyomo/contrib/fbbt/tests/test_fbbt.py
+++ b/pyomo/contrib/fbbt/tests/test_fbbt.py
@@ -1,14 +1,25 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as pe
+import pyomo.environ as pyo
from pyomo.contrib.fbbt.fbbt import fbbt, compute_bounds_on_expr
-from pyomo.contrib.fbbt import interval
from pyomo.common.dependencies import numpy as np, numpy_available
from pyomo.common.errors import InfeasibleConstraintException
-from pyomo.core.expr.numeric_expr import ProductExpression, UnaryFunctionExpression
+from pyomo.core.expr.numeric_expr import (ProductExpression,
+ UnaryFunctionExpression)
import math
import logging
import io
+
class DummyExpr(ProductExpression):
pass
@@ -20,17 +31,17 @@ def test_add(self):
c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)]
for xl, xu in x_bounds:
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(xl, xu))
- m.y = pe.Var()
- m.p = pe.Param(mutable=True)
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(xl, xu))
+ m.y = pyo.Var()
+ m.p = pyo.Param(mutable=True)
m.p.value = 1
- m.c = pe.Constraint(expr=pe.inequality(body=m.x+m.y+(m.p+1), lower=cl, upper=cu))
+ m.c = pyo.Constraint(expr=pyo.inequality(body=m.x+m.y+(m.p+1), lower=cl, upper=cu))
new_bounds = fbbt(m)
- self.assertEqual(new_bounds[m.x], (pe.value(m.x.lb), pe.value(m.x.ub)))
- self.assertEqual(new_bounds[m.y], (pe.value(m.y.lb), pe.value(m.y.ub)))
- x = np.linspace(pe.value(m.x.lb), pe.value(m.x.ub), 100)
- z = np.linspace(pe.value(m.c.lower), pe.value(m.c.upper), 100)
+ self.assertEqual(new_bounds[m.x], (pyo.value(m.x.lb), pyo.value(m.x.ub)))
+ self.assertEqual(new_bounds[m.y], (pyo.value(m.y.lb), pyo.value(m.y.ub)))
+ x = np.linspace(pyo.value(m.x.lb), pyo.value(m.x.ub), 100)
+ z = np.linspace(pyo.value(m.c.lower), pyo.value(m.c.upper), 100)
if m.y.lb is None:
yl = -np.inf
else:
@@ -50,13 +61,13 @@ def test_sub1(self):
c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)]
for xl, xu in x_bounds:
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(xl, xu))
- m.y = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=m.x-m.y, lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(xl, xu))
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=m.x-m.y, lower=cl, upper=cu))
fbbt(m)
- x = np.linspace(pe.value(m.x.lb), pe.value(m.x.ub), 100)
- z = np.linspace(pe.value(m.c.lower), pe.value(m.c.upper), 100)
+ x = np.linspace(pyo.value(m.x.lb), pyo.value(m.x.ub), 100)
+ z = np.linspace(pyo.value(m.c.lower), pyo.value(m.c.upper), 100)
if m.y.lb is None:
yl = -np.inf
else:
@@ -76,13 +87,13 @@ def test_sub2(self):
c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)]
for xl, xu in x_bounds:
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(xl, xu))
- m.y = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=m.y-m.x, lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(xl, xu))
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=m.y-m.x, lower=cl, upper=cu))
fbbt(m)
- x = np.linspace(pe.value(m.x.lb), pe.value(m.x.ub), 100)
- z = np.linspace(pe.value(m.c.lower), pe.value(m.c.upper), 100)
+ x = np.linspace(pyo.value(m.x.lb), pyo.value(m.x.ub), 100)
+ z = np.linspace(pyo.value(m.c.lower), pyo.value(m.c.upper), 100)
if m.y.lb is None:
yl = -np.inf
else:
@@ -102,13 +113,13 @@ def test_mul(self):
c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)]
for xl, xu in x_bounds:
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(xl, xu))
- m.y = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=m.x*m.y, lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(xl, xu))
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=m.x*m.y, lower=cl, upper=cu))
fbbt(m)
- x = np.linspace(pe.value(m.x.lb) + 1e-6, pe.value(m.x.ub), 100, endpoint=False)
- z = np.linspace(pe.value(m.c.lower), pe.value(m.c.upper), 100)
+ x = np.linspace(pyo.value(m.x.lb) + 1e-6, pyo.value(m.x.ub), 100, endpoint=False)
+ z = np.linspace(pyo.value(m.c.lower), pyo.value(m.c.upper), 100)
if m.y.lb is None:
yl = -np.inf
else:
@@ -128,13 +139,13 @@ def test_div1(self):
c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)]
for xl, xu in x_bounds:
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(xl, xu))
- m.y = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=m.x/m.y, lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(xl, xu))
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=m.x/m.y, lower=cl, upper=cu))
fbbt(m)
- x = np.linspace(pe.value(m.x.lb), pe.value(m.x.ub), 100)
- z = np.linspace(pe.value(m.c.lower) + 1e-6, pe.value(m.c.upper), 100, endpoint=False)
+ x = np.linspace(pyo.value(m.x.lb), pyo.value(m.x.ub), 100)
+ z = np.linspace(pyo.value(m.c.lower) + 1e-6, pyo.value(m.c.upper), 100, endpoint=False)
if m.y.lb is None:
yl = -np.inf
else:
@@ -154,13 +165,13 @@ def test_div2(self):
c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)]
for xl, xu in x_bounds:
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(xl, xu))
- m.y = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=m.y/m.x, lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(xl, xu))
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=m.y/m.x, lower=cl, upper=cu))
fbbt(m)
- x = np.linspace(pe.value(m.x.lb), pe.value(m.x.ub), 100)
- z = np.linspace(pe.value(m.c.lower), pe.value(m.c.upper), 100)
+ x = np.linspace(pyo.value(m.x.lb), pyo.value(m.x.ub), 100)
+ z = np.linspace(pyo.value(m.c.lower), pyo.value(m.c.upper), 100)
if m.y.lb is None:
yl = -np.inf
else:
@@ -180,17 +191,17 @@ def test_pow1(self):
c_bounds = [(-2.5, 2.8), (0.5, 2.8), (-2.5, 0), (0, 2.8), (1, 2.8), (0.5, 1)]
for xl, xu in x_bounds:
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(xl, xu))
- m.y = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=m.x**m.y, lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(xl, xu))
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=m.x**m.y, lower=cl, upper=cu))
if xl > 0 and cu <= 0:
with self.assertRaises(InfeasibleConstraintException):
fbbt(m)
else:
fbbt(m)
- x = np.linspace(pe.value(m.x.lb) + 1e-6, pe.value(m.x.ub), 100, endpoint=False)
- z = np.linspace(pe.value(m.c.lower) + 1e-6, pe.value(m.c.upper), 100, endpoint=False)
+ x = np.linspace(pyo.value(m.x.lb) + 1e-6, pyo.value(m.x.ub), 100, endpoint=False)
+ z = np.linspace(pyo.value(m.c.lower) + 1e-6, pyo.value(m.c.upper), 100, endpoint=False)
if m.y.lb is None:
yl = -np.inf
else:
@@ -210,13 +221,13 @@ def test_pow2(self):
c_bounds = [(-2.5, 2.8), (0.5, 2.8), (0, 2.8), (1, 2.8), (0.5, 1)]
for xl, xu in x_bounds:
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(xl, xu))
- m.y = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=m.y**m.x, lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(xl, xu))
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=m.y**m.x, lower=cl, upper=cu))
fbbt(m)
- x = np.linspace(pe.value(m.x.lb) + 1e-6, pe.value(m.x.ub), 100, endpoint=False)
- z = np.linspace(pe.value(m.c.lower) + 1e-6, pe.value(m.c.upper), 100, endpoint=False)
+ x = np.linspace(pyo.value(m.x.lb) + 1e-6, pyo.value(m.x.ub), 100, endpoint=False)
+ z = np.linspace(pyo.value(m.c.lower) + 1e-6, pyo.value(m.c.upper), 100, endpoint=False)
if m.y.lb is None:
yl = -np.inf
else:
@@ -231,10 +242,10 @@ def test_pow2(self):
self.assertTrue(np.all(yu >= _y))
def test_x_sq(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.c = pe.Constraint(expr=m.x**2 == m.y)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=m.x**2 == m.y)
fbbt(m)
self.assertEqual(m.x.lb, None)
@@ -284,20 +295,20 @@ def test_x_sq(self):
self.assertEqual(m.x.ub, 0)
def test_pow5(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var(bounds=(0.5, 1))
- m.c = pe.Constraint(expr=2**m.x == m.y)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var(bounds=(0.5, 1))
+ m.c = pyo.Constraint(expr=2**m.x == m.y)
fbbt(m)
self.assertAlmostEqual(m.x.lb, -1)
self.assertAlmostEqual(m.x.ub, 0)
def test_x_pow_minus_2(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.c = pe.Constraint(expr=m.x**(-2) == m.y)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=m.x**(-2) == m.y)
fbbt(m)
self.assertEqual(m.x.lb, None)
@@ -336,10 +347,10 @@ def test_x_pow_minus_2(self):
self.assertAlmostEqual(m.x.ub, -1)
def test_x_cubed(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.c = pe.Constraint(expr=m.x**3 == m.y)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=m.x**3 == m.y)
fbbt(m)
self.assertEqual(m.x.lb, None)
@@ -380,10 +391,10 @@ def test_x_cubed(self):
self.assertAlmostEqual(m.x.ub, -1)
def test_x_pow_minus_3(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.c = pe.Constraint(expr=m.x**(-3) == m.y)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=m.x**(-3) == m.y)
fbbt(m)
self.assertEqual(m.x.lb, None)
@@ -424,12 +435,12 @@ def test_pow4(self):
exp_vals = [-3, -2.5, -2, -1.5, -1, -0.5, 0.5, 1, 1.5, 2, 2.5, 3]
for yl, yu in y_bounds:
for _exp_val in exp_vals:
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.y = pe.Var(bounds=(yl, yu))
- m.c = pe.Constraint(expr=m.x**_exp_val == m.y)
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.y = pyo.Var(bounds=(yl, yu))
+ m.c = pyo.Constraint(expr=m.x**_exp_val == m.y)
fbbt(m)
- y = np.linspace(pe.value(m.y.lb) + 1e-6, pe.value(m.y.ub), 100, endpoint=True)
+ y = np.linspace(pyo.value(m.y.lb) + 1e-6, pyo.value(m.y.ub), 100, endpoint=True)
if m.x.lb is None:
xl = -np.inf
else:
@@ -443,10 +454,10 @@ def test_pow4(self):
self.assertTrue(np.all(xu >= _x))
def test_sqrt(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.c = pe.Constraint(expr=pe.sqrt(m.x) == m.y)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.sqrt(m.x) == m.y)
fbbt(m)
self.assertEqual(m.x.lb, 0)
@@ -489,23 +500,23 @@ def test_sqrt(self):
def test_exp(self):
c_bounds = [(-2.5, 2.8), (0.5, 2.8), (0, 2.8), (1, 2.8), (0.5, 1)]
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=pe.exp(m.x), lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.exp(m.x), lower=cl, upper=cu))
fbbt(m)
- if pe.value(m.c.lower) <= 0:
+ if pyo.value(m.c.lower) <= 0:
_cl = 1e-6
else:
- _cl = pe.value(m.c.lower)
- z = np.linspace(_cl, pe.value(m.c.upper), 100)
+ _cl = pyo.value(m.c.lower)
+ z = np.linspace(_cl, pyo.value(m.c.upper), 100)
if m.x.lb is None:
xl = -np.inf
else:
- xl = pe.value(m.x.lb)
+ xl = pyo.value(m.x.lb)
if m.x.ub is None:
xu = np.inf
else:
- xu = pe.value(m.x.ub)
+ xu = pyo.value(m.x.ub)
x = np.log(z)
self.assertTrue(np.all(xl <= x))
self.assertTrue(np.all(xu >= x))
@@ -514,19 +525,19 @@ def test_exp(self):
def test_log(self):
c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)]
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=pe.log(m.x), lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.log(m.x), lower=cl, upper=cu))
fbbt(m)
- z = np.linspace(pe.value(m.c.lower), pe.value(m.c.upper), 100)
+ z = np.linspace(pyo.value(m.c.lower), pyo.value(m.c.upper), 100)
if m.x.lb is None:
xl = -np.inf
else:
- xl = pe.value(m.x.lb)
+ xl = pyo.value(m.x.lb)
if m.x.ub is None:
xu = np.inf
else:
- xu = pe.value(m.x.ub)
+ xu = pyo.value(m.x.ub)
x = np.exp(z)
self.assertTrue(np.all(xl <= x))
self.assertTrue(np.all(xu >= x))
@@ -535,19 +546,19 @@ def test_log(self):
def test_log10(self):
c_bounds = [(-2.5, 2.8), (-2.5, -0.5), (0.5, 2.8), (-2.5, 0), (0, 2.8), (-2.5, -1), (1, 2.8), (-1, -0.5), (0.5, 1)]
for cl, cu in c_bounds:
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=pe.log10(m.x), lower=cl, upper=cu))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.log10(m.x), lower=cl, upper=cu))
fbbt(m)
- z = np.linspace(pe.value(m.c.lower), pe.value(m.c.upper), 100)
+ z = np.linspace(pyo.value(m.c.lower), pyo.value(m.c.upper), 100)
if m.x.lb is None:
xl = -np.inf
else:
- xl = pe.value(m.x.lb)
+ xl = pyo.value(m.x.lb)
if m.x.ub is None:
xu = np.inf
else:
- xu = pe.value(m.x.ub)
+ xu = pyo.value(m.x.ub)
x = 10**z
print(xl, xu, cl, cu)
print(x)
@@ -555,149 +566,149 @@ def test_log10(self):
self.assertTrue(np.all(xu >= x))
def test_sin(self):
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(-math.pi/2, math.pi/2))
- m.c = pe.Constraint(expr=pe.inequality(body=pe.sin(m.x), lower=-0.5, upper=0.5))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(-math.pi/2, math.pi/2))
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.sin(m.x), lower=-0.5, upper=0.5))
fbbt(m.c)
- self.assertAlmostEqual(pe.value(m.x.lb), math.asin(-0.5))
- self.assertAlmostEqual(pe.value(m.x.ub), math.asin(0.5))
+ self.assertAlmostEqual(pyo.value(m.x.lb), math.asin(-0.5))
+ self.assertAlmostEqual(pyo.value(m.x.ub), math.asin(0.5))
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=pe.sin(m.x), lower=-0.5, upper=0.5))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.sin(m.x), lower=-0.5, upper=0.5))
fbbt(m.c)
self.assertEqual(m.x.lb, None)
self.assertEqual(m.x.ub, None)
def test_cos(self):
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(0, math.pi))
- m.c = pe.Constraint(expr=pe.inequality(body=pe.cos(m.x), lower=-0.5, upper=0.5))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(0, math.pi))
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.cos(m.x), lower=-0.5, upper=0.5))
fbbt(m)
- self.assertAlmostEqual(pe.value(m.x.lb), math.acos(0.5))
- self.assertAlmostEqual(pe.value(m.x.ub), math.acos(-0.5))
+ self.assertAlmostEqual(pyo.value(m.x.lb), math.acos(0.5))
+ self.assertAlmostEqual(pyo.value(m.x.ub), math.acos(-0.5))
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=pe.cos(m.x), lower=-0.5, upper=0.5))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.cos(m.x), lower=-0.5, upper=0.5))
fbbt(m)
self.assertEqual(m.x.lb, None)
self.assertEqual(m.x.ub, None)
def test_tan(self):
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(-math.pi/2, math.pi/2))
- m.c = pe.Constraint(expr=pe.inequality(body=pe.tan(m.x), lower=-0.5, upper=0.5))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(-math.pi/2, math.pi/2))
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.tan(m.x), lower=-0.5, upper=0.5))
fbbt(m)
- self.assertAlmostEqual(pe.value(m.x.lb), math.atan(-0.5))
- self.assertAlmostEqual(pe.value(m.x.ub), math.atan(0.5))
+ self.assertAlmostEqual(pyo.value(m.x.lb), math.atan(-0.5))
+ self.assertAlmostEqual(pyo.value(m.x.ub), math.atan(0.5))
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=pe.tan(m.x), lower=-0.5, upper=0.5))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.tan(m.x), lower=-0.5, upper=0.5))
fbbt(m)
self.assertEqual(m.x.lb, None)
self.assertEqual(m.x.ub, None)
def test_asin(self):
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=pe.asin(m.x), lower=-0.5, upper=0.5))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.asin(m.x), lower=-0.5, upper=0.5))
fbbt(m)
- self.assertAlmostEqual(pe.value(m.x.lb), math.sin(-0.5))
- self.assertAlmostEqual(pe.value(m.x.ub), math.sin(0.5))
+ self.assertAlmostEqual(pyo.value(m.x.lb), math.sin(-0.5))
+ self.assertAlmostEqual(pyo.value(m.x.ub), math.sin(0.5))
def test_acos(self):
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=pe.acos(m.x), lower=1, upper=2))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.acos(m.x), lower=1, upper=2))
fbbt(m)
- self.assertAlmostEqual(pe.value(m.x.lb), math.cos(2))
- self.assertAlmostEqual(pe.value(m.x.ub), math.cos(1))
+ self.assertAlmostEqual(pyo.value(m.x.lb), math.cos(2))
+ self.assertAlmostEqual(pyo.value(m.x.ub), math.cos(1))
def test_atan(self):
- m = pe.Block(concrete=True)
- m.x = pe.Var()
- m.c = pe.Constraint(expr=pe.inequality(body=pe.atan(m.x), lower=-0.5, upper=0.5))
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=pyo.inequality(body=pyo.atan(m.x), lower=-0.5, upper=0.5))
fbbt(m)
- self.assertAlmostEqual(pe.value(m.x.lb), math.tan(-0.5))
- self.assertAlmostEqual(pe.value(m.x.ub), math.tan(0.5))
+ self.assertAlmostEqual(pyo.value(m.x.lb), math.tan(-0.5))
+ self.assertAlmostEqual(pyo.value(m.x.ub), math.tan(0.5))
def test_multiple_constraints(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(-3, 3))
- m.y = pe.Var(bounds=(0, None))
- m.z = pe.Var()
- m.c = pe.ConstraintList()
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(-3, 3))
+ m.y = pyo.Var(bounds=(0, None))
+ m.z = pyo.Var()
+ m.c = pyo.ConstraintList()
m.c.add(m.x + m.y >= -1)
m.c.add(m.x + m.y <= -1)
m.c.add(m.y - m.x*m.z <= 2)
m.c.add(m.y - m.x*m.z >= -2)
m.c.add(m.x + m.z == 1)
fbbt(m)
- self.assertAlmostEqual(pe.value(m.x.lb), -1, 8)
- self.assertAlmostEqual(pe.value(m.x.ub), -1, 8)
- self.assertAlmostEqual(pe.value(m.y.lb), 0, 8)
- self.assertAlmostEqual(pe.value(m.y.ub), 0, 8)
- self.assertAlmostEqual(pe.value(m.z.lb), 2, 8)
- self.assertAlmostEqual(pe.value(m.z.ub), 2, 8)
+ self.assertAlmostEqual(pyo.value(m.x.lb), -1, 8)
+ self.assertAlmostEqual(pyo.value(m.x.ub), -1, 8)
+ self.assertAlmostEqual(pyo.value(m.y.lb), 0, 8)
+ self.assertAlmostEqual(pyo.value(m.y.ub), 0, 8)
+ self.assertAlmostEqual(pyo.value(m.z.lb), 2, 8)
+ self.assertAlmostEqual(pyo.value(m.z.ub), 2, 8)
def test_multiple_constraints2(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(-3, 3))
- m.y = pe.Var(bounds=(None, 0))
- m.z = pe.Var()
- m.c = pe.ConstraintList()
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(-3, 3))
+ m.y = pyo.Var(bounds=(None, 0))
+ m.z = pyo.Var()
+ m.c = pyo.ConstraintList()
m.c.add(-m.x - m.y >= -1)
m.c.add(-m.x - m.y <= -1)
m.c.add(-m.y - m.x*m.z >= -2)
m.c.add(-m.y - m.x*m.z <= 2)
m.c.add(-m.x - m.z == 1)
fbbt(m)
- self.assertAlmostEqual(pe.value(m.x.lb), 1, 8)
- self.assertAlmostEqual(pe.value(m.x.ub), 1, 8)
- self.assertAlmostEqual(pe.value(m.y.lb), 0, 8)
- self.assertAlmostEqual(pe.value(m.y.ub), 0, 8)
- self.assertAlmostEqual(pe.value(m.z.lb), -2, 8)
- self.assertAlmostEqual(pe.value(m.z.ub), -2, 8)
+ self.assertAlmostEqual(pyo.value(m.x.lb), 1, 8)
+ self.assertAlmostEqual(pyo.value(m.x.ub), 1, 8)
+ self.assertAlmostEqual(pyo.value(m.y.lb), 0, 8)
+ self.assertAlmostEqual(pyo.value(m.y.ub), 0, 8)
+ self.assertAlmostEqual(pyo.value(m.z.lb), -2, 8)
+ self.assertAlmostEqual(pyo.value(m.z.ub), -2, 8)
def test_binary(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(domain=pe.Binary)
- m.y = pe.Var(domain=pe.Binary)
- m.c = pe.Constraint(expr=m.x + m.y >= 1.5)
- fbbt(m)
- self.assertEqual(pe.value(m.x.lb), 1)
- self.assertEqual(pe.value(m.x.ub), 1)
- self.assertEqual(pe.value(m.y.lb), 1)
- self.assertEqual(pe.value(m.y.ub), 1)
-
- m = pe.ConcreteModel()
- m.x = pe.Var(domain=pe.Binary)
- m.y = pe.Var(domain=pe.Binary)
- m.c = pe.Constraint(expr=m.x + m.y <= 0.5)
- fbbt(m)
- self.assertEqual(pe.value(m.x.lb), 0)
- self.assertEqual(pe.value(m.x.ub), 0)
- self.assertEqual(pe.value(m.y.lb), 0)
- self.assertEqual(pe.value(m.y.ub), 0)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(domain=pyo.Binary)
+ m.y = pyo.Var(domain=pyo.Binary)
+ m.c = pyo.Constraint(expr=m.x + m.y >= 1.5)
+ fbbt(m)
+ self.assertEqual(pyo.value(m.x.lb), 1)
+ self.assertEqual(pyo.value(m.x.ub), 1)
+ self.assertEqual(pyo.value(m.y.lb), 1)
+ self.assertEqual(pyo.value(m.y.ub), 1)
+
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(domain=pyo.Binary)
+ m.y = pyo.Var(domain=pyo.Binary)
+ m.c = pyo.Constraint(expr=m.x + m.y <= 0.5)
+ fbbt(m)
+ self.assertEqual(pyo.value(m.x.lb), 0)
+ self.assertEqual(pyo.value(m.x.ub), 0)
+ self.assertEqual(pyo.value(m.y.lb), 0)
+ self.assertEqual(pyo.value(m.y.ub), 0)
def test_always_feasible(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(1,2))
- m.y = pe.Var(bounds=(1,2))
- m.c = pe.Constraint(expr=m.x + m.y >= 0)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(1,2))
+ m.y = pyo.Var(bounds=(1,2))
+ m.c = pyo.Constraint(expr=m.x + m.y >= 0)
fbbt(m)
self.assertTrue(m.c.active)
fbbt(m, deactivate_satisfied_constraints=True)
self.assertFalse(m.c.active)
def test_iteration_limit(self):
- m = pe.ConcreteModel()
- m.x_set = pe.Set(initialize=[0, 1, 2], ordered=True)
- m.c_set = pe.Set(initialize=[0, 1], ordered=True)
- m.x = pe.Var(m.x_set)
- m.c = pe.Constraint(m.c_set)
+ m = pyo.ConcreteModel()
+ m.x_set = pyo.Set(initialize=[0, 1, 2], ordered=True)
+ m.c_set = pyo.Set(initialize=[0, 1], ordered=True)
+ m.x = pyo.Var(m.x_set)
+ m.c = pyo.Constraint(m.c_set)
m.c[0] = m.x[0] == m.x[1]
m.c[1] = m.x[1] == m.x[2]
m.x[2].setlb(-1)
@@ -709,9 +720,9 @@ def test_iteration_limit(self):
self.assertEqual(m.x[0].ub, None)
def test_inf_bounds_on_expr(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(-1, 1))
- m.y = pe.Var()
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(-1, 1))
+ m.y = pyo.Var()
lb, ub = compute_bounds_on_expr(m.x + m.y)
self.assertEqual(lb, None)
self.assertEqual(ub, None)
@@ -719,11 +730,11 @@ def test_inf_bounds_on_expr(self):
@unittest.skip('This test passes locally, but not on travis or appveyor. I will add an issue.')
def test_skip_unknown_expression1(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(1,1))
- m.y = pe.Var()
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(1,1))
+ m.y = pyo.Var()
expr = DummyExpr([m.x, m.y])
- m.c = pe.Constraint(expr=expr == 1)
+ m.c = pyo.Constraint(expr=expr == 1)
logging_io = io.StringIO()
handler = logging.StreamHandler(stream=logging_io)
handler.setLevel(logging.WARNING)
@@ -731,10 +742,10 @@ def test_skip_unknown_expression1(self):
logger.addHandler(handler)
new_bounds = fbbt(m)
handler.flush()
- self.assertEqual(pe.value(m.x.lb), 1)
- self.assertEqual(pe.value(m.x.ub), 1)
- self.assertEqual(pe.value(m.y.lb), None)
- self.assertEqual(pe.value(m.y.ub), None)
+ self.assertEqual(pyo.value(m.x.lb), 1)
+ self.assertEqual(pyo.value(m.x.ub), 1)
+ self.assertEqual(pyo.value(m.y.lb), None)
+ self.assertEqual(pyo.value(m.y.ub), None)
a = "Unsupported expression type for FBBT"
b = logging_io.getvalue()
a = a.strip()
@@ -747,10 +758,10 @@ def test_skip_unknown_expression2(self):
def dummy_unary_expr(x):
return 0.5*x
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(0,4))
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(0,4))
expr = UnaryFunctionExpression((m.x,), name='dummy_unary_expr', fcn=dummy_unary_expr)
- m.c = pe.Constraint(expr=expr == 1)
+ m.c = pyo.Constraint(expr=expr == 1)
logging_io = io.StringIO()
handler = logging.StreamHandler(stream=logging_io)
handler.setLevel(logging.WARNING)
@@ -758,8 +769,8 @@ def dummy_unary_expr(x):
logger.addHandler(handler)
new_bounds = fbbt(m)
handler.flush()
- self.assertEqual(pe.value(m.x.lb), 0)
- self.assertEqual(pe.value(m.x.ub), 4)
+ self.assertEqual(pyo.value(m.x.lb), 0)
+ self.assertEqual(pyo.value(m.x.ub), 4)
a = "Unsupported expression type for FBBT"
b = logging_io.getvalue()
a = a.strip()
@@ -768,19 +779,19 @@ def dummy_unary_expr(x):
logger.removeHandler(handler)
def test_compute_expr_bounds(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(-1,1))
- m.y = pe.Var(bounds=(-1,1))
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(-1,1))
+ m.y = pyo.Var(bounds=(-1,1))
e = m.x + m.y
lb, ub = compute_bounds_on_expr(e)
self.assertAlmostEqual(lb, -2, 14)
self.assertAlmostEqual(ub, 2, 14)
def test_encountered_bugs1(self):
- m = pe.Block(concrete=True)
- m.x = pe.Var(bounds=(-0.035, -0.035))
- m.y = pe.Var(bounds=(-0.023, -0.023))
- m.c = pe.Constraint(expr=m.x**2 + m.y**2 <= 0.0256)
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(bounds=(-0.035, -0.035))
+ m.y = pyo.Var(bounds=(-0.023, -0.023))
+ m.c = pyo.Constraint(expr=m.x**2 + m.y**2 <= 0.0256)
fbbt(m.c)
self.assertEqual(m.x.lb, -0.035)
self.assertEqual(m.x.ub, -0.035)
@@ -788,10 +799,10 @@ def test_encountered_bugs1(self):
self.assertEqual(m.y.ub, -0.023)
def test_encountered_bugs2(self):
- m = pe.Block(concrete=True)
- m.x = pe.Var(within=pe.Integers)
- m.y = pe.Var(within=pe.Integers)
- m.c = pe.Constraint(expr=m.x + m.y == 1)
+ m = pyo.Block(concrete=True)
+ m.x = pyo.Var(within=pyo.Integers)
+ m.y = pyo.Var(within=pyo.Integers)
+ m.c = pyo.Constraint(expr=m.x + m.y == 1)
fbbt(m.c)
self.assertEqual(m.x.lb, None)
self.assertEqual(m.x.ub, None)
@@ -804,11 +815,11 @@ def test_encountered_bugs3(self):
yl = 0.03369608678342047
yu = 0.04009243987444148
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(xl, xu))
- m.y = pe.Var(bounds=(yl, yu))
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(xl, xu))
+ m.y = pyo.Var(bounds=(yl, yu))
- m.c = pe.Constraint(expr=m.x == pe.sin(m.y))
+ m.c = pyo.Constraint(expr=m.x == pyo.sin(m.y))
fbbt(m.c)
diff --git a/pyomo/contrib/fme/fourier_motzkin_elimination.py b/pyomo/contrib/fme/fourier_motzkin_elimination.py
index 005e01be084..a8fa6dc7c2a 100644
--- a/pyomo/contrib/fme/fourier_motzkin_elimination.py
+++ b/pyomo/contrib/fme/fourier_motzkin_elimination.py
@@ -12,11 +12,8 @@
Expression, Objective, SortComponents, value,
ConstraintList)
from pyomo.core.base import TransformationFactory, _VarData
-from pyomo.core.base.block import _BlockData
-from pyomo.core.base.param import _ParamData
-from pyomo.core.base.constraint import _ConstraintData
from pyomo.core.plugins.transform.hierarchy import Transformation
-from pyomo.common.config import ConfigBlock, ConfigValue
+from pyomo.common.config import ConfigBlock, ConfigValue, NonNegativeFloat
from pyomo.common.modeling import unique_component_name
from pyomo.repn.standard_repn import generate_standard_repn
from pyomo.common.collections import ComponentMap, ComponentSet
@@ -25,9 +22,9 @@
import logging
from six import iteritems
-import inspect
-logger = logging.getLogger('pyomo.contrib.fourier_motzkin_elimination')
+logger = logging.getLogger('pyomo.contrib.fme')
+NAME_BUFFER = {}
def _check_var_bounds_filter(constraint):
"""Check if the constraint is already implied by the variable bounds"""
@@ -67,6 +64,17 @@ def vars_to_eliminate_list(x):
"Expected Var or list of Vars."
"\n\tRecieved %s" % type(x))
+def gcd(a,b):
+ while b != 0:
+ a, b = b, a % b
+ return abs(a)
+
+def lcm(ints):
+ a = ints[0]
+ for b in ints[1:]:
+ a = abs(a*b) // gcd(a,b)
+ return a
+
@TransformationFactory.register('contrib.fourier_motzkin_elimination',
doc="Project out specified (continuous) "
"variables from a linear model.")
@@ -74,13 +82,13 @@ class Fourier_Motzkin_Elimination_Transformation(Transformation):
"""Project out specified variables from a linear model.
This transformation requires the following keyword argument:
- vars_to_eliminate: A user-specified list of continuous variables to
+ vars_to_eliminate: A user-specified list of continuous variables to
project out of the model
The transformation will deactivate the original constraints of the model
- and create a new block named "_pyomo_contrib_fme_transformation" with the
- projected constraints. Note that this transformation will flatten the
- structure of the original model since there is no obvious mapping between
+ and create a new block named "_pyomo_contrib_fme_transformation" with the
+ projected constraints. Note that this transformation will flatten the
+ structure of the original model since there is no obvious mapping between
the original model and the transformed one.
"""
@@ -90,10 +98,10 @@ class Fourier_Motzkin_Elimination_Transformation(Transformation):
default=None,
domain=vars_to_eliminate_list,
description="Continuous variable or list of continuous variables to "
- "project out of the model",
+ "project out of the model",
doc="""
This specifies the list of variables to project out of the model.
- Note that these variables must all be continuous and the model must be
+ Note that these variables must all be continuous and the model must be
linear."""
))
CONFIG.declare('constraint_filtering_callback', ConfigValue(
@@ -105,26 +113,98 @@ class Fourier_Motzkin_Elimination_Transformation(Transformation):
Specify None in order for no constraint filtering to occur during the
transformation.
- Specify a function that accepts a constraint (represented in the >=
+ Specify a function that accepts a constraint (represented in the >=
dictionary form used in this transformation) and returns a Boolean
indicating whether or not to add it to the model.
"""
))
+ CONFIG.declare('do_integer_arithmetic', ConfigValue(
+ default=False,
+ domain=bool,
+ description="A Boolean flag to decide whether Fourier-Motzkin "
+ "elimination will be performed with only integer arithmetic.",
+ doc="""
+ If True, only integer arithmetic will be performed during Fourier-
+ Motzkin elimination. This should result in no numerical error.
+ If True and there is non-integer data in the constraints being
+ projected, an error will be raised.
+
+ If False, the algorithm will not check whether data is integer, and will
+ perform division operations. Use this setting when not all data is
+ integer, or when you are willing to sacrifice some numeric accuracy.
+ """
+ ))
+ CONFIG.declare('verbose', ConfigValue(
+ default=False,
+ domain=bool,
+ description="A Boolean flag to enable verbose output.",
+ doc="""
+ If True, logs the steps of the projection.
+ """
+ ))
+ CONFIG.declare('zero_tolerance', ConfigValue(
+ default=0,
+ domain=NonNegativeFloat,
+ description="Absolute tolerance at which a float will be considered 0.",
+ doc="""
+ Whenever fourier-motzkin elimination is used with non-integer data,
+ there is a chance of numeric trouble, the most obvious of which is
+ that 'eliminated' variables will remain in the constraints with very
+ small coefficients. Set this tolerance so that floating points smaller
+ than this will be treated as 0 (and reported that way in the final
+ constraints).
+ """
+ ))
+ CONFIG.declare('integer_tolerance', ConfigValue(
+ default=0,
+ domain=NonNegativeFloat,
+ description="Absolute tolerance at which a float will be considered "
+ "(and cast to) an integer, when do_integer_arithmetic is True",
+ doc="""
+ Tolerance at which a number x will be considered an integer, when we
+ are performing fourier-motzkin elimination with only integer_arithmetic.
+ That is, x will be cast to an integer if
+ abs(int(x) - x) <= integer_tolerance.
+ """
+ ))
def __init__(self):
"""Initialize transformation object"""
super(Fourier_Motzkin_Elimination_Transformation, self).__init__()
-
+
def _apply_to(self, instance, **kwds):
- config = self.CONFIG(kwds.pop('options', {}))
- config.set_value(kwds)
+ log_level = logger.getEffectiveLevel()
+ try:
+ assert not NAME_BUFFER
+ config = self.CONFIG(kwds.pop('options', {}))
+ config.set_value(kwds)
+ # lower logging values emit more
+ if config.verbose and log_level > logging.INFO:
+ logger.setLevel(logging.INFO)
+ self.verbose = True
+ # if the user used the logger to ask for info level messages
+ elif log_level <= logging.INFO:
+ self.verbose = True
+ else:
+ self.verbose = False
+ self._apply_to_impl(instance, config)
+ finally:
+ # clear the global name buffer
+ NAME_BUFFER.clear()
+ # restore logging level
+ logger.setLevel(log_level)
+
+ def _apply_to_impl(self, instance, config):
vars_to_eliminate = config.vars_to_eliminate
self.constraint_filter = config.constraint_filtering_callback
+ self.do_integer_arithmetic = config.do_integer_arithmetic
+ self.integer_tolerance = config.integer_tolerance
+ self.zero_tolerance = config.zero_tolerance
if vars_to_eliminate is None:
raise RuntimeError("The Fourier-Motzkin Elimination transformation "
"requires the argument vars_to_eliminate, a "
"list of Vars to be projected out of the model.")
-
+
# make transformation block
transBlockName = unique_component_name(
instance,
@@ -138,7 +218,7 @@ def _apply_to(self, instance, **kwds):
# NOTE that we are ignoring deactivated constraints
constraints = []
ctypes_not_to_transform = set((Block, Param, Objective, Set, SetOf,
- Expression, Suffix))
+ Expression, Suffix, Var))
for obj in instance.component_data_objects(
descend_into=Block,
sort=SortComponents.deterministic,
@@ -149,30 +229,27 @@ def _apply_to(self, instance, **kwds):
cons_list = self._process_constraint(obj)
constraints.extend(cons_list)
obj.deactivate() # the truth will be on our transformation block
- elif obj.ctype is Var:
- # variable bounds are constraints, but we only need them if this
- # is a variable we are projecting out
- if obj not in vars_to_eliminate:
- continue
- if obj.lb is not None:
- constraints.append({'body': generate_standard_repn(obj),
- 'lower': value(obj.lb),
- 'map': ComponentMap([(obj, 1)])})
- if obj.ub is not None:
- constraints.append({'body': generate_standard_repn(-obj),
- 'lower': -value(obj.ub),
- 'map': ComponentMap([(obj, -1)])})
else:
raise RuntimeError(
"Found active component %s of type %s. The "
"Fourier-Motzkin Elimination transformation can only "
"handle purely algebraic models. That is, only "
"Sets, Params, Vars, Constraints, Expressions, Blocks, "
- "and Objectives may be active on the model." % (obj.name,
+ "and Objectives may be active on the model." % (obj.name,
obj.ctype))
- new_constraints = self._fourier_motzkin_elimination(constraints,
- vars_to_eliminate)
+ for obj in vars_to_eliminate:
+ if obj.lb is not None:
+ constraints.append({'body': generate_standard_repn(obj),
+ 'lower': value(obj.lb),
+ 'map': ComponentMap([(obj, 1)])})
+ if obj.ub is not None:
+ constraints.append({'body': generate_standard_repn(-obj),
+ 'lower': -value(obj.ub),
+ 'map': ComponentMap([(obj, -1)])})
+
+ new_constraints = self._fourier_motzkin_elimination( constraints,
+ vars_to_eliminate)
# put the new constraints on the transformation block
for cons in new_constraints:
@@ -182,18 +259,14 @@ def _apply_to(self, instance, **kwds):
except:
logger.error("Problem calling constraint filter callback "
"on constraint with right-hand side %s and "
- "body:\n%s" % (cons['lower'], cons['body']))
+ "body:\n%s" % (cons['lower'],
+ cons['body'].to_expression()))
raise
if not keep:
continue
- body = cons['body']
- lhs = sum(coef*var for (coef, var) in zip(body.linear_coefs,
- body.linear_vars)) + \
- sum(coef*v1*v2 for (coef, (v1, v2)) in zip(body.quadratic_coefs,
- body.quadratic_vars))
- if body.nonlinear_expr is not None:
- lhs += body.nonlinear_expr
+ lhs = cons['body'].to_expression(sort=True)
lower = cons['lower']
+ assert type(lower) is int or type(lower) is float
if type(lhs >= lower) is bool:
if lhs >= lower:
continue
@@ -210,8 +283,8 @@ def _process_constraint(self, constraint):
representing only >= constraints. That is, if the constraint has both an
ub and a lb, it is transformed into two constraints. Otherwise it is
flipped if it is <=. Each dictionary contains the keys 'lower',
- and 'body' where, after the process, 'lower' will be a constant, and
- 'body' will be the standard repn of the body. (The constant will be
+ and 'body' where, after the process, 'lower' will be a constant, and
+ 'body' will be the standard repn of the body. (The constant will be
moved to the RHS and we know that the upper bound is None after this).
"""
body = constraint.body
@@ -242,7 +315,7 @@ def _process_constraint(self, constraint):
return constraints_to_add
def _move_constant_and_add_map(self, cons_dict):
- """Takes constraint in dicionary form already in >= form,
+ """Takes constraint in dicionary form already in >= form,
and moves the constant to the RHS
"""
body = cons_dict['body']
@@ -255,25 +328,26 @@ def _move_constant_and_add_map(self, cons_dict):
# time searches later. Note also that we will take the value of the
# coeficient here so that we never have to worry about it again during
# the transformation.
- cons_dict['map'] = ComponentMap(zip(body.linear_vars,
+ cons_dict['map'] = ComponentMap(zip(body.linear_vars,
[value(coef) for coef in
body.linear_coefs]))
def _fourier_motzkin_elimination(self, constraints, vars_to_eliminate):
- """Performs FME on the constraint list in the argument
- (which is assumed to be all >= constraints and stored in the
- dictionary representation), projecting out each of the variables in
+ """Performs FME on the constraint list in the argument
+ (which is assumed to be all >= constraints and stored in the
+ dictionary representation), projecting out each of the variables in
vars_to_eliminate"""
# We only need to eliminate variables that actually appear in
# this set of constraints... Revise our list.
vars_that_appear = []
+ vars_that_appear_set = ComponentSet()
for cons in constraints:
std_repn = cons['body']
if not std_repn.is_linear():
# as long as none of vars_that_appear are in the nonlinear part,
# we are actually okay.
- nonlinear_vars = ComponentSet(v for two_tuple in
+ nonlinear_vars = ComponentSet(v for two_tuple in
std_repn.quadratic_vars for
v in two_tuple)
nonlinear_vars.update(v for v in std_repn.nonlinear_vars)
@@ -283,16 +357,23 @@ def _fourier_motzkin_elimination(self, constraints, vars_to_eliminate):
"constraint. The Fourier-Motzkin "
"Elimination transformation can only "
"be used to eliminate variables "
- "which only appear linearly." %
+ "which only appear linearly." %
var.name)
for var in std_repn.linear_vars:
if var in vars_to_eliminate:
- vars_that_appear.append(var)
+ if not var in vars_that_appear_set:
+ vars_that_appear.append(var)
+ vars_that_appear_set.add(var)
# we actually begin the recursion here
while vars_that_appear:
# first var we will project out
the_var = vars_that_appear.pop()
+ if self.verbose:
+ logger.info("Projecting out %s" %
+ the_var.getname(fully_qualified=True,
+ name_buffer=NAME_BUFFER))
+ logger.info("New constraints are:")
# we are 'reorganizing' the constraints, we sort based on the sign
# of the coefficient of the_var: This tells us whether we have
@@ -301,10 +382,15 @@ def _fourier_motzkin_elimination(self, constraints, vars_to_eliminate):
geq_list = []
waiting_list = []
+ coefs = []
for cons in constraints:
leaving_var_coef = cons['map'].get(the_var)
if leaving_var_coef is None or leaving_var_coef == 0:
waiting_list.append(cons)
+ if self.verbose:
+ logger.info("\t%s <= %s"
+ % (cons['lower'],
+ cons['body'].to_expression()))
continue
# we know the constraint is a >= constraint, using that
@@ -312,45 +398,145 @@ def _fourier_motzkin_elimination(self, constraints, vars_to_eliminate):
# NOTE: neither of the scalar multiplications below flip the
# constraint. So we are sure to have only geq constraints
# forever, which is exactly what we want.
- if leaving_var_coef < 0:
- leq_list.append(
- self._nonneg_scalar_multiply_linear_constraint(
- cons, -1.0/leaving_var_coef))
+ if not self.do_integer_arithmetic:
+ if leaving_var_coef < 0:
+ leq_list.append(
+ self._nonneg_scalar_multiply_linear_constraint(
+ cons, -1.0/leaving_var_coef))
+ else:
+ geq_list.append(
+ self._nonneg_scalar_multiply_linear_constraint(
+ cons, 1.0/leaving_var_coef))
else:
- geq_list.append(
- self._nonneg_scalar_multiply_linear_constraint(
- cons, 1.0/leaving_var_coef))
+ coefs.append(self._as_integer(
+ leaving_var_coef,
+ self._get_noninteger_coef_error_message,
+ (the_var.name, leaving_var_coef)
+ ))
+ if self.do_integer_arithmetic and len(coefs) > 0:
+ least_common_mult = lcm(coefs)
+ for cons in constraints:
+ leaving_var_coef = cons['map'].get(the_var)
+ if leaving_var_coef is None or leaving_var_coef == 0:
+ continue
+ to_lcm = least_common_mult // abs(int(leaving_var_coef))
+ if leaving_var_coef < 0:
+ leq_list.append(
+ self._nonneg_scalar_multiply_linear_constraint(
+ cons, to_lcm))
+ else:
+ geq_list.append(
+ self._nonneg_scalar_multiply_linear_constraint(
+ cons, to_lcm))
constraints = waiting_list
for leq in leq_list:
for geq in geq_list:
- constraints.append(self._add_linear_constraints(leq, geq))
+ constraints.append( self._add_linear_constraints( leq, geq))
+ if self.verbose:
+ cons = constraints[len(constraints)-1]
+ logger.info("\t%s <= %s" %
+ (cons['lower'],
+ cons['body'].to_expression()))
return constraints
+ def _get_noninteger_coef_error_message(self, varname, coef):
+ return ("The do_integer_arithmetic flag was "
+ "set to True, but the coefficient of "
+ "%s is non-integer within the specified "
+ "tolerance, with value %s. \n"
+ "Please set do_integer_arithmetic="
+ "False, increase integer_tolerance, "
+ "or make your data integer." % (varname, coef))
+
+ def _as_integer(self, x, error_message, error_args):
+ if abs(int(x) - x) <= self.integer_tolerance:
+ return int(round(x))
+ raise ValueError(error_message if error_args is None
+ else error_message(*error_args))
+
+ def _multiply(self, scalar, coef, error_message, error_args):
+ if self.do_integer_arithmetic:
+ assert type(scalar) is int
+ return scalar * self._as_integer(coef, error_message, error_args)
+ elif abs(scalar*coef) > self.zero_tolerance:
+ return scalar*coef
+ else:
+ return 0
+
+ def _add(self, a, b, error_message, error_args):
+ if self.do_integer_arithmetic:
+ return self._as_integer(a, error_message, error_args) \
+ + self._as_integer(b, error_message, error_args)
+ elif abs(a + b) > self.zero_tolerance:
+ return a + b
+ else:
+ return 0
+
+ def _nonneg_scalar_multiply_linear_constraint_error_msg(self, cons, coef):
+ return (
+ "The do_integer_arithmetic flag was set to True, but the "
+ "lower bound of %s is non-integer within the specified "
+ "tolerance, with value %s. \n"
+ "Please set do_integer_arithmetic=False, increase "
+ "integer_tolerance, or make your data integer." %
+ (cons['body'].to_expression() >= cons['lower'], coef)
+ )
+
def _nonneg_scalar_multiply_linear_constraint(self, cons, scalar):
"""Multiplies all coefficients and the RHS of a >= constraint by scalar.
- There is no logic for flipping the equality, so this is just the
+ There is no logic for flipping the equality, so this is just the
special case with a nonnegative scalar, which is all we need.
+
+ If self.do_integer_arithmetic is True, this assumes that scalar is an
+ int. It also will throw an error if any data is non-integer (within
+ tolerance)
"""
body = cons['body']
- body.linear_coefs = [scalar*coef for coef in body.linear_coefs]
+ new_coefs = []
+ for i, coef in enumerate(body.linear_coefs):
+ v = body.linear_vars[i]
+ new_coefs.append(self._multiply(
+ scalar, coef, self._get_noninteger_coef_error_message,
+ (v.name, coef)
+ ))
+ # update the map
+ cons['map'][v] = new_coefs[i]
+ body.linear_coefs = new_coefs
+
body.quadratic_coefs = [scalar*coef for coef in body.quadratic_coefs]
body.nonlinear_expr = scalar*body.nonlinear_expr if \
body.nonlinear_expr is not None else None
- # and update the map... (It isn't lovely that I am storing this in two
- # places...)
- for var, coef in cons['map'].items():
- cons['map'][var] = coef*scalar
# assume scalar >= 0 and constraint only has lower bound
- if cons['lower'] is not None:
- cons['lower'] *= scalar
-
+ lb = cons['lower']
+ if lb is not None:
+ cons['lower'] = self._multiply(
+ scalar, lb,
+ self._nonneg_scalar_multiply_linear_constraint_error_msg,
+ (cons, coef)
+ )
return cons
+ def _add_linear_constraints_error_msg(self, cons1, cons2):
+ return (
+ "The do_integer_arithmetic flag was set to True, but while "
+ "adding %s and %s, encountered a coefficient that is "
+ "non-integer within the specified tolerance\n"
+ "Please set do_integer_arithmetic=False, increase "
+ "integer_tolerance, or make your data integer." %
+ (cons1['body'].to_expression() >= cons1['lower'],
+ cons2['body'].to_expression() >= cons2['lower'])
+ )
+
def _add_linear_constraints(self, cons1, cons2):
- """Adds two >= constraints"""
+ """Adds two >= constraints
+
+ Because this is always called after
+ _nonneg_scalar_multiply_linear_constraint, though it is implemented
+ more generally.
+ """
ans = {'lower': None, 'body': None, 'map': ComponentMap()}
cons1_body = cons1['body']
cons2_body = cons2['body']
@@ -362,23 +548,28 @@ def _add_linear_constraints(self, cons1, cons2):
for v in cons2_body.linear_vars:
if v not in seen:
all_vars.append(v)
-
+
expr = 0
for var in all_vars:
- coef = cons1['map'].get(var, 0) + cons2['map'].get(var, 0)
+ coef = self._add(
+ cons1['map'].get(var, 0), cons2['map'].get(var, 0),
+ self._add_linear_constraints_error_msg, (cons1, cons2))
ans['map'][var] = coef
expr += coef*var
+
# deal with nonlinear stuff if there is any
for cons in [cons1_body, cons2_body]:
if cons.nonlinear_expr is not None:
expr += cons.nonlinear_expr
expr += sum(coef*v1*v2 for (coef, (v1, v2)) in
- zip(cons.quadratic_coefs, cons.quadratic_vars))
-
+ zip(cons.quadratic_coefs, cons.quadratic_vars))
+
ans['body'] = generate_standard_repn(expr)
# upper is None and lower exists, so this gets the constant
- ans['lower'] = cons1['lower'] + cons2['lower']
+ ans['lower'] = self._add(
+ cons1['lower'], cons2['lower'],
+ self._add_linear_constraints_error_msg, (cons1, cons2))
return ans
@@ -388,22 +579,22 @@ def post_process_fme_constraints(self, m, solver_factory, tolerance=0):
Parameters
----------------
- m: A model, already transformed with FME. Note that if constraints
- have been added, activated, or deactivated, we will check for
- redundancy against the whole active part of the model. If you call
- this straight after FME, you are only checking within the projected
+ m: A model, already transformed with FME. Note that if constraints
+ have been added, activated, or deactivated, we will check for
+ redundancy against the whole active part of the model. If you call
+ this straight after FME, you are only checking within the projected
constraints, but otherwise it is up to the user.
- solver_factory: A SolverFactory object (constructed with a solver
- which can solve the continuous relaxation of the
- active constraints on the model. That is, if you
- had nonlinear constraints unrelated to the variables
- being projected, you need to either deactivate them or
+ solver_factory: A SolverFactory object (constructed with a solver
+ which can solve the continuous relaxation of the
+ active constraints on the model. That is, if you
+ had nonlinear constraints unrelated to the variables
+ being projected, you need to either deactivate them or
provide a solver which will do the right thing.)
tolerance: Tolerance at which we decide a constraint is implied by the
- others. Default is 0, meaning we remove the constraint if
- the LP solve finds the constraint can be tight but not
+ others. Default is 0, meaning we remove the constraint if
+ the LP solve finds the constraint can be tight but not
violated. Setting this to a small positive value would
- remove constraints more conservatively. Setting it to a
+ remove constraints more conservatively. Setting it to a
negative value would result in a relaxed problem.
"""
# make sure m looks like what we expect
@@ -414,7 +605,7 @@ def post_process_fme_constraints(self, m, solver_factory, tolerance=0):
% m.name)
transBlock = m._pyomo_contrib_fme_transformation
constraints = transBlock.projected_constraints
-
+
# relax integrality so that we can do this with LP solves.
TransformationFactory('core.relax_integer_vars').apply_to(
m, transform_deactivated_blocks=True)
@@ -449,7 +640,7 @@ def post_process_fme_constraints(self, m, solver_factory, tolerance=0):
raise RuntimeError("Unsuccessful subproblem solve when checking"
"constraint %s.\n\t"
"Termination Condition: %s" %
- (constraints[i].name,
+ (constraints[i].name,
results.solver.termination_condition))
else:
obj_val = value(obj)
diff --git a/pyomo/contrib/fme/plugins.py b/pyomo/contrib/fme/plugins.py
index 73e6acc24ce..a992684a81a 100644
--- a/pyomo/contrib/fme/plugins.py
+++ b/pyomo/contrib/fme/plugins.py
@@ -1,2 +1,12 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
def load():
import pyomo.contrib.fme.fourier_motzkin_elimination
diff --git a/pyomo/contrib/fme/tests/test_fourier_motzkin_elimination.py b/pyomo/contrib/fme/tests/test_fourier_motzkin_elimination.py
index 61f7df8f734..a28563221f1 100644
--- a/pyomo/contrib/fme/tests/test_fourier_motzkin_elimination.py
+++ b/pyomo/contrib/fme/tests/test_fourier_motzkin_elimination.py
@@ -78,6 +78,7 @@ def test_no_vars_specified(self):
def check_projected_constraints(self, m, indices):
constraints = m._pyomo_contrib_fme_transformation.projected_constraints
+
# x - 0.01y <= 1
cons = constraints[indices[0]]
self.assertEqual(value(cons.lower), -1)
@@ -100,10 +101,10 @@ def check_projected_constraints(self, m, indices):
linear_vars = body.linear_vars
coefs = body.linear_coefs
self.assertEqual(len(linear_vars), 2)
- self.assertIs(linear_vars[0], m.y)
- self.assertEqual(coefs[0], -1)
- self.assertIs(linear_vars[1], m.u[1])
- self.assertEqual(coefs[1], -1000)
+ self.assertIs(linear_vars[0], m.u[1])
+ self.assertEqual(coefs[0], -1000)
+ self.assertIs(linear_vars[1], m.y)
+ self.assertEqual(coefs[1], -1)
# -x + 0.01y + 1 <= 1000*(1 - u_2)
cons = constraints[indices[2]]
@@ -113,12 +114,12 @@ def check_projected_constraints(self, m, indices):
linear_vars = body.linear_vars
coefs = body.linear_coefs
self.assertEqual(len(linear_vars), 3)
- self.assertIs(linear_vars[0], m.x)
- self.assertEqual(coefs[0], 1)
- self.assertIs(linear_vars[1], m.y)
- self.assertEqual(coefs[1], -0.01)
- self.assertIs(linear_vars[2], m.u[2])
- self.assertEqual(coefs[2], -1000)
+ self.assertIs(linear_vars[0], m.u[2])
+ self.assertEqual(coefs[0], -1000)
+ self.assertIs(linear_vars[1], m.x)
+ self.assertEqual(coefs[1], 1)
+ self.assertIs(linear_vars[2], m.y)
+ self.assertEqual(coefs[2], -0.01)
# u_2 + 100u_1 >= 1
cons = constraints[indices[3]]
@@ -258,8 +259,7 @@ def not_a_callback(cons):
raise RuntimeError("I don't know how to do my job.")
fme = TransformationFactory('contrib.fourier_motzkin_elimination')
log = StringIO()
- with LoggingIntercept(log, 'pyomo.contrib.fourier_motzkin_elimination',
- logging.ERROR):
+ with LoggingIntercept(log, 'pyomo.contrib.fme', logging.ERROR):
self.assertRaisesRegexp(
RuntimeError,
"I don't know how to do my job.",
@@ -276,8 +276,7 @@ def test_constraint_filtering_callback_not_callable_error(self):
m = self.makeModel()
fme = TransformationFactory('contrib.fourier_motzkin_elimination')
log = StringIO()
- with LoggingIntercept(log, 'pyomo.contrib.fourier_motzkin_elimination',
- logging.ERROR):
+ with LoggingIntercept(log, 'pyomo.contrib.fme', logging.ERROR):
self.assertRaisesRegexp(
TypeError,
"'int' object is not callable",
@@ -300,7 +299,7 @@ def test_combine_three_inequalities_and_flatten_blocks(self):
m.b.b2 = Block()
m.b.b2.c = Constraint(expr=m.y >= 4)
TransformationFactory('contrib.fourier_motzkin_elimination').apply_to(
- m, vars_to_eliminate=m.y)
+ m, vars_to_eliminate=m.y, do_integer_arithmetic=True)
constraints = m._pyomo_contrib_fme_transformation.projected_constraints
self.assertEqual(len(constraints), 2)
@@ -323,10 +322,10 @@ def check_hull_projected_constraints(self, m, constraints, indices):
self.assertEqual(body.constant, 0)
self.assertEqual(len(body.linear_vars), 2)
self.assertTrue(body.is_linear())
- self.assertIs(body.linear_vars[0], m.p[1])
- self.assertEqual(body.linear_coefs[0], 1)
- self.assertIs(body.linear_vars[1], m.on.indicator_var)
- self.assertEqual(body.linear_coefs[1], -1)
+ self.assertIs(body.linear_vars[0], m.on.indicator_var)
+ self.assertEqual(body.linear_coefs[0], -1)
+ self.assertIs(body.linear_vars[1], m.p[1])
+ self.assertEqual(body.linear_coefs[1], 1)
# p[1] <= 10*on.ind_var + 10*off.ind_var
cons = constraints[indices[1]]
@@ -336,9 +335,9 @@ def check_hull_projected_constraints(self, m, constraints, indices):
self.assertEqual(body.constant, 0)
self.assertEqual(len(body.linear_vars), 3)
self.assertTrue(body.is_linear())
- self.assertIs(body.linear_vars[0], m.on.indicator_var)
+ self.assertIs(body.linear_vars[0], m.off.indicator_var)
self.assertEqual(body.linear_coefs[0], 10)
- self.assertIs(body.linear_vars[1], m.off.indicator_var)
+ self.assertIs(body.linear_vars[1], m.on.indicator_var)
self.assertEqual(body.linear_coefs[1], 10)
self.assertIs(body.linear_vars[2], m.p[1])
self.assertEqual(body.linear_coefs[2], -1)
@@ -364,10 +363,10 @@ def check_hull_projected_constraints(self, m, constraints, indices):
self.assertEqual(body.constant, 0)
self.assertEqual(len(body.linear_vars), 2)
self.assertTrue(body.is_linear())
- self.assertIs(body.linear_vars[0], m.time1_disjuncts[0].indicator_var)
- self.assertEqual(body.linear_coefs[0], 10)
- self.assertIs(body.linear_vars[1], m.p[1])
- self.assertEqual(body.linear_coefs[1], -1)
+ self.assertIs(body.linear_vars[0], m.p[1])
+ self.assertEqual(body.linear_coefs[0], -1)
+ self.assertIs(body.linear_vars[1], m.time1_disjuncts[0].indicator_var)
+ self.assertEqual(body.linear_coefs[1], 10)
# p[2] - p[1] <= 3*on.ind_var + 2*startup.ind_var
cons = constraints[indices[4]]
@@ -377,14 +376,14 @@ def check_hull_projected_constraints(self, m, constraints, indices):
self.assertEqual(body.constant, 0)
self.assertEqual(len(body.linear_vars), 4)
self.assertTrue(body.is_linear())
- self.assertIs(body.linear_vars[3], m.p[2])
- self.assertEqual(body.linear_coefs[3], -1)
- self.assertIs(body.linear_vars[0], m.p[1])
- self.assertEqual(body.linear_coefs[0], 1)
- self.assertIs(body.linear_vars[1], m.on.indicator_var)
- self.assertEqual(body.linear_coefs[1], 3)
- self.assertIs(body.linear_vars[2], m.startup.indicator_var)
- self.assertEqual(body.linear_coefs[2], 2)
+ self.assertIs(body.linear_vars[0], m.on.indicator_var)
+ self.assertEqual(body.linear_coefs[0], 3)
+ self.assertIs(body.linear_vars[1], m.p[1])
+ self.assertEqual(body.linear_coefs[1], 1)
+ self.assertIs(body.linear_vars[2], m.p[2])
+ self.assertEqual(body.linear_coefs[2], -1)
+ self.assertIs(body.linear_vars[3], m.startup.indicator_var)
+ self.assertEqual(body.linear_coefs[3], 2)
# p[2] >= on.ind_var + startup.ind_var
cons = constraints[indices[5]]
@@ -394,11 +393,11 @@ def check_hull_projected_constraints(self, m, constraints, indices):
self.assertEqual(body.constant, 0)
self.assertEqual(len(body.linear_vars), 3)
self.assertTrue(body.is_linear())
- self.assertIs(body.linear_vars[0], m.p[2])
- self.assertEqual(body.linear_coefs[0], 1)
- self.assertIs(body.linear_vars[1], m.startup.indicator_var)
- self.assertEqual(body.linear_coefs[1], -1)
- self.assertIs(body.linear_vars[2], m.on.indicator_var)
+ self.assertIs(body.linear_vars[0], m.on.indicator_var)
+ self.assertEqual(body.linear_coefs[0], -1)
+ self.assertIs(body.linear_vars[1], m.p[2])
+ self.assertEqual(body.linear_coefs[1], 1)
+ self.assertIs(body.linear_vars[2], m.startup.indicator_var)
self.assertEqual(body.linear_coefs[2], -1)
# p[2] <= 10*on.ind_var + 2*startup.ind_var
@@ -411,10 +410,10 @@ def check_hull_projected_constraints(self, m, constraints, indices):
self.assertTrue(body.is_linear())
self.assertIs(body.linear_vars[0], m.on.indicator_var)
self.assertEqual(body.linear_coefs[0], 10)
- self.assertIs(body.linear_vars[1], m.startup.indicator_var)
- self.assertEqual(body.linear_coefs[1], 2)
- self.assertIs(body.linear_vars[2], m.p[2])
- self.assertEqual(body.linear_coefs[2], -1)
+ self.assertIs(body.linear_vars[1], m.p[2])
+ self.assertEqual(body.linear_coefs[1], -1)
+ self.assertIs(body.linear_vars[2], m.startup.indicator_var)
+ self.assertEqual(body.linear_coefs[2], 2)
# 1 <= time1_disjuncts[0].ind_var + time_1.disjuncts[1].ind_var
cons = constraints[indices[7]]
@@ -450,13 +449,13 @@ def check_hull_projected_constraints(self, m, constraints, indices):
self.assertEqual(body.constant, 0)
self.assertEqual(len(body.linear_vars), 3)
self.assertTrue(body.is_linear())
- self.assertIs(body.linear_vars[0], m.on.indicator_var)
+ self.assertIs(body.linear_vars[0], m.off.indicator_var)
self.assertEqual(body.linear_coefs[0], 1)
- self.assertIs(body.linear_vars[1], m.startup.indicator_var)
+ self.assertIs(body.linear_vars[1], m.on.indicator_var)
self.assertEqual(body.linear_coefs[1], 1)
- self.assertIs(body.linear_vars[2], m.off.indicator_var)
+ self.assertIs(body.linear_vars[2], m.startup.indicator_var)
self.assertEqual(body.linear_coefs[2], 1)
-
+
# 1 >= on.ind_var + startup.ind_var + off.ind_var
cons = constraints[indices[10]]
self.assertEqual(cons.lower, -1)
@@ -465,11 +464,11 @@ def check_hull_projected_constraints(self, m, constraints, indices):
self.assertEqual(body.constant, 0)
self.assertEqual(len(body.linear_vars), 3)
self.assertTrue(body.is_linear())
- self.assertIs(body.linear_vars[0], m.on.indicator_var)
+ self.assertIs(body.linear_vars[0], m.off.indicator_var)
self.assertEqual(body.linear_coefs[0], -1)
- self.assertIs(body.linear_vars[1], m.startup.indicator_var)
+ self.assertIs(body.linear_vars[1], m.on.indicator_var)
self.assertEqual(body.linear_coefs[1], -1)
- self.assertIs(body.linear_vars[2], m.off.indicator_var)
+ self.assertIs(body.linear_vars[2], m.startup.indicator_var)
self.assertEqual(body.linear_coefs[2], -1)
def create_hull_model(self):
@@ -518,28 +517,28 @@ def test_project_disaggregated_vars(self):
create_using(m, vars_to_eliminate=disaggregatedVars)
TransformationFactory('contrib.fourier_motzkin_elimination').apply_to(
m, vars_to_eliminate=disaggregatedVars,
- constraint_filtering_callback=None)
+ constraint_filtering_callback=None, do_integer_arithmetic=True)
constraints = m._pyomo_contrib_fme_transformation.projected_constraints
# we of course get tremendous amounts of garbage, but we make sure that
# what should be here is:
- self.check_hull_projected_constraints(m, constraints, [21, 16, 57, 59,
- 55, 33, 27, 1, 2,
- 4, 5])
+ self.check_hull_projected_constraints(m, constraints, [16, 11, 57, 59,
+ 46, 48, 27, 1, 2,
+ 4, 5])
# and when we filter, it's still there.
constraints = filtered._pyomo_contrib_fme_transformation.\
projected_constraints
- constraints.pprint()
self.check_hull_projected_constraints(filtered, constraints, [6, 5, 16,
- 17, 15,
- 9, 8, 1,
- 2, 3, 4])
+ 17, 12,
+ 13, 8, 1,
+ 2, 3, 4])
@unittest.skipIf(not 'glpk' in solvers, 'glpk not available')
def test_post_processing(self):
m, disaggregatedVars = self.create_hull_model()
fme = TransformationFactory('contrib.fourier_motzkin_elimination')
- fme.apply_to(m, vars_to_eliminate=disaggregatedVars)
+ fme.apply_to(m, vars_to_eliminate=disaggregatedVars,
+ do_integer_arithmetic=True)
# post-process
fme.post_process_fme_constraints(m, SolverFactory('glpk'))
@@ -548,9 +547,9 @@ def test_post_processing(self):
# They should be the same as the above, but now these are *all* the
# constraints
- self.check_hull_projected_constraints(m, constraints, [6, 5, 16, 17,
- 15, 9, 8, 1, 2,
- 3, 4])
+ self.check_hull_projected_constraints(m, constraints, [6, 5, 16, 17, 12,
+ 13, 8, 1, 2, 3,
+ 4])
# and check that we didn't change the model
for disj in m.component_data_objects(Disjunct):
@@ -582,11 +581,11 @@ def cons(m, i):
constraints = m._pyomo_contrib_fme_transformation.projected_constraints
# 0 <= y <= 3
- cons = constraints[6]
- self.assertEqual(cons.lower, 0)
- self.assertIs(cons.body, m.y)
cons = constraints[5]
- self.assertEqual(cons.lower, -3)
+ self.assertEqual(value(cons.lower), 0)
+ self.assertIs(cons.body, m.y)
+ cons = constraints[6]
+ self.assertEqual(value(cons.lower), -3)
body = generate_standard_repn(cons.body)
self.assertTrue(body.is_linear())
self.assertEqual(len(body.linear_vars), 1)
@@ -594,8 +593,8 @@ def cons(m, i):
self.assertEqual(body.linear_coefs[0], -1)
# z <= y**2 + 3
- cons = constraints[4]
- self.assertEqual(cons.lower, -3)
+ cons = constraints[2]
+ self.assertEqual(value(cons.lower), -3)
body = generate_standard_repn(cons.body)
self.assertTrue(body.is_quadratic())
self.assertEqual(len(body.linear_vars), 1)
@@ -607,7 +606,7 @@ def cons(m, i):
self.assertIs(body.quadratic_vars[0][1], m.y)
# z <= 6
- cons = constraints[2]
+ cons = constraints[4]
self.assertEqual(cons.lower, -6)
body = generate_standard_repn(cons.body)
self.assertTrue(body.is_linear())
@@ -617,7 +616,7 @@ def cons(m, i):
# 0 <= ln(y+ 1)
cons = constraints[1]
- self.assertEqual(cons.lower, 0)
+ self.assertEqual(value(cons.lower), 0)
body = generate_standard_repn(cons.body)
self.assertTrue(body.is_nonlinear())
self.assertFalse(body.is_quadratic())
@@ -629,7 +628,7 @@ def cons(m, i):
# 0 <= y**2
cons = constraints[3]
- self.assertEqual(cons.lower, 0)
+ self.assertEqual(value(cons.lower), 0)
body = generate_standard_repn(cons.body)
self.assertTrue(body.is_quadratic())
self.assertEqual(len(body.quadratic_vars), 1)
@@ -652,7 +651,7 @@ def cons(m, i):
# check post process these are non-convex, so I don't want to deal with
# it... (and this is a good test that I *don't* deal with it.)
- constraints[4].deactivate()
+ constraints[2].deactivate()
constraints[3].deactivate()
constraints[1].deactivate()
# NOTE also that some of the suproblems in this test are unbounded: We
@@ -670,4 +669,239 @@ def cons(m, i):
# now we should have lost one constraint
self.assertEqual(len(constraints), 5)
# and it should be the y <= 3 one...
- self.assertIsNone(dict(constraints).get(5))
+ self.assertIsNone(dict(constraints).get(6))
+
+ @unittest.skipIf(not 'glpk' in solvers, 'glpk not available')
+ def test_noninteger_coefficients_of_vars_being_projected_error(self):
+ m = ConcreteModel()
+ m.x = Var(bounds=(0,9))
+ m.y = Var(bounds=(-5, 5))
+ m.c1 = Constraint(expr=2*m.x + 0.5*m.y >= 2)
+ m.c2 = Constraint(expr=0.25*m.y >= 0.5*m.x)
+
+ fme = TransformationFactory('contrib.fourier_motzkin_elimination')
+ self.assertRaisesRegexp(
+ ValueError,
+ "The do_integer_arithmetic flag was "
+ "set to True, but the coefficient of "
+ "x is non-integer within the specified tolerance, "
+ "with value -0.5. \n"
+ "Please set do_integer_arithmetic="
+ "False, increase integer_tolerance, or make your data integer.",
+ fme.apply_to,
+ m,
+ vars_to_eliminate=m.x,
+ do_integer_arithmetic=True)
+
+ @unittest.skipIf(not 'glpk' in solvers, 'glpk not available')
+ def test_noninteger_coefficients_of_vars_not_being_projected_error(self):
+ m = ConcreteModel()
+ m.x = Var(bounds=(0,9))
+ m.y = Var(bounds=(-5, 5))
+ m.c1 = Constraint(expr=2*m.x + 0.5*m.y >= 2)
+ m.c2 = Constraint(expr=0.25*m.y >= 5*m.x)
+
+ fme = TransformationFactory('contrib.fourier_motzkin_elimination')
+ self.assertRaisesRegexp(
+ ValueError,
+ "The do_integer_arithmetic flag was "
+ "set to True, but the coefficient of "
+ "y is non-integer within the specified tolerance, "
+ "with value 0.5. \n"
+ "Please set do_integer_arithmetic="
+ "False, increase integer_tolerance, or make your data integer.",
+ fme.apply_to,
+ m,
+ vars_to_eliminate=m.x,
+ do_integer_arithmetic=True)
+
+ def test_integer_arithmetic_non1_coefficients(self):
+ m = ConcreteModel()
+ m.x = Var(bounds=(0,9))
+ m.y = Var(bounds=(-5, 5))
+ m.c1 = Constraint(expr=4*m.x + m.y >= 4)
+ m.c2 = Constraint(expr=m.y >= 2*m.x)
+
+ fme = TransformationFactory('contrib.fourier_motzkin_elimination')
+
+ fme.apply_to( m, vars_to_eliminate=m.x,
+ constraint_filtering_callback=None,
+ do_integer_arithmetic=True, verbose=True)
+
+ constraints = m._pyomo_contrib_fme_transformation.projected_constraints
+
+ self.assertEqual(len(constraints), 3)
+
+ cons = constraints[3]
+ self.assertEqual(value(cons.lower), -32)
+ self.assertIs(cons.body, m.y)
+ self.assertIsNone(cons.upper)
+
+ cons = constraints[2]
+ self.assertEqual(value(cons.lower), 0)
+ self.assertIsNone(cons.upper)
+ repn = generate_standard_repn(cons.body)
+ self.assertTrue(repn.is_linear())
+ self.assertEqual(len(repn.linear_coefs), 1)
+ self.assertIs(repn.linear_vars[0], m.y)
+ self.assertEqual(repn.linear_coefs[0], 2)
+
+ cons = constraints[1]
+ self.assertEqual(value(cons.lower), 4)
+ self.assertIsNone(cons.upper)
+ repn = generate_standard_repn(cons.body)
+ self.assertTrue(repn.is_linear())
+ self.assertEqual(len(repn.linear_coefs), 1)
+ self.assertIs(repn.linear_vars[0], m.y)
+ self.assertEqual(repn.linear_coefs[0], 3)
+
+ def test_numerical_instability_almost_canceling(self):
+ # It's possible that we get almost-but-not-quite zero on the variable
+ # being eliminated when we are doing this with floating point
+ # arithmetic. This can get ugly later becuase it might get muliplied by
+ # a large number later and start to "reappear"
+ m = ConcreteModel()
+ m.x = Var()
+ m.x0 = Var()
+ m.y = Var()
+
+ m.cons1 = Constraint(expr=(1.342 + 2.371e-8)*m.x0 <= m.x + 17*m.y)
+ m.cons2 = Constraint(expr=(17.56 + 3.2e-7)*m.x0 >= m.y)
+
+ fme = TransformationFactory('contrib.fourier_motzkin_elimination')
+
+ fme.apply_to(m, vars_to_eliminate=[m.x0], verbose=True,
+ zero_tolerance=1e-9)
+
+ constraints = m._pyomo_contrib_fme_transformation.projected_constraints
+
+ # There's going to be numerical error here, and I can't really help
+ # it. What I care about is that x0 really is gone.
+
+ useful = constraints[1]
+ repn = generate_standard_repn(useful.body)
+ self.assertTrue(repn.is_linear())
+ self.assertEqual(len(repn.linear_coefs), 2) # this is the real test
+ self.assertEqual(useful.lower, 0)
+ self.assertIs(repn.linear_vars[0], m.x)
+ self.assertAlmostEqual(repn.linear_coefs[0], 0.7451564696962295)
+ self.assertIs(repn.linear_vars[1], m.y)
+ self.assertAlmostEqual(repn.linear_coefs[1], 12.610712377673217)
+ self.assertEqual(repn.constant, 0)
+ self.assertIsNone(useful.upper)
+
+ def test_numerical_instability_early_elimination(self):
+ # A more subtle numerical problem is that, in infinite precision, a
+ # variable might be eliminated early. However, if this goes wrong, the
+ # result can be unexpected (including getting no constraints when some
+ # are expected.)
+ m = ConcreteModel()
+ m.x = Var()
+ m.x0 = Var()
+ m.y = Var()
+
+ # we'll pretend that the 1.123e-9 is noise from previous calculations
+ m.cons1 = Constraint(expr=0 <= (4.27 + 1.123e-9)*m.x + 13*m.y - m.x0)
+ m.cons2 = Constraint(expr=m.x0 >= 12*m.y + 4.27*m.x)
+
+ fme = TransformationFactory('contrib.fourier_motzkin_elimination')
+
+ # doing my own clones because I want assertIs tests
+ first = m.clone()
+ second = m.clone()
+ third = m.clone()
+
+ fme.apply_to(first, vars_to_eliminate=[first.x0], zero_tolerance=1e-10)
+ constraints = first._pyomo_contrib_fme_transformation.\
+ projected_constraints
+ cons = constraints[1]
+ self.assertEqual(cons.lower, 0)
+ repn = generate_standard_repn(cons.body)
+ self.assertTrue(repn.is_linear())
+ self.assertEqual(repn.constant, 0)
+ self.assertEqual(len(repn.linear_coefs), 2) # x is still around
+ self.assertIs(repn.linear_vars[0], first.x)
+ self.assertAlmostEqual(repn.linear_coefs[0], 1.123e-9)
+ self.assertIs(repn.linear_vars[1], first.y)
+ self.assertEqual(repn.linear_coefs[1], 1)
+ self.assertIsNone(cons.upper)
+
+ # so just to drive home the point, this results in no constraints:
+ # (Though also note that that only happens if x0 is the first to be
+ # projected out)
+ fme.apply_to(second, vars_to_eliminate=[second.x0, second.x],
+ zero_tolerance=1e-10)
+ self.assertEqual(len(second._pyomo_contrib_fme_transformation.\
+ projected_constraints), 0)
+
+ # but in this version, we assume that x is already gone...
+ fme.apply_to(third, vars_to_eliminate=[third.x0], verbose=True,
+ zero_tolerance=1e-8)
+ constraints = third._pyomo_contrib_fme_transformation.\
+ projected_constraints
+ cons = constraints[1]
+ self.assertEqual(cons.lower, 0)
+ self.assertIs(cons.body, third.y)
+ self.assertIsNone(cons.upper)
+
+ # and this is exactly the same as the above:
+ fme.apply_to(m, vars_to_eliminate=[m.x0, m.x], verbose=True,
+ zero_tolerance=1e-8)
+ constraints = m._pyomo_contrib_fme_transformation.projected_constraints
+ cons = constraints[1]
+ self.assertEqual(cons.lower, 0)
+ self.assertIs(cons.body, m.y)
+ self.assertIsNone(cons.upper)
+
+ def test_use_all_var_bounds(self):
+ m = ConcreteModel()
+ m.b = Block()
+ m.x = Var(bounds=(0, 15))
+ m.y = Var(bounds=(3, 5))
+ m.b.c = Constraint(expr=m.x + m.y <= 8)
+
+ fme = TransformationFactory('contrib.fourier_motzkin_elimination')
+ fme.apply_to(m.b, vars_to_eliminate=[m.y])
+ constraints = m.b.\
+ _pyomo_contrib_fme_transformation.projected_constraints
+
+ # if we hadn't included y's bounds, then we wouldn't get any constraints
+ # and y wouldn't be eliminated. If we do include y's bounds, we get new
+ # information that x <= 5:
+ self.assertEqual(len(constraints), 1)
+ cons = constraints[1]
+ self.assertEqual(value(cons.lower), -5)
+ self.assertIsNone(cons.upper)
+ repn = generate_standard_repn(cons.body)
+ self.assertEqual(repn.constant, 0)
+ self.assertEqual(len(repn.linear_vars), 1)
+ self.assertIs(repn.linear_vars[0], m.x)
+ self.assertEqual(repn.linear_coefs[0], -1)
+
+ def test_simple_hull_example(self):
+ m = ConcreteModel()
+ m.x0 = Var(bounds=(0,3))
+ m.x1 = Var(bounds=(0,3))
+ m.x = Var(bounds=(0,3))
+ m.disaggregation = Constraint(expr=m.x == m.x0 + m.x1)
+ m.y = Var(domain=Binary)
+ m.cons = Constraint(expr=2*m.y <= m.x1)
+
+ fme = TransformationFactory('contrib.fourier_motzkin_elimination')
+ fme.apply_to(m, vars_to_eliminate=[m.x0, m.x1])
+
+ constraints = m._pyomo_contrib_fme_transformation.projected_constraints
+ constraints.pprint()
+
+ self.assertEqual(len(constraints), 1)
+ cons = constraints[1]
+ self.assertIsNone(cons.upper)
+ self.assertEqual(value(cons.lower), 0)
+ repn = generate_standard_repn(cons.body)
+ self.assertEqual(repn.constant, 0)
+ self.assertEqual(len(repn.linear_vars), 2)
+ self.assertIs(repn.linear_vars[0], m.x)
+ self.assertEqual(repn.linear_coefs[0], 1)
+ self.assertIs(repn.linear_vars[1], m.y)
+ self.assertEqual(repn.linear_coefs[1], -2)
+ self.assertTrue(repn.is_linear())
diff --git a/pyomo/contrib/gdp_bounds/compute_bounds.py b/pyomo/contrib/gdp_bounds/compute_bounds.py
index 7d0a030b501..58f5655117b 100644
--- a/pyomo/contrib/gdp_bounds/compute_bounds.py
+++ b/pyomo/contrib/gdp_bounds/compute_bounds.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Provides functions to compute and enforce disjunctive variable bounds.
These are tighter variable bounds that are valid within the scope of a certain
@@ -15,7 +25,7 @@
from pyomo.core.base.block import Block, TraversalStrategy
from pyomo.core.expr.current import identify_variables
from pyomo.core import (Constraint, Objective,
- TransformationFactory, maximize, minimize, value)
+ TransformationFactory, minimize, value)
from pyomo.opt import SolverFactory
from pyomo.gdp.disjunct import Disjunct
from pyomo.core.plugins.transform.hierarchy import Transformation
diff --git a/pyomo/contrib/gdp_bounds/plugins.py b/pyomo/contrib/gdp_bounds/plugins.py
index 541dca352be..ca43eca54cb 100644
--- a/pyomo/contrib/gdp_bounds/plugins.py
+++ b/pyomo/contrib/gdp_bounds/plugins.py
@@ -1,2 +1,12 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
def load():
import pyomo.contrib.gdp_bounds.compute_bounds
diff --git a/pyomo/contrib/gdpopt/branch_and_bound.py b/pyomo/contrib/gdpopt/branch_and_bound.py
index ad93f69b8e7..52b3e6d4d39 100644
--- a/pyomo/contrib/gdpopt/branch_and_bound.py
+++ b/pyomo/contrib/gdpopt/branch_and_bound.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import traceback
from collections import namedtuple
from heapq import heappush, heappop
diff --git a/pyomo/contrib/gdpopt/cut_generation.py b/pyomo/contrib/gdpopt/cut_generation.py
index f775fed2185..a9ef71daac4 100644
--- a/pyomo/contrib/gdpopt/cut_generation.py
+++ b/pyomo/contrib/gdpopt/cut_generation.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""This module provides functions for cut generation."""
from __future__ import division
@@ -12,7 +22,6 @@
minimize, value, TransformationFactory)
from pyomo.core.expr import differentiate
from pyomo.core.expr.visitor import identify_variables
-from pyomo.gdp import Disjunct
MAX_SYMBOLIC_DERIV_SIZE = 1000
JacInfo = namedtuple('JacInfo', ['mode','vars','jac'])
diff --git a/pyomo/contrib/gdpopt/mip_solve.py b/pyomo/contrib/gdpopt/mip_solve.py
index 786914b34bd..c8a62bd7db8 100644
--- a/pyomo/contrib/gdpopt/mip_solve.py
+++ b/pyomo/contrib/gdpopt/mip_solve.py
@@ -82,12 +82,14 @@ def solve_linear_GDP(linear_GDP_model, solve_data, config):
mip_args['add_options'] = mip_args.get('add_options', [])
mip_args['add_options'].append('option reslim=%s;' % remaining)
elif config.mip_solver == 'multisolve':
- mip_args['time_limit'] = min(mip_args.get('time_limit', float('inf')), remaining)
+ mip_args['time_limit'] = min(mip_args.get(
+ 'time_limit', float('inf')), remaining)
results = SolverFactory(config.mip_solver).solve(
m, **mip_args)
except RuntimeError as e:
if 'GAMS encountered an error during solve.' in str(e):
- config.logger.warning("GAMS encountered an error in solve. Treating as infeasible.")
+ config.logger.warning(
+ "GAMS encountered an error in solve. Treating as infeasible.")
mip_result = MasterProblemResult()
mip_result.feasible = False
mip_result.var_values = list(v.value for v in GDPopt.variable_list)
@@ -115,7 +117,8 @@ def solve_linear_GDP(linear_GDP_model, solve_data, config):
'Resolving with arbitrary bound values of (-{0:.10g}, {0:.10g}) on the objective. '
'Check your initialization routine.'.format(obj_bound))
main_objective = next(m.component_data_objects(Objective, active=True))
- GDPopt.objective_bound = Constraint(expr=(-obj_bound, main_objective.expr, obj_bound))
+ GDPopt.objective_bound = Constraint(
+ expr=(-obj_bound, main_objective.expr, obj_bound))
with SuppressInfeasibleWarning():
results = SolverFactory(config.mip_solver).solve(
m, **config.mip_solver_args)
@@ -129,7 +132,7 @@ def solve_linear_GDP(linear_GDP_model, solve_data, config):
mip_result.disjunct_values = list(
disj.indicator_var.value for disj in GDPopt.disjunct_list)
- if terminate_cond is tc.optimal or terminate_cond is tc.locallyOptimal:
+ if terminate_cond in {tc.optimal, tc.locallyOptimal, tc.feasible}:
pass
elif terminate_cond is tc.infeasible:
config.logger.info(
diff --git a/pyomo/contrib/gdpopt/nlp_solve.py b/pyomo/contrib/gdpopt/nlp_solve.py
index 4516bf613ed..317e00f76a3 100644
--- a/pyomo/contrib/gdpopt/nlp_solve.py
+++ b/pyomo/contrib/gdpopt/nlp_solve.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Functions for solving the nonlinear subproblem."""
from __future__ import division
@@ -5,7 +15,6 @@
from pyomo.common.collections import ComponentSet
from pyomo.common.errors import InfeasibleConstraintException
-from pyomo.contrib.fbbt.fbbt import fbbt
from pyomo.contrib.gdpopt.data_class import SubproblemResult
from pyomo.contrib.gdpopt.util import (SuppressInfeasibleWarning,
is_feasible, get_main_elapsed_time)
diff --git a/pyomo/contrib/gdpopt/plugins.py b/pyomo/contrib/gdpopt/plugins.py
index 853eb9a932f..f4dc4bfa917 100644
--- a/pyomo/contrib/gdpopt/plugins.py
+++ b/pyomo/contrib/gdpopt/plugins.py
@@ -1,2 +1,12 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
def load():
import pyomo.contrib.gdpopt.GDPopt
diff --git a/pyomo/contrib/gdpopt/tests/test_gdpopt.py b/pyomo/contrib/gdpopt/tests/test_gdpopt.py
index 50a2f370cc2..4e4f99872e7 100644
--- a/pyomo/contrib/gdpopt/tests/test_gdpopt.py
+++ b/pyomo/contrib/gdpopt/tests/test_gdpopt.py
@@ -1,7 +1,17 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Tests for the GDPopt solver plugin."""
import logging
from math import fabs
-from os.path import abspath, dirname, join, normpath
+from os.path import join, normpath
from six import StringIO
diff --git a/pyomo/contrib/gdpopt/util.py b/pyomo/contrib/gdpopt/util.py
index 4f8c618fcda..0234c27e06b 100644
--- a/pyomo/contrib/gdpopt/util.py
+++ b/pyomo/contrib/gdpopt/util.py
@@ -155,8 +155,10 @@ def process_objective(solve_data, config, move_linear_objective=False, use_mcpp=
else:
# Use Pyomo's contrib.fbbt package
lb, ub = compute_bounds_on_expr(main_obj.expr)
- util_blk.objective_value.setub(ub)
- util_blk.objective_value.setlb(lb)
+ if solve_data.results.problem.sense == ProblemSense.minimize:
+ util_blk.objective_value.setlb(lb)
+ else:
+ util_blk.objective_value.setub(ub)
if main_obj.sense == minimize:
util_blk.objective_constr = Constraint(
diff --git a/pyomo/contrib/interior_point/examples/ex1.py b/pyomo/contrib/interior_point/examples/ex1.py
index f71c5f27890..1c503153492 100644
--- a/pyomo/contrib/interior_point/examples/ex1.py
+++ b/pyomo/contrib/interior_point/examples/ex1.py
@@ -1,4 +1,14 @@
-import pyomo.environ as pe
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+import pyomo.environ as pyo
from pyomo.contrib.interior_point.interior_point import InteriorPointSolver
from pyomo.contrib.interior_point.interface import InteriorPointInterface
from pyomo.contrib.interior_point.linalg.mumps_interface import MumpsInterface
@@ -7,20 +17,20 @@
logging.basicConfig(level=logging.INFO)
# Supposedly this sets the root logger's level to INFO.
-# But when linear_solver.logger logs with debug,
+# But when linear_solver.logger logs with debug,
# it gets propagated to a mysterious root logger with
# level NOTSET...
-m = pe.ConcreteModel()
-m.x = pe.Var()
-m.y = pe.Var()
-m.obj = pe.Objective(expr=m.x**2 + m.y**2)
-m.c1 = pe.Constraint(expr=m.y == pe.exp(m.x))
-m.c2 = pe.Constraint(expr=m.y >= (m.x - 1)**2)
+m = pyo.ConcreteModel()
+m.x = pyo.Var()
+m.y = pyo.Var()
+m.obj = pyo.Objective(expr=m.x**2 + m.y**2)
+m.c1 = pyo.Constraint(expr=m.y == pyo.exp(m.x))
+m.c2 = pyo.Constraint(expr=m.y >= (m.x - 1)**2)
interface = InteriorPointInterface(m)
linear_solver = MumpsInterface(
-# log_filename='lin_sol.log',
- icntl_options={11: 1}, # Set error level to 1 (most detailed)
+ # log_filename='lin_sol.log',
+ icntl_options={11: 1}, # Set error level to 1 (most detailed)
)
ip_solver = InteriorPointSolver(linear_solver)
diff --git a/pyomo/contrib/interior_point/inverse_reduced_hessian.py b/pyomo/contrib/interior_point/inverse_reduced_hessian.py
index 91a9389e681..97390dee9c0 100644
--- a/pyomo/contrib/interior_point/inverse_reduced_hessian.py
+++ b/pyomo/contrib/interior_point/inverse_reduced_hessian.py
@@ -1,10 +1,22 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyomo.environ as pyo
from pyomo.opt import check_optimal_termination
from pyomo.common.dependencies import attempt_import
from .interface import InteriorPointInterface
from .linalg.scipy_interface import ScipyInterface
-np, numpy_available = attempt_import('numpy', 'Interior point requires numpy', minimum_version='1.13.0')
+np, numpy_available = attempt_import('numpy',
+ 'Interior point requires numpy',
+ minimum_version='1.13.0')
# Todo: This function currently used IPOPT for the initial solve - should accept solver
@@ -56,7 +68,7 @@ def inv_reduced_hessian_barrier(model, independent_variables, bound_tolerance=1e
# create the ipopt solver
solver = pyo.SolverFactory('ipopt')
-
+
# copy additional solver options
if solver_options is not None:
for key in solver_options:
@@ -101,7 +113,7 @@ def inv_reduced_hessian_barrier(model, independent_variables, bound_tolerance=1e
# check that none of the independent variables are at their bounds
for v in ind_vardatas:
if (v.has_lb() and pyo.value(v) - v.lb <= bound_tolerance) or \
- (v.has_ub() and v.ub - pyo.value(b) <= bound_tolerance):
+ (v.has_ub() and v.ub - pyo.value(v) <= bound_tolerance):
raise ValueError("Independent variable: {} has a solution value that is near"
" its bound (according to tolerance). The reduced hessian"
" computation does not support this at this time. All"
diff --git a/pyomo/contrib/interior_point/linalg/mumps_interface.py b/pyomo/contrib/interior_point/linalg/mumps_interface.py
index e435cbc0837..0a0d1bcca33 100644
--- a/pyomo/contrib/interior_point/linalg/mumps_interface.py
+++ b/pyomo/contrib/interior_point/linalg/mumps_interface.py
@@ -1,9 +1,19 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from .base_linear_solver_interface import LinearSolverInterface
from .results import LinearSolverStatus, LinearSolverResults
from pyomo.common.dependencies import attempt_import
from scipy.sparse import isspmatrix_coo, tril
from collections import OrderedDict
-import logging
+
mumps, mumps_available = attempt_import(name='pyomo.contrib.pynumero.linalg.mumps_interface',
error_message='pymumps is required to use the MumpsInterface')
diff --git a/pyomo/contrib/interior_point/tests/test_interior_point.py b/pyomo/contrib/interior_point/tests/test_interior_point.py
index 333ba92d158..ff896a43692 100644
--- a/pyomo/contrib/interior_point/tests/test_interior_point.py
+++ b/pyomo/contrib/interior_point/tests/test_interior_point.py
@@ -1,5 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as pe
+import pyomo.environ as pyo
from pyomo.common.dependencies import attempt_import
np, numpy_available = attempt_import('numpy', 'Interior point requires numpy', minimum_version='1.13.0')
@@ -36,12 +46,12 @@
@unittest.skipIf(not asl_available, 'asl is not available')
class TestSolveInteriorPoint(unittest.TestCase):
def _test_solve_interior_point_1(self, linear_solver):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.obj = pe.Objective(expr=m.x**2 + m.y**2)
- m.c1 = pe.Constraint(expr=m.y == pe.exp(m.x))
- m.c2 = pe.Constraint(expr=m.y >= (m.x - 1)**2)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.obj = pyo.Objective(expr=m.x**2 + m.y**2)
+ m.c1 = pyo.Constraint(expr=m.y == pyo.exp(m.x))
+ m.c2 = pyo.Constraint(expr=m.y >= (m.x - 1)**2)
interface = InteriorPointInterface(m)
ip_solver = InteriorPointSolver(linear_solver)
status = ip_solver.solve(interface)
@@ -58,9 +68,9 @@ def _test_solve_interior_point_1(self, linear_solver):
self.assertAlmostEqual(m.y.value, 1)
def _test_solve_interior_point_2(self, linear_solver):
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(1, 4))
- m.obj = pe.Objective(expr=m.x**2)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(1, 4))
+ m.obj = pyo.Objective(expr=m.x**2)
interface = InteriorPointInterface(m)
ip_solver = InteriorPointSolver(linear_solver)
status = ip_solver.solve(interface)
diff --git a/pyomo/contrib/interior_point/tests/test_inverse_reduced_hessian.py b/pyomo/contrib/interior_point/tests/test_inverse_reduced_hessian.py
index dd6e3d17749..8122b134cf2 100644
--- a/pyomo/contrib/interior_point/tests/test_inverse_reduced_hessian.py
+++ b/pyomo/contrib/interior_point/tests/test_inverse_reduced_hessian.py
@@ -1,5 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as pe
+import pyomo.environ as pyo
from pyomo.opt import check_optimal_termination
from pyomo.common.dependencies import attempt_import
@@ -15,9 +25,9 @@
if not (numpy_available and scipy_available and asl_available):
raise unittest.SkipTest('inverse_reduced_hessian tests require numpy, scipy, and asl')
-from pyomo.common.dependencies import(pandas as pd, pandas_available)
-import pyomo.environ as pe
-ipopt_solver = pe.SolverFactory('ipopt')
+from pyomo.common.dependencies import (pandas as pd, pandas_available)
+
+ipopt_solver = pyo.SolverFactory('ipopt')
if not ipopt_solver.available(exception_flag=False):
raise unittest.SkipTest('ipopt is not available')
@@ -32,10 +42,10 @@
class TestInverseReducedHessian(unittest.TestCase):
# the original test
def test_invrh_zavala_thesis(self):
- m = pe.ConcreteModel()
- m.x = pe.Var([1,2,3])
- m.obj = pe.Objective(expr=(m.x[1]-1)**2 + (m.x[2]-2)**2 + (m.x[3]-3)**2)
- m.c1 = pe.Constraint(expr=m.x[1] + 2*m.x[2] + 3*m.x[3]==0)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var([1,2,3])
+ m.obj = pyo.Objective(expr=(m.x[1]-1)**2 + (m.x[2]-2)**2 + (m.x[3]-3)**2)
+ m.c1 = pyo.Constraint(expr=m.x[1] + 2*m.x[2] + 3*m.x[3]==0)
status, invrh = inv_reduced_hessian_barrier(m, [m.x[2], m.x[3]])
expected_invrh = np.asarray([[ 0.35714286, -0.21428571],
@@ -66,26 +76,26 @@ def _simple_model(self, add_constraint=False):
[18, 1.29, 15.60649164]],
columns=['tofu','chard', 'y'])
- model = pe.ConcreteModel()
+ model = pyo.ConcreteModel()
- model.b0 = pe.Var(initialize = 0)
- model.bindexes = pe.Set(initialize=['tofu', 'chard'])
- model.b = pe.Var(model.bindexes, initialize = 1)
+ model.b0 = pyo.Var(initialize = 0)
+ model.bindexes = pyo.Set(initialize=['tofu', 'chard'])
+ model.b = pyo.Var(model.bindexes, initialize = 1)
# try to make trouble
if add_constraint:
- model.binding_constraint = pe.Constraint(expr=model.b0>=10)
+ model.binding_constraint = pyo.Constraint(expr=model.b0>=10)
# The columns need to have unique values (or you get warnings)
def response_rule(m, t, c):
expr = m.b0 + m.b['tofu']*t + m.b['chard']*c
return expr
- model.response_function = pe.Expression(data.tofu, data.chard, rule = response_rule)
+ model.response_function = pyo.Expression(data.tofu, data.chard, rule = response_rule)
def SSE_rule(m):
return sum((data.y[i] - m.response_function[data.tofu[i], data.chard[i]])**2\
for i in data.index)
- model.SSE = pe.Objective(rule = SSE_rule, sense=pe.minimize)
+ model.SSE = pyo.Objective(rule = SSE_rule, sense=pyo.minimize)
return model
@@ -95,18 +105,18 @@ def test_3x3_using_linear_regression(self):
""" simple linear regression with two x columns, so 3x3 Hessian"""
model = self._simple_model()
- solver = pe.SolverFactory("ipopt")
+ solver = pyo.SolverFactory("ipopt")
status = solver.solve(model)
self.assertTrue(check_optimal_termination(status))
- tstar = [pe.value(model.b0),
- pe.value(model.b['tofu']), pe.value(model.b['chard'])]
+ tstar = [pyo.value(model.b0),
+ pyo.value(model.b['tofu']), pyo.value(model.b['chard'])]
def _ndwrap(x):
# wrapper for numdiff call
model.b0.fix(x[0])
model.b["tofu"].fix(x[1])
model.b["chard"].fix(x[2])
- rval = pe.value(model.SSE)
+ rval = pyo.value(model.SSE)
return rval
H = nd.Hessian(_ndwrap)(tstar)
@@ -136,6 +146,6 @@ def test_with_binding_constraint(self):
model.b["chard"]])
print("test_with_binding_constraint should see an error raised.")
-
+
if __name__ == '__main__':
unittest.main()
diff --git a/pyomo/contrib/interior_point/tests/test_reg.py b/pyomo/contrib/interior_point/tests/test_reg.py
index 0cfc31c0525..848c94e6d81 100644
--- a/pyomo/contrib/interior_point/tests/test_reg.py
+++ b/pyomo/contrib/interior_point/tests/test_reg.py
@@ -1,5 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as pe
+import pyomo.environ as pyo
from pyomo.core.base import ConcreteModel, Var, Constraint, Objective
from pyomo.common.dependencies import attempt_import
@@ -51,7 +61,7 @@ def make_model_2():
m.x = Var(initialize=0.1, bounds=(0, 1))
m.y = Var(initialize=0.1, bounds=(0, 1))
m.obj = Objective(expr=-m.x**2 - m.y**2)
- m.c = Constraint(expr=m.y <= pe.exp(-m.x))
+ m.c = Constraint(expr=m.y <= pyo.exp(-m.x))
return m
@@ -103,7 +113,7 @@ def _test_regularization_2(self, linear_solver):
self.assertEqual(status, InteriorPointStatus.optimal)
interface.load_primals_into_pyomo_model()
self.assertAlmostEqual(m.x.value, 1)
- self.assertAlmostEqual(m.y.value, pe.exp(-1))
+ self.assertAlmostEqual(m.y.value, pyo.exp(-1))
@unittest.skipIf(not mumps_available, 'Mumps is not available')
def test_mumps_2(self):
diff --git a/pyomo/contrib/mcpp/getMCPP.py b/pyomo/contrib/mcpp/getMCPP.py
index 32f61571002..051ddb36f7c 100644
--- a/pyomo/contrib/mcpp/getMCPP.py
+++ b/pyomo/contrib/mcpp/getMCPP.py
@@ -10,7 +10,6 @@
import logging
import os
-import stat
import sys
from pyomo.common.download import FileDownloader
diff --git a/pyomo/contrib/mindtpy/MindtPy.py b/pyomo/contrib/mindtpy/MindtPy.py
index b0c67a84d40..4a07d395517 100644
--- a/pyomo/contrib/mindtpy/MindtPy.py
+++ b/pyomo/contrib/mindtpy/MindtPy.py
@@ -1,4 +1,15 @@
# -*- coding: utf-8 -*-
+
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Implementation of the MindtPy solver.
The MindtPy (MINLP Decomposition Toolkit) solver applies a variety of
@@ -22,25 +33,23 @@
import logging
-from pyomo.common.config import (
- ConfigBlock, ConfigValue, In, PositiveFloat, PositiveInt
-)
from pyomo.contrib.gdpopt.util import (
- _DoNothing, copy_var_list_values,
+ copy_var_list_values,
create_utility_block,
- restore_logger_level, time_code,
- setup_results_object, process_objective, a_logger, lower_logger_level_to)
+ time_code,
+ setup_results_object, process_objective, lower_logger_level_to)
from pyomo.contrib.mindtpy.initialization import MindtPy_initialize_master
from pyomo.contrib.mindtpy.iterate import MindtPy_iteration_loop
from pyomo.contrib.mindtpy.util import (
MindtPySolveData, model_is_valid
)
from pyomo.core import (
- Block, ConstraintList, NonNegativeReals, RangeSet, Set, Suffix, Var, value,
- VarList, TransformationFactory)
+ Block, ConstraintList, NonNegativeReals, Set, Suffix, Var,
+ VarList, TransformationFactory, Objective)
from pyomo.opt import SolverFactory, SolverResults
from pyutilib.misc import Container
-
+from pyomo.contrib.fbbt.fbbt import fbbt
+from pyomo.contrib.mindtpy.config_options import _get_GDPopt_config
logger = logging.getLogger('pyomo.contrib.mindtpy')
@@ -53,214 +62,7 @@
class MindtPySolver(object):
"""A decomposition-based MINLP solver.
"""
-
- CONFIG = ConfigBlock("MindtPy")
- CONFIG.declare("bound_tolerance", ConfigValue(
- default=1E-5,
- domain=PositiveFloat,
- description="Bound tolerance",
- doc="Relative tolerance for bound feasibility checks."
- ))
- CONFIG.declare("iteration_limit", ConfigValue(
- default=30,
- domain=PositiveInt,
- description="Iteration limit",
- doc="Number of maximum iterations in the decomposition methods."
- ))
- CONFIG.declare("time_limit", ConfigValue(
- default=600,
- domain=PositiveInt,
- description="Time limit (seconds, default=600)",
- doc="Seconds allowed until terminated. Note that the time limit can"
- "currently only be enforced between subsolver invocations. You may"
- "need to set subsolver time limits as well."
- ))
- CONFIG.declare("strategy", ConfigValue(
- default="OA",
- domain=In(["OA", "GBD", "ECP", "PSC"]),
- description="Decomposition strategy",
- doc="MINLP Decomposition strategy to be applied to the method. "
- "Currently available Outer Approximation (OA), Extended Cutting "
- "Plane (ECP), Partial Surrogate Cuts (PSC), and Generalized "
- "Benders Decomposition (GBD)."
- ))
- CONFIG.declare("init_strategy", ConfigValue(
- default="rNLP",
- domain=In(["rNLP", "initial_binary", "max_binary"]),
- description="Initialization strategy",
- doc="Initialization strategy used by any method. Currently the "
- "continuous relaxation of the MINLP (rNLP), solve a maximal "
- "covering problem (max_binary), and fix the initial value for "
- "the integer variables (initial_binary)."
- ))
- CONFIG.declare("max_slack", ConfigValue(
- default=1000.0,
- domain=PositiveFloat,
- description="Maximum slack variable",
- doc="Maximum slack variable value allowed for the Outer Approximation "
- "cuts."
- ))
- CONFIG.declare("OA_penalty_factor", ConfigValue(
- default=1000.0,
- domain=PositiveFloat,
- description="Outer Approximation slack penalty factor",
- doc="In the objective function of the Outer Approximation method, the "
- "slack variables corresponding to all the constraints get "
- "multiplied by this number and added to the objective."
- ))
- CONFIG.declare("ECP_tolerance", ConfigValue(
- default=1E-4,
- domain=PositiveFloat,
- description="ECP tolerance",
- doc="Feasibility tolerance used to determine the stopping criterion in"
- "the ECP method. As long as nonlinear constraint are violated for "
- "more than this tolerance, the method will keep iterating."
- ))
- CONFIG.declare("nlp_solver", ConfigValue(
- default="ipopt",
- domain=In(["ipopt", "gams"]),
- description="NLP subsolver name",
- doc="Which NLP subsolver is going to be used for solving the nonlinear"
- "subproblems."
- ))
- CONFIG.declare("nlp_solver_args", ConfigBlock(
- implicit=True,
- description="NLP subsolver options",
- doc="Which NLP subsolver options to be passed to the solver while "
- "solving the nonlinear subproblems."
- ))
- CONFIG.declare("mip_solver", ConfigValue(
- default="glpk",
- domain=In(["gurobi", "cplex", "cbc", "glpk", "gams",
- "gurobi_persistent", "cplex_persistent"]),
- description="MIP subsolver name",
- doc="Which MIP subsolver is going to be used for solving the mixed-"
- "integer master problems."
- ))
- CONFIG.declare("mip_solver_args", ConfigBlock(
- implicit=True,
- description="MIP subsolver options",
- doc="Which MIP subsolver options to be passed to the solver while "
- "solving the mixed-integer master problems."
- ))
- CONFIG.declare("call_after_master_solve", ConfigValue(
- default=_DoNothing(),
- domain=None,
- description="Function to be executed after every master problem",
- doc="Callback hook after a solution of the master problem."
- ))
- CONFIG.declare("call_after_subproblem_solve", ConfigValue(
- default=_DoNothing(),
- domain=None,
- description="Function to be executed after every subproblem",
- doc="Callback hook after a solution of the nonlinear subproblem."
- ))
- CONFIG.declare("call_after_subproblem_feasible", ConfigValue(
- default=_DoNothing(),
- domain=None,
- description="Function to be executed after every feasible subproblem",
- doc="Callback hook after a feasible solution"
- " of the nonlinear subproblem."
- ))
- CONFIG.declare("tee", ConfigValue(
- default=False,
- description="Stream output to terminal.",
- domain=bool
- ))
- CONFIG.declare("logger", ConfigValue(
- default='pyomo.contrib.mindtpy',
- description="The logger object or name to use for reporting.",
- domain=a_logger
- ))
- CONFIG.declare("small_dual_tolerance", ConfigValue(
- default=1E-8,
- description="When generating cuts, small duals multiplied "
- "by expressions can cause problems. Exclude all duals "
- "smaller in absolute value than the following."
- ))
- CONFIG.declare("integer_tolerance", ConfigValue(
- default=1E-5,
- description="Tolerance on integral values."
- ))
- CONFIG.declare("constraint_tolerance", ConfigValue(
- default=1E-6,
- description="Tolerance on constraint satisfaction."
- ))
- CONFIG.declare("variable_tolerance", ConfigValue(
- default=1E-8,
- description="Tolerance on variable bounds."
- ))
- CONFIG.declare("zero_tolerance", ConfigValue(
- default=1E-8,
- description="Tolerance on variable equal to zero."
- ))
- CONFIG.declare("initial_feas", ConfigValue(
- default=True,
- description="Apply an initial feasibility step.",
- domain=bool
- ))
- CONFIG.declare("obj_bound", ConfigValue(
- default=1E15,
- domain=PositiveFloat,
- description="Bound applied to the linearization of the objective function if master MILP is unbounded."
- ))
- CONFIG.declare("integer_to_binary", ConfigValue(
- default=False,
- description="Convert integer variables to binaries (for integer cuts).",
- domain=bool
- ))
- CONFIG.declare("add_integer_cuts", ConfigValue(
- default=False,
- description="Add integer cuts (no-good cuts) to binary variables to disallow same integer solution again."
- "Note that 'integer_to_binary' flag needs to be used to apply it to actual integers and not just binaries.",
- domain=bool
- ))
- CONFIG.declare("single_tree", ConfigValue(
- default=False,
- description="Use single tree implementation in solving the MILP master problem.",
- domain=bool
- ))
- CONFIG.declare("solution_pool", ConfigValue(
- default=False,
- description="Use solution pool in solving the MILP master problem.",
- domain=bool
- ))
- CONFIG.declare("add_slack", ConfigValue(
- default=False,
- description="whether add slack variable here."
- "slack variables here are used to deal with nonconvex MINLP.",
- domain=bool
- ))
- CONFIG.declare("continuous_var_bound", ConfigValue(
- default=1e10,
- description="default bound added to unbounded continuous variables in nonlinear constraint if single tree is activated.",
- domain=PositiveFloat
- ))
- CONFIG.declare("integer_var_bound", ConfigValue(
- default=1e9,
- description="default bound added to unbounded integral variables in nonlinear constraint if single tree is activated.",
- domain=PositiveFloat
- ))
- CONFIG.declare("cycling_check", ConfigValue(
- default=True,
- description="check if OA algorithm is stalled in a cycle and terminate.",
- domain=bool
- ))
- CONFIG.declare("feasibility_norm", ConfigValue(
- default="L_infinity",
- domain=In(["L1", "L2", "L_infinity"]),
- description="different forms of objective function in feasibility subproblem."
- ))
- CONFIG.declare("differentiate_mode", ConfigValue(
- default="reverse_symbolic",
- domain=In(["reverse_symbolic", "sympy"]),
- description="differentiate mode to calculate jacobian."
- ))
- CONFIG.declare("linearize_inactive", ConfigValue(
- default=False,
- description="Add OA cuts for inactive constraints.",
- domain=bool
- ))
+ CONFIG = _get_GDPopt_config()
def available(self, exception_flag=True):
"""Check if solver is available.
@@ -288,11 +90,11 @@ def solve(self, model, **kwds):
config = self.CONFIG(kwds.pop('options', {}))
config.set_value(kwds)
- # configration confirmation
+ # configuration confirmation
if config.single_tree:
config.iteration_limit = 1
config.add_slack = False
- config.add_integer_cuts = False
+ config.add_nogood_cuts = False
config.mip_solver = 'cplex_persistent'
config.logger.info(
"Single tree implementation is activated. The defalt MIP solver is 'cplex_persistent'")
@@ -300,12 +102,36 @@ def solve(self, model, **kwds):
if config.max_slack == 0.0:
config.add_slack = False
+ if config.strategy == "GOA":
+ config.add_nogood_cuts = True
+ config.add_slack = True
+ config.use_mcpp = True
+ config.integer_to_binary = True
+ config.use_dual = False
+ config.use_fbbt = True
+
+ if config.nlp_solver == "baron":
+ config.use_dual = False
+ # if ecp tolerance is not provided use bound tolerance
+ if config.ecp_tolerance is None:
+ config.ecp_tolerance = config.bound_tolerance
+
+ # if the objective function is a constant, dual bound constraint is not added.
+ obj = next(model.component_data_objects(ctype=Objective, active=True))
+ if obj.expr.polynomial_degree() == 0:
+ config.use_dual_bound = False
+
solve_data = MindtPySolveData()
solve_data.results = SolverResults()
solve_data.timing = Container()
solve_data.curr_int_sol = []
solve_data.prev_int_sol = []
+ if config.use_fbbt:
+ fbbt(model)
+ config.logger.info(
+ "Use the fbbt to tighten the bounds of variables")
+
solve_data.original_model = model
solve_data.working_model = model.clone()
if config.integer_to_binary:
@@ -320,7 +146,7 @@ def solve(self, model, **kwds):
MindtPy = solve_data.working_model.MindtPy_utils
setup_results_object(solve_data, config)
- process_objective(solve_data, config, use_mcpp=False)
+ process_objective(solve_data, config, use_mcpp=config.use_mcpp)
# Save model initial values.
solve_data.initial_var_values = list(
@@ -329,6 +155,7 @@ def solve(self, model, **kwds):
# Store the initial model state as the best solution found. If we
# find no better solution, then we will restore from this copy.
solve_data.best_solution_found = None
+ solve_data.best_solution_found_time = None
# Record solver name
solve_data.results.solver.name = 'MindtPy' + str(config.strategy)
@@ -373,6 +200,10 @@ def solve(self, model, **kwds):
solve_data.UB = float('inf')
solve_data.LB_progress = [solve_data.LB]
solve_data.UB_progress = [solve_data.UB]
+ if config.single_tree and config.add_nogood_cuts:
+ solve_data.stored_bound = {}
+ if config.strategy == 'GOA' and config.add_nogood_cuts:
+ solve_data.num_no_good_cuts_added = {}
# Set of NLP iterations for which cuts were generated
lin.nlp_iters = Set(dimen=1)
@@ -400,12 +231,13 @@ def solve(self, model, **kwds):
# iteration or not
solve_data.solution_improved = False
- if not hasattr(solve_data.working_model, 'ipopt_zL_out'):
- solve_data.working_model.ipopt_zL_out = Suffix(
- direction=Suffix.IMPORT)
- if not hasattr(solve_data.working_model, 'ipopt_zU_out'):
- solve_data.working_model.ipopt_zU_out = Suffix(
- direction=Suffix.IMPORT)
+ if config.nlp_solver == 'ipopt':
+ if not hasattr(solve_data.working_model, 'ipopt_zL_out'):
+ solve_data.working_model.ipopt_zL_out = Suffix(
+ direction=Suffix.IMPORT)
+ if not hasattr(solve_data.working_model, 'ipopt_zU_out'):
+ solve_data.working_model.ipopt_zU_out = Suffix(
+ direction=Suffix.IMPORT)
# Initialize the master problem
with time_code(solve_data.timing, 'initialization'):
@@ -436,6 +268,7 @@ def solve(self, model, **kwds):
solve_data.results.solver.wallclock_time = solve_data.timing.total
solve_data.results.solver.iterations = solve_data.mip_iter
+ solve_data.results.solver.best_solution_found_time = solve_data.best_solution_found_time
if config.single_tree:
solve_data.results.solver.num_nodes = solve_data.nlp_iter - \
diff --git a/pyomo/contrib/mindtpy/config_options.py b/pyomo/contrib/mindtpy/config_options.py
new file mode 100644
index 00000000000..c5440775898
--- /dev/null
+++ b/pyomo/contrib/mindtpy/config_options.py
@@ -0,0 +1,251 @@
+from pyomo.common.config import (
+ ConfigBlock, ConfigValue, In, PositiveFloat, PositiveInt, NonNegativeInt)
+from pyomo.contrib.gdpopt.util import _DoNothing, a_logger
+
+
+def _get_GDPopt_config():
+ CONFIG = ConfigBlock("MindtPy")
+ CONFIG.declare("bound_tolerance", ConfigValue(
+ default=1E-4,
+ domain=PositiveFloat,
+ description="Bound tolerance",
+ doc="Relative tolerance for bound feasibility checks."
+ ))
+ CONFIG.declare("iteration_limit", ConfigValue(
+ default=50,
+ domain=PositiveInt,
+ description="Iteration limit",
+ doc="Number of maximum iterations in the decomposition methods."
+ ))
+ CONFIG.declare("stalling_limit", ConfigValue(
+ default=15,
+ domain=PositiveInt,
+ description="Stalling limit",
+ doc="Stalling limit for progress in the decomposition methods."
+ ))
+ CONFIG.declare("time_limit", ConfigValue(
+ default=600,
+ domain=PositiveInt,
+ description="Time limit (seconds, default=600)",
+ doc="Seconds allowed until terminated. Note that the time limit can"
+ "currently only be enforced between subsolver invocations. You may"
+ "need to set subsolver time limits as well."
+ ))
+ CONFIG.declare("strategy", ConfigValue(
+ default="OA",
+ domain=In(["OA", "GBD", "ECP", "PSC", "GOA"]),
+ description="Decomposition strategy",
+ doc="MINLP Decomposition strategy to be applied to the method. "
+ "Currently available Outer Approximation (OA), Extended Cutting "
+ "Plane (ECP), Partial Surrogate Cuts (PSC), and Generalized "
+ "Benders Decomposition (GBD)."
+ ))
+ CONFIG.declare("init_strategy", ConfigValue(
+ default=None,
+ domain=In(["rNLP", "initial_binary", "max_binary"]),
+ description="Initialization strategy",
+ doc="Initialization strategy used by any method. Currently the "
+ "continuous relaxation of the MINLP (rNLP), solve a maximal "
+ "covering problem (max_binary), and fix the initial value for "
+ "the integer variables (initial_binary)."
+ ))
+ CONFIG.declare("max_slack", ConfigValue(
+ default=1000.0,
+ domain=PositiveFloat,
+ description="Maximum slack variable",
+ doc="Maximum slack variable value allowed for the Outer Approximation "
+ "cuts."
+ ))
+ CONFIG.declare("OA_penalty_factor", ConfigValue(
+ default=1000.0,
+ domain=PositiveFloat,
+ description="Outer Approximation slack penalty factor",
+ doc="In the objective function of the Outer Approximation method, the "
+ "slack variables corresponding to all the constraints get "
+ "multiplied by this number and added to the objective."
+ ))
+ CONFIG.declare("ecp_tolerance", ConfigValue(
+ default=None,
+ domain=PositiveFloat,
+ description="ECP tolerance",
+ doc="Feasibility tolerance used to determine the stopping criterion in"
+ "the ECP method. As long as nonlinear constraint are violated for "
+ "more than this tolerance, the method will keep iterating."
+ ))
+ CONFIG.declare("nlp_solver", ConfigValue(
+ default="ipopt",
+ domain=In(["ipopt", "gams", "baron"]),
+ description="NLP subsolver name",
+ doc="Which NLP subsolver is going to be used for solving the nonlinear"
+ "subproblems."
+ ))
+ CONFIG.declare("nlp_solver_args", ConfigBlock(
+ implicit=True,
+ description="NLP subsolver options",
+ doc="Which NLP subsolver options to be passed to the solver while "
+ "solving the nonlinear subproblems."
+ ))
+ CONFIG.declare("mip_solver", ConfigValue(
+ default="glpk",
+ domain=In(["gurobi", "cplex", "cbc", "glpk", "gams",
+ "gurobi_persistent", "cplex_persistent"]),
+ description="MIP subsolver name",
+ doc="Which MIP subsolver is going to be used for solving the mixed-"
+ "integer master problems."
+ ))
+ CONFIG.declare("mip_solver_args", ConfigBlock(
+ implicit=True,
+ description="MIP subsolver options",
+ doc="Which MIP subsolver options to be passed to the solver while "
+ "solving the mixed-integer master problems."
+ ))
+ CONFIG.declare("call_after_master_solve", ConfigValue(
+ default=_DoNothing(),
+ domain=None,
+ description="Function to be executed after every master problem",
+ doc="Callback hook after a solution of the master problem."
+ ))
+ CONFIG.declare("call_after_subproblem_solve", ConfigValue(
+ default=_DoNothing(),
+ domain=None,
+ description="Function to be executed after every subproblem",
+ doc="Callback hook after a solution of the nonlinear subproblem."
+ ))
+ CONFIG.declare("call_after_subproblem_feasible", ConfigValue(
+ default=_DoNothing(),
+ domain=None,
+ description="Function to be executed after every feasible subproblem",
+ doc="Callback hook after a feasible solution"
+ " of the nonlinear subproblem."
+ ))
+ CONFIG.declare("tee", ConfigValue(
+ default=False,
+ description="Stream output to terminal.",
+ domain=bool
+ ))
+ CONFIG.declare("solver_tee", ConfigValue(
+ default=False,
+ description="Stream the output of mip solver and nlp solver to terminal.",
+ domain=bool
+ ))
+ CONFIG.declare("logger", ConfigValue(
+ default='pyomo.contrib.mindtpy',
+ description="The logger object or name to use for reporting.",
+ domain=a_logger
+ ))
+ CONFIG.declare("small_dual_tolerance", ConfigValue(
+ default=1E-8,
+ description="When generating cuts, small duals multiplied "
+ "by expressions can cause problems. Exclude all duals "
+ "smaller in absolute value than the following."
+ ))
+ CONFIG.declare("integer_tolerance", ConfigValue(
+ default=1E-5,
+ description="Tolerance on integral values."
+ ))
+ CONFIG.declare("constraint_tolerance", ConfigValue(
+ default=1E-6,
+ description="Tolerance on constraint satisfaction."
+ ))
+ CONFIG.declare("variable_tolerance", ConfigValue(
+ default=1E-8,
+ description="Tolerance on variable bounds."
+ ))
+ CONFIG.declare("zero_tolerance", ConfigValue(
+ default=1E-7,
+ description="Tolerance on variable equal to zero."
+ ))
+ CONFIG.declare("initial_feas", ConfigValue(
+ default=True,
+ description="Apply an initial feasibility step.",
+ domain=bool
+ ))
+ CONFIG.declare("obj_bound", ConfigValue(
+ default=1E15,
+ domain=PositiveFloat,
+ description="Bound applied to the linearization of the objective function if master MILP is unbounded."
+ ))
+ CONFIG.declare("integer_to_binary", ConfigValue(
+ default=False,
+ description="Convert integer variables to binaries (for integer cuts).",
+ domain=bool
+ ))
+ CONFIG.declare("add_nogood_cuts", ConfigValue(
+ default=False,
+ description="Add integer cuts (no-good cuts) to binary variables to disallow same integer solution again."
+ "Note that 'integer_to_binary' flag needs to be used to apply it to actual integers and not just binaries.",
+ domain=bool
+ ))
+ CONFIG.declare("single_tree", ConfigValue(
+ default=False,
+ description="Use single tree implementation in solving the MILP master problem.",
+ domain=bool
+ ))
+ CONFIG.declare("solution_pool", ConfigValue(
+ default=False,
+ description="Use solution pool in solving the MILP master problem.",
+ domain=bool
+ ))
+ CONFIG.declare("add_slack", ConfigValue(
+ default=False,
+ description="whether add slack variable here."
+ "slack variables here are used to deal with nonconvex MINLP.",
+ domain=bool
+ ))
+ CONFIG.declare("continuous_var_bound", ConfigValue(
+ default=1e10,
+ description="default bound added to unbounded continuous variables in nonlinear constraint if single tree is activated.",
+ domain=PositiveFloat
+ ))
+ CONFIG.declare("integer_var_bound", ConfigValue(
+ default=1e9,
+ description="default bound added to unbounded integral variables in nonlinear constraint if single tree is activated.",
+ domain=PositiveFloat
+ ))
+ CONFIG.declare("cycling_check", ConfigValue(
+ default=True,
+ description="check if OA algorithm is stalled in a cycle and terminate.",
+ domain=bool
+ ))
+ CONFIG.declare("feasibility_norm", ConfigValue(
+ default="L_infinity",
+ domain=In(["L1", "L2", "L_infinity"]),
+ description="different forms of objective function in feasibility subproblem."
+ ))
+ CONFIG.declare("differentiate_mode", ConfigValue(
+ default="reverse_symbolic",
+ domain=In(["reverse_symbolic", "sympy"]),
+ description="differentiate mode to calculate jacobian."
+ ))
+ CONFIG.declare("linearize_inactive", ConfigValue(
+ default=False,
+ description="Add OA cuts for inactive constraints.",
+ domain=bool
+ ))
+ CONFIG.declare("use_mcpp", ConfigValue(
+ default=False,
+ description="use package MC++ to set a bound for variable 'objective_value', which is introduced when the original problem's objective function is nonlinear.",
+ domain=bool
+ ))
+ CONFIG.declare("use_dual", ConfigValue(
+ default=True,
+ description="use dual solution from the nlp solver to add OA cuts for equality constraints.",
+ domain=bool
+ ))
+ CONFIG.declare("use_fbbt", ConfigValue(
+ default=False,
+ description="use fbbt to tighten the feasible region of the problem",
+ domain=bool
+ ))
+ CONFIG.declare("threads", ConfigValue(
+ default=0,
+ domain=NonNegativeInt,
+ description="Threads",
+ doc="Threads used by milp solver and nlp solver."
+ ))
+ CONFIG.declare("use_dual_bound", ConfigValue(
+ default=True,
+ description="add dual bound constraint to enforce the objective function should improve on the best found dual bound",
+ domain=bool
+ ))
+ return CONFIG
diff --git a/pyomo/contrib/mindtpy/cut_generation.py b/pyomo/contrib/mindtpy/cut_generation.py
index 867365a9247..e814dd2da6a 100644
--- a/pyomo/contrib/mindtpy/cut_generation.py
+++ b/pyomo/contrib/mindtpy/cut_generation.py
@@ -1,20 +1,37 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Cut generation."""
from __future__ import division
-
+import logging
from math import copysign
-from pyomo.core import Constraint, minimize, value
+from pyomo.core import minimize, value, Block, ConstraintList
from pyomo.core.expr import current as EXPR
-from pyomo.contrib.gdpopt.util import copy_var_list_values, identify_variables
-from pyomo.core.expr.taylor_series import taylor_series_expansion
-from pyomo.core.expr import differentiate
+from pyomo.contrib.gdpopt.util import identify_variables
+from pyomo.contrib.mcpp.pyomo_mcpp import McCormick as mc, MCPP_Error
+logger = logging.getLogger('pyomo.contrib.mindtpy')
-def add_objective_linearization(solve_data, config):
- """Adds initial linearized objective in case it is nonlinear.
-
- This should be done for initializing the ECP method.
+def add_objective_linearization(solve_data, config):
+ """
+ If objective is nonlinear, then this function adds a linearized objective. This function should be used to
+ initialize the ECP method.
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
"""
m = solve_data.working_model
MindtPy = m.MindtPy_utils
@@ -23,6 +40,7 @@ def add_objective_linearization(solve_data, config):
if obj is MindtPy.MindtPy_objective_expr)
MindtPy.MindtPy_linear_cuts.mip_iters.add(solve_data.mip_iter)
sign_adjust = 1 if MindtPy.obj.sense == minimize else -1
+
# generate new constraints
# TODO some kind of special handling if the dual is phenomenally small?
for obj in gen:
@@ -34,13 +52,31 @@ def add_objective_linearization(solve_data, config):
MindtPy.ECP_constr_map[obj, solve_data.mip_iter] = c
+'''
def add_oa_cuts(target_model, dual_values, solve_data, config,
linearize_active=True,
linearize_violated=True):
- """Linearizes nonlinear constraints.
+ """
+ Linearizes nonlinear constraints; modifies the model to include the OA cuts
For nonconvex problems, turn on 'config.add_slack'. Slack variables will
always be used for nonlinear equality constraints.
+
+ Parameters
+ ----------
+ target_model:
+ this is the MIP/MILP model for the OA algorithm; we want to add the OA cuts to 'target_model'
+ dual_values:
+ contains the value of the duals for each constraint
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ linearize_active: bool, optional
+ this parameter acts as a Boolean flag that signals whether the linearized constraint is active
+ linearize_violated: bool, optional
+ this parameter acts as a Boolean flag that signals whether the nonlinear constraint represented by the
+ linearized constraint has been violated
"""
for (constr, dual_value) in zip(target_model.MindtPy_utils.constraint_list,
dual_values):
@@ -63,6 +99,80 @@ def add_oa_cuts(target_model, dual_values, solve_data, config,
+ value(constr.body) - rhs)
- (slack_var if config.add_slack else 0) <= 0)
+ else: # Inequality constraint (possibly two-sided)
+ if constr.has_ub() \
+ and (linearize_active and abs(constr.uslack()) < config.bound_tolerance) \
+ or (linearize_violated and constr.uslack() < 0) \
+ or (config.linearize_inactive and constr.uslack() > 0):
+ if config.add_slack:
+ slack_var = target_model.MindtPy_utils.MindtPy_linear_cuts.slack_vars.add()
+
+ target_model.MindtPy_utils.MindtPy_linear_cuts.oa_cuts.add(
+ expr=(sum(value(jacs[constr][var])*(var - var.value)
+ for var in constr_vars) + value(constr.body)
+ - (slack_var if config.add_slack else 0)
+ <= constr.upper)
+ )
+
+ if constr.has_lb() \
+ and (linearize_active and abs(constr.lslack()) < config.bound_tolerance) \
+ or (linearize_violated and constr.lslack() < 0) \
+ or (config.linearize_inactive and constr.lslack() > 0):
+ if config.add_slack:
+ slack_var = target_model.MindtPy_utils.MindtPy_linear_cuts.slack_vars.add()
+
+ target_model.MindtPy_utils.MindtPy_linear_cuts.oa_cuts.add(
+ expr=(sum(value(jacs[constr][var])*(var - var.value)
+ for var in constr_vars) + value(constr.body)
+ + (slack_var if config.add_slack else 0)
+ >= constr.lower)
+ )
+'''
+
+
+def add_oa_cuts(target_model, dual_values, solve_data, config,
+ linearize_active=True,
+ linearize_violated=True):
+ """
+ Linearizes nonlinear constraints; modifies the model to include the OA cuts
+ For nonconvex problems, turn on 'config.add_slack'. Slack variables will
+ always be used for nonlinear equality constraints.
+ Parameters
+ ----------
+ target_model:
+ this is the MIP/MILP model for the OA algorithm; we want to add the OA cuts to 'target_model'
+ dual_values:
+ contains the value of the duals for each constraint
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ linearize_active: bool, optional
+ this parameter acts as a Boolean flag that signals whether the linearized constraint is active
+ linearize_violated: bool, optional
+ this parameter acts as a Boolean flag that signals whether the nonlinear constraint represented by the
+ linearized constraint has been violated
+ """
+ for index, constr in enumerate(target_model.MindtPy_utils.constraint_list):
+ if constr.body.polynomial_degree() in (0, 1):
+ continue
+
+ constr_vars = list(identify_variables(constr.body))
+ jacs = solve_data.jacobians
+
+ # Equality constraint (makes the problem nonconvex)
+ if constr.has_ub() and constr.has_lb() and constr.upper == constr.lower and config.use_dual:
+ sign_adjust = -1 if solve_data.objective_sense == minimize else 1
+ rhs = constr.lower
+ if config.add_slack:
+ slack_var = target_model.MindtPy_utils.MindtPy_linear_cuts.slack_vars.add()
+ target_model.MindtPy_utils.MindtPy_linear_cuts.oa_cuts.add(
+ expr=copysign(1, sign_adjust * dual_values[index])
+ * (sum(value(jacs[constr][var]) * (var - value(var))
+ for var in list(EXPR.identify_variables(constr.body)))
+ + value(constr.body) - rhs)
+ - (slack_var if config.add_slack else 0) <= 0)
+
else: # Inequality constraint (possibly two-sided)
if constr.has_ub() \
and (linearize_active and abs(constr.uslack()) < config.zero_tolerance) \
@@ -92,6 +202,91 @@ def add_oa_cuts(target_model, dual_values, solve_data, config,
>= constr.lower)
)
+
+def add_ecp_cuts(target_model, solve_data, config,
+ linearize_active=True,
+ linearize_violated=True):
+ """
+ Linearizes nonlinear constraints. Adds the cuts for the ECP method.
+
+ For nonconvex problems, turn on 'config.add_slack'. Slack variables will
+ always be used for nonlinear equality constraints.
+
+ Parameters
+ ----------
+ target_model:
+ this is the MIP/MILP model for the OA algorithm; we want to add the OA cuts to 'target_model'
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ linearize_active: bool, optional
+ this parameter acts as a Boolean flag that signals whether the linearized constraint is active
+ linearize_violated: bool, optional
+ this parameter acts as a Boolean flag that signals whether the nonlinear constraint represented by the
+ linearized constraint has been violated
+ """
+ for constr in target_model.MindtPy_utils.constraint_list:
+
+ if constr.body.polynomial_degree() in (0, 1):
+ continue
+
+ constr_vars = list(identify_variables(constr.body))
+ jacs = solve_data.jacobians
+
+ if constr.has_lb() and constr.has_ub():
+ config.logger.warning(
+ 'constraint {} has both a lower '
+ 'and upper bound.'
+ '\n'.format(
+ constr))
+ continue
+ if constr.has_ub():
+ try:
+ upper_slack = constr.uslack()
+ except (ValueError, OverflowError):
+ config.logger.warning(
+ 'constraint {} has caused either a '
+ 'ValueError or OverflowError.'
+ '\n'.format(
+ constr))
+ continue
+ if (linearize_active and abs(upper_slack) < config.ecp_tolerance) \
+ or (linearize_violated and upper_slack < 0) \
+ or (config.linearize_inactive and upper_slack > 0):
+ if config.add_slack:
+ slack_var = target_model.MindtPy_utils.MindtPy_linear_cuts.slack_vars.add()
+
+ target_model.MindtPy_utils.MindtPy_linear_cuts.ecp_cuts.add(
+ expr=(sum(value(jacs[constr][var])*(var - var.value)
+ for var in constr_vars)
+ - (slack_var if config.add_slack else 0)
+ <= upper_slack)
+ )
+
+ if constr.has_lb():
+ try:
+ lower_slack = constr.lslack()
+ except (ValueError, OverflowError):
+ config.logger.warning(
+ 'constraint {} has caused either a '
+ 'ValueError or OverflowError.'
+ '\n'.format(
+ constr))
+ continue
+ if (linearize_active and abs(lower_slack) < config.ecp_tolerance) \
+ or (linearize_violated and lower_slack < 0) \
+ or (config.linearize_inactive and lower_slack > 0):
+ if config.add_slack:
+ slack_var = target_model.MindtPy_utils.MindtPy_linear_cuts.slack_vars.add()
+
+ target_model.MindtPy_utils.MindtPy_linear_cuts.ecp_cuts.add(
+ expr=(sum(value(jacs[constr][var])*(var - var.value)
+ for var in constr_vars)
+ + (slack_var if config.add_slack else 0)
+ >= -lower_slack)
+ )
+
# def add_oa_equality_relaxation(var_values, duals, solve_data, config, ignore_integrality=False):
# """More general case for outer approximation
@@ -144,11 +339,25 @@ def add_oa_cuts(target_model, dual_values, solve_data, config,
# - slack_var <= 0)
-def add_int_cut(var_values, solve_data, config, feasible=False):
- if not config.add_integer_cuts:
+def add_nogood_cuts(var_values, solve_data, config, feasible=False):
+ """
+ Adds integer cuts; modifies the model to include integer cuts
+
+ Parameters
+ ----------
+ var_values: list
+ values of the current variables, used to generate the cut
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ feasible: bool, optional
+ boolean indicating if integer combination yields a feasible or infeasible NLP
+ """
+ if not config.add_nogood_cuts:
return
- config.logger.info("Adding integer cuts")
+ config.logger.info("Adding nogood cuts")
m = solve_data.mip
MindtPy = m.MindtPy_utils
@@ -168,7 +377,7 @@ def add_int_cut(var_values, solve_data, config, feasible=False):
raise ValueError('Binary {} = {} is not 0 or 1'.format(
v.name, value(v)))
- if not binary_vars: # if no binary variables, skip.
+ if not binary_vars: # if no binary variables, skip
return
int_cut = (sum(1 - v for v in binary_vars
@@ -178,9 +387,91 @@ def add_int_cut(var_values, solve_data, config, feasible=False):
MindtPy.MindtPy_linear_cuts.integer_cuts.add(expr=int_cut)
- # TODO need to handle theoretical implications of backtracking
- # if not feasible:
- # # Add the integer cut
- # MindtPy.MindtPy_linear_cuts.integer_cuts.add(expr=int_cut)
- # else:
- # MindtPy.MindtPy_linear_cuts.feasible_integer_cuts.add(expr=int_cut)
+
+def add_affine_cuts(solve_data, config):
+ """
+ Adds affine cuts using MCPP; modifies the model to include affine cuts
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
+
+ m = solve_data.mip
+ config.logger.info("Adding affine cuts")
+ counter = 0
+
+ for constr in m.MindtPy_utils.constraint_list:
+ if constr.body.polynomial_degree() in (1, 0):
+ continue
+
+ vars_in_constr = list(
+ identify_variables(constr.body))
+ if any(var.value is None for var in vars_in_constr):
+ continue # a variable has no values
+
+ # mcpp stuff
+ try:
+ mc_eqn = mc(constr.body)
+ except MCPP_Error as e:
+ config.logger.debug(
+ "Skipping constraint %s due to MCPP error %s" % (constr.name, str(e)))
+ continue # skip to the next constraint
+
+ ccSlope = mc_eqn.subcc()
+ cvSlope = mc_eqn.subcv()
+ ccStart = mc_eqn.concave()
+ cvStart = mc_eqn.convex()
+
+ # check if the value of ccSlope and cvSlope is not Nan or inf. If so, we skip this.
+ concave_cut_valid = True
+ convex_cut_valid = True
+ for var in vars_in_constr:
+ if not var.fixed:
+ if ccSlope[var] == float('nan') or ccSlope[var] == float('inf'):
+ concave_cut_valid = False
+ if cvSlope[var] == float('nan') or cvSlope[var] == float('inf'):
+ convex_cut_valid = False
+ # check if the value of ccSlope and cvSlope all equals zero. if so, we skip this.
+ if not any(list(ccSlope.values())):
+ concave_cut_valid = False
+ if not any(list(cvSlope.values())):
+ convex_cut_valid = False
+ if ccStart == float('nan') or ccStart == float('inf'):
+ concave_cut_valid = False
+ if cvStart == float('nan') or cvStart == float('inf'):
+ convex_cut_valid = False
+ if (concave_cut_valid or convex_cut_valid) is False:
+ continue
+
+ ub_int = min(constr.upper, mc_eqn.upper()
+ ) if constr.has_ub() else mc_eqn.upper()
+ lb_int = max(constr.lower, mc_eqn.lower()
+ ) if constr.has_lb() else mc_eqn.lower()
+
+ parent_block = constr.parent_block()
+ # Create a block on which to put outer approximation cuts.
+ # TODO: create it at the beginning.
+ aff_utils = parent_block.component('MindtPy_aff')
+ if aff_utils is None:
+ aff_utils = parent_block.MindtPy_aff = Block(
+ doc="Block holding affine constraints")
+ aff_utils.MindtPy_aff_cons = ConstraintList()
+ aff_cuts = aff_utils.MindtPy_aff_cons
+ if concave_cut_valid:
+ concave_cut = sum(ccSlope[var] * (var - var.value)
+ for var in vars_in_constr
+ if not var.fixed) + ccStart >= lb_int
+ aff_cuts.add(expr=concave_cut)
+ counter += 1
+ if convex_cut_valid:
+ convex_cut = sum(cvSlope[var] * (var - var.value)
+ for var in vars_in_constr
+ if not var.fixed) + cvStart <= ub_int
+ aff_cuts.add(expr=convex_cut)
+ counter += 1
+
+ config.logger.info("Added %s affine cuts" % counter)
diff --git a/pyomo/contrib/mindtpy/initialization.py b/pyomo/contrib/mindtpy/initialization.py
index 3c02bf3b465..82187eee03c 100644
--- a/pyomo/contrib/mindtpy/initialization.py
+++ b/pyomo/contrib/mindtpy/initialization.py
@@ -1,27 +1,50 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Initialization functions."""
from __future__ import division
-
-from pyomo.contrib.gdpopt.util import SuppressInfeasibleWarning, _DoNothing, copy_var_list_values
-from pyomo.contrib.mindtpy.cut_generation import (
- add_oa_cuts, add_objective_linearization,
-)
+import logging
+from pyomo.contrib.gdpopt.util import (SuppressInfeasibleWarning, _DoNothing,
+ copy_var_list_values,
+ get_main_elapsed_time)
+from pyomo.contrib.mindtpy.cut_generation import (add_oa_cuts,
+ add_affine_cuts)
from pyomo.contrib.mindtpy.nlp_solve import solve_NLP_subproblem
from pyomo.contrib.mindtpy.util import (calc_jacobians)
from pyomo.core import (ConstraintList, Objective,
- TransformationFactory, maximize, minimize, value, Var)
-from pyomo.opt import TerminationCondition as tc
-from pyomo.opt import SolverFactory
+ TransformationFactory, maximize, minimize,
+ value, Var,)
+from pyomo.opt import SolverFactory, TerminationCondition as tc
from pyomo.solvers.plugins.solvers.persistent_solver import PersistentSolver
-from pyomo.contrib.mindtpy.nlp_solve import (solve_NLP_subproblem,
- handle_NLP_subproblem_optimal, handle_NLP_subproblem_infeasible,
+from pyomo.contrib.mindtpy.nlp_solve import (handle_NLP_subproblem_optimal,
+ handle_NLP_subproblem_infeasible,
handle_NLP_subproblem_other_termination)
from pyomo.contrib.mindtpy.util import var_bound_add
+import math
+
+logger = logging.getLogger('pyomo.contrib.mindtpy')
def MindtPy_initialize_master(solve_data, config):
- """Initialize the decomposition algorithm.
- This includes generating the initial cuts require to build the master
- problem.
+ """
+ Initializes the decomposition algorithm and creates the master MIP/MILP problem.
+
+ This function initializes the decomposition problem, which includes generating the initial cuts required to
+ build the master MIP/MILP
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
"""
# if single tree is activated, we need to add bounds for unbounded variables in nonlinear constraints to avoid unbounded master problem.
if config.single_tree:
@@ -29,16 +52,17 @@ def MindtPy_initialize_master(solve_data, config):
m = solve_data.mip = solve_data.working_model.clone()
MindtPy = m.MindtPy_utils
- m.dual.deactivate()
+ if config.use_dual:
+ m.dual.deactivate()
if config.strategy == 'OA':
calc_jacobians(solve_data, config) # preload jacobians
MindtPy.MindtPy_linear_cuts.oa_cuts = ConstraintList(
doc='Outer approximation cuts')
- # elif config.strategy == 'ECP':
- # calc_jacobians(solve_data, config) # preload jacobians
- # MindtPy.MindtPy_linear_cuts.ecp_cuts = ConstraintList(
- # doc='Extended Cutting Planes')
+ elif config.strategy == 'ECP':
+ calc_jacobians(solve_data, config) # preload jacobians
+ MindtPy.MindtPy_linear_cuts.ecp_cuts = ConstraintList(
+ doc='Extended Cutting Planes')
# elif config.strategy == 'PSC':
# detect_nonlinear_vars(solve_data, config)
# MindtPy.MindtPy_linear_cuts.psc_cuts = ConstraintList(
@@ -49,59 +73,86 @@ def MindtPy_initialize_master(solve_data, config):
# Set default initialization_strategy
if config.init_strategy is None:
- if config.strategy == 'OA':
+ if config.strategy in {'OA', 'GOA'}:
config.init_strategy = 'rNLP'
else:
config.init_strategy = 'max_binary'
+
+ config.logger.info(
+ '{} is the initial strategy being used.'
+ '\n'.format(
+ config.init_strategy))
# Do the initialization
- elif config.init_strategy == 'rNLP':
+ if config.init_strategy == 'rNLP':
init_rNLP(solve_data, config)
elif config.init_strategy == 'max_binary':
init_max_binaries(solve_data, config)
- # if config.strategy == 'ECP':
- # add_ecp_cut(solve_data, config)
- # else:
-
- fixed_nlp, fixed_nlp_result = solve_NLP_subproblem(solve_data, config)
- if fixed_nlp_result.solver.termination_condition is tc.optimal or fixed_nlp_result.solver.termination_condition is tc.locallyOptimal:
- handle_NLP_subproblem_optimal(fixed_nlp, solve_data, config)
- elif fixed_nlp_result.solver.termination_condition is tc.infeasible:
- handle_NLP_subproblem_infeasible(fixed_nlp, solve_data, config)
- else:
- handle_NLP_subproblem_other_termination(fixed_nlp, fixed_nlp_result.solver.termination_condition,
- solve_data, config)
+ elif config.init_strategy == 'initial_binary':
+ if config.strategy != 'ECP':
+ fixed_nlp, fixed_nlp_result = solve_NLP_subproblem(
+ solve_data, config)
+ if fixed_nlp_result.solver.termination_condition in {tc.optimal, tc.locallyOptimal, tc.feasible}:
+ handle_NLP_subproblem_optimal(fixed_nlp, solve_data, config)
+ elif fixed_nlp_result.solver.termination_condition is tc.infeasible:
+ handle_NLP_subproblem_infeasible(fixed_nlp, solve_data, config)
+ else:
+ handle_NLP_subproblem_other_termination(fixed_nlp, fixed_nlp_result.solver.termination_condition,
+ solve_data, config)
def init_rNLP(solve_data, config):
- """Initialize by solving the rNLP (relaxed binary variables)."""
+ """
+ Initialize the problem by solving the relaxed NLP (fixed binary variables) and then store the optimal variable
+ values obtained from solving the rNLP
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
solve_data.nlp_iter += 1
m = solve_data.working_model.clone()
config.logger.info(
"NLP %s: Solve relaxed integrality" % (solve_data.nlp_iter,))
MindtPy = m.MindtPy_utils
TransformationFactory('core.relax_integer_vars').apply_to(m)
+ nlp_args = dict(config.nlp_solver_args)
+ elapsed = get_main_elapsed_time(solve_data.timing)
+ remaining = int(max(config.time_limit - elapsed, 1))
+ if config.nlp_solver == 'gams':
+ nlp_args['add_options'] = nlp_args.get('add_options', [])
+ nlp_args['add_options'].append('option reslim=%s;' % remaining)
with SuppressInfeasibleWarning():
results = SolverFactory(config.nlp_solver).solve(
- m, **config.nlp_solver_args)
+ m, tee=config.solver_tee, **nlp_args)
subprob_terminate_cond = results.solver.termination_condition
- if subprob_terminate_cond is tc.optimal or subprob_terminate_cond is tc.locallyOptimal:
+ if subprob_terminate_cond in {tc.optimal, tc.feasible, tc.locallyOptimal}:
+ if subprob_terminate_cond in {tc.feasible, tc.locallyOptimal}:
+ config.logger.info(
+ 'relaxed NLP is not solved to optimality.')
main_objective = next(m.component_data_objects(Objective, active=True))
nlp_solution_values = list(v.value for v in MindtPy.variable_list)
- dual_values = list(m.dual[c] for c in MindtPy.constraint_list)
+ dual_values = list(
+ m.dual[c] for c in MindtPy.constraint_list) if config.use_dual else None
# Add OA cut
- if main_objective.sense == minimize:
- solve_data.LB = value(main_objective.expr)
- else:
- solve_data.UB = value(main_objective.expr)
+ if main_objective.sense == minimize and not math.isnan(results['Problem'][0]['Lower bound']):
+ solve_data.LB = results['Problem'][0]['Lower bound']
+ elif not math.isnan(results['Problem'][0]['Upper bound']):
+ solve_data.UB = results['Problem'][0]['Upper bound']
config.logger.info(
'NLP %s: OBJ: %s LB: %s UB: %s'
% (solve_data.nlp_iter, value(main_objective.expr),
solve_data.LB, solve_data.UB))
- if config.strategy == 'OA':
+ if config.strategy in {'OA', 'GOA'}:
copy_var_list_values(m.MindtPy_utils.variable_list,
solve_data.mip.MindtPy_utils.variable_list,
config, ignore_integrality=True)
- add_oa_cuts(solve_data.mip, dual_values, solve_data, config)
+ if config.strategy == 'OA':
+ add_oa_cuts(solve_data.mip, dual_values, solve_data, config)
+ elif config.strategy == 'GOA':
+ add_affine_cuts(solve_data, config)
# TODO check if value of the binary or integer varibles is 0/1 or integer value.
for var in solve_data.mip.component_data_objects(ctype=Var):
if var.is_integer():
@@ -111,6 +162,12 @@ def init_rNLP(solve_data, config):
config.logger.info(
'Initial relaxed NLP problem is infeasible. '
'Problem may be infeasible.')
+ elif subprob_terminate_cond is tc.maxTimeLimit:
+ config.logger.info(
+ 'NLP subproblem failed to converge within time limit.')
+ elif subprob_terminate_cond is tc.maxIterations:
+ config.logger.info(
+ 'NLP subproblem failed to converge within iteration limit.')
else:
raise ValueError(
'MindtPy unable to handle relaxed NLP termination condition '
@@ -119,14 +176,22 @@ def init_rNLP(solve_data, config):
def init_max_binaries(solve_data, config):
- """Initialize by turning on as many binary variables as possible.
+ """
+ Modifies model by maximizing the number of activated binary variables
- The user would usually want to call _solve_NLP_subproblem after an
+ Note - The user would usually want to call solve_NLP_subproblem after an
invocation of this function.
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
"""
m = solve_data.working_model.clone()
- m.dual.deactivate()
+ if config.use_dual:
+ m.dual.deactivate()
MindtPy = m.MindtPy_utils
solve_data.mip_subiter += 1
config.logger.info(
@@ -150,10 +215,12 @@ def init_max_binaries(solve_data, config):
if isinstance(opt, PersistentSolver):
opt.set_instance(m)
mip_args = dict(config.mip_solver_args)
+ elapsed = get_main_elapsed_time(solve_data.timing)
+ remaining = int(max(config.time_limit - elapsed, 1))
if config.mip_solver == 'gams':
mip_args['add_options'] = mip_args.get('add_options', [])
- mip_args['add_options'].append('option optcr=0.0;')
- results = opt.solve(m, **mip_args)
+ mip_args['add_options'].append('option optcr=0.001;')
+ results = opt.solve(m, tee=config.solver_tee, **mip_args)
solve_terminate_cond = results.solver.termination_condition
if solve_terminate_cond is tc.optimal:
@@ -168,6 +235,12 @@ def init_max_binaries(solve_data, config):
'MILP master problem is infeasible. '
'Problem may have no more feasible '
'binary configurations.')
+ elif solve_terminate_cond is tc.maxTimeLimit:
+ config.logger.info(
+ 'NLP subproblem failed to converge within time limit.')
+ elif solve_terminate_cond is tc.maxIterations:
+ config.logger.info(
+ 'NLP subproblem failed to converge within iteration limit.')
else:
raise ValueError(
'MindtPy unable to handle MILP master termination condition '
diff --git a/pyomo/contrib/mindtpy/iterate.py b/pyomo/contrib/mindtpy/iterate.py
index 415bc813690..d7df09b3b8f 100644
--- a/pyomo/contrib/mindtpy/iterate.py
+++ b/pyomo/contrib/mindtpy/iterate.py
@@ -1,17 +1,52 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Iteration loop for MindtPy."""
from __future__ import division
+import logging
+from pyomo.contrib.mindtpy.cut_generation import add_ecp_cuts
from pyomo.contrib.mindtpy.mip_solve import (solve_OA_master,
- handle_master_mip_optimal, handle_master_mip_other_conditions)
+ handle_master_mip_optimal,
+ handle_master_mip_other_conditions,
+ handle_master_mip_infeasible)
+
from pyomo.contrib.mindtpy.nlp_solve import (solve_NLP_subproblem,
- handle_NLP_subproblem_optimal, handle_NLP_subproblem_infeasible,
+ handle_NLP_subproblem_optimal,
+ handle_NLP_subproblem_infeasible,
handle_NLP_subproblem_other_termination)
+
from pyomo.core import minimize, Objective, Var
+from pyomo.opt.results import ProblemSense
from pyomo.opt import TerminationCondition as tc
from pyomo.contrib.gdpopt.util import get_main_elapsed_time
+from pyomo.solvers.plugins.solvers.persistent_solver import PersistentSolver
+from pyomo.opt import SolverFactory
+
+logger = logging.getLogger('pyomo.contrib.mindtpy')
def MindtPy_iteration_loop(solve_data, config):
+ """
+ Main loop for MindtPy Algorithms
+
+ This is the outermost function for the algorithms in this package; this function controls the progression of
+ solving the model.
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
working_model = solve_data.working_model
main_objective = next(
working_model.component_data_objects(Objective, active=True))
@@ -21,33 +56,37 @@ def MindtPy_iteration_loop(solve_data, config):
'---MindtPy Master Iteration %s---'
% solve_data.mip_iter)
- if algorithm_should_terminate(solve_data, config, check_cycling=False):
- break
-
solve_data.mip_subiter = 0
# solve MILP master problem
- if config.strategy == 'OA':
+ if config.strategy in {'OA', 'GOA', 'ECP'}:
master_mip, master_mip_results = solve_OA_master(
solve_data, config)
- if master_mip_results.solver.termination_condition is tc.optimal:
- handle_master_mip_optimal(master_mip, solve_data, config)
- else:
- handle_master_mip_other_conditions(master_mip, master_mip_results,
- solve_data, config)
- # Call the MILP post-solve callback
- config.call_after_master_solve(master_mip, solve_data)
+ if config.single_tree is False:
+ if master_mip_results.solver.termination_condition is tc.optimal:
+ handle_master_mip_optimal(master_mip, solve_data, config)
+ elif master_mip_results.solver.termination_condition is tc.infeasible:
+ handle_master_mip_infeasible(
+ master_mip, solve_data, config)
+ last_iter_cuts = True
+ break
+ else:
+ handle_master_mip_other_conditions(master_mip, master_mip_results,
+ solve_data, config)
+ # Call the MILP post-solve callback
+ config.call_after_master_solve(master_mip, solve_data)
else:
raise NotImplementedError()
if algorithm_should_terminate(solve_data, config, check_cycling=True):
+ last_iter_cuts = False
break
- if config.single_tree is False: # if we don't use lazy callback, i.e. LP_NLP
+ if config.single_tree is False and config.strategy != 'ECP': # if we don't use lazy callback, i.e. LP_NLP
# Solve NLP subproblem
# The constraint linearization happens in the handlers
fixed_nlp, fixed_nlp_result = solve_NLP_subproblem(
solve_data, config)
- if fixed_nlp_result.solver.termination_condition is tc.optimal or fixed_nlp_result.solver.termination_condition is tc.locallyOptimal:
+ if fixed_nlp_result.solver.termination_condition in {tc.optimal, tc.locallyOptimal, tc.feasible}:
handle_NLP_subproblem_optimal(fixed_nlp, solve_data, config)
elif fixed_nlp_result.solver.termination_condition is tc.infeasible:
handle_NLP_subproblem_infeasible(fixed_nlp, solve_data, config)
@@ -57,6 +96,13 @@ def MindtPy_iteration_loop(solve_data, config):
# Call the NLP post-solve callback
config.call_after_subproblem_solve(fixed_nlp, solve_data)
+ if algorithm_should_terminate(solve_data, config, check_cycling=False):
+ last_iter_cuts = True
+ break
+
+ if config.strategy == 'ECP':
+ add_ecp_cuts(solve_data.mip, solve_data, config)
+
# if config.strategy == 'PSC':
# # If the hybrid algorithm is not making progress, switch to OA.
# progress_required = 1E-6
@@ -92,15 +138,35 @@ def MindtPy_iteration_loop(solve_data, config):
# 'Switching to OA.'.format(max_nonimprove_iter))
# config.strategy = 'OA'
+ # if add_nogood_cuts is True, the bound obtained in the last iteration is no reliable.
+ # we correct it after the iteration.
+ if config.add_nogood_cuts:
+ bound_fix(solve_data, config, last_iter_cuts)
+
def algorithm_should_terminate(solve_data, config, check_cycling):
- """Check if the algorithm should terminate.
+ """
+ Checks if the algorithm should terminate at the given point
- Termination conditions based on solver options and progress.
- Sets the solve_data.results.solver.termination_condition to the appropriate
- condition, i.e. optimal, maxIterations, maxTimeLimit
+ This function determines whether the algorithm should terminate based on the solver options and progress.
+ (Sets the solve_data.results.solver.termination_condition to the appropriate condition, i.e. optimal,
+ maxIterations, maxTimeLimit)
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ check_cycling: bool
+ check for a special case that causes a binary variable to loop through the same values
+
+ Returns
+ -------
+ boolean
+ True if the algorithm should terminate else returns False
"""
+
# Check bound convergence
if solve_data.LB + config.bound_tolerance >= solve_data.UB:
config.logger.info(
@@ -118,7 +184,10 @@ def algorithm_should_terminate(solve_data, config, check_cycling):
config.logger.info(
'Final bound values: LB: {} UB: {}'.
format(solve_data.LB, solve_data.UB))
- solve_data.results.solver.termination_condition = tc.maxIterations
+ if config.single_tree:
+ solve_data.results.solver.termination_condition = tc.feasible
+ else:
+ solve_data.results.solver.termination_condition = tc.maxIterations
return True
# Check time limit
@@ -134,8 +203,72 @@ def algorithm_should_terminate(solve_data, config, check_cycling):
solve_data.results.solver.termination_condition = tc.maxTimeLimit
return True
+ # Check if algorithm is stalling
+ if len(solve_data.LB_progress) >= config.stalling_limit:
+ if abs(solve_data.LB_progress[-1] - solve_data.LB_progress[-config.stalling_limit]) <= config.zero_tolerance:
+ config.logger.info(
+ 'Algorithm is not making enough progress. '
+ 'Exiting iteration loop.')
+ config.logger.info(
+ 'Final bound values: LB: {} UB: {}'.
+ format(solve_data.LB, solve_data.UB))
+ if solve_data.best_solution_found is not None:
+ solve_data.results.solver.termination_condition = tc.feasible
+ else:
+ solve_data.best_solution_found = solve_data.working_model.clone()
+ config.logger.warning(
+ 'Algorithm did not find a feasible solution. '
+ 'Returning best bound solution. Consider increasing stalling_limit or bound_tolerance.')
+ solve_data.results.solver.termination_condition = tc.noSolution
+
+ return True
+
+ if config.strategy == 'ECP':
+ # check to see if the nonlinear constraints are satisfied
+ MindtPy = solve_data.working_model.MindtPy_utils
+ nonlinear_constraints = [c for c in MindtPy.constraint_list if
+ c.body.polynomial_degree() not in (1, 0)]
+ for nlc in nonlinear_constraints:
+ if nlc.has_lb():
+ try:
+ lower_slack = nlc.lslack()
+ except (ValueError, OverflowError):
+ lower_slack = -10
+ # Use not fixed numbers in this case. Try some factor of ecp_tolerance
+ if lower_slack < -config.ecp_tolerance:
+ config.logger.info(
+ 'MindtPy-ECP continuing as {} has not met the '
+ 'nonlinear constraints satisfaction.'
+ '\n'.format(
+ nlc))
+ return False
+ if nlc.has_ub():
+ try:
+ upper_slack = nlc.uslack()
+ except (ValueError, OverflowError):
+ upper_slack = -10
+ if upper_slack < -config.ecp_tolerance:
+ config.logger.info(
+ 'MindtPy-ECP continuing as {} has not met the '
+ 'nonlinear constraints satisfaction.'
+ '\n'.format(
+ nlc))
+ return False
+ # For ECP to know whether to know which bound to copy over (primal or dual)
+ if solve_data.objective_sense == 1:
+ solve_data.UB = solve_data.LB
+ else:
+ solve_data.LB = solve_data.UB
+ config.logger.info(
+ 'MindtPy-ECP exiting on nonlinear constraints satisfaction. '
+ 'LB: {} UB: {}\n'.format(
+ solve_data.LB, solve_data.UB))
+
+ solve_data.best_solution_found = solve_data.working_model.clone()
+ solve_data.results.solver.termination_condition = tc.optimal
+ return True
# Cycling check
- if config.cycling_check == True and solve_data.mip_iter >= 1 and check_cycling:
+ if config.cycling_check and solve_data.mip_iter >= 1 and check_cycling:
temp = []
for var in solve_data.mip.component_data_objects(ctype=Var):
if var.is_integer():
@@ -163,3 +296,75 @@ def algorithm_should_terminate(solve_data, config, check_cycling):
# 'Exiting iteration loop.')
# return True
return False
+
+
+def bound_fix(solve_data, config, last_iter_cuts):
+ if config.single_tree:
+ config.logger.info(
+ 'Fix the bound to the value of one iteration before optimal solution is found.')
+ if solve_data.results.problem.sense == ProblemSense.minimize:
+ solve_data.LB = solve_data.stored_bound[solve_data.UB]
+ else:
+ solve_data.UB = solve_data.stored_bound[solve_data.LB]
+ else:
+ config.logger.info(
+ 'Solve the master problem without the last nogood cut to fix the bound.'
+ 'zero_tolerance is set to 1E-4')
+ config.zero_tolerance = 1E-4
+ # Solve NLP subproblem
+ # The constraint linearization happens in the handlers
+ if last_iter_cuts is False:
+ fixed_nlp, fixed_nlp_result = solve_NLP_subproblem(
+ solve_data, config)
+ if fixed_nlp_result.solver.termination_condition in {tc.optimal, tc.locallyOptimal, tc.feasible}:
+ handle_NLP_subproblem_optimal(fixed_nlp, solve_data, config)
+ elif fixed_nlp_result.solver.termination_condition is tc.infeasible:
+ handle_NLP_subproblem_infeasible(fixed_nlp, solve_data, config)
+ else:
+ handle_NLP_subproblem_other_termination(fixed_nlp, fixed_nlp_result.solver.termination_condition,
+ solve_data, config)
+
+ MindtPy = solve_data.mip.MindtPy_utils
+ # only deactivate the last integer cut.
+ if config.strategy == 'GOA':
+ if solve_data.results.problem.sense == ProblemSense.minimize:
+ valid_no_good_cuts_num = solve_data.num_no_good_cuts_added[solve_data.UB]
+ else:
+ valid_no_good_cuts_num = solve_data.num_no_good_cuts_added[solve_data.LB]
+ for i in range(valid_no_good_cuts_num+1, len(
+ MindtPy.MindtPy_linear_cuts.integer_cuts)+1):
+ MindtPy.MindtPy_linear_cuts.integer_cuts[i].deactivate()
+ elif config.strategy == 'OA':
+ MindtPy.MindtPy_linear_cuts.integer_cuts[len(
+ MindtPy.MindtPy_linear_cuts.integer_cuts)].deactivate()
+ # MindtPy.MindtPy_linear_cuts.oa_cuts.activate()
+ masteropt = SolverFactory(config.mip_solver)
+ # determine if persistent solver is called.
+ if isinstance(masteropt, PersistentSolver):
+ masteropt.set_instance(solve_data.mip, symbolic_solver_labels=True)
+ mip_args = dict(config.mip_solver_args)
+ elapsed = get_main_elapsed_time(solve_data.timing)
+ remaining = int(max(config.time_limit - elapsed, 1))
+ if config.mip_solver == 'gams':
+ mip_args['add_options'] = mip_args.get('add_options', [])
+ mip_args['add_options'].append('option optcr=0.001;')
+ if config.threads > 0:
+ masteropt.options["threads"] = config.threads
+ master_mip_results = masteropt.solve(
+ solve_data.mip, tee=config.solver_tee, **mip_args)
+ main_objective = next(
+ solve_data.working_model.component_data_objects(Objective, active=True))
+ if main_objective.sense == minimize:
+ solve_data.LB = max(
+ [master_mip_results.problem.lower_bound] + solve_data.LB_progress[:-1])
+ solve_data.LB_progress.append(solve_data.LB)
+ else:
+ solve_data.UB = min(
+ [master_mip_results.problem.upper_bound] + solve_data.UB_progress[:-1])
+ solve_data.UB_progress.append(solve_data.UB)
+ config.logger.info(
+ 'Fixed bound values: LB: {} UB: {}'.
+ format(solve_data.LB, solve_data.UB))
+ # Check bound convergence
+ if solve_data.LB + config.bound_tolerance >= solve_data.UB:
+ solve_data.results.solver.termination_condition = tc.optimal
diff --git a/pyomo/contrib/mindtpy/mip_solve.py b/pyomo/contrib/mindtpy/mip_solve.py
index 7bd04930478..2b42ba2d29c 100644
--- a/pyomo/contrib/mindtpy/mip_solve.py
+++ b/pyomo/contrib/mindtpy/mip_solve.py
@@ -1,35 +1,49 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Master problem functions."""
from __future__ import division
-
+import logging
from pyomo.contrib.gdpopt.util import copy_var_list_values
-from pyomo.core import Constraint, Expression, Objective, minimize, value, Var
+from pyomo.core import Constraint, Expression, Objective, minimize, value
from pyomo.opt import TerminationCondition as tc
from pyomo.opt import SolutionStatus, SolverFactory
-from pyomo.contrib.gdpopt.util import SuppressInfeasibleWarning, _DoNothing
+from pyomo.contrib.gdpopt.util import SuppressInfeasibleWarning, _DoNothing, get_main_elapsed_time
from pyomo.contrib.gdpopt.mip_solve import distinguish_mip_infeasible_or_unbounded
from pyomo.solvers.plugins.solvers.persistent_solver import PersistentSolver
-
-from pyomo.contrib.mindtpy.nlp_solve import (solve_NLP_subproblem,
- handle_NLP_subproblem_optimal, handle_NLP_subproblem_infeasible,
- handle_NLP_subproblem_other_termination, solve_NLP_feas)
-from pyomo.contrib.mindtpy.cut_generation import (add_oa_cuts,
- add_int_cut)
-from pyomo.contrib.gdpopt.util import copy_var_list_values, identify_variables
-from math import copysign
-from pyomo.environ import *
-from pyomo.core import Constraint, minimize, value
-from pyomo.core.expr import current as EXPR
-from math import fabs
-
-from pyomo.repn import generate_standard_repn
-
from pyomo.common.dependencies import attempt_import
+logger = logging.getLogger('pyomo.contrib.mindtpy')
+
single_tree, single_tree_available = attempt_import(
'pyomo.contrib.mindtpy.single_tree')
def solve_OA_master(solve_data, config):
+ """
+ This function solves the MIP master problem for the OA algorithm
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+
+ Returns
+ -------
+ solve_data.mip: Pyomo model
+ the MIP stored in solve_data
+ master_mip_results: Pyomo results object
+ result from solving the master MIP
+ """
solve_data.mip_iter += 1
MindtPy = solve_data.mip.MindtPy_utils
config.logger.info(
@@ -55,16 +69,30 @@ def solve_OA_master(solve_data, config):
expr=sign_adjust * config.OA_penalty_factor * sum(
v for v in MindtPy.MindtPy_linear_cuts.slack_vars[...]))
- MindtPy.MindtPy_oa_obj = Objective(
- expr=main_objective.expr + MindtPy.MindtPy_penalty_expr,
- sense=main_objective.sense)
- else:
- MindtPy.MindtPy_oa_obj = Objective(
- expr=main_objective.expr,
- sense=main_objective.sense)
+ MindtPy.MindtPy_oa_obj = Objective(
+ expr=main_objective.expr +
+ (MindtPy.MindtPy_penalty_expr if config.add_slack else 0),
+ sense=main_objective.sense)
+
+ if config.use_dual_bound:
+ # Delete previously added dual bound constraint
+ if MindtPy.MindtPy_linear_cuts.find_component('dual_bound') is not None:
+ MindtPy.MindtPy_linear_cuts.del_component('dual_bound')
+ if main_objective.sense == minimize:
+ MindtPy.MindtPy_linear_cuts.dual_bound = Constraint(
+ expr=main_objective.expr +
+ (MindtPy.MindtPy_penalty_expr if config.add_slack else 0) >= solve_data.LB,
+ doc='Objective function expression should improve on the best found dual bound')
+ else:
+ MindtPy.MindtPy_linear_cuts.dual_bound = Constraint(
+ expr=main_objective.expr +
+ (MindtPy.MindtPy_penalty_expr if config.add_slack else 0) <= solve_data.UB,
+ doc='Objective function expression should improve on the best found dual bound')
+
# Deactivate extraneous IMPORT/EXPORT suffixes
- getattr(solve_data.mip, 'ipopt_zL_out', _DoNothing()).deactivate()
- getattr(solve_data.mip, 'ipopt_zU_out', _DoNothing()).deactivate()
+ if config.nlp_solver == 'ipopt':
+ getattr(solve_data.mip, 'ipopt_zL_out', _DoNothing()).deactivate()
+ getattr(solve_data.mip, 'ipopt_zU_out', _DoNothing()).deactivate()
masteropt = SolverFactory(config.mip_solver)
# determine if persistent solver is called.
@@ -83,15 +111,24 @@ def solve_OA_master(solve_data, config):
masteropt._solver_model.set_log_stream(None)
masteropt._solver_model.set_error_stream(None)
masteropt.options['timelimit'] = config.time_limit
+ if config.threads > 0:
+ masteropt.options["threads"] = config.threads
mip_args = dict(config.mip_solver_args)
+ elapsed = get_main_elapsed_time(solve_data.timing)
+ remaining = int(max(config.time_limit - elapsed, 1))
if config.mip_solver == 'gams':
mip_args['add_options'] = mip_args.get('add_options', [])
- mip_args['add_options'].append('option optcr=0.0;')
+ mip_args['add_options'].append('option optcr=0.001;')
+ mip_args['add_options'].append('option reslim=%s;' % remaining)
+ # elif config.mip_solver == 'glpk':
+ # masteropt.options['timelimit'] = remaining
master_mip_results = masteropt.solve(
- solve_data.mip, **mip_args) # , tee=True)
+ solve_data.mip, tee=config.solver_tee, **mip_args)
+
+ # if config.single_tree is False and config.add_nogood_cuts is False:
if master_mip_results.solver.termination_condition is tc.optimal:
- if config.single_tree:
+ if config.single_tree and config.add_nogood_cuts is False:
if main_objective.sense == minimize:
solve_data.LB = max(
master_mip_results.problem.lower_bound, solve_data.LB)
@@ -111,18 +148,34 @@ def solve_OA_master(solve_data, config):
return solve_data.mip, master_mip_results
-def handle_master_mip_optimal(master_mip, solve_data, config, copy=True):
- """Copy the result to working model and update upper or lower bound"""
+# The following functions deal with handling the solution we get from the above MIP solver function
+
+
+def handle_master_mip_optimal(master_mip, solve_data, config):
+ """
+ This function copies the result from 'solve_OA_master' to the working model and updates the upper/lower bound. This
+ function is called after an optimal solution is found for the master problem.
+
+ Parameters
+ ----------
+ master_mip: Pyomo model
+ the MIP master problem
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
# proceed. Just need integer values
MindtPy = master_mip.MindtPy_utils
main_objective = next(
master_mip.component_data_objects(Objective, active=True))
# check if the value of binary variable is valid
for var in MindtPy.variable_list:
- if var.value == None and var.is_integer():
+ if var.value is None and var.is_integer():
config.logger.warning(
- "Integer variable {} not initialized. It is set to it's lower bound when using the initial_binary initialization method".format(var.name))
+ "Integer variable {} not initialized. It is set to it's lower bound".format(var.name))
var.value = var.lb # nlp_var.bounds[0]
+ # warm start for the nlp subproblem
copy_var_list_values(
master_mip.MindtPy_utils.variable_list,
solve_data.working_model.MindtPy_utils.variable_list,
@@ -143,6 +196,21 @@ def handle_master_mip_optimal(master_mip, solve_data, config, copy=True):
def handle_master_mip_other_conditions(master_mip, master_mip_results, solve_data, config):
+ """
+ This function handles the result of the latest iteration of solving the MIP problem (given any of a few
+ edge conditions, such as if the solution is neither infeasible nor optimal).
+
+ Parameters
+ ----------
+ master_mip: Pyomo model
+ the MIP master problem
+ master_mip_results: Pyomo results object
+ result from solving the MIP problem
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
if master_mip_results.solver.termination_condition is tc.infeasible:
handle_master_mip_infeasible(master_mip, solve_data, config)
elif master_mip_results.solver.termination_condition is tc.unbounded:
@@ -150,7 +218,7 @@ def handle_master_mip_other_conditions(master_mip, master_mip_results, solve_dat
elif master_mip_results.solver.termination_condition is tc.maxTimeLimit:
handle_master_mip_max_timelimit(master_mip, solve_data, config)
elif (master_mip_results.solver.termination_condition is tc.other and
- master_mip_results.solution.status is SolutionStatus.feasible):
+ master_mip_results.solution.status is SolutionStatus.feasible):
# load the solution and suppress the warning message by setting
# solver status to ok.
MindtPy = master_mip.MindtPy_utils
@@ -181,6 +249,18 @@ def handle_master_mip_other_conditions(master_mip, master_mip_results, solve_dat
def handle_master_mip_infeasible(master_mip, solve_data, config):
+ """
+ This function handles the result of the latest iteration of solving the MIP problem given an infeasible solution.
+
+ Parameters
+ ----------
+ master_mip: Pyomo model
+ the MIP master problem
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
config.logger.info(
'MILP master problem is infeasible. '
'Problem may have no more feasible '
@@ -189,6 +269,7 @@ def handle_master_mip_infeasible(master_mip, solve_data, config):
config.logger.warning(
'MindtPy initialization may have generated poor '
'quality cuts.')
+ # TODO nogood cuts for single tree case
# set optimistic bound to infinity
main_objective = next(
master_mip.component_data_objects(Objective, active=True))
@@ -196,9 +277,29 @@ def handle_master_mip_infeasible(master_mip, solve_data, config):
solve_data.LB_progress.append(solve_data.LB)
else:
solve_data.UB_progress.append(solve_data.UB)
+ config.logger.info(
+ 'MindtPy exiting due to MILP master problem infeasibility.')
+ if solve_data.results.solver.termination_condition is None:
+ if solve_data.mip_iter == 0:
+ solve_data.results.solver.termination_condition = tc.infeasible
+ else:
+ solve_data.results.solver.termination_condition = tc.feasible
def handle_master_mip_max_timelimit(master_mip, solve_data, config):
+ """
+ This function handles the result of the latest iteration of solving the MIP problem given that solving the
+ MIP takes too long.
+
+ Parameters
+ ----------
+ master_mip: Pyomo model
+ the MIP master problem
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
# TODO check that status is actually ok and everything is feasible
MindtPy = master_mip.MindtPy_utils
config.logger.info(
@@ -224,6 +325,19 @@ def handle_master_mip_max_timelimit(master_mip, solve_data, config):
def handle_master_mip_unbounded(master_mip, solve_data, config):
+ """
+ This function handles the result of the latest iteration of solving the MIP problem given an unbounded solution
+ due to the relaxation.
+
+ Parameters
+ ----------
+ master_mip: Pyomo model
+ the MIP master problem
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
# Solution is unbounded. Add an arbitrary bound to the objective and resolve.
# This occurs when the objective is nonlinear. The nonlinear objective is moved
# to the constraints, and deactivated for the linear master problem.
@@ -241,4 +355,4 @@ def handle_master_mip_unbounded(master_mip, solve_data, config):
if isinstance(opt, PersistentSolver):
opt.set_instance(master_mip)
master_mip_results = opt.solve(
- master_mip, **config.mip_solver_args)
+ master_mip, tee=config.solver_tee, **config.mip_solver_args)
diff --git a/pyomo/contrib/mindtpy/nlp_solve.py b/pyomo/contrib/mindtpy/nlp_solve.py
index f17378b7e19..d45290ff7bc 100644
--- a/pyomo/contrib/mindtpy/nlp_solve.py
+++ b/pyomo/contrib/mindtpy/nlp_solve.py
@@ -1,29 +1,51 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Solution of NLP subproblems."""
from __future__ import division
-
+import logging
from pyomo.common.collections import ComponentMap
from pyomo.contrib.mindtpy.cut_generation import (add_oa_cuts,
- add_int_cut)
+ add_nogood_cuts, add_affine_cuts)
from pyomo.contrib.mindtpy.util import add_feas_slacks
-from pyomo.contrib.gdpopt.util import copy_var_list_values
-from pyomo.core import (Constraint, Objective, TransformationFactory, Var,
+from pyomo.contrib.gdpopt.util import copy_var_list_values, get_main_elapsed_time
+from pyomo.core import (Constraint, Objective, TransformationFactory,
minimize, value)
from pyomo.opt import TerminationCondition as tc
from pyomo.opt import SolverFactory
from pyomo.contrib.gdpopt.util import SuppressInfeasibleWarning
+from pyomo.opt.results import ProblemSense
+logger = logging.getLogger('pyomo.contrib.mindtpy')
-def solve_NLP_subproblem(solve_data, config):
- """ Solves fixed NLP with fixed working model binaries
- Sets up local working model `fixed_nlp`
- Fixes binaries
- Sets continuous variables to initial var values
- Precomputes dual values
- Deactivates trivial constraints
- Solves NLP model
-
- Returns the fixed-NLP model and the solver results
+def solve_NLP_subproblem(solve_data, config):
+ """
+ Solves the fixed NLP (with fixed binaries)
+
+ This function sets up the 'fixed_nlp' by fixing binaries, sets continuous variables to their intial var values,
+ precomputes dual values, deactivates trivial constraints, and then solves NLP model.
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+
+ Returns
+ -------
+ fixed_nlp: Pyomo model
+ fixed NLP from the model
+ results: Pyomo results object
+ result from solving the fixed NLP
"""
fixed_nlp = solve_data.working_model.clone()
@@ -75,24 +97,49 @@ def solve_NLP_subproblem(solve_data, config):
TransformationFactory('contrib.deactivate_trivial_constraints')\
.apply_to(fixed_nlp, tmp=True, ignore_infeasible=True)
# Solve the NLP
+ nlpopt = SolverFactory(config.nlp_solver)
+ nlp_args = dict(config.nlp_solver_args)
+ elapsed = get_main_elapsed_time(solve_data.timing)
+ remaining = int(max(config.time_limit - elapsed, 1))
+ if config.nlp_solver == 'gams':
+ nlp_args['add_options'] = nlp_args.get('add_options', [])
+ nlp_args['add_options'].append('option reslim=%s;' % remaining)
with SuppressInfeasibleWarning():
- results = SolverFactory(config.nlp_solver).solve(
- fixed_nlp, **config.nlp_solver_args)
+ results = nlpopt.solve(
+ fixed_nlp, tee=config.solver_tee, **nlp_args)
return fixed_nlp, results
+# The next few functions deal with handling the solution we get from the above NLP solver function
+
+
def handle_NLP_subproblem_optimal(fixed_nlp, solve_data, config):
- """Copies result to working model, updates bound, adds OA and integer cut,
- stores best solution if new one is best"""
+ """
+ This function copies the result of the NLP solver function ('solve_NLP_subproblem') to the working model, updates
+ the bounds, adds OA and integer cuts, and then stores the new solution if it is the new best solution. This
+ function handles the result of the latest iteration of solving the NLP subproblem given an optimal solution.
+
+ Parameters
+ ----------
+ fixed_nlp: Pyomo model
+ fixed NLP from the model
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
copy_var_list_values(
fixed_nlp.MindtPy_utils.variable_list,
solve_data.working_model.MindtPy_utils.variable_list,
config)
- for c in fixed_nlp.tmp_duals:
- if fixed_nlp.dual.get(c, None) is None:
- fixed_nlp.dual[c] = fixed_nlp.tmp_duals[c]
- dual_values = list(fixed_nlp.dual[c]
- for c in fixed_nlp.MindtPy_utils.constraint_list)
+ if config.use_dual:
+ for c in fixed_nlp.tmp_duals:
+ if fixed_nlp.dual.get(c, None) is None:
+ fixed_nlp.dual[c] = fixed_nlp.tmp_duals[c]
+ dual_values = list(fixed_nlp.dual[c]
+ for c in fixed_nlp.MindtPy_utils.constraint_list)
+ else:
+ dual_values = None
main_objective = next(
fixed_nlp.component_data_objects(Objective, active=True))
@@ -113,6 +160,15 @@ def handle_NLP_subproblem_optimal(fixed_nlp, solve_data, config):
if solve_data.solution_improved:
solve_data.best_solution_found = fixed_nlp.clone()
+ solve_data.best_solution_found_time = get_main_elapsed_time(
+ solve_data.timing)
+ if config.strategy == 'GOA':
+ if solve_data.results.problem.sense == ProblemSense.minimize:
+ solve_data.num_no_good_cuts_added.update(
+ {solve_data.UB: len(solve_data.mip.MindtPy_utils.MindtPy_linear_cuts.integer_cuts)})
+ else:
+ solve_data.num_no_good_cuts_added.update(
+ {solve_data.LB: len(solve_data.mip.MindtPy_utils.MindtPy_linear_cuts.integer_cuts)})
# Add the linear cut
if config.strategy == 'OA':
@@ -120,9 +176,16 @@ def handle_NLP_subproblem_optimal(fixed_nlp, solve_data, config):
solve_data.mip.MindtPy_utils.variable_list,
config)
add_oa_cuts(solve_data.mip, dual_values, solve_data, config)
+ elif config.strategy == "GOA":
+ copy_var_list_values(fixed_nlp.MindtPy_utils.variable_list,
+ solve_data.mip.MindtPy_utils.variable_list,
+ config)
+ add_affine_cuts(solve_data, config)
elif config.strategy == 'PSC':
+ # !!THIS SEEMS LIKE A BUG!! - mrmundt #
add_psc_cut(solve_data, config)
elif config.strategy == 'GBD':
+ # !!THIS SEEMS LIKE A BUG!! - mrmundt #
add_gbd_cut(solve_data, config)
# This adds an integer cut to the feasible_integer_cuts
@@ -130,27 +193,39 @@ def handle_NLP_subproblem_optimal(fixed_nlp, solve_data, config):
# may be activated as needed in certain situations or for certain
# values of option flags.
var_values = list(v.value for v in fixed_nlp.MindtPy_utils.variable_list)
- if config.add_integer_cuts:
- add_int_cut(var_values, solve_data, config, feasible=True)
+ if config.add_nogood_cuts:
+ add_nogood_cuts(var_values, solve_data, config, feasible=True)
config.call_after_subproblem_feasible(fixed_nlp, solve_data)
def handle_NLP_subproblem_infeasible(fixed_nlp, solve_data, config):
- """Solve feasibility problem, add cut according to strategy.
+ """
+ Solves feasibility problem and adds cut according to the specified strategy
- The solution of the feasibility problem is copied to the working model.
+ This function handles the result of the latest iteration of solving the NLP subproblem given an infeasible
+ solution and copies the solution of the feasibility problem to the working model.
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
"""
# TODO try something else? Reinitialize with different initial
# value?
config.logger.info('NLP subproblem was locally infeasible.')
- for c in fixed_nlp.component_data_objects(ctype=Constraint):
- rhs = c.upper if c. has_ub() else c.lower
- c_geq = -1 if c.has_ub() else 1
- fixed_nlp.dual[c] = (c_geq
- * max(0, c_geq * (rhs - value(c.body))))
- dual_values = list(fixed_nlp.dual[c]
- for c in fixed_nlp.MindtPy_utils.constraint_list)
+ if config.use_dual:
+ for c in fixed_nlp.component_data_objects(ctype=Constraint):
+ rhs = c.upper if c. has_ub() else c.lower
+ c_geq = -1 if c.has_ub() else 1
+ fixed_nlp.dual[c] = (c_geq
+ * max(0, c_geq * (rhs - value(c.body))))
+ dual_values = list(fixed_nlp.dual[c]
+ for c in fixed_nlp.MindtPy_utils.constraint_list)
+ else:
+ dual_values = None
# if config.strategy == 'PSC' or config.strategy == 'GBD':
# for var in fixed_nlp.component_data_objects(ctype=Var, descend_into=True):
@@ -161,7 +236,7 @@ def handle_NLP_subproblem_infeasible(fixed_nlp, solve_data, config):
# elif var.has_lb() and abs(value(var) - var.lb) < config.bound_tolerance:
# fixed_nlp.ipopt_zU_out[var] = -1
- if config.strategy == 'OA':
+ if config.strategy in {'OA', 'GOA'}:
config.logger.info('Solving feasibility problem')
if config.initial_feas:
# add_feas_slacks(fixed_nlp, solve_data)
@@ -170,26 +245,41 @@ def handle_NLP_subproblem_infeasible(fixed_nlp, solve_data, config):
copy_var_list_values(feas_NLP.MindtPy_utils.variable_list,
solve_data.mip.MindtPy_utils.variable_list,
config)
- add_oa_cuts(solve_data.mip, dual_values, solve_data, config)
+ if config.strategy == "OA":
+ add_oa_cuts(solve_data.mip, dual_values, solve_data, config)
+ elif config.strategy == "GOA":
+ add_affine_cuts(solve_data, config)
# Add an integer cut to exclude this discrete option
var_values = list(v.value for v in fixed_nlp.MindtPy_utils.variable_list)
- if config.add_integer_cuts:
+ if config.add_nogood_cuts:
# excludes current discrete option
- add_int_cut(var_values, solve_data, config)
+ add_nogood_cuts(var_values, solve_data, config)
def handle_NLP_subproblem_other_termination(fixed_nlp, termination_condition,
solve_data, config):
- """Case that fix-NLP is neither optimal nor infeasible (i.e. max_iterations)"""
+ """
+ Handles the result of the latest iteration of solving the NLP subproblem given a solution that is neither optimal
+ nor infeasible.
+
+ Parameters
+ ----------
+ termination_condition: Pyomo TerminationCondition
+ the termination condition of the NLP subproblem
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
if termination_condition is tc.maxIterations:
# TODO try something else? Reinitialize with different initial value?
config.logger.info(
'NLP subproblem failed to converge within iteration limit.')
var_values = list(
v.value for v in fixed_nlp.MindtPy_utils.variable_list)
- if config.add_integer_cuts:
+ if config.add_nogood_cuts:
# excludes current discrete option
- add_int_cut(var_values, solve_data, config)
+ add_nogood_cuts(var_values, solve_data, config)
else:
raise ValueError(
'MindtPy unable to handle NLP subproblem termination '
@@ -197,15 +287,32 @@ def handle_NLP_subproblem_other_termination(fixed_nlp, termination_condition,
def solve_NLP_feas(solve_data, config):
- """Solves feasibility NLP and copies result to working model
-
- Returns: Result values and dual values
"""
- fixed_nlp = solve_data.working_model.clone()
- add_feas_slacks(fixed_nlp, config)
- MindtPy = fixed_nlp.MindtPy_utils
- next(fixed_nlp.component_data_objects(Objective, active=True)).deactivate()
- for constr in fixed_nlp.component_data_objects(
+ Solves a feasibility NLP if the fixed_nlp problem is infeasible
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+
+ Returns
+ -------
+ feas_nlp: Pyomo model
+ feasibility NLP from the model
+ feas_soln: Pyomo results object
+ result from solving the feasibility NLP
+ """
+ feas_nlp = solve_data.working_model.clone()
+ add_feas_slacks(feas_nlp, config)
+
+ MindtPy = feas_nlp.MindtPy_utils
+ if MindtPy.find_component('objective_value') is not None:
+ MindtPy.objective_value.value = 0
+
+ next(feas_nlp.component_data_objects(Objective, active=True)).deactivate()
+ for constr in feas_nlp.component_data_objects(
ctype=Constraint, active=True, descend_into=True):
if constr.body.polynomial_degree() not in [0, 1]:
constr.deactivate()
@@ -223,13 +330,28 @@ def solve_NLP_feas(solve_data, config):
MindtPy.MindtPy_feas_obj = Objective(
expr=MindtPy.MindtPy_feas.slack_var,
sense=minimize)
- TransformationFactory('core.fix_integer_vars').apply_to(fixed_nlp)
-
+ TransformationFactory('core.fix_integer_vars').apply_to(feas_nlp)
with SuppressInfeasibleWarning():
- feas_soln = SolverFactory(config.nlp_solver).solve(
- fixed_nlp, **config.nlp_solver_args)
+ try:
+ nlpopt = SolverFactory(config.nlp_solver)
+ nlp_args = dict(config.nlp_solver_args)
+ elapsed = get_main_elapsed_time(solve_data.timing)
+ remaining = int(max(config.time_limit - elapsed, 1))
+ if config.nlp_solver == 'gams':
+ nlp_args['add_options'] = nlp_args.get('add_options', [])
+ nlp_args['add_options'].append('option reslim=%s;' % remaining)
+ feas_soln = nlpopt.solve(
+ feas_nlp, tee=config.solver_tee, **nlp_args)
+ except (ValueError, OverflowError) as error:
+ for nlp_var, orig_val in zip(
+ MindtPy.variable_list,
+ solve_data.initial_var_values):
+ if not nlp_var.fixed and not nlp_var.is_binary():
+ nlp_var.value = orig_val
+ feas_soln = nlpopt.solve(
+ feas_nlp, tee=config.solver_tee, **nlp_args)
subprob_terminate_cond = feas_soln.solver.termination_condition
- if subprob_terminate_cond is tc.optimal or subprob_terminate_cond is tc.locallyOptimal:
+ if subprob_terminate_cond in {tc.optimal, tc.locallyOptimal, tc.feasible}:
copy_var_list_values(
MindtPy.variable_list,
solve_data.working_model.MindtPy_utils.variable_list,
@@ -237,6 +359,9 @@ def solve_NLP_feas(solve_data, config):
elif subprob_terminate_cond is tc.infeasible:
raise ValueError('Feasibility NLP infeasible. '
'This should never happen.')
+ elif subprob_terminate_cond is tc.maxIterations:
+ raise ValueError('Subsolver reached its maximum number of iterations without converging, '
+ 'consider increasing the iterations limit of the subsolver or reviewing your formulation.')
else:
raise ValueError(
'MindtPy unable to handle feasibility NLP termination condition '
@@ -251,8 +376,9 @@ def solve_NLP_feas(solve_data, config):
duals[i] = c_geq * max(
0, c_geq * (rhs - value(c.body)))
- if value(MindtPy.MindtPy_feas_obj.expr) == 0:
- raise ValueError(
- 'Problem is not feasible, check NLP solver')
+ if value(MindtPy.MindtPy_feas_obj.expr) <= config.zero_tolerance:
+ config.logger.warning("The objective value %.4E of feasibility problem is less than zero_tolerance. "
+ "This indicates that the nlp subproblem is feasible, although it is found infeasible in the previous step. "
+ "Check the nlp solver output" % value(MindtPy.MindtPy_feas_obj.expr))
- return fixed_nlp, feas_soln
+ return feas_nlp, feas_soln
diff --git a/pyomo/contrib/mindtpy/plugins.py b/pyomo/contrib/mindtpy/plugins.py
index 9aecfd948f7..48ec1ad25f4 100644
--- a/pyomo/contrib/mindtpy/plugins.py
+++ b/pyomo/contrib/mindtpy/plugins.py
@@ -1,2 +1,12 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
def load():
import pyomo.contrib.mindtpy.MindtPy
diff --git a/pyomo/contrib/mindtpy/single_tree.py b/pyomo/contrib/mindtpy/single_tree.py
index 52eb5582529..01b42f23672 100644
--- a/pyomo/contrib/mindtpy/single_tree.py
+++ b/pyomo/contrib/mindtpy/single_tree.py
@@ -1,22 +1,31 @@
-from __future__ import division
-
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
-from pyomo.core import Constraint, Expression, Objective, minimize, value, Var
+from __future__ import division
+from pyomo.core import Constraint, Objective, minimize, value
from pyomo.opt import TerminationCondition as tc
from pyomo.contrib.mindtpy.nlp_solve import (solve_NLP_subproblem,
- handle_NLP_subproblem_optimal, handle_NLP_subproblem_infeasible,
- handle_NLP_subproblem_other_termination, solve_NLP_feas)
-from pyomo.contrib.gdpopt.util import copy_var_list_values, identify_variables
+ solve_NLP_feas)
+from pyomo.contrib.gdpopt.util import copy_var_list_values, identify_variables, get_main_elapsed_time
from math import copysign
-from pyomo.environ import *
+import pyomo.environ as pyo
from pyomo.core.expr import current as EXPR
from math import fabs
from pyomo.repn import generate_standard_repn
import logging
-from pyomo.common.dependencies import attempt_import
import cplex
from cplex.callbacks import LazyConstraintCallback
+from pyomo.contrib.mcpp.pyomo_mcpp import McCormick as mc, MCPP_Error
+from pyomo.opt.results import ProblemSense
+logger = logging.getLogger('pyomo.contrib.mindtpy')
class LazyOACallback_cplex(LazyConstraintCallback):
"""Inherent class in Cplex to call Lazy callback."""
@@ -24,10 +33,20 @@ class LazyOACallback_cplex(LazyConstraintCallback):
def copy_lazy_var_list_values(self, opt, from_list, to_list, config,
skip_stale=False, skip_fixed=True,
ignore_integrality=False):
- """Copy variable values from one list to another.
-
+ """This function copies variable values from one list to another.
Rounds to Binary/Integer if neccessary
Sets to zero for NonNegativeReals if neccessary
+
+ Parameters
+ ----------
+ opt: SolverFactory
+ the mip solver
+ from_list: variable list
+ contains variables and their values
+ to_list: variable list
+ contains the variables that need to set value
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
"""
for v_from, v_to in zip(from_list, to_list):
if skip_stale and v_from.stale:
@@ -42,9 +61,9 @@ def copy_lazy_var_list_values(self, opt, from_list, to_list, config,
v_to.stale = False
except ValueError:
# Snap the value to the bounds
- if v_to.has_lb() and v_val < v_to.lb and v_to.lb - v_val <= config.zero_tolerance:
+ if v_to.has_lb() and v_val < v_to.lb and v_to.lb - v_val <= config.bound_tolerance:
v_to.set_value(v_to.lb)
- elif v_to.has_ub() and v_val > v_to.ub and v_val - v_to.ub <= config.zero_tolerance:
+ elif v_to.has_ub() and v_val > v_to.ub and v_val - v_to.ub <= config.bound_tolerance:
v_to.set_value(v_to.ub)
# ... or the nearest integer
elif v_to.is_integer():
@@ -58,8 +77,30 @@ def copy_lazy_var_list_values(self, opt, from_list, to_list, config,
def add_lazy_oa_cuts(self, target_model, dual_values, solve_data, config, opt,
linearize_active=True,
linearize_violated=True):
- """Add oa_cuts through Cplex inherent function self.add()"""
+ """
+ Linearizes nonlinear constraints; add the OA cuts through Cplex inherent function self.add()
+ For nonconvex problems, turn on 'config.add_slack'. Slack variables will
+ always be used for nonlinear equality constraints.
+ Parameters
+ ----------
+ target_model:
+ this is the MIP/MILP model for the OA algorithm; we want to add the OA cuts to 'target_model'
+ dual_values:
+ contains the value of the duals for each constraint
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ opt: SolverFactory
+ the mip solver
+ linearize_active: bool, optional
+ this parameter acts as a Boolean flag that signals whether the linearized constraint is active
+ linearize_violated: bool, optional
+ this parameter acts as a Boolean flag that signals whether the nonlinear constraint represented by the
+ linearized constraint has been violated
+ """
+ config.logger.info("Adding OA cuts")
for (constr, dual_value) in zip(target_model.MindtPy_utils.constraint_list,
dual_values):
if constr.body.polynomial_degree() in (0, 1):
@@ -71,7 +112,7 @@ def add_lazy_oa_cuts(self, target_model, dual_values, solve_data, config, opt,
# Equality constraint (makes the problem nonconvex)
if constr.has_ub() and constr.has_lb() and constr.upper == constr.lower:
sign_adjust = -1 if solve_data.objective_sense == minimize else 1
- rhs = constr.lower if constr.has_lb() and constr.has_ub() else rhs
+ rhs = constr.lower
# since the cplex requires the lazy cuts in cplex type, we need to transform the pyomo expression into cplex expression
pyomo_expr = copysign(1, sign_adjust * dual_value) * (sum(value(jacs[constr][var]) * (
@@ -83,7 +124,7 @@ def add_lazy_oa_cuts(self, target_model, dual_values, solve_data, config, opt,
rhs=cplex_rhs)
else: # Inequality constraint (possibly two-sided)
if constr.has_ub() \
- and (linearize_active and abs(constr.uslack()) < config.zero_tolerance) \
+ and (linearize_active and abs(constr.uslack()) < config.bound_tolerance) \
or (linearize_violated and constr.uslack() < 0) \
or (config.linearize_inactive and constr.uslack() > 0):
@@ -93,9 +134,9 @@ def add_lazy_oa_cuts(self, target_model, dual_values, solve_data, config, opt,
cplex_expr, _ = opt._get_expr_from_pyomo_expr(pyomo_expr)
self.add(constraint=cplex.SparsePair(ind=cplex_expr.variables, val=cplex_expr.coefficients),
sense="L",
- rhs=constr.upper.value+cplex_rhs)
+ rhs=constr.upper.value + cplex_rhs)
if constr.has_lb() \
- and (linearize_active and abs(constr.lslack()) < config.zero_tolerance) \
+ and (linearize_active and abs(constr.lslack()) < config.bound_tolerance) \
or (linearize_violated and constr.lslack() < 0) \
or (config.linearize_inactive and constr.lslack() > 0):
pyomo_expr = sum(value(jacs[constr][var]) * (var - self.get_values(
@@ -106,10 +147,181 @@ def add_lazy_oa_cuts(self, target_model, dual_values, solve_data, config, opt,
sense="G",
rhs=constr.lower.value + cplex_rhs)
+ def add_lazy_affine_cuts(self, solve_data, config, opt):
+ """
+ Adds affine cuts using MCPP; add affine cuts through Cplex inherent function self.add()
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ opt: SolverFactory
+ the mip solver
+ """
+ m = solve_data.mip
+ config.logger.info("Adding affine cuts")
+ counter = 0
+
+ for constr in m.MindtPy_utils.constraint_list:
+ if constr.body.polynomial_degree() in (1, 0):
+ continue
+
+ vars_in_constr = list(
+ identify_variables(constr.body))
+ if any(var.value is None for var in vars_in_constr):
+ continue # a variable has no values
+
+ # mcpp stuff
+ try:
+ mc_eqn = mc(constr.body)
+ except MCPP_Error as e:
+ config.logger.debug(
+ "Skipping constraint %s due to MCPP error %s" % (constr.name, str(e)))
+ continue # skip to the next constraint
+ # TODO: check if the value of ccSlope and cvSlope is not Nan or inf. If so, we skip this.
+ ccSlope = mc_eqn.subcc()
+ cvSlope = mc_eqn.subcv()
+ ccStart = mc_eqn.concave()
+ cvStart = mc_eqn.convex()
+
+ concave_cut_valid = True
+ convex_cut_valid = True
+ for var in vars_in_constr:
+ if not var.fixed:
+ if ccSlope[var] == float('nan') or ccSlope[var] == float('inf'):
+ concave_cut_valid = False
+ if cvSlope[var] == float('nan') or cvSlope[var] == float('inf'):
+ convex_cut_valid = False
+ if ccStart == float('nan') or ccStart == float('inf'):
+ concave_cut_valid = False
+ if cvStart == float('nan') or cvStart == float('inf'):
+ convex_cut_valid = False
+ # check if the value of ccSlope and cvSlope all equals zero. if so, we skip this.
+ if not any(list(ccSlope.values())):
+ concave_cut_valid = False
+ if not any(list(cvSlope.values())):
+ convex_cut_valid = False
+ if (concave_cut_valid or convex_cut_valid) is False:
+ continue
+
+ ub_int = min(constr.upper, mc_eqn.upper()
+ ) if constr.has_ub() else mc_eqn.upper()
+ lb_int = max(constr.lower, mc_eqn.lower()
+ ) if constr.has_lb() else mc_eqn.lower()
+
+ parent_block = constr.parent_block()
+ # Create a block on which to put outer approximation cuts.
+ # TODO: create it at the beginning.
+ aff_utils = parent_block.component('MindtPy_aff')
+ if aff_utils is None:
+ aff_utils = parent_block.MindtPy_aff = pyo.Block(
+ doc="Block holding affine constraints")
+ aff_utils.MindtPy_aff_cons = pyo.ConstraintList()
+ aff_cuts = aff_utils.MindtPy_aff_cons
+ if concave_cut_valid:
+ pyomo_concave_cut = sum(ccSlope[var] * (var - var.value)
+ for var in vars_in_constr
+ if not var.fixed) + ccStart
+ cplex_concave_rhs = generate_standard_repn(
+ pyomo_concave_cut).constant
+ cplex_concave_cut, _ = opt._get_expr_from_pyomo_expr(
+ pyomo_concave_cut)
+ self.add(constraint=cplex.SparsePair(ind=cplex_concave_cut.variables, val=cplex_concave_cut.coefficients),
+ sense="G",
+ rhs=lb_int - cplex_concave_rhs)
+ counter += 1
+ if convex_cut_valid:
+ pyomo_convex_cut = sum(cvSlope[var] * (var - var.value)
+ for var in vars_in_constr
+ if not var.fixed) + cvStart
+ cplex_convex_rhs = generate_standard_repn(
+ pyomo_convex_cut).constant
+ cplex_convex_cut, _ = opt._get_expr_from_pyomo_expr(
+ pyomo_convex_cut)
+ self.add(constraint=cplex.SparsePair(ind=cplex_convex_cut.variables, val=cplex_convex_cut.coefficients),
+ sense="L",
+ rhs=ub_int - cplex_convex_rhs)
+ # aff_cuts.add(expr=convex_cut)
+ counter += 1
+
+ config.logger.info("Added %s affine cuts" % counter)
+
+ def add_lazy_nogood_cuts(self, var_values, solve_data, config, opt, feasible=False):
+ """
+ Adds integer cuts; add the nogood cuts through Cplex inherent function self.add()
+
+ Parameters
+ ----------
+ var_values: list
+ values of the current variables, used to generate the cut
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ feasible: bool, optional
+ boolean indicating if integer combination yields a feasible or infeasible NLP
+ opt: SolverFactory
+ the mip solver
+ """
+ if not config.add_nogood_cuts:
+ return
+
+ config.logger.info("Adding nogood cuts")
+
+ m = solve_data.mip
+ MindtPy = m.MindtPy_utils
+ int_tol = config.integer_tolerance
+
+ binary_vars = [v for v in MindtPy.variable_list if v.is_binary()]
+
+ # copy variable values over
+ for var, val in zip(MindtPy.variable_list, var_values):
+ if not var.is_binary():
+ continue
+ var.value = val
+
+ # check to make sure that binary variables are all 0 or 1
+ for v in binary_vars:
+ if value(abs(v - 1)) > int_tol and value(abs(v)) > int_tol:
+ raise ValueError('Binary {} = {} is not 0 or 1'.format(
+ v.name, value(v)))
+
+ if not binary_vars: # if no binary variables, skip
+ return
+
+ # int_cut = (sum(1 - v for v in binary_vars
+ # if value(abs(v - 1)) <= int_tol) +
+ # sum(v for v in binary_vars
+ # if value(abs(v)) <= int_tol) >= 1)
+
+ # MindtPy.MindtPy_linear_cuts.integer_cuts.add(expr=int_cut)
+
+ pyomo_nogood_cut = sum(1 - v for v in binary_vars if value(abs(v - 1))
+ <= int_tol) + sum(v for v in binary_vars if value(abs(v)) <= int_tol)
+ cplex_nogood_rhs = generate_standard_repn(pyomo_nogood_cut).constant
+ cplex_nogood_cut, _ = opt._get_expr_from_pyomo_expr(pyomo_nogood_cut)
+
+ self.add(constraint=cplex.SparsePair(ind=cplex_nogood_cut.variables, val=cplex_nogood_cut.coefficients),
+ sense="G",
+ rhs=1 - cplex_nogood_rhs)
+
def handle_lazy_master_mip_feasible_sol(self, master_mip, solve_data, config, opt):
""" This function is called during the branch and bound of master mip, more exactly when a feasible solution is found and LazyCallback is activated.
- Copy the result to working model and update upper or lower bound
+ Copy the result to working model and update upper or lower bound.
In LP-NLP, upper or lower bound are updated during solving the master problem
+
+ Parameters
+ ----------
+ master_mip: Pyomo model
+ the MIP master problem
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ opt: SolverFactory
+ the mip solver
"""
# proceed. Just need integer values
MindtPy = master_mip.MindtPy_utils
@@ -121,19 +333,45 @@ def handle_lazy_master_mip_feasible_sol(self, master_mip, solve_data, config, op
master_mip.MindtPy_utils.variable_list,
solve_data.working_model.MindtPy_utils.variable_list,
config)
+ # if config.strategy == 'GOA':
+ # if not config.add_nogood_cuts:
+ if main_objective.sense == minimize:
+ solve_data.LB = max(
+ self.get_best_objective_value(), solve_data.LB)
+ solve_data.LB_progress.append(solve_data.LB)
+ else:
+ solve_data.UB = min(
+ self.get_best_objective_value(), solve_data.UB)
+ solve_data.UB_progress.append(solve_data.UB)
config.logger.info(
- 'MIP %s: OBJ: %s LB: %s UB: %s'
- % (solve_data.mip_iter, value(MindtPy.MindtPy_oa_obj.expr),
+ 'MIP %s: OBJ: %s Bound: %s LB: %s UB: %s'
+ % (solve_data.mip_iter, value(MindtPy.MindtPy_oa_obj.expr), self.get_best_objective_value(),
solve_data.LB, solve_data.UB))
def handle_lazy_NLP_subproblem_optimal(self, fixed_nlp, solve_data, config, opt):
- """Copies result to mip(explaination see below), updates bound, adds OA and integer cut,
- stores best solution if new one is best"""
- for c in fixed_nlp.tmp_duals:
- if fixed_nlp.dual.get(c, None) is None:
- fixed_nlp.dual[c] = fixed_nlp.tmp_duals[c]
- dual_values = list(fixed_nlp.dual[c]
- for c in fixed_nlp.MindtPy_utils.constraint_list)
+ """
+ This function copies result to mip(explaination see below), updates bound, adds OA and integer cut,
+ stores best solution if new one is best
+
+ Parameters
+ ----------
+ fixed_nlp: Pyomo model
+ fixed NLP from the model
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ opt: SolverFactory
+ the mip solver
+ """
+ if config.use_dual:
+ for c in fixed_nlp.tmp_duals:
+ if fixed_nlp.dual.get(c, None) is None:
+ fixed_nlp.dual[c] = fixed_nlp.tmp_duals[c]
+ dual_values = list(fixed_nlp.dual[c]
+ for c in fixed_nlp.MindtPy_utils.constraint_list)
+ else:
+ dual_values = None
main_objective = next(
fixed_nlp.component_data_objects(Objective, active=True))
@@ -154,50 +392,95 @@ def handle_lazy_NLP_subproblem_optimal(self, fixed_nlp, solve_data, config, opt)
if solve_data.solution_improved:
solve_data.best_solution_found = fixed_nlp.clone()
+ solve_data.best_solution_found_time = get_main_elapsed_time(
+ solve_data.timing)
+ if config.add_nogood_cuts:
+ if solve_data.results.problem.sense == ProblemSense.minimize:
+ solve_data.stored_bound.update(
+ {solve_data.UB: solve_data.LB})
+ else:
+ solve_data.stored_bound.update(
+ {solve_data.LB: solve_data.UB})
+ # In OA algorithm, OA cuts are generated based on the solution of the subproblem
+ # We need to first copy the value of variables from the subproblem and then add cuts
+ # since value(constr.body), value(jacs[constr][var]), value(var) are used in self.add_lazy_oa_cuts()
+ copy_var_list_values(fixed_nlp.MindtPy_utils.variable_list,
+ solve_data.mip.MindtPy_utils.variable_list,
+ config)
if config.strategy == 'OA':
- # In OA algorithm, OA cuts are generated based on the solution of the subproblem
- # We need to first copy the value of variables from the subproblem and then add cuts
- # since value(constr.body), value(jacs[constr][var]), value(var) are used in self.add_lazy_oa_cuts()
- copy_var_list_values(fixed_nlp.MindtPy_utils.variable_list,
- solve_data.mip.MindtPy_utils.variable_list,
- config)
self.add_lazy_oa_cuts(
solve_data.mip, dual_values, solve_data, config, opt)
+ elif config.strategy == 'GOA':
+ self.add_lazy_affine_cuts(solve_data, config, opt)
+ if config.add_nogood_cuts:
+ var_values = list(
+ v.value for v in fixed_nlp.MindtPy_utils.variable_list)
+ self.add_lazy_nogood_cuts(var_values, solve_data, config, opt)
def handle_lazy_NLP_subproblem_infeasible(self, fixed_nlp, solve_data, config, opt):
- """Solve feasibility problem, add cut according to strategy.
+ """
+ Solves feasibility problem and adds cut according to the specified strategy
- The solution of the feasibility problem is copied to the working model.
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ opt: SolverFactory
+ the mip solver
"""
# TODO try something else? Reinitialize with different initial
# value?
config.logger.info('NLP subproblem was locally infeasible.')
- for c in fixed_nlp.component_data_objects(ctype=Constraint):
- rhs = ((0 if c.upper is None else c.upper)
- + (0 if c.lower is None else c.lower))
- sign_adjust = 1 if value(c.upper) is None else -1
- fixed_nlp.dual[c] = (sign_adjust
- * max(0, sign_adjust * (rhs - value(c.body))))
- dual_values = list(fixed_nlp.dual[c]
- for c in fixed_nlp.MindtPy_utils.constraint_list)
+ if config.use_dual:
+ for c in fixed_nlp.component_data_objects(ctype=Constraint):
+ rhs = ((0 if c.upper is None else c.upper)
+ + (0 if c.lower is None else c.lower))
+ sign_adjust = 1 if value(c.upper) is None else -1
+ fixed_nlp.dual[c] = (sign_adjust
+ * max(0, sign_adjust * (rhs - value(c.body))))
+ dual_values = list(fixed_nlp.dual[c]
+ for c in fixed_nlp.MindtPy_utils.constraint_list)
+ else:
+ dual_values = None
- if config.strategy == 'OA':
- config.logger.info('Solving feasibility problem')
- if config.initial_feas:
- # config.initial_feas = False
- feas_NLP, feas_NLP_results = solve_NLP_feas(solve_data, config)
- # In OA algorithm, OA cuts are generated based on the solution of the subproblem
- # We need to first copy the value of variables from the subproblem and then add cuts
- copy_var_list_values(feas_NLP.MindtPy_utils.variable_list,
- solve_data.mip.MindtPy_utils.variable_list,
- config)
+ config.logger.info('Solving feasibility problem')
+ if config.initial_feas:
+ # config.initial_feas = False
+ feas_NLP, feas_NLP_results = solve_NLP_feas(solve_data, config)
+ # In OA algorithm, OA cuts are generated based on the solution of the subproblem
+ # We need to first copy the value of variables from the subproblem and then add cuts
+ copy_var_list_values(feas_NLP.MindtPy_utils.variable_list,
+ solve_data.mip.MindtPy_utils.variable_list,
+ config)
+ if config.strategy == 'OA':
self.add_lazy_oa_cuts(
solve_data.mip, dual_values, solve_data, config, opt)
+ elif config.strategy == 'GOA':
+ self.add_lazy_affine_cuts(solve_data, config, opt)
+ if config.add_nogood_cuts:
+ var_values = list(
+ v.value for v in fixed_nlp.MindtPy_utils.variable_list)
+ self.add_lazy_nogood_cuts(
+ var_values, solve_data, config, opt)
def handle_lazy_NLP_subproblem_other_termination(self, fixed_nlp, termination_condition,
solve_data, config):
- """Case that fix-NLP is neither optimal nor infeasible (i.e. max_iterations)"""
+ """
+ Handles the result of the latest iteration of solving the NLP subproblem given a solution that is neither optimal
+ nor infeasible.
+
+ Parameters
+ ----------
+ termination_condition: Pyomo TerminationCondition
+ the termination condition of the NLP subproblem
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
if termination_condition is tc.maxIterations:
# TODO try something else? Reinitialize with different initial value?
config.logger.info(
@@ -210,6 +493,10 @@ def handle_lazy_NLP_subproblem_other_termination(self, fixed_nlp, termination_co
'condition of {}'.format(termination_condition))
def __call__(self):
+ """
+ This is an inherent function in LazyConstraintCallback in cplex.
+ This funtion is call whenever the a integer solution is found during the branch and bound process
+ """
solve_data = self.solve_data
config = self.config
opt = self.opt
@@ -219,15 +506,31 @@ def __call__(self):
self.handle_lazy_master_mip_feasible_sol(
master_mip, solve_data, config, opt)
+ if solve_data.LB + config.bound_tolerance >= solve_data.UB:
+ config.logger.info(
+ 'MindtPy exiting on bound convergence. '
+ 'LB: {} + (tol {}) >= UB: {}\n'.format(
+ solve_data.LB, config.bound_tolerance, solve_data.UB))
+ solve_data.results.solver.termination_condition = tc.optimal
+ return
+ # else:
# solve subproblem
# Solve NLP subproblem
# The constraint linearization happens in the handlers
- fixed_nlp, fixed_nlp_result = solve_NLP_subproblem(solve_data, config)
+ fixed_nlp, fixed_nlp_result = solve_NLP_subproblem(
+ solve_data, config)
# add oa cuts
- if fixed_nlp_result.solver.termination_condition is tc.optimal or fixed_nlp_result.solver.termination_condition is tc.locallyOptimal:
+ if fixed_nlp_result.solver.termination_condition in {tc.optimal, tc.locallyOptimal, tc.feasible}:
self.handle_lazy_NLP_subproblem_optimal(
fixed_nlp, solve_data, config, opt)
+ if solve_data.LB + config.bound_tolerance >= solve_data.UB:
+ config.logger.info(
+ 'MindtPy exiting on bound convergence. '
+ 'LB: {} + (tol {}) >= UB: {}\n'.format(
+ solve_data.LB, config.bound_tolerance, solve_data.UB))
+ solve_data.results.solver.termination_condition = tc.optimal
+ return
elif fixed_nlp_result.solver.termination_condition is tc.infeasible:
self.handle_lazy_NLP_subproblem_infeasible(
fixed_nlp, solve_data, config, opt)
diff --git a/pyomo/contrib/mindtpy/tests/MINLP2_simple.py b/pyomo/contrib/mindtpy/tests/MINLP2_simple.py
index b91a1a264ce..36a3ff46396 100644
--- a/pyomo/contrib/mindtpy/tests/MINLP2_simple.py
+++ b/pyomo/contrib/mindtpy/tests/MINLP2_simple.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Re-implementation of example 1 of Outer approximation and ECP.
Re-implementation of Duran example 1 as written by Westerlund
@@ -28,8 +38,7 @@
from six import iteritems
from pyomo.environ import (Binary, ConcreteModel, Constraint, NonNegativeReals,
- Objective, Param, RangeSet, Var, exp, minimize,
- maximize, log)
+ Objective, RangeSet, Var, minimize, log)
class SimpleMINLP(ConcreteModel):
diff --git a/pyomo/contrib/mindtpy/tests/MINLP3_simple.py b/pyomo/contrib/mindtpy/tests/MINLP3_simple.py
index 5d0151e2926..f0437d97b73 100644
--- a/pyomo/contrib/mindtpy/tests/MINLP3_simple.py
+++ b/pyomo/contrib/mindtpy/tests/MINLP3_simple.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Re-implementation of example 1 of Quesada and Grossmann.
Re-implementation of Quesada example 2 MINLP test problem in Pyomo
@@ -20,10 +30,8 @@
"""
from __future__ import division
-from six import iteritems
-
from pyomo.environ import (Binary, ConcreteModel, Constraint, Reals,
- Objective, Param, RangeSet, Var, exp, minimize, log)
+ Objective, RangeSet, Var, minimize, log)
class SimpleMINLP(ConcreteModel):
diff --git a/pyomo/contrib/mindtpy/tests/MINLP_simple.py b/pyomo/contrib/mindtpy/tests/MINLP_simple.py
index 06d76cc67d1..75277cfafdd 100644
--- a/pyomo/contrib/mindtpy/tests/MINLP_simple.py
+++ b/pyomo/contrib/mindtpy/tests/MINLP_simple.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Implementation of MINLP problem in Assignment 6 of the Advanced PSE lecture at CMU.
Author: David Bernal
@@ -19,8 +29,8 @@
from six import iteritems
from pyomo.environ import (Binary, ConcreteModel, Constraint,
- NonNegativeReals, Objective, Param,
- RangeSet, Var, exp, minimize)
+ NonNegativeReals, Objective,
+ RangeSet, Var, minimize)
class SimpleMINLP(ConcreteModel):
diff --git a/pyomo/contrib/mindtpy/tests/eight_process_problem.py b/pyomo/contrib/mindtpy/tests/eight_process_problem.py
index 70e5bddad72..4b6e35b316d 100644
--- a/pyomo/contrib/mindtpy/tests/eight_process_problem.py
+++ b/pyomo/contrib/mindtpy/tests/eight_process_problem.py
@@ -32,7 +32,7 @@
class EightProcessFlowsheet(ConcreteModel):
"""Flowsheet for the 8 process problem."""
- def __init__(self, *args, **kwargs):
+ def __init__(self, convex=True, *args, **kwargs):
"""Create the flowsheet."""
kwargs.setdefault('name', 'DuranEx3')
super(EightProcessFlowsheet, self).__init__(*args, **kwargs)
@@ -96,14 +96,21 @@ def __init__(self, *args, **kwargs):
"""Constraint definitions"""
# INPUT-OUTPUT RELATIONS FOR process units 1 through 8
- m.inout1 = Constraint(expr=exp(m.X[3]) - 1 == m.X[2])
- m.inout2 = Constraint(expr=exp(m.X[5] / 1.2) - 1 == m.X[4])
m.inout3 = Constraint(expr=1.5 * m.X[9] + m.X[10] == m.X[8])
m.inout4 = Constraint(expr=1.25 * (m.X[12] + m.X[14]) == m.X[13])
m.inout5 = Constraint(expr=m.X[15] == 2 * m.X[16])
- m.inout6 = Constraint(expr=exp(m.X[20] / 1.5) - 1 == m.X[19])
- m.inout7 = Constraint(expr=exp(m.X[22]) - 1 == m.X[21])
- m.inout8 = Constraint(expr=exp(m.X[18]) - 1 == m.X[10] + m.X[17])
+ if convex:
+ m.inout1 = Constraint(expr=exp(m.X[3]) - 1 <= m.X[2])
+ m.inout2 = Constraint(expr=exp(m.X[5] / 1.2) - 1 <= m.X[4])
+ m.inout7 = Constraint(expr=exp(m.X[22]) - 1 <= m.X[21])
+ m.inout8 = Constraint(expr=exp(m.X[18]) - 1 <= m.X[10] + m.X[17])
+ m.inout6 = Constraint(expr=exp(m.X[20] / 1.5) - 1 <= m.X[19])
+ else:
+ m.inout1 = Constraint(expr=exp(m.X[3]) - 1 == m.X[2])
+ m.inout2 = Constraint(expr=exp(m.X[5] / 1.2) - 1 == m.X[4])
+ m.inout7 = Constraint(expr=exp(m.X[22]) - 1 == m.X[21])
+ m.inout8 = Constraint(expr=exp(m.X[18]) - 1 == m.X[10] + m.X[17])
+ m.inout6 = Constraint(expr=exp(m.X[20] / 1.5) - 1 == m.X[19])
# Mass balance equations
m.massbal1 = Constraint(expr=m.X[13] == m.X[19] + m.X[21])
@@ -144,6 +151,8 @@ def __init__(self, *args, **kwargs):
"""Bound definitions"""
# x (flow) upper bounds
- x_ubs = {3: 2, 5: 2, 9: 2, 10: 1, 14: 1, 17: 2, 19: 2, 21: 2, 25: 3}
+ # x_ubs = {3: 2, 5: 2, 9: 2, 10: 1, 14: 1, 17: 2, 19: 2, 21: 2, 25: 3}
+ x_ubs = {2: 10, 3: 2, 4: 10, 5: 2, 9: 2, 10: 1, 14: 1, 17: 2, 18: 10, 19: 2,
+ 20: 10, 21: 2, 22: 10, 25: 3} # add bounds for variables in nonlinear constraints
for i, x_ub in iteritems(x_ubs):
X[i].setub(x_ub)
diff --git a/pyomo/contrib/mindtpy/tests/nonconvex1.py b/pyomo/contrib/mindtpy/tests/nonconvex1.py
new file mode 100644
index 00000000000..3295e52c926
--- /dev/null
+++ b/pyomo/contrib/mindtpy/tests/nonconvex1.py
@@ -0,0 +1,35 @@
+"""Problem A in paper "Outer approximation algorithms for separable nonconvex mixed-integer nonlinear programs"
+
+Ref:
+Kesavan P, Allgor R J, Gatzke E P, et al. Outer approximation algorithms for separable nonconvex mixed-integer nonlinear programs[J]. Mathematical Programming, 2004, 100(3): 517-535.
+
+Problem type: nonconvex MINLP
+ size: 3 binary variable
+ 2 continuous variables
+ 6 constraints
+
+"""
+from pyomo.environ import *
+
+
+class Nonconvex1(ConcreteModel):
+ def __init__(self, *args, **kwargs):
+ """Create the problem."""
+ kwargs.setdefault('name', 'Nonconvex1')
+ super(Nonconvex1, self).__init__(*args, **kwargs)
+ m = self
+
+ m.x1 = Var(within=Reals, bounds=(0, 10))
+ m.x2 = Var(within=Reals, bounds=(0, 10))
+ m.y1 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y2 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y3 = Var(within=Binary, bounds=(0, 1), initialize=0)
+
+ m.objective = Objective(expr=2 * m.x1 + 3 * m.x2 + 1.5 * m.y1 +
+ 2 * m.y2 - 0.5 * m.y3, sense=minimize)
+
+ m.c1 = Constraint(expr=m.x1 * m.x1 + m.y1 == 1.25)
+ m.c2 = Constraint(expr=m.x2 ** 1.5 + 1.5 * m.y2 == 3)
+ m.c4 = Constraint(expr=m.x1 + m.y1 <= 1.6)
+ m.c5 = Constraint(expr=1.333 * m.x2 + m.y2 <= 3)
+ m.c6 = Constraint(expr=-m.y1 - m.y2 + m.y3 <= 0)
diff --git a/pyomo/contrib/mindtpy/tests/nonconvex2.py b/pyomo/contrib/mindtpy/tests/nonconvex2.py
new file mode 100644
index 00000000000..57368d1a1ee
--- /dev/null
+++ b/pyomo/contrib/mindtpy/tests/nonconvex2.py
@@ -0,0 +1,47 @@
+"""Problem B in paper "Outer approximation algorithms for separable nonconvex mixed-integer nonlinear programs"
+
+Ref:
+Kesavan P, Allgor R J, Gatzke E P, et al. Outer approximation algorithms for separable nonconvex mixed-integer nonlinear programs[J]. Mathematical Programming, 2004, 100(3): 517-535.
+
+Problem type: nonconvex MINLP
+ size: 8 binary variable
+ 3 continuous variables
+ 7 constraints
+
+"""
+from pyomo.environ import *
+
+
+class Nonconvex2(ConcreteModel):
+ def __init__(self, *args, **kwargs):
+ """Create the problem."""
+ kwargs.setdefault('name', 'Nonconvex2')
+ super(Nonconvex2, self).__init__(*args, **kwargs)
+ m = self
+
+ m.x1 = Var(within=Reals, bounds=(0, 0.9970))
+ m.x2 = Var(within=Reals, bounds=(0, 0.9985))
+ m.x3 = Var(within=Reals, bounds=(0, 0.9988))
+ m.y1 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y2 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y3 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y4 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y5 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y6 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y7 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y8 = Var(within=Binary, bounds=(0, 1), initialize=0)
+
+ m.objective = Objective(expr=- m.x1 * m.x2 * m.x3, sense=minimize)
+
+ m.c1 = Constraint(expr=-log(1 - m.x1) + log(0.1) * m.y1 +
+ log(0.2) * m.y2 + log(0.15) * m.y3 == 0)
+ m.c2 = Constraint(expr=-log(1 - m.x2) + log(0.05) * m.y4 +
+ log(0.2) * m.y5 + log(0.15) * m.y6 == 0)
+ m.c3 = Constraint(expr=-log(1 - m.x3) + log(0.02) * m.y7 +
+ log(0.06) * m.y8 == 0)
+
+ m.c4 = Constraint(expr=-m.y1 - m.y2 - m.y3 <= -1)
+ m.c5 = Constraint(expr=-m.y4 - m.y5 - m.y6 <= -1)
+ m.c6 = Constraint(expr=-m.y7 - m.y8 <= -1)
+ m.c7 = Constraint(expr=3 * m.y1 + m.y2 + 2 * m.y3 + 3 *
+ m.y4 + 2 * m.y5 + m.y6 + 3 * m.y7 + 2 * m.y8 <= 10)
diff --git a/pyomo/contrib/mindtpy/tests/nonconvex3.py b/pyomo/contrib/mindtpy/tests/nonconvex3.py
new file mode 100644
index 00000000000..ec878ea9fef
--- /dev/null
+++ b/pyomo/contrib/mindtpy/tests/nonconvex3.py
@@ -0,0 +1,39 @@
+"""Problem C in paper "Outer approximation algorithms for separable nonconvex mixed-integer nonlinear programs"
+
+Ref:
+Kesavan P, Allgor R J, Gatzke E P, et al. Outer approximation algorithms for separable nonconvex mixed-integer nonlinear programs[J]. Mathematical Programming, 2004, 100(3): 517-535.
+
+Problem type: nonconvex MINLP
+ size: 6 binary variable
+ 2 continuous variables
+ 6 constraints
+
+"""
+from pyomo.environ import *
+
+
+class Nonconvex3(ConcreteModel):
+ def __init__(self, *args, **kwargs):
+ """Create the problem."""
+ kwargs.setdefault('name', 'Nonconvex3')
+ super(Nonconvex3, self).__init__(*args, **kwargs)
+ m = self
+
+ m.x1 = Var(within=Reals, bounds=(1, 5))
+ m.x2 = Var(within=Reals, bounds=(1, 5))
+ m.y1 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y2 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y3 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y4 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y5 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y6 = Var(within=Binary, bounds=(0, 1), initialize=0)
+
+ m.objective = Objective(expr=7 * m.x1 + 10 * m.x2, sense=minimize)
+
+ m.c1 = Constraint(expr=(m.x1 ** 1.2) * (m.x2 ** 1.7) -
+ 7 * m.x1 - 9 * m.x2 <= -24)
+ m.c2 = Constraint(expr=-m.x1 - 2 * m.x2 <= 5)
+ m.c3 = Constraint(expr=-3 * m.x1 + m.x2 <= 1)
+ m.c4 = Constraint(expr=4 * m.x1 - 3 * m.x2 <= 11)
+ m.c5 = Constraint(expr=-m.x1 + m.y1 + 2 * m.y2 + 4 * m.y3 == 0)
+ m.c6 = Constraint(expr=-m.x2 + m.y4 + 2 * m.y5 + m.y6 == 0)
diff --git a/pyomo/contrib/mindtpy/tests/nonconvex4.py b/pyomo/contrib/mindtpy/tests/nonconvex4.py
new file mode 100644
index 00000000000..f41a97d5fcf
--- /dev/null
+++ b/pyomo/contrib/mindtpy/tests/nonconvex4.py
@@ -0,0 +1,34 @@
+"""Problem D in paper "Outer approximation algorithms for separable nonconvex mixed-integer nonlinear programs"
+
+Ref:
+Kesavan P, Allgor R J, Gatzke E P, et al. Outer approximation algorithms for separable nonconvex mixed-integer nonlinear programs[J]. Mathematical Programming, 2004, 100(3): 517-535.
+
+Problem type: nonconvex MINLP
+ size: 3 binary variable
+ 2 continuous variables
+ 4 constraints
+
+"""
+from pyomo.environ import *
+
+
+class Nonconvex4(ConcreteModel):
+ def __init__(self, *args, **kwargs):
+ """Create the problem."""
+ kwargs.setdefault('name', 'Nonconvex4')
+ super(Nonconvex4, self).__init__(*args, **kwargs)
+ m = self
+
+ m.x1 = Var(within=Reals, bounds=(1, 10))
+ m.x2 = Var(within=Reals, bounds=(1, 6))
+ m.y1 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y2 = Var(within=Binary, bounds=(0, 1), initialize=0)
+ m.y3 = Var(within=Binary, bounds=(0, 1), initialize=0)
+
+ m.objective = Objective(expr=-5 * m.x1 + 3 * m.x2, sense=minimize)
+
+ m.c1 = Constraint(expr=2 * (m.x2 ** 2) - 2 * (m.x2 ** 0.5) -
+ 2 * (m.x1 ** 0.5) * (m.x2 ** 2) + 11 * m.x2 + 8 * m.x1 <= 39)
+ m.c2 = Constraint(expr=m.x1 - m.x2 <= 3)
+ m.c3 = Constraint(expr=3 * m.x1 + 2 * m.x2 <= 24)
+ m.c4 = Constraint(expr=-m.x1 + m.y1 + 2 * m.y2 + 4 * m.y3 == 0)
diff --git a/pyomo/contrib/mindtpy/tests/online_doc_example.py b/pyomo/contrib/mindtpy/tests/online_doc_example.py
index a7199eadffa..bb0d2631e71 100644
--- a/pyomo/contrib/mindtpy/tests/online_doc_example.py
+++ b/pyomo/contrib/mindtpy/tests/online_doc_example.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
""" Example in the online doc.
The expected optimal solution value is 2.438447187191098.
@@ -10,10 +20,8 @@
"""
from __future__ import division
-from six import iteritems
-
-from pyomo.environ import (Binary, ConcreteModel, Constraint, Reals,
- Objective, Param, RangeSet, Var, exp, minimize, log)
+from pyomo.environ import (Binary, ConcreteModel, Constraint,
+ Objective, Var, minimize, log)
class OnlineDocExample(ConcreteModel):
diff --git a/pyomo/contrib/mindtpy/tests/test_mindtpy.py b/pyomo/contrib/mindtpy/tests/test_mindtpy.py
index 735439650a1..98983d81a15 100644
--- a/pyomo/contrib/mindtpy/tests/test_mindtpy.py
+++ b/pyomo/contrib/mindtpy/tests/test_mindtpy.py
@@ -1,5 +1,14 @@
-"""Tests for the MINDT solver plugin."""
-from math import fabs
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+"""Tests for the MindtPy solver."""
import pyomo.core.base.symbolic
import pyutilib.th as unittest
from pyomo.contrib.mindtpy.tests.eight_process_problem import \
@@ -10,11 +19,9 @@
from pyomo.contrib.mindtpy.tests.from_proposal import ProposalModel
from pyomo.contrib.mindtpy.tests.constraint_qualification_example import ConstraintQualificationExample
from pyomo.contrib.mindtpy.tests.online_doc_example import OnlineDocExample
-from pyomo.environ import SolverFactory, value
-from pyomo.environ import *
+from pyomo.environ import SolverFactory, value, maximize
from pyomo.solvers.tests.models.LP_unbounded import LP_unbounded
from pyomo.solvers.tests.models.QCP_simple import QCP_simple
-from pyomo.solvers.tests.models.MIQCP_simple import MIQCP_simple
from pyomo.opt import TerminationCondition
required_solvers = ('ipopt', 'glpk')
@@ -36,7 +43,7 @@ class TestMindtPy(unittest.TestCase):
def test_OA_8PP(self):
"""Test the outer approximation decomposition algorithm."""
with SolverFactory('mindtpy') as opt:
- model = EightProcessFlowsheet()
+ model = EightProcessFlowsheet(convex=False)
print('\n Solving 8PP problem with Outer Approximation')
results = opt.solve(model, strategy='OA',
init_strategy='rNLP',
@@ -51,7 +58,7 @@ def test_OA_8PP(self):
def test_OA_8PP_init_max_binary(self):
"""Test the outer approximation decomposition algorithm."""
with SolverFactory('mindtpy') as opt:
- model = EightProcessFlowsheet()
+ model = EightProcessFlowsheet(convex=False)
print('\n Solving 8PP problem with Outer Approximation(max_binary)')
results = opt.solve(model, strategy='OA',
init_strategy='max_binary',
@@ -65,7 +72,7 @@ def test_OA_8PP_init_max_binary(self):
def test_OA_8PP_L2_norm(self):
"""Test the outer approximation decomposition algorithm."""
with SolverFactory('mindtpy') as opt:
- model = EightProcessFlowsheet()
+ model = EightProcessFlowsheet(convex=False)
print('\n Solving 8PP problem with Outer Approximation(max_binary)')
results = opt.solve(model, strategy='OA',
mip_solver=required_solvers[1],
@@ -79,7 +86,7 @@ def test_OA_8PP_L2_norm(self):
def test_OA_8PP_sympy(self):
"""Test the outer approximation decomposition algorithm."""
with SolverFactory('mindtpy') as opt:
- model = EightProcessFlowsheet()
+ model = EightProcessFlowsheet(convex=False)
print('\n Solving 8PP problem with Outer Approximation(max_binary)')
results = opt.solve(model, strategy='OA',
mip_solver=required_solvers[1],
@@ -137,8 +144,7 @@ def test_OA_MINLP_simple(self):
results = opt.solve(model, strategy='OA',
init_strategy='initial_binary',
mip_solver=required_solvers[1],
- nlp_solver=required_solvers[0],
- obj_bound=10)
+ nlp_solver=required_solvers[0])
self.assertIs(results.solver.termination_condition,
TerminationCondition.optimal)
@@ -152,8 +158,7 @@ def test_OA_MINLP2_simple(self):
results = opt.solve(model, strategy='OA',
init_strategy='initial_binary',
mip_solver=required_solvers[1],
- nlp_solver=required_solvers[0],
- obj_bound=10)
+ nlp_solver=required_solvers[0])
self.assertIs(results.solver.termination_condition,
TerminationCondition.optimal)
@@ -166,8 +171,7 @@ def test_OA_MINLP3_simple(self):
print('\n Solving MINLP3_simple problem with Outer Approximation')
results = opt.solve(model, strategy='OA', init_strategy='initial_binary',
mip_solver=required_solvers[1],
- nlp_solver=required_solvers[0],
- obj_bound=10)
+ nlp_solver=required_solvers[0])
self.assertIs(results.solver.termination_condition,
TerminationCondition.optimal)
@@ -194,7 +198,7 @@ def test_OA_Proposal_with_int_cuts(self):
results = opt.solve(model, strategy='OA',
mip_solver=required_solvers[1],
nlp_solver=required_solvers[0],
- add_integer_cuts=True,
+ add_nogood_cuts=True,
integer_to_binary=True # if we use lazy callback, we cannot set integer_to_binary True
)
@@ -222,10 +226,10 @@ def test_OA_ConstraintQualificationExample_integer_cut(self):
results = opt.solve(model, strategy='OA',
mip_solver=required_solvers[1],
nlp_solver=required_solvers[0],
- add_integer_cuts=True
+ add_nogood_cuts=True
)
self.assertIs(results.solver.termination_condition,
- TerminationCondition.feasible)
+ TerminationCondition.optimal)
self.assertAlmostEqual(value(model.objective.expr), 3, places=2)
def test_OA_OnlineDocExample(self):
@@ -337,7 +341,6 @@ def test_initial_binary_add_slack(self):
init_strategy='initial_binary',
mip_solver=required_solvers[1],
nlp_solver=required_solvers[0],
- obj_bound=10,
add_slack=True)
self.assertIs(results.solver.termination_condition,
diff --git a/pyomo/contrib/mindtpy/tests/test_mindtpy_ECP.py b/pyomo/contrib/mindtpy/tests/test_mindtpy_ECP.py
new file mode 100644
index 00000000000..75a5631c755
--- /dev/null
+++ b/pyomo/contrib/mindtpy/tests/test_mindtpy_ECP.py
@@ -0,0 +1,289 @@
+"""Tests for the MindtPy solver."""
+from math import fabs
+import pyomo.core.base.symbolic
+import pyutilib.th as unittest
+from pyomo.contrib.mindtpy.tests.eight_process_problem import \
+ EightProcessFlowsheet
+from pyomo.contrib.mindtpy.tests.MINLP_simple import SimpleMINLP as SimpleMINLP
+from pyomo.contrib.mindtpy.tests.MINLP2_simple import SimpleMINLP as SimpleMINLP2
+from pyomo.contrib.mindtpy.tests.MINLP3_simple import SimpleMINLP as SimpleMINLP3
+from pyomo.contrib.mindtpy.tests.from_proposal import ProposalModel
+from pyomo.contrib.mindtpy.tests.constraint_qualification_example import ConstraintQualificationExample
+from pyomo.contrib.mindtpy.tests.online_doc_example import OnlineDocExample
+from pyomo.environ import SolverFactory, value
+from pyomo.environ import *
+from pyomo.solvers.tests.models.LP_unbounded import LP_unbounded
+from pyomo.solvers.tests.models.QCP_simple import QCP_simple
+from pyomo.solvers.tests.models.MIQCP_simple import MIQCP_simple
+from pyomo.opt import TerminationCondition
+
+required_solvers = ('ipopt', 'glpk')
+# required_solvers = ('gams', 'gams')
+if all(SolverFactory(s).available() for s in required_solvers):
+ subsolvers_available = True
+else:
+ subsolvers_available = False
+
+
+@unittest.skipIf(not subsolvers_available,
+ "Required subsolvers %s are not available"
+ % (required_solvers,))
+@unittest.skipIf(not pyomo.core.base.symbolic.differentiate_available,
+ "Symbolic differentiation is not available")
+class TestMindtPy(unittest.TestCase):
+ """Tests for the MindtPy solver plugin."""
+
+ def test_ECP_8PP(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with extended cutting plane')
+ results = opt.solve(model, strategy='ECP',
+ init_strategy='rNLP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ bound_tolerance=1E-5)
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_ECP_8PP_init_max_binary(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with extended cutting plane(max_binary)')
+ results = opt.solve(model, strategy='ECP',
+ init_strategy='max_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0], obj_bound=5500)
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_ECP_8PP_L2_norm(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with extended cutting plane(max_binary)')
+ results = opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0], obj_bound=5500,
+ feasibility_norm='L2')
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_ECP_8PP_sympy(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with extended cutting plane(max_binary)')
+ results = opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0], obj_bound=5500,
+ differentiate_mode='sympy')
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_ECP_MINLP_simple(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP()
+ print('\n Solving MINLP_simple problem with extended cutting plane')
+ results = opt.solve(model, strategy='ECP',
+ init_strategy='initial_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0])
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 3.5, places=2)
+
+ def test_ECP_MINLP2_simple(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP2()
+ print('\n Solving MINLP2_simple problem with extended cutting plane')
+ results = opt.solve(model, strategy='ECP',
+ init_strategy='initial_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0])
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 6.00976, places=2)
+
+ def test_ECP_MINLP3_simple(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP3()
+ print('\n Solving MINLP3_simple problem with extended cutting plane')
+ results = opt.solve(model, strategy='ECP', init_strategy='initial_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0])
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), -5.512, places=2)
+
+ def test_ECP_Proposal(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = ProposalModel()
+ print('\n Solving Proposal problem with extended cutting plane')
+ results = opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0])
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.obj.expr), 0.66555, places=2)
+
+ def test_ECP_ConstraintQualificationExample(self):
+ with SolverFactory('mindtpy') as opt:
+ model = ConstraintQualificationExample()
+ print(
+ '\n Solving Constraint Qualification Example with extended cutting plane')
+ results = opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0], bound_tolerance=1e-5
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.objective.expr), 3, places=2)
+
+ def test_ECP_OnlineDocExample(self):
+ with SolverFactory('mindtpy') as opt:
+ model = OnlineDocExample()
+ print('\n Solving Online Doc Example with extended cutting plane')
+ results = opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0], bound_tolerance=1e-3
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 2.438447, places=2)
+
+ def test_ECP_OnlineDocExample_L_infinity_norm(self):
+ with SolverFactory('mindtpy') as opt:
+ model = OnlineDocExample()
+ print('\n Solving Online Doc Example with extended cutting plane')
+ results = opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0], bound_tolerance=1e-3,
+ feasibility_norm="L_infinity"
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 2.438447, places=2)
+
+ # the following tests are used to improve code coverage
+
+ def test_iteration_limit(self):
+ with SolverFactory('mindtpy') as opt:
+ model = ConstraintQualificationExample()
+ print('\n test iteration_limit to improve code coverage')
+ opt.solve(model, strategy='ECP',
+ iteration_limit=1,
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0]
+ )
+ # self.assertAlmostEqual(value(model.objective.expr), 3, places=2)
+
+ def test_time_limit(self):
+ with SolverFactory('mindtpy') as opt:
+ model = ConstraintQualificationExample()
+ print('\n test time_limit to improve code coverage')
+ opt.solve(model, strategy='ECP',
+ time_limit=1,
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0]
+ )
+
+ def test_LP_case(self):
+ with SolverFactory('mindtpy') as opt:
+ m_class = LP_unbounded()
+ m_class._generate_model()
+ model = m_class.model
+ print('\n Solving LP case with extended cutting plane')
+ opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ )
+
+ def test_QCP_case(self):
+ with SolverFactory('mindtpy') as opt:
+ m_class = QCP_simple()
+ m_class._generate_model()
+ model = m_class.model
+ print('\n Solving QCP case with extended cutting plane')
+ opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ )
+
+ def test_maximize_obj(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = ProposalModel()
+ model.obj.sense = maximize
+ print('\n test maximize case to improve code coverage')
+ opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ # mip_solver_args={'timelimit': 0.9}
+ )
+ self.assertAlmostEqual(value(model.obj.expr), 14.83, places=1)
+
+ def test_rNLP_add_slack(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print(
+ '\n Test rNLP initialize strategy and add_slack to improve code coverage')
+ opt.solve(model, strategy='ECP',
+ init_strategy='rNLP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ bound_tolerance=1E-5,
+ add_slack=True)
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_initial_binary_add_slack(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP()
+ print(
+ '\n Test initial_binary initialize strategy and add_slack to improve code coverage')
+ results = opt.solve(model, strategy='ECP',
+ init_strategy='initial_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_slack=True)
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 3.5, places=2)
+
+ def test_maximize_obj(self):
+ """Test the extended cutting plane decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = ProposalModel()
+ model.obj.sense = maximize
+ print('\n test maximize case to improve code coverage')
+ opt.solve(model, strategy='ECP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0]
+ )
+ self.assertAlmostEqual(value(model.obj.expr), 14.83, places=1)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/pyomo/contrib/mindtpy/tests/test_mindtpy_global.py b/pyomo/contrib/mindtpy/tests/test_mindtpy_global.py
new file mode 100644
index 00000000000..401fb794672
--- /dev/null
+++ b/pyomo/contrib/mindtpy/tests/test_mindtpy_global.py
@@ -0,0 +1,293 @@
+"""Tests for the MindtPy solver."""
+from math import fabs
+import pyomo.core.base.symbolic
+import pyutilib.th as unittest
+from pyomo.contrib.mindtpy.tests.eight_process_problem import \
+ EightProcessFlowsheet
+from pyomo.contrib.mindtpy.tests.MINLP_simple import SimpleMINLP as SimpleMINLP
+from pyomo.contrib.mindtpy.tests.MINLP2_simple import SimpleMINLP as SimpleMINLP2
+from pyomo.contrib.mindtpy.tests.MINLP3_simple import SimpleMINLP as SimpleMINLP3
+from pyomo.contrib.mindtpy.tests.from_proposal import ProposalModel
+from pyomo.contrib.mindtpy.tests.constraint_qualification_example import ConstraintQualificationExample
+from pyomo.contrib.mindtpy.tests.online_doc_example import OnlineDocExample
+from pyomo.contrib.mindtpy.tests.nonconvex1 import Nonconvex1
+from pyomo.contrib.mindtpy.tests.nonconvex2 import Nonconvex2
+from pyomo.contrib.mindtpy.tests.nonconvex3 import Nonconvex3
+from pyomo.contrib.mindtpy.tests.nonconvex4 import Nonconvex4
+from pyomo.environ import SolverFactory, value
+from pyomo.environ import *
+from pyomo.solvers.tests.models.LP_unbounded import LP_unbounded
+from pyomo.solvers.tests.models.QCP_simple import QCP_simple
+from pyomo.solvers.tests.models.MIQCP_simple import MIQCP_simple
+from pyomo.opt import TerminationCondition
+
+required_solvers = ('baron', 'cplex')
+if not all(SolverFactory(s).available(False) for s in required_solvers):
+ subsolvers_available = False
+elif not SolverFactory('baron').license_is_valid():
+ subsolvers_available = False
+else:
+ subsolvers_available = True
+
+
+@unittest.skipIf(not subsolvers_available,
+ "Required subsolvers %s are not available"
+ % (required_solvers,))
+@unittest.skipIf(not pyomo.core.base.symbolic.differentiate_available,
+ "Symbolic differentiation is not available")
+@unittest.skipIf(not pyomo.contrib.mcpp.pyomo_mcpp.mcpp_available(),
+ "MC++ is not available")
+class TestMindtPy(unittest.TestCase):
+ """Tests for the MindtPy solver plugin."""
+
+ def test_GOA_8PP(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ init_strategy='rNLP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ bound_tolerance=1E-5)
+
+ self.assertIn(results.solver.termination_condition, [
+ TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_GOA_8PP_init_max_binary(self):
+ """Test the outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with Outer Approximation(max_binary)')
+ results = opt.solve(model, strategy='GOA',
+ init_strategy='max_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True)
+
+ self.assertIn(results.solver.termination_condition, [
+ TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_GOA_8PP_L2_norm(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with Outer Approximation(L2_norm)')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ feasibility_norm='L2',
+ add_nogood_cuts=True)
+
+ self.assertIn(results.solver.termination_condition, [
+ TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_GOA_8PP_sympy(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with Outer Approximation(sympy)')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ differentiate_mode='sympy',
+ add_nogood_cuts=True)
+
+ self.assertIn(results.solver.termination_condition, [
+ TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_GOA_MINLP_simple(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP()
+ print('\n Solving MINLP_simple problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ obj_bound=10,
+ add_nogood_cuts=True)
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 3.5, places=2)
+
+ def test_GOA_MINLP2_simple(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP2()
+ print('\n Solving MINLP2_simple problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ init_strategy='initial_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ obj_bound=10,
+ add_nogood_cuts=True)
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 6.00976, places=2)
+
+ def test_GOA_MINLP3_simple(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP3()
+ print('\n Solving MINLP3_simple problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA', init_strategy='initial_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ obj_bound=10,
+ add_nogood_cuts=True,
+ use_mcpp=True)
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), -5.512, places=2)
+
+ def test_GOA_Proposal(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = ProposalModel()
+ print('\n Solving Proposal problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ integer_to_binary=True)
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.obj.expr), 0.66555, places=2)
+
+ def test_GOA_Proposal_with_int_cuts(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = ProposalModel()
+ print('\n Solving Proposal problem with Outer Approximation(integer cuts)')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ integer_to_binary=True # if we use lazy callback, we cannot set integer_to_binary True
+ )
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.obj.expr), 0.66555, places=2)
+
+ def test_GOA_ConstraintQualificationExample(self):
+ with SolverFactory('mindtpy') as opt:
+ model = ConstraintQualificationExample()
+ print(
+ '\n Solving Constraint Qualification Example with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ )
+ # self.assertIs(results.solver.termination_condition,
+ # TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.objective.expr), 3, places=2)
+
+ def test_GOA_ConstraintQualificationExample_integer_cut(self):
+ with SolverFactory('mindtpy') as opt:
+ model = ConstraintQualificationExample()
+ print(
+ '\n Solving Constraint Qualification Example with global Outer Approximation(integer cut)')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True
+ )
+ self.assertIn(results.solver.termination_condition, [
+ TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.objective.expr), 3, places=2)
+
+ def test_GOA_OnlineDocExample(self):
+ with SolverFactory('mindtpy') as opt:
+ model = OnlineDocExample()
+ print('\n Solving Online Doc Example with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True
+ )
+ # self.assertIs(results.solver.termination_condition,
+ # TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 2.438447, places=2)
+
+ def test_GOA_OnlineDocExample_L_infinity_norm(self):
+ with SolverFactory('mindtpy') as opt:
+ model = OnlineDocExample()
+ print('\n Solving Online Doc Example with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ feasibility_norm="L_infinity",
+ add_nogood_cuts=True,
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 2.438447, places=2)
+
+ def test_GOA_Nonconvex1(self):
+ with SolverFactory('mindtpy') as opt:
+ model = Nonconvex1()
+ print('\n Solving Nonconvex1 with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver='baron',
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 7.667, places=2)
+
+ def test_GOA_Nonconvex2(self):
+ with SolverFactory('mindtpy') as opt:
+ model = Nonconvex2()
+ print('\n Solving Nonconvex2 with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver='baron',
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), -0.94347, places=2)
+
+ def test_GOA_Nonconvex3(self):
+ with SolverFactory('mindtpy') as opt:
+ model = Nonconvex3()
+ print('\n Solving Nonconvex3 with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver='baron',
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 31, places=2)
+
+ def test_GOA_Nonconvex4(self):
+ with SolverFactory('mindtpy') as opt:
+ model = Nonconvex4()
+ print('\n Solving Nonconvex4 with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver='baron',
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), -17, places=2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/pyomo/contrib/mindtpy/tests/test_mindtpy_global_lp_nlp.py b/pyomo/contrib/mindtpy/tests/test_mindtpy_global_lp_nlp.py
new file mode 100644
index 00000000000..bafa8fe703e
--- /dev/null
+++ b/pyomo/contrib/mindtpy/tests/test_mindtpy_global_lp_nlp.py
@@ -0,0 +1,311 @@
+"""Tests for the MindtPy solver."""
+from math import fabs
+import pyomo.core.base.symbolic
+import pyutilib.th as unittest
+from pyomo.contrib.mindtpy.tests.eight_process_problem import \
+ EightProcessFlowsheet
+from pyomo.contrib.mindtpy.tests.MINLP_simple import SimpleMINLP as SimpleMINLP
+from pyomo.contrib.mindtpy.tests.MINLP2_simple import SimpleMINLP as SimpleMINLP2
+from pyomo.contrib.mindtpy.tests.MINLP3_simple import SimpleMINLP as SimpleMINLP3
+from pyomo.contrib.mindtpy.tests.from_proposal import ProposalModel
+from pyomo.contrib.mindtpy.tests.constraint_qualification_example import ConstraintQualificationExample
+from pyomo.contrib.mindtpy.tests.online_doc_example import OnlineDocExample
+from pyomo.contrib.mindtpy.tests.nonconvex1 import Nonconvex1
+from pyomo.contrib.mindtpy.tests.nonconvex2 import Nonconvex2
+from pyomo.contrib.mindtpy.tests.nonconvex3 import Nonconvex3
+from pyomo.contrib.mindtpy.tests.nonconvex4 import Nonconvex4
+from pyomo.environ import SolverFactory, value
+from pyomo.environ import *
+from pyomo.solvers.tests.models.LP_unbounded import LP_unbounded
+from pyomo.solvers.tests.models.QCP_simple import QCP_simple
+from pyomo.solvers.tests.models.MIQCP_simple import MIQCP_simple
+
+from pyomo.opt import TerminationCondition
+
+required_solvers = ('baron', 'cplex_persistent')
+if not all(SolverFactory(s).available(False) for s in required_solvers):
+ subsolvers_available = False
+elif not SolverFactory('baron').license_is_valid():
+ subsolvers_available = False
+else:
+ subsolvers_available = True
+
+
+@unittest.skipIf(not subsolvers_available,
+ "Required subsolvers %s are not available"
+ % (required_solvers,))
+@unittest.skipIf(not pyomo.core.base.symbolic.differentiate_available,
+ "Symbolic differentiation is not available")
+@unittest.skipIf(not pyomo.contrib.mcpp.pyomo_mcpp.mcpp_available(),
+ "MC++ is not available")
+class TestMindtPy(unittest.TestCase):
+ """Tests for the MindtPy solver plugin."""
+
+ def test_GOA_8PP(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ init_strategy='rNLP',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ bound_tolerance=1E-5,
+ single_tree=True)
+
+ self.assertIn(results.solver.termination_condition,
+ [TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_GOA_8PP_init_max_binary(self):
+ """Test the outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with Outer Approximation(max_binary)')
+ results = opt.solve(model, strategy='GOA',
+ init_strategy='max_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ single_tree=True)
+
+ self.assertIn(results.solver.termination_condition,
+ [TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_GOA_8PP_L2_norm(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with Outer Approximation(L2_norm)')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ feasibility_norm='L2',
+ add_nogood_cuts=True,
+ single_tree=True)
+
+ self.assertIn(results.solver.termination_condition,
+ [TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_GOA_8PP_sympy(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = EightProcessFlowsheet()
+ print('\n Solving 8PP problem with Outer Approximation(sympy)')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ differentiate_mode='sympy',
+ add_nogood_cuts=True,
+ single_tree=True)
+
+ self.assertIn(results.solver.termination_condition,
+ [TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
+
+ def test_GOA_MINLP_simple(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP()
+ print('\n Solving MINLP_simple problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ obj_bound=10,
+ add_nogood_cuts=True,
+ single_tree=True)
+
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 3.5, places=2)
+
+ # if no affine cuts is added in lp/nlp , stop
+
+ def test_GOA_MINLP2_simple(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP2()
+ print('\n Solving MINLP2_simple problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver='baron',
+ add_nogood_cuts=True,
+ single_tree=True,
+ bound_tolerance=1E-2
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.cost.expr), 6.00976, places=2)
+
+ def test_GOA_MINLP3_simple(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = SimpleMINLP3()
+ print('\n Solving MINLP3_simple problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA', init_strategy='initial_binary',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ obj_bound=10,
+ add_nogood_cuts=True,
+ use_mcpp=True,
+ single_tree=True)
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.feasible)
+ self.assertAlmostEqual(value(model.cost.expr), -5.512, places=2)
+
+ def test_GOA_Proposal(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = ProposalModel()
+ print('\n Solving Proposal problem with Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ integer_to_binary=True,
+ single_tree=True)
+
+ self.assertIn(results.solver.termination_condition,
+ [TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.obj.expr), 0.66555, places=2)
+
+ def test_GOA_Proposal_with_int_cuts(self):
+ """Test the global outer approximation decomposition algorithm."""
+ with SolverFactory('mindtpy') as opt:
+ model = ProposalModel()
+ print('\n Solving Proposal problem with Outer Approximation(integer cuts)')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ integer_to_binary=True, # if we use lazy callback, we cannot set integer_to_binary True
+ single_tree=True
+ )
+
+ self.assertIn(results.solver.termination_condition,
+ [TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.obj.expr), 0.66555, places=2)
+
+ def test_GOA_ConstraintQualificationExample(self):
+ with SolverFactory('mindtpy') as opt:
+ model = ConstraintQualificationExample()
+ print(
+ '\n Solving Constraint Qualification Example with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ single_tree=True
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(value(model.objective.expr), 3, places=2)
+
+ def test_GOA_ConstraintQualificationExample_integer_cut(self):
+ with SolverFactory('mindtpy') as opt:
+ model = ConstraintQualificationExample()
+ print(
+ '\n Solving Constraint Qualification Example with global Outer Approximation(integer cut)')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ single_tree=True
+ )
+ self.assertIn(results.solver.termination_condition, [
+ TerminationCondition.optimal, TerminationCondition.feasible])
+ self.assertAlmostEqual(value(model.objective.expr), 3, places=2)
+
+ def test_GOA_OnlineDocExample(self):
+ with SolverFactory('mindtpy') as opt:
+ model = OnlineDocExample()
+ print('\n Solving Online Doc Example with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ add_nogood_cuts=True,
+ single_tree=True
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 2.438447, places=2)
+
+ def test_GOA_OnlineDocExample_L_infinity_norm(self):
+ with SolverFactory('mindtpy') as opt:
+ model = OnlineDocExample()
+ print('\n Solving Online Doc Example with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver=required_solvers[0],
+ feasibility_norm="L_infinity",
+ add_nogood_cuts=True,
+ single_tree=True
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 2.438447, places=2)
+
+ def test_GOA_Nonconvex1(self):
+ with SolverFactory('mindtpy') as opt:
+ model = Nonconvex1()
+ print('\n Solving Nonconvex1 with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver='baron',
+ single_tree=True
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 7.667, places=2)
+
+ def test_GOA_Nonconvex2(self):
+ with SolverFactory('mindtpy') as opt:
+ model = Nonconvex2()
+ print('\n Solving Nonconvex2 with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver='baron',
+ single_tree=True,
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), -0.94347, places=2)
+
+ def test_GOA_Nonconvex3(self):
+ with SolverFactory('mindtpy') as opt:
+ model = Nonconvex3()
+ print('\n Solving Nonconvex3 with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver='baron',
+ single_tree=True
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), 31, places=2)
+
+ def test_GOA_Nonconvex4(self):
+ with SolverFactory('mindtpy') as opt:
+ model = Nonconvex4()
+ print('\n Solving Nonconvex4 with global Outer Approximation')
+ results = opt.solve(model, strategy='GOA',
+ mip_solver=required_solvers[1],
+ nlp_solver='baron',
+ single_tree=True,
+ )
+ self.assertIs(results.solver.termination_condition,
+ TerminationCondition.optimal)
+ self.assertAlmostEqual(
+ value(model.objective.expr), -17, places=2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/pyomo/contrib/mindtpy/tests/test_mindtpy_lp_nlp.py b/pyomo/contrib/mindtpy/tests/test_mindtpy_lp_nlp.py
index 6cf764b0b37..53fef35ff41 100644
--- a/pyomo/contrib/mindtpy/tests/test_mindtpy_lp_nlp.py
+++ b/pyomo/contrib/mindtpy/tests/test_mindtpy_lp_nlp.py
@@ -1,5 +1,14 @@
-"""Tests for the MINDT solver plugin."""
-from math import fabs
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+"""Tests for the MindtPy solver."""
import pyomo.core.base.symbolic
import pyutilib.th as unittest
from pyomo.contrib.mindtpy.tests.eight_process_problem import \
@@ -42,8 +51,8 @@ def test_lazy_OA_8PP(self):
bound_tolerance=1E-5,
single_tree=True)
- self.assertIs(results.solver.termination_condition,
- TerminationCondition.optimal)
+ self.assertIn(results.solver.termination_condition,
+ [TerminationCondition.optimal, TerminationCondition.feasible])
self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
def test_lazy_OA_8PP_init_max_binary(self):
@@ -57,8 +66,8 @@ def test_lazy_OA_8PP_init_max_binary(self):
nlp_solver=required_solvers[0],
single_tree=True)
- self.assertIs(results.solver.termination_condition,
- TerminationCondition.optimal)
+ self.assertIn(results.solver.termination_condition,
+ [TerminationCondition.optimal, TerminationCondition.feasible])
self.assertAlmostEqual(value(model.cost.expr), 68, places=1)
def test_lazy_OA_MINLP_simple(self):
@@ -117,8 +126,8 @@ def test_lazy_OA_Proposal(self):
nlp_solver=required_solvers[0],
single_tree=True)
- self.assertIs(results.solver.termination_condition,
- TerminationCondition.optimal)
+ self.assertIn(results.solver.termination_condition,
+ [TerminationCondition.optimal, TerminationCondition.feasible])
self.assertAlmostEqual(value(model.obj.expr), 0.66555, places=2)
def test_lazy_OA_ConstraintQualificationExample(self):
@@ -131,7 +140,7 @@ def test_lazy_OA_ConstraintQualificationExample(self):
single_tree=True
)
self.assertIs(results.solver.termination_condition,
- TerminationCondition.maxIterations)
+ TerminationCondition.feasible)
self.assertAlmostEqual(value(model.objective.expr), 3, places=2)
def test_OA_OnlineDocExample(self):
diff --git a/pyomo/contrib/mindtpy/util.py b/pyomo/contrib/mindtpy/util.py
index c5ee9c4ddd0..c95b85d88c7 100644
--- a/pyomo/contrib/mindtpy/util.py
+++ b/pyomo/contrib/mindtpy/util.py
@@ -1,19 +1,26 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Utility functions and classes for the MindtPy solver."""
from __future__ import division
import logging
-from math import fabs, floor, log
-
-from pyomo.common.collections import ComponentMap, ComponentSet
-from pyomo.core import (Any, Binary, Block, Constraint, NonNegativeReals,
- Objective, Reals, Suffix, Var, minimize, value)
+from pyomo.common.collections import ComponentMap
+from pyomo.core import Objective, Suffix
from pyomo.core.expr import differentiate
from pyomo.core.expr import current as EXPR
-from pyomo.core.expr.numvalue import native_numeric_types
from pyomo.opt import SolverFactory
-from pyomo.opt.results import ProblemSense
from pyomo.solvers.plugins.solvers.persistent_solver import PersistentSolver
+logger = logging.getLogger('pyomo.contrib')
+
class MindtPySolveData(object):
"""Data container to hold solve-instance data.
@@ -25,11 +32,22 @@ class MindtPySolveData(object):
def model_is_valid(solve_data, config):
- """Validate that the model is solveable by MindtPy.
+ """
+ Determines whether the model is solveable by MindtPy.
- Also preforms some preprocessing such as moving the objective to the
- constraints.
+ This function returns True if the given model is solveable by MindtPy (and performs some preprocessing such
+ as moving the objective to the constraints).
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: MindtPy configurations
+ contains the specific configurations for the algorithm
+
+ Returns
+ -------
+ Boolean value (True if model is solveable in MindtPy else False)
"""
m = solve_data.working_model
MindtPy = m.MindtPy_utils
@@ -47,7 +65,7 @@ def model_is_valid(solve_data, config):
"Your model is an NLP (nonlinear program). "
"Using NLP solver %s to solve." % config.nlp_solver)
SolverFactory(config.nlp_solver).solve(
- solve_data.original_model, **config.nlp_solver_args)
+ solve_data.original_model, tee=config.solver_tee, **config.nlp_solver_args)
return False
else:
config.logger.info(
@@ -56,20 +74,34 @@ def model_is_valid(solve_data, config):
mipopt = SolverFactory(config.mip_solver)
if isinstance(mipopt, PersistentSolver):
mipopt.set_instance(solve_data.original_model)
-
- mipopt.solve(solve_data.original_model, **config.mip_solver_args)
+ if config.threads > 0:
+ mipopt.options["threads"] = config.threads
+ mipopt.solve(solve_data.original_model,
+ tee=config.solver_tee, **config.mip_solver_args)
return False
- if not hasattr(m, 'dual'): # Set up dual value reporting
+ if not hasattr(m, 'dual') and config.use_dual: # Set up dual value reporting
m.dual = Suffix(direction=Suffix.IMPORT)
- # TODO if any continuous variables are multipled with binary ones, need
- # to do some kind of transformation (Glover?) or throw an error message
+ # TODO if any continuous variables are multiplied with binary ones,
+ # need to do some kind of transformation (Glover?) or throw an error message
return True
def calc_jacobians(solve_data, config):
- """Generate a map of jacobians."""
+ """
+ Generates a map of jacobians for the variables in the model
+
+ This function generates a map of jacobians corresponding to the variables in the model and adds this
+ ComponentMap to solve_data
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: MindtPy configurations
+ contains the specific configurations for the algorithm
+ """
# Map nonlinear_constraint --> Map(
# variable --> jacobian of constraint wrt. variable)
solve_data.jacobians = ComponentMap()
@@ -89,24 +121,53 @@ def calc_jacobians(solve_data, config):
def add_feas_slacks(m, config):
+ """
+ Adds feasibility slack variables according to config.feasibility_norm (given an infeasible problem)
+
+ Parameters
+ ----------
+ m: model
+ Pyomo model
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+ """
MindtPy = m.MindtPy_utils
# generate new constraints
for i, constr in enumerate(MindtPy.constraint_list, 1):
if constr.body.polynomial_degree() not in [0, 1]:
- rhs = constr.upper if constr.has_ub() else constr.lower
- if config.feasibility_norm in {'L1', 'L2'}:
- c = MindtPy.MindtPy_feas.feas_constraints.add(
- constr.body - rhs
- <= MindtPy.MindtPy_feas.slack_var[i])
- else:
- c = MindtPy.MindtPy_feas.feas_constraints.add(
- constr.body - rhs
- <= MindtPy.MindtPy_feas.slack_var)
+ if constr.has_ub():
+ if config.feasibility_norm in {'L1', 'L2'}:
+ c = MindtPy.MindtPy_feas.feas_constraints.add(
+ constr.body - constr.upper
+ <= MindtPy.MindtPy_feas.slack_var[i])
+ else:
+ c = MindtPy.MindtPy_feas.feas_constraints.add(
+ constr.body - constr.upper
+ <= MindtPy.MindtPy_feas.slack_var)
+ if constr.has_lb():
+ if config.feasibility_norm in {'L1', 'L2'}:
+ c = MindtPy.MindtPy_feas.feas_constraints.add(
+ constr.body - constr.lower
+ >= -MindtPy.MindtPy_feas.slack_var[i])
+ else:
+ c = MindtPy.MindtPy_feas.feas_constraints.add(
+ constr.body - constr.lower
+ >= -MindtPy.MindtPy_feas.slack_var)
def var_bound_add(solve_data, config):
- """This function will add bound for variables in nonlinear constraints if they are not bounded.
- This is to avoid an unbound master problem in the LP/NLP algorithm.
+ """
+ This function will add bounds for variables in nonlinear constraints if they are not bounded. (This is to avoid
+ an unbounded master problem in the LP/NLP algorithm.) Thus, the model will be updated to include bounds for the
+ unbounded variables in nonlinear constraints.
+
+ Parameters
+ ----------
+ solve_data: MindtPy Data Container
+ data container that holds solve-instance data
+ config: ConfigBlock
+ contains the specific configurations for the algorithm
+
"""
m = solve_data.working_model
MindtPy = m.MindtPy_utils
diff --git a/pyomo/contrib/parmest/examples/reactor_design/reactor_design.py b/pyomo/contrib/parmest/examples/reactor_design/reactor_design.py
index c90da3ab820..4b243fc9c69 100644
--- a/pyomo/contrib/parmest/examples/reactor_design/reactor_design.py
+++ b/pyomo/contrib/parmest/examples/reactor_design/reactor_design.py
@@ -12,8 +12,7 @@
pyomo\examples\doc\pyomobook\nonlinear-ch\react_design\ReactorDesign.py
"""
import pandas as pd
-from pyomo.environ import *
-from pyomo.core import *
+from pyomo.environ import ConcreteModel, Var, PositiveReals, Objective, Constraint, maximize, SolverFactory
def reactor_design_model(data):
diff --git a/pyomo/contrib/parmest/examples/rooney_biegler/rooney_biegler.py b/pyomo/contrib/parmest/examples/rooney_biegler/rooney_biegler.py
index 72a60799bf4..6d2a114ea5d 100644
--- a/pyomo/contrib/parmest/examples/rooney_biegler/rooney_biegler.py
+++ b/pyomo/contrib/parmest/examples/rooney_biegler/rooney_biegler.py
@@ -7,38 +7,42 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
"""
Rooney Biegler model, based on Rooney, W. C. and Biegler, L. T. (2001). Design for
model parameter uncertainty using nonlinear confidence regions. AIChE Journal,
47(8), 1794-1804.
"""
+
import pandas as pd
import pyomo.environ as pyo
+
def rooney_biegler_model(data):
-
+
model = pyo.ConcreteModel()
model.asymptote = pyo.Var(initialize = 15)
model.rate_constant = pyo.Var(initialize = 0.5)
-
+
def response_rule(m, h):
expr = m.asymptote * (1 - pyo.exp(-m.rate_constant * h))
return expr
model.response_function = pyo.Expression(data.hour, rule = response_rule)
-
+
def SSE_rule(m):
return sum((data.y[i] - m.response_function[data.hour[i]])**2 for i in data.index)
model.SSE = pyo.Objective(rule = SSE_rule, sense=pyo.minimize)
-
+
return model
+
if __name__ == '__main__':
-
+
# These were taken from Table A1.4 in Bates and Watts (1988).
data = pd.DataFrame(data=[[1,8.3],[2,10.3],[3,19.0],[4,16.0],[5,15.6],[7,19.8]],
columns=['hour', 'y'])
-
+
model = rooney_biegler_model(data)
solver = pyo.SolverFactory('ipopt')
solver.solve(model)
diff --git a/pyomo/contrib/parmest/examples/semibatch/semibatch.py b/pyomo/contrib/parmest/examples/semibatch/semibatch.py
index 7c267e65bff..552eace1d92 100644
--- a/pyomo/contrib/parmest/examples/semibatch/semibatch.py
+++ b/pyomo/contrib/parmest/examples/semibatch/semibatch.py
@@ -14,8 +14,8 @@
algebraic equations. Mathematical Programming Computation, 10(2), 187-223.
"""
import json
-from pyomo.environ import *
-from pyomo.dae import *
+from pyomo.environ import ConcreteModel, Set, Param, Var, Constraint, ConstraintList, Expression, Objective, TransformationFactory, SolverFactory, exp, minimize
+from pyomo.dae import ContinuousSet, DerivativeVar
def generate_model(data):
diff --git a/pyomo/contrib/parmest/graphics.py b/pyomo/contrib/parmest/graphics.py
index be20338772e..ec76070c911 100644
--- a/pyomo/contrib/parmest/graphics.py
+++ b/pyomo/contrib/parmest/graphics.py
@@ -32,6 +32,7 @@
except (ImportError, RuntimeError, SyntaxError):
imports_available = False
+from pyomo.common.dependencies import check_min_version
def _get_variables(ax,columns):
sps = ax.get_subplotspec()
@@ -93,15 +94,16 @@ def _get_data_slice(xvar,yvar,columns,data,theta_star):
return X,Y,Z
-
-def _add_scatter(x,y,color,label,columns,theta_star):
+# Note: seaborn 0.11 no longer expects color and label to be passed to the
+# plotting functions. label is kept here for backward compatibility
+def _add_scatter(x,y,color,columns,theta_star,label=None):
ax = plt.gca()
xvar, yvar, loc = _get_variables(ax, columns)
ax.scatter(theta_star[xvar], theta_star[yvar], c=color, s=35)
-def _add_rectangle_CI(x,y,color,label,columns,lower_bound,upper_bound):
+def _add_rectangle_CI(x,y,color,columns,lower_bound,upper_bound,label=None):
ax = plt.gca()
xvar, yvar, loc = _get_variables(ax,columns)
@@ -116,7 +118,7 @@ def _add_rectangle_CI(x,y,color,label,columns,lower_bound,upper_bound):
ax.plot([xmin, xmin], [ymax, ymin], color=color)
-def _add_scipy_dist_CI(x,y,color,label,columns,ncells,alpha,dist,theta_star):
+def _add_scipy_dist_CI(x,y,color,columns,ncells,alpha,dist,theta_star,label=None):
ax = plt.gca()
xvar, yvar, loc = _get_variables(ax,columns)
@@ -152,7 +154,7 @@ def _add_scipy_dist_CI(x,y,color,label,columns,ncells,alpha,dist,theta_star):
ax.contour(X,Y,Z, levels=[alpha], colors=color)
-def _add_obj_contour(x,y,color,label,columns,data,theta_star):
+def _add_obj_contour(x,y,color,columns,data,theta_star,label=None):
ax = plt.gca()
xvar, yvar, loc = _get_variables(ax,columns)
@@ -165,18 +167,6 @@ def _add_obj_contour(x,y,color,label,columns,data,theta_star):
plt.tricontourf(triang,Z,cmap=cmap)
except:
print('Objective contour plot for', xvar, yvar,'slice failed')
-
-
-def _add_LR_contour(x,y,color,label,columns,data,theta_star,threshold):
- ax = plt.gca()
- xvar, yvar, loc = _get_variables(ax,columns)
-
- X, Y, Z = _get_data_slice(xvar,yvar,columns,data,theta_star)
-
- triang = tri.Triangulation(X, Y)
-
- plt.tricontour(triang,Z,[threshold], colors='r')
-
def _set_axis_limits(g, axis_limits, theta_vals, theta_star):
@@ -273,7 +263,13 @@ def pairwise_plot(theta_values, theta_star=None, alpha=None, distributions=[],
g = sns.PairGrid(thetas)
# Plot histogram on the diagonal
- g.map_diag(sns.distplot, kde=False, hist=True, norm_hist=False)
+ # Note: distplot is deprecated and will be removed in a future
+ # version of seaborn, use histplot. distplot is kept for older
+ # versions of python.
+ if check_min_version(sns, "0.11"):
+ g.map_diag(sns.histplot)
+ else:
+ g.map_diag(sns.distplot, kde=False, hist=True, norm_hist=False)
# Plot filled contours using all theta values based on obj
if 'obj' in theta_values.columns and add_obj_contour:
diff --git a/pyomo/contrib/parmest/mpi_utils.py b/pyomo/contrib/parmest/mpi_utils.py
index 7183461f443..71344786229 100644
--- a/pyomo/contrib/parmest/mpi_utils.py
+++ b/pyomo/contrib/parmest/mpi_utils.py
@@ -10,6 +10,7 @@
from collections import OrderedDict
import importlib
+from six import iteritems
"""
This module is a collection of classes that provide a
friendlier interface to MPI (through mpi4py). They help
@@ -117,7 +118,7 @@ def global_to_local_data(self, global_data):
local_data = OrderedDict()
assert (len(global_data) == self._n_total_tasks)
idx = 0
- for k,v in six.iteritems(global_data):
+ for k,v in iteritems(global_data):
if idx in self._local_map:
local_data[k] = v
idx += idx
diff --git a/pyomo/contrib/parmest/parmest.py b/pyomo/contrib/parmest/parmest.py
index 3078ae4554a..d1848787e8e 100644
--- a/pyomo/contrib/parmest/parmest.py
+++ b/pyomo/contrib/parmest/parmest.py
@@ -19,7 +19,6 @@
pandas as pd, pandas_available,
scipy, scipy_available,
)
-parmest_available = numpy_available & pandas_available & scipy_available
import pyomo.environ as pyo
import pyomo.pysp.util.rapper as st
@@ -29,20 +28,24 @@
import pyomo.contrib.parmest.mpi_utils as mpiu
import pyomo.contrib.parmest.ipopt_solver_wrapper as ipopt_solver_wrapper
-from pyomo.contrib.parmest.graphics import pairwise_plot, grouped_boxplot, grouped_violinplot, \
- fit_rect_dist, fit_mvn_dist, fit_kde_dist
+from pyomo.contrib.parmest.graphics import (fit_rect_dist,
+ fit_mvn_dist,
+ fit_kde_dist)
+
+parmest_available = numpy_available & pandas_available & scipy_available
if numpy_available and scipy_available:
from pyomo.contrib.pynumero.asl import AmplInterface
asl_available = AmplInterface.available()
else:
- asl_available=False
+ asl_available = False
if asl_available:
from pyomo.contrib.interior_point.inverse_reduced_hessian import inv_reduced_hessian_barrier
__version__ = 0.1
+
#=============================================
def _object_from_string(instance, vstr):
"""
@@ -51,8 +54,8 @@ def _object_from_string(instance, vstr):
instance: a concrete pyomo model
vstr: a particular Var or Param (e.g. "pp.Keq_a[2]")
output:
- the object
- NOTE: We need to deal with blocks
+ the object
+ NOTE: We need to deal with blocks
and with indexes that might really be strings or ints
"""
# pull off the index
@@ -554,11 +557,11 @@ def _Q_opt(self, ThetaVals=None, solver="ef_ipopt",
if len(return_values) > 0:
var_values = []
- for exp_i in stsolver.ef_instance.component_objects(Block, descend_into=False):
+ for exp_i in self.ef_instance.component_objects(Block, descend_into=False):
vals = {}
for var in return_values:
exp_i_var = eval('exp_i.'+ str(var))
- temp = [_.value for _ in exp_i_var.itervalues()]
+ temp = [pyo.value(_) for _ in exp_i_var.itervalues()]
if len(temp) == 1:
vals[var] = temp[0]
else:
diff --git a/pyomo/contrib/parmest/scenariocreator.py b/pyomo/contrib/parmest/scenariocreator.py
index 46e946c555f..720bc897242 100644
--- a/pyomo/contrib/parmest/scenariocreator.py
+++ b/pyomo/contrib/parmest/scenariocreator.py
@@ -1,8 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
# ScenariosCreator.py - Class to create and deliver scenarios using parmest
# DLW March 2020
-import json
-import pyomo.contrib.parmest.parmest as parmest
import pyomo.environ as pyo
diff --git a/pyomo/contrib/parmest/tests/test_parmest.py b/pyomo/contrib/parmest/tests/test_parmest.py
index 8fd0cf349c0..d67d6b9a150 100644
--- a/pyomo/contrib/parmest/tests/test_parmest.py
+++ b/pyomo/contrib/parmest/tests/test_parmest.py
@@ -24,13 +24,9 @@
is_osx = platform.mac_ver()[0] != ''
import pyutilib.th as unittest
-import tempfile
import sys
import os
-import shutil
-import glob
import subprocess
-import sys
from itertools import product
import pyomo.contrib.parmest.parmest as parmest
@@ -121,9 +117,9 @@ def test_bootstrap(self):
self.assertTrue(CR[0.75].sum() == 7)
self.assertTrue(CR[1.0].sum() == 10) # all true
- parmest.pairwise_plot(theta_est)
- parmest.pairwise_plot(theta_est, thetavals)
- parmest.pairwise_plot(theta_est, thetavals, 0.8, ['MVN', 'KDE', 'Rect'])
+ graphics.pairwise_plot(theta_est)
+ graphics.pairwise_plot(theta_est, thetavals)
+ graphics.pairwise_plot(theta_est, thetavals, 0.8, ['MVN', 'KDE', 'Rect'])
@unittest.skipIf(not graphics.imports_available,
"parmest.graphics imports are unavailable")
@@ -143,7 +139,7 @@ def test_likelihood_ratio(self):
self.assertTrue(LR[0.9].sum() == 11)
self.assertTrue(LR[1.0].sum() == 60) # all true
- parmest.pairwise_plot(LR, thetavals, 0.8)
+ graphics.pairwise_plot(LR, thetavals, 0.8)
def test_leaveNout(self):
lNo_theta = self.pest.theta_est_leaveNout(1)
@@ -272,7 +268,7 @@ def test_theta_est_cov(self):
@unittest.skipIf(not imports_present, "Cannot test parmest: required dependencies are missing")
-@unittest.skipIf(not ipopt_available, "The 'ipopt' command is not available")
+@unittest.skipIf(not ipopt_available, "The 'ipopt' solver is not available")
class parmest_object_Tester_reactor_design(unittest.TestCase):
def setUp(self):
@@ -320,6 +316,13 @@ def test_theta_est(self):
self.assertAlmostEqual(thetavals['k1'], 5.0/6.0, places=4)
self.assertAlmostEqual(thetavals['k2'], 5.0/3.0, places=4)
self.assertAlmostEqual(thetavals['k3'], 1.0/6000.0, places=7)
+
+ def test_return_values(self):
+ objval, thetavals, data_rec =\
+ self.pest.theta_est(return_values=['ca', 'cb', 'cc', 'cd', 'caf'])
+ self.assertAlmostEqual(data_rec["cc"].loc[18], 893.84924, places=3)
+
+
@unittest.skipIf(not parmest.parmest_available,
"Cannot test parmest: required dependencies are missing")
@@ -333,14 +336,14 @@ def setUp(self):
self.B = pd.DataFrame(np.random.randint(0,100,size=(100,4)), columns=list('ABCD'))
def test_pairwise_plot(self):
- parmest.pairwise_plot(self.A, alpha=0.8, distributions=['Rect', 'MVN', 'KDE'])
+ graphics.pairwise_plot(self.A, alpha=0.8, distributions=['Rect', 'MVN', 'KDE'])
def test_grouped_boxplot(self):
- parmest.grouped_boxplot(self.A, self.B, normalize=True,
+ graphics.grouped_boxplot(self.A, self.B, normalize=True,
group_names=['A', 'B'])
def test_grouped_violinplot(self):
- parmest.grouped_violinplot(self.A, self.B)
+ graphics.grouped_violinplot(self.A, self.B)
if __name__ == '__main__':
unittest.main()
diff --git a/pyomo/contrib/parmest/tests/test_scenariocreator.py b/pyomo/contrib/parmest/tests/test_scenariocreator.py
index 5a0aa43ecab..920ebb171e8 100644
--- a/pyomo/contrib/parmest/tests/test_scenariocreator.py
+++ b/pyomo/contrib/parmest/tests/test_scenariocreator.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
# the matpolotlib stuff is to avoid $DISPLAY errors on Travis (DLW Oct 2018)
try:
import matplotlib
@@ -19,16 +29,11 @@
import pyutilib.th as unittest
import os
-import sys
-
import pyomo.contrib.parmest.parmest as parmest
import pyomo.contrib.parmest.scenariocreator as sc
-import pyomo.contrib.parmest.graphics as graphics
-import pyomo.contrib.parmest as parmestbase
-import pyomo.environ as pyo
import pyomo.contrib.parmest.examples.semibatch.scencreate as sbc
-
-from pyomo.opt import SolverFactory
+import pyomo.environ as pyo
+from pyomo.environ import SolverFactory
ipopt_available = SolverFactory('ipopt').available()
testdir = os.path.dirname(os.path.abspath(__file__))
diff --git a/pyomo/contrib/petsc/examples/dae_pyomo/car_example.py b/pyomo/contrib/petsc/examples/dae_pyomo/car_example.py
index f2aecc44728..e54f02c8eca 100644
--- a/pyomo/contrib/petsc/examples/dae_pyomo/car_example.py
+++ b/pyomo/contrib/petsc/examples/dae_pyomo/car_example.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
# Ampl Car Example
#
# Modified pyomo.dae example to remove optimization, and set up PETSc solve
@@ -9,8 +19,7 @@
# v(0)=0; v(tf)=0
# -3<=a<=1
-from pyomo.environ import *
-from pyomo.dae import *
+from pyomo.environ import ConcreteModel, Param, Var, Constraint, Suffix, SolverFactory
m = ConcreteModel()
diff --git a/pyomo/contrib/petsc/examples/dae_pyomo/chemakzo.py b/pyomo/contrib/petsc/examples/dae_pyomo/chemakzo.py
index 8bd12abf688..ee259b30daa 100644
--- a/pyomo/contrib/petsc/examples/dae_pyomo/chemakzo.py
+++ b/pyomo/contrib/petsc/examples/dae_pyomo/chemakzo.py
@@ -1,12 +1,20 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""
A test problem from https://archimede.dm.uniba.it/~testset/report/chemakzo.pdf
"""
from __future__ import division # No integer division
from __future__ import print_function # Python 3 style print
-from pyomo.environ import *
-from pyomo.opt import SolverFactory
-import os
+from pyomo.environ import ConcreteModel, Param, Var, Constraint, Suffix, SolverFactory
if __name__ == "__main__":
opt = SolverFactory('petsc')
diff --git a/pyomo/contrib/petsc/examples/dae_pyomo/path_constraint.py b/pyomo/contrib/petsc/examples/dae_pyomo/path_constraint.py
index 6c34e332677..f198bb484d9 100644
--- a/pyomo/contrib/petsc/examples/dae_pyomo/path_constraint.py
+++ b/pyomo/contrib/petsc/examples/dae_pyomo/path_constraint.py
@@ -21,8 +21,7 @@
# Modified for no optimization, and PETSc solver
-from pyomo.environ import *
-from pyomo.dae import *
+from pyomo.environ import ConcreteModel, Param, Var, Constraint, Suffix, SolverFactory
m = ConcreteModel()
m.tf = Param(initialize=1)
diff --git a/pyomo/contrib/preprocessing/plugins/bounds_to_vars.py b/pyomo/contrib/preprocessing/plugins/bounds_to_vars.py
index b6ddfc224b2..fa3d38ffd1d 100644
--- a/pyomo/contrib/preprocessing/plugins/bounds_to_vars.py
+++ b/pyomo/contrib/preprocessing/plugins/bounds_to_vars.py
@@ -1,11 +1,20 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Transformation to convert explicit bounds to variable bounds."""
from __future__ import division
-import math
from math import fabs
+import math
-from pyomo.core import Integers
from pyomo.core.base.plugin import TransformationFactory
from pyomo.common.config import (ConfigBlock, ConfigValue, NonNegativeFloat,
add_docstring_list)
@@ -83,9 +92,11 @@ def _apply_to(self, model, **kwds):
if var.is_integer() or var.is_binary():
# Make sure that the lb and ub are integral. Use safe construction if near to integer.
if var.has_lb():
- var.setlb(int(min(math.ceil(var.lb - config.tolerance), math.ceil(var.lb))))
+ var.setlb(int(min(math.ceil(var.lb - config.tolerance),
+ math.ceil(var.lb))))
if var.has_ub():
- var.setub(int(max(math.floor(var.ub + config.tolerance), math.floor(var.ub))))
+ var.setub(int(max(math.floor(var.ub + config.tolerance),
+ math.floor(var.ub))))
if var is not None and var.value is not None:
_adjust_var_value_if_not_feasible(var)
diff --git a/pyomo/contrib/preprocessing/plugins/deactivate_trivial_constraints.py b/pyomo/contrib/preprocessing/plugins/deactivate_trivial_constraints.py
index fd8a59249e9..f9998a2a822 100644
--- a/pyomo/contrib/preprocessing/plugins/deactivate_trivial_constraints.py
+++ b/pyomo/contrib/preprocessing/plugins/deactivate_trivial_constraints.py
@@ -1,7 +1,17 @@
# -*- coding: utf-8 -*-
+
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Transformation to deactivate trivial constraints."""
import logging
-import textwrap
from pyomo.common.collections import ComponentSet
from pyomo.common.config import (ConfigBlock, ConfigValue, NonNegativeFloat,
@@ -11,6 +21,7 @@
from pyomo.core.expr.numvalue import value
from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
+logger = logging.getLogger('pyomo.contrib.preprocessing')
@TransformationFactory.register(
'contrib.deactivate_trivial_constraints',
diff --git a/pyomo/contrib/preprocessing/plugins/detect_fixed_vars.py b/pyomo/contrib/preprocessing/plugins/detect_fixed_vars.py
index dc62c6a734b..80e751eefec 100644
--- a/pyomo/contrib/preprocessing/plugins/detect_fixed_vars.py
+++ b/pyomo/contrib/preprocessing/plugins/detect_fixed_vars.py
@@ -1,5 +1,14 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Transformation to detect variables fixed by bounds and fix them."""
-import textwrap
from math import fabs
from six import iteritems
diff --git a/pyomo/contrib/preprocessing/plugins/equality_propagate.py b/pyomo/contrib/preprocessing/plugins/equality_propagate.py
index 2f3caf3e4fc..cce0658ba49 100644
--- a/pyomo/contrib/preprocessing/plugins/equality_propagate.py
+++ b/pyomo/contrib/preprocessing/plugins/equality_propagate.py
@@ -1,5 +1,14 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Transformation to propagate state through an equality set."""
-import textwrap
from pyomo.common.collections import ComponentSet, ComponentMap
from pyomo.core.base.constraint import Constraint
diff --git a/pyomo/contrib/preprocessing/plugins/induced_linearity.py b/pyomo/contrib/preprocessing/plugins/induced_linearity.py
index b3a6c81eb57..a9b570cd5f8 100644
--- a/pyomo/contrib/preprocessing/plugins/induced_linearity.py
+++ b/pyomo/contrib/preprocessing/plugins/induced_linearity.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Transformation to reformulate nonlinear models with linearity induced from
discrete variables.
@@ -16,7 +26,6 @@
from pyomo.common.config import (ConfigBlock, ConfigValue, NonNegativeFloat,
add_docstring_list)
from pyomo.common.modeling import unique_component_name
-from pyomo.common.config import ConfigBlock, ConfigValue, NonNegativeFloat
from pyomo.contrib.preprocessing.util import SuppressConstantObjectiveWarning
from pyomo.core import (Binary, Block, Constraint, Objective, Set,
TransformationFactory, Var, summation, value)
diff --git a/pyomo/contrib/preprocessing/plugins/init_vars.py b/pyomo/contrib/preprocessing/plugins/init_vars.py
index b8bdc0d98f5..5810430940b 100644
--- a/pyomo/contrib/preprocessing/plugins/init_vars.py
+++ b/pyomo/contrib/preprocessing/plugins/init_vars.py
@@ -1,8 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Automatically initialize variables."""
from __future__ import division
-import textwrap
-
from pyomo.core.base.var import Var
from pyomo.core.base.plugin import TransformationFactory
from pyomo.core.expr.numvalue import value
diff --git a/pyomo/contrib/preprocessing/plugins/int_to_binary.py b/pyomo/contrib/preprocessing/plugins/int_to_binary.py
index 199cf35dbb1..7bde2a38e12 100644
--- a/pyomo/contrib/preprocessing/plugins/int_to_binary.py
+++ b/pyomo/contrib/preprocessing/plugins/int_to_binary.py
@@ -53,9 +53,10 @@ def _apply_to(self, model, **kwds):
integer_vars = list(
v for v in model.component_data_objects(
ctype=Var, descend_into=(Block, Disjunct))
- if v.is_integer() and not v.fixed)
+ if v.is_integer() and not v.is_binary() and not v.fixed)
if len(integer_vars) == 0:
- logger.info("Model has no free integer variables. No reformulation needed.")
+ logger.info(
+ "Model has no free integer variables. No reformulation needed.")
return
vars_on_constr = ComponentSet()
@@ -111,7 +112,7 @@ def _apply_to(self, model, **kwds):
idx, expr=int_var == sum(
reform_block.new_binary_var[idx, pwr] * (2 ** pwr)
for pwr in range(0, highest_power + 1))
- + int_var.lb)
+ + int_var.lb)
# Relax the original integer variable
if config.relax_integrality:
diff --git a/pyomo/contrib/preprocessing/plugins/remove_zero_terms.py b/pyomo/contrib/preprocessing/plugins/remove_zero_terms.py
index 08f3022fe9d..0e031d35bfd 100644
--- a/pyomo/contrib/preprocessing/plugins/remove_zero_terms.py
+++ b/pyomo/contrib/preprocessing/plugins/remove_zero_terms.py
@@ -1,16 +1,23 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
# -*- coding: UTF-8 -*-
"""Transformation to remove zero terms from constraints."""
from __future__ import division
-import textwrap
-
from pyomo.core import quicksum
from pyomo.core.base.constraint import Constraint
from pyomo.core.base.plugin import TransformationFactory
from pyomo.core.expr import current as EXPR
from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
from pyomo.repn import generate_standard_repn
-from pyutilib.math.util import isclose
@TransformationFactory.register(
diff --git a/pyomo/contrib/preprocessing/plugins/strip_bounds.py b/pyomo/contrib/preprocessing/plugins/strip_bounds.py
index b12ad4b96e5..076d758595a 100644
--- a/pyomo/contrib/preprocessing/plugins/strip_bounds.py
+++ b/pyomo/contrib/preprocessing/plugins/strip_bounds.py
@@ -1,5 +1,14 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Transformation to strip variable bounds from a model."""
-import textwrap
from pyomo.common.collections import ComponentMap
from pyomo.common.config import ConfigBlock, ConfigValue, add_docstring_list
diff --git a/pyomo/contrib/preprocessing/plugins/var_aggregator.py b/pyomo/contrib/preprocessing/plugins/var_aggregator.py
index 8b5ba8f3088..5160caf479e 100644
--- a/pyomo/contrib/preprocessing/plugins/var_aggregator.py
+++ b/pyomo/contrib/preprocessing/plugins/var_aggregator.py
@@ -1,11 +1,21 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Transformation to aggregate equal variables."""
from __future__ import division
-import textwrap
-
from pyomo.common.collections import ComponentMap, ComponentSet
-from pyomo.core.base import Block, Constraint, VarList, Objective, TransformationFactory
+from pyomo.core.base import (
+ Block, Constraint, VarList, Objective, TransformationFactory,
+)
from pyomo.core.expr.current import ExpressionReplacementVisitor
from pyomo.core.expr.numvalue import value
from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
diff --git a/pyomo/contrib/preprocessing/plugins/zero_sum_propagator.py b/pyomo/contrib/preprocessing/plugins/zero_sum_propagator.py
index d31368ed9f3..0d8d760bc8f 100644
--- a/pyomo/contrib/preprocessing/plugins/zero_sum_propagator.py
+++ b/pyomo/contrib/preprocessing/plugins/zero_sum_propagator.py
@@ -1,5 +1,14 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Transformation to propagate a zero value to terms of a sum."""
-import textwrap
from pyomo.core.base.plugin import TransformationFactory
from pyomo.core.base.constraint import Constraint
diff --git a/pyomo/contrib/preprocessing/tests/test_int_to_binary.py b/pyomo/contrib/preprocessing/tests/test_int_to_binary.py
index 7c45d7f26b6..9b4bb2ad75f 100644
--- a/pyomo/contrib/preprocessing/tests/test_int_to_binary.py
+++ b/pyomo/contrib/preprocessing/tests/test_int_to_binary.py
@@ -1,6 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
"""Tests the integer to binary variable reformulation."""
import pyutilib.th as unittest
-from pyomo.environ import ConcreteModel, Var, Integers, NonNegativeReals, value
+from pyomo.environ import ConcreteModel, Var, Integers, value
from pyomo.environ import TransformationFactory as xfrm
from pyomo.common.log import LoggingIntercept
diff --git a/pyomo/contrib/pynumero/algorithms/solvers/cyipopt_solver.py b/pyomo/contrib/pynumero/algorithms/solvers/cyipopt_solver.py
index a25ca96b4a0..4cd10ad896a 100644
--- a/pyomo/contrib/pynumero/algorithms/solvers/cyipopt_solver.py
+++ b/pyomo/contrib/pynumero/algorithms/solvers/cyipopt_solver.py
@@ -8,29 +8,96 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
"""
-The cyipopt_solver module includes the python interface to the
-Cythonized ipopt solver cyipopt (see more:
-https://github.com/matthias-k/cyipopt.git). To use the solver,
+The cyipopt_solver module includes the python interface to the
+Cythonized ipopt solver cyipopt (see more:
+https://github.com/matthias-k/cyipopt.git). To use the solver,
you can create a derived implementation from the abstract base class
CyIpoptProblemInterface that provides the necessary methods.
Note: This module also includes a default implementation CyIpopt
-that works with problems derived from AslNLP as long as those
+that works with problems derived from AslNLP as long as those
classes return numpy ndarray objects for the vectors and coo_matrix
objects for the matrices (e.g., AmplNLP and PyomoNLP)
"""
-try:
- import ipopt
-except ImportError:
- raise ImportError('ipopt solver relies on cyipopt. Install cyipopt'
- ' https://github.com/matthias-k/cyipopt.git')
-import numpy as np
-from pyomo.contrib.pynumero.interfaces.pyomo_nlp import PyomoNLP
import six
import sys
import os
import abc
+from pyomo.common.dependencies import (
+ attempt_import,
+ numpy as np, numpy_available,
+)
+ipopt, ipopt_available = attempt_import(
+ 'ipopt',
+ error_message='cyipopt solver relies on the ipopt module from cyipopt. '
+ 'See https://github.com/matthias-k/cyipopt.git for cyipopt '
+ 'installation instructions.'
+)
+# Because pynumero.interfaces requires numpy, we will leverage deferred
+# imports here so that the solver can be registered even when numpy is
+# not available.
+pyomo_nlp = attempt_import('pyomo.contrib.pynumero.interfaces.pyomo_nlp')[0]
+egb = attempt_import('pyomo.contrib.pynumero.interfaces.external_grey_box')[0]
+
+from pyomo.common.config import ConfigBlock, ConfigValue
+from pyomo.common.timing import TicTocTimer
+from pyomo.core.base import Block, Objective, minimize
+from pyomo.opt import (
+ SolverStatus, SolverResults, TerminationCondition, ProblemSense
+)
+
+# This maps the cyipopt STATUS_MESSAGES back to string representations
+# of the Ipopt ApplicationReturnStatus enum
+_cyipopt_status_enum = [
+ 'Solve_Succeeded', b'Algorithm terminated successfully at a locally optimal point, satisfying the convergence tolerances (can be specified by options).',
+ 'Solved_To_Acceptable_Level', b'Algorithm stopped at a point that was converged, not to "desired" tolerances, but to "acceptable" tolerances (see the acceptable-... options).',
+ 'Infeasible_Problem_Detected', b'Algorithm converged to a point of local infeasibility. Problem may be infeasible.',
+ 'Search_Direction_Becomes_Too_Small', b'Algorithm proceeds with very little progress.',
+ 'Diverging_Iterates', b'It seems that the iterates diverge.',
+ 'User_Requested_Stop', b'The user call-back function intermediate_callback (see Section 3.3.4 in the documentation) returned false, i.e., the user code requested a premature termination of the optimization.',
+ 'Feasible_Point_Found', b'Feasible point for square problem found.',
+ 'Maximum_Iterations_Exceeded', b'Maximum number of iterations exceeded (can be specified by an option).',
+ 'Restoration_Failed', b'Restoration phase failed, algorithm doesn\'t know how to proceed.',
+ 'Error_In_Step_Computation', b'An unrecoverable error occurred while Ipopt tried to compute the search direction.',
+ 'Maximum_CpuTime_Exceeded', b'Maximum CPU time exceeded.',
+ 'Not_Enough_Degrees_Of_Freedom', b'Problem has too few degrees of freedom.',
+ 'Invalid_Problem_Definition', b'Invalid problem definition.',
+ 'Invalid_Option', b'Invalid option encountered.',
+ 'Invalid_Number_Detected', b'Algorithm received an invalid number (such as NaN or Inf) from the NLP; see also option check_derivatives_for_naninf',
+ 'Unrecoverable_Exception', b'Some uncaught Ipopt exception encountered.',
+ 'NonIpopt_Exception_Thrown', b'Unknown Exception caught in Ipopt',
+ 'Insufficient_Memory', b'Not enough memory.',
+ 'Internal_Error', b'An unknown internal error occurred. Please contact the Ipopt authors through the mailing list.'
+]
+_cyipopt_status_enum = {
+ _cyipopt_status_enum[i+1]: _cyipopt_status_enum[i]
+ for i in range(0, len(_cyipopt_status_enum), 2)
+}
+
+# This maps Ipopt ApplicationReturnStatus enum strings to an appropriate
+# Pyomo TerminationCondition
+_ipopt_term_cond = {
+ 'Solve_Succeeded': TerminationCondition.optimal,
+ 'Solved_To_Acceptable_Level': TerminationCondition.feasible,
+ 'Infeasible_Problem_Detected': TerminationCondition.infeasible,
+ 'Search_Direction_Becomes_Too_Small': TerminationCondition.minStepLength,
+ 'Diverging_Iterates': TerminationCondition.unbounded,
+ 'User_Requested_Stop': TerminationCondition.userInterrupt,
+ 'Feasible_Point_Found': TerminationCondition.feasible,
+ 'Maximum_Iterations_Exceeded': TerminationCondition.maxIterations,
+ 'Restoration_Failed': TerminationCondition.noSolution,
+ 'Error_In_Step_Computation': TerminationCondition.solverFailure,
+ 'Maximum_CpuTime_Exceeded': TerminationCondition.maxTimeLimit,
+ 'Not_Enough_Degrees_Of_Freedom': TerminationCondition.invalidProblem,
+ 'Invalid_Problem_Definition': TerminationCondition.invalidProblem,
+ 'Invalid_Option': TerminationCondition.error,
+ 'Invalid_Number_Detected': TerminationCondition.internalSolverError,
+ 'Unrecoverable_Exception': TerminationCondition.internalSolverError,
+ 'NonIpopt_Exception_Thrown': TerminationCondition.error,
+ 'Insufficient_Memory': TerminationCondition.resourceInterrupt,
+ 'Internal_Error': TerminationCondition.internalSolverError,
+}
@six.add_metaclass(abc.ABCMeta)
class CyIpoptProblemInterface(object):
@@ -39,7 +106,7 @@ def x_init(self):
"""Return the initial values for x as a numpy ndarray
"""
pass
-
+
@abc.abstractmethod
def x_lb(self):
"""Return the lower bounds on x as a numpy ndarray
@@ -97,7 +164,7 @@ def constraints(self, x):
def jacobianstructure(self):
"""Return the structure of the jacobian
in coordinate format. That is, return (rows,cols)
- where rows and cols are both numpy ndarray
+ where rows and cols are both numpy ndarray
objects that contain the row and column indices
for each of the nonzeros in the jacobian.
"""
@@ -115,7 +182,7 @@ def jacobian(self, x):
def hessianstructure(self):
"""Return the structure of the hessian
in coordinate format. That is, return (rows,cols)
- where rows and cols are both numpy ndarray
+ where rows and cols are both numpy ndarray
objects that contain the row and column indices
for each of the nonzeros in the hessian.
Note: return ONLY the lower diagonal of this symmetric matrix.
@@ -131,7 +198,7 @@ def hessian(self, x, y, obj_factor):
Note: return ONLY the lower diagonal of this symmetric matrix.
"""
pass
-
+
def intermediate(self, alg_mod, iter_count, obj_value,
inf_pr, inf_du, mu, d_norm, regularization_size,
alpha_du, alpha_pr, ls_trials):
@@ -145,8 +212,8 @@ def intermediate(self, alg_mod, iter_count, obj_value,
class CyIpoptNLP(CyIpoptProblemInterface):
def __init__(self, nlp):
"""This class provides a CyIpoptProblemInterface for use
- with the CyIpoptSolver class that can take in an NLP
- as long as it provides vectors as numpy ndarrays and
+ with the CyIpoptSolver class that can take in an NLP
+ as long as it provides vectors as numpy ndarrays and
matrices as scipy.sparse.coo_matrix objects. This class
provides the interface between AmplNLP or PyomoNLP objects
and the CyIpoptSolver
@@ -167,8 +234,14 @@ def __init__(self, nlp):
# get jacobian and hessian structures
self._jac_g = nlp.evaluate_jacobian()
- self._hess_lag = nlp.evaluate_hessian_lag()
- self._hess_lower_mask = self._hess_lag.row >= self._hess_lag.col
+ try:
+ self._hess_lag = nlp.evaluate_hessian_lag()
+ self._hess_lower_mask = self._hess_lag.row >= self._hess_lag.col
+ self._hessian_available = True
+ except NotImplementedError:
+ self._hessian_available = False
+ self._hess_lag = None
+ self._hess_lower_mask = None
def _set_primals_if_necessary(self, x):
if not np.array_equal(x, self._cached_x):
@@ -190,7 +263,7 @@ def x_init(self):
def x_lb(self):
return self._nlp.primals_lb()
-
+
def x_ub(self):
return self._nlp.primals_ub()
@@ -199,7 +272,7 @@ def g_lb(self):
def g_ub(self):
return self._nlp.constraints_ub()
-
+
def scaling_factors(self):
obj_scaling = self._nlp.get_obj_scaling()
x_scaling = self._nlp.get_primals_scaling()
@@ -220,18 +293,25 @@ def constraints(self, x):
def jacobianstructure(self):
return self._jac_g.row, self._jac_g.col
-
+
def jacobian(self, x):
self._set_primals_if_necessary(x)
self._nlp.evaluate_jacobian(out=self._jac_g)
return self._jac_g.data
def hessianstructure(self):
+ if not self._hessian_available:
+ return np.zeros(0), np.zeros(0)
+
row = np.compress(self._hess_lower_mask, self._hess_lag.row)
col = np.compress(self._hess_lower_mask, self._hess_lag.col)
return row, col
+
def hessian(self, x, y, obj_factor):
+ if not self._hessian_available:
+ raise ValueError("Hessian requested, but not supported by the NLP")
+
self._set_primals_if_necessary(x)
self._set_duals_if_necessary(y)
self._set_obj_factor_if_necessary(obj_factor)
@@ -256,7 +336,7 @@ def intermediate(
pass
-def redirect_stdout():
+def _redirect_stdout():
sys.stdout.flush() # <--- important when redirecting to files
# Duplicate stdout (file descriptor 1)
@@ -282,9 +362,8 @@ def redirect_stdout():
class CyIpoptSolver(object):
def __init__(self, problem_interface, options=None):
"""Create an instance of the CyIpoptSolver. You must
- provide a problem_interface that corresponds to
+ provide a problem_interface that corresponds to
the abstract class CyIpoptProblemInterface
-
options can be provided as a dictionary of key value
pairs
"""
@@ -305,22 +384,23 @@ def solve(self, x0=None, tee=False):
if x0 is None:
x0 = self._problem.x_init()
xstart = x0
-
+
nx = len(xstart)
ng = len(gl)
- cyipopt_solver = ipopt.problem(n=nx,
- m=ng,
- problem_obj=self._problem,
- lb=xl,
- ub=xu,
- cl=gl,
- cu=gu
+ cyipopt_solver = ipopt.problem(
+ n=nx,
+ m=ng,
+ problem_obj=self._problem,
+ lb=xl,
+ ub=xu,
+ cl=gl,
+ cu=gu
)
# check if we need scaling
obj_scaling, x_scaling, g_scaling = self._problem.scaling_factors()
- if obj_scaling is not None or x_scaling is not None or g_scaling is not None:
+ if any(_ is not None for _ in (obj_scaling, x_scaling, g_scaling)):
# need to set scaling factors
if obj_scaling is None:
obj_scaling = 1.0
@@ -328,7 +408,6 @@ def solve(self, x0=None, tee=False):
x_scaling = np.ones(nx)
if g_scaling is None:
g_scaling = np.ones(ng)
-
cyipopt_solver.setProblemScaling(obj_scaling, x_scaling, g_scaling)
# add options
@@ -338,8 +417,172 @@ def solve(self, x0=None, tee=False):
if tee:
x, info = cyipopt_solver.solve(xstart)
else:
- newstdout = redirect_stdout()
+ newstdout = _redirect_stdout()
x, info = cyipopt_solver.solve(xstart)
os.dup2(newstdout, 1)
return x, info
+
+
+def _numpy_vector(val):
+ ans = np.array(val, np.float64)
+ if len(ans.shape) != 1:
+ raise ValueError("expected a vector, but recieved a matrix "
+ "with shape %s" % (ans.shape,))
+ return ans
+
+
+class PyomoCyIpoptSolver(object):
+
+ CONFIG = ConfigBlock("cyipopt")
+ CONFIG.declare("tee", ConfigValue(
+ default=False,
+ domain=bool,
+ description="Stream solver output to console",
+ ))
+ CONFIG.declare("load_solutions", ConfigValue(
+ default=True,
+ domain=bool,
+ description="Store the final solution into the original Pyomo model",
+ ))
+ CONFIG.declare("options", ConfigBlock(implicit=True))
+
+
+ def __init__(self, **kwds):
+ """Create an instance of the CyIpoptSolver. You must
+ provide a problem_interface that corresponds to
+ the abstract class CyIpoptProblemInterface
+
+ options can be provided as a dictionary of key value
+ pairs
+ """
+ self.config = self.CONFIG(kwds)
+
+ def _set_model(self, model):
+ self._model = model
+
+ def available(self, exception_flag=False):
+ return numpy_available and ipopt_available
+
+ def version(self):
+ return tuple(int(_) for _ in ipopt.__version__.split('.'))
+
+ def solve(self, model, **kwds):
+ config = self.config(kwds, preserve_implicit=True)
+
+ if not isinstance(model, Block):
+ raise ValueError("PyomoCyIpoptSolver.solve(model): model "
+ "must be a Pyomo Block")
+
+ # If this is a Pyomo model / block, then we need to create
+ # the appropriate PyomoNLP, then wrap it in a CyIpoptNLP
+ grey_box_blocks = list(model.component_data_objects(
+ egb.ExternalGreyBoxBlock, active=True))
+ if grey_box_blocks:
+ nlp = pyomo_nlp.PyomoGreyBoxNLP(model)
+ else:
+ nlp = pyomo_nlp.PyomoNLP(model)
+ problem = CyIpoptNLP(nlp)
+
+ xl = problem.x_lb()
+ xu = problem.x_ub()
+ gl = problem.g_lb()
+ gu = problem.g_ub()
+
+ nx = len(xl)
+ ng = len(gl)
+
+ cyipopt_solver = ipopt.problem(
+ n=nx,
+ m=ng,
+ problem_obj=problem,
+ lb=xl,
+ ub=xu,
+ cl=gl,
+ cu=gu
+ )
+
+ # check if we need scaling
+ obj_scaling, x_scaling, g_scaling = problem.scaling_factors()
+ if any(_ is not None for _ in (obj_scaling, x_scaling, g_scaling)):
+ # need to set scaling factors
+ if obj_scaling is None:
+ obj_scaling = 1.0
+ if x_scaling is None:
+ x_scaling = np.ones(nx)
+ if g_scaling is None:
+ g_scaling = np.ones(ng)
+ cyipopt_solver.setProblemScaling(obj_scaling, x_scaling, g_scaling)
+
+ # add options
+ for k, v in config.options.items():
+ cyipopt_solver.addOption(k, v)
+
+ timer = TicTocTimer()
+ try:
+ if config.tee:
+ x, info = cyipopt_solver.solve(problem.x_init())
+ else:
+ newstdout = _redirect_stdout()
+ x, info = cyipopt_solver.solve(problem.x_init())
+ os.dup2(newstdout, 1)
+ solverStatus = SolverStatus.ok
+ except:
+ solverStatus = SolverStatus.unknown
+ wall_time = timer.toc("")
+
+ results = SolverResults()
+
+ if config.load_solutions:
+ nlp.set_primals(x)
+ nlp.set_duals(info['mult_g'])
+ nlp.load_state_into_pyomo(
+ bound_multipliers=(info['mult_x_L'], info['mult_x_U']))
+ else:
+ soln = results.solution.add()
+ soln.variable.update(
+ (i, {'Value':j, 'ipopt_zL_out': zl, 'ipopt_zU_out': zu})
+ for i,j,zl,zu in zip( nlp.variable_names(),
+ x,
+ info['mult_x_L'],
+ info['mult_x_U'] )
+ )
+ soln.constraint.update(
+ (i, {'Dual':j}) for i,j in zip(
+ nlp.constraint_names(), info['mult_g']))
+
+
+ results.problem.name = model.name
+ obj = next(model.component_data_objects(Objective, active=True))
+ if obj.sense == minimize:
+ results.problem.sense = ProblemSense.minimize
+ results.problem.upper_bound = info['obj_val']
+ else:
+ results.problem.sense = ProblemSense.maximize
+ results.problem.lower_bound = info['obj_val']
+ results.problem.number_of_objectives = 1
+ results.problem.number_of_constraints = ng
+ results.problem.number_of_variables = nx
+ results.problem.number_of_binary_variables = 0
+ results.problem.number_of_integer_variables = 0
+ results.problem.number_of_continuous_variables = nx
+ # TODO: results.problem.number_of_nonzeros
+
+ results.solver.name = 'cyipopt'
+ results.solver.return_code = info['status']
+ results.solver.message = info['status_msg']
+ results.solver.wallclock_time = wall_time
+ status_enum = _cyipopt_status_enum[info['status_msg']]
+ results.solver.termination_condition = _ipopt_term_cond[status_enum]
+ results.solver.status = TerminationCondition.to_solver_status(
+ results.solver.termination_condition)
+ return results
+
+ #
+ # Support "with" statements.
+ #
+ def __enter__(self):
+ return self
+
+ def __exit__(self, t, v, traceback):
+ pass
diff --git a/pyomo/contrib/pynumero/algorithms/solvers/tests/test_cyipopt_interfaces.py b/pyomo/contrib/pynumero/algorithms/solvers/tests/test_cyipopt_interfaces.py
index 32421fbc0b0..392d5b70c3b 100644
--- a/pyomo/contrib/pynumero/algorithms/solvers/tests/test_cyipopt_interfaces.py
+++ b/pyomo/contrib/pynumero/algorithms/solvers/tests/test_cyipopt_interfaces.py
@@ -83,7 +83,7 @@ def test_model1_CyIpoptNLP_scaling(self):
cynlp = CyIpoptNLP(PyomoNLP(m))
obj_scaling, x_scaling, g_scaling = cynlp.scaling_factors()
- self.assertTrue(obj_scaling == None)
+ self.assertTrue(obj_scaling == 1.0)
self.assertTrue(len(x_scaling) == 3)
# vars are in order x[2], x[3], x[1]
self.assertTrue(x_scaling[0] == 1.0)
diff --git a/pyomo/contrib/pynumero/algorithms/solvers/tests/test_cyipopt_solver.py b/pyomo/contrib/pynumero/algorithms/solvers/tests/test_cyipopt_solver.py
index 4031b979ed8..b0a1d4d6e16 100644
--- a/pyomo/contrib/pynumero/algorithms/solvers/tests/test_cyipopt_solver.py
+++ b/pyomo/contrib/pynumero/algorithms/solvers/tests/test_cyipopt_solver.py
@@ -34,6 +34,7 @@
CyIpoptSolver, CyIpoptNLP
)
+
def create_model1():
m = pyo.ConcreteModel()
m.x = pyo.Var([1, 2, 3], initialize=4.0)
@@ -45,6 +46,7 @@ def create_model1():
return m
+
def create_model2():
m = pyo.ConcreteModel()
m.x = pyo.Var([1, 2], initialize=4.0)
@@ -223,7 +225,3 @@ def test_options(self):
x, info = solver.solve(tee=False)
nlp.set_primals(x)
self.assertAlmostEqual(nlp.evaluate_objective(), -5.0879028e+02, places=5)
-
-
-
-
diff --git a/pyomo/contrib/pynumero/algorithms/solvers/tests/test_pyomo_ext_cyipopt.py b/pyomo/contrib/pynumero/algorithms/solvers/tests/test_pyomo_ext_cyipopt.py
index 2b87fd2e44d..5aece7d0988 100644
--- a/pyomo/contrib/pynumero/algorithms/solvers/tests/test_pyomo_ext_cyipopt.py
+++ b/pyomo/contrib/pynumero/algorithms/solvers/tests/test_pyomo_ext_cyipopt.py
@@ -31,6 +31,7 @@
from pyomo.contrib.pynumero.algorithms.solvers.pyomo_ext_cyipopt import ExternalInputOutputModel, PyomoExternalCyIpoptProblem
from pyomo.contrib.pynumero.algorithms.solvers.cyipopt_solver import CyIpoptSolver
+
class PressureDropModel(ExternalInputOutputModel):
def __init__(self):
self._Pin = None
@@ -56,6 +57,7 @@ def evaluate_derivatives(self):
jac = np.asarray(jac, dtype=np.float64)
return spa.coo_matrix(jac)
+
class TestExternalInputOutputModel(unittest.TestCase):
def test_interface(self):
diff --git a/pyomo/contrib/pynumero/asl.py b/pyomo/contrib/pynumero/asl.py
index a14223f5b98..32474271371 100644
--- a/pyomo/contrib/pynumero/asl.py
+++ b/pyomo/contrib/pynumero/asl.py
@@ -7,12 +7,11 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
from pyomo.common.fileutils import find_library
import numpy.ctypeslib as npct
import numpy as np
-import platform
import ctypes
-import sys
import os
class _NotSet:
diff --git a/pyomo/contrib/pynumero/doc/source/conf.py b/pyomo/contrib/pynumero/doc/source/conf.py
index b75d2d105a7..90bf3e61543 100644
--- a/pyomo/contrib/pynumero/doc/source/conf.py
+++ b/pyomo/contrib/pynumero/doc/source/conf.py
@@ -26,7 +26,6 @@
# sys.path.insert(0, os.path.abspath('.'))
import sys
import os
-import shlex
sys.path.insert(0, os.path.abspath('../'))
# -- Project information -----------------------------------------------------
diff --git a/pyomo/contrib/pynumero/examples/basic.py b/pyomo/contrib/pynumero/examples/basic.py
index 583f918c212..84f4e4c3915 100644
--- a/pyomo/contrib/pynumero/examples/basic.py
+++ b/pyomo/contrib/pynumero/examples/basic.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from pyomo.contrib.pynumero.interfaces.pyomo_nlp import PyomoNLP
import pyomo.environ as pyo
@@ -13,6 +23,7 @@ def create_model():
return m
+
model = create_model()
nlp = PyomoNLP(model)
diff --git a/pyomo/contrib/pynumero/examples/derivatives.py b/pyomo/contrib/pynumero/examples/derivatives.py
index f4f5d93ee61..7c8ecdaf13c 100644
--- a/pyomo/contrib/pynumero/examples/derivatives.py
+++ b/pyomo/contrib/pynumero/examples/derivatives.py
@@ -7,6 +7,7 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
from pyomo.contrib.pynumero.sparse import BlockMatrix
from pyomo.contrib.pynumero.interfaces.pyomo_nlp import PyomoNLP
import matplotlib.pylab as plt
@@ -55,11 +56,15 @@ def _int_rule(M, i):
m.init_condition_names = ['init_conditions']
return m
+
instance = create_problem(0.0, 10.0)
# Discretize model using Orthogonal Collocation
discretizer = pyo.TransformationFactory('dae.collocation')
discretizer.apply_to(instance, nfe=100, ncp=3, scheme='LAGRANGE-RADAU')
-discretizer.reduce_collocation_points(instance, var=instance.u, ncp=1, contset=instance.t)
+discretizer.reduce_collocation_points(instance,
+ var=instance.u,
+ ncp=1,
+ contset=instance.t)
# Interface pyomo model with nlp
nlp = PyomoNLP(instance)
@@ -84,11 +89,10 @@ def _int_rule(M, i):
plt.show()
# Build KKT matrix
-kkt = BlockMatrix(2,2)
+kkt = BlockMatrix(2, 2)
kkt.set_block(0, 0, hess_lag)
kkt.set_block(1, 0, jac)
kkt.set_block(0, 1, jac.transpose())
plt.spy(kkt.tocoo())
plt.title('KKT system\n')
plt.show()
-
diff --git a/pyomo/contrib/pynumero/examples/external_grey_box/react-example/maximize_cb_outputs.py b/pyomo/contrib/pynumero/examples/external_grey_box/react-example/maximize_cb_outputs.py
new file mode 100644
index 00000000000..7ec2be479d4
--- /dev/null
+++ b/pyomo/contrib/pynumero/examples/external_grey_box/react-example/maximize_cb_outputs.py
@@ -0,0 +1,49 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from __future__ import division
+import pyomo.environ as pyo
+from pyomo.contrib.pynumero.interfaces.external_grey_box import \
+ ExternalGreyBoxBlock
+from reactor_model_outputs import ReactorConcentrationsOutputModel
+
+def maximize_cb_outputs(show_solver_log=False):
+ # in this simple example, we will use an external grey box model representing
+ # a steady-state reactor, and solve for the space velocity that maximizes
+ # the concentration of component B coming out of the reactor
+ m = pyo.ConcreteModel()
+
+ # create a block to store the external reactor model
+ m.reactor = ExternalGreyBoxBlock(
+ external_model=ReactorConcentrationsOutputModel()
+ )
+
+ # The reaction rate constants and the feed concentration will
+ # be fixed for this example
+ m.k1con = pyo.Constraint(expr=m.reactor.inputs['k1'] == 5/6)
+ m.k2con = pyo.Constraint(expr=m.reactor.inputs['k2'] == 5/3)
+ m.k3con = pyo.Constraint(expr=m.reactor.inputs['k3'] == 1/6000)
+ m.cafcon = pyo.Constraint(expr=m.reactor.inputs['caf'] == 10000)
+
+ # add an objective function that maximizes the concentration
+ # of cb coming out of the reactor
+ m.obj = pyo.Objective(expr=m.reactor.outputs['cb'], sense=pyo.maximize)
+
+ solver = pyo.SolverFactory('cyipopt')
+ solver.config.options['hessian_approximation'] = 'limited-memory'
+ results = solver.solve(m, tee=show_solver_log)
+ pyo.assert_optimal_termination(results)
+ return m
+
+if __name__ == '__main__':
+ m = maximize_cb_outputs(show_solver_log=True)
+ m.pprint()
+
+
diff --git a/pyomo/contrib/pynumero/examples/external_grey_box/react-example/maximize_cb_ratio_residuals.py b/pyomo/contrib/pynumero/examples/external_grey_box/react-example/maximize_cb_ratio_residuals.py
new file mode 100644
index 00000000000..e4a71912942
--- /dev/null
+++ b/pyomo/contrib/pynumero/examples/external_grey_box/react-example/maximize_cb_ratio_residuals.py
@@ -0,0 +1,164 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+import pyomo.environ as pyo
+from pyomo.contrib.pynumero.interfaces.external_grey_box import ExternalGreyBoxBlock
+from reactor_model_residuals import ReactorModel, ReactorModelNoOutputs, ReactorModelScaled
+
+def maximize_cb_ratio_residuals_with_output(show_solver_log=False, additional_options={}):
+ # in this simple example, we will use an external grey box model representing
+ # a steady-state reactor, and solve for the space velocity that maximizes
+ # the ratio of B to the other components coming out of the reactor
+ # This example illustrates the use of "equality constraints" or residuals
+ # in the external grey box example as well as outputs
+ m = pyo.ConcreteModel()
+
+ # create a block to store the external reactor model
+ m.reactor = ExternalGreyBoxBlock(external_model=ReactorModel())
+
+ # The feed concentration will be fixed for this example
+ m.cafcon = pyo.Constraint(expr=m.reactor.inputs['caf'] == 10000)
+
+ # add an objective function that maximizes the concentration
+ # of cb coming out of the reactor
+ m.obj = pyo.Objective(expr=m.reactor.outputs['cb_ratio'], sense=pyo.maximize)
+
+ solver = pyo.SolverFactory('cyipopt')
+ solver.config.options['hessian_approximation'] = 'limited-memory'
+ for k,v in additional_options.items():
+ solver.config.options[k] = v
+ results = solver.solve(m, tee=show_solver_log)
+ pyo.assert_optimal_termination(results)
+ return m
+
+def maximize_cb_ratio_residuals_with_output_scaling(show_solver_log=False, additional_options={}):
+ # in this simple example, we will use an external grey box model representing
+ # a steady-state reactor, and solve for the space velocity that maximizes
+ # the ratio of B to the other components coming out of the reactor
+ # This example illustrates the use of "equality constraints" or residuals
+ # in the external grey box example as well as outputs
+
+ # This example also shows how to do scaling.
+ # There are two things to scale, the "Pyomo" variables/constraints,
+ # and the external model residuals / output equations.
+ # The scaling factors for the external residuals and output equations
+ # are set in the derived ExternalGreyBoxModel class (see ReactorModelScaled
+ # for this example).
+ # The scaling factors for the Pyomo part of the model are set using suffixes
+ # - this requires that we declare the scaling suffix on the main model as
+ # shown below.
+ # - Then the scaling factors can be set directly on the Pyomo variables
+ # and constraints as also shown below.
+ # - Note: In this example, the scaling factors for the input and output
+ # variables from the grey box model are set in the finalize_block_construction
+ # callback (again, see ReactorModelScaled)
+ m = pyo.ConcreteModel()
+
+ # declare the scaling suffix on the model
+ m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT)
+
+ # create a block to store the external reactor model
+ m.reactor = ExternalGreyBoxBlock(external_model=ReactorModelScaled())
+
+ # The feed concentration will be fixed for this example
+ m.cafcon = pyo.Constraint(expr=m.reactor.inputs['caf'] == 10000)
+ # set a scaling factor for this constraint - if we had additional pyomo
+ # variables, we could set them the same way
+ m.scaling_factor[m.cafcon] = 42.0
+
+ # add an objective function that maximizes the concentration
+ # of cb coming out of the reactor
+ m.obj = pyo.Objective(expr=m.reactor.outputs['cb_ratio'], sense=pyo.maximize)
+
+ solver = pyo.SolverFactory('cyipopt')
+ solver.config.options['hessian_approximation'] = 'limited-memory'
+ for k,v in additional_options.items():
+ solver.config.options[k] = v
+ results = solver.solve(m, tee=show_solver_log)
+ pyo.assert_optimal_termination(results)
+ return m
+
+def maximize_cb_ratio_residuals_with_obj(show_solver_log=False, additional_options={}):
+ # in this simple example, we will use an external grey box model representing
+ # a steady-state reactor, and solve for the space velocity that maximizes
+ # the ratio of B to the other components coming out of the reactor
+ # This example illustrates the use of "equality constraints" or residuals
+ # in the external grey box example as well as additional pyomo variables
+ # and constraints
+ m = pyo.ConcreteModel()
+
+ # create a block to store the external reactor model
+ m.reactor = ExternalGreyBoxBlock()
+ m.reactor.set_external_model(ReactorModelNoOutputs())
+
+ # The feed concentration will be fixed for this example
+ m.cafcon = pyo.Constraint(expr=m.reactor.inputs['caf'] == 10000)
+
+ # add an objective function that maximizes the concentration
+ # of cb coming out of the reactor
+ u = m.reactor.inputs
+ m.obj = pyo.Objective(expr=u['cb']/(u['ca']+u['cc']+u['cd']), sense=pyo.maximize)
+
+ solver = pyo.SolverFactory('cyipopt')
+ solver.config.options['hessian_approximation'] = 'limited-memory'
+ for k,v in additional_options.items():
+ solver.config.options[k] = v
+ results = solver.solve(m, tee=show_solver_log)
+ pyo.assert_optimal_termination(results)
+ return m
+
+def maximize_cb_ratio_residuals_with_pyomo_variables(show_solver_log=False, additional_options={}):
+ # in this simple example, we will use an external grey box model representing
+ # a steady-state reactor, and solve for the space velocity that maximizes
+ # the ratio of B to the other components coming out of the reactor
+ # This example illustrates the use of "equality constraints" or residuals
+ # in the external grey box example as well as additional pyomo variables
+ # and constraints
+ m = pyo.ConcreteModel()
+
+ # create a block to store the external reactor model
+ m.reactor = ExternalGreyBoxBlock()
+ m.reactor.set_external_model(ReactorModelNoOutputs())
+
+ # add a variable and constraint for the cb ratio
+ m.cb_ratio = pyo.Var(initialize=1)
+ u = m.reactor.inputs
+ m.cb_ratio_con = pyo.Constraint(expr = \
+ u['cb']/(u['ca']+u['cc']+u['cd']) - m.cb_ratio == 0)
+
+ # The feed concentration will be fixed for this example
+ m.cafcon = pyo.Constraint(expr=m.reactor.inputs['caf'] == 10000)
+
+ # add an objective function that maximizes the concentration
+ # of cb coming out of the reactor
+ m.obj = pyo.Objective(expr=m.cb_ratio, sense=pyo.maximize)
+
+ solver = pyo.SolverFactory('cyipopt')
+ solver.config.options['hessian_approximation'] = 'limited-memory'
+ for k,v in additional_options.items():
+ solver.config.options[k] = v
+ results = solver.solve(m, tee=show_solver_log)
+ pyo.assert_optimal_termination(results)
+ return m
+
+if __name__ == '__main__':
+ #m = maximize_cb_ratio_residuals_with_output(show_solver_log=True)
+ #m.pprint()
+ aoptions={'hessian_approximation':'limited-memory',
+ #'limited_memory_update_type': 'sr1',
+ 'nlp_scaling_method': 'user-scaling',
+ 'print_level':10}
+ m = maximize_cb_ratio_residuals_with_output_scaling(show_solver_log=True, additional_options=aoptions)
+ #m.pprint()
+ #m = maximize_cb_ratio_residuals_with_obj(show_solver_log=True)
+ #m.pprint()
+ #m = maximize_cb_ratio_residuals_with_pyomo_variables(show_solver_log=True)
+ #m.pprint()
+
+
diff --git a/pyomo/contrib/pynumero/examples/external_grey_box/react-example/reactor_model_outputs.py b/pyomo/contrib/pynumero/examples/external_grey_box/react-example/reactor_model_outputs.py
new file mode 100644
index 00000000000..64377bc540d
--- /dev/null
+++ b/pyomo/contrib/pynumero/examples/external_grey_box/react-example/reactor_model_outputs.py
@@ -0,0 +1,129 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+"""
+This file contains a black box model representing a simple
+reactor design problem described in the Pyomo book.
+It is part of the external_grey_box example with PyNumero.
+
+These functions solve a reactor model using scipy
+Note: In this case, this model can be solved using
+standard Pyomo constructs (see the Pyomo book), but
+this is included as an example of the external grey
+box model interface.
+"""
+
+from __future__ import division
+
+import numpy as np
+from scipy.optimize import fsolve
+from scipy.sparse import coo_matrix
+from pyomo.contrib.pynumero.interfaces.external_grey_box import ExternalGreyBoxModel
+
+def reactor_outlet_concentrations(sv, caf, k1, k2, k3):
+ def _model(x, sv, caf, k1, k2, k3):
+ ca, cb, cc, cd = x[0], x[1], x[2], x[3]
+
+ # compute the residuals
+ r = np.zeros(4)
+ r[0] = sv*caf + (-sv-k1)*ca - 2*k3*ca**2
+ r[1] = k1*ca + (-sv-k2)*cb
+ r[2] = k2*cb - sv*cc
+ r[3] = k3*ca**2 - sv*cd
+
+ return r
+
+ concentrations = \
+ fsolve(lambda x: _model(x, sv, caf, k1, k2, k3), np.ones(4), xtol=1e-8)
+
+ # Todo: check solve status
+ return concentrations
+
+class ReactorConcentrationsOutputModel(ExternalGreyBoxModel):
+ def input_names(self):
+ return ['sv', 'caf', 'k1', 'k2', 'k3']
+
+ def output_names(self):
+ return ['ca', 'cb', 'cc', 'cd']
+
+ def set_input_values(self, input_values):
+ self._input_values = list(input_values)
+
+ def finalize_block_construction(self, pyomo_block):
+ # set lower bounds on the inputs and outputs
+ pyomo_block.inputs['sv'].setlb(0)
+ pyomo_block.outputs['ca'].setlb(0)
+ pyomo_block.outputs['cb'].setlb(0)
+ pyomo_block.outputs['cc'].setlb(0)
+ pyomo_block.outputs['cd'].setlb(0)
+
+ # initialize the variables
+ pyomo_block.inputs['sv'].value = 5
+ pyomo_block.inputs['caf'].value = 10000
+ pyomo_block.inputs['k1'].value = 5/6
+ pyomo_block.inputs['k2'].value = 5/3
+ pyomo_block.inputs['k3'].value = 1/6000
+ pyomo_block.outputs['ca'].value = 1
+ pyomo_block.outputs['cb'].value = 1
+ pyomo_block.outputs['cc'].value = 1
+ pyomo_block.outputs['cd'].value = 1
+
+ def evaluate_outputs(self):
+ sv = self._input_values[0]
+ caf = self._input_values[1]
+ k1 = self._input_values[2]
+ k2 = self._input_values[3]
+ k3 = self._input_values[4]
+ ret = reactor_outlet_concentrations(sv, caf, k1, k2, k3)
+ return np.asarray(ret, dtype=np.float64)
+
+ def evaluate_jacobian_outputs(self):
+ # here, we compute the derivatives using finite difference
+ # however, this would be better with analytical derivatives
+ delta = 1e-6
+ u0 = np.copy(self._input_values)
+ y0 = self.evaluate_outputs()
+ jac = np.empty((4,5))
+ u = np.copy(self._input_values)
+ for j in range(len(u)):
+ # perturb the variables
+ u[j] += delta
+ self.set_input_values(u)
+ yperturb = self.evaluate_outputs()
+ jac_col = (yperturb - y0)/delta
+ jac[:,j] = jac_col
+ u[j] = u0[j]
+
+ # return us back to our starting state
+ self.set_input_values(u0)
+
+ # this needs to be a sparse coo_matrix
+ # this approach is inefficient, but clear for an example
+ row = []
+ col = []
+ data = []
+ for r in range(4):
+ for c in range(5):
+ row.append(r)
+ col.append(c)
+ data.append(jac[r,c])
+
+ return coo_matrix((data, (row, col)), shape=(4,5))
+
+if __name__ == '__main__':
+ sv = 1.34
+ caf = 10000
+ k1 = 5/6
+ k2 = 5/3
+ k3 = 1/6000
+ concentrations = reactor_outlet_concentrations(sv, caf, k1, k2, k3)
+ print(concentrations)
+
+
diff --git a/pyomo/contrib/pynumero/examples/external_grey_box/react-example/reactor_model_residuals.py b/pyomo/contrib/pynumero/examples/external_grey_box/react-example/reactor_model_residuals.py
new file mode 100644
index 00000000000..857b3d88221
--- /dev/null
+++ b/pyomo/contrib/pynumero/examples/external_grey_box/react-example/reactor_model_residuals.py
@@ -0,0 +1,357 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+"""
+This file contains an external grey box model representing a simple
+reactor design problem described in the Pyomo book.
+It is part of the external_grey_box examples with PyNumero.
+
+Note: In this case, this model can be solved using
+standard Pyomo constructs (see the Pyomo book), but
+this is included as an example of the external grey
+box model interface.
+"""
+
+from __future__ import division
+
+import numpy as np
+from scipy.sparse import coo_matrix
+from pyomo.contrib.pynumero.interfaces.external_grey_box import ExternalGreyBoxModel
+
+class ReactorModel(ExternalGreyBoxModel):
+ def __init__(self, use_exact_derivatives=True):
+ self._use_exact_derivatives = use_exact_derivatives
+
+ def input_names(self):
+ return ['sv', 'caf', 'ca', 'cb', 'cc', 'cd']
+
+ def equality_constraint_names(self):
+ return ['ca_bal', 'cb_bal', 'cc_bal', 'cd_bal']
+
+ def output_names(self):
+ return ['cb_ratio']
+
+ def finalize_block_construction(self, pyomo_block):
+ # set lower bounds on the variables
+ pyomo_block.inputs['sv'].setlb(0)
+ pyomo_block.inputs['ca'].setlb(0)
+ pyomo_block.inputs['cb'].setlb(0)
+ pyomo_block.inputs['cc'].setlb(0)
+ pyomo_block.inputs['cd'].setlb(0)
+
+ # initialize the variables
+ pyomo_block.inputs['sv'].value = 1
+ pyomo_block.inputs['caf'].value = 1
+ pyomo_block.inputs['ca'].value = 1
+ pyomo_block.inputs['cb'].value = 1
+ pyomo_block.inputs['cc'].value = 1
+ pyomo_block.inputs['cd'].value = 1
+ pyomo_block.outputs['cb_ratio'].value = 1
+
+ def set_input_values(self, input_values):
+ self._input_values = list(input_values)
+
+ def evaluate_equality_constraints(self):
+ sv = self._input_values[0]
+ caf = self._input_values[1]
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ k1 = 5/6
+ k2 = 5/3
+ k3 = 1/6000
+ r = np.zeros(4)
+ r[0] = sv*caf + (-sv-k1)*ca - 2*k3*ca**2
+ r[1] = k1*ca + (-sv-k2)*cb
+ r[2] = k2*cb - sv*cc
+ r[3] = k3*ca**2 - sv*cd
+ return r
+
+ def evaluate_outputs(self):
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ cb_ratio = cb/(ca+cc+cd)
+ return np.asarray([cb_ratio], dtype=np.float64)
+
+ def evaluate_jacobian_equality_constraints(self):
+ sv = self._input_values[0]
+ caf = self._input_values[1]
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ k1 = 5/6
+ k2 = 5/3
+ k3 = 1/6000
+
+ if self._use_exact_derivatives:
+ row = np.zeros(12)
+ col = np.zeros(12)
+ data = np.zeros(12)
+ row[0], col[0], data[0] = (0, 0, caf-ca)
+ row[1], col[1], data[1] = (0, 1, sv)
+ row[2], col[2], data[2] = (0, 2, -sv-k1-4*k3*ca)
+ row[3], col[3], data[3] = (1, 0, -cb)
+ row[4], col[4], data[4] = (1, 2, k1)
+ row[5], col[5], data[5] = (1, 3, -sv-k2)
+ row[6], col[6], data[6] = (2, 0, -cc)
+ row[7], col[7], data[7] = (2, 3, k2)
+ row[8], col[8], data[8] = (2, 4, -sv)
+ row[9], col[9], data[9] = (3, 0, -cd)
+ row[10], col[10], data[10] = (3, 2, 2*k3*ca)
+ row[11], col[11], data[11] = (3, 5, -sv)
+ ret = coo_matrix((data, (row, col)), shape=(4,6))
+ return ret
+ else:
+ delta = 1e-8
+ u0 = np.copy(self._input_values)
+ y0 = self.evaluate_equality_constraints()
+ jac = np.empty((4,6))
+ u = np.copy(self._input_values)
+ for j in range(len(u)):
+ # perturb the variables
+ u[j] += delta
+ self.set_input_values(u)
+ yperturb = self.evaluate_equality_constraints()
+ jac_col = (yperturb - y0)/delta
+ jac[:,j] = jac_col
+ u[j] = u0[j]
+
+ # return us back to our starting state
+ self.set_input_values(u0)
+
+ # this needs to be a sparse coo_matrix
+ # this approach is inefficient, but clear for an example
+ row = []
+ col = []
+ data = []
+ for r in range(4):
+ for c in range(6):
+ row.append(r)
+ col.append(c)
+ data.append(jac[r,c])
+ ret = coo_matrix((data, (row, col)), shape=(4,6))
+ return ret
+
+ def evaluate_jacobian_outputs(self):
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ cb_ratio = cb/(ca+cc+cd)
+ row = np.zeros(4)
+ col = np.zeros(4)
+ data = np.zeros(4)
+ row[0], col[0], data[0] = (0, 2, -cb/(ca+cc+cd)**2)
+ row[1], col[1], data[1] = (0, 3, 1/(ca+cc+cd))
+ row[2], col[2], data[2] = (0, 4, -cb/(ca+cc+cd)**2)
+ row[3], col[3], data[3] = (0, 5, -cb/(ca+cc+cd)**2)
+ return coo_matrix((data, (row, col)), shape=(1,6))
+
+class ReactorModelNoOutputs(ExternalGreyBoxModel):
+ def input_names(self):
+ return ['sv', 'caf', 'ca', 'cb', 'cc', 'cd']
+
+ def equality_constraint_names(self):
+ return ['ca_bal', 'cb_bal', 'cc_bal', 'cd_bal']
+
+ def output_names(self):
+ return []
+
+ def finalize_block_construction(self, pyomo_block):
+ # set lower bounds on the variables
+ pyomo_block.inputs['sv'].setlb(0)
+ pyomo_block.inputs['ca'].setlb(0)
+ pyomo_block.inputs['cb'].setlb(0)
+ pyomo_block.inputs['cc'].setlb(0)
+ pyomo_block.inputs['cd'].setlb(0)
+
+ # initialize the variables
+ pyomo_block.inputs['sv'].value = 1
+ pyomo_block.inputs['caf'].value = 1
+ pyomo_block.inputs['ca'].value = 1
+ pyomo_block.inputs['cb'].value = 1
+ pyomo_block.inputs['cc'].value = 1
+ pyomo_block.inputs['cd'].value = 1
+
+ def set_input_values(self, input_values):
+ self._input_values = list(input_values)
+
+ def evaluate_equality_constraints(self):
+ sv = self._input_values[0]
+ caf = self._input_values[1]
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ k1 = 5/6
+ k2 = 5/3
+ k3 = 1/6000
+ r = np.zeros(4)
+ r[0] = sv*caf + (-sv-k1)*ca - 2*k3*ca**2
+ r[1] = k1*ca + (-sv-k2)*cb
+ r[2] = k2*cb - sv*cc
+ r[3] = k3*ca**2 - sv*cd
+ return r
+
+ def evaluate_outputs(self):
+ raise NotImplementedError()
+
+ def evaluate_jacobian_equality_constraints(self):
+ sv = self._input_values[0]
+ caf = self._input_values[1]
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ k1 = 5/6
+ k2 = 5/3
+ k3 = 1/6000
+
+ row = np.zeros(12)
+ col = np.zeros(12)
+ data = np.zeros(12)
+ row[0], col[0], data[0] = (0, 0, caf-ca)
+ row[1], col[1], data[1] = (0, 1, sv)
+ row[2], col[2], data[2] = (0, 2, -sv-k1-4*k3*ca)
+ row[3], col[3], data[3] = (1, 0, -cb)
+ row[4], col[4], data[4] = (1, 2, k1)
+ row[5], col[5], data[5] = (1, 3, -sv-k2)
+ row[6], col[6], data[6] = (2, 0, -cc)
+ row[7], col[7], data[7] = (2, 3, k2)
+ row[8], col[8], data[8] = (2, 4, -sv)
+ row[9], col[9], data[9] = (3, 0, -cd)
+ row[10], col[10], data[10] = (3, 2, 2*k3*ca)
+ row[11], col[11], data[11] = (3, 5, -sv)
+ ret = coo_matrix((data, (row, col)), shape=(4,6))
+ return ret
+
+ def evaluate_jacobian_outputs(self):
+ raise NotImplementedError()
+
+class ReactorModelScaled(ExternalGreyBoxModel):
+ def input_names(self):
+ return ['sv', 'caf', 'ca', 'cb', 'cc', 'cd']
+
+ def equality_constraint_names(self):
+ return ['ca_bal', 'cb_bal', 'cc_bal', 'cd_bal']
+
+ def output_names(self):
+ return ['cb_ratio']
+
+ def finalize_block_construction(self, pyomo_block):
+ # set lower bounds on the variables
+ pyomo_block.inputs['sv'].setlb(0)
+ pyomo_block.inputs['ca'].setlb(0)
+ pyomo_block.inputs['cb'].setlb(0)
+ pyomo_block.inputs['cc'].setlb(0)
+ pyomo_block.inputs['cd'].setlb(0)
+
+ # initialize the variables
+ pyomo_block.inputs['sv'].value = 1
+ pyomo_block.inputs['caf'].value = 1
+ pyomo_block.inputs['ca'].value = 1
+ pyomo_block.inputs['cb'].value = 1
+ pyomo_block.inputs['cc'].value = 1
+ pyomo_block.inputs['cd'].value = 1
+ pyomo_block.outputs['cb_ratio'].value = 1
+
+ m = pyomo_block.model()
+ if not hasattr(m, 'scaling_factor'):
+ # add the scaling factor suffix to the model if it is not already declared
+ m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT)
+
+ m.scaling_factor[pyomo_block.inputs['sv']] = 1.1
+ m.scaling_factor[pyomo_block.inputs['caf']] = 1.2
+ m.scaling_factor[pyomo_block.inputs['ca']] = 1.3
+ m.scaling_factor[pyomo_block.inputs['cb']] = 1.4
+ m.scaling_factor[pyomo_block.inputs['cc']] = 1.5
+ m.scaling_factor[pyomo_block.inputs['cd']] = 1.6
+ m.scaling_factor[pyomo_block.outputs['cb_ratio']] = 1.7
+
+ def get_equality_constraint_scaling_factors(self):
+ return np.asarray([0.1, 0.2, 0.3, 0.4])
+
+ def get_output_constraint_scaling_factors(self):
+ return np.asarray([10])
+
+ def set_input_values(self, input_values):
+ self._input_values = list(input_values)
+
+ def evaluate_equality_constraints(self):
+ sv = self._input_values[0]
+ caf = self._input_values[1]
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ k1 = 5/6
+ k2 = 5/3
+ k3 = 1/6000
+ r = np.zeros(4)
+ r[0] = sv*caf + (-sv-k1)*ca - 2*k3*ca**2
+ r[1] = k1*ca + (-sv-k2)*cb
+ r[2] = k2*cb - sv*cc
+ r[3] = k3*ca**2 - sv*cd
+ return r
+
+ def evaluate_outputs(self):
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ cb_ratio = cb/(ca+cc+cd)
+ return np.asarray([cb_ratio], dtype=np.float64)
+
+ def evaluate_jacobian_equality_constraints(self):
+ sv = self._input_values[0]
+ caf = self._input_values[1]
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ k1 = 5/6
+ k2 = 5/3
+ k3 = 1/6000
+
+ row = np.zeros(12)
+ col = np.zeros(12)
+ data = np.zeros(12)
+ row[0], col[0], data[0] = (0, 0, caf-ca)
+ row[1], col[1], data[1] = (0, 1, sv)
+ row[2], col[2], data[2] = (0, 2, -sv-k1-4*k3*ca)
+ row[3], col[3], data[3] = (1, 0, -cb)
+ row[4], col[4], data[4] = (1, 2, k1)
+ row[5], col[5], data[5] = (1, 3, -sv-k2)
+ row[6], col[6], data[6] = (2, 0, -cc)
+ row[7], col[7], data[7] = (2, 3, k2)
+ row[8], col[8], data[8] = (2, 4, -sv)
+ row[9], col[9], data[9] = (3, 0, -cd)
+ row[10], col[10], data[10] = (3, 2, 2*k3*ca)
+ row[11], col[11], data[11] = (3, 5, -sv)
+ ret = coo_matrix((data, (row, col)), shape=(4,6))
+ return ret
+
+ def evaluate_jacobian_outputs(self):
+ ca = self._input_values[2]
+ cb = self._input_values[3]
+ cc = self._input_values[4]
+ cd = self._input_values[5]
+ cb_ratio = cb/(ca+cc+cd)
+ row = np.zeros(4)
+ col = np.zeros(4)
+ data = np.zeros(4)
+ row[0], col[0], data[0] = (0, 2, -cb/(ca+cc+cd)**2)
+ row[1], col[1], data[1] = (0, 3, 1/(ca+cc+cd))
+ row[2], col[2], data[2] = (0, 4, -cb/(ca+cc+cd)**2)
+ row[3], col[3], data[3] = (0, 5, -cb/(ca+cc+cd)**2)
+ return coo_matrix((data, (row, col)), shape=(1,6))
diff --git a/pyomo/contrib/pynumero/examples/feasibility.py b/pyomo/contrib/pynumero/examples/feasibility.py
index 64c3906bb0a..d24d38ec26b 100644
--- a/pyomo/contrib/pynumero/examples/feasibility.py
+++ b/pyomo/contrib/pynumero/examples/feasibility.py
@@ -7,9 +7,11 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
from pyomo.contrib.pynumero.interfaces.pyomo_nlp import PyomoNLP
-from pyomo.contrib.pynumero.interfaces.utils import build_bounds_mask, build_compression_matrix, full_to_compressed
-import matplotlib.pylab as plt
+from pyomo.contrib.pynumero.interfaces.utils import (build_bounds_mask,
+ build_compression_matrix,
+ full_to_compressed)
import pyomo.environ as pyo
import numpy as np
@@ -101,4 +103,3 @@ def create_basic_model():
feasible = True
print("Is x0 feasible:", feasible)
-
diff --git a/pyomo/contrib/pynumero/examples/gas_network_model.py b/pyomo/contrib/pynumero/examples/gas_network_model.py
index a5e50a3c9da..55b6b510140 100644
--- a/pyomo/contrib/pynumero/examples/gas_network_model.py
+++ b/pyomo/contrib/pynumero/examples/gas_network_model.py
@@ -7,11 +7,12 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
import pyomo.environ as pyo
import pyomo.dae as dae
import numpy as np
import networkx
-import json
+
def create_model(demand_factor=1.0):
diff --git a/pyomo/contrib/pynumero/examples/sensitivity.py b/pyomo/contrib/pynumero/examples/sensitivity.py
index ac56b8e1a40..afbbc443fdb 100644
--- a/pyomo/contrib/pynumero/examples/sensitivity.py
+++ b/pyomo/contrib/pynumero/examples/sensitivity.py
@@ -7,6 +7,7 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
import pyomo.environ as pyo
from pyomo.contrib.pynumero.interfaces.pyomo_nlp import PyomoNLP
from pyomo.contrib.pynumero.sparse import BlockMatrix, BlockVector
@@ -110,7 +111,7 @@ def compute_init_lam(nlp, x=None, lam_max=1e3):
new_x = x[x_indices] + dx
print("dp:", dp)
print("dx:", dx)
-print("Variable names: \n",x_names[x_indices])
+print("Variable names: \n", x_names[x_indices])
print("Sensitivity based x:\n", new_x)
#################################################################
diff --git a/pyomo/contrib/pynumero/examples/structured/nlp_transformations.py b/pyomo/contrib/pynumero/examples/structured/nlp_transformations.py
index 2c405e7c62f..8af3a628323 100644
--- a/pyomo/contrib/pynumero/examples/structured/nlp_transformations.py
+++ b/pyomo/contrib/pynumero/examples/structured/nlp_transformations.py
@@ -7,11 +7,12 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
from pyomo.contrib.pynumero.interfaces.nlp import NLP
from pyomo.contrib.pynumero.sparse import empty_matrix
-from scipy.sparse import coo_matrix, csc_matrix, csr_matrix
-import pyomo.environ as aml
+from scipy.sparse import coo_matrix, csr_matrix
+import pyomo.environ as pyo
import numpy as np
__all__ = ['AdmmNLP']
@@ -711,15 +712,15 @@ def compose_two_stage_stochastic_model(models, complicating_vars):
assert len(v) == nz, 'all models must have same number of complicating variables'
counter += 1
- model = aml.ConcreteModel()
- model.z = aml.Var(range(nz))
+ model = pyo.ConcreteModel()
+ model.z = pyo.Var(range(nz))
model.scenario_names = sorted([name for name in models.keys()])
obj = 0.0
for i, j in enumerate(model.scenario_names):
instance = models[j].clone()
- model.add_component("{}_linking".format(j), aml.ConstraintList())
+ model.add_component("{}_linking".format(j), pyo.ConstraintList())
model.add_component("{}".format(j), instance)
linking = getattr(model, "{}_linking".format(j))
x = complicating_vars[j]
@@ -727,16 +728,16 @@ def compose_two_stage_stochastic_model(models, complicating_vars):
for k, var in enumerate(x):
if var.is_indexed():
raise RuntimeError('indexed complicating variables not supported')
- vid = aml.ComponentUID(var)
+ vid = pyo.ComponentUID(var)
vv = vid.find_component_on(instance)
linking.add(vv == model.z[k])
# gets objective
- objectives = instance.component_map(aml.Objective, active=True)
+ objectives = instance.component_map(pyo.Objective, active=True)
if len(objectives) > 1:
raise RuntimeError('Multiple objectives not supported')
instance_obj = list(objectives.values())[0]
obj += instance_obj.expr
instance_obj.deactivate()
- model.obj = aml.Objective(expr=obj)
+ model.obj = pyo.Objective(expr=obj)
return model
\ No newline at end of file
diff --git a/pyomo/contrib/pynumero/examples/structured/stochastic_nlp.py b/pyomo/contrib/pynumero/examples/structured/stochastic_nlp.py
index c06af88d2ca..06e8af51ca4 100644
--- a/pyomo/contrib/pynumero/examples/structured/stochastic_nlp.py
+++ b/pyomo/contrib/pynumero/examples/structured/stochastic_nlp.py
@@ -7,27 +7,29 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
from pyomo.contrib.pynumero.interfaces import PyomoNLP
from pyomo.contrib.pynumero.interfaces.nlp_compositions import TwoStageStochasticNLP
-from pyomo.contrib.pynumero.sparse import BlockSymMatrix, BlockVector
+from pyomo.contrib.pynumero.sparse import BlockSymMatrix
import matplotlib.pylab as plt
-import pyomo.environ as aml
+import pyomo.environ as pyo
import numpy as np
-import os
+
def create_basic_dense_qp(G, A, b, c):
nx = G.shape[0]
nl = A.shape[0]
- model = aml.ConcreteModel()
+ model = pyo.ConcreteModel()
model.var_ids = range(nx)
model.con_ids = range(nl)
- model.x = aml.Var(model.var_ids, initialize=0.0)
-
+ model.x = pyo.Var(model.var_ids, initialize=0.0)
+
def equality_constraint_rule(m, i):
return sum(A[i, j] * m.x[j] for j in m.var_ids) == b[i]
- model.equalities = aml.Constraint(model.con_ids, rule=equality_constraint_rule)
+ model.equalities = pyo.Constraint(model.con_ids,
+ rule=equality_constraint_rule)
def objective_rule(m):
accum = 0.0
@@ -37,10 +39,11 @@ def objective_rule(m):
accum += sum(m.x[j] * c[j] for j in m.var_ids)
return accum
- model.obj = aml.Objective(rule=objective_rule, sense=aml.minimize)
+ model.obj = pyo.Objective(rule=objective_rule, sense=pyo.minimize)
return model
+
G = np.array([[6, 2, 1], [2, 5, 2], [1, 2, 4]])
A = np.array([[1, 0, 1], [0, 1, 1]])
b = np.array([3, 0])
diff --git a/pyomo/contrib/pynumero/examples/structured/tests/test_nlp_compositions.py b/pyomo/contrib/pynumero/examples/structured/tests/test_nlp_compositions.py
index b802309d2ba..56bf718aa87 100644
--- a/pyomo/contrib/pynumero/examples/structured/tests/test_nlp_compositions.py
+++ b/pyomo/contrib/pynumero/examples/structured/tests/test_nlp_compositions.py
@@ -7,8 +7,9 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as aml
+import pyomo.environ as pyo
import os
from pyomo.contrib.pynumero.dependencies import (
numpy as np, numpy_available, scipy_sparse, scipy_available
@@ -31,30 +32,30 @@ def create_basic_dense_qp(G, A, b, c, complicated_var_ids):
nx = G.shape[0]
nl = A.shape[0]
- model = aml.ConcreteModel()
+ model = pyo.ConcreteModel()
model.var_ids = range(nx)
model.complicated_var_ids = complicated_var_ids
model.con_ids = range(nl)
- model.x = aml.Var(model.var_ids, initialize=0.0)
+ model.x = pyo.Var(model.var_ids, initialize=0.0)
model.x[0].value = 1.0
model.x[0].setlb(-100.0)
model.x[0].setub(100.0)
- model.z = aml.Var(model.complicated_var_ids, initialize=0.0)
- model.hessian_f = aml.Param(model.var_ids, model.var_ids, mutable=True, rule=lambda m, i, j: G[i, j])
- model.jacobian_c = aml.Param(model.con_ids, model.var_ids, mutable=True, rule=lambda m, i, j: A[i, j])
- model.rhs = aml.Param(model.con_ids, mutable=True, rule=lambda m, i: b[i])
- model.grad_f = aml.Param(model.var_ids, mutable=True, rule=lambda m, i: c[i])
+ model.z = pyo.Var(model.complicated_var_ids, initialize=0.0)
+ model.hessian_f = pyo.Param(model.var_ids, model.var_ids, mutable=True, rule=lambda m, i, j: G[i, j])
+ model.jacobian_c = pyo.Param(model.con_ids, model.var_ids, mutable=True, rule=lambda m, i, j: A[i, j])
+ model.rhs = pyo.Param(model.con_ids, mutable=True, rule=lambda m, i: b[i])
+ model.grad_f = pyo.Param(model.var_ids, mutable=True, rule=lambda m, i: c[i])
def equality_constraint_rule(m, i):
return sum(m.jacobian_c[i, j] * m.x[j] for j in m.var_ids) == m.rhs[i]
- model.equalities = aml.Constraint(model.con_ids, rule=equality_constraint_rule)
+ model.equalities = pyo.Constraint(model.con_ids, rule=equality_constraint_rule)
def fixing_constraints_rule(m, i):
return m.z[i] == m.x[i]
- model.fixing_constraints = aml.Constraint(model.complicated_var_ids, rule=fixing_constraints_rule)
+ model.fixing_constraints = pyo.Constraint(model.complicated_var_ids, rule=fixing_constraints_rule)
def second_stage_cost_rule(m):
accum = 0.0
@@ -64,30 +65,30 @@ def second_stage_cost_rule(m):
accum += sum(m.x[j] * m.grad_f[j] for j in m.var_ids)
return accum
- model.FirstStageCost = aml.Expression(expr=0.0)
- model.SecondStageCost = aml.Expression(rule=second_stage_cost_rule)
+ model.FirstStageCost = pyo.Expression(expr=0.0)
+ model.SecondStageCost = pyo.Expression(rule=second_stage_cost_rule)
- model.obj = aml.Objective(expr=model.FirstStageCost + model.SecondStageCost,
- sense=aml.minimize)
+ model.obj = pyo.Objective(expr=model.FirstStageCost + model.SecondStageCost,
+ sense=pyo.minimize)
return model
def create_basic_model():
- m = aml.ConcreteModel()
- m.x = aml.Var([1, 2, 3], domain=aml.Reals)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var([1, 2, 3], domain=pyo.Reals)
for i in range(1, 4):
m.x[i].value = i
- m.c1 = aml.Constraint(expr=m.x[1] ** 2 - m.x[2] - 1 == 0)
- m.c2 = aml.Constraint(expr=m.x[1] - m.x[3] - 0.5 == 0)
- m.d1 = aml.Constraint(expr=m.x[1] + m.x[2] <= 100.0)
- m.d2 = aml.Constraint(expr=m.x[2] + m.x[3] >= -100.0)
- m.d3 = aml.Constraint(expr=m.x[2] + m.x[3] + m.x[1] >= -500.0)
+ m.c1 = pyo.Constraint(expr=m.x[1] ** 2 - m.x[2] - 1 == 0)
+ m.c2 = pyo.Constraint(expr=m.x[1] - m.x[3] - 0.5 == 0)
+ m.d1 = pyo.Constraint(expr=m.x[1] + m.x[2] <= 100.0)
+ m.d2 = pyo.Constraint(expr=m.x[2] + m.x[3] >= -100.0)
+ m.d3 = pyo.Constraint(expr=m.x[2] + m.x[3] + m.x[1] >= -500.0)
m.x[2].setlb(0.0)
m.x[3].setlb(0.0)
m.x[2].setub(100.0)
- m.obj = aml.Objective(expr=m.x[2]**2)
+ m.obj = pyo.Objective(expr=m.x[2]**2)
return m
diff --git a/pyomo/contrib/pynumero/examples/structured/tests/test_nlp_transformations.py b/pyomo/contrib/pynumero/examples/structured/tests/test_nlp_transformations.py
index 80b0442620b..38c0fc7626a 100644
--- a/pyomo/contrib/pynumero/examples/structured/tests/test_nlp_transformations.py
+++ b/pyomo/contrib/pynumero/examples/structured/tests/test_nlp_transformations.py
@@ -7,10 +7,8 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
import pyutilib.th as unittest
-from pyomo.common.plugin import alias
-import pyomo.environ as aml
-import os
from pyomo.contrib.pynumero.dependencies import (
numpy as np, numpy_available, scipy_sparse as spa, scipy_available
@@ -27,7 +25,7 @@
from pyomo.contrib.pynumero.interfaces.nlp import PyomoNLP
from pyomo.contrib.pynumero.interfaces.nlp_transformations import AdmmNLP
from pyomo.core.plugins.transform.hierarchy import Transformation
-import pyomo.environ as aml
+import pyomo.environ as pyo
class AdmmModel(Transformation):
@@ -59,7 +57,7 @@ def _apply_to(self, model, **kwds):
cloned_vars = []
original_vars = []
for v in complicating_vars:
- vid = aml.ComponentUID(v)
+ vid = pyo.ComponentUID(v)
vv = vid.find_component_on(model)
if v.is_indexed():
raise RuntimeError('Indexed variables not supported')
@@ -78,16 +76,16 @@ def _apply_to(self, model, **kwds):
assert len(w_estimates) == nz
w_vals = w_estimates
- model._z = aml.Param(range(nz), initialize=0.0, mutable=True)
- model._w = aml.Param(range(nz), initialize=0.0, mutable=True)
+ model._z = pyo.Param(range(nz), initialize=0.0, mutable=True)
+ model._w = pyo.Param(range(nz), initialize=0.0, mutable=True)
for i in range(nz):
model._z[i].value = z_vals[i]
model._w[i].value = w_vals[i]
- model._rho = aml.Param(initialize=rho, mutable=True)
+ model._rho = pyo.Param(initialize=rho, mutable=True)
# defines objective
- objectives = model.component_map(aml.Objective, active=True)
+ objectives = model.component_map(pyo.Objective, active=True)
if len(objectives) > 1:
raise RuntimeError('Multiple objectives not supported')
obj = list(objectives.values())[0]
@@ -95,7 +93,8 @@ def _apply_to(self, model, **kwds):
def rule_linkin_exprs(m, i):
return cloned_vars[i] - m._z[i]
# store non-anticipativity expression
- model._linking_residuals = aml.Expression(range(nz), rule=rule_linkin_exprs)
+ model._linking_residuals = pyo.Expression(range(nz),
+ rule=rule_linkin_exprs)
dual_term = 0.0
penalty_term = 0.0
@@ -104,11 +103,11 @@ def rule_linkin_exprs(m, i):
penalty_term += (model._linking_residuals[zid])**2
# multiplier terms in objective
- model._dual_obj_term = aml.Expression(expr=dual_term)
+ model._dual_obj_term = pyo.Expression(expr=dual_term)
# penalty term
- model._penalty_obj_term = aml.Expression(expr=0.5 * model._rho * penalty_term)
+ model._penalty_obj_term = pyo.Expression(expr=0.5 * model._rho * penalty_term)
- model._aug_obj = aml.Objective(expr=obj.expr +
+ model._aug_obj = pyo.Objective(expr=obj.expr +
model._dual_obj_term +
model._penalty_obj_term)
@@ -116,11 +115,12 @@ def rule_linkin_exprs(m, i):
def propagate_solution(self, augmented_model, original_model):
- for avar in augmented_model.component_objects(ctype=aml.Var, descend_into=True):
- cuid = aml.ComponentUID(avar)
+ for avar in augmented_model.component_objects(ctype=pyo.Var,
+ descend_into=True):
+ cuid = pyo.ComponentUID(avar)
original_v = cuid.find_component_on(original_model)
for k in avar:
- original_v[k].value = aml.value(avar[k])
+ original_v[k].value = pyo.value(avar[k])
def create_basic_dense_qp(G, A, b, c):
@@ -128,11 +128,11 @@ def create_basic_dense_qp(G, A, b, c):
nx = G.shape[0]
nl = A.shape[0]
- model = aml.ConcreteModel()
+ model = pyo.ConcreteModel()
model.var_ids = range(nx)
model.con_ids = range(nl)
- model.x = aml.Var(model.var_ids, initialize=0.0)
+ model.x = pyo.Var(model.var_ids, initialize=0.0)
model.hessian_f = G
model.jacobian_c = A
model.rhs = b
@@ -140,7 +140,8 @@ def create_basic_dense_qp(G, A, b, c):
def equality_constraint_rule(m, i):
return sum(m.jacobian_c[i, j] * m.x[j] for j in m.var_ids) == m.rhs[i]
- model.equalities = aml.Constraint(model.con_ids, rule=equality_constraint_rule)
+ model.equalities = pyo.Constraint(model.con_ids,
+ rule=equality_constraint_rule)
def objective_rule(m):
accum = 0.0
@@ -150,44 +151,44 @@ def objective_rule(m):
accum += sum(m.x[j] * m.grad_f[j] for j in m.var_ids)
return accum
- model.obj = aml.Objective(rule=objective_rule, sense=aml.minimize)
+ model.obj = pyo.Objective(rule=objective_rule, sense=pyo.minimize)
return model
def create_model2():
- model = aml.ConcreteModel()
+ model = pyo.ConcreteModel()
model.indices = [i for i in range(1, 6)]
- model.x = aml.Var(model.indices, initialize=2)
+ model.x = pyo.Var(model.indices, initialize=2)
def rule_obj(m):
expr = (m.x[1] - m.x[2]) ** 2 + (m.x[2] + m.x[3] - 2) ** 2 + (m.x[4] - 1) ** 2 + (m.x[5] - 1) **2
return expr
- model.obj = aml.Objective(rule=rule_obj)
+ model.obj = pyo.Objective(rule=rule_obj)
- model.c1 = aml.Constraint(expr=model.x[1] + 3 * model.x[2] == 0.0)
- model.c2 = aml.Constraint(expr=model.x[3] + model.x[4] - 2 * model.x[5] == 0.0)
- model.c3 = aml.Constraint(expr=model.x[2] - model.x[5] == 0.0)
+ model.c1 = pyo.Constraint(expr=model.x[1] + 3 * model.x[2] == 0.0)
+ model.c2 = pyo.Constraint(expr=model.x[3] + model.x[4] - 2 * model.x[5] == 0.0)
+ model.c3 = pyo.Constraint(expr=model.x[2] - model.x[5] == 0.0)
return model
def create_basic_model():
- m = aml.ConcreteModel()
- m.x = aml.Var([1, 2, 3], domain=aml.Reals)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var([1, 2, 3], domain=pyo.Reals)
for i in range(1, 4):
m.x[i].value = i
- m.c1 = aml.Constraint(expr=m.x[1] ** 2 - m.x[2] - 1 == 0)
- m.c2 = aml.Constraint(expr=m.x[1] - m.x[3] - 0.5 == 0)
- m.d1 = aml.Constraint(expr=m.x[1] + m.x[2] <= 100.0)
- m.d2 = aml.Constraint(expr=m.x[2] + m.x[3] >= -100.0)
- m.d3 = aml.Constraint(expr=m.x[2] + m.x[3] + m.x[1] >= -500.0)
+ m.c1 = pyo.Constraint(expr=m.x[1] ** 2 - m.x[2] - 1 == 0)
+ m.c2 = pyo.Constraint(expr=m.x[1] - m.x[3] - 0.5 == 0)
+ m.d1 = pyo.Constraint(expr=m.x[1] + m.x[2] <= 100.0)
+ m.d2 = pyo.Constraint(expr=m.x[2] + m.x[3] >= -100.0)
+ m.d3 = pyo.Constraint(expr=m.x[2] + m.x[3] + m.x[1] >= -500.0)
m.x[2].setlb(0.0)
m.x[3].setlb(0.0)
m.x[2].setub(100.0)
- m.obj = aml.Objective(expr=m.x[1]**2 + m.x[2]**2 + m.x[3]**2)
+ m.obj = pyo.Objective(expr=m.x[1]**2 + m.x[2]**2 + m.x[3]**2)
return m
diff --git a/pyomo/contrib/pynumero/interfaces/ampl_nlp.py b/pyomo/contrib/pynumero/interfaces/ampl_nlp.py
index 12c612088ed..5aafaedccd7 100644
--- a/pyomo/contrib/pynumero/interfaces/ampl_nlp.py
+++ b/pyomo/contrib/pynumero/interfaces/ampl_nlp.py
@@ -362,13 +362,13 @@ def create_new_vector(self, vector_type):
numpy.ndarray
"""
if vector_type == 'primals':
- return np.zeros(self._n_primals, dtype=np.float64)
+ return np.zeros(self.n_primals(), dtype=np.float64)
elif vector_type == 'constraints' or vector_type == 'duals':
- return np.zeros(self._n_con_full, dtype=np.float64)
+ return np.zeros(self.n_constraints(), dtype=np.float64)
elif vector_type == 'eq_constraints' or vector_type == 'duals_eq':
- return np.zeros(self._n_con_eq, dtype=np.float64)
+ return np.zeros(self.n_eq_constraints(), dtype=np.float64)
elif vector_type == 'ineq_constraints' or vector_type == 'duals_ineq':
- return np.zeros(self._n_con_ineq, dtype=np.float64)
+ return np.zeros(self.n_ineq_constraints(), dtype=np.float64)
else:
raise RuntimeError('Called create_new_vector with an unknown vector_type')
@@ -440,14 +440,16 @@ def get_constraints_scaling(self):
def get_eq_constraints_scaling(self):
constraints_scaling = self.get_constraints_scaling()
if constraints_scaling is not None:
- return np.compress(self._con_full_eq_mask, constraints_scaling)
+ return np.compress(self._con_full_eq_mask,
+ constraints_scaling)
return None
# overloaded from ExtendedNLP
def get_ineq_constraints_scaling(self):
constraints_scaling = self.get_constraints_scaling()
if constraints_scaling is not None:
- return np.compress(self._con_full_ineq_mask, constraints_scaling)
+ return np.compress(self._con_full_ineq_mask,
+ constraints_scaling)
return None
def _evaluate_objective_and_cache_if_necessary(self):
diff --git a/pyomo/contrib/pynumero/interfaces/external_grey_box.py b/pyomo/contrib/pynumero/interfaces/external_grey_box.py
new file mode 100644
index 00000000000..80c72394215
--- /dev/null
+++ b/pyomo/contrib/pynumero/interfaces/external_grey_box.py
@@ -0,0 +1,454 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+import abc
+import logging
+import numpy as np
+from scipy.sparse import coo_matrix
+
+from pyomo.common.timing import ConstructionTimer
+from pyomo.core.base import Var, Constraint, value
+from pyomo.core.base.block import _BlockData, Block, declare_custom_block
+from pyomo.core.base.util import Initializer
+
+from ..sparse.block_matrix import BlockMatrix
+
+from six import add_metaclass, itervalues, iteritems
+from six.moves import xrange
+
+logger = logging.getLogger('pyomo.contrib.pynumero')
+
+"""
+This module is used for interfacing an external model as
+a block in a Pyomo model.
+
+An ExternalGreyBoxModel is model is a model that does not
+provide constraints explicitly as algebraic expressions, but
+instead provides a set of methods that can compute the residuals
+of the constraints (or outputs) and their derivatives.
+
+This allows one to interface external codes (e.g., compiled
+external models) with a Pyomo model.
+
+Note: To solve a Pyomo model that contains these external models
+ we have a specialized interface built on PyNumero that provides
+ an interface to the CyIpopt solver.
+
+To use this interface:
+ * Create a class that is derived from ExternalGreyBoxModel and
+ implement the necessary methods. This derived class must provide
+ a list of names for: the inputs to your model, the equality constraints
+ (or residuals) that need to be converged, and any outputs that
+ are computed from your model. It will also need to provide methods to
+ compute the residuals, outputs, and the jacobian of these with respect to
+ the inputs. See the documentation on ExternalGreyBoxModel for more details.
+
+ * Create a Pyomo model and make use of the ExternalGreyBoxBlock
+ to produce a Pyomo modeling component that represents your
+ external model. This block is a Pyomo component, and when you
+ call set_external_model() and provide an instance of your derived
+ ExternalGreyBoxModel, it will automatically create pyomo variables to
+ represent the inputs and the outputs from the external model. You
+ can implement a callback to modify the Pyomo block after it is
+ constructed. This also provides a mechanism to initalize variables,
+ etc.
+
+ * Create a PyomoGreyBoxNLP and provide it with the Pyomo model
+ that contains the ExternalGreyBoxBlocks. This class presents
+ an NLP interface (i.e., the PyNumero NLP abstract class), and
+ can be used with any solver that makes use of this interface
+ (e.g., the CyIpopt solver interface provided in PyNumero)
+
+See pyomo/contrib/pynumero/examples/external_grey_box for examples
+of the use of this interface.
+
+Note:
+
+ * Currently, you cannot "fix" a pyomo variable that corresponds to an
+ input or output and you must use a constraint instead (this is
+ because Pyomo removes fixed variables before sending them to the
+ solver)
+
+"""
+
+@add_metaclass(abc.ABCMeta)
+class ExternalGreyBoxModel(object):
+ """
+ This is the base class for building external input output models
+ for use with Pyomo and CyIpopt. See the module documentation above,
+ and documentation of individual methods as well as examples.
+ """
+ def n_inputs(self):
+ """ This method returns the number of inputs. You do not
+ need to overload this method in derived classes.
+ """
+ return len(self.input_names())
+
+ def n_equality_constraints(self):
+ """ This method returns the number of equality constraints.
+ You do not need to overload this method in derived classes.
+ """
+ return len(self.equality_constraint_names())
+
+ def n_outputs(self):
+ """ This method returns the number of outputs. You do not
+ need to overload this method in derived classes.
+ """
+ return len(self.output_names())
+
+ @abc.abstractmethod
+ def input_names(self):
+ """
+ Provide the list of string names to corresponding to the inputs
+ of this external model. These should be returned in the same order
+ that they are to be used in set_input_values.
+ """
+ pass
+
+ def equality_constraint_names(self):
+ """
+ Provide the list of string names corresponding to any residuals
+ for this external model. These should be in the order corresponding
+ to values returned from evaluate_residuals. Return an empty list
+ if there are no equality constraints.
+ """
+ return []
+
+ def output_names(self):
+ """
+ Provide the list of string names corresponding to the outputs
+ of this external model. These should be in the order corresponding
+ to values returned from evaluate_outputs. Return an empty list if there
+ are no computed outputs.
+ """
+ return []
+
+ def finalize_block_construction(self, pyomo_block):
+ """
+ Implement this callback to provide any additional
+ specifications to the Pyomo block that is created
+ to represent this external grey box model.
+
+ Note that pyomo_block.inputs and pyomo_block.outputs
+ have been created, and this callback provides an
+ opportunity to set initial values, bounds, etc.
+ """
+ pass
+
+ @abc.abstractmethod
+ def set_input_values(self, input_values):
+ """
+ This method is called by the solver to set the current values
+ for the input variables. The derived class must cache these if
+ necessary for any subsequent calls to evalute_outputs or
+ evaluate_derivatives.
+ """
+ pass
+
+ def get_equality_constraint_scaling_factors(self):
+ """
+ This method is called by the solver interface to get desired
+ values for scaling the equality constraints. None means no
+ scaling is desired. Note that, depending on the solver,
+ one may need to set solver options so these factors are used
+ """
+ return None
+
+ def get_output_constraint_scaling_factors(self):
+ """
+ This method is called by the solver interface to get desired
+ values for scaling the constraints with output variables. Returning
+ None means that no scaling of the output constraints is desired.
+ Note that, depending on the solver, one may need to set solver options
+ so these factors are used
+ """
+ return None
+
+ def evaluate_equality_constraints(self):
+ """
+ Compute the residuals from the model (using the values
+ set in input_values) and return as a numpy array
+ """
+ raise NotImplementedError()
+
+ def evaluate_outputs(self):
+ """
+ Compute the outputs from the model (using the values
+ set in input_values) and return as a numpy array
+ """
+ raise NotImplementedError()
+
+ def evaluate_jacobian_equality_constraints(self):
+ """
+ Compute the derivatives of the residuals with respect
+ to the inputs (using the values set in input_values).
+ This should be a scipy matrix with the rows in
+ the order of the residual names and the cols in
+ the order of the input variables.
+ """
+ raise NotImplementedError()
+
+ def evaluate_jacobian_outputs(self):
+ """
+ Compute the derivatives of the outputs with respect
+ to the inputs (using the values set in input_values).
+ This should be a scipy matrix with the rows in
+ the order of the output variables and the cols in
+ the order of the input variables.
+ """
+ raise NotImplementedError()
+
+ # ToDo: Hessians not yet handled
+
+
+class ExternalGreyBoxBlockData(_BlockData):
+
+ def set_external_model(self, external_grey_box_model):
+ self._ex_model = ex_model = external_grey_box_model
+ if ex_model is None:
+ self._input_names = self._output_names = None
+ self.inputs = self.outputs = None
+ return
+
+ self._input_names = ex_model.input_names()
+ if self._input_names is None or len(self._input_names) == 0:
+ raise ValueError(
+ 'No input_names specified for external_grey_box_model.'
+ ' Must specify at least one input.')
+ self.inputs = Var(self._input_names)
+
+ self._equality_constraint_names = ex_model.equality_constraint_names()
+ self._output_names = ex_model.output_names()
+
+ # Note, this works even if output_names is an empty list
+ self.outputs = Var(self._output_names)
+
+ # call the callback so the model can set initialization, bounds, etc.
+ external_grey_box_model.finalize_block_construction(self)
+
+ def get_external_model(self):
+ return self._ex_model
+
+
+class ExternalGreyBoxBlock(Block):
+ def __new__(cls, *args, **kwds):
+ if cls != ExternalGreyBoxBlock:
+ target_cls = cls
+ elif not args or (args[0] is UnindexedComponent_set and len(args) == 1):
+ target_cls = SimpleExternalGreyBoxBlock
+ else:
+ target_cls = IndexedExternalGreyBoxBlock
+ return super(ExternalGreyBoxBlock, cls).__new__(target_cls)
+
+ def __init__(self, *args, **kwds):
+ kwds.setdefault('ctype', ExternalGreyBoxBlock)
+ self._init_model = Initializer(kwds.pop('external_model', None))
+ Block.__init__(self, *args, **kwds)
+
+ def construct(self, data=None):
+ """
+ Construct the ExternalGreyBoxBlockDatas
+ """
+ if self._constructed:
+ return
+ # Do not set the constructed flag - Block.construct() will do that
+
+ timer = ConstructionTimer(self)
+ if __debug__ and logger.isEnabledFor(logging.DEBUG):
+ logger.debug("Constructing external grey box model %s"
+ % (self.name))
+
+ super(ExternalGreyBoxBlock, self).construct(data)
+
+ if self._init_model is not None:
+ block = self.parent_block()
+ for index, data in iteritems(self):
+ data.set_external_model(self._init_model(block, index))
+
+
+class SimpleExternalGreyBoxBlock(ExternalGreyBoxBlockData, ExternalGreyBoxBlock):
+ def __init__(self, *args, **kwds):
+ ExternalGreyBoxBlockData.__init__(self, component=self)
+ ExternalGreyBoxBlock.__init__(self, *args, **kwds)
+
+ # Pick up the display() from Block and not BlockData
+ display = ExternalGreyBoxBlock.display
+
+
+class IndexedExternalGreyBoxBlock(Block):
+ pass
+
+
+class _ExternalGreyBoxModelHelper(object):
+ def __init__(self, ex_grey_box_block, vardata_to_idx, initial_primal_values):
+ """This helper takes an ExternalGreyBoxModel and provides the residual
+ and Jacobian computation.
+
+ The ExternalGreyBoxModel provides an interface that supports
+ equality constraints (pure residuals) and output equations. Let
+ u be the inputs, o be the outputs, and x be the full set of
+ primal variables from the entire pyomo_nlp.
+
+ With this, the ExternalGreyBoxModel provides the residual
+ computations w_eq(u), and w_o(u), as well as the Jacobians,
+ Jw_eq(u), and Jw_o(u). This helper provides h(x)=0, where h(x) =
+ [h_eq(x); h_o(x)-o] and h_eq(x)=w_eq(Pu*x), and
+ h_o(x)=w_o(Pu*x), and Pu is a mapping from the full primal
+ variables "x" to the inputs "u".
+
+ It also provides the Jacobian of h w.r.t. x.
+ J_h(x) = [Jw_eq(Pu*x); Jw_o(Pu*x)-Po*x]
+ where Po is a mapping from the full primal variables "x" to the
+ outputs "o".
+
+ """
+ self._block = ex_grey_box_block
+ self._ex_model = ex_grey_box_block.get_external_model()
+ self._n_primals = len(initial_primal_values)
+ n_inputs = len(self._block.inputs)
+ n_outputs = len(self._block.outputs)
+
+ # store the map of input indices (0 .. n_inputs) to
+ # the indices in the full primals vector
+ self._inputs_to_primals_map = np.fromiter(
+ (vardata_to_idx[v] for v in itervalues(self._block.inputs)),
+ dtype=np.int64, count=n_inputs)
+
+ # store the map of output indices (0 .. n_outputs) to
+ # the indices in the full primals vector
+ self._outputs_to_primals_map = np.fromiter(
+ (vardata_to_idx[v] for v in itervalues(self._block.outputs)),
+ dtype=np.int64, count=n_outputs)
+
+ # setup some structures for the jacobians
+ input_values = initial_primal_values[self._inputs_to_primals_map]
+ self._ex_model.set_input_values(input_values)
+
+ if self._ex_model.n_outputs() == 0 and \
+ self._ex_model.n_equality_constraints() == 0:
+ raise ValueError(
+ 'ExternalGreyBoxModel has no equality constraints '
+ 'or outputs. It must have at least one or both.')
+
+ # we need to change the column indices in the jacobian
+ # from the 0..n_inputs provided by the external model
+ # to the indices corresponding to the full Pyomo model
+ # so we create that here
+ self._eq_jac_primal_jcol = None
+ if self._ex_model.n_equality_constraints() > 0:
+ jac = self._ex_model.evaluate_jacobian_equality_constraints()
+ self._eq_jac_primal_jcol = self._inputs_to_primals_map[jac.col]
+
+ self._outputs_jac_primal_jcol = None
+ if self._ex_model.n_outputs() > 0:
+ jac = self._ex_model.evaluate_jacobian_outputs()
+ self._outputs_jac_primal_jcol = self._inputs_to_primals_map[jac.col]
+
+ # create the irow, jcol, nnz structure for the
+ # output variable portion of h(u)-o=0
+ self._additional_output_entries_irow = np.asarray(xrange(n_outputs))
+ self._additional_output_entries_jcol = self._outputs_to_primals_map
+ self._additional_output_entries_data = -1.0*np.ones(n_outputs)
+
+ def set_primals(self, primals):
+ # map the full primals "x" to the inputs "u" and set
+ # the values on the external model
+ input_values = primals[self._inputs_to_primals_map]
+ self._ex_model.set_input_values(input_values)
+
+ # map the full primals "x" to the outputs "o" and
+ # store a vector of the current output values to
+ # use when evaluating residuals
+ self._output_values = primals[self._outputs_to_primals_map]
+
+ def n_residuals(self):
+ return self._ex_model.n_equality_constraints() \
+ + self._ex_model.n_outputs()
+
+ def get_residual_scaling(self):
+ eq_scaling = self._ex_model.get_equality_constraint_scaling_factors()
+ output_con_scaling = self._ex_model.get_output_constraint_scaling_factors()
+ if eq_scaling is None and output_con_scaling is None:
+ return None
+ if eq_scaling is None:
+ eq_scaling = np.ones(self._ex_model.n_equality_constraints())
+ if output_con_scaling is None:
+ output_con_scaling = np.ones(self._ex_model.n_outputs())
+
+ return np.concatenate((
+ eq_scaling,
+ output_con_scaling))
+
+ def evaluate_residuals(self):
+ # evalute the equality constraints and the output equations
+ # and return a single vector of residuals
+ # returns residual for h(x)=0, where h(x) = [h_eq(x); h_o(x)-o]
+ resid_list = []
+ if self._ex_model.n_equality_constraints() > 0:
+ resid_list.append(self._ex_model.evaluate_equality_constraints())
+
+ if self._ex_model.n_outputs() > 0:
+ computed_output_values = self._ex_model.evaluate_outputs()
+ output_resid = computed_output_values - self._output_values
+ resid_list.append(output_resid)
+
+ return np.concatenate(resid_list)
+
+ def evaluate_jacobian(self):
+ # compute the jacobian of h(x) w.r.t. x
+ # J_h(x) = [Jw_eq(Pu*x); Jw_o(Pu*x)-Po*x]
+
+ # Jw_eq(x)
+ eq_jac = None
+ if self._ex_model.n_equality_constraints() > 0:
+ eq_jac = self._ex_model.evaluate_jacobian_equality_constraints()
+ # map the columns from the inputs "u" back to the full primals "x"
+ eq_jac = coo_matrix(
+ (eq_jac.data, (eq_jac.row, self._eq_jac_primal_jcol)),
+ (eq_jac.shape[0], self._n_primals))
+
+ outputs_jac = None
+ if self._ex_model.n_outputs() > 0:
+ outputs_jac = self._ex_model.evaluate_jacobian_outputs()
+
+ row = outputs_jac.row
+ # map the columns from the inputs "u" back to the full primals "x"
+ col = self._outputs_jac_primal_jcol
+ data = outputs_jac.data
+
+ # add the additional entries for the -Po*x portion of the jacobian
+ row = np.concatenate((row, self._additional_output_entries_irow))
+ col = np.concatenate((col, self._additional_output_entries_jcol))
+ data = np.concatenate((data, self._additional_output_entries_data))
+ outputs_jac = coo_matrix(
+ (data, (row, col)),
+ shape=(outputs_jac.shape[0], self._n_primals))
+
+ jac = None
+ if eq_jac is not None:
+ if outputs_jac is not None:
+ # create a jacobian with both Jw_eq and Jw_o
+ jac = BlockMatrix(2,1)
+ jac.name = 'external model jacobian'
+ jac.set_block(0,0,eq_jac)
+ jac.set_block(1,0,outputs_jac)
+ else:
+ assert self._ex_model.n_outputs() == 0
+ assert self._ex_model.n_equality_constraints() > 0
+ # only need the Jacobian with Jw_eq (there are not
+ # output equations)
+ jac = eq_jac
+ else:
+ assert outputs_jac is not None
+ assert self._ex_model.n_outputs() > 0
+ assert self._ex_model.n_equality_constraints() == 0
+ # only need the Jacobian with Jw_o (there are no equalities)
+ jac = outputs_jac
+
+ return jac
diff --git a/pyomo/contrib/pynumero/interfaces/pyomo_nlp.py b/pyomo/contrib/pynumero/interfaces/pyomo_nlp.py
index 5a4b0b4c8e9..09283e3f0a3 100644
--- a/pyomo/contrib/pynumero/interfaces/pyomo_nlp.py
+++ b/pyomo/contrib/pynumero/interfaces/pyomo_nlp.py
@@ -18,12 +18,15 @@
from scipy.sparse import coo_matrix
-import pyutilib
-import pyomo
-import pyomo.environ as aml
+from pyutilib.services import TempfileManager
+from pyomo.opt import WriterFactory
+import pyomo.core.base as pyo
from pyomo.common.collections import ComponentMap
from pyomo.common.env import CtypesEnviron
+from ..sparse.block_matrix import BlockMatrix
from pyomo.contrib.pynumero.interfaces.ampl_nlp import AslNLP
+from pyomo.contrib.pynumero.interfaces.nlp import NLP
+from .external_grey_box import ExternalGreyBoxBlock, _ExternalGreyBoxModelHelper
__all__ = ['PyomoNLP']
@@ -39,27 +42,36 @@ def __init__(self, pyomo_model):
pyomo_model: pyomo.environ.ConcreteModel
Pyomo concrete model
"""
- pyutilib.services.TempfileManager.push()
+ TempfileManager.push()
try:
# get the temp file names for the nl file
- nl_file = pyutilib.services.TempfileManager.create_tempfile(suffix='pynumero.nl')
-
- # The current AmplInterface code only supports a single objective function
- # Therefore, we throw an error if there is not one (and only one) active
- # objective function. This is better than adding a dummy objective that the
- # user does not know about (since we do nnot have a good place to remove
- # this objective later
- # TODO: extend the AmplInterface and the AslNLP to correctly handle this
+ nl_file = TempfileManager.create_tempfile(
+ suffix='pynumero.nl')
+
+ # The current AmplInterface code only supports a single
+ # objective function Therefore, we throw an error if there
+ # is not one (and only one) active objective function. This
+ # is better than adding a dummy objective that the user does
+ # not know about (since we do not have a good place to
+ # remove this objective later)
+ #
+ # TODO: extend the AmplInterface and the AslNLP to correctly
+ # handle this
+ #
# This currently addresses issue #1217
- objectives = list(pyomo_model.component_data_objects(ctype=aml.Objective, active=True, descend_into=True))
+ objectives = list(pyomo_model.component_data_objects(
+ ctype=pyo.Objective, active=True, descend_into=True))
if len(objectives) != 1:
- raise NotImplementedError('The ASL interface and PyomoNLP in PyNumero currently only support single objective'
- ' problems. Deactivate any extra objectives you may have, or add a dummy objective'
- ' (f(x)=0) if you have a square problem.')
+ raise NotImplementedError(
+ 'The ASL interface and PyomoNLP in PyNumero currently '
+ 'only support single objective problems. Deactivate '
+ 'any extra objectives you may have, or add a dummy '
+ 'objective (f(x)=0) if you have a square problem.')
self._objective = objectives[0]
# write the nl file for the Pyomo model and get the symbolMap
- fname, symbolMap = pyomo.opt.WriterFactory('nl')(pyomo_model, nl_file, lambda x:True, {})
+ fname, symbolMap = WriterFactory('nl')(
+ pyomo_model, nl_file, lambda x:True, {})
# create component maps from vardata to idx and condata to idx
self._vardata_to_idx = vdidx = ComponentMap()
@@ -88,7 +100,8 @@ def __init__(self, pyomo_model):
finally:
# delete the nl file
- pyutilib.services.TempfileManager.pop()
+ TempfileManager.pop()
+
def pyomo_model(self):
"""
@@ -127,7 +140,7 @@ def variable_names(self):
names in the order corresponding to the primals
"""
pyomo_variables = self.get_pyomo_variables()
- return [v.getname() for v in pyomo_variables]
+ return [v.getname(fully_qualified=True) for v in pyomo_variables]
def constraint_names(self):
"""
@@ -135,7 +148,7 @@ def constraint_names(self):
names in the order corresponding to internal constraint order
"""
pyomo_constraints = self.get_pyomo_constraints()
- return [v.getname() for v in pyomo_constraints]
+ return [v.getname(fully_qualified=True) for v in pyomo_constraints]
def get_primal_indices(self, pyomo_variables):
"""
@@ -183,15 +196,16 @@ def get_constraint_indices(self, pyomo_constraints):
def get_obj_scaling(self):
obj = self.get_pyomo_objective()
scaling_suffix = self._pyomo_model.component('scaling_factor')
- if scaling_suffix and scaling_suffix.ctype is aml.Suffix and \
- obj in scaling_suffix:
- return scaling_suffix[obj]
+ if scaling_suffix and scaling_suffix.ctype is pyo.Suffix:
+ if obj in scaling_suffix:
+ return scaling_suffix[obj]
+ return 1.0
return None
# overloaded from NLP
def get_primals_scaling(self):
scaling_suffix = self._pyomo_model.component('scaling_factor')
- if scaling_suffix and scaling_suffix.ctype is aml.Suffix:
+ if scaling_suffix and scaling_suffix.ctype is pyo.Suffix:
primals_scaling = np.ones(self.n_primals())
for i,v in enumerate(self.get_pyomo_variables()):
if v in scaling_suffix:
@@ -202,7 +216,7 @@ def get_primals_scaling(self):
# overloaded from NLP
def get_constraints_scaling(self):
scaling_suffix = self._pyomo_model.component('scaling_factor')
- if scaling_suffix and scaling_suffix.ctype is aml.Suffix:
+ if scaling_suffix and scaling_suffix.ctype is pyo.Suffix:
constraints_scaling = np.ones(self.n_constraints())
for i,c in enumerate(self.get_pyomo_constraints()):
if c in scaling_suffix:
@@ -296,3 +310,620 @@ def extract_submatrix_hessian_lag(self, pyomo_variables_rows, pyomo_variables_co
submatrix_jcols[i] = submatrix_map[v]
return coo_matrix((submatrix_data, (submatrix_irows, submatrix_jcols)), shape=(len(primal_indices_rows), len(primal_indices_cols)))
+
+ def load_state_into_pyomo(self, bound_multipliers=None):
+ primals = self.get_primals()
+ variables = self.get_pyomo_variables()
+ for var, val in zip(variables, primals):
+ var.set_value(val)
+ m = self.pyomo_model()
+ model_suffixes = dict(
+ pyo.suffix.active_import_suffix_generator(m))
+ if 'dual' in model_suffixes:
+ duals = self.get_duals()
+ constraints = self.get_pyomo_constraints()
+ model_suffixes['dual'].clear()
+ model_suffixes['dual'].update(
+ zip(constraints, duals))
+ if 'ipopt_zL_out' in model_suffixes:
+ model_suffixes['ipopt_zL_out'].clear()
+ if bound_multipliers is not None:
+ model_suffixes['ipopt_zL_out'].update(
+ zip(variables, bound_multipliers[0]))
+ if 'ipopt_zU_out' in model_suffixes:
+ model_suffixes['ipopt_zU_out'].clear()
+ if bound_multipliers is not None:
+ model_suffixes['ipopt_zU_out'].update(
+ zip(variables, bound_multipliers[1]))
+
+
+class PyomoGreyBoxNLP(NLP):
+ def __init__(self, pyomo_model):
+ # store all the greybox custom block data objects
+ greybox_components = []
+ try:
+ # We support Pynumero's ExternalGreyBoxBlock modeling
+ # objects. We need to find them and convert them to Blocks
+ # before calling the NL writer so that the attached Vars get
+ # picked up by the writer.
+ for greybox in pyomo_model.component_objects(
+ ExternalGreyBoxBlock, descend_into=True):
+ greybox.parent_block().reclassify_component_type(
+ greybox, pyo.Block)
+ greybox_components.append(greybox)
+
+ self._pyomo_model = pyomo_model
+ self._pyomo_nlp = PyomoNLP(pyomo_model)
+
+ finally:
+ # Restore the ctypes of the ExternalGreyBoxBlock components
+ for greybox in greybox_components:
+ greybox.parent_block().reclassify_component_type(
+ greybox, ExternalGreyBoxBlock)
+
+ # get the greybox block data objects
+ greybox_data = []
+ for greybox in greybox_components:
+ greybox_data.extend(data for data in greybox.values()
+ if data.active)
+
+ if len(greybox_data) > 1:
+ raise NotImplementedError("The PyomoGreyBoxModel interface has not"
+ " been tested with Pyomo models that contain"
+ " more than one ExternalGreyBoxBlock. Currently,"
+ " only a single block is supported.")
+
+ if self._pyomo_nlp.n_primals() == 0:
+ raise ValueError(
+ "No variables were found in the Pyomo part of the model."
+ " PyomoGreyBoxModel requires at least one variable"
+ " to be active in a Pyomo objective or constraint")
+
+ # number of additional variables required - they are in the
+ # greybox models but not included in the NL file
+ self._n_greybox_primals = 0
+
+ # number of residuals (equality constraints + output constraints
+ # coming from the grey box models
+ self._greybox_primals_names = []
+ self._greybox_constraints_names = []
+
+ # Update the primal index map with any variables in the
+ # greybox models that do not otherwise appear in the NL
+ # and capture some other book keeping items
+ n_primals = self._pyomo_nlp.n_primals()
+ greybox_primals = []
+ self._vardata_to_idx = ComponentMap(self._pyomo_nlp._vardata_to_idx)
+ for data in greybox_data:
+ # check that none of the inputs / outputs are fixed
+ for v in six.itervalues(data.inputs):
+ if v.fixed:
+ raise NotImplementedError('Found a grey box model input that is fixed: {}.'
+ ' This interface does not currently support fixed'
+ ' variables. Please add a constraint instead.'
+ ''.format(v.getname(fully_qualified=True)))
+ for v in six.itervalues(data.outputs):
+ if v.fixed:
+ raise NotImplementedError('Found a grey box model output that is fixed: {}.'
+ ' This interface does not currently support fixed'
+ ' variables. Please add a constraint instead.'
+ ''.format(v.getname(fully_qualified=True)))
+
+ block_name = data.getname()
+ for nm in data._ex_model.equality_constraint_names():
+ self._greybox_constraints_names.append('{}.{}'.format(block_name, nm))
+ for nm in data._ex_model.output_names():
+ self._greybox_constraints_names.append('{}.{}_con'.format(block_name, nm))
+
+ for var in data.component_data_objects(pyo.Var):
+ if var not in self._vardata_to_idx:
+ # there is a variable in the greybox block that
+ # is not in the NL - append this to the end
+ self._vardata_to_idx[var] = n_primals
+ n_primals += 1
+ greybox_primals.append(var)
+ self._greybox_primals_names.append(var.getname(fully_qualified=True))
+ self._n_greybox_primals = len(greybox_primals)
+ self._greybox_primal_variables = greybox_primals
+
+ # Configure the primal and dual data caches
+ self._greybox_primals_lb = np.zeros(self._n_greybox_primals)
+ self._greybox_primals_ub = np.zeros(self._n_greybox_primals)
+ self._init_greybox_primals = np.zeros(self._n_greybox_primals)
+ for i, var in enumerate(greybox_primals):
+ if var.value is not None:
+ self._init_greybox_primals[i] = var.value
+ self._greybox_primals_lb[i] = -np.inf if var.lb is None else var.lb
+ self._greybox_primals_ub[i] = np.inf if var.ub is None else var.ub
+ self._greybox_primals_lb.flags.writeable = False
+ self._greybox_primals_ub.flags.writeable = False
+
+ self._greybox_primals = self._init_greybox_primals.copy()
+
+ # data member to store the cached greybox constraints and jacobian
+ self._cached_greybox_constraints = None
+ self._cached_greybox_jac = None
+
+ # Now that we know the total number of columns, create the
+ # necessary greybox helper objects
+ self._external_greybox_helpers = \
+ [_ExternalGreyBoxModelHelper(data, self._vardata_to_idx, self.init_primals()) for data in greybox_data]
+
+ # make sure the primal values get to the greybox models
+ self.set_primals(self.get_primals())
+
+ self._n_greybox_constraints = 0
+ for h in self._external_greybox_helpers:
+ self._n_greybox_constraints += h.n_residuals()
+ assert len(self._greybox_constraints_names) == self._n_greybox_constraints
+
+ # If any part of the problem is scaled (i.e., obj, primals,
+ # or any of the constraints for any of the external grey boxes),
+ # then we want scaling factors for everything (defaulting to
+ # ones for any of the missing factors).
+ # This code builds all the scaling factors, with the defaults,
+ # but then sets them all to None if *no* scaling factors are provided
+ # for any of the pieces. (inefficient, but only done once)
+ need_scaling = False
+ self._obj_scaling = self._pyomo_nlp.get_obj_scaling()
+ if self._obj_scaling is None:
+ self._obj_scaling = 1.0
+ else:
+ need_scaling = True
+
+ self._primals_scaling = np.ones(self.n_primals())
+ scaling_suffix = self._pyomo_nlp._pyomo_model.component('scaling_factor')
+ if scaling_suffix and scaling_suffix.ctype is pyo.Suffix:
+ need_scaling = True
+ for i,v in enumerate(self.get_pyomo_variables()):
+ if v in scaling_suffix:
+ self._primals_scaling[i] = scaling_suffix[v]
+
+ self._constraints_scaling = []
+ pyomo_nlp_scaling = self._pyomo_nlp.get_constraints_scaling()
+ if pyomo_nlp_scaling is None:
+ pyomo_nlp_scaling = np.ones(self._pyomo_nlp.n_constraints())
+ else:
+ need_scaling = True
+ self._constraints_scaling.append(pyomo_nlp_scaling)
+
+ for h in self._external_greybox_helpers:
+ tmp_scaling = h.get_residual_scaling()
+ if tmp_scaling is None:
+ tmp_scaling = np.ones(h.n_residuals())
+ else:
+ need_scaling = True
+ self._constraints_scaling.append(tmp_scaling)
+
+ if need_scaling:
+ self._constraints_scaling = np.concatenate(self._constraints_scaling)
+ else:
+ self._obj_scaling = None
+ self._primals_scaling = None
+ self._constraints_scaling = None
+
+ # might want the user to be able to specify these at some point
+ self._init_greybox_duals = np.ones(self._n_greybox_constraints)
+ self._init_greybox_primals.flags.writeable = False
+ self._init_greybox_duals.flags.writeable = False
+ self._greybox_duals = self._init_greybox_duals.copy()
+
+ # compute the jacobian for the external greybox models
+ # to get some of the statistics
+ self._evaluate_greybox_jacobians_and_cache_if_necessary()
+ self._nnz_greybox_jac = len(self._cached_greybox_jac.data)
+
+ def _invalidate_greybox_primals_cache(self):
+ self._greybox_constraints_cached = False
+ self._greybox_jac_cached = False
+
+ # overloaded from NLP
+ def n_primals(self):
+ return self._pyomo_nlp.n_primals() + self._n_greybox_primals
+
+ # overloaded from NLP
+ def n_constraints(self):
+ return self._pyomo_nlp.n_constraints() + self._n_greybox_constraints
+
+ # overloaded from ExtendedNLP
+ def n_eq_constraints(self):
+ return self._pyomo_nlp.n_eq_constraints() + self._n_greybox_constraints
+
+ # overloaded from ExtendedNLP
+ def n_ineq_constraints(self):
+ return self._pyomo_nlp.n_ineq_constraints()
+
+ # overloaded from NLP
+ def nnz_jacobian(self):
+ return self._pyomo_nlp.nnz_jacobian() + self._nnz_greybox_jac
+
+ # overloaded from AslNLP
+ def nnz_jacobian_eq(self):
+ return self._pyomo_nlp.nnz_jacobian_eq() + self._nnz_greybox_jac
+
+ # overloaded from NLP
+ def nnz_hessian_lag(self):
+ raise NotImplementedError(
+ "PyomoGreyBoxNLP does not currently support Hessians")
+
+ # overloaded from NLP
+ def primals_lb(self):
+ return np.concatenate((self._pyomo_nlp.primals_lb(),
+ self._greybox_primals_lb,
+ ))
+
+ # overloaded from NLP
+ def primals_ub(self):
+ return np.concatenate((
+ self._pyomo_nlp.primals_ub(),
+ self._greybox_primals_ub,
+ ))
+
+ # overloaded from NLP
+ def constraints_lb(self):
+ return np.concatenate((
+ self._pyomo_nlp.constraints_lb(),
+ np.zeros(self._n_greybox_constraints, dtype=np.float64),
+ ))
+
+ # overloaded from NLP
+ def constraints_ub(self):
+ return np.concatenate((
+ self._pyomo_nlp.constraints_ub(),
+ np.zeros(self._n_greybox_constraints, dtype=np.float64),
+ ))
+
+ # overloaded from NLP
+ def init_primals(self):
+ return np.concatenate((
+ self._pyomo_nlp.init_primals(),
+ self._init_greybox_primals,
+ ))
+
+ # overloaded from NLP
+ def init_duals(self):
+ return np.concatenate((
+ self._pyomo_nlp.init_duals(),
+ self._init_greybox_duals,
+ ))
+
+ # overloaded from ExtendedNLP
+ def init_duals_eq(self):
+ return np.concatenate((
+ self._pyomo_nlp.init_duals_eq(),
+ self._init_greybox_duals,
+ ))
+
+ # overloaded from NLP / Extended NLP
+ def create_new_vector(self, vector_type):
+ if vector_type == 'primals':
+ return np.zeros(self.n_primals(), dtype=np.float64)
+ elif vector_type == 'constraints' or vector_type == 'duals':
+ return np.zeros(self.n_constraints(), dtype=np.float64)
+ elif vector_type == 'eq_constraints' or vector_type == 'duals_eq':
+ return np.zeros(self.n_eq_constraints(), dtype=np.float64)
+ elif vector_type == 'ineq_constraints' or vector_type == 'duals_ineq':
+ return np.zeros(self.n_ineq_constraints(), dtype=np.float64)
+ else:
+ raise RuntimeError('Called create_new_vector with an unknown vector_type')
+
+ # overloaded from NLP
+ def set_primals(self, primals):
+ self._invalidate_greybox_primals_cache()
+
+ # set the primals on the "pyomo" part of the nlp
+ self._pyomo_nlp.set_primals(
+ primals[:self._pyomo_nlp.n_primals()])
+
+ # copy the values for the greybox primals
+ np.copyto(self._greybox_primals, primals[self._pyomo_nlp.n_primals():])
+
+ for external in self._external_greybox_helpers:
+ external.set_primals(primals)
+
+ # overloaded from AslNLP
+ def get_primals(self):
+ # return the value of the primals that the pyomo
+ # part knows about as well as any extra values that
+ # are only in the greybox part
+ return np.concatenate((
+ self._pyomo_nlp.get_primals(),
+ self._greybox_primals,
+ ))
+
+ # overloaded from NLP
+ def set_duals(self, duals):
+ #self._invalidate_greybox_duals_cache()
+
+ # set the duals for the pyomo part of the nlp
+ self._pyomo_nlp.set_duals(
+ duals[:-self._n_greybox_constraints])
+
+ # set the duals for the greybox part of the nlp
+ np.copyto(self._greybox_duals, duals[-self._n_greybox_constraints:])
+
+ # overloaded from NLP
+ def get_duals(self):
+ # return the duals for the pyomo part of the nlp
+ # concatenated with the greybox part
+ return np.concatenate((
+ self._pyomo_nlp.get_duals(),
+ self._greybox_duals,
+ ))
+
+ # overloaded from ExtendedNLP
+ def set_duals_eq(self, duals):
+ #self._invalidate_greybox_duals_cache()
+
+ # set the duals for the pyomo part of the nlp
+ self._pyomo_nlp.set_duals_eq(
+ duals[:-self._n_greybox_constraints])
+
+ # set the duals for the greybox part of the nlp
+ np.copyto(self._greybox_duals, duals[-self._n_greybox_constraints:])
+
+ # overloaded from NLP
+ def get_duals_eq(self):
+ # return the duals for the pyomo part of the nlp
+ # concatenated with the greybox part
+ return np.concatenate((
+ self._pyomo_nlp.get_duals_eq(),
+ self._greybox_duals,
+ ))
+
+ # overloaded from NLP
+ def set_obj_factor(self, obj_factor):
+ # objective is owned by the pyomo model
+ self._pyomo_nlp.set_obj_factor(obj_factor)
+
+ # overloaded from NLP
+ def get_obj_factor(self):
+ # objective is owned by the pyomo model
+ return self._pyomo_nlp.get_obj_factor()
+
+ # overloaded from NLP
+ def get_obj_scaling(self):
+ return self._obj_scaling
+
+ # overloaded from NLP
+ def get_primals_scaling(self):
+ return self._primals_scaling
+
+ # overloaded from NLP
+ def get_constraints_scaling(self):
+ return self._constraints_scaling
+
+ # overloaded from NLP
+ def evaluate_objective(self):
+ # objective is owned by the pyomo model
+ return self._pyomo_nlp.evaluate_objective()
+
+ # overloaded from NLP
+ def evaluate_grad_objective(self, out=None):
+ # objective is owned by the pyomo model
+ return np.concatenate((
+ self._pyomo_nlp.evaluate_grad_objective(out),
+ np.zeros(self._n_greybox_primals)))
+
+ def _evaluate_greybox_constraints_and_cache_if_necessary(self):
+ if self._greybox_constraints_cached:
+ return
+
+ self._cached_greybox_constraints = np.concatenate(tuple(
+ external.evaluate_residuals()
+ for external in self._external_greybox_helpers))
+ self._greybox_constraints_cached = True
+
+ # overloaded from NLP
+ def evaluate_constraints(self, out=None):
+ self._evaluate_greybox_constraints_and_cache_if_necessary()
+
+ if out is not None:
+ if not isinstance(out, np.ndarray) \
+ or out.size != self.n_constraints():
+ raise RuntimeError(
+ 'Called evaluate_constraints with an invalid'
+ ' "out" argument - should take an ndarray of '
+ 'size {}'.format(self.n_constraints()))
+
+ # call on the pyomo part of the nlp
+ self._pyomo_nlp.evaluate_constraints(
+ out[:-self._n_greybox_constraints])
+
+ # call on the greybox part of the nlp
+ np.copyto(out[-self._n_greybox_constraints:],
+ self._cached_greybox_constraints)
+ return out
+
+ else:
+ # concatenate the pyomo and external constraint residuals
+ return np.concatenate((
+ self._pyomo_nlp.evaluate_constraints(),
+ self._cached_greybox_constraints,
+ ))
+
+ # overloaded from ExtendedNLP
+ def evaluate_eq_constraints(self, out=None):
+ self._evaluate_greybox_constraints_and_cache_if_necessary()
+
+ if out is not None:
+ if not isinstance(out, np.ndarray) \
+ or out.size != self.n_eq_constraints():
+ raise RuntimeError(
+ 'Called evaluate_eq_constraints with an invalid'
+ ' "out" argument - should take an ndarray of '
+ 'size {}'.format(self.n_eq_constraints()))
+ self._pyomo_nlp.evaluate_eq_constraints(
+ out[:-self._n_greybox_constraints])
+ np.copyto(out[-self._n_greybox_constraints:], self._cached_greybox_constraints)
+ return out
+ else:
+ return np.concatenate((
+ self._pyomo_nlp.evaluate_eq_constraints(),
+ self._cached_greybox_constraints,
+ ))
+
+ def _evaluate_greybox_jacobians_and_cache_if_necessary(self):
+ if self._greybox_jac_cached:
+ return
+
+ jac = BlockMatrix(len(self._external_greybox_helpers), 1)
+ for i, external in enumerate(self._external_greybox_helpers):
+ jac.set_block(i, 0, external.evaluate_jacobian())
+ self._cached_greybox_jac = jac.tocoo()
+ self._greybox_jac_cached = True
+
+ # overloaded from NLP
+ def evaluate_jacobian(self, out=None):
+ self._evaluate_greybox_jacobians_and_cache_if_necessary()
+
+ if out is not None:
+ if ( not isinstance(out, coo_matrix)
+ or out.shape[0] != self.n_constraints()
+ or out.shape[1] != self.n_primals()
+ or out.nnz != self.nnz_jacobian() ):
+ raise RuntimeError(
+ 'evaluate_jacobian called with an "out" argument'
+ ' that is invalid. This should be a coo_matrix with'
+ ' shape=({},{}) and nnz={}'
+ .format(self.n_constraints(), self.n_primals(),
+ self.nnz_jacobian()))
+ n_pyomo_constraints = self.n_constraints() - self._n_greybox_constraints
+ self._pyomo_nlp.evaluate_jacobian(
+ out=coo_matrix((out.data[:-self._nnz_greybox_jac],
+ (out.row[:-self._nnz_greybox_jac],
+ out.col[:-self._nnz_greybox_jac])),
+ shape=(n_pyomo_constraints, self._pyomo_nlp.n_primals())))
+ np.copyto(out.data[-self._nnz_greybox_jac:],
+ self._cached_greybox_jac.data)
+ return out
+ else:
+ base = self._pyomo_nlp.evaluate_jacobian()
+ base = coo_matrix((base.data, (base.row, base.col)),
+ shape=(base.shape[0], self.n_primals()))
+
+ jac = BlockMatrix(2,1)
+ jac.set_block(0, 0, base)
+ jac.set_block(1, 0, self._cached_greybox_jac)
+ return jac.tocoo()
+
+ # TODO: Doesn't this need a "shape" specification?
+ #return coo_matrix((
+ # np.concatenate((base.data, self._cached_greybox_jac.data)),
+ # ( np.concatenate((base.row, self._cached_greybox_jac.row)),
+ # np.concatenate((base.col, self._cached_greybox_jac.col)) )
+ #))
+
+ # overloaded from ExtendedNLP
+ """
+ def evaluate_jacobian_eq(self, out=None):
+ raise NotImplementedError()
+ self._evaluate_greybox_jacobians_and_cache_if_necessary()
+
+ if out is not None:
+ if ( not isinstance(out, coo_matrix)
+ or out.shape[0] != self.n_eq_constraints()
+ or out.shape[1] != self.n_primals()
+ or out.nnz != self.nnz_jacobian_eq() ):
+ raise RuntimeError(
+ 'evaluate_jacobian called with an "out" argument'
+ ' that is invalid. This should be a coo_matrix with'
+ ' shape=({},{}) and nnz={}'
+ .format(self.n_eq_constraints(), self.n_primals(),
+ self.nnz_jacobian_eq()))
+ self._pyomo_nlp.evaluate_jacobian_eq(
+ coo_matrix((out.data[:-self._nnz_greybox_jac],
+ (out.row[:-self._nnz_greybox_jac],
+ out.col[:-self._nnz_greybox_jac])))
+ )
+ np.copyto(out.data[-self._nnz_greybox_jac],
+ self._cached_greybox_jac.data)
+ return out
+ else:
+ base = self._pyomo_nlp.evaluate_jacobian_eq()
+ # TODO: Doesn't this need a "shape" specification?
+ return coo_matrix((
+ np.concatenate((base.data, self._cached_greybox_jac.data)),
+ ( np.concatenate((base.row, self._cached_greybox_jac.row)),
+ np.concatenate((base.col, self._cached_greybox_jac.col)) )
+ ))
+ """
+ # overloaded from NLP
+ def evaluate_hessian_lag(self, out=None):
+ # return coo_matrix(([], ([],[])), shape=(self.n_primals(), self.n_primals()))
+ raise NotImplementedError(
+ "PyomoGreyBoxNLP does not currently support Hessians")
+
+ # overloaded from NLP
+ def report_solver_status(self, status_code, status_message):
+ raise NotImplementedError('Todo: implement this')
+
+ def variable_names(self):
+ names = list(self._pyomo_nlp.variable_names())
+ names.extend(self._greybox_primals_names)
+ return names
+
+ def constraint_names(self):
+ names = list(self._pyomo_nlp.constraint_names())
+ names.extend(self._greybox_constraints_names)
+ return names
+
+ def pyomo_model(self):
+ """
+ Return optimization model
+ """
+ return self._pyomo_model
+
+ def get_pyomo_objective(self):
+ """
+ Return an instance of the active objective function on the Pyomo model.
+ (there can be only one)
+ """
+ return self._pyomo_nlp.get_pyomo_objective()
+
+ def get_pyomo_variables(self):
+ """
+ Return an ordered list of the Pyomo VarData objects in
+ the order corresponding to the primals
+ """
+ return self._pyomo_nlp.get_pyomo_variables() + \
+ self._greybox_primal_variables
+
+ def get_pyomo_constraints(self):
+ """
+ Return an ordered list of the Pyomo ConData objects in
+ the order corresponding to the primals
+ """
+ # FIXME: what do we return for the external block constraints?
+ # return self._pyomo_nlp.get_pyomo_constraints()
+ raise NotImplementedError(
+ "returning list of all constraints when using an external "
+ "model is TBD")
+
+ def load_state_into_pyomo(self, bound_multipliers=None):
+ primals = self.get_primals()
+ variables = self.get_pyomo_variables()
+ for var, val in zip(variables, primals):
+ var.set_value(val)
+ m = self.pyomo_model()
+ model_suffixes = dict(
+ pyo.suffix.active_import_suffix_generator(m))
+ if 'dual' in model_suffixes:
+ model_suffixes['dual'].clear()
+ # Until we sort out how to return the duals for the external
+ # block (implied) constraints, I am disabling *all* duals
+ #
+ # duals = self.get_duals()
+ # constraints = self.get_pyomo_constraints()
+ # model_suffixes['dual'].update(
+ # zip(constraints, duals))
+ if 'ipopt_zL_out' in model_suffixes:
+ model_suffixes['ipopt_zL_out'].clear()
+ if bound_multipliers is not None:
+ model_suffixes['ipopt_zL_out'].update(
+ zip(variables, bound_multipliers[0]))
+ if 'ipopt_zU_out' in model_suffixes:
+ model_suffixes['ipopt_zU_out'].clear()
+ if bound_multipliers is not None:
+ model_suffixes['ipopt_zU_out'].update(
+ zip(variables, bound_multipliers[1]))
diff --git a/pyomo/contrib/pynumero/interfaces/tests/test_external.py b/pyomo/contrib/pynumero/interfaces/tests/test_external_asl_function.py
similarity index 93%
rename from pyomo/contrib/pynumero/interfaces/tests/test_external.py
rename to pyomo/contrib/pynumero/interfaces/tests/test_external_asl_function.py
index 949a0458ca6..5d5d0bf8508 100644
--- a/pyomo/contrib/pynumero/interfaces/tests/test_external.py
+++ b/pyomo/contrib/pynumero/interfaces/tests/test_external_asl_function.py
@@ -20,9 +20,7 @@
"Pynumero needs the ASL extension to run NLP tests")
from pyomo.contrib.pynumero.interfaces.pyomo_nlp import PyomoNLP
from pyomo.common.getGSL import find_GSL
-from pyomo.environ import *
-from pyomo.core.base.external import (PythonCallbackFunction,
- AMPLExternalFunction)
+from pyomo.environ import ConcreteModel, ExternalFunction, Var, Objective
class TestAMPLExternalFunction(unittest.TestCase):
def assertListsAlmostEqual(self, first, second, places=7, msg=None):
diff --git a/pyomo/contrib/pynumero/interfaces/tests/test_external_grey_box_model.py b/pyomo/contrib/pynumero/interfaces/tests/test_external_grey_box_model.py
new file mode 100644
index 00000000000..75b0bcef1aa
--- /dev/null
+++ b/pyomo/contrib/pynumero/interfaces/tests/test_external_grey_box_model.py
@@ -0,0 +1,1494 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+import os
+import pyutilib.th as unittest
+import pyomo.environ as pyo
+
+from pyomo.contrib.pynumero.dependencies import (
+ numpy as np, numpy_available, scipy_sparse as spa, scipy_available
+)
+if not (numpy_available and scipy_available):
+ raise unittest.SkipTest("Pynumero needs scipy and numpy to run NLP tests")
+
+from pyomo.contrib.pynumero.asl import AmplInterface
+if not AmplInterface.available():
+ raise unittest.SkipTest(
+ "Pynumero needs the ASL extension to run CyIpoptSolver tests")
+
+from pyomo.contrib.pynumero.algorithms.solvers.cyipopt_solver import (
+ CyIpoptSolver, CyIpoptNLP, ipopt, ipopt_available,
+)
+
+from ..external_grey_box import ExternalGreyBoxModel, ExternalGreyBoxBlock, _ExternalGreyBoxModelHelper
+from ..pyomo_nlp import PyomoGreyBoxNLP
+
+# set of external models for testing
+# basic model is a simple pipe sequence with nonlinear pressure drop
+# Pin -> P1 -> P2 -> P3 -> Pout
+#
+# We will assume that we have an external model to compute
+# the pressure drop in this sequence of pipes, where the dP
+# is given by c*F^2
+#
+# There are several ways to format this.
+# Model 1: Use the "external model" to compute the output pressure
+# no equalities, 1 output
+# u = [Pin, c, F]
+# o = [Pout]
+# h_eq(u) = {empty}
+# h_o(u) = [Pin - 4*c*F^2]
+#
+# Model 2: Same as model 1, but treat Pout as an input to be converged by the optimizer
+# 1 equality, no outputs
+# u = [Pin, c, F, Pout]
+# o = {empty}
+# h_eq(u) = [Pout - (Pin - 4*c*F^2]
+# h_o(u) = {empty}
+#
+# Model 3: Use the "external model" to compute the output pressure and the pressure
+# at node 2 (e.g., maybe we have a measurement there we want to match)
+# no equalities, 2 outputs
+# u = [Pin, c, F]
+# o = [P2, Pout]
+# h_eq(u) = {empty}
+# h_o(u) = [Pin - 2*c*F^2]
+# [Pin - 4*c*F^2]
+#
+# Model 4: Same as model 2, but treat P2, and Pout as an input to be converged by the optimizer
+# 2 equality, no outputs
+# u = [Pin, c, F, P2, Pout]
+# o = {empty}
+# h_eq(u) = [P2 - (Pin - 2*c*F^2]
+# [Pout - (P2 - 2*c*F^2]
+# h_o(u) = {empty}
+
+# Model 4: Same as model 2, but treat P2 as an input to be converged by the solver
+# u = [Pin, c, F, P2]
+# o = [Pout]
+# h_eq(u) = P2 - (Pin-2*c*F^2)]
+# h_o(u) = [Pin - 4*c*F^2] (or could also be [P2 - 2*c*F^2])
+#
+# Model 5: treat all "internal" variables as "inputs", equality and output equations
+# u = [Pin, c, F, P1, P2, P3]
+# o = [Pout]
+# h_eq(u) = [
+# P1 - (Pin - c*F^2);
+# P2 - (P1 - c*F^2);
+# P3 - (P2 - c*F^2);
+# ]
+# h_o(u) = [P3 - c*F^2] (or could also be [Pin - 4*c*F^2] or [P1 - 3*c*F^2] or [P2 - 2*c*F^2])
+#
+# Model 6: treat all variables as "inputs", equality only, and no output equations
+# u = [Pin, c, F, P1, P2, P3, Pout]
+# o = {empty}
+# h_eq(u) = [
+# P1 - (Pin - c*F^2);
+# P2 - (P1 - c*F^2);
+# P3 - (P2 - c*F^2);
+# Pout = (P3 - c*F^2);
+# ]
+# h_o(u) = {empty}
+#
+class PressureDropSingleOutput(ExternalGreyBoxModel):
+ def __init__(self):
+ self._input_names = ['Pin', 'c', 'F']
+ self._input_values = np.zeros(3, dtype=np.float64)
+ self._output_names = ['Pout']
+
+ def input_names(self):
+ return self._input_names
+
+ def equality_constraint_names(self):
+ return []
+
+ def output_names(self):
+ return self._output_names
+
+ def set_input_values(self, input_values):
+ assert len(input_values) == 3
+ np.copyto(self._input_values, input_values)
+
+ def evaluate_equality_constraints(self):
+ raise NotImplementedError('This method should not be called for this model.')
+
+ def evaluate_outputs(self):
+ Pin = self._input_values[0]
+ c = self._input_values[1]
+ F = self._input_values[2]
+ Pout = Pin - 4*c*F**2
+ return np.asarray([Pout], dtype=np.float64)
+
+ def evaluate_jacobian_equality_constraints(self):
+ raise NotImplementedError('This method should not be called for this model.')
+
+ def evaluate_jacobian_outputs(self):
+ c = self._input_values[1]
+ F = self._input_values[2]
+ irow = np.asarray([0, 0, 0], dtype=np.int64)
+ jcol = np.asarray([0, 1, 2], dtype=np.int64)
+ nonzeros = np.asarray([1, -4*F**2, -4*c*2*F], dtype=np.float64)
+ jac = spa.coo_matrix((nonzeros, (irow, jcol)), shape=(1,3))
+ return jac
+
+class PressureDropSingleEquality(ExternalGreyBoxModel):
+ # u = [Pin, c, F, Pout]
+ # o = {empty}
+ # h_eq(u) = [Pout - (Pin - 4*c*F^2]
+ # h_o(u) = {empty}
+ def __init__(self):
+ self._input_names = ['Pin', 'c', 'F', 'Pout']
+ self._input_values = np.zeros(4, dtype=np.float64)
+ self._equality_constraint_names = ['pdrop']
+
+ def input_names(self):
+ return self._input_names
+
+ def equality_constraint_names(self):
+ return self._equality_constraint_names
+
+ def output_names(self):
+ return []
+
+ def set_input_values(self, input_values):
+ assert len(input_values) == 4
+ np.copyto(self._input_values, input_values)
+
+ def evaluate_equality_constraints(self):
+ Pin = self._input_values[0]
+ c = self._input_values[1]
+ F = self._input_values[2]
+ Pout = self._input_values[3]
+ return np.asarray([Pout - (Pin - 4*c*F**2)], dtype=np.float64)
+
+ def evaluate_outputs(self):
+ raise NotImplementedError('This method should not be called for this model.')
+
+ def evaluate_jacobian_equality_constraints(self):
+ c = self._input_values[1]
+ F = self._input_values[2]
+ irow = np.asarray([0, 0, 0, 0], dtype=np.int64)
+ jcol = np.asarray([0, 1, 2, 3], dtype=np.int64)
+ nonzeros = np.asarray([-1, 4*F**2, 4*2*c*F, 1], dtype=np.float64)
+ jac = spa.coo_matrix((nonzeros, (irow, jcol)), shape=(1,4))
+ return jac
+
+ def evaluate_jacobian_outputs(self):
+ raise NotImplementedError('This method should not be called for this model.')
+
+class PressureDropTwoOutputs(ExternalGreyBoxModel):
+ # u = [Pin, c, F]
+ # o = [P2, Pout]
+ # h_eq(u) = {empty}
+ # h_o(u) = [Pin - 2*c*F^2]
+ # [Pin - 4*c*F^2]
+ def __init__(self):
+ self._input_names = ['Pin', 'c', 'F']
+ self._input_values = np.zeros(3, dtype=np.float64)
+ self._output_names = ['P2', 'Pout']
+
+ def input_names(self):
+ return self._input_names
+
+ def equality_constraint_names(self):
+ return []
+
+ def output_names(self):
+ return self._output_names
+
+ def set_input_values(self, input_values):
+ assert len(input_values) == 3
+ np.copyto(self._input_values, input_values)
+
+ def evaluate_equality_constraints(self):
+ raise NotImplementedError('This method should not be called for this model.')
+
+ def evaluate_outputs(self):
+ Pin = self._input_values[0]
+ c = self._input_values[1]
+ F = self._input_values[2]
+ P2 = Pin - 2*c*F**2
+ Pout = Pin - 4*c*F**2
+ return np.asarray([P2, Pout], dtype=np.float64)
+
+ def evaluate_jacobian_equality_constraints(self):
+ raise NotImplementedError('This method should not be called for this model.')
+
+ def evaluate_jacobian_outputs(self):
+ c = self._input_values[1]
+ F = self._input_values[2]
+ irow = np.asarray([0, 0, 0, 1, 1, 1], dtype=np.int64)
+ jcol = np.asarray([0, 1, 2, 0, 1, 2], dtype=np.int64)
+ nonzeros = np.asarray([1, -2*F**2, -2*c*2*F, 1, -4*F**2, -4*c*2*F], dtype=np.float64)
+ jac = spa.coo_matrix((nonzeros, (irow, jcol)), shape=(2,3))
+ return jac
+
+class PressureDropTwoEqualities(ExternalGreyBoxModel):
+ # u = [Pin, c, F, P2, Pout]
+ # o = {empty}
+ # h_eq(u) = [P2 - (Pin - 2*c*F^2]
+ # [Pout - (P2 - 2*c*F^2]
+ # h_o(u) = {empty}
+ def __init__(self):
+ self._input_names = ['Pin', 'c', 'F', 'P2', 'Pout']
+ self._input_values = np.zeros(5, dtype=np.float64)
+ self._equality_constraint_names = ['pdrop2', 'pdropout']
+
+ def input_names(self):
+ return self._input_names
+
+ def equality_constraint_names(self):
+ return self._equality_constraint_names
+
+ def output_names(self):
+ return []
+
+ def set_input_values(self, input_values):
+ assert len(input_values) == 5
+ np.copyto(self._input_values, input_values)
+
+ def evaluate_equality_constraints(self):
+ Pin = self._input_values[0]
+ c = self._input_values[1]
+ F = self._input_values[2]
+ P2 = self._input_values[3]
+ Pout = self._input_values[4]
+ return np.asarray([P2 - (Pin - 2*c*F**2), Pout - (P2 - 2*c*F**2)], dtype=np.float64)
+
+ def evaluate_outputs(self):
+ raise NotImplementedError('This method should not be called for this model.')
+
+ def evaluate_jacobian_equality_constraints(self):
+ c = self._input_values[1]
+ F = self._input_values[2]
+ irow = np.asarray([0, 0, 0, 0, 1, 1, 1, 1], dtype=np.int64)
+ jcol = np.asarray([0, 1, 2, 3, 1, 2, 3, 4], dtype=np.int64)
+ nonzeros = np.asarray([-1, 2*F**2, 2*2*c*F, 1, 2*F**2, 2*2*c*F, -1, 1], dtype=np.float64)
+ jac = spa.coo_matrix((nonzeros, (irow, jcol)), shape=(2,5))
+ return jac
+
+ def evaluate_jacobian_outputs(self):
+ raise NotImplementedError('This method should not be called for this model.')
+
+class PressureDropTwoEqualitiesTwoOutputs(ExternalGreyBoxModel):
+ # u = [Pin, c, F, P1, P3]
+ # o = {P2, Pout}
+ # h_eq(u) = [P1 - (Pin - c*F^2]
+ # [P3 - (P1 - 2*c*F^2]
+ # h_o(u) = [P1 - c*F^2]
+ # [Pin - 4*c*F^2]
+ def __init__(self):
+ self._input_names = ['Pin', 'c', 'F', 'P1', 'P3']
+ self._input_values = np.zeros(5, dtype=np.float64)
+ self._equality_constraint_names = ['pdrop1', 'pdrop3']
+ self._output_names = ['P2', 'Pout']
+
+ def input_names(self):
+ return self._input_names
+
+ def equality_constraint_names(self):
+ return self._equality_constraint_names
+
+ def output_names(self):
+ return self._output_names
+
+ def set_input_values(self, input_values):
+ assert len(input_values) == 5
+ np.copyto(self._input_values, input_values)
+
+ def evaluate_equality_constraints(self):
+ Pin = self._input_values[0]
+ c = self._input_values[1]
+ F = self._input_values[2]
+ P1 = self._input_values[3]
+ P3 = self._input_values[4]
+ return np.asarray([P1 - (Pin - c*F**2), P3 - (P1 - 2*c*F**2)], dtype=np.float64)
+
+ def evaluate_outputs(self):
+ Pin = self._input_values[0]
+ c = self._input_values[1]
+ F = self._input_values[2]
+ P1 = self._input_values[3]
+ return np.asarray([P1 - c*F**2, Pin - 4*c*F**2], dtype=np.float64)
+
+ def evaluate_jacobian_equality_constraints(self):
+ c = self._input_values[1]
+ F = self._input_values[2]
+ irow = np.asarray([0, 0, 0, 0, 1, 1, 1, 1], dtype=np.int64)
+ jcol = np.asarray([0, 1, 2, 3, 1, 2, 3, 4], dtype=np.int64)
+ nonzeros = np.asarray([-1, F**2, 2*c*F, 1, 2*F**2, 4*c*F, -1, 1], dtype=np.float64)
+ jac = spa.coo_matrix((nonzeros, (irow, jcol)), shape=(2,5))
+ return jac
+
+ def evaluate_jacobian_outputs(self):
+ c = self._input_values[1]
+ F = self._input_values[2]
+ irow = np.asarray([0, 0, 0, 1, 1, 1], dtype=np.int64)
+ jcol = np.asarray([1, 2, 3, 0, 1, 2], dtype=np.int64)
+ nonzeros = np.asarray([-F**2, -c*2*F, 1, 1, -4*F**2, -4*c*2*F], dtype=np.float64)
+ jac = spa.coo_matrix((nonzeros, (irow, jcol)), shape=(2,5))
+ return jac
+
+class PressureDropTwoEqualitiesTwoOutputsScaleBoth(PressureDropTwoEqualitiesTwoOutputs):
+ def get_equality_constraint_scaling_factors(self):
+ return np.asarray([3.1, 3.2], dtype=np.float64)
+
+ def get_output_constraint_scaling_factors(self):
+ return np.asarray([4.1, 4.2])
+
+class PressureDropTwoEqualitiesTwoOutputsScaleEqualities(PressureDropTwoEqualitiesTwoOutputs):
+ def get_equality_constraint_scaling_factors(self):
+ return np.asarray([3.1, 3.2], dtype=np.float64)
+
+class PressureDropTwoEqualitiesTwoOutputsScaleOutputs(PressureDropTwoEqualitiesTwoOutputs):
+ def get_output_constraint_scaling_factors(self):
+ return np.asarray([4.1, 4.2])
+
+
+class TestExternalGreyBoxModel(unittest.TestCase):
+
+ def test_pressure_drop_single_output(self):
+ egbm = PressureDropSingleOutput()
+ input_names = egbm.input_names()
+ self.assertEqual(input_names, ['Pin', 'c', 'F'])
+ eq_con_names = egbm.equality_constraint_names()
+ self.assertEqual(eq_con_names, [])
+ output_names = egbm.output_names()
+ self.assertEqual(output_names, ['Pout'])
+
+ egbm.set_input_values(np.asarray([100, 2, 3], dtype=np.float64))
+
+ with self.assertRaises(NotImplementedError):
+ tmp = egbm.evaluate_equality_constraints()
+
+ o = egbm.evaluate_outputs()
+ self.assertTrue(np.array_equal(o, np.asarray([28], dtype=np.float64)))
+
+ with self.assertRaises(NotImplementedError):
+ tmp = egbm.evaluate_jacobian_equality_constraints()
+
+ jac_o = egbm.evaluate_jacobian_outputs()
+ self.assertTrue(np.array_equal(jac_o.row, np.asarray([0,0,0], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_o.col, np.asarray([0,1,2], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_o.data, np.asarray([1,-36,-48], dtype=np.float64)))
+
+ def test_pressure_drop_single_equality(self):
+ egbm = PressureDropSingleEquality()
+ input_names = egbm.input_names()
+ self.assertEqual(input_names, ['Pin', 'c', 'F', 'Pout'])
+ eq_con_names = egbm.equality_constraint_names()
+ self.assertEqual(eq_con_names, ['pdrop'])
+ output_names = egbm.output_names()
+ self.assertEqual(output_names, [])
+
+ egbm.set_input_values(np.asarray([100, 2, 3, 50], dtype=np.float64))
+
+ eq = egbm.evaluate_equality_constraints()
+ self.assertTrue(np.array_equal(eq, np.asarray([22], dtype=np.float64)))
+
+ with self.assertRaises(NotImplementedError):
+ tmp = egbm.evaluate_outputs()
+
+ with self.assertRaises(NotImplementedError):
+ tmp = egbm.evaluate_jacobian_outputs()
+
+ jac_eq = egbm.evaluate_jacobian_equality_constraints()
+ self.assertTrue(np.array_equal(jac_eq.row, np.asarray([0,0,0,0], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_eq.col, np.asarray([0,1,2,3], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_eq.data, np.asarray([-1, 36, 48, 1], dtype=np.float64)))
+
+ def test_pressure_drop_two_outputs(self):
+ egbm = PressureDropTwoOutputs()
+ input_names = egbm.input_names()
+ self.assertEqual(input_names, ['Pin', 'c', 'F'])
+ eq_con_names = egbm.equality_constraint_names()
+ self.assertEqual([], eq_con_names)
+ output_names = egbm.output_names()
+ self.assertEqual(output_names, ['P2', 'Pout'])
+
+ egbm.set_input_values(np.asarray([100, 2, 3], dtype=np.float64))
+
+ with self.assertRaises(NotImplementedError):
+ tmp = egbm.evaluate_equality_constraints()
+
+ # u = [Pin, c, F]
+ # o = [P2, Pout]
+ # h_eq(u) = {empty}
+ # h_o(u) = [Pin - 2*c*F^2]
+ # [Pin - 4*c*F^2]
+
+ o = egbm.evaluate_outputs()
+ self.assertTrue(np.array_equal(o, np.asarray([64, 28], dtype=np.float64)))
+
+ with self.assertRaises(NotImplementedError):
+ tmp = egbm.evaluate_jacobian_equality_constraints()
+
+ jac_o = egbm.evaluate_jacobian_outputs()
+ self.assertTrue(np.array_equal(jac_o.row, np.asarray([0,0,0,1,1,1], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_o.col, np.asarray([0,1,2,0,1,2], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_o.data, np.asarray([1, -18, -24, 1,-36,-48], dtype=np.float64)))
+
+ def test_pressure_drop_two_equalities(self):
+ egbm = PressureDropTwoEqualities()
+ input_names = egbm.input_names()
+ self.assertEqual(input_names, ['Pin', 'c', 'F', 'P2', 'Pout'])
+ eq_con_names = egbm.equality_constraint_names()
+ self.assertEqual(eq_con_names, ['pdrop2', 'pdropout'])
+ output_names = egbm.output_names()
+ self.assertEqual([], output_names)
+
+ egbm.set_input_values(np.asarray([100, 2, 3, 20, 50], dtype=np.float64))
+
+ # u = [Pin, c, F, P2, Pout]
+ # o = {empty}
+ # h_eq(u) = [P2 - (Pin - 2*c*F^2]
+ # [Pout - (P2 - 2*c*F^2]
+ # h_o(u) = {empty}
+ eq = egbm.evaluate_equality_constraints()
+ self.assertTrue(np.array_equal(eq, np.asarray([-44, 66], dtype=np.float64)))
+
+ with self.assertRaises(NotImplementedError):
+ tmp = egbm.evaluate_outputs()
+
+ with self.assertRaises(NotImplementedError):
+ tmp = egbm.evaluate_jacobian_outputs()
+
+ jac_eq = egbm.evaluate_jacobian_equality_constraints()
+ self.assertTrue(np.array_equal(jac_eq.row, np.asarray([0,0,0,0,1,1,1,1], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_eq.col, np.asarray([0,1,2,3,1,2,3,4], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_eq.data, np.asarray([-1, 18, 24, 1, 18, 24, -1, 1], dtype=np.float64)))
+
+ def test_pressure_drop_two_equalities_two_outputs(self):
+ # u = [Pin, c, F, P1, P3]
+ # o = {P2, Pout}
+ # h_eq(u) = [P1 - (Pin - c*F^2]
+ # [P3 - (Pin - 2*c*F^2]
+ # h_o(u) = [P1 - c*F^2]
+ # [Pin - 4*c*F^2]
+ egbm = PressureDropTwoEqualitiesTwoOutputs()
+ input_names = egbm.input_names()
+ self.assertEqual(input_names, ['Pin', 'c', 'F', 'P1', 'P3'])
+ eq_con_names = egbm.equality_constraint_names()
+ self.assertEqual(eq_con_names, ['pdrop1', 'pdrop3'])
+ output_names = egbm.output_names()
+ self.assertEqual(output_names, ['P2', 'Pout'])
+
+ egbm.set_input_values(np.asarray([100, 2, 3, 80, 70], dtype=np.float64))
+ eq = egbm.evaluate_equality_constraints()
+ self.assertTrue(np.array_equal(eq, np.asarray([-2, 26], dtype=np.float64)))
+
+ o = egbm.evaluate_outputs()
+ self.assertTrue(np.array_equal(o, np.asarray([62, 28], dtype=np.float64)))
+
+ jac_eq = egbm.evaluate_jacobian_equality_constraints()
+ self.assertTrue(np.array_equal(jac_eq.row, np.asarray([0,0,0,0,1,1,1,1], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_eq.col, np.asarray([0,1,2,3,1,2,3,4], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_eq.data, np.asarray([-1, 9, 12, 1, 18, 24, -1, 1], dtype=np.float64)))
+
+ jac_o = egbm.evaluate_jacobian_outputs()
+ self.assertTrue(np.array_equal(jac_o.row, np.asarray([0,0,0,1,1,1], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_o.col, np.asarray([1,2,3,0,1,2], dtype=np.int64)))
+ self.assertTrue(np.array_equal(jac_o.data, np.asarray([-9, -12, 1, 1, -36, -48], dtype=np.float64)))
+
+# TODO: make this work even if there is only external and no variables anywhere in pyomo part
+class TestPyomoGreyBoxNLP(unittest.TestCase):
+ @unittest.skip("It looks like ASL exits when there are no variables")
+ def test_error_no_variables(self):
+ m = pyo.ConcreteModel()
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropSingleOutput())
+ m.obj = pyo.Objective(expr=1)
+ with self.assertRaises(ValueError):
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ def test_error_fixed_inputs_outputs(self):
+ m = pyo.ConcreteModel()
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropSingleOutput())
+ m.egb.inputs['Pin'].fix(100)
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ with self.assertRaises(NotImplementedError):
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ m = pyo.ConcreteModel()
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropTwoOutputs())
+ m.egb.outputs['P2'].fix(50)
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ with self.assertRaises(NotImplementedError):
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ def test_pressure_drop_single_output(self):
+ m = pyo.ConcreteModel()
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropSingleOutput())
+ m.egb.inputs['Pin'].value = 100
+ m.egb.inputs['Pin'].setlb(50)
+ m.egb.inputs['Pin'].setub(150)
+ m.egb.inputs['c'].value = 2
+ m.egb.inputs['c'].setlb(1)
+ m.egb.inputs['c'].setub(5)
+ m.egb.inputs['F'].value = 3
+ m.egb.inputs['F'].setlb(1)
+ m.egb.inputs['F'].setub(5)
+ m.egb.outputs['Pout'].value = 50
+ m.egb.outputs['Pout'].setlb(0)
+ m.egb.outputs['Pout'].setub(100)
+ #m.dummy = pyo.Constraint(expr=sum(m.egb.inputs[i] for i in m.egb.inputs) + sum(m.egb.outputs[i] for i in m.egb.outputs) <= 1e6)
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ self.assertEqual(4, pyomo_nlp.n_primals())
+ self.assertEqual(1, pyomo_nlp.n_constraints())
+ self.assertEqual(4, pyomo_nlp.nnz_jacobian())
+ with self.assertRaises(NotImplementedError):
+ tmp = pyomo_nlp.nnz_hessian_lag()
+
+ comparison_x_order = ['egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[F]', 'egb.outputs[Pout]']
+ x_order = pyomo_nlp.variable_names()
+ comparison_c_order = ['egb.Pout_con']
+ c_order = pyomo_nlp.constraint_names()
+
+ xlb = pyomo_nlp.primals_lb()
+ comparison_xlb = np.asarray([50, 1, 1, 0], dtype=np.float64)
+ check_vectors_specific_order(self, xlb, x_order, comparison_xlb, comparison_x_order)
+ xub = pyomo_nlp.primals_ub()
+ comparison_xub = np.asarray([150, 5, 5, 100], dtype=np.float64)
+ check_vectors_specific_order(self, xub, x_order, comparison_xub, comparison_x_order)
+ clb = pyomo_nlp.constraints_lb()
+ comparison_clb = np.asarray([0], dtype=np.float64)
+ check_vectors_specific_order(self, clb, c_order, comparison_clb, comparison_c_order)
+ cub = pyomo_nlp.constraints_ub()
+ comparison_cub = np.asarray([0], dtype=np.float64)
+ check_vectors_specific_order(self, cub, c_order, comparison_cub, comparison_c_order)
+
+ xinit = pyomo_nlp.init_primals()
+ comparison_xinit = np.asarray([100, 2, 3, 50], dtype=np.float64)
+ check_vectors_specific_order(self, xinit, x_order, comparison_xinit, comparison_x_order)
+ duals_init = pyomo_nlp.init_duals()
+ comparison_duals_init = np.asarray([1], dtype=np.float64)
+ check_vectors_specific_order(self, duals_init, c_order, comparison_duals_init, comparison_c_order)
+
+ self.assertEqual(4, len(pyomo_nlp.create_new_vector('primals')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('constraints')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('duals')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('eq_constraints')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('ineq_constraints')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('duals_eq')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('duals_ineq')))
+
+ pyomo_nlp.set_primals(np.asarray([1, 2, 3, 4], dtype=np.float64))
+ x = pyomo_nlp.get_primals()
+ self.assertTrue(np.array_equal(x, np.asarray([1,2,3,4], dtype=np.float64)))
+ pyomo_nlp.set_primals(pyomo_nlp.init_primals())
+
+ pyomo_nlp.set_duals(np.asarray([42], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([42], dtype=np.float64)))
+ pyomo_nlp.set_duals(np.asarray([1], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([1], dtype=np.float64)))
+
+ fac = pyomo_nlp.get_obj_factor()
+ self.assertEqual(fac, 1)
+ pyomo_nlp.set_obj_factor(42)
+ self.assertEqual(pyomo_nlp.get_obj_factor(), 42)
+ pyomo_nlp.set_obj_factor(1)
+
+ f = pyomo_nlp.evaluate_objective()
+ self.assertEqual(f, 900)
+
+ gradf = pyomo_nlp.evaluate_grad_objective()
+ comparison_gradf = np.asarray([0, 0, 0, 60], dtype=np.float64)
+ check_vectors_specific_order(self, gradf, x_order, comparison_gradf, comparison_x_order)
+ c = pyomo_nlp.evaluate_constraints()
+ comparison_c = np.asarray([-22], dtype=np.float64)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+ c = np.zeros(1)
+ pyomo_nlp.evaluate_constraints(out=c)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+
+
+ j = pyomo_nlp.evaluate_jacobian()
+ comparison_j = np.asarray([[1, -36, -48, -1]])
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ j = 2.0*j
+ pyomo_nlp.evaluate_jacobian(out=j)
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ with self.assertRaises(NotImplementedError):
+ h = pyomo_nlp.evaluate_hessian_lag()
+
+ def test_pressure_drop_single_equality(self):
+ m = pyo.ConcreteModel()
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropSingleEquality())
+ m.egb.inputs['Pin'].value = 100
+ m.egb.inputs['Pin'].setlb(50)
+ m.egb.inputs['Pin'].setub(150)
+ m.egb.inputs['c'].value = 2
+ m.egb.inputs['c'].setlb(1)
+ m.egb.inputs['c'].setub(5)
+ m.egb.inputs['F'].value = 3
+ m.egb.inputs['F'].setlb(1)
+ m.egb.inputs['F'].setub(5)
+ m.egb.inputs['Pout'].value = 50
+ m.egb.inputs['Pout'].setlb(0)
+ m.egb.inputs['Pout'].setub(100)
+ m.obj = pyo.Objective(expr=(m.egb.inputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ self.assertEqual(4, pyomo_nlp.n_primals())
+ self.assertEqual(1, pyomo_nlp.n_constraints())
+ self.assertEqual(4, pyomo_nlp.nnz_jacobian())
+ with self.assertRaises(NotImplementedError):
+ tmp = pyomo_nlp.nnz_hessian_lag()
+
+ comparison_x_order = ['egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[F]', 'egb.inputs[Pout]']
+ x_order = pyomo_nlp.variable_names()
+ comparison_c_order = ['egb.pdrop']
+ c_order = pyomo_nlp.constraint_names()
+
+ xlb = pyomo_nlp.primals_lb()
+ comparison_xlb = np.asarray([50, 1, 1, 0], dtype=np.float64)
+ check_vectors_specific_order(self, xlb, x_order, comparison_xlb, comparison_x_order)
+ xub = pyomo_nlp.primals_ub()
+ comparison_xub = np.asarray([150, 5, 5, 100], dtype=np.float64)
+ check_vectors_specific_order(self, xub, x_order, comparison_xub, comparison_x_order)
+ clb = pyomo_nlp.constraints_lb()
+ comparison_clb = np.asarray([0], dtype=np.float64)
+ check_vectors_specific_order(self, clb, c_order, comparison_clb, comparison_c_order)
+ cub = pyomo_nlp.constraints_ub()
+ comparison_cub = np.asarray([0], dtype=np.float64)
+ check_vectors_specific_order(self, cub, c_order, comparison_cub, comparison_c_order)
+
+ xinit = pyomo_nlp.init_primals()
+ comparison_xinit = np.asarray([100, 2, 3, 50], dtype=np.float64)
+ check_vectors_specific_order(self, xinit, x_order, comparison_xinit, comparison_x_order)
+ duals_init = pyomo_nlp.init_duals()
+ comparison_duals_init = np.asarray([1], dtype=np.float64)
+ check_vectors_specific_order(self, duals_init, c_order, comparison_duals_init, comparison_c_order)
+
+ self.assertEqual(4, len(pyomo_nlp.create_new_vector('primals')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('constraints')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('duals')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('eq_constraints')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('ineq_constraints')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('duals_eq')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('duals_ineq')))
+
+ pyomo_nlp.set_primals(np.asarray([1, 2, 3, 4], dtype=np.float64))
+ x = pyomo_nlp.get_primals()
+ self.assertTrue(np.array_equal(x, np.asarray([1,2,3,4], dtype=np.float64)))
+ pyomo_nlp.set_primals(pyomo_nlp.init_primals())
+
+ pyomo_nlp.set_duals(np.asarray([42], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([42], dtype=np.float64)))
+ pyomo_nlp.set_duals(np.asarray([1], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([1], dtype=np.float64)))
+
+ fac = pyomo_nlp.get_obj_factor()
+ self.assertEqual(fac, 1)
+ pyomo_nlp.set_obj_factor(42)
+ self.assertEqual(pyomo_nlp.get_obj_factor(), 42)
+ pyomo_nlp.set_obj_factor(1)
+
+ f = pyomo_nlp.evaluate_objective()
+ self.assertEqual(f, 900)
+
+ gradf = pyomo_nlp.evaluate_grad_objective()
+ comparison_gradf = np.asarray([0, 0, 0, 60], dtype=np.float64)
+ check_vectors_specific_order(self, gradf, x_order, comparison_gradf, comparison_x_order)
+ c = pyomo_nlp.evaluate_constraints()
+ comparison_c = np.asarray([22], dtype=np.float64)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+ c = np.zeros(1)
+ pyomo_nlp.evaluate_constraints(out=c)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+
+
+ j = pyomo_nlp.evaluate_jacobian()
+ comparison_j = np.asarray([[-1, 36, 48, 1]])
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ j = 2.0*j
+ pyomo_nlp.evaluate_jacobian(out=j)
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ with self.assertRaises(NotImplementedError):
+ h = pyomo_nlp.evaluate_hessian_lag()
+
+ def test_pressure_drop_two_outputs(self):
+ m = pyo.ConcreteModel()
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropTwoOutputs())
+ m.egb.inputs['Pin'].value = 100
+ m.egb.inputs['Pin'].setlb(50)
+ m.egb.inputs['Pin'].setub(150)
+ m.egb.inputs['c'].value = 2
+ m.egb.inputs['c'].setlb(1)
+ m.egb.inputs['c'].setub(5)
+ m.egb.inputs['F'].value = 3
+ m.egb.inputs['F'].setlb(1)
+ m.egb.inputs['F'].setub(5)
+ m.egb.outputs['P2'].value = 80
+ m.egb.outputs['P2'].setlb(10)
+ m.egb.outputs['P2'].setub(90)
+ m.egb.outputs['Pout'].value = 50
+ m.egb.outputs['Pout'].setlb(0)
+ m.egb.outputs['Pout'].setub(100)
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ self.assertEqual(5, pyomo_nlp.n_primals())
+ self.assertEqual(2, pyomo_nlp.n_constraints())
+ self.assertEqual(8, pyomo_nlp.nnz_jacobian())
+ with self.assertRaises(NotImplementedError):
+ tmp = pyomo_nlp.nnz_hessian_lag()
+
+ comparison_x_order = ['egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[F]', 'egb.outputs[P2]', 'egb.outputs[Pout]']
+ x_order = pyomo_nlp.variable_names()
+ comparison_c_order = ['egb.P2_con', 'egb.Pout_con']
+ c_order = pyomo_nlp.constraint_names()
+
+ xlb = pyomo_nlp.primals_lb()
+ comparison_xlb = np.asarray([50, 1, 1, 10, 0], dtype=np.float64)
+ check_vectors_specific_order(self, xlb, x_order, comparison_xlb, comparison_x_order)
+ xub = pyomo_nlp.primals_ub()
+ comparison_xub = np.asarray([150, 5, 5, 90, 100], dtype=np.float64)
+ check_vectors_specific_order(self, xub, x_order, comparison_xub, comparison_x_order)
+ clb = pyomo_nlp.constraints_lb()
+ comparison_clb = np.asarray([0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, clb, c_order, comparison_clb, comparison_c_order)
+ cub = pyomo_nlp.constraints_ub()
+ comparison_cub = np.asarray([0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, cub, c_order, comparison_cub, comparison_c_order)
+
+ xinit = pyomo_nlp.init_primals()
+ comparison_xinit = np.asarray([100, 2, 3, 80, 50], dtype=np.float64)
+ check_vectors_specific_order(self, xinit, x_order, comparison_xinit, comparison_x_order)
+ duals_init = pyomo_nlp.init_duals()
+ comparison_duals_init = np.asarray([1, 1], dtype=np.float64)
+ check_vectors_specific_order(self, duals_init, c_order, comparison_duals_init, comparison_c_order)
+
+ self.assertEqual(5, len(pyomo_nlp.create_new_vector('primals')))
+ self.assertEqual(2, len(pyomo_nlp.create_new_vector('constraints')))
+ self.assertEqual(2, len(pyomo_nlp.create_new_vector('duals')))
+ self.assertEqual(2, len(pyomo_nlp.create_new_vector('eq_constraints')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('ineq_constraints')))
+ self.assertEqual(2, len(pyomo_nlp.create_new_vector('duals_eq')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('duals_ineq')))
+
+ pyomo_nlp.set_primals(np.asarray([1, 2, 3, 4, 5], dtype=np.float64))
+ x = pyomo_nlp.get_primals()
+ self.assertTrue(np.array_equal(x, np.asarray([1,2,3,4,5], dtype=np.float64)))
+ pyomo_nlp.set_primals(pyomo_nlp.init_primals())
+
+ pyomo_nlp.set_duals(np.asarray([42, 10], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([42, 10], dtype=np.float64)))
+ pyomo_nlp.set_duals(np.asarray([1, 1], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([1, 1], dtype=np.float64)))
+
+ fac = pyomo_nlp.get_obj_factor()
+ self.assertEqual(fac, 1)
+ pyomo_nlp.set_obj_factor(42)
+ self.assertEqual(pyomo_nlp.get_obj_factor(), 42)
+ pyomo_nlp.set_obj_factor(1)
+
+ f = pyomo_nlp.evaluate_objective()
+ self.assertEqual(f, 900)
+
+ gradf = pyomo_nlp.evaluate_grad_objective()
+ comparison_gradf = np.asarray([0, 0, 0, 0, 60], dtype=np.float64)
+ check_vectors_specific_order(self, gradf, x_order, comparison_gradf, comparison_x_order)
+ c = pyomo_nlp.evaluate_constraints()
+ comparison_c = np.asarray([-16, -22], dtype=np.float64)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+ c = np.zeros(2)
+ pyomo_nlp.evaluate_constraints(out=c)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+
+
+ j = pyomo_nlp.evaluate_jacobian()
+ comparison_j = np.asarray([[1, -18, -24, -1, 0], [1, -36, -48, 0, -1]])
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ j = 2.0*j
+ pyomo_nlp.evaluate_jacobian(out=j)
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ with self.assertRaises(NotImplementedError):
+ h = pyomo_nlp.evaluate_hessian_lag()
+
+ def test_pressure_drop_two_equalities(self):
+ m = pyo.ConcreteModel()
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropTwoEqualities())
+ m.egb.inputs['Pin'].value = 100
+ m.egb.inputs['Pin'].setlb(50)
+ m.egb.inputs['Pin'].setub(150)
+ m.egb.inputs['c'].value = 2
+ m.egb.inputs['c'].setlb(1)
+ m.egb.inputs['c'].setub(5)
+ m.egb.inputs['F'].value = 3
+ m.egb.inputs['F'].setlb(1)
+ m.egb.inputs['F'].setub(5)
+ m.egb.inputs['P2'].value = 80
+ m.egb.inputs['P2'].setlb(10)
+ m.egb.inputs['P2'].setub(90)
+ m.egb.inputs['Pout'].value = 50
+ m.egb.inputs['Pout'].setlb(0)
+ m.egb.inputs['Pout'].setub(100)
+ m.obj = pyo.Objective(expr=(m.egb.inputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ self.assertEqual(5, pyomo_nlp.n_primals())
+ self.assertEqual(2, pyomo_nlp.n_constraints())
+ self.assertEqual(8, pyomo_nlp.nnz_jacobian())
+ with self.assertRaises(NotImplementedError):
+ tmp = pyomo_nlp.nnz_hessian_lag()
+
+ comparison_x_order = ['egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[F]', 'egb.inputs[P2]', 'egb.inputs[Pout]']
+ x_order = pyomo_nlp.variable_names()
+ comparison_c_order = ['egb.pdrop2', 'egb.pdropout']
+ c_order = pyomo_nlp.constraint_names()
+
+ xlb = pyomo_nlp.primals_lb()
+ comparison_xlb = np.asarray([50, 1, 1, 10, 0], dtype=np.float64)
+ check_vectors_specific_order(self, xlb, x_order, comparison_xlb, comparison_x_order)
+ xub = pyomo_nlp.primals_ub()
+ comparison_xub = np.asarray([150, 5, 5, 90, 100], dtype=np.float64)
+ check_vectors_specific_order(self, xub, x_order, comparison_xub, comparison_x_order)
+ clb = pyomo_nlp.constraints_lb()
+ comparison_clb = np.asarray([0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, clb, c_order, comparison_clb, comparison_c_order)
+ cub = pyomo_nlp.constraints_ub()
+ comparison_cub = np.asarray([0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, cub, c_order, comparison_cub, comparison_c_order)
+
+ xinit = pyomo_nlp.init_primals()
+ comparison_xinit = np.asarray([100, 2, 3, 80, 50], dtype=np.float64)
+ check_vectors_specific_order(self, xinit, x_order, comparison_xinit, comparison_x_order)
+ duals_init = pyomo_nlp.init_duals()
+ comparison_duals_init = np.asarray([1, 1], dtype=np.float64)
+ check_vectors_specific_order(self, duals_init, c_order, comparison_duals_init, comparison_c_order)
+
+ self.assertEqual(5, len(pyomo_nlp.create_new_vector('primals')))
+ self.assertEqual(2, len(pyomo_nlp.create_new_vector('constraints')))
+ self.assertEqual(2, len(pyomo_nlp.create_new_vector('duals')))
+ self.assertEqual(2, len(pyomo_nlp.create_new_vector('eq_constraints')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('ineq_constraints')))
+ self.assertEqual(2, len(pyomo_nlp.create_new_vector('duals_eq')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('duals_ineq')))
+
+ pyomo_nlp.set_primals(np.asarray([1, 2, 3, 4, 5], dtype=np.float64))
+ x = pyomo_nlp.get_primals()
+ self.assertTrue(np.array_equal(x, np.asarray([1,2,3,4,5], dtype=np.float64)))
+ pyomo_nlp.set_primals(pyomo_nlp.init_primals())
+
+ pyomo_nlp.set_duals(np.asarray([42, 10], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([42, 10], dtype=np.float64)))
+ pyomo_nlp.set_duals(np.asarray([1, 1], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([1, 1], dtype=np.float64)))
+
+ fac = pyomo_nlp.get_obj_factor()
+ self.assertEqual(fac, 1)
+ pyomo_nlp.set_obj_factor(42)
+ self.assertEqual(pyomo_nlp.get_obj_factor(), 42)
+ pyomo_nlp.set_obj_factor(1)
+
+ f = pyomo_nlp.evaluate_objective()
+ self.assertEqual(f, 900)
+
+ gradf = pyomo_nlp.evaluate_grad_objective()
+ comparison_gradf = np.asarray([0, 0, 0, 0, 60], dtype=np.float64)
+ check_vectors_specific_order(self, gradf, x_order, comparison_gradf, comparison_x_order)
+ c = pyomo_nlp.evaluate_constraints()
+ comparison_c = np.asarray([16, 6], dtype=np.float64)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+ c = np.zeros(2)
+ pyomo_nlp.evaluate_constraints(out=c)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+
+
+ j = pyomo_nlp.evaluate_jacobian()
+ comparison_j = np.asarray([[-1, 18, 24, 1, 0], [0, 18, 24, -1, 1]])
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ j = 2.0*j
+ pyomo_nlp.evaluate_jacobian(out=j)
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ with self.assertRaises(NotImplementedError):
+ h = pyomo_nlp.evaluate_hessian_lag()
+
+ def test_pressure_drop_two_equalities_two_outputs(self):
+ m = pyo.ConcreteModel()
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropTwoEqualitiesTwoOutputs())
+ m.egb.inputs['Pin'].value = 100
+ m.egb.inputs['Pin'].setlb(50)
+ m.egb.inputs['Pin'].setub(150)
+ m.egb.inputs['c'].value = 2
+ m.egb.inputs['c'].setlb(1)
+ m.egb.inputs['c'].setub(5)
+ m.egb.inputs['F'].value = 3
+ m.egb.inputs['F'].setlb(1)
+ m.egb.inputs['F'].setub(5)
+ m.egb.inputs['P1'].value = 80
+ m.egb.inputs['P1'].setlb(10)
+ m.egb.inputs['P1'].setub(90)
+ m.egb.inputs['P3'].value = 70
+ m.egb.inputs['P3'].setlb(20)
+ m.egb.inputs['P3'].setub(80)
+ m.egb.outputs['P2'].value = 75
+ m.egb.outputs['P2'].setlb(15)
+ m.egb.outputs['P2'].setub(85)
+ m.egb.outputs['Pout'].value = 50
+ m.egb.outputs['Pout'].setlb(30)
+ m.egb.outputs['Pout'].setub(70)
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ self.assertEqual(7, pyomo_nlp.n_primals())
+ self.assertEqual(4, pyomo_nlp.n_constraints())
+ self.assertEqual(16, pyomo_nlp.nnz_jacobian())
+ with self.assertRaises(NotImplementedError):
+ tmp = pyomo_nlp.nnz_hessian_lag()
+
+ comparison_x_order = ['egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[F]',
+ 'egb.inputs[P1]', 'egb.inputs[P3]',
+ 'egb.outputs[P2]', 'egb.outputs[Pout]']
+ x_order = pyomo_nlp.variable_names()
+ comparison_c_order = ['egb.pdrop1', 'egb.pdrop3', 'egb.P2_con', 'egb.Pout_con']
+ c_order = pyomo_nlp.constraint_names()
+
+ xlb = pyomo_nlp.primals_lb()
+ comparison_xlb = np.asarray([50, 1, 1, 10, 20, 15, 30], dtype=np.float64)
+ check_vectors_specific_order(self, xlb, x_order, comparison_xlb, comparison_x_order)
+ xub = pyomo_nlp.primals_ub()
+ comparison_xub = np.asarray([150, 5, 5, 90, 80, 85, 70], dtype=np.float64)
+ check_vectors_specific_order(self, xub, x_order, comparison_xub, comparison_x_order)
+ clb = pyomo_nlp.constraints_lb()
+ comparison_clb = np.asarray([0, 0, 0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, clb, c_order, comparison_clb, comparison_c_order)
+ cub = pyomo_nlp.constraints_ub()
+ comparison_cub = np.asarray([0, 0, 0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, cub, c_order, comparison_cub, comparison_c_order)
+
+ xinit = pyomo_nlp.init_primals()
+ comparison_xinit = np.asarray([100, 2, 3, 80, 70, 75, 50], dtype=np.float64)
+ check_vectors_specific_order(self, xinit, x_order, comparison_xinit, comparison_x_order)
+ duals_init = pyomo_nlp.init_duals()
+ comparison_duals_init = np.asarray([1, 1, 1, 1], dtype=np.float64)
+ check_vectors_specific_order(self, duals_init, c_order, comparison_duals_init, comparison_c_order)
+
+ self.assertEqual(7, len(pyomo_nlp.create_new_vector('primals')))
+ self.assertEqual(4, len(pyomo_nlp.create_new_vector('constraints')))
+ self.assertEqual(4, len(pyomo_nlp.create_new_vector('duals')))
+ self.assertEqual(4, len(pyomo_nlp.create_new_vector('eq_constraints')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('ineq_constraints')))
+ self.assertEqual(4, len(pyomo_nlp.create_new_vector('duals_eq')))
+ self.assertEqual(0, len(pyomo_nlp.create_new_vector('duals_ineq')))
+
+ pyomo_nlp.set_primals(np.asarray([1, 2, 3, 4, 5, 6, 7], dtype=np.float64))
+ x = pyomo_nlp.get_primals()
+ self.assertTrue(np.array_equal(x, np.asarray([1,2,3,4,5,6,7], dtype=np.float64)))
+ pyomo_nlp.set_primals(pyomo_nlp.init_primals())
+
+ pyomo_nlp.set_duals(np.asarray([42, 10, 11, 12], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([42, 10, 11, 12], dtype=np.float64)))
+ pyomo_nlp.set_duals(np.asarray([1, 1, 1, 1], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([1, 1, 1, 1], dtype=np.float64)))
+
+ fac = pyomo_nlp.get_obj_factor()
+ self.assertEqual(fac, 1)
+ pyomo_nlp.set_obj_factor(42)
+ self.assertEqual(pyomo_nlp.get_obj_factor(), 42)
+ pyomo_nlp.set_obj_factor(1)
+
+ f = pyomo_nlp.evaluate_objective()
+ self.assertEqual(f, 900)
+
+ gradf = pyomo_nlp.evaluate_grad_objective()
+ comparison_gradf = np.asarray([0, 0, 0, 0, 0, 0, 60], dtype=np.float64)
+ check_vectors_specific_order(self, gradf, x_order, comparison_gradf, comparison_x_order)
+ c = pyomo_nlp.evaluate_constraints()
+ comparison_c = np.asarray([-2, 26, -13, -22], dtype=np.float64)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+ c = np.zeros(4)
+ pyomo_nlp.evaluate_constraints(out=c)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+
+
+ j = pyomo_nlp.evaluate_jacobian()
+ comparison_j = np.asarray([[-1, 9, 12, 1, 0, 0, 0],
+ [ 0, 18, 24, -1, 1, 0, 0],
+ [ 0, -9, -12, 1, 0, -1, 0],
+ [ 1, -36, -48, 0, 0, 0, -1]])
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ j = 2.0*j
+ pyomo_nlp.evaluate_jacobian(out=j)
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ with self.assertRaises(NotImplementedError):
+ h = pyomo_nlp.evaluate_hessian_lag()
+
+ def test_external_additional_constraints_vars(self):
+ m = pyo.ConcreteModel()
+ m.hin = pyo.Var(bounds=(0,None), initialize=10)
+ m.hout = pyo.Var(bounds=(0,None))
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropTwoEqualitiesTwoOutputs())
+ m.incon = pyo.Constraint(expr= 0 <= m.egb.inputs['Pin'] - 10*m.hin)
+ m.outcon = pyo.Constraint(expr= 0 == m.egb.outputs['Pout'] - 10*m.hout)
+ m.egb.inputs['Pin'].value = 100
+ m.egb.inputs['Pin'].setlb(50)
+ m.egb.inputs['Pin'].setub(150)
+ m.egb.inputs['c'].value = 2
+ m.egb.inputs['c'].setlb(1)
+ m.egb.inputs['c'].setub(5)
+ m.egb.inputs['F'].value = 3
+ m.egb.inputs['F'].setlb(1)
+ m.egb.inputs['F'].setub(5)
+ m.egb.inputs['P1'].value = 80
+ m.egb.inputs['P1'].setlb(10)
+ m.egb.inputs['P1'].setub(90)
+ m.egb.inputs['P3'].value = 70
+ m.egb.inputs['P3'].setlb(20)
+ m.egb.inputs['P3'].setub(80)
+ m.egb.outputs['P2'].value = 75
+ m.egb.outputs['P2'].setlb(15)
+ m.egb.outputs['P2'].setub(85)
+ m.egb.outputs['Pout'].value = 50
+ m.egb.outputs['Pout'].setlb(30)
+ m.egb.outputs['Pout'].setub(70)
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ self.assertEqual(9, pyomo_nlp.n_primals())
+ self.assertEqual(6, pyomo_nlp.n_constraints())
+ self.assertEqual(20, pyomo_nlp.nnz_jacobian())
+ with self.assertRaises(NotImplementedError):
+ tmp = pyomo_nlp.nnz_hessian_lag()
+
+ comparison_x_order = ['egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[F]',
+ 'egb.inputs[P1]', 'egb.inputs[P3]',
+ 'egb.outputs[P2]', 'egb.outputs[Pout]',
+ 'hin', 'hout']
+ x_order = pyomo_nlp.variable_names()
+ comparison_c_order = ['egb.pdrop1', 'egb.pdrop3', 'egb.P2_con', 'egb.Pout_con', 'incon', 'outcon']
+ c_order = pyomo_nlp.constraint_names()
+
+ xlb = pyomo_nlp.primals_lb()
+ comparison_xlb = np.asarray([50, 1, 1, 10, 20, 15, 30, 0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, xlb, x_order, comparison_xlb, comparison_x_order)
+ xub = pyomo_nlp.primals_ub()
+ comparison_xub = np.asarray([150, 5, 5, 90, 80, 85, 70, np.inf, np.inf], dtype=np.float64)
+ check_vectors_specific_order(self, xub, x_order, comparison_xub, comparison_x_order)
+ clb = pyomo_nlp.constraints_lb()
+ comparison_clb = np.asarray([0, 0, 0, 0, 0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, clb, c_order, comparison_clb, comparison_c_order)
+ cub = pyomo_nlp.constraints_ub()
+ comparison_cub = np.asarray([0, 0, 0, 0, np.inf, 0], dtype=np.float64)
+ check_vectors_specific_order(self, cub, c_order, comparison_cub, comparison_c_order)
+
+ xinit = pyomo_nlp.init_primals()
+ comparison_xinit = np.asarray([100, 2, 3, 80, 70, 75, 50, 10, 0], dtype=np.float64)
+ check_vectors_specific_order(self, xinit, x_order, comparison_xinit, comparison_x_order)
+ duals_init = pyomo_nlp.init_duals()
+ comparison_duals_init = np.asarray([1, 1, 1, 1, 0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, duals_init, c_order, comparison_duals_init, comparison_c_order)
+
+ self.assertEqual(9, len(pyomo_nlp.create_new_vector('primals')))
+ self.assertEqual(6, len(pyomo_nlp.create_new_vector('constraints')))
+ self.assertEqual(6, len(pyomo_nlp.create_new_vector('duals')))
+ self.assertEqual(5, len(pyomo_nlp.create_new_vector('eq_constraints')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('ineq_constraints')))
+ self.assertEqual(5, len(pyomo_nlp.create_new_vector('duals_eq')))
+ self.assertEqual(1, len(pyomo_nlp.create_new_vector('duals_ineq')))
+
+ pyomo_nlp.set_primals(np.asarray([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=np.float64))
+ x = pyomo_nlp.get_primals()
+ self.assertTrue(np.array_equal(x, np.asarray([1,2,3,4,5,6,7,8,9], dtype=np.float64)))
+ pyomo_nlp.set_primals(pyomo_nlp.init_primals())
+
+ pyomo_nlp.set_duals(np.asarray([42, 10, 11, 12, 13, 14], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([42, 10, 11, 12, 13, 14], dtype=np.float64)))
+ pyomo_nlp.set_duals(np.asarray([1, 1, 1, 1, 0, 0], dtype=np.float64))
+ y = pyomo_nlp.get_duals()
+ self.assertTrue(np.array_equal(y, np.asarray([1, 1, 1, 1, 0, 0], dtype=np.float64)))
+
+ fac = pyomo_nlp.get_obj_factor()
+ self.assertEqual(fac, 1)
+ pyomo_nlp.set_obj_factor(42)
+ self.assertEqual(pyomo_nlp.get_obj_factor(), 42)
+ pyomo_nlp.set_obj_factor(1)
+
+ f = pyomo_nlp.evaluate_objective()
+ self.assertEqual(f, 900)
+
+ gradf = pyomo_nlp.evaluate_grad_objective()
+ comparison_gradf = np.asarray([0, 0, 0, 0, 0, 0, 60, 0, 0], dtype=np.float64)
+ check_vectors_specific_order(self, gradf, x_order, comparison_gradf, comparison_x_order)
+ c = pyomo_nlp.evaluate_constraints()
+ comparison_c = np.asarray([-2, 26, -13, -22, 0, 50], dtype=np.float64)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+ c = np.zeros(6)
+ pyomo_nlp.evaluate_constraints(out=c)
+ check_vectors_specific_order(self, c, c_order, comparison_c, comparison_c_order)
+
+ j = pyomo_nlp.evaluate_jacobian()
+ comparison_j = np.asarray([[-1, 9, 12, 1, 0, 0, 0, 0, 0],
+ [ 0, 18, 24, -1, 1, 0, 0, 0, 0],
+ [ 0, -9, -12, 1, 0, -1, 0, 0, 0],
+ [ 1, -36, -48, 0, 0, 0, -1, 0, 0],
+ [ 1, 0, 0, 0, 0, 0, 0, -10, 0],
+ [ 0, 0, 0, 0, 0, 0, 1, 0, -10]])
+
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ j = 2.0*j
+ pyomo_nlp.evaluate_jacobian(out=j)
+ check_sparse_matrix_specific_order(self, j, c_order, x_order, comparison_j, comparison_c_order, comparison_x_order)
+
+ with self.assertRaises(NotImplementedError):
+ h = pyomo_nlp.evaluate_hessian_lag()
+
+ @unittest.skipIf(not ipopt_available, "CyIpopt needed to run tests with solve")
+ def test_external_greybox_solve(self):
+ m = pyo.ConcreteModel()
+ m.mu = pyo.Var(bounds=(0,None), initialize=1)
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropTwoEqualitiesTwoOutputs())
+ m.ccon = pyo.Constraint(expr = m.egb.inputs['c'] == 128/(3.14*1e-4)*m.mu*m.egb.inputs['F'])
+ m.pcon = pyo.Constraint(expr = m.egb.inputs['Pin'] - m.egb.outputs['Pout'] <= 72)
+ m.pincon = pyo.Constraint(expr = m.egb.inputs['Pin'] == 100.0)
+ m.egb.inputs['Pin'].value = 100
+ m.egb.inputs['Pin'].setlb(50)
+ m.egb.inputs['Pin'].setub(150)
+ m.egb.inputs['c'].value = 2
+ m.egb.inputs['c'].setlb(1)
+ m.egb.inputs['c'].setub(5)
+ m.egb.inputs['F'].value = 3
+ m.egb.inputs['F'].setlb(1)
+ m.egb.inputs['F'].setub(5)
+ m.egb.inputs['P1'].value = 80
+ m.egb.inputs['P1'].setlb(10)
+ m.egb.inputs['P1'].setub(90)
+ m.egb.inputs['P3'].value = 70
+ m.egb.inputs['P3'].setlb(20)
+ m.egb.inputs['P3'].setub(80)
+ m.egb.outputs['P2'].value = 75
+ m.egb.outputs['P2'].setlb(15)
+ m.egb.outputs['P2'].setub(85)
+ m.egb.outputs['Pout'].value = 50
+ m.egb.outputs['Pout'].setlb(10)
+ m.egb.outputs['Pout'].setub(70)
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2 + (m.egb.inputs['F']-3)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ options = {'hessian_approximation':'limited-memory'}
+ cyipopt_problem = CyIpoptNLP(pyomo_nlp)
+ solver = CyIpoptSolver(cyipopt_problem, options)
+ x, info = solver.solve(tee=False)
+ pyomo_nlp.set_primals(x)
+ pyomo_nlp.load_state_into_pyomo()
+
+ self.assertAlmostEqual(pyo.value(m.egb.inputs['F']), 3.0, places=3)
+ self.assertAlmostEqual(pyo.value(m.mu), 1.63542e-6, places=3)
+ self.assertAlmostEqual(pyo.value(m.egb.outputs['Pout']), 28.0, places=3)
+ self.assertAlmostEqual(pyo.value(m.egb.inputs['Pin']), 100.0, places=3)
+ self.assertAlmostEqual(pyo.value(m.egb.inputs['c']), 2.0, places=3)
+ self.assertAlmostEqual(pyo.value(m.egb.inputs['P1']), 82.0, places=3)
+ self.assertAlmostEqual(pyo.value(m.egb.inputs['P3']), 46.0, places=3)
+ self.assertAlmostEqual(pyo.value(m.egb.outputs['P2']), 64.0, places=3)
+ self.assertAlmostEqual(pyo.value(m.egb.inputs['F']), 3.0, places=3)
+
+ def create_model_two_equalities_two_outputs(self, external_model):
+ m = pyo.ConcreteModel()
+ m.hin = pyo.Var(bounds=(0,None), initialize=10)
+ m.hout = pyo.Var(bounds=(0,None))
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(external_model)
+ m.incon = pyo.Constraint(expr= 0 <= m.egb.inputs['Pin'] - 10*m.hin)
+ m.outcon = pyo.Constraint(expr= 0 == m.egb.outputs['Pout'] - 10*m.hout)
+ m.egb.inputs['Pin'].value = 100
+ m.egb.inputs['Pin'].setlb(50)
+ m.egb.inputs['Pin'].setub(150)
+ m.egb.inputs['c'].value = 2
+ m.egb.inputs['c'].setlb(1)
+ m.egb.inputs['c'].setub(5)
+ m.egb.inputs['F'].value = 3
+ m.egb.inputs['F'].setlb(1)
+ m.egb.inputs['F'].setub(5)
+ m.egb.inputs['P1'].value = 80
+ m.egb.inputs['P1'].setlb(10)
+ m.egb.inputs['P1'].setub(90)
+ m.egb.inputs['P3'].value = 70
+ m.egb.inputs['P3'].setlb(20)
+ m.egb.inputs['P3'].setub(80)
+ m.egb.outputs['P2'].value = 75
+ m.egb.outputs['P2'].setlb(15)
+ m.egb.outputs['P2'].setub(85)
+ m.egb.outputs['Pout'].value = 50
+ m.egb.outputs['Pout'].setlb(30)
+ m.egb.outputs['Pout'].setub(70)
+ return m
+
+ def test_scaling_all_missing(self):
+ m = self.create_model_two_equalities_two_outputs(PressureDropTwoEqualitiesTwoOutputs())
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+ fs = pyomo_nlp.get_obj_scaling()
+ xs = pyomo_nlp.get_primals_scaling()
+ cs = pyomo_nlp.get_constraints_scaling()
+ self.assertIsNone(fs)
+ self.assertIsNone(xs)
+ self.assertIsNone(cs)
+
+ def test_scaling_pyomo_model_only(self):
+ m = self.create_model_two_equalities_two_outputs(PressureDropTwoEqualitiesTwoOutputs())
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT)
+ #m.scaling_factor[m.obj] = 0.1 # scale the objective
+ m.scaling_factor[m.egb.inputs['Pin']] = 1.1 # scale the variable
+ m.scaling_factor[m.egb.inputs['c']] = 1.2 # scale the variable
+ m.scaling_factor[m.egb.inputs['F']] = 1.3 # scale the variable
+ #m.scaling_factor[m.egb.inputs['P1']] = 1.4 # scale the variable
+ m.scaling_factor[m.egb.inputs['P3']] = 1.5 # scale the variable
+ m.scaling_factor[m.egb.outputs['P2']] = 1.6 # scale the variable
+ m.scaling_factor[m.egb.outputs['Pout']] = 1.7 # scale the variable
+ #m.scaling_factor[m.hin] = 1.8
+ m.scaling_factor[m.hout] = 1.9
+ #m.scaling_factor[m.incon] = 2.1
+ m.scaling_factor[m.outcon] = 2.2
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ comparison_x_order = ['egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[F]',
+ 'egb.inputs[P1]', 'egb.inputs[P3]',
+ 'egb.outputs[P2]', 'egb.outputs[Pout]',
+ 'hin', 'hout']
+ x_order = pyomo_nlp.variable_names()
+ comparison_c_order = ['egb.pdrop1', 'egb.pdrop3', 'egb.P2_con', 'egb.Pout_con', 'incon', 'outcon']
+ c_order = pyomo_nlp.constraint_names()
+
+ fs = pyomo_nlp.get_obj_scaling()
+ self.assertEqual(fs, 1.0)
+
+ xs = pyomo_nlp.get_primals_scaling()
+ comparison_xs = np.asarray([1.1, 1.2, 1.3, 1.0, 1.5, 1.6, 1.7, 1.0, 1.9], dtype=np.float64)
+ check_vectors_specific_order(self, xs, x_order, comparison_xs, comparison_x_order)
+
+ cs = pyomo_nlp.get_constraints_scaling()
+ comparison_cs = np.asarray([1, 1, 1, 1, 1, 2.2], dtype=np.float64)
+ check_vectors_specific_order(self, cs, c_order, comparison_cs, comparison_c_order)
+
+ def test_scaling_greybox_only(self):
+ m = self.create_model_two_equalities_two_outputs(PressureDropTwoEqualitiesTwoOutputsScaleBoth())
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ comparison_x_order = ['egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[F]',
+ 'egb.inputs[P1]', 'egb.inputs[P3]',
+ 'egb.outputs[P2]', 'egb.outputs[Pout]',
+ 'hin', 'hout']
+ x_order = pyomo_nlp.variable_names()
+ comparison_c_order = ['egb.pdrop1', 'egb.pdrop3', 'egb.P2_con', 'egb.Pout_con', 'incon', 'outcon']
+ c_order = pyomo_nlp.constraint_names()
+
+ fs = pyomo_nlp.get_obj_scaling()
+ self.assertEqual(fs, 1.0)
+
+ xs = pyomo_nlp.get_primals_scaling()
+ comparison_xs = np.asarray([1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=np.float64)
+ check_vectors_specific_order(self, xs, x_order, comparison_xs, comparison_x_order)
+
+ cs = pyomo_nlp.get_constraints_scaling()
+ comparison_cs = np.asarray([3.1, 3.2, 4.1, 4.2, 1, 1], dtype=np.float64)
+ check_vectors_specific_order(self, cs, c_order, comparison_cs, comparison_c_order)
+
+ m = self.create_model_two_equalities_two_outputs(PressureDropTwoEqualitiesTwoOutputsScaleEqualities())
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+ cs = pyomo_nlp.get_constraints_scaling()
+ comparison_cs = np.asarray([3.1, 3.2, 1, 1, 1, 1], dtype=np.float64)
+ check_vectors_specific_order(self, cs, c_order, comparison_cs, comparison_c_order)
+
+ m = self.create_model_two_equalities_two_outputs(PressureDropTwoEqualitiesTwoOutputsScaleOutputs())
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+ cs = pyomo_nlp.get_constraints_scaling()
+ comparison_cs = np.asarray([1, 1, 4.1, 4.2, 1, 1], dtype=np.float64)
+ check_vectors_specific_order(self, cs, c_order, comparison_cs, comparison_c_order)
+
+ def test_scaling_pyomo_model_and_greybox(self):
+ m = self.create_model_two_equalities_two_outputs(PressureDropTwoEqualitiesTwoOutputsScaleBoth())
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2)
+ m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT)
+ #m.scaling_factor[m.obj] = 0.1 # scale the objective
+ m.scaling_factor[m.egb.inputs['Pin']] = 1.1 # scale the variable
+ m.scaling_factor[m.egb.inputs['c']] = 1.2 # scale the variable
+ m.scaling_factor[m.egb.inputs['F']] = 1.3 # scale the variable
+ #m.scaling_factor[m.egb.inputs['P1']] = 1.4 # scale the variable
+ m.scaling_factor[m.egb.inputs['P3']] = 1.5 # scale the variable
+ m.scaling_factor[m.egb.outputs['P2']] = 1.6 # scale the variable
+ m.scaling_factor[m.egb.outputs['Pout']] = 1.7 # scale the variable
+ #m.scaling_factor[m.hin] = 1.8
+ m.scaling_factor[m.hout] = 1.9
+ #m.scaling_factor[m.incon] = 2.1
+ m.scaling_factor[m.outcon] = 2.2
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ comparison_x_order = ['egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[F]',
+ 'egb.inputs[P1]', 'egb.inputs[P3]',
+ 'egb.outputs[P2]', 'egb.outputs[Pout]',
+ 'hin', 'hout']
+ x_order = pyomo_nlp.variable_names()
+ comparison_c_order = ['egb.pdrop1', 'egb.pdrop3', 'egb.P2_con', 'egb.Pout_con', 'incon', 'outcon']
+ c_order = pyomo_nlp.constraint_names()
+
+ fs = pyomo_nlp.get_obj_scaling()
+ self.assertEqual(fs, 1.0)
+
+ xs = pyomo_nlp.get_primals_scaling()
+ comparison_xs = np.asarray([1.1, 1.2, 1.3, 1.0, 1.5, 1.6, 1.7, 1.0, 1.9], dtype=np.float64)
+ check_vectors_specific_order(self, xs, x_order, comparison_xs, comparison_x_order)
+
+ cs = pyomo_nlp.get_constraints_scaling()
+ comparison_cs = np.asarray([3.1, 3.2, 4.1, 4.2, 1, 2.2], dtype=np.float64)
+ check_vectors_specific_order(self, cs, c_order, comparison_cs, comparison_c_order)
+
+ @unittest.skipIf(not ipopt_available, "CyIpopt needed to run tests with solve")
+ def test_external_greybox_solve_scaling(self):
+ m = pyo.ConcreteModel()
+ m.mu = pyo.Var(bounds=(0,None), initialize=1)
+ m.egb = ExternalGreyBoxBlock()
+ m.egb.set_external_model(PressureDropTwoEqualitiesTwoOutputsScaleBoth())
+ m.ccon = pyo.Constraint(expr = m.egb.inputs['c'] == 128/(3.14*1e-4)*m.mu*m.egb.inputs['F'])
+ m.pcon = pyo.Constraint(expr = m.egb.inputs['Pin'] - m.egb.outputs['Pout'] <= 72)
+ m.pincon = pyo.Constraint(expr = m.egb.inputs['Pin'] == 100.0)
+ m.egb.inputs['Pin'].value = 100
+ m.egb.inputs['Pin'].setlb(50)
+ m.egb.inputs['Pin'].setub(150)
+ m.egb.inputs['c'].value = 2
+ m.egb.inputs['c'].setlb(1)
+ m.egb.inputs['c'].setub(5)
+ m.egb.inputs['F'].value = 3
+ m.egb.inputs['F'].setlb(1)
+ m.egb.inputs['F'].setub(5)
+ m.egb.inputs['P1'].value = 80
+ m.egb.inputs['P1'].setlb(10)
+ m.egb.inputs['P1'].setub(90)
+ m.egb.inputs['P3'].value = 70
+ m.egb.inputs['P3'].setlb(20)
+ m.egb.inputs['P3'].setub(80)
+ m.egb.outputs['P2'].value = 75
+ m.egb.outputs['P2'].setlb(15)
+ m.egb.outputs['P2'].setub(85)
+ m.egb.outputs['Pout'].value = 50
+ m.egb.outputs['Pout'].setlb(10)
+ m.egb.outputs['Pout'].setub(70)
+ m.obj = pyo.Objective(expr=(m.egb.outputs['Pout']-20)**2 + (m.egb.inputs['F']-3)**2)
+
+ m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT)
+ m.scaling_factor[m.obj] = 0.1 # scale the objective
+ m.scaling_factor[m.egb.inputs['Pin']] = 1.1 # scale the variable
+ m.scaling_factor[m.egb.inputs['c']] = 1.2 # scale the variable
+ m.scaling_factor[m.egb.inputs['F']] = 1.3 # scale the variable
+ #m.scaling_factor[m.egb.inputs['P1']] = 1.4 # scale the variable
+ m.scaling_factor[m.egb.inputs['P3']] = 1.5 # scale the variable
+ m.scaling_factor[m.egb.outputs['P2']] = 1.6 # scale the variable
+ m.scaling_factor[m.egb.outputs['Pout']] = 1.7 # scale the variable
+ m.scaling_factor[m.mu] = 1.9
+ m.scaling_factor[m.pincon] = 2.2
+ pyomo_nlp = PyomoGreyBoxNLP(m)
+
+ options={'hessian_approximation':'limited-memory',
+ 'nlp_scaling_method': 'user-scaling',
+ 'output_file': '_cyipopt-external-greybox-scaling.log',
+ 'file_print_level':10,
+ 'max_iter': 0}
+ cyipopt_problem = CyIpoptNLP(pyomo_nlp)
+ solver = CyIpoptSolver(cyipopt_problem, options)
+ x, info = solver.solve(tee=False)
+
+ with open('_cyipopt-external-greybox-scaling.log', 'r') as fd:
+ solver_trace = fd.read()
+ #os.remove('_cyipopt-external-greybox-scaling.log')
+
+ self.assertIn('nlp_scaling_method = user-scaling', solver_trace)
+ self.assertIn('output_file = _cyipopt-external-greybox-scaling.log', solver_trace)
+ self.assertIn('objective scaling factor = 0.1', solver_trace)
+ self.assertIn('x scaling provided', solver_trace)
+ self.assertIn('c scaling provided', solver_trace)
+ self.assertIn('d scaling provided', solver_trace)
+ # x order: ['egb.inputs[F]', 'mu', 'egb.outputs[Pout]', 'egb.inputs[Pin]', 'egb.inputs[c]', 'egb.inputs[P1]', 'egb.inputs[P3]', 'egb.outputs[P2]']
+ # c order: ['ccon', 'pcon', 'pincon', 'egb.pdrop1', 'egb.pdrop3', 'egb.P2_con', 'egb.Pout_con']
+ self.assertIn('DenseVector "x scaling vector" with 8 elements:', solver_trace)
+ self.assertIn('x scaling vector[ 1]= 1.3000000000000000e+00', solver_trace) # F
+ self.assertIn('x scaling vector[ 2]= 1.8999999999999999e+00', solver_trace) # mu
+ self.assertIn('x scaling vector[ 3]= 1.7000000000000000e+00', solver_trace) # Pout
+ self.assertIn('x scaling vector[ 4]= 1.1000000000000001e+00', solver_trace) # Pin
+ self.assertIn('x scaling vector[ 5]= 1.2000000000000000e+00', solver_trace) # c
+ self.assertIn('x scaling vector[ 6]= 1.0000000000000000e+00', solver_trace) # P1
+ self.assertIn('x scaling vector[ 7]= 1.5000000000000000e+00', solver_trace) # P3
+ self.assertIn('x scaling vector[ 8]= 1.6000000000000001e+00', solver_trace) # P2
+ self.assertIn('DenseVector "c scaling vector" with 6 elements:', solver_trace)
+ self.assertIn('c scaling vector[ 1]= 1.0000000000000000e+00', solver_trace) # ccon
+ self.assertIn('c scaling vector[ 2]= 2.2000000000000002e+00', solver_trace) # pincon
+ self.assertIn('c scaling vector[ 3]= 3.1000000000000001e+00', solver_trace) # pdrop1
+ self.assertIn('c scaling vector[ 4]= 3.2000000000000002e+00', solver_trace) # pdrop3
+ self.assertIn('c scaling vector[ 5]= 4.0999999999999996e+00', solver_trace) # P2_con
+ self.assertIn('c scaling vector[ 6]= 4.2000000000000002e+00', solver_trace) # Pout_con
+ self.assertIn('DenseVector "d scaling vector" with 1 elements:', solver_trace)
+ self.assertIn('d scaling vector[ 1]= 1.0000000000000000e+00', solver_trace) # pcon
+
+def check_vectors_specific_order(tst, v1, v1order, v2, v2order):
+ tst.assertEqual(len(v1), len(v1order))
+ tst.assertEqual(len(v2), len(v2order))
+ tst.assertEqual(len(v1), len(v2))
+ v2map = {s:i for i,s in enumerate(v2order)}
+ for i,s in enumerate(v1order):
+ tst.assertEqual(v1[i], v2[v2map[s]])
+
+def check_sparse_matrix_specific_order(tst, m1, m1rows, m1cols, m2, m2rows, m2cols):
+ tst.assertEqual(m1.shape[0], len(m1rows))
+ tst.assertEqual(m1.shape[1], len(m1cols))
+ tst.assertEqual(m2.shape[0], len(m2rows))
+ tst.assertEqual(m2.shape[1], len(m2cols))
+ tst.assertEqual(len(m1rows), len(m2rows))
+ tst.assertEqual(len(m1cols), len(m2cols))
+
+ m1c = m1.todense()
+ m2c = np.zeros((len(m2rows), len(m2cols)))
+ rowmap = [m2rows.index(x) for x in m1rows]
+ colmap = [m2cols.index(x) for x in m1cols]
+ for i in range(len(m1rows)):
+ for j in range(len(m1cols)):
+ m2c[i,j] = m2[rowmap[i], colmap[j]]
+
+ #print(m1c)
+ #print(m2c)
+ tst.assertTrue(np.array_equal(m1c, m2c))
+
+if __name__ == '__main__':
+ TestPyomoGreyBoxNLP().test_external_greybox_solve(self)
diff --git a/pyomo/contrib/pynumero/interfaces/tests/test_nlp.py b/pyomo/contrib/pynumero/interfaces/tests/test_nlp.py
index 70bc4d8d07d..9f409e4e081 100644
--- a/pyomo/contrib/pynumero/interfaces/tests/test_nlp.py
+++ b/pyomo/contrib/pynumero/interfaces/tests/test_nlp.py
@@ -7,6 +7,7 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
import pyutilib.th as unittest
import os
@@ -22,16 +23,14 @@
"Pynumero needs the ASL extension to run NLP tests")
import pyomo.environ as pyo
-from pyomo.opt.base import WriterFactory
from pyomo.contrib.pynumero.interfaces.ampl_nlp import AslNLP, AmplNLP
from pyomo.contrib.pynumero.interfaces.pyomo_nlp import PyomoNLP
import tempfile
-from scipy.sparse import coo_matrix
-
from pyomo.contrib.pynumero.interfaces.utils import build_bounds_mask, build_compression_matrix, \
build_compression_mask_for_finite_values, full_to_compressed, compressed_to_full
+
def create_pyomo_model1():
m = pyo.ConcreteModel()
m.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT_EXPORT)
diff --git a/pyomo/contrib/pynumero/intrinsic.py b/pyomo/contrib/pynumero/intrinsic.py
index 062d48f7c71..b1ecfb286fa 100644
--- a/pyomo/contrib/pynumero/intrinsic.py
+++ b/pyomo/contrib/pynumero/intrinsic.py
@@ -18,7 +18,7 @@ def norm(x, ord=None):
f = np.linalg.norm
if isinstance(x, np.ndarray):
return f(x, ord=ord)
- elif isinstance(x, BlockVector):
+ elif isinstance(x, block_vector.BlockVector):
flat_x = x.flatten()
return f(flat_x, ord=ord)
else:
diff --git a/pyomo/contrib/pynumero/linalg/ma57.py b/pyomo/contrib/pynumero/linalg/ma57.py
index 26a13e092f6..9b633505cec 100644
--- a/pyomo/contrib/pynumero/linalg/ma57.py
+++ b/pyomo/contrib/pynumero/linalg/ma57.py
@@ -7,13 +7,13 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
from pyomo.common.fileutils import find_library
from pyomo.contrib.pynumero.linalg.utils import (validate_index,
validate_value, _NotSet)
import numpy.ctypeslib as npct
import numpy as np
import ctypes
-import sys
import os
class MA57Interface(object):
diff --git a/pyomo/contrib/pynumero/linalg/tests/test_ma27.py b/pyomo/contrib/pynumero/linalg/tests/test_ma27.py
index 7f831b67dae..78844dc3415 100644
--- a/pyomo/contrib/pynumero/linalg/tests/test_ma27.py
+++ b/pyomo/contrib/pynumero/linalg/tests/test_ma27.py
@@ -11,7 +11,8 @@
from pyomo.contrib.pynumero.dependencies import numpy as np, numpy_available
if not numpy_available:
raise unittest.SkipTest('pynumero MA27 tests require numpy')
-from pyomo.contrib.pynumero.linalg.ma27 import *
+import ctypes
+from pyomo.contrib.pynumero.linalg.ma27 import MA27Interface
@unittest.skipIf(not MA27Interface.available(), reason='MA27 not available')
diff --git a/pyomo/contrib/pynumero/linalg/tests/test_ma57.py b/pyomo/contrib/pynumero/linalg/tests/test_ma57.py
index 61def1b91b4..4569f6c5133 100644
--- a/pyomo/contrib/pynumero/linalg/tests/test_ma57.py
+++ b/pyomo/contrib/pynumero/linalg/tests/test_ma57.py
@@ -12,7 +12,7 @@
from pyomo.contrib.pynumero.dependencies import numpy as np, numpy_available
if not numpy_available:
raise unittest.SkipTest('pynumero MA27 tests require numpy')
-from pyomo.contrib.pynumero.linalg.ma57 import *
+from pyomo.contrib.pynumero.linalg.ma57 import MA57Interface
@unittest.skipIf(not MA57Interface.available(), reason='MA57 not available')
diff --git a/pyomo/contrib/pynumero/plugins.py b/pyomo/contrib/pynumero/plugins.py
index 9f7944b74e2..ae74c755900 100644
--- a/pyomo/contrib/pynumero/plugins.py
+++ b/pyomo/contrib/pynumero/plugins.py
@@ -9,8 +9,13 @@
# ___________________________________________________________________________
from pyomo.common.extensions import ExtensionBuilderFactory
+from pyomo.opt import SolverFactory
from .build import PyNumeroBuilder
+from .algorithms.solvers.cyipopt_solver import PyomoCyIpoptSolver
def load():
ExtensionBuilderFactory.register('pynumero')(PyNumeroBuilder)
-
+ SolverFactory.register(
+ 'cyipopt',
+ doc='Cyipopt: direct python bindings to the Ipopt NLP solver'
+ )(PyomoCyIpoptSolver)
diff --git a/pyomo/contrib/pynumero/sparse/base_block.py b/pyomo/contrib/pynumero/sparse/base_block.py
index 36bd46cd01f..37dc7684671 100644
--- a/pyomo/contrib/pynumero/sparse/base_block.py
+++ b/pyomo/contrib/pynumero/sparse/base_block.py
@@ -8,9 +8,6 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import abc
-import six
-
# These classes are for checking types consistently and raising errors
@@ -172,10 +169,10 @@ def setdiag(self, values, k=0):
msg = "setdiag not implemented for {}".format(self.__class__.__name__)
raise NotImplementedError(msg)
- def transpose(*axes):
+ def transpose(self, *axes):
msg = "transpose not implemented for {}".format(self.__class__.__name__)
raise NotImplementedError(msg)
- def tostring(order='C'):
+ def tostring(self, order='C'):
msg = "tostring not implemented for {}".format(self.__class__.__name__)
raise NotImplementedError(msg)
diff --git a/pyomo/contrib/pynumero/sparse/block_matrix.py b/pyomo/contrib/pynumero/sparse/block_matrix.py
index 6d76d19a3f3..e3b873db275 100644
--- a/pyomo/contrib/pynumero/sparse/block_matrix.py
+++ b/pyomo/contrib/pynumero/sparse/block_matrix.py
@@ -21,17 +21,13 @@
"""
-from scipy.sparse.sputils import upcast, isscalarlike, get_index_dtype
+from scipy.sparse.sputils import get_index_dtype
from pyomo.contrib.pynumero.sparse.block_vector import BlockVector
from scipy.sparse import coo_matrix, csr_matrix, csc_matrix
from scipy.sparse import isspmatrix
-from pyomo.contrib.pynumero.sparse.utils import is_symmetric_sparse
from .base_block import BaseBlockMatrix
-from scipy.sparse.base import spmatrix
import operator
import numpy as np
-import six
-import abc
import logging
import warnings
@@ -143,7 +139,10 @@ def dtype(self):
Returns data type of the matrix.
"""
all_dtypes = [blk.dtype for blk in self._blocks[self._block_mask]]
- ref_dtype = all_dtypes[0]
+ if len(all_dtypes) == 0:
+ ref_dtype = np.double
+ else:
+ ref_dtype = all_dtypes[0]
if all(ref_dtype is i for i in all_dtypes):
return ref_dtype
else:
@@ -268,6 +267,12 @@ def block_shapes(self):
sizes[i].append(shape)
return sizes
+ def get_block_mask(self, copy=True):
+ if copy:
+ return self._block_mask.copy()
+ else:
+ return self._block_mask
+
def dot(self, other):
"""
Ordinary dot product
@@ -824,10 +829,8 @@ def __setitem__(self, item, val):
raise NotImplementedError('BlockMatrix does not support __setitem__. '
'Use get_block or set_block to access sub-blocks.')
- def __add__(self, other):
-
+ def _binary_operation_helper(self, other, operation):
assert_block_structure(self)
-
result = BlockMatrix(self.bshape[0], self.bshape[1])
if isinstance(other, BlockMatrix):
@@ -837,71 +840,40 @@ def __add__(self, other):
'dimensions mismatch {} != {}'.format(self.shape, other.shape)
assert_block_structure(other)
- iterator = set(zip(*np.nonzero(self._block_mask)))
- iterator.update(zip(*np.nonzero(other._block_mask)))
- for i, j in iterator:
- if not self.is_empty_block(i, j) and not other.is_empty_block(i, j):
- result.set_block(i, j, self._blocks[i, j] + other.get_block(i, j))
- elif not self.is_empty_block(i, j):
- result.set_block(i, j, self._blocks[i, j].copy())
- elif not other.is_empty_block(i, j):
- result.set_block(i, j, other.get_block(i, j).copy())
+ block_indices = np.bitwise_or(self.get_block_mask(copy=False), other.get_block_mask(copy=False))
+ for i, j in zip(*np.nonzero(block_indices)):
+ mat1 = self.get_block(i, j)
+ mat2 = other.get_block(i, j)
+ if mat1 is not None and mat2 is not None:
+ result.set_block(i, j, operation(mat1, mat2))
+ elif mat1 is not None:
+ result.set_block(i, j, operation(mat1, 0))
+ elif mat2 is not None:
+ result.set_block(i, j, operation(0, mat2))
return result
elif isspmatrix(other):
# Note: this is not efficient but is just for flexibility.
mat = self.copy_structure()
mat.copyfrom(other)
- return self.__add__(mat)
+ return operation(self, mat)
+ elif np.isscalar(other):
+ for i, j in zip(*np.nonzero(self.get_block_mask(copy=False))):
+ result.set_block(i, j, operation(self.get_block(i, j), other))
+ return result
else:
- if other.__class__.__name__ == 'MPIBlockMatrix':
- raise RuntimeError('Operation not supported by BlockMatrix')
+ return NotImplemented
- raise NotImplementedError('Operation not supported by BlockMatrix')
+ def __add__(self, other):
+ return self._binary_operation_helper(other, operator.add)
def __radd__(self, other):
- return self.__add__(other)
+ return self._binary_operation_helper(other, operator.add)
def __sub__(self, other):
-
- assert_block_structure(self)
- result = BlockMatrix(self.bshape[0], self.bshape[1])
-
- if isinstance(other, BlockMatrix):
- assert other.bshape == self.bshape, \
- 'dimensions mismatch {} != {}'.format(self.bshape, other.bshape)
- assert other.shape == self.shape, \
- 'dimensions mismatch {} != {}'.format(self.shape, other.shape)
- assert_block_structure(other)
- iterator = set(zip(*np.nonzero(self._block_mask)))
- iterator.update(zip(*np.nonzero(other._block_mask)))
- for i, j in iterator:
- if not self.is_empty_block(i, j) and not other.is_empty_block(i, j):
- result.set_block(i, j, self._blocks[i, j] - other.get_block(i, j))
- elif not self.is_empty_block(i, j):
- result.set_block(i, j, self._blocks[i, j].copy())
- elif not other.is_empty_block(i, j):
- result.set_block(i, j, -other.get_block(i, j))
- return result
- elif isspmatrix(other):
- # Note: this is not efficient but is just for flexibility.
- mat = self.copy_structure()
- mat.copyfrom(other)
- return self.__sub__(mat)
- else:
- if other.__class__.__name__ == 'MPIBlockMatrix':
- raise RuntimeError('Operation not supported by BlockMatrix')
- raise NotImplementedError('Operation not supported by BlockMatrix')
+ return self._binary_operation_helper(other, operator.sub)
def __rsub__(self, other):
- assert_block_structure(self)
- result = BlockMatrix(self.bshape[0], self.bshape[1])
- if isspmatrix(other):
- # Note: this is not efficient but is just for flexibility.
- mat = self.copy_structure()
- mat.copyfrom(other)
- return mat - self
- else:
- raise NotImplementedError('Operation not supported by BlockMatrix')
+ return (-self) + other
def __mul__(self, other):
"""
@@ -912,11 +884,7 @@ def __mul__(self, other):
bm, bn = self.bshape
if np.isscalar(other):
- result = BlockMatrix(bm, bn)
- ii, jj = np.nonzero(self._block_mask)
- for i, j in zip(ii, jj):
- result.set_block(i, j, self._blocks[i, j] * other)
- return result
+ return self._binary_operation_helper(other, operator.mul)
elif isinstance(other, BlockVector):
assert bn == other.bshape[0], 'Dimension mismatch'
assert self.shape[1] == other.shape[0], 'Dimension mismatch'
@@ -927,14 +895,13 @@ def __mul__(self, other):
result = BlockVector(nblocks)
for i in range(bm):
result.set_block(i, np.zeros(self._brow_lengths[i]))
- for j in range(bn):
- if not self.is_empty_block(i, j):
- x = other.get_block(j)
- A = self._blocks[i, j]
- blk = result.get_block(i)
- _tmp = A*x
- _tmp += blk
- result.set_block(i, _tmp)
+ for i, j in zip(*np.nonzero(self._block_mask)):
+ x = other.get_block(j)
+ A = self._blocks[i, j]
+ blk = result.get_block(i)
+ _tmp = A*x
+ _tmp += blk
+ result.set_block(i, _tmp)
return result
elif isinstance(other, np.ndarray):
@@ -957,23 +924,18 @@ def __mul__(self, other):
x = other[counter: counter + A.shape[1]]
blk = result.get_block(i)
blk += A * x
- counter += A.shape[0]
+ counter += self.get_col_size(j)
return result
elif isinstance(other, BlockMatrix) or isspmatrix(other):
assert_block_structure(self)
return self._mul_sparse_matrix(other)
else:
- raise NotImplementedError('input not recognized for multiplication')
+ return NotImplemented
def __truediv__(self, other):
- bm, bn = self.bshape
if np.isscalar(other):
- result = BlockMatrix(bm, bn)
- ii, jj = np.nonzero(self._block_mask)
- for i, j in zip(ii, jj):
- result.set_block(i, j, self._blocks[i, j] / other)
- return result
- raise NotImplementedError('Operation not supported by BlockMatrix')
+ return self._binary_operation_helper(other, operator.truediv)
+ return NotImplemented
def __rtruediv__(self, other):
raise NotImplementedError('Operation not supported by BlockMatrix')
diff --git a/pyomo/contrib/pynumero/sparse/block_vector.py b/pyomo/contrib/pynumero/sparse/block_vector.py
index 410c51f97aa..d3b24a5a02c 100644
--- a/pyomo/contrib/pynumero/sparse/block_vector.py
+++ b/pyomo/contrib/pynumero/sparse/block_vector.py
@@ -1387,7 +1387,6 @@ def toMPIBlockVector(self, rank_ownership, mpi_comm):
# populate blocks in the right spaces
for bid in mpi_bv.owned_blocks:
mpi_bv.set_block(bid, self.get_block(bid))
- mpi_bv.broadcast_block_sizes()
return mpi_bv
diff --git a/pyomo/contrib/pynumero/sparse/mpi_block_matrix.py b/pyomo/contrib/pynumero/sparse/mpi_block_matrix.py
index 954c0ba0411..5b57af17952 100644
--- a/pyomo/contrib/pynumero/sparse/mpi_block_matrix.py
+++ b/pyomo/contrib/pynumero/sparse/mpi_block_matrix.py
@@ -22,13 +22,10 @@
"""
from .mpi_block_vector import MPIBlockVector
-from .mpi_block_vector import assert_block_structure as mpi_block_vector_assert_block_structure
from .block_vector import BlockVector
-from .block_vector import assert_block_structure as block_vector_assert_block_structure
from .block_matrix import BlockMatrix, NotFullyDefinedBlockMatrixError
from .block_matrix import assert_block_structure as block_matrix_assert_block_structure
from .base_block import BaseBlockMatrix
-from warnings import warn
from mpi4py import MPI
import numpy as np
from scipy.sparse import coo_matrix
@@ -36,16 +33,10 @@
__all__ = ['MPIBlockMatrix']
-# Array classifiers
-SINGLE_OWNER = 1
-MULTIPLE_OWNER = 2
-ALL_OWN_IT = 0
-
-
-# ALL_OWNED = -1
-
def assert_block_structure(mat):
+ if mat.has_undefined_row_sizes() or mat.has_undefined_col_sizes():
+ mat.broadcast_block_sizes()
if mat.has_undefined_row_sizes() or mat.has_undefined_col_sizes():
msg = 'Call MPIBlockMatrix.broadcast_block_sizes() first. '
raise NotFullyDefinedBlockMatrixError(msg)
@@ -62,7 +53,7 @@ class MPIBlockMatrix(BaseBlockMatrix):
single processor or by all processors. Blocks own by all processors have
ownership -1. Blocks own by a single processor have ownership rank. where
rank=MPI.COMM_WORLD.Get_rank()
- _mpiw: MPI communicator
+ _mpiw: MPI.Comm
A communicator from the MPI space. Typically MPI.COMM_WORLD
_block_matrix: BlockMatrix
Internal BlockMatrix. Blocks that belong to this processor are stored
@@ -146,6 +137,7 @@ def shape(self):
"""
Returns tuple with total number of rows and columns
"""
+ assert_block_structure(self)
return self._block_matrix.shape
@property
@@ -230,6 +222,9 @@ def is_row_size_defined(self, row):
def is_col_size_defined(self, col):
return self._block_matrix.is_col_size_defined(col)
+ def get_block_mask(self, copy=True):
+ return self._block_matrix.get_block_mask(copy=copy)
+
@property
def T(self):
"""
@@ -269,7 +264,6 @@ def transpose(self, axes=None, copy=True):
m = self.bshape[0]
n = self.bshape[1]
- assert_block_structure(self)
result = MPIBlockMatrix(n, m, self._rank_owner.T, self._mpiw)
result._block_matrix = self._block_matrix.transpose()
return result
@@ -340,6 +334,7 @@ def to_local_array(self):
-------
result: np.ndarray
"""
+ assert_block_structure(self)
local_result = self._block_matrix.copy_structure()
rank = self._mpiw.Get_rank()
block_indices = self._unique_owned_mask if rank != 0 else self._owned_mask
@@ -349,7 +344,7 @@ def to_local_array(self):
if not self._block_matrix.is_empty_block(i, j):
local_result.set_block(i, j, self.get_block(i, j))
local_result = local_result.toarray()
- global_result = np.zeros(shape=local_result.shape, dtype=local_result.dtype)
+ global_result = np.zeros(shape=self.shape, dtype=local_result.dtype)
self._mpiw.Allreduce(local_result, global_result)
return global_result
@@ -695,107 +690,231 @@ def __getitem__(self, item):
def __setitem__(self, item, val):
raise NotImplementedError('MPIBlockMatrix does not support __setitem__.')
- def __add__(self, other):
- assert_block_structure(self)
- m, n = self.bshape
+ def _binary_operation_helper(self, other, operation):
result = self.copy_structure()
-
- rank = self._mpiw.Get_rank()
-
- if isinstance(other, MPIBlockMatrix):
- assert_block_structure(other)
-
+ if isinstance(other, (MPIBlockMatrix, BlockMatrix)):
assert other.bshape == self.bshape, \
'dimensions mismatch {} != {}'.format(self.bshape, other.bshape)
- assert np.array_equal(self._rank_owner, other._rank_owner), \
- 'MPIBlockMatrices must be distributed in same processors'
+ if isinstance(other, MPIBlockMatrix):
+ assert np.array_equal(self._rank_owner, other._rank_owner), \
+ 'MPIBlockMatrices must be distributed in same processors'
- ii, jj = np.nonzero(self._owned_mask)
+ block_indices = np.bitwise_or(self.get_block_mask(copy=False), other.get_block_mask(copy=False))
+ block_indices = np.bitwise_and(block_indices, self._owned_mask)
+ ii, jj = np.nonzero(block_indices)
for i, j in zip(ii, jj):
mat1 = self.get_block(i, j)
mat2 = other.get_block(i, j)
if mat1 is not None and mat2 is not None:
- result.set_block(i, j, mat1 + mat2)
+ result.set_block(i, j, operation(mat1, mat2))
elif mat1 is not None and mat2 is None:
- result.set_block(i, j, mat1.copy())
+ result.set_block(i, j, operation(mat1, 0))
elif mat1 is None and mat2 is not None:
- result.set_block(i, j, mat2.copy())
+ result.set_block(i, j, operation(0, mat2))
else:
- result.set_block(i, j, None)
- return result
-
- raise NotImplementedError('Operation not supported by MPIBlockMatrix')
-
- def __radd__(self, other): # other + self
- return self.__add__(other)
-
- def __sub__(self, other):
- assert_block_structure(self)
- m, n = self.bshape
- result = self.copy_structure()
- rank = self._mpiw.Get_rank()
+ raise ValueError('This is unexpected. Please report to the developers.')
+ elif np.isscalar(other):
+ block_indices = np.bitwise_and(self.get_block_mask(copy=False), self._owned_mask)
+ for i, j in zip(*np.nonzero(block_indices)):
+ result.set_block(i, j, operation(self.get_block(i, j), other))
+ else:
+ raise NotImplementedError('Operation not supported by MPIBlockMatrix')
+ return result
- if isinstance(other, MPIBlockMatrix):
- assert_block_structure(other)
+ def _inplace_binary_operation_helper(self, other, operation):
+ if isinstance(other, (MPIBlockMatrix, BlockMatrix)):
+ assert operation in {operator.iadd, operator.isub}
assert other.bshape == self.bshape, \
'dimensions mismatch {} != {}'.format(self.bshape, other.bshape)
- assert np.array_equal(self._rank_owner, other._rank_owner), \
- 'MPIBlockMatrices must be distributed in same processors'
+ if isinstance(other, MPIBlockMatrix):
+ assert np.array_equal(self._rank_owner, other._rank_owner), \
+ 'MPIBlockMatrices must be distributed in same processors'
- ii, jj = np.nonzero(self._owned_mask)
+ block_indices = other.get_block_mask(copy=False)
+ block_indices = np.bitwise_and(block_indices, self._owned_mask)
+ ii, jj = np.nonzero(block_indices)
for i, j in zip(ii, jj):
mat1 = self.get_block(i, j)
mat2 = other.get_block(i, j)
if mat1 is not None and mat2 is not None:
- result.set_block(i, j, mat1 - mat2)
- elif mat1 is not None and mat2 is None:
- result.set_block(i, j, mat1.copy())
+ mat1 = operation(mat1, mat2)
+ self.set_block(i, j, mat1)
elif mat1 is None and mat2 is not None:
- result.set_block(i, j, -mat2)
+ if operation is operator.iadd:
+ sub_res = mat2.copy()
+ else:
+ sub_res = -mat2
+ self.set_block(i, j, sub_res)
else:
- result.set_block(i, j, None)
- return result
+ raise RuntimeError('Please report this to the developers.')
+ elif np.isscalar(other):
+ block_indices = np.bitwise_and(self.get_block_mask(copy=False), self._owned_mask)
+ for i, j in zip(*np.nonzero(block_indices)):
+ blk = self.get_block(i, j)
+ blk = operation(blk, other)
+ self.set_block(i, j, blk)
+ else:
+ raise NotImplementedError('Operation not supported by MPIBlockMatrix')
+ return self
- raise NotImplementedError('Operation not supported by MPIBlockMatrix')
+ def __add__(self, other):
+ return self._binary_operation_helper(other, operator.add)
- def __rsub__(self, other):
- raise NotImplementedError('Operation not supported by MPIBlockMatrix')
+ def __radd__(self, other): # other + self
+ return self._binary_operation_helper(other, operator.add)
- def _block_vector_multiply(self, other):
- """
- Parameters
- ----------
- other: BlockVector
+ def __sub__(self, other):
+ return self._binary_operation_helper(other, operator.sub)
- Returns
- -------
- result: BlockVector
- """
- block_vector_assert_block_structure(other)
- assert self.bshape[1] == other.nblocks, 'Dimension mismatch'
- local_result = BlockVector(self.bshape[0])
- for row_ndx in range(self.bshape[0]):
- local_result.set_block(row_ndx, np.zeros(self.get_row_size(row_ndx)))
- rank = self._mpiw.Get_rank()
+ def __rsub__(self, other):
+ return (-self) + other
+
+ def _get_block_vector_for_dot_product(self, x):
+ if isinstance(x, MPIBlockVector):
+ """
+ Consider a non-empty block m_{i, j} from the mpi block matrix with rank owner r_m and the
+ corresponding block v_{j} from the mpi block vector with rank owner r_v. There are 4 cases:
+ 1. r_m = r_v
+ In this case, all is good.
+ 2. r_v = -1
+ In this case, all is good.
+ 3. r_m = -1 and r_v = 0
+ All is good
+ 4. If none of the above cases hold, then v_{j} must be broadcast
+ """
+ n_block_rows, n_block_cols = self.bshape
+ blocks_needing_broadcast = np.zeros(n_block_cols, dtype=np.int64) # a value > 0 means broadcast
+ x_rank_ownership = x.rank_ownership
+ comm = self._mpiw
+ rank = comm.Get_rank()
+
+ if rank == 0:
+ block_indices = self._owned_mask
+ else:
+ block_indices = self._unique_owned_mask
+ block_indices = np.bitwise_and(block_indices, self.get_block_mask(copy=False))
+ for i, j in zip(*np.nonzero(block_indices)):
+ r_m = self._rank_owner[i, j]
+ r_v = x_rank_ownership[j]
+ if r_m == r_v:
+ pass
+ elif r_v == -1:
+ pass
+ elif r_m == -1 and r_v == 0:
+ pass
+ else:
+ blocks_needing_broadcast[j] = 1
+
+ global_blocks_needing_broadcast = np.zeros(n_block_cols, dtype=np.int64)
+ comm.Allreduce(blocks_needing_broadcast, global_blocks_needing_broadcast)
+ indices_needing_broadcast = np.nonzero(global_blocks_needing_broadcast)[0]
+ if len(indices_needing_broadcast) == 0:
+ return x
+ else:
+ res = BlockVector(n_block_cols)
+ for ndx in np.nonzero(x.ownership_mask)[0]:
+ res.set_block(ndx, x.get_block(ndx))
+ for j in indices_needing_broadcast:
+ j_owner = x_rank_ownership[j]
+ if rank == j_owner:
+ j_size = x.get_block_size(j)
+ else:
+ j_size = None
+ j_size = comm.bcast(j_size, j_owner)
+ if rank == j_owner:
+ data = x.get_block(j).flatten()
+ else:
+ data = np.empty(j_size)
+ comm.Bcast(data, j_owner)
+ res.set_block(j, data)
+ return res
+ elif isinstance(x, BlockVector):
+ return x
+ elif isinstance(x, np.ndarray):
+ y = BlockVector(self.bshape[1])
+ for ndx, size in enumerate(self.col_block_sizes(copy=False)):
+ y.set_block(ndx, np.zeros(size))
+ y.copyfrom(x)
+ return y
+ else:
+ raise NotImplementedError('Dot product is not yet supported for MPIBlockMatrix*'+str(type(x)))
+
+ def _block_vector_multiply(self, x):
+ """
+ In this method, we assume that we can access the correct blocks from x. This means that
+ _get_block_vector_for_dot_product should be called first.
+
+ For a given block row, if there are multiple non-empty blocks with different rank owners,
+ then the result for that row is owned by all, and we need to do an Allreduce. Otherwise the
+ rank owner of the resulting block is the rank owner of the non-empty blocks in the block row.
+ """
+ n_block_rows, n_block_cols = self.bshape
+ comm = self._mpiw
+ rank = comm.Get_rank()
+
+ blocks_that_need_reduced = np.zeros(n_block_rows, dtype=np.int64)
+ res_rank_owner = np.zeros(n_block_rows, dtype=np.int64)
+ for i, j in zip(*np.nonzero(self._block_matrix._block_mask)):
+ blocks_that_need_reduced[i] = 1
+ res_rank_owner[i] = self._rank_owner[i, j]
+
+ # we need some special handling to determine the owner of empty rows
+ local_empty_rows = self._block_matrix._block_mask.any(axis=1)
+ local_empty_rows = np.array(local_empty_rows, dtype=np.int64)
+ global_empty_rows = np.empty(local_empty_rows.size, dtype=np.int64)
+ comm.Allreduce(local_empty_rows, global_empty_rows)
+ empty_rows = np.nonzero(global_empty_rows == 0)[0]
+
+ global_blocks_that_need_reduced = np.zeros(n_block_rows, dtype=np.int64)
+ comm.Allreduce(blocks_that_need_reduced, global_blocks_that_need_reduced)
+ block_indices_that_need_reduced = np.nonzero(global_blocks_that_need_reduced > 1)[0]
+ global_res_rank_owner = np.zeros(n_block_rows, dtype=np.int64)
+ comm.Allreduce(res_rank_owner, global_res_rank_owner)
+ global_res_rank_owner[block_indices_that_need_reduced] = -1
+ for ndx in empty_rows:
+ row_owners = set(self._rank_owner[ndx, :])
+ if len(row_owners) == 1:
+ global_res_rank_owner[ndx] = row_owners.pop()
+ elif len(row_owners) == 2 and -1 in row_owners:
+ tmp = row_owners.pop()
+ if tmp == -1:
+ global_res_rank_owner[ndx] = row_owners.pop()
+ else:
+ global_res_rank_owner[ndx] = tmp
+ else:
+ global_res_rank_owner[ndx] = -1
+
+ res = MPIBlockVector(nblocks=n_block_rows,
+ rank_owner=global_res_rank_owner,
+ mpi_comm=comm,
+ assert_correct_owners=False)
+ for ndx in np.nonzero(res.ownership_mask)[0]:
+ res.set_block(ndx, np.zeros(self.get_row_size(ndx)))
if rank == 0:
block_indices = self._owned_mask
else:
block_indices = self._unique_owned_mask
+ block_indices = np.bitwise_and(block_indices, self._block_matrix._block_mask)
for row_ndx, col_ndx in zip(*np.nonzero(block_indices)):
- if self.get_block(row_ndx, col_ndx) is not None:
- res_blk = local_result.get_block(row_ndx)
- _tmp = self.get_block(row_ndx, col_ndx) * other.get_block(col_ndx)
- res_blk = _tmp + res_blk
- local_result.set_block(row_ndx, res_blk)
- flat_local = local_result.flatten()
- flat_global = np.zeros(flat_local.size)
- self._mpiw.Allreduce(flat_local, flat_global)
- global_result = local_result.copy_structure()
- global_result.copyfrom(flat_global)
- return global_result
+ res_blk = res.get_block(row_ndx)
+ tmp = self.get_block(row_ndx, col_ndx) * x.get_block(col_ndx)
+ tmp += res_blk
+ res.set_block(row_ndx, tmp)
+
+ for ndx in block_indices_that_need_reduced:
+ local = res.get_block(ndx)
+ flat_local = local.flatten()
+ flat_global = np.zeros(flat_local.size)
+ comm.Allreduce(flat_local, flat_global)
+ if isinstance(local, BlockVector):
+ local.copyfrom(flat_global)
+ else:
+ res.set_block(ndx, flat_global)
+
+ return res
def __mul__(self, other):
"""
@@ -803,30 +922,11 @@ def __mul__(self, other):
A*B with scipy sparse matrices, a matrix-matrix dot product is performed. We are following the
scipy sparse matrix API.
"""
-
- assert_block_structure(self)
-
- if isinstance(other, MPIBlockVector):
- global_other = other.make_local_copy()
- result = self._block_vector_multiply(global_other)
- return result
- elif isinstance(other, BlockVector):
- return self._block_vector_multiply(other)
- elif isinstance(other, np.ndarray):
- block_other = BlockVector(nblocks=self.bshape[1])
- for ndx in range(self.bshape[1]):
- block_other[ndx] = np.zeros(self.get_col_size(ndx), dtype=other.dtype)
- block_other.copyfrom(other)
- return self._block_vector_multiply(block_other).flatten()
- elif np.isscalar(other):
- result = self.copy_structure()
- ii, jj = np.nonzero(self._owned_mask)
- for i, j in zip(ii, jj):
- if not self._block_matrix.is_empty_block(i, j):
- result.set_block(i, j, self.get_block(i, j) * other)
- return result
+ if np.isscalar(other):
+ return self._binary_operation_helper(other, operator.mul)
else:
- raise NotImplementedError('Operation not supported by MPIBlockMatrix')
+ x = self._get_block_vector_for_dot_product(other)
+ return self._block_vector_multiply(x)
def __rmul__(self, other):
"""
@@ -834,17 +934,8 @@ def __rmul__(self, other):
A*B with scipy sparse matrices, a matrix-matrix dot product is performed. We are following the
scipy sparse matrix API.
"""
-
- assert_block_structure(self)
- m, n = self.bshape
- result = self.copy_structure()
-
if np.isscalar(other):
- ii, jj = np.nonzero(self._owned_mask)
- for i, j in zip(ii, jj):
- if not self._block_matrix.is_empty_block(i, j):
- result.set_block(i, j, self.get_block(i, j) * other)
- return result
+ return self._binary_operation_helper(other, operator.mul)
if isinstance(other, MPIBlockVector):
raise NotImplementedError('Vector-Matrix multiply not supported yet')
@@ -862,100 +953,35 @@ def __pow__(self, other):
raise NotImplementedError('Operation not supported by MPIBlockMatrix')
def __truediv__(self, other):
- assert_block_structure(self)
- m, n = self.bshape
- result = self.copy_structure()
-
if np.isscalar(other):
- ii, jj = np.nonzero(self._owned_mask)
- for i, j in zip(ii, jj):
- if not self._block_matrix.is_empty_block(i, j):
- result.set_block(i, j, self.get_block(i, j) / other)
- return result
+ return self._binary_operation_helper(other, operator.truediv)
raise NotImplementedError('Operation not supported by MPIBlockMatrix')
- def __floordiv__(self, other):
+ def __rtruediv__(self, other):
raise NotImplementedError('Operation not supported by MPIBlockMatrix')
- def __iadd__(self, other):
- assert_block_structure(self)
- m, n = self.bshape
-
- if isinstance(other, MPIBlockMatrix):
- assert_block_structure(other)
-
- assert other.bshape == self.bshape, \
- 'dimensions mismatch {} != {}'.format(self.bshape, other.bshape)
-
- assert np.array_equal(self._rank_owner, other._rank_owner), \
- 'MPIBlockMatrices must be distributed in same processors'
-
- ii, jj = np.nonzero(self._owned_mask)
- for i, j in zip(ii, jj):
- mat1 = self.get_block(i, j)
- mat2 = other.get_block(i, j)
- if mat1 is not None and mat2 is not None:
- mat1 += mat2
- self.set_block(i, j, mat1)
- elif mat1 is None and mat2 is not None:
- self.set_block(i, j, mat2.copy())
- return self
-
+ def __floordiv__(self, other):
+ if np.isscalar(other):
+ return self._binary_operation_helper(other, operator.floordiv)
raise NotImplementedError('Operation not supported by MPIBlockMatrix')
- def __isub__(self, other):
- assert_block_structure(self)
- m, n = self.bshape
-
- if isinstance(other, MPIBlockMatrix):
- assert_block_structure(other)
-
- assert other.bshape == self.bshape, \
- 'dimensions mismatch {} != {}'.format(self.bshape, other.bshape)
-
- assert np.array_equal(self._rank_owner, other._rank_owner), \
- 'MPIBlockMatrices must be distributed in same processors'
+ def __rfloordiv__(self, other):
+ raise NotImplementedError('Operation not supported by MPIBlockMatrix')
- ii, jj = np.nonzero(self._owned_mask)
- for i, j in zip(ii, jj):
- mat1 = self.get_block(i, j)
- mat2 = other.get_block(i, j)
- if mat1 is not None and mat2 is not None:
- blk = self.get_block(i, j)
- blk -= mat2
- self.set_block(i, j, blk)
- elif mat1 is None and mat2 is not None:
- self.set_block(i, j, -mat2)
- return self
+ def __iadd__(self, other):
+ return self._inplace_binary_operation_helper(other, operator.iadd)
- raise NotImplementedError('Operation not supported by MPIBlockMatrix')
+ def __isub__(self, other):
+ return self._inplace_binary_operation_helper(other, operator.isub)
def __imul__(self, other):
- assert_block_structure(self)
- m, n = self.bshape
-
if np.isscalar(other):
- ii, jj = np.nonzero(self._owned_mask)
- for i, j in zip(ii, jj):
- if not self._block_matrix.is_empty_block(i, j):
- blk = self.get_block(i, j)
- blk *= other
- self.set_block(i, j, blk)
- return self
+ return self._inplace_binary_operation_helper(other, operator.imul)
raise NotImplementedError('Operation not supported by MPIBlockMatrix')
def __itruediv__(self, other):
- assert_block_structure(self)
- m, n = self.bshape
-
if np.isscalar(other):
- ii, jj = np.nonzero(self._owned_mask)
- for i, j in zip(ii, jj):
- if not self._block_matrix.is_empty_block(i, j):
- blk = self.get_block(i, j)
- blk /= other
- self.set_block(i, j, blk)
- return self
+ return self._inplace_binary_operation_helper(other, operator.itruediv)
raise NotImplementedError('Operation not supported by MPIBlockMatrix')
def __div__(self, other):
@@ -968,32 +994,24 @@ def __idiv__(self, other):
return self.__itruediv__(other)
def __neg__(self):
- assert_block_structure(self)
result = self.copy_structure()
-
- ii, jj = np.nonzero(self._owned_mask)
- for i, j in zip(ii, jj):
- if not self._block_matrix.is_empty_block(i, j):
- result.set_block(i, j, -self.get_block(i, j))
+ block_indices = np.bitwise_and(self.get_block_mask(copy=False), self._owned_mask)
+ for i, j in zip(*np.nonzero(block_indices)):
+ result.set_block(i, j, -self.get_block(i, j))
return result
def __abs__(self):
- assert_block_structure(self)
result = self.copy_structure()
-
- ii, jj = np.nonzero(self._owned_mask)
- for i, j in zip(ii, jj):
- if not self._block_matrix.is_empty_block(i, j):
- result.set_block(i, j, abs(self.get_block(i, j)))
+ block_indices = np.bitwise_and(self.get_block_mask(copy=False), self._owned_mask)
+ for i, j in zip(*np.nonzero(block_indices)):
+ result.set_block(i, j, abs(self.get_block(i, j)))
return result
def _comparison_helper(self, operation, other):
assert_block_structure(self)
- m, n = self.bshape
result = self.copy_structure()
if isinstance(other, MPIBlockMatrix):
- assert_block_structure(other)
assert other.bshape == self.bshape, 'dimension mismatch {} != {}'.format(self.bshape, other.bshape)
assert np.array_equal(self.rank_ownership, other.rank_ownership), 'MPIBlockMatrices must be distributed in ' \
'the same processors'
@@ -1239,8 +1257,13 @@ def fromBlockMatrix(block_matrix, rank_ownership, mpi_comm):
mpi_comm)
# populate matrix
+ for i in range(bm):
+ mat.set_row_size(i, block_matrix.get_row_size(i))
+
+ for j in range(bn):
+ mat.set_col_size(j, block_matrix.get_col_size(j))
+
for i, j in mat.owned_blocks:
mat.set_block(i, j, block_matrix.get_block(i, j))
- mat.broadcast_block_sizes()
return mat
diff --git a/pyomo/contrib/pynumero/sparse/mpi_block_vector.py b/pyomo/contrib/pynumero/sparse/mpi_block_vector.py
index 532055263ae..a5f689c0709 100644
--- a/pyomo/contrib/pynumero/sparse/mpi_block_vector.py
+++ b/pyomo/contrib/pynumero/sparse/mpi_block_vector.py
@@ -15,7 +15,6 @@
from .block_vector import assert_block_structure as block_vector_assert_block_structure
from mpi4py import MPI
import numpy as np
-import copy as cp
import operator
__all__ = ['MPIBlockVector']
@@ -85,7 +84,7 @@ class MPIBlockVector(np.ndarray, BaseBlockVector):
An MPI communicator. Tyically MPI.COMM_WORLD
"""
- def __new__(cls, nblocks, rank_owner, mpi_comm):
+ def __new__(cls, nblocks, rank_owner, mpi_comm, assert_correct_owners=True):
assert isinstance(nblocks, int)
assert len(rank_owner) == nblocks
@@ -114,11 +113,11 @@ def __new__(cls, nblocks, rank_owner, mpi_comm):
obj._unique_owned_blocks.append(i)
# containers that facilitate looping
- obj._owned_blocks = np.array(obj._owned_blocks)
- obj._unique_owned_blocks = np.array(obj._unique_owned_blocks)
+ obj._owned_blocks = np.array(obj._owned_blocks, dtype=np.int)
+ obj._unique_owned_blocks = np.array(obj._unique_owned_blocks, dtype=np.int)
obj._brow_lengths = np.empty(nblocks, dtype=np.float64)
obj._brow_lengths.fill(np.nan)
- obj._undefined_brows = set(range(nblocks))
+ obj._undefined_brows = set(obj._owned_blocks)
# make some pointers unmutable. These arrays don't change after
# MPIBlockVector has been created
@@ -127,13 +126,16 @@ def __new__(cls, nblocks, rank_owner, mpi_comm):
obj._owned_mask.flags.writeable = False
obj._unique_owned_blocks.flags.writeable = False
+ obj._broadcasted = False
+
return obj
- def __init__(self, nblocks, rank_owner, mpi_comm):
+ def __init__(self, nblocks, rank_owner, mpi_comm, assert_correct_owners=True):
# Note: this requires communication but is disabled when assertions
# are turned off
- assert self._assert_correct_owners(), \
- 'rank_owner must be the same in all processors'
+ if assert_correct_owners:
+ assert self._assert_correct_owners(), \
+ 'rank_owner must be the same in all processors'
def __array_prepare__(self, out_arr, context=None):
return super(MPIBlockVector, self).__array_prepare__(self, out_arr, context)
@@ -208,7 +210,7 @@ def _binary_operation(self, ufunc, method, *args, **kwargs):
if isinstance(x1, MPIBlockVector) and isinstance(x2, MPIBlockVector):
msg = 'BlockVectors must be distributed in same processors'
- assert np.array_equal(x1._rank_owner, x2._rank_owner), msg
+ assert np.array_equal(x1._rank_owner, x2._rank_owner) or self._mpiw.Get_size() == 1, msg
assert x1._mpiw == x2._mpiw, 'Need to have same communicator'
res = x1.copy_structure()
@@ -266,8 +268,7 @@ def shape(self):
"""
Returns total number of elements in the MPIBlockVector
"""
- assert_block_structure(self)
- return np.sum(self._brow_lengths),
+ return (self.size,)
@property
def size(self):
@@ -275,7 +276,16 @@ def size(self):
Returns total number of elements in this MPIBlockVector
"""
assert_block_structure(self)
- return np.sum(self._brow_lengths)
+ comm = self._mpiw
+ rank = comm.Get_rank()
+ if rank == 0:
+ indices = self._owned_blocks
+ else:
+ indices = self._unique_owned_blocks
+ local_size = np.sum(self._brow_lengths[indices])
+ size = comm.allreduce(local_size)
+ assert int(size) == size
+ return int(size)
@property
def ndim(self):
@@ -326,26 +336,30 @@ def mpi_comm(self):
"""Returns MPI communicator"""
return self._mpiw
+ def is_broadcasted(self):
+ return self._broadcasted
+
def block_sizes(self, copy=True):
"""
Returns 1D-Array with sizes of individual blocks in this MPIBlockVector
"""
- assert_block_structure(self)
+ if not self._broadcasted:
+ self.broadcast_block_sizes()
if copy:
return self._brow_lengths.copy()
return self._brow_lengths
def get_block_size(self, ndx):
- if ndx in self._undefined_brows:
+ res = self._brow_lengths[ndx]
+ if np.isnan(res):
raise NotFullyDefinedBlockVectorError('The dimensions of the requested block are not defined.')
- return self._brow_lengths[ndx]
+ res = int(res)
+ return res
def _set_block_size(self, ndx, size):
if ndx in self._undefined_brows:
self._undefined_brows.remove(ndx)
self._brow_lengths[ndx] = size
- if len(self._undefined_brows) == 0:
- self._brow_lengths = np.asarray(self._brow_lengths, dtype=np.int64)
else:
if self._brow_lengths[ndx] != size:
raise ValueError('Incompatible dimensions for block {ndx}; '
@@ -360,6 +374,7 @@ def broadcast_block_sizes(self):
this MPIBlockVector knows it's dimensions across all blocks. This method
must be called before running any operations with the MPIBlockVector.
"""
+ assert_block_structure(self)
rank = self._mpiw.Get_rank()
num_processors = self._mpiw.Get_size()
@@ -395,7 +410,26 @@ def broadcast_block_sizes(self):
msg = 'The dimension of block {} was not specified in any process'.format(i)
# here block_length must only have one element
- self._set_block_size(i, block_length.pop())
+ self._brow_lengths[i] = block_length.pop()
+
+ self._brow_lengths = np.asarray(self._brow_lengths, dtype=np.int64)
+ self._broadcasted = True
+
+ def finalize_block_sizes(self, broadcast=True, block_sizes=None):
+ """
+ Only set broadcast=False if you know what you are doing!
+
+ Parameters
+ ----------
+ broadcast: bool
+ block_sizes: None or np.ndarray
+ """
+ if broadcast:
+ self.broadcast_block_sizes()
+ else:
+ self._undefined_brows = set()
+ self._brow_lengths = block_sizes
+ self._broadcasted = True
# Note: this requires communication but is only run in __new__
def _assert_correct_owners(self, root=0):
@@ -533,7 +567,6 @@ def nonzero(self):
assert_block_structure(self)
for i in self._owned_blocks:
result.set_block(i, self._block_vector.get_block(i).nonzero()[0])
- result.broadcast_block_sizes()
return (result,)
def round(self, decimals=0, out=None):
@@ -595,7 +628,6 @@ def compress(self, condition, axis=None, out=None):
assert self._mpiw == condition._mpiw, 'Need to have same communicator'
for i in self._owned_blocks:
result.set_block(i, self.get_block(i).compress(condition.get_block(i)))
- result.broadcast_block_sizes()
return result
if isinstance(condition, BlockVector):
raise RuntimeError('Operation not supported by MPIBlockVector')
@@ -635,6 +667,8 @@ def copyfrom(self, other):
self.set_block(i, other.get_block(i).copy())
elif isinstance(other, np.ndarray):
assert_block_structure(self)
+ if not self.is_broadcasted():
+ self.broadcast_block_sizes()
assert self.shape == other.shape, 'Dimension mismatch {} != {}'.format(self.shape, other.shape)
offset = 0
for idx in range(self.nblocks):
@@ -718,10 +752,18 @@ def copy_structure(self):
"""
Returns a copy of the MPIBlockVector structure filled with zeros
"""
- result = MPIBlockVector(self.nblocks, self.rank_ownership, self.mpi_comm)
- result._block_vector = self._block_vector.copy_structure()
- result._brow_lengths = self._brow_lengths.copy()
- result._undefined_brows = set(self._undefined_brows)
+ result = MPIBlockVector(self.nblocks, self.rank_ownership, self.mpi_comm, assert_correct_owners=False)
+ if self.is_broadcasted():
+ result.finalize_block_sizes(broadcast=False, block_sizes=self.block_sizes(copy=False))
+ for bid in self.owned_blocks:
+ block = self.get_block(bid)
+ if block is not None:
+ if isinstance(block, BlockVector):
+ result.set_block(bid, block.copy_structure())
+ elif type(block) == np.ndarray:
+ result.set_block(bid, np.zeros(block.size))
+ else:
+ raise NotImplementedError('Should never get here')
return result
def fill(self, value):
@@ -775,7 +817,6 @@ def dot(self, other, out=None):
'Number of blocks mismatch: {} != {}'.format(self.nblocks, other.nblocks)
return self.dot(other.toMPIBlockVector(self.rank_ownership, self.mpi_comm))
elif isinstance(other, np.ndarray):
- assert self.shape == other.shape, 'Dimension mismatch: {} != {}'.format(self.shape, other.shape)
other_bv = self.copy_structure()
other_bv.copyfrom(other)
return self.dot(other_bv)
@@ -909,6 +950,8 @@ def make_local_copy(self):
BlockVector
"""
assert_block_structure(self)
+ if not self.is_broadcasted():
+ self.broadcast_block_sizes()
result = self.make_local_structure_copy()
local_data = np.zeros(self.size)
@@ -943,7 +986,7 @@ def _binary_operation_helper(self, other, operation):
assert self.nblocks == other.nblocks, \
'Number of blocks mismatch: {} != {}'.format(self.nblocks, other.nblocks)
if isinstance(other, MPIBlockVector):
- assert np.array_equal(self._rank_owner, other._rank_owner), \
+ assert np.array_equal(self._rank_owner, other._rank_owner) or self._mpiw.Get_size() == 1, \
'MPIBlockVectors must be distributed in same processors'
assert self._mpiw == other._mpiw, 'Need to have same communicator'
for i in self._owned_blocks:
@@ -980,7 +1023,7 @@ def _inplace_binary_operation_helper(self, other, operation):
assert self.nblocks == other.nblocks, \
'Number of blocks mismatch: {} != {}'.format(self.nblocks, other.nblocks)
if isinstance(other, MPIBlockVector):
- assert np.array_equal(self._rank_owner, other._rank_owner), \
+ assert np.array_equal(self._rank_owner, other._rank_owner) or self._mpiw.Get_size() == 1, \
'MPIBlockVectors must be distributed in same processors'
assert self._mpiw == other._mpiw, 'Need to have same communicator'
assert_block_structure(other)
@@ -1070,7 +1113,7 @@ def _comparison_helper(self, other, operation):
assert_block_structure(other)
assert self.nblocks == other.nblocks, \
'Number of blocks mismatch: {} != {}'.format(self.nblocks, other.nblocks)
- assert np.array_equal(self._rank_owner, other._rank_owner), \
+ assert np.array_equal(self._rank_owner, other._rank_owner) or self._mpiw.Get_size() == 1, \
'MPIBlockVectors must be distributed in same processors'
assert self._mpiw == other._mpiw, 'Need to have same communicator'
@@ -1139,7 +1182,7 @@ def _has_equal_structure(self, other):
if self.nblocks != other.nblocks:
return False
if isinstance(other, MPIBlockVector):
- if (self.owned_blocks != other.owned_blocks).any():
+ if (self.owned_blocks != other.owned_blocks).any() and self._mpiw.Get_size() != 1:
return False
for ndx in self.owned_blocks:
block1 = self.get_block(ndx)
@@ -1215,7 +1258,7 @@ def pprint(self, root=0):
print(msg)
def __len__(self):
- return self.nblocks
+ raise NotImplementedError('Use size or nblocks')
def __iter__(self):
raise NotImplementedError('Not supported by MPIBlockVector')
diff --git a/pyomo/contrib/pynumero/sparse/tests/test_block_matrix.py b/pyomo/contrib/pynumero/sparse/tests/test_block_matrix.py
index 580e172475a..35193c079e2 100644
--- a/pyomo/contrib/pynumero/sparse/tests/test_block_matrix.py
+++ b/pyomo/contrib/pynumero/sparse/tests/test_block_matrix.py
@@ -220,6 +220,16 @@ def test_dot(self):
self.assertTrue(np.allclose(A_dense.dot(x), block_res.flatten()))
self.assertEqual(block_res.bshape[0], 2)
+ m = BlockMatrix(2, 2)
+ sub_m = np.array([[1, 0],
+ [0, 1]])
+ sub_m = coo_matrix(sub_m)
+ m.set_block(0, 1, sub_m.copy())
+ m.set_block(1, 0, sub_m.copy())
+ x = np.arange(4)
+ res = m*x
+ self.assertTrue(np.allclose(res.flatten(), np.array([2, 3, 0, 1])))
+
def test_reset_brow(self):
self.basic_m.reset_brow(0)
for j in range(self.basic_m.bshape[1]):
@@ -318,7 +328,7 @@ def test_add(self):
self.assertTrue(np.allclose(r.toarray(), dense_res))
with self.assertRaises(Exception) as context:
- mm = A_block.__radd__(A_block.toarray())
+ mm = A_block.toarray() + A_block
with self.assertRaises(Exception) as context:
mm = A_block + A_block.toarray()
diff --git a/pyomo/contrib/pynumero/sparse/tests/test_block_vector.py b/pyomo/contrib/pynumero/sparse/tests/test_block_vector.py
index d6aebd6a049..e0a72800717 100644
--- a/pyomo/contrib/pynumero/sparse/tests/test_block_vector.py
+++ b/pyomo/contrib/pynumero/sparse/tests/test_block_vector.py
@@ -7,8 +7,8 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
from __future__ import division
-import sys
import pyutilib.th as unittest
from pyomo.contrib.pynumero.dependencies import (
diff --git a/pyomo/contrib/pynumero/sparse/tests/test_intrinsics.py b/pyomo/contrib/pynumero/sparse/tests/test_intrinsics.py
index b7c876b4a96..3f14955dff7 100644
--- a/pyomo/contrib/pynumero/sparse/tests/test_intrinsics.py
+++ b/pyomo/contrib/pynumero/sparse/tests/test_intrinsics.py
@@ -7,7 +7,7 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import sys
+
import pyutilib.th as unittest
from pyomo.contrib.pynumero.dependencies import (
diff --git a/pyomo/contrib/pynumero/sparse/tests/test_mpi_block_matrix.py b/pyomo/contrib/pynumero/sparse/tests/test_mpi_block_matrix.py
index 2beea888532..6269c3041f8 100644
--- a/pyomo/contrib/pynumero/sparse/tests/test_mpi_block_matrix.py
+++ b/pyomo/contrib/pynumero/sparse/tests/test_mpi_block_matrix.py
@@ -73,7 +73,6 @@ def setUpClass(cls):
serial_bm.set_block(1, 1, m)
cls.square_serial_mat = serial_bm
- bm.broadcast_block_sizes()
cls.square_mpi_mat = bm
# create mpi matrix
@@ -95,7 +94,6 @@ def setUpClass(cls):
bm.set_block(1, 1, m)
bm.set_block(0, 1, m)
- bm.broadcast_block_sizes()
cls.square_mpi_mat2 = bm
# create serial matrix image
@@ -117,7 +115,6 @@ def setUpClass(cls):
bm.set_block(0, 2, m2)
if rank == 1:
bm.set_block(1, 1, m)
- bm.broadcast_block_sizes()
cls.rectangular_mpi_mat = bm
bm = BlockMatrix(2, 3)
@@ -133,8 +130,6 @@ def test_bshape(self):
def test_shape(self):
self.assertEqual(self.square_mpi_mat.shape, (8, 8))
self.assertEqual(self.rectangular_mpi_mat.shape, (8, 10))
- with self.assertRaises(NotFullyDefinedBlockMatrixError):
- self.assertEqual(self.square_mpi_mat_no_broadcast.shape, (8, 8))
def test_tocoo(self):
with self.assertRaises(Exception) as context:
@@ -228,7 +223,6 @@ def test_reset_brow(self):
bm.set_block(0, 0, m)
if rank == 1:
bm.set_block(1, 1, m)
- bm.broadcast_block_sizes()
serial_bm = BlockMatrix(2, 2)
serial_bm.set_block(0, 0, m)
@@ -261,7 +255,6 @@ def test_reset_bcol(self):
bm.set_block(0, 0, m)
if rank == 1:
bm.set_block(1, 1, m)
- bm.broadcast_block_sizes()
serial_bm = BlockMatrix(2, 2)
serial_bm.set_block(0, 0, m)
@@ -358,43 +351,35 @@ def test_transpose(self):
self.assertTrue(np.allclose(res.get_block(i, j).toarray().T,
mat2.get_block(j, i).toarray()))
- def test_add(self):
+ def _compare_mpi_and_serial_block_matrices(self, mpi_mat, serial_mat):
+ self.assertIsInstance(mpi_mat, MPIBlockMatrix)
+ rows, columns = np.nonzero(mpi_mat.ownership_mask)
+ for i, j in zip(rows, columns):
+ if mpi_mat.get_block(i, j) is not None:
+ self.assertTrue(np.allclose(mpi_mat.get_block(i, j).toarray(),
+ serial_mat.get_block(i, j).toarray()))
+ else:
+ self.assertIsNone(serial_mat.get_block(i, j))
+ def test_add(self):
mat1 = self.square_mpi_mat
mat2 = self.square_mpi_mat2
serial_mat1 = self.square_serial_mat
serial_mat2 = self.square_serial_mat2
- res = mat1 + mat1
- serial_res = serial_mat1 + serial_mat1
- self.assertIsInstance(res, MPIBlockMatrix)
- self.assertTrue(np.allclose(mat1.rank_ownership, res.rank_ownership))
- rows, columns = np.nonzero(res.ownership_mask)
- for i, j in zip(rows, columns):
- if res.get_block(i, j) is not None:
- self.assertTrue(np.allclose(res.get_block(i, j).toarray(),
- serial_res.get_block(i, j).toarray()))
- else:
- self.assertIsNone(serial_res.get_block(i, j))
-
res = mat1 + mat2
serial_res = serial_mat1 + serial_mat2
- self.assertIsInstance(res, MPIBlockMatrix)
- rows, columns = np.nonzero(res.ownership_mask)
self.assertTrue(np.allclose(mat1.rank_ownership, res.rank_ownership))
- for i, j in zip(rows, columns):
- if res.get_block(i, j) is not None:
- self.assertTrue(np.allclose(res.get_block(i, j).toarray(),
- serial_res.get_block(i, j).toarray()))
- else:
- self.assertIsNone(serial_res.get_block(i, j))
+ self._compare_mpi_and_serial_block_matrices(res, serial_res)
- with self.assertRaises(Exception) as context:
- res = mat1 + serial_mat2
+ res = mat1 + serial_mat2
+ self.assertTrue(np.allclose(mat1.rank_ownership, res.rank_ownership))
+ self._compare_mpi_and_serial_block_matrices(res, serial_res)
- with self.assertRaises(Exception) as context:
- res = serial_mat2 + mat1
+ res = serial_mat2 + mat1
+ self.assertTrue(np.allclose(mat1.rank_ownership, res.rank_ownership))
+ self._compare_mpi_and_serial_block_matrices(res, serial_res)
with self.assertRaises(Exception) as context:
res = mat1 + serial_mat2.tocoo()
@@ -410,171 +395,26 @@ def test_sub(self):
serial_mat1 = self.square_serial_mat
serial_mat2 = self.square_serial_mat2
- res = mat1 - mat1
- serial_res = serial_mat1 - serial_mat1
- self.assertIsInstance(res, MPIBlockMatrix)
- self.assertTrue(np.allclose(mat1.rank_ownership, res.rank_ownership))
- rows, columns = np.nonzero(res.ownership_mask)
- for i, j in zip(rows, columns):
- if res.get_block(i, j) is not None:
- self.assertTrue(np.allclose(res.get_block(i, j).toarray(),
- serial_res.get_block(i, j).toarray()))
- else:
- self.assertIsNone(serial_res.get_block(i, j))
-
res = mat1 - mat2
serial_res = serial_mat1 - serial_mat2
- self.assertIsInstance(res, MPIBlockMatrix)
- rows, columns = np.nonzero(res.ownership_mask)
- for i, j in zip(rows, columns):
- if res.get_block(i, j) is not None:
- self.assertTrue(np.allclose(res.get_block(i, j).toarray(),
- serial_res.get_block(i, j).toarray()))
- else:
- self.assertIsNone(serial_res.get_block(i, j))
+ self.assertTrue(np.allclose(mat1.rank_ownership, res.rank_ownership))
+ self._compare_mpi_and_serial_block_matrices(res, serial_res)
+
+ res = mat1 - serial_mat2
+ self._compare_mpi_and_serial_block_matrices(res, serial_res)
+
+ res = mat2 - mat1
+ serial_res = serial_mat2 - serial_mat1
+ self._compare_mpi_and_serial_block_matrices(res, serial_res)
+
+ res = serial_mat2 - mat1
+ self._compare_mpi_and_serial_block_matrices(res, serial_res)
- with self.assertRaises(Exception) as context:
- res = mat1 - serial_mat2
- with self.assertRaises(Exception) as context:
- res = serial_mat2 - mat1
with self.assertRaises(Exception) as context:
res = mat1 - serial_mat2.tocoo()
with self.assertRaises(Exception) as context:
res = serial_mat2.tocoo() - mat1
- def test_mul(self):
-
- mat1 = self.square_mpi_mat
- mat2 = self.square_mpi_mat2
-
- serial_mat1 = self.square_serial_mat
- serial_mat2 = self.square_serial_mat2
-
- rank = comm.Get_rank()
-
- bv1 = MPIBlockVector(2, [0, 1], comm)
-
- if rank == 0:
- bv1.set_block(0, np.arange(4, dtype=np.float64))
- if rank == 1:
- bv1.set_block(1, np.arange(4, dtype=np.float64) + 4)
- bv1.broadcast_block_sizes()
-
- serial_bv1 = BlockVector(2)
- serial_bv1.set_block(0, np.arange(4, dtype=np.float64))
- serial_bv1.set_block(1, np.arange(4, dtype=np.float64) + 4)
-
- res = mat1 * bv1
- serial_res = serial_mat1 * serial_bv1
- self.assertIsInstance(res, BlockVector)
- self.assertEqual(res.nblocks, serial_res.nblocks)
- for bid in range(serial_res.nblocks):
- self.assertTrue(np.allclose(res.get_block(bid),
- serial_res.get_block(bid)))
-
- res = mat2 * bv1
- serial_res = serial_mat2 * serial_bv1
- self.assertIsInstance(res, BlockVector)
- self.assertEqual(res.nblocks, serial_res.nblocks)
- for bid in range(serial_res.nblocks):
- self.assertTrue(np.allclose(res.get_block(bid),
- serial_res.get_block(bid)))
-
- bv1 = MPIBlockVector(2, [0, -1], comm)
-
- if rank == 0:
- bv1.set_block(0, np.arange(4, dtype=np.float64))
- bv1.set_block(1, np.arange(4, dtype=np.float64) + 4)
- bv1.broadcast_block_sizes()
-
- res = mat1 * bv1
- serial_res = serial_mat1 * serial_bv1
- self.assertIsInstance(res, BlockVector)
- self.assertEqual(res.nblocks, serial_res.nblocks)
- for bid in range(serial_res.nblocks):
- self.assertTrue(np.allclose(res.get_block(bid),
- serial_res.get_block(bid)))
-
- res = mat2 * bv1
- serial_res = serial_mat2 * serial_bv1
- self.assertIsInstance(res, BlockVector)
- self.assertEqual(res.nblocks, serial_res.nblocks)
- for bid in range(serial_res.nblocks):
- self.assertTrue(np.allclose(res.get_block(bid),
- serial_res.get_block(bid)))
-
- # rectangular matrix
- mat1 = self.rectangular_mpi_mat
- serial_mat1 = self.rectangular_serial_mat
-
- bv1 = MPIBlockVector(3, [0, 1, 2], comm)
-
- if rank == 0:
- bv1.set_block(0, np.arange(4, dtype=np.float64))
- if rank == 1:
- bv1.set_block(1, np.arange(4, dtype=np.float64) + 4)
- if rank == 2:
- bv1.set_block(2, np.arange(2, dtype=np.float64) + 8)
-
- bv1.broadcast_block_sizes()
-
- serial_bv1 = BlockVector(3)
- serial_bv1.set_block(0, np.arange(4, dtype=np.float64))
- serial_bv1.set_block(1, np.arange(4, dtype=np.float64) + 4)
- serial_bv1.set_block(2, np.arange(2, dtype=np.float64) + 8)
-
- # with warnings.catch_warnings():
- # warnings.simplefilter("ignore")
- res = mat1 * bv1
- serial_res = serial_mat1 * serial_bv1
-
- self.assertIsInstance(res, BlockVector)
- self.assertEqual(serial_res.nblocks, 2)
- self.assertEqual(res.nblocks, 2)
- for bid in range(serial_res.nblocks):
- self.assertTrue(np.allclose(res.get_block(bid),
- serial_res.get_block(bid)))
-
- bv1 = MPIBlockVector(3, [0, 1, 0], comm)
-
- if rank == 0:
- bv1.set_block(0, np.arange(4, dtype=np.float64))
- bv1.set_block(2, np.arange(2, dtype=np.float64) + 8)
- if rank == 1:
- bv1.set_block(1, np.arange(4, dtype=np.float64) + 4)
- bv1.broadcast_block_sizes()
-
- res = mat1 * bv1
- serial_res = serial_mat1 * serial_bv1
- self.assertIsInstance(res, BlockVector)
- self.assertEqual(res.nblocks, serial_res.nblocks)
- for bid in range(serial_res.nblocks):
- self.assertTrue(np.allclose(res.get_block(bid),
- serial_res.get_block(bid)))
-
- res = mat1 * 3.0
- serial_res = serial_mat1 * 3.0
- self.assertIsInstance(res, MPIBlockMatrix)
- rows, columns = np.nonzero(res.ownership_mask)
- for i, j in zip(rows, columns):
- if res.get_block(i, j) is not None:
- self.assertTrue(np.allclose(res.get_block(i, j).toarray(),
- serial_res.get_block(i, j).toarray()))
- else:
- self.assertIsNone(serial_res.get_block(i, j))
-
- res = 3.0 * mat1
- serial_res = serial_mat1 * 3.0
-
- self.assertIsInstance(res, MPIBlockMatrix)
- rows, columns = np.nonzero(res.ownership_mask)
- for i, j in zip(rows, columns):
- if res.get_block(i, j) is not None:
- self.assertTrue(np.allclose(res.get_block(i, j).toarray(),
- serial_res.get_block(i, j).toarray()))
- else:
- self.assertIsNone(serial_res.get_block(i, j))
-
def test_div(self):
mat1 = self.square_mpi_mat
@@ -592,36 +432,6 @@ def test_div(self):
else:
self.assertIsNone(serial_res.get_block(i, j))
- def test_dot(self):
-
- mat1 = self.square_mpi_mat
- mat2 = self.square_mpi_mat2
-
- serial_mat1 = self.square_serial_mat
- serial_mat2 = self.square_serial_mat2
-
- rank = comm.Get_rank()
-
- bv1 = MPIBlockVector(2, [0, 1], comm)
-
- if rank == 0:
- bv1.set_block(0, np.arange(4, dtype=np.float64))
- if rank == 1:
- bv1.set_block(1, np.arange(4, dtype=np.float64) + 4)
- bv1.broadcast_block_sizes()
-
- serial_bv1 = BlockVector(2)
- serial_bv1.set_block(0, np.arange(4, dtype=np.float64))
- serial_bv1.set_block(1, np.arange(4, dtype=np.float64) + 4)
-
- res = mat1.dot(bv1)
- serial_res = serial_mat1.dot(serial_bv1)
- self.assertIsInstance(res, BlockVector)
- self.assertEqual(res.nblocks, serial_res.nblocks)
- for bid in range(serial_res.nblocks):
- self.assertTrue(np.allclose(res.get_block(bid),
- serial_res.get_block(bid)))
-
def test_iadd(self):
row = np.array([0, 3, 1, 2, 3, 0])
@@ -637,7 +447,6 @@ def test_iadd(self):
bm.set_block(0, 0, m.copy())
if rank == 1:
bm.set_block(1, 1, m.copy())
- bm.broadcast_block_sizes()
serial_bm = BlockMatrix(2, 2)
serial_bm.set_block(0, 0, m.copy())
@@ -652,16 +461,9 @@ def test_iadd(self):
self.assertTrue(np.allclose(bm.get_block(i, j).toarray(),
serial_bm.get_block(i, j).toarray()))
- with self.assertRaises(Exception) as context:
- bm += serial_bm
-
- serial_bm2 = BlockMatrix(2, 2)
- serial_bm2.set_block(0, 0, m.copy())
- serial_bm2.set_block(0, 1, m.copy())
- serial_bm2.set_block(1, 1, m.copy())
-
- with self.assertRaises(Exception) as context:
- bm += serial_bm2
+ bm += serial_bm
+ serial_bm += serial_bm
+ self._compare_mpi_and_serial_block_matrices(bm, serial_bm)
def test_isub(self):
@@ -678,7 +480,6 @@ def test_isub(self):
bm.set_block(0, 0, m.copy())
if rank == 1:
bm.set_block(1, 1, m.copy())
- bm.broadcast_block_sizes()
serial_bm = BlockMatrix(2, 2)
serial_bm.set_block(0, 0, m.copy())
@@ -693,8 +494,9 @@ def test_isub(self):
self.assertTrue(np.allclose(bm.get_block(i, j).toarray(),
serial_bm.get_block(i, j).toarray()))
- with self.assertRaises(Exception) as context:
- bm -= serial_bm
+ bm -= serial_bm
+ serial_bm -= serial_bm
+ self._compare_mpi_and_serial_block_matrices(bm, serial_bm)
def test_imul(self):
@@ -711,7 +513,6 @@ def test_imul(self):
bm.set_block(0, 0, m)
if rank == 1:
bm.set_block(1, 1, m)
- bm.broadcast_block_sizes()
serial_bm = BlockMatrix(2, 2)
serial_bm.set_block(0, 0, m)
@@ -741,7 +542,6 @@ def test_idiv(self):
bm.set_block(0, 0, m)
if rank == 1:
bm.set_block(1, 1, m)
- bm.broadcast_block_sizes()
serial_bm = BlockMatrix(2, 2)
serial_bm.set_block(0, 0, m)
@@ -771,7 +571,6 @@ def test_neg(self):
bm.set_block(0, 0, m)
if rank == 1:
bm.set_block(1, 1, m)
- bm.broadcast_block_sizes()
serial_bm = BlockMatrix(2, 2)
serial_bm.set_block(0, 0, m)
@@ -801,7 +600,6 @@ def test_abs(self):
bm.set_block(0, 0, m)
if rank == 1:
bm.set_block(1, 1, m)
- bm.broadcast_block_sizes()
serial_bm = BlockMatrix(2, 2)
serial_bm.set_block(0, 0, m)
@@ -1153,3 +951,200 @@ def test_gt(self):
with self.assertRaises(Exception) as context:
res = serial_mat1 > mat1
+
+
+@unittest.category("mpi")
+class TestMPIMatVec(unittest.TestCase):
+
+ @classmethod
+ @unittest.skipIf(SKIPTESTS, SKIPTESTS)
+ def setUpClass(cls):
+ pass
+
+ def test_get_block_vector_for_dot_product_1(self):
+ rank = comm.Get_rank()
+
+ rank_ownership = np.array([[0, 1, 2],
+ [1, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2]])
+ m = MPIBlockMatrix(4, 3, rank_ownership, comm)
+ sub_m = np.array([[1, 0],
+ [0, 1]])
+ sub_m = coo_matrix(sub_m)
+ m.set_block(rank, rank, sub_m.copy())
+ m.set_block(3, rank, sub_m.copy())
+
+ rank_ownership = np.array([0, 1, 2])
+ v = MPIBlockVector(3, rank_ownership, comm)
+ sub_v = np.ones(2)
+ v.set_block(rank, sub_v)
+
+ res = m._get_block_vector_for_dot_product(v)
+
+ self.assertIs(res, v)
+
+ def test_get_block_vector_for_dot_product_2(self):
+ rank = comm.Get_rank()
+
+ rank_ownership = np.array([[1, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2]])
+ m = MPIBlockMatrix(4, 3, rank_ownership, comm)
+ sub_m = np.array([[1, 0],
+ [0, 1]])
+ sub_m = coo_matrix(sub_m)
+ if rank == 0:
+ m.set_block(3, rank, sub_m.copy())
+ elif rank == 1:
+ m.set_block(0, 0, sub_m.copy())
+ m.set_block(rank, rank, sub_m.copy())
+ m.set_block(3, rank, sub_m.copy())
+ else:
+ m.set_block(rank, rank, sub_m.copy())
+ m.set_block(3, rank, sub_m.copy())
+
+ rank_ownership = np.array([-1, 1, 2])
+ v = MPIBlockVector(3, rank_ownership, comm)
+ sub_v = np.ones(2)
+ v.set_block(0, sub_v.copy())
+ if rank != 0:
+ v.set_block(rank, sub_v.copy())
+
+ res = m._get_block_vector_for_dot_product(v)
+
+ self.assertIs(res, v)
+
+ def test_get_block_vector_for_dot_product_3(self):
+ rank = comm.Get_rank()
+
+ rank_ownership = np.array([[1, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2]])
+ m = MPIBlockMatrix(4, 3, rank_ownership, comm)
+ sub_m = np.array([[1, 0],
+ [0, 1]])
+ sub_m = coo_matrix(sub_m)
+ if rank == 0:
+ m.set_block(3, rank, sub_m.copy())
+ elif rank == 1:
+ m.set_block(0, 0, sub_m.copy())
+ m.set_block(rank, rank, sub_m.copy())
+ m.set_block(3, rank, sub_m.copy())
+ else:
+ m.set_block(rank, rank, sub_m.copy())
+ m.set_block(3, rank, sub_m.copy())
+
+ rank_ownership = np.array([0, 1, 2])
+ v = MPIBlockVector(3, rank_ownership, comm)
+ sub_v = np.ones(2)
+ v.set_block(rank, sub_v.copy())
+
+ res = m._get_block_vector_for_dot_product(v)
+
+ self.assertIsNot(res, v)
+ self.assertTrue(np.array_equal(res.get_block(0), sub_v))
+ if rank == 0:
+ self.assertIsNone(res.get_block(1))
+ self.assertIsNone(res.get_block(2))
+ elif rank == 1:
+ self.assertTrue(np.array_equal(res.get_block(1), sub_v))
+ self.assertIsNone(res.get_block(2))
+ elif rank == 2:
+ self.assertTrue(np.array_equal(res.get_block(2), sub_v))
+ self.assertIsNone(res.get_block(1))
+
+ def test_get_block_vector_for_dot_product_4(self):
+ rank = comm.Get_rank()
+
+ rank_ownership = np.array([[-1, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2]])
+ m = MPIBlockMatrix(4, 3, rank_ownership, comm)
+ sub_m = np.array([[1, 0],
+ [0, 1]])
+ sub_m = coo_matrix(sub_m)
+ m.set_block(0, 0, sub_m.copy())
+ if rank == 0:
+ m.set_block(3, rank, sub_m.copy())
+ else:
+ m.set_block(rank, rank, sub_m.copy())
+ m.set_block(3, rank, sub_m.copy())
+
+ rank_ownership = np.array([0, 1, 2])
+ v = MPIBlockVector(3, rank_ownership, comm)
+ sub_v = np.ones(2)
+ v.set_block(rank, sub_v.copy())
+
+ res = m._get_block_vector_for_dot_product(v)
+
+ self.assertIs(res, v)
+
+ def test_get_block_vector_for_dot_product_5(self):
+ rank = comm.Get_rank()
+
+ rank_ownership = np.array([[1, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2],
+ [0, 1, 2]])
+ m = MPIBlockMatrix(4, 3, rank_ownership, comm)
+ sub_m = np.array([[1, 0],
+ [0, 1]])
+ sub_m = coo_matrix(sub_m)
+ if rank == 0:
+ m.set_block(3, rank, sub_m.copy())
+ elif rank == 1:
+ m.set_block(0, 0, sub_m.copy())
+ m.set_block(rank, rank, sub_m.copy())
+ m.set_block(3, rank, sub_m.copy())
+ else:
+ m.set_block(rank, rank, sub_m.copy())
+ m.set_block(3, rank, sub_m.copy())
+
+ v = BlockVector(3)
+ sub_v = np.ones(2)
+ for ndx in range(3):
+ v.set_block(ndx, sub_v.copy())
+
+ res = m._get_block_vector_for_dot_product(v)
+
+ self.assertIs(res, v)
+
+ v_flat = v.flatten()
+ res = m._get_block_vector_for_dot_product(v_flat)
+ self.assertIsInstance(res, BlockVector)
+ for ndx in range(3):
+ block = res.get_block(ndx)
+ self.assertTrue(np.array_equal(block, sub_v))
+
+ def test_matvec_1(self):
+ rank = comm.Get_rank()
+
+ rank_ownership = np.array([[0, -1, -1, 0],
+ [-1, 1, -1, 1],
+ [-1, -1, 2, 2],
+ [0, 1, 2, -1]])
+ m = MPIBlockMatrix(4, 4, rank_ownership, comm)
+ sub_m = np.array([[1, 0],
+ [0, 1]])
+ sub_m = coo_matrix(sub_m)
+ m.set_block(rank, rank, sub_m.copy())
+ m.set_block(rank, 3, sub_m.copy())
+ m.set_block(3, rank, sub_m.copy())
+ m.set_block(3, 3, sub_m.copy())
+
+ rank_ownership = np.array([0, 1, 2, -1])
+ v = MPIBlockVector(4, rank_ownership, comm)
+ sub_v = np.ones(2)
+ v.set_block(rank, sub_v.copy())
+ v.set_block(3, sub_v.copy())
+
+ res = m.dot(v)
+ self.assertIsInstance(res, MPIBlockVector)
+ self.assertTrue(np.array_equal(res.get_block(rank), sub_v*2))
+ self.assertTrue(np.array_equal(res.get_block(3), sub_v*4))
+ self.assertTrue(np.array_equal(res.rank_ownership, np.array([0, 1, 2, -1])))
+ self.assertFalse(res.has_none)
diff --git a/pyomo/contrib/pynumero/sparse/tests/test_mpi_block_vector.py b/pyomo/contrib/pynumero/sparse/tests/test_mpi_block_vector.py
index db6fd4ce836..eab076a2409 100644
--- a/pyomo/contrib/pynumero/sparse/tests/test_mpi_block_vector.py
+++ b/pyomo/contrib/pynumero/sparse/tests/test_mpi_block_vector.py
@@ -59,7 +59,6 @@ def setUpClass(cls):
v1.set_block(3, np.ones(2))
cls.v1 = v1
- cls.v1.broadcast_block_sizes()
v2 = MPIBlockVector(7, [0,0,1,1,2,2,-1], comm)
rank = comm.Get_rank()
@@ -75,7 +74,6 @@ def setUpClass(cls):
v2.set_block(6, np.ones(2) * 3)
cls.v2 = v2
- cls.v2.broadcast_block_sizes()
def test_nblocks(self):
v1 = self.v1
@@ -91,8 +89,10 @@ def test_bshape(self):
def test_size(self):
v1 = self.v1
+ self.assertEqual(type(v1.size), int)
self.assertEqual(v1.size, 10)
v2 = self.v2
+ self.assertEqual(type(v2.size), int)
self.assertEqual(v2.size, 20)
def test_shape(self):
@@ -106,12 +106,18 @@ def test_ndim(self):
self.assertEqual(v1.ndim, 1)
def test_has_none(self):
- v = MPIBlockVector(4, [0,1,0,1], comm)
+ v = MPIBlockVector(4, [0, 1, 0, 1], comm)
rank = comm.Get_rank()
if rank == 0:
+ self.assertTrue(v.has_none)
v.set_block(0, np.ones(3))
+ self.assertTrue(v.has_none)
v.set_block(2, np.ones(3))
- self.assertTrue(v.has_none)
+ self.assertFalse(v.has_none)
+ elif rank == 1:
+ self.assertTrue(v.has_none)
+ else:
+ self.assertFalse(v.has_none)
self.assertFalse(self.v1.has_none)
def test_any(self):
@@ -121,7 +127,6 @@ def test_any(self):
v.set_block(0, np.ones(3))
if rank == 1:
v.set_block(1, np.zeros(3))
- v.broadcast_block_sizes()
self.assertTrue(v.any())
self.assertTrue(self.v1.any())
self.assertTrue(self.v2.any())
@@ -133,7 +138,6 @@ def test_all(self):
v.set_block(0, np.ones(3))
if rank == 1:
v.set_block(1, np.zeros(3))
- v.broadcast_block_sizes()
self.assertFalse(v.all())
if rank == 1:
v.set_block(1, np.ones(3))
@@ -148,7 +152,6 @@ def test_min(self):
v.set_block(0, np.arange(3) + 10)
if rank == 1:
v.set_block(1, np.arange(3))
- v.broadcast_block_sizes()
self.assertEqual(v.min(), 0.0)
if rank == 1:
v.set_block(1, -np.arange(3))
@@ -161,7 +164,6 @@ def test_min(self):
if rank == 1:
v.set_block(1, np.arange(3))
v.set_block(2, -np.arange(6))
- v.broadcast_block_sizes()
self.assertEqual(v.min(), -5.0)
self.assertEqual(self.v1.min(), 0.0)
self.assertEqual(self.v2.min(), 0.0)
@@ -173,7 +175,6 @@ def test_max(self):
v.set_block(0, np.arange(3) + 10)
if rank == 1:
v.set_block(1, np.arange(3))
- v.broadcast_block_sizes()
self.assertEqual(v.max(), 12.0)
v = MPIBlockVector(3, [0,1,-1], comm)
@@ -183,7 +184,6 @@ def test_max(self):
if rank == 1:
v.set_block(1, np.arange(3))
v.set_block(2, np.arange(60))
- v.broadcast_block_sizes()
self.assertEqual(v.max(), 59.0)
self.assertEqual(self.v1.max(), 1.0)
self.assertEqual(self.v2.max(), 3.0)
@@ -196,7 +196,6 @@ def test_sum(self):
if rank == 1:
v.set_block(1, np.arange(3) + 3)
v.set_block(2, np.arange(3) + 6)
- v.broadcast_block_sizes()
b = np.arange(9)
self.assertEqual(b.sum(), v.sum())
@@ -211,7 +210,6 @@ def test_prod(self):
if rank == 1:
v.set_block(1, np.ones(3))
v.set_block(2, np.ones(3))
- v.broadcast_block_sizes()
self.assertEqual(1.0, v.prod())
if rank == 1:
v.set_block(1, np.ones(3) * 2)
@@ -230,7 +228,6 @@ def test_conj(self):
if rank == 1:
v.set_block(1, np.ones(3))
v.set_block(2, np.ones(3))
- v.broadcast_block_sizes()
res = v.conj()
self.assertTrue(isinstance(res, MPIBlockVector))
self.assertEqual(res.nblocks, v.nblocks)
@@ -245,7 +242,6 @@ def test_conjugate(self):
if rank == 1:
v.set_block(1, np.ones(3))
v.set_block(2, np.ones(3))
- v.broadcast_block_sizes()
res = v.conjugate()
self.assertTrue(isinstance(res, MPIBlockVector))
self.assertEqual(res.nblocks, v.nblocks)
@@ -260,7 +256,6 @@ def test_nonzero(self):
if rank == 1:
v.set_block(1, np.array([0,0,2]))
v.set_block(2, np.ones(3))
- v.broadcast_block_sizes()
res = v.nonzero()[0]
self.assertTrue(isinstance(res, MPIBlockVector))
self.assertEqual(res.nblocks, v.nblocks)
@@ -286,7 +281,6 @@ def test_round(self):
if rank == 1:
v.set_block(1, np.arange(3) + 3 + 0.01)
v.set_block(2, np.arange(3) + 6 + 0.01)
- v.broadcast_block_sizes()
res = v.round()
self.assertTrue(isinstance(res, MPIBlockVector))
@@ -305,7 +299,6 @@ def test_clip(self):
if rank == 1:
v.set_block(1, np.arange(3) + 3)
v.set_block(2, np.arange(3) + 6)
- v.broadcast_block_sizes()
res = v.clip(min=2.0)
self.assertTrue(isinstance(res, MPIBlockVector))
@@ -343,7 +336,6 @@ def test_compress(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
cond = MPIBlockVector(3, [0, 1, -1], comm)
rank = comm.Get_rank()
@@ -352,7 +344,6 @@ def test_compress(self):
if rank == 1:
cond.set_block(1, np.array([True, True, True, False]))
cond.set_block(2, np.array([True, True]))
- cond.broadcast_block_sizes()
res = v.compress(cond)
self.assertTrue(isinstance(res, MPIBlockVector))
@@ -458,7 +449,6 @@ def test_copyto(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
vv = MPIBlockVector(3, [0, 1, -1], comm)
v.copyto(vv)
@@ -482,7 +472,6 @@ def test_fill(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
v.fill(7.0)
self.assertTrue(isinstance(v, MPIBlockVector))
@@ -504,7 +493,6 @@ def test_dot(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
all_v = np.concatenate([np.arange(3), np.arange(4), np.arange(2)])
expected = all_v.dot(all_v)
@@ -523,7 +511,6 @@ def test_add(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
res = v + v
self.assertTrue(isinstance(res, MPIBlockVector))
@@ -572,7 +559,6 @@ def test_sub(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
res = v - v
self.assertTrue(isinstance(res, MPIBlockVector))
@@ -621,7 +607,6 @@ def test_mul(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
res = v * v
self.assertTrue(isinstance(res, MPIBlockVector))
@@ -670,7 +655,6 @@ def test_truediv(self):
if rank == 1:
v.set_block(1, np.arange(4) + 1.0)
v.set_block(2, np.arange(2) + 1.0)
- v.broadcast_block_sizes()
res = v / v
self.assertTrue(isinstance(res, MPIBlockVector))
@@ -720,7 +704,6 @@ def test_floordiv(self):
if rank == 1:
v.set_block(1, np.arange(4) + 1.0)
v.set_block(2, np.arange(2) + 1.0)
- v.broadcast_block_sizes()
res = v // v
self.assertTrue(isinstance(res, MPIBlockVector))
@@ -777,7 +760,6 @@ def test_isum(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
v += v
self.assertTrue(isinstance(v, MPIBlockVector))
@@ -795,7 +777,6 @@ def test_isum(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
v = MPIBlockVector(3, [0,1,-1], comm)
rank = comm.Get_rank()
@@ -804,7 +785,6 @@ def test_isum(self):
if rank == 1:
v.set_block(1, np.arange(4, dtype='d'))
v.set_block(2, np.arange(2, dtype='d'))
- v.broadcast_block_sizes()
v += 7.0
self.assertTrue(isinstance(v, MPIBlockVector))
@@ -824,7 +804,6 @@ def test_isub(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
v -= v
self.assertTrue(isinstance(v, MPIBlockVector))
@@ -842,7 +821,6 @@ def test_isub(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
v = MPIBlockVector(3, [0,1,-1], comm)
rank = comm.Get_rank()
@@ -851,7 +829,6 @@ def test_isub(self):
if rank == 1:
v.set_block(1, np.arange(4, dtype='d'))
v.set_block(2, np.arange(2, dtype='d'))
- v.broadcast_block_sizes()
v -= 7.0
self.assertTrue(isinstance(v, MPIBlockVector))
@@ -871,7 +848,6 @@ def test_imul(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
v *= v
self.assertTrue(isinstance(v, MPIBlockVector))
@@ -889,7 +865,6 @@ def test_imul(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
v = MPIBlockVector(3, [0,1,-1], comm)
rank = comm.Get_rank()
@@ -898,7 +873,6 @@ def test_imul(self):
if rank == 1:
v.set_block(1, np.arange(4, dtype='d'))
v.set_block(2, np.arange(2, dtype='d'))
- v.broadcast_block_sizes()
v *= 7.0
self.assertTrue(isinstance(v, MPIBlockVector))
@@ -918,7 +892,6 @@ def test_itruediv(self):
if rank == 1:
v.set_block(1, np.arange(4) + 1.0)
v.set_block(2, np.arange(2) + 1.0)
- v.broadcast_block_sizes()
v /= v
self.assertTrue(isinstance(v, MPIBlockVector))
@@ -936,7 +909,6 @@ def test_itruediv(self):
if rank == 1:
v.set_block(1, np.arange(4) + 1.0)
v.set_block(2, np.arange(2) + 1.0)
- v.broadcast_block_sizes()
v = MPIBlockVector(3, [0,1,-1], comm)
rank = comm.Get_rank()
@@ -945,7 +917,6 @@ def test_itruediv(self):
if rank == 1:
v.set_block(1, np.arange(4, dtype='d'))
v.set_block(2, np.arange(2, dtype='d'))
- v.broadcast_block_sizes()
v /= 2.0
self.assertTrue(isinstance(v, MPIBlockVector))
@@ -964,7 +935,6 @@ def test_le(self):
if rank == 1:
v.set_block(1, np.ones(4) * 2)
v.set_block(2, np.ones(2) * 4)
- v.broadcast_block_sizes()
v1 = MPIBlockVector(3, [0, 1, -1], comm)
rank = comm.Get_rank()
@@ -973,7 +943,6 @@ def test_le(self):
if rank == 1:
v1.set_block(1, np.ones(4) * 8)
v1.set_block(2, np.ones(2) * 4)
- v1.broadcast_block_sizes()
res = v <= v1
@@ -1043,7 +1012,6 @@ def test_lt(self):
if rank == 1:
v.set_block(1, np.ones(4) * 2)
v.set_block(2, np.ones(2) * 4)
- v.broadcast_block_sizes()
v1 = MPIBlockVector(3, [0,1,-1], comm)
rank = comm.Get_rank()
@@ -1052,7 +1020,6 @@ def test_lt(self):
if rank == 1:
v1.set_block(1, np.ones(4) * 8)
v1.set_block(2, np.ones(2) * 4)
- v1.broadcast_block_sizes()
res = v < v1
@@ -1122,7 +1089,6 @@ def test_ge(self):
if rank == 1:
v.set_block(1, np.ones(4) * 2)
v.set_block(2, np.ones(2) * 4)
- v.broadcast_block_sizes()
v1 = MPIBlockVector(3, [0,1,-1], comm)
rank = comm.Get_rank()
@@ -1131,7 +1097,6 @@ def test_ge(self):
if rank == 1:
v1.set_block(1, np.ones(4) * 8)
v1.set_block(2, np.ones(2) * 4)
- v1.broadcast_block_sizes()
res = v >= v1
@@ -1201,7 +1166,6 @@ def test_gt(self):
if rank == 1:
v.set_block(1, np.ones(4) * 2)
v.set_block(2, np.ones(2) * 4)
- v.broadcast_block_sizes()
v1 = MPIBlockVector(3, [0,1,-1], comm)
rank = comm.Get_rank()
@@ -1210,7 +1174,6 @@ def test_gt(self):
if rank == 1:
v1.set_block(1, np.ones(4) * 8)
v1.set_block(2, np.ones(2) * 4)
- v1.broadcast_block_sizes()
res = v > v1
@@ -1280,7 +1243,6 @@ def test_eq(self):
if rank == 1:
v.set_block(1, np.ones(4) * 2)
v.set_block(2, np.ones(2) * 4)
- v.broadcast_block_sizes()
v1 = MPIBlockVector(3, [0,1,-1], comm)
rank = comm.Get_rank()
@@ -1289,7 +1251,6 @@ def test_eq(self):
if rank == 1:
v1.set_block(1, np.ones(4) * 8)
v1.set_block(2, np.ones(2) * 4)
- v1.broadcast_block_sizes()
res = v == v1
@@ -1359,7 +1320,6 @@ def test_ne(self):
if rank == 1:
v.set_block(1, np.ones(4) * 2)
v.set_block(2, np.ones(2) * 4)
- v.broadcast_block_sizes()
v1 = MPIBlockVector(3, [0,1,-1], comm)
rank = comm.Get_rank()
@@ -1368,7 +1328,6 @@ def test_ne(self):
if rank == 1:
v1.set_block(1, np.ones(4) * 8)
v1.set_block(2, np.ones(2) * 4)
- v1.broadcast_block_sizes()
res = v != v1
@@ -1482,7 +1441,6 @@ def test_reduce_ufuncs(self):
v.set_block(0, np.ones(3) * 0.5)
if rank == 1:
v.set_block(1, np.ones(2) * 0.8)
- v.broadcast_block_sizes()
bv = BlockVector(2)
bv.set_block(0, np.ones(3) * 0.5)
@@ -1605,23 +1563,10 @@ def test_contains(self):
v.set_block(0, np.ones(3))
if rank == 1:
v.set_block(1, np.zeros(2))
- v.broadcast_block_sizes()
self.assertTrue(0 in v)
self.assertFalse(3 in v)
- def test_len(self):
-
- v = MPIBlockVector(2, [0,1], comm)
-
- rank = comm.Get_rank()
- if rank == 0:
- v.set_block(0, np.ones(3))
- if rank == 1:
- v.set_block(1, np.zeros(2))
- v.broadcast_block_sizes()
- self.assertEqual(len(v), 2)
-
def test_copyfrom(self):
v = MPIBlockVector(3, [0,1,-1], comm)
@@ -1631,7 +1576,6 @@ def test_copyfrom(self):
if rank == 1:
v.set_block(1, np.arange(4))
v.set_block(2, np.arange(2))
- v.broadcast_block_sizes()
bv = BlockVector(3)
bv.set_blocks([np.arange(3), np.arange(4), np.arange(2)])
diff --git a/pyomo/contrib/pynumero/src/CMakeLists.txt b/pyomo/contrib/pynumero/src/CMakeLists.txt
index 001e1319175..1258519e545 100644
--- a/pyomo/contrib/pynumero/src/CMakeLists.txt
+++ b/pyomo/contrib/pynumero/src/CMakeLists.txt
@@ -23,6 +23,9 @@ OPTION(BUILD_AMPLMP_IF_NEEDED
"Automatically enable AMPLMP build if ASL not found" OFF)
MARK_AS_ADVANCED(BUILD_AMPLMP_IF_NEEDED)
+OPTION(ENABLE_HSL "Enable the HSL library interfaces" ON)
+MARK_AS_ADVANCED(ENABLE_HSL)
+
#OPTION(STATIC_LINK "STATIC_LINK" OFF)
# If we build AMPLMP, then we will get a dependency on dlopen
@@ -48,7 +51,7 @@ ENDIF()
# cmake does not search LD_LIBRARY_PATH by default. So that libraries
# like HSL can be added through mechanisms like 'environment modules',
-# we will explicitly add LD_LIBRARY_PATH to teh search path
+# we will explicitly add LD_LIBRARY_PATH to the search path
string(REPLACE ":" ";" LD_LIBRARY_DIR_LIST
$ENV{LD_LIBRARY_PATH}:$ENV{DYLD_LIBRARY_PATH}
)
@@ -98,6 +101,12 @@ IF( MA27_LIBRARY OR MA27_OBJECT )
set_property(CACHE BUILD_MA27 PROPERTY VALUE ON)
ENDIF()
+#...but if the HSL interface is not enabled, do not build the MA* libraries
+IF( NOT ENABLE_HSL )
+ set_property(CACHE BUILD_MA27 PROPERTY VALUE OFF)
+ set_property(CACHE BUILD_MA57 PROPERTY VALUE OFF)
+ENDIF()
+
# If BUILD_AMPLMP_IF_NEEDED is set and we couldn't find / weren't
# pointed to an ASL build, then we will forcibly enable the AMPLMP build
# to provide the ASL.
diff --git a/pyomo/contrib/pynumero/tests/test_cyipopt_examples.py b/pyomo/contrib/pynumero/tests/test_cyipopt_examples.py
new file mode 100644
index 00000000000..09cd3982289
--- /dev/null
+++ b/pyomo/contrib/pynumero/tests/test_cyipopt_examples.py
@@ -0,0 +1,99 @@
+import os.path
+from pyomo.common.fileutils import this_file_dir
+import pyutilib.th as unittest
+from pyutilib.misc import import_file
+import pyomo.environ as pyo
+
+from pyomo.contrib.pynumero.dependencies import (
+ numpy as np, numpy_available, scipy_sparse as spa, scipy_available
+)
+if not (numpy_available and scipy_available):
+ raise unittest.SkipTest("Pynumero needs scipy and numpy to run CyIpopt tests")
+
+from pyomo.contrib.pynumero.asl import AmplInterface
+if not AmplInterface.available():
+ raise unittest.SkipTest(
+ "Pynumero needs the ASL extension to run CyIpopt tests")
+
+import pyomo.contrib.pynumero.algorithms.solvers.cyipopt_solver as cyipopt_solver
+if not cyipopt_solver.ipopt_available:
+ raise unittest.SkipTest("PyNumero needs CyIpopt installed to run CyIpopt tests")
+import cyipopt as cyipopt_core
+
+example_dir = os.path.join(this_file_dir(), '..', 'examples')
+
+class TestPyomoCyIpoptSolver(unittest.TestCase):
+ def test_status_maps(self):
+ self.assertEqual(len(cyipopt_core.STATUS_MESSAGES),
+ len(cyipopt_solver._cyipopt_status_enum))
+ self.assertEqual(len(cyipopt_core.STATUS_MESSAGES),
+ len(cyipopt_solver._ipopt_term_cond))
+ for msg in cyipopt_core.STATUS_MESSAGES.values():
+ self.assertIn(msg, cyipopt_solver._cyipopt_status_enum)
+ for status in cyipopt_solver._cyipopt_status_enum.values():
+ self.assertIn(status, cyipopt_solver._ipopt_term_cond)
+
+
+class TestExamples(unittest.TestCase):
+ def test_external_grey_box_react_example_maximize_cb_outputs(self):
+ ex = import_file(os.path.join(example_dir, 'external_grey_box', 'react-example', 'maximize_cb_outputs.py'))
+ m = ex.maximize_cb_outputs()
+ self.assertAlmostEqual(pyo.value(m.reactor.inputs['sv']), 1.34381, places=3)
+ self.assertAlmostEqual(pyo.value(m.reactor.outputs['cb']), 1072.4372, places=2)
+
+ def test_external_grey_box_react_example_maximize_cb_outputs_scaling(self):
+ ex = import_file(os.path.join(example_dir, 'external_grey_box', 'react-example', 'maximize_cb_ratio_residuals.py'))
+ aoptions={'nlp_scaling_method': 'user-scaling',
+ 'output_file': '_cyipopt-external-greybox-react-scaling.log',
+ 'file_print_level':10}
+ m = ex.maximize_cb_ratio_residuals_with_output_scaling(additional_options=aoptions)
+ self.assertAlmostEqual(pyo.value(m.reactor.inputs['sv']), 1.26541996, places=3)
+ self.assertAlmostEqual(pyo.value(m.reactor.inputs['cb']), 1071.7410089, places=2)
+ self.assertAlmostEqual(pyo.value(m.reactor.outputs['cb_ratio']), 0.15190409266, places=3)
+
+ with open('_cyipopt-external-greybox-react-scaling.log', 'r') as fd:
+ solver_trace = fd.read()
+ os.remove('_cyipopt-external-greybox-react-scaling.log')
+
+ self.assertIn('nlp_scaling_method = user-scaling', solver_trace)
+ self.assertIn('output_file = _cyipopt-external-greybox-react-scaling.log', solver_trace)
+ self.assertIn('objective scaling factor = 1', solver_trace)
+ self.assertIn('x scaling provided', solver_trace)
+ self.assertIn('c scaling provided', solver_trace)
+ self.assertIn('d scaling provided', solver_trace)
+ self.assertIn('DenseVector "x scaling vector" with 7 elements:', solver_trace)
+ self.assertIn('x scaling vector[ 1]= 1.2000000000000000e+00', solver_trace)
+ self.assertIn('x scaling vector[ 2]= 1.7000000000000000e+00', solver_trace)
+ self.assertIn('x scaling vector[ 3]= 1.1000000000000001e+00', solver_trace)
+ self.assertIn('x scaling vector[ 4]= 1.3000000000000000e+00', solver_trace)
+ self.assertIn('x scaling vector[ 5]= 1.3999999999999999e+00', solver_trace)
+ self.assertIn('x scaling vector[ 6]= 1.5000000000000000e+00', solver_trace)
+ self.assertIn('x scaling vector[ 7]= 1.6000000000000001e+00', solver_trace)
+ self.assertIn('DenseVector "c scaling vector" with 6 elements:', solver_trace)
+ self.assertIn('c scaling vector[ 1]= 4.2000000000000000e+01', solver_trace)
+ self.assertIn('c scaling vector[ 2]= 1.0000000000000001e-01', solver_trace)
+ self.assertIn('c scaling vector[ 3]= 2.0000000000000001e-01', solver_trace)
+ self.assertIn('c scaling vector[ 4]= 2.9999999999999999e-01', solver_trace)
+ self.assertIn('c scaling vector[ 5]= 4.0000000000000002e-01', solver_trace)
+ self.assertIn('c scaling vector[ 6]= 1.0000000000000000e+01', solver_trace)
+
+ def test_external_grey_box_react_example_maximize_with_output(self):
+ ex = import_file(os.path.join(example_dir, 'external_grey_box', 'react-example', 'maximize_cb_ratio_residuals.py'))
+ m = ex.maximize_cb_ratio_residuals_with_output()
+ self.assertAlmostEqual(pyo.value(m.reactor.inputs['sv']), 1.26541996, places=3)
+ self.assertAlmostEqual(pyo.value(m.reactor.inputs['cb']), 1071.7410089, places=2)
+ self.assertAlmostEqual(pyo.value(m.reactor.outputs['cb_ratio']), 0.15190409266, places=3)
+
+ def test_external_grey_box_react_example_maximize_with_obj(self):
+ ex = import_file(os.path.join(example_dir, 'external_grey_box', 'react-example', 'maximize_cb_ratio_residuals.py'))
+ m = ex.maximize_cb_ratio_residuals_with_obj()
+ self.assertAlmostEqual(pyo.value(m.reactor.inputs['sv']), 1.26541996, places=3)
+ self.assertAlmostEqual(pyo.value(m.reactor.inputs['cb']), 1071.7410089, places=2)
+ self.assertAlmostEqual(pyo.value(m.obj), 0.15190409266, places=3)
+
+ def test_external_grey_box_react_example_maximize_with_additional_pyomo_variables(self):
+ ex = import_file(os.path.join(example_dir, 'external_grey_box', 'react-example', 'maximize_cb_ratio_residuals.py'))
+ m = ex.maximize_cb_ratio_residuals_with_pyomo_variables()
+ self.assertAlmostEqual(pyo.value(m.reactor.inputs['sv']), 1.26541996, places=3)
+ self.assertAlmostEqual(pyo.value(m.reactor.inputs['cb']), 1071.7410089, places=2)
+ self.assertAlmostEqual(pyo.value(m.cb_ratio), 0.15190409266, places=3)
diff --git a/pyomo/contrib/sensitivity_toolbox/examples/HIV_Transmission.py b/pyomo/contrib/sensitivity_toolbox/examples/HIV_Transmission.py
index b52197589a6..16e744e0b99 100755
--- a/pyomo/contrib/sensitivity_toolbox/examples/HIV_Transmission.py
+++ b/pyomo/contrib/sensitivity_toolbox/examples/HIV_Transmission.py
@@ -14,9 +14,10 @@
#
from __future__ import division
-from pyomo.environ import *
+from pyomo.environ import (ConcreteModel, Param, Var, Objective,
+ Constraint, Set, Expression, Suffix,
+ value, exp, TransformationFactory)
from pyomo.dae import ContinuousSet, DerivativeVar
-from pyomo.core import TransformationFactory
from pyomo.dae.simulator import Simulator
from pyomo.contrib.sensitivity_toolbox.sens import sipopt
@@ -24,7 +25,7 @@
def create_model():
m = ConcreteModel()
-
+
m.tf = Param(initialize=20)
m.t = ContinuousSet(bounds=(0,m.tf))
m.i = Set(initialize=[0,1,2,3,4,5],ordered=True)
@@ -276,12 +277,3 @@ def initialize_model(m,n_sim,n_nfe,n_ncp):
m_sipopt = sipopt(m,[m.eps,m.qq,m.aa],
[m.epsDelta,m.qqDelta,m.aaDelta],
streamSoln = True)
-
-
-
-
-
-
-
-
-
diff --git a/pyomo/contrib/sensitivity_toolbox/examples/feedbackController.py b/pyomo/contrib/sensitivity_toolbox/examples/feedbackController.py
index 30d33634431..d1f0530c7b6 100644
--- a/pyomo/contrib/sensitivity_toolbox/examples/feedbackController.py
+++ b/pyomo/contrib/sensitivity_toolbox/examples/feedbackController.py
@@ -17,9 +17,8 @@
#
# min J(u) = (1/2)*H*x^2(T)+\int_0^T ((1/4)*u^2(t)dt)
-from pyomo.environ import *
-from pyomo.core import TransformationFactory
-from pyomo.opt import SolverFactory
+from pyomo.environ import (ConcreteModel, Param, Var, Objective, Constraint,
+ Suffix, value, TransformationFactory, SolverFactory)
from pyomo.dae import ContinuousSet, DerivativeVar
from pyomo.dae.simulator import Simulator
from pyomo.contrib.sensitivity_toolbox.sens import sipopt
diff --git a/pyomo/contrib/sensitivity_toolbox/examples/parameter.py b/pyomo/contrib/sensitivity_toolbox/examples/parameter.py
index 5f594ee7c82..88fd21c8116 100644
--- a/pyomo/contrib/sensitivity_toolbox/examples/parameter.py
+++ b/pyomo/contrib/sensitivity_toolbox/examples/parameter.py
@@ -14,8 +14,8 @@
#
from __future__ import print_function
-from pyomo.environ import *
-from pyomo.contrib.sensitivity_toolbox.sens import sipopt
+from pyomo.environ import ConcreteModel, Param, Var, Objective, Constraint, NonNegativeReals, value
+from pyomo.contrib.sensitivity_toolbox.sens import sensitivity_calculation
def create_model():
''' Create a concrete Pyomo model for this example
@@ -52,9 +52,9 @@ def run_example(print_flag=True):
m.perturbed_eta2 = Param(initialize = 1.0)
- m_sipopt = sipopt(m,[m.eta1,m.eta2],
- [m.perturbed_eta1,m.perturbed_eta2],
- streamSoln=True)
+ m_sipopt = sensitivity_calculation('sipopt',m,[m.eta1,m.eta2],
+ [m.perturbed_eta1,m.perturbed_eta2],
+ streamSoln=True)
diff --git a/pyomo/contrib/sensitivity_toolbox/examples/parameter_kaug.py b/pyomo/contrib/sensitivity_toolbox/examples/parameter_kaug.py
index 41511d5d8ef..3161c8a563a 100644
--- a/pyomo/contrib/sensitivity_toolbox/examples/parameter_kaug.py
+++ b/pyomo/contrib/sensitivity_toolbox/examples/parameter_kaug.py
@@ -15,7 +15,7 @@
from pyomo.environ import *
-from pyomo.contrib.sensitivity_toolbox.sens import kaug
+from pyomo.contrib.sensitivity_toolbox.sens import sensitivity_calculation
def create_model():
''' Create a concrete Pyomo model for this example
@@ -35,7 +35,7 @@ def create_model():
return m
-def example(print_flag=True):
+def run_example(print_flag=True):
'''
Execute the example
@@ -52,11 +52,9 @@ def example(print_flag=True):
m.perturbed_eta2 = Param(initialize = 1.0)
- m_kaug_dsdp = kaug(m,[m.eta1,m.eta2],
- [m.perturbed_eta1,m.perturbed_eta2],
- streamSoln=True)
-
-
+ m_kaug_dsdp = sensitivity_calculation('kaug',m,[m.eta1,m.eta2],
+ [m.perturbed_eta1,m.perturbed_eta2],
+ streamSoln=True)
if print_flag:
print("\nOriginal parameter values:")
@@ -99,4 +97,4 @@ def example(print_flag=True):
return d
if __name__=='__main__':
- d = example()
+ d = run_example()
diff --git a/pyomo/contrib/sensitivity_toolbox/examples/rangeInequality.py b/pyomo/contrib/sensitivity_toolbox/examples/rangeInequality.py
index b6097c9eda4..9b55b6ee0bf 100644
--- a/pyomo/contrib/sensitivity_toolbox/examples/rangeInequality.py
+++ b/pyomo/contrib/sensitivity_toolbox/examples/rangeInequality.py
@@ -9,9 +9,8 @@
# ___________________________________________________________________________
#
-from pyomo.environ import *
-from pyomo.opt import SolverFactory
-from pyomo.dae import ContinuousSet
+from pyomo.environ import ConcreteModel, Param, Var, Constraint, inequality
+
from pyomo.contrib.sensitivity_toolbox.sens import sipopt
diff --git a/pyomo/contrib/sensitivity_toolbox/sens.py b/pyomo/contrib/sensitivity_toolbox/sens.py
index 114063fa532..3aa238edd3c 100644
--- a/pyomo/contrib/sensitivity_toolbox/sens.py
+++ b/pyomo/contrib/sensitivity_toolbox/sens.py
@@ -7,21 +7,21 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License
# ______________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import Param, Var, Block, ComponentMap, Objective, Constraint, ConstraintList, Suffix, value
-from pyomo.core.base import _ConstraintData, _ObjectiveData, _ExpressionData
from pyomo.core.base.misc import sorted_robust
-from pyomo.core.expr.current import (clone_expression, identify_variables,
- ExpressionReplacementVisitor)
+from pyomo.core.expr.current import ExpressionReplacementVisitor
from pyomo.common.modeling import unique_component_name
from pyomo.common.deprecation import deprecated
from pyomo.opt import SolverFactory
import logging
-_log = logging.getLogger('__name__')
+_log = logging.getLogger('pyomo.contrib.sensitivity_toolbox')
-@deprecated('The sipopt function has been deprecated. Use the sensitivity_calculation() function with method="sipopt" to access this functionality.',
+@deprecated("The sipopt function has been deprecated. Use the sensitivity_calculation() "
+ "function with method='sipopt' to access this functionality.",
+ logger='pyomo.contrib.sensitivity_toolbox',
version='TBD')
def sipopt(instance, paramSubList, perturbList,
cloneModel=True, streamSoln=False, keepfiles=False):
@@ -30,7 +30,8 @@ def sipopt(instance, paramSubList, perturbList,
return m
-@deprecated('The kaug function has been deprecated. Use the sensitivity_calculation() function with method="kaug" to access this functionality.',
+@deprecated("The kaug function has been deprecated. Use the sensitivity_calculation() "
+ "function with method='kaug' to access this functionality.",
version='TBD')
def kaug(instance, paramSubList, perturbList,
cloneModel=True, streamSoln=False, keepfiles=False, optarg=None):
diff --git a/pyomo/contrib/sensitivity_toolbox/tests/test_sens.py b/pyomo/contrib/sensitivity_toolbox/tests/test_sens.py
index f3fe0473ff4..5c6e11ae4f9 100644
--- a/pyomo/contrib/sensitivity_toolbox/tests/test_sens.py
+++ b/pyomo/contrib/sensitivity_toolbox/tests/test_sens.py
@@ -13,13 +13,18 @@
"""
import pyutilib.th as unittest
+from six import StringIO
+import logging
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Param, Var, Block, Suffix, value
from pyomo.opt import SolverFactory
from pyomo.dae import ContinuousSet
from pyomo.common.dependencies import scipy_available
+from pyomo.common.log import LoggingIntercept
from pyomo.core.expr.current import identify_variables
-from pyomo.contrib.sensitivity_toolbox.sens import sipopt, kaug
+from pyomo.contrib.sensitivity_toolbox.sens import sipopt, kaug, sensitivity_calculation
+import pyomo.contrib.sensitivity_toolbox.examples.parameter as param_ex
+import pyomo.contrib.sensitivity_toolbox.examples.parameter_kaug as param_kaug_ex
import pyomo.contrib.sensitivity_toolbox.examples.feedbackController as fc
import pyomo.contrib.sensitivity_toolbox.examples.rangeInequality as ri
import pyomo.contrib.sensitivity_toolbox.examples.HIV_Transmission as hiv
@@ -28,6 +33,87 @@
opt_kaug = SolverFactory('k_aug',solver_io='nl')
opt_dotsens = SolverFactory('dot_sens',solver_io='nl')
+
+class FunctionDeprecationTest(unittest.TestCase):
+
+ @unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
+ def test_sipopt_deprecated(self):
+ m = param_ex.create_model()
+ m.perturbed_eta1 = Param(initialize = 4.0)
+ m.perturbed_eta2 = Param(initialize = 1.0)
+
+ output = StringIO()
+ with LoggingIntercept(output, 'pyomo.contrib.sensitivity_toolbox', logging.WARNING):
+ sipopt(m,[m.eta1,m.eta1],
+ [m.perturbed_eta1,m.perturbed_eta2],
+ cloneModel=False)
+ self.assertIn("DEPRECATED: The sipopt function has been deprecated. Use the "
+ "sensitivity_calculation() function with method='sipopt' to access",
+ output.getvalue().replace('\n', ' '))
+
+
+ @unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
+ def test_sipopt_equivalent(self):
+ m1 = param_ex.create_model()
+ m1.perturbed_eta1 = Param(initialize = 4.0)
+ m1.perturbed_eta2 = Param(initialize = 1.0)
+
+ m2 = param_ex.create_model()
+ m2.perturbed_eta1 = Param(initialize = 4.0)
+ m2.perturbed_eta2 = Param(initialize = 1.0)
+
+ m11 = sipopt(m1,[m1.eta1,m1.eta2],
+ [m1.perturbed_eta1,m1.perturbed_eta2],
+ cloneModel=True)
+ m22 = sensitivity_calculation('sipopt',m2,[m2.eta1,m2.eta2],
+ [m2.perturbed_eta1,m2.perturbed_eta2],
+ cloneModel=True)
+ out1 = StringIO()
+ out2 = StringIO()
+ m11._sipopt_data.constList.pprint(ostream=out1)
+ m22._sipopt_data.constList.pprint(ostream=out2)
+ self.assertMultiLineEqual(out1.getvalue(), out2.getvalue())
+
+ @unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
+ @unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
+ def test_kaug_deprecated(self):
+ m = param_ex.create_model()
+ m.perturbed_eta1 = Param(initialize = 4.0)
+ m.perturbed_eta2 = Param(initialize = 1.0)
+
+ output = StringIO()
+ with LoggingIntercept(output, 'pyomo.contrib.sensitivity_toolbox', logging.WARNING):
+ kaug(m,[m.eta1,m.eta1],
+ [m.perturbed_eta1,m.perturbed_eta2],
+ cloneModel=False)
+ self.assertIn("DEPRECATED: The kaug function has been deprecated. Use the "
+ "sensitivity_calculation() function with method='kaug'",
+ output.getvalue().replace('\n', ' '))
+
+ @unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
+ @unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
+ def test_kaug_equivalent(self):
+ m1 = param_ex.create_model()
+ m1.perturbed_eta1 = Param(initialize = 4.0)
+ m1.perturbed_eta2 = Param(initialize = 1.0)
+
+ m2 = param_ex.create_model()
+ m2.perturbed_eta1 = Param(initialize = 4.0)
+ m2.perturbed_eta2 = Param(initialize = 1.0)
+
+ m11 = kaug(m1,[m1.eta1,m1.eta2],
+ [m1.perturbed_eta1,m1.perturbed_eta2],
+ cloneModel=True)
+ m22 = sensitivity_calculation('kaug',m2,[m2.eta1,m2.eta2],
+ [m2.perturbed_eta1,m2.perturbed_eta2],
+ cloneModel=True)
+ out1 = StringIO()
+ out2 = StringIO()
+ m11.pprint(ostream=out1)
+ m22.pprint(ostream=out2)
+ self.assertMultiLineEqual(out1.getvalue(), out2.getvalue())
+
+
class TestSensitivityToolbox(unittest.TestCase):
# test arguments
@@ -49,35 +135,30 @@ def test_bad_arg(self):
# verify ValueError thrown when param and perturb list are different
# lengths
- try:
- Result = sipopt(m,list_one,list_two)
- self.fail("Expected ValueError: for different length lists")
- except ValueError:
- pass
+ with self.assertRaises(ValueError) as context:
+ Result = sensitivity_calculation('sipopt',m,list_one,list_two)
+ self.assertTrue("Length of paramSubList argument does not equal "
+ "length of perturbList" in str(context.exception))
# verify ValueError thrown when param list has a Var in it
- try:
- Result = sipopt(m,list_three,list_two)
- self.fail("Expected ValueError: variable sent through paramSubList")
- except ValueError:
- pass
+ with self.assertRaises(ValueError) as context:
+ Result = sensitivity_calculation('sipopt',m,list_three,list_one)
+ self.assertTrue("paramSubList argument is expecting a list of Params" in str(context.exception))
# verify ValueError thrown when perturb list has Var in it
- try:
- Result = sipopt(m,list_one,list_three)
- self.fail("Expected ValueError: variable sent through perturbList")
- except ValueError:
- pass
+ with self.assertRaises(ValueError) as context:
+ Result = sensitivity_calculation('sipopt',m,list_one,list_three)
+ self.assertTrue("perturbList argument is expecting a list of Params" in str(context.exception))
# verify ValueError thrown when param list has an unmutable param
- try:
- Result = sipopt(m,list_four,list_one)
- self.fail("Expected ValueError:"
- "unmutable param sent through paramSubList")
- except ValueError:
- pass
-
+ with self.assertRaises(ValueError) as context:
+ Result = sensitivity_calculation('sipopt',m,list_four,list_one)
+ self.assertTrue("parameters within paramSubList must be mutable" in str(context.exception))
+ # verify ValueError thrown when an invalid method is specified
+ with self.assertRaises(ValueError) as context:
+ Result = sensitivity_calculation('foo',m,list_four,list_one)
+ self.assertTrue("method should be 'sipopt' or 'kaug'" in str(context.exception))
# test feedbackController Solution when the model gets cloned
@unittest.skipIf(not scipy_available, "scipy is required for this test")
@@ -90,7 +171,7 @@ def test_clonedModel_soln(self):
m_orig.perturbed_a = Param(initialize=-0.25)
m_orig.perturbed_H = Param(initialize=0.55)
- m_sipopt = sipopt(m_orig,[m_orig.a,m_orig.H],
+ m_sipopt = sensitivity_calculation('sipopt',m_orig,[m_orig.a,m_orig.H],
[m_orig.perturbed_a,m_orig.perturbed_H],
cloneModel=True)
@@ -185,7 +266,7 @@ def test_noClone_soln(self):
m_orig.perturbed_a = Param(initialize=-0.25)
m_orig.perturbed_H = Param(initialize=0.55)
- m_sipopt = sipopt(m_orig,[m_orig.a,m_orig.H],
+ m_sipopt = sensitivity_calculation('sipopt',m_orig,[m_orig.a,m_orig.H],
[m_orig.perturbed_a,m_orig.perturbed_H],
cloneModel=False)
@@ -257,8 +338,6 @@ def test_noClone_soln(self):
self.assertAlmostEqual(value(m_sipopt.J),0.0048956783,8)
-
-
# test indexed param mapping to var and perturbed values
@unittest.skipIf(not scipy_available, "scipy is required for this test")
@unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
@@ -282,7 +361,7 @@ def test_indexedParamsMapping(self):
m.aaDelta = Param(initialize =0.0001001)
- m_sipopt = sipopt(m, [m.eps,m.qq,m.aa],
+ m_sipopt = sensitivity_calculation('sipopt',m, [m.eps,m.qq,m.aa],
[m.epsDelta,m.qqDelta,m.aaDelta])
# param to var data
@@ -316,7 +395,7 @@ def test_constraintSub(self):
m.pert_a = Param(initialize=0.01)
m.pert_b = Param(initialize=1.01)
- m_sipopt = sipopt(m,[m.a,m.b], [m.pert_a,m.pert_b])
+ m_sipopt = sensitivity_calculation('sipopt',m,[m.a,m.b], [m.pert_a,m.pert_b])
# verify substitutions in equality constraint
self.assertTrue(m_sipopt.C_equal.lower.ctype is Param and
@@ -357,8 +436,7 @@ def test_constraintSub(self):
@unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
def test_parameter_example(self):
- from pyomo.contrib.sensitivity_toolbox.examples.parameter import run_example
- d = run_example()
+ d = param_ex.run_example()
d_correct = {'eta1':4.5, 'eta2':1.0, 'x1_init':0.15, 'x2_init':0.15, 'x3_init':0.0,
'cost_sln':0.5, 'x1_sln':0.5, 'x2_sln':0.5, 'x3_sln':0.0, 'eta1_pert':4.0,
@@ -372,53 +450,7 @@ def test_parameter_example(self):
# Test kaug
- # Perform the same tests as ipopt_sens
- # test arguments
- @unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
- @unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
- def test_kaug_bad_arg_kaug(self):
- m = ConcreteModel()
- m.t = ContinuousSet(bounds=(0,1))
-
- m.a = Param(initialize=1, mutable=True)
- m.b = Param(initialize=2, mutable=True)
- m.c = Param(initialize=3, mutable=False)
-
- m.x = Var(m.t)
-
- list_one = [m.a,m.b]
- list_two = [m.a,m.b,m.c]
- list_three = [m.a, m.x]
- list_four = [m.a,m.c]
-
- # verify ValueError thrown when param and perturb list are different
- # lengths
- with self.assertRaises(ValueError):
- Result = kaug(m, list_one, list_two)
-
- # verify ValueError thrown when param list has a Var in it
- try:
- Result = kaug(m,list_three,list_two)
- self.fail("Expected ValueError: variable sent through paramSubList")
- except ValueError:
- pass
-
- # verify ValueError thrown when perturb list has Var in it
- try:
- Result = kaug(m,list_one,list_three)
- self.fail("Expected ValueError: variable sent through perturbList")
- except ValueError:
- pass
-
- # verify ValueError thrown when param list has an unmutable param
- try:
- Result = kaug(m,list_four,list_one)
- self.fail("Expected ValueError:"
- "unmutable param sent through paramSubList")
- except ValueError:
- pass
-
-
+ # Perform the same tests as for sipopt
# test feedbackController Solution when the model gets cloned
@unittest.skipIf(not scipy_available, "scipy is required for this test")
@unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
@@ -430,7 +462,7 @@ def test_kaug_clonedModel_soln_kaug(self):
m_orig.perturbed_a = Param(initialize=-0.25)
m_orig.perturbed_H = Param(initialize=0.55)
- m_kaug = kaug(m_orig,[m_orig.a,m_orig.H],
+ m_kaug = sensitivity_calculation('kaug',m_orig,[m_orig.a,m_orig.H],
[m_orig.perturbed_a,m_orig.perturbed_H],
cloneModel=True)
@@ -525,7 +557,7 @@ def test_noClone_soln_kaug(self):
m_orig.perturbed_a = Param(initialize=-0.25)
m_orig.perturbed_H = Param(initialize=0.55)
- m_kaug = kaug(m_orig,[m_orig.a,m_orig.H],
+ m_kaug = sensitivity_calculation('kaug',m_orig,[m_orig.a,m_orig.H],
[m_orig.perturbed_a,m_orig.perturbed_H],
cloneModel=False)
@@ -612,7 +644,7 @@ def test_indexedParamsMapping_kaug(self):
m.aaDelta = Param(initialize =0.0001001)
- m_kaug = kaug(m, [m.eps,m.qq,m.aa],
+ m_kaug = sensitivity_calculation('kaug',m, [m.eps,m.qq,m.aa],
[m.epsDelta,m.qqDelta,m.aaDelta])
# param to var data
@@ -648,7 +680,7 @@ def test_constraintSub_kaug(self):
# m_kaug = kaug(m,[m.a,m.b], [m.pert_a,m.pert_b])
# verify ValueError thrown when param list has an unmutable param
with self.assertRaises(Exception) as context:
- m_kaug = kaug(m,[m.a,m.b], [m.pert_a,m.pert_b])
+ m_kaug = sensitivity_calculation('kaug',m,[m.a,m.b], [m.pert_a,m.pert_b])
self.assertTrue('kaug does not support inequality constraints.' in str(context.exception))
# Test example `parameter_kaug.py`
@@ -656,8 +688,7 @@ def test_constraintSub_kaug(self):
@unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
def test_parameter_example_kaug(self):
- from parameter_kaug import example
- d = example()
+ d = param_kaug_ex.run_example()
d_correct = {'eta1':4.5, 'eta2':1.0, 'x1_init':0.15, 'x2_init':0.15, 'x3_init':0.0,
'eta1_pert':4.0, 'eta2_pert':1.0, 'x1_pert':0.3333333,'x2_pert':0.6666667,
diff --git a/pyomo/contrib/sensitivity_toolbox/tests/test_sens_sensitivity_calculation.py b/pyomo/contrib/sensitivity_toolbox/tests/test_sens_sensitivity_calculation.py
deleted file mode 100644
index aaef6b4d088..00000000000
--- a/pyomo/contrib/sensitivity_toolbox/tests/test_sens_sensitivity_calculation.py
+++ /dev/null
@@ -1,743 +0,0 @@
-# ____________________________________________________________________________
-#
-# Pyomo: Python Optimization Modeling Objects
-# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
-# Under the terms of Contract DE-NA0003525 with National Technology and
-# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
-# rights in this software.
-# This software is distributed under the 3-clause BSD License.
-# ____________________________________________________________________________
-
-"""
-Unit Tests for interfacing with sensitivity_calculation
-"""
-
-import pyutilib.th as unittest
-
-from pyomo.environ import *
-from pyomo.opt import SolverFactory
-from pyomo.dae import ContinuousSet
-from pyomo.common.dependencies import scipy_available
-from pyomo.core.expr.current import identify_variables
-from pyomo.contrib.sensitivity_toolbox.sens import sensitivity_calculation
-import pyomo.contrib.sensitivity_toolbox.examples.feedbackController as fc
-import pyomo.contrib.sensitivity_toolbox.examples.rangeInequality as ri
-import pyomo.contrib.sensitivity_toolbox.examples.HIV_Transmission as hiv
-
-opt = SolverFactory('ipopt_sens', solver_io='nl')
-opt_kaug = SolverFactory('k_aug',solver_io='nl')
-opt_dotsens = SolverFactory('dot_sens',solver_io='nl')
-
-class TestSensitivityToolbox(unittest.TestCase):
-
- # test arguments
- @unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
- def test_bad_arg(self):
- m = ConcreteModel()
- m.t = ContinuousSet(bounds=(0,1))
-
- m.a = Param(initialize=1, mutable=True)
- m.b = Param(initialize=2, mutable=True)
- m.c = Param(initialize=3, mutable=False)
-
- m.x = Var(m.t)
-
- list_one = [m.a,m.b]
- list_two = [m.a,m.b,m.c]
- list_three = [m.a, m.x]
- list_four = [m.a,m.c]
-
- # verify ValueError thrown when param and perturb list are different
- # lengths
- try:
- Result = sensitivity_calculation('sipopt', m,list_one,list_two)
- self.fail("Expected ValueError: for different length lists")
- except ValueError:
- pass
-
- # verify ValueError thrown when param list has a Var in it
- try:
- Result = sensitivity_calculation('sipopt', m,list_three,list_two)
- self.fail("Expected ValueError: variable sent through paramSubList")
- except ValueError:
- pass
-
- # verify ValueError thrown when perturb list has Var in it
- try:
- Result = sensitivity_calculation('sipopt', m,list_one,list_three)
- self.fail("Expected ValueError: variable sent through perturbList")
- except ValueError:
- pass
-
- # verify ValueError thrown when param list has an unmutable param
- try:
- Result = sensitivity_calculation('sipopt', m,list_four,list_one)
- self.fail("Expected ValueError:"
- "unmutable param sent through paramSubList")
- except ValueError:
- pass
-
-
-
- # test feedbackController Solution when the model gets cloned
- @unittest.skipIf(not scipy_available, "scipy is required for this test")
- @unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
- def test_clonedModel_soln(self):
-
- m_orig = fc.create_model()
- fc.initialize_model(m_orig,100)
-
- m_orig.perturbed_a = Param(initialize=-0.25)
- m_orig.perturbed_H = Param(initialize=0.55)
-
- m_sipopt = sensitivity_calculation('sipopt', m_orig,[m_orig.a,m_orig.H],
- [m_orig.perturbed_a,m_orig.perturbed_H],
- cloneModel=True)
-
- # verify cloned model has _sipopt_data block
- # and original model is untouched
- self.assertFalse(m_sipopt == m_orig)
-
- self.assertTrue(hasattr(m_sipopt,'_sipopt_data') and
- m_sipopt._sipopt_data.ctype is Block)
-
- self.assertFalse(hasattr(m_orig,'_sipopt_data'))
- self.assertFalse(hasattr(m_orig,'b'))
-
- # verify variable declaration
- self.assertTrue(hasattr(m_sipopt._sipopt_data,'a') and
- m_sipopt._sipopt_data.a.ctype is Var)
- self.assertTrue(hasattr(m_sipopt._sipopt_data,'H') and
- m_sipopt._sipopt_data.H.ctype is Var)
-
- # verify suffixes
- self.assertTrue(hasattr(m_sipopt,'sens_state_0') and
- m_sipopt.sens_state_0.ctype is Suffix and
- m_sipopt.sens_state_0[m_sipopt._sipopt_data.H]==2 and
- m_sipopt.sens_state_0[m_sipopt._sipopt_data.a]==1)
-
- self.assertTrue(hasattr(m_sipopt,'sens_state_1') and
- m_sipopt.sens_state_1.ctype is Suffix and
- m_sipopt.sens_state_1[m_sipopt._sipopt_data.H]==2 and
- m_sipopt.sens_state_1[m_sipopt._sipopt_data.a]==1)
-
- self.assertTrue(hasattr(m_sipopt,'sens_state_value_1') and
- m_sipopt.sens_state_value_1.ctype is Suffix and
- m_sipopt.sens_state_value_1[
- m_sipopt._sipopt_data.H]==0.55 and
- m_sipopt.sens_state_value_1[
- m_sipopt._sipopt_data.a]==-0.25)
-
- self.assertTrue(hasattr(m_sipopt,'sens_init_constr') and
- m_sipopt.sens_init_constr.ctype is Suffix and
- m_sipopt.sens_init_constr[
- m_sipopt._sipopt_data.paramConst[1]]==1 and
- m_sipopt.sens_init_constr[
- m_sipopt._sipopt_data.paramConst[2]]==2)
-
- self.assertTrue(hasattr(m_sipopt,'sens_sol_state_1') and
- m_sipopt.sens_sol_state_1.ctype is Suffix)
- self.assertAlmostEqual(
- m_sipopt.sens_sol_state_1[
- m_sipopt.F[15]],-0.00102016765,8)
-
- self.assertTrue(hasattr(m_sipopt,'sens_sol_state_1_z_L') and
- m_sipopt.sens_sol_state_1_z_L.ctype is Suffix)
- self.assertAlmostEqual(
- m_sipopt.sens_sol_state_1_z_L[
- m_sipopt.u[15]],-2.181712e-09,13)
-
- self.assertTrue(hasattr(m_sipopt,'sens_sol_state_1_z_U') and
- m_sipopt.sens_sol_state_1_z_U.ctype is Suffix)
- self.assertAlmostEqual(
- m_sipopt.sens_sol_state_1_z_U[
- m_sipopt.u[15]],6.580899e-09,13)
-
- # verify deactivated constraints for cloned model
- self.assertFalse(m_sipopt.FDiffCon[0].active and
- m_sipopt.FDiffCon[7.5].active and
- m_sipopt.FDiffCon[15].active )
-
- self.assertFalse(m_sipopt.x_dot[0].active and
- m_sipopt.x_dot[7.5].active and
- m_sipopt.x_dot[15].active )
-
- # verify constraints on original model are still active
- self.assertTrue(m_orig.FDiffCon[0].active and
- m_orig.FDiffCon[7.5].active and
- m_orig.FDiffCon[15].active )
-
- self.assertTrue(m_orig.x_dot[0].active and
- m_orig.x_dot[7.5].active and
- m_orig.x_dot[15].active )
-
- # verify solution
- self.assertAlmostEqual(value(m_sipopt.J),0.0048956783,8)
-
-
- @unittest.skipIf(not scipy_available, "scipy is required for this test")
- @unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
- def test_noClone_soln(self):
-
- m_orig = fc.create_model()
- fc.initialize_model(m_orig,100)
-
- m_orig.perturbed_a = Param(initialize=-0.25)
- m_orig.perturbed_H = Param(initialize=0.55)
-
- m_sipopt = sensitivity_calculation('sipopt', m_orig,[m_orig.a,m_orig.H],
- [m_orig.perturbed_a,m_orig.perturbed_H],
- cloneModel=False)
-
- self.assertTrue(m_sipopt == m_orig)
-
- # test _sipopt_data block exists
- self.assertTrue(hasattr(m_orig,'_sipopt_data') and
- m_orig._sipopt_data.ctype is Block)
-
- # test variable declaration
- self.assertTrue(hasattr(m_sipopt._sipopt_data,'a') and
- m_sipopt._sipopt_data.a.ctype is Var)
- self.assertTrue(hasattr(m_sipopt._sipopt_data,'H') and
- m_sipopt._sipopt_data.H.ctype is Var)
-
- # test for suffixes
- self.assertTrue(hasattr(m_sipopt,'sens_state_0') and
- m_sipopt.sens_state_0.ctype is Suffix and
- m_sipopt.sens_state_0[m_sipopt._sipopt_data.H]==2 and
- m_sipopt.sens_state_0[m_sipopt._sipopt_data.a]==1)
-
- self.assertTrue(hasattr(m_sipopt,'sens_state_1') and
- m_sipopt.sens_state_1.ctype is Suffix and
- m_sipopt.sens_state_1[m_sipopt._sipopt_data.H]==2 and
- m_sipopt.sens_state_1[m_sipopt._sipopt_data.a]==1)
-
- self.assertTrue(hasattr(m_sipopt,'sens_state_value_1') and
- m_sipopt.sens_state_value_1.ctype is Suffix and
- m_sipopt.sens_state_value_1[
- m_sipopt._sipopt_data.H]==0.55 and
- m_sipopt.sens_state_value_1[
- m_sipopt._sipopt_data.a]==-0.25)
-
- self.assertTrue(hasattr(m_sipopt,'sens_init_constr') and
- m_sipopt.sens_init_constr.ctype is Suffix and
- m_sipopt.sens_init_constr[
- m_sipopt._sipopt_data.paramConst[1]]==1 and
- m_sipopt.sens_init_constr[
- m_sipopt._sipopt_data.paramConst[2]]==2)
-
- self.assertTrue(hasattr(m_sipopt,'sens_sol_state_1') and
- m_sipopt.sens_sol_state_1.ctype is Suffix)
- self.assertAlmostEqual(
- m_sipopt.sens_sol_state_1[
- m_sipopt.F[15]],-0.00102016765,8)
-
- self.assertTrue(hasattr(m_sipopt,'sens_sol_state_1_z_L') and
- m_sipopt.sens_sol_state_1_z_L.ctype is Suffix)
- self.assertAlmostEqual(
- m_sipopt.sens_sol_state_1_z_L[
- m_sipopt.u[15]],-2.181712e-09,13)
-
- self.assertTrue(hasattr(m_sipopt,'sens_sol_state_1_z_U') and
- m_sipopt.sens_sol_state_1_z_U.ctype is Suffix)
- self.assertAlmostEqual(
- m_sipopt.sens_sol_state_1_z_U[
- m_sipopt.u[15]],6.580899e-09,13)
-
- # verify deactivated constraints on model
- self.assertFalse(m_sipopt.FDiffCon[0].active and
- m_sipopt.FDiffCon[7.5].active and
- m_sipopt.FDiffCon[15].active )
-
- self.assertFalse(m_sipopt.x_dot[0].active and
- m_sipopt.x_dot[7.5].active and
- m_sipopt.x_dot[15].active )
-
- # test model solution
- self.assertAlmostEqual(value(m_sipopt.J),0.0048956783,8)
-
-
-
-
- # test indexed param mapping to var and perturbed values
- @unittest.skipIf(not scipy_available, "scipy is required for this test")
- @unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
- def test_indexedParamsMapping(self):
-
- m = hiv.create_model()
- hiv.initialize_model(m,10,5,1)
-
- m.epsDelta = Param(initialize = 0.75001)
-
- q_del = {}
- q_del[(0,0)] = 1.001
- q_del[(0,1)] = 1.002
- q_del[(1,0)] = 1.003
- q_del[(1,1)] = 1.004
- q_del[(2,0)] = 0.83001
- q_del[(2,1)] = 0.83002
- q_del[(3,0)] = 0.42001
- q_del[(4,0)] = 0.17001
- m.qqDelta = Param(m.ij, initialize = q_del)
-
- m.aaDelta = Param(initialize =0.0001001)
-
- m_sipopt = sensitivity_calculation('sipopt', m, [m.eps,m.qq,m.aa],
- [m.epsDelta,m.qqDelta,m.aaDelta])
-
- # param to var data
- self.assertEqual(
- m_sipopt._sipopt_data.paramConst[1].lower.local_name, 'eps')
- self.assertEqual(
- m_sipopt._sipopt_data.paramConst[1].body.local_name, 'eps')
- self.assertEqual(
- m_sipopt._sipopt_data.paramConst[1].upper.local_name, 'eps')
- self.assertEqual(
- m_sipopt._sipopt_data.paramConst[6].lower.local_name, 'qq[2,0]')
- self.assertEqual(
- m_sipopt._sipopt_data.paramConst[6].body.local_name, 'qq[2,0]')
- self.assertEqual(
- m_sipopt._sipopt_data.paramConst[6].upper.local_name, 'qq[2,0]')
- self.assertEqual(
- m_sipopt._sipopt_data.paramConst[10].lower.local_name, 'aa')
- self.assertEqual(
- m_sipopt._sipopt_data.paramConst[10].body.local_name, 'aa')
- self.assertEqual(
- m_sipopt._sipopt_data.paramConst[10].upper.local_name, 'aa')
-
-
-
- # test Constraint substitution
- @unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
- def test_constraintSub(self):
-
- m = ri.create_model()
-
- m.pert_a = Param(initialize=0.01)
- m.pert_b = Param(initialize=1.01)
-
- m_sipopt = sensitivity_calculation('sipopt', m,[m.a,m.b], [m.pert_a,m.pert_b])
-
- # verify substitutions in equality constraint
- self.assertTrue(m_sipopt.C_equal.lower.ctype is Param and
- m_sipopt.C_equal.upper.ctype is Param)
- self.assertFalse(m_sipopt.C_equal.active)
-
- self.assertTrue(m_sipopt._sipopt_data.constList[3].lower == 0.0 and
- m_sipopt._sipopt_data.constList[3].upper == 0.0 and
- len(list(identify_variables(
- m_sipopt._sipopt_data.constList[3].body))) == 2)
-
- # verify substitutions in one-sided bounded constraint
- self.assertTrue(m_sipopt.C_singleBnd.lower is None and
- m_sipopt.C_singleBnd.upper.ctype is Param)
- self.assertFalse(m_sipopt.C_singleBnd.active)
-
- self.assertTrue(m_sipopt._sipopt_data.constList[4].lower is None and
- m_sipopt._sipopt_data.constList[4].upper == 0.0 and
- len(list(identify_variables(
- m_sipopt._sipopt_data.constList[4].body))) == 2)
-
- # verify substitutions in ranged inequality constraint
- self.assertTrue(m_sipopt.C_rangedIn.lower.ctype is Param and
- m_sipopt.C_rangedIn.upper.ctype is Param)
- self.assertFalse(m_sipopt.C_rangedIn.active)
-
- self.assertTrue(m_sipopt._sipopt_data.constList[1].lower is None and
- m_sipopt._sipopt_data.constList[1].upper == 0.0 and
- len(list(identify_variables(
- m_sipopt._sipopt_data.constList[1].body))) == 2)
-
- self.assertTrue(m_sipopt._sipopt_data.constList[2].lower is None and
- m_sipopt._sipopt_data.constList[2].upper == 0.0 and
- len(list(identify_variables(
- m_sipopt._sipopt_data.constList[2].body))) == 2)
-
- # Test example `parameter.py`
- @unittest.skipIf(not opt.available(False), "ipopt_sens is not available")
- def test_parameter_example(self):
-
- m = ConcreteModel()
-
- m.x1 = Var(initialize = 0.15, within=NonNegativeReals)
- m.x2 = Var(initialize = 0.15, within=NonNegativeReals)
- m.x3 = Var(initialize = 0.0, within=NonNegativeReals)
-
- m.eta1 = Param(initialize=4.5, mutable=True)
- m.eta2 = Param(initialize=1.0, mutable=True)
-
- m.const1 = Constraint(expr=6*m.x1+3*m.x2+2*m.x3-m.eta1 ==0)
- m.const2 = Constraint(expr=m.eta2*m.x1+m.x2-m.x3-1 ==0)
- m.cost = Objective(expr=m.x1**2+m.x2**2+m.x3**2)
-
- m.perturbed_eta1 = Param(initialize = 4.0)
- m.perturbed_eta2 = Param(initialize = 1.0)
-
-
- m_sipopt = sensitivity_calculation('sipopt', m,[m.eta1,m.eta2],
- [m.perturbed_eta1,m.perturbed_eta2],
- streamSoln=True)
- x1 = m_sipopt.sens_sol_state_1[m_sipopt.x1]
- x2 = m_sipopt.sens_sol_state_1[m_sipopt.x2]
- x3 = m_sipopt.sens_sol_state_1[m_sipopt.x3]
- obj = x1**2 + x2**2 + x3**2
-
- d = dict()
- d['eta1'] = m.eta1()
- d['eta2'] = m.eta2()
- d['x1_init'] = m.x1()
- d['x2_init'] = m.x2()
- d['x3_init'] = m.x3()
- d['x1_sln'] = m_sipopt.x1()
- d['x2_sln'] = m_sipopt.x2()
- d['x3_sln'] = m_sipopt.x3()
- d['cost_sln'] = m_sipopt.cost()
- d['eta1_pert'] = m_sipopt.perturbed_eta1()
- d['eta2_pert'] = m_sipopt.perturbed_eta2()
- d['x1_pert'] = x1
- d['x2_pert'] = x2
- d['x3_pert'] = x3
- d['cost_pert'] = obj
-
- d_correct = {'eta1':4.5, 'eta2':1.0, 'x1_init':0.15, 'x2_init':0.15, 'x3_init':0.0,
- 'cost_sln':0.5, 'x1_sln':0.5, 'x2_sln':0.5, 'x3_sln':0.0, 'eta1_pert':4.0,
- 'eta2_pert':1.0, 'x1_pert':0.3333333,'x2_pert':0.6666667,'x3_pert':0.0,
- 'cost_pert':0.55555556}
-
- for k in d_correct.keys():
- # Check each element of the 'correct' dictionary against the returned
- # dictionary to 3 decimal places
- self.assertAlmostEqual(d[k],d_correct[k],3)
-
-
- # Test kaug
- # Perform the same tests as ipopt_sens
- # test arguments
- @unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
- @unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
- def test_kaug_bad_arg_kaug(self):
- m = ConcreteModel()
- m.t = ContinuousSet(bounds=(0,1))
-
- m.a = Param(initialize=1, mutable=True)
- m.b = Param(initialize=2, mutable=True)
- m.c = Param(initialize=3, mutable=False)
-
- m.x = Var(m.t)
-
- list_one = [m.a,m.b]
- list_two = [m.a,m.b,m.c]
- list_three = [m.a, m.x]
- list_four = [m.a,m.c]
-
- # verify ValueError thrown when param and perturb list are different
- # lengths
- with self.assertRaises(ValueError):
- Result = sensitivity_calculation('kaug', m, list_one, list_two)
-
- # verify ValueError thrown when param list has a Var in it
- try:
- Result = sensitivity_calculation('kaug', m,list_three,list_two)
- self.fail("Expected ValueError: variable sent through paramSubList")
- except ValueError:
- pass
-
- # verify ValueError thrown when perturb list has Var in it
- try:
- Result = sensitivity_calculation('kaug', m,list_one,list_three)
- self.fail("Expected ValueError: variable sent through perturbList")
- except ValueError:
- pass
-
- # verify ValueError thrown when param list has an unmutable param
- try:
- Result = sensitivity_calculation('kaug', m,list_four,list_one)
- self.fail("Expected ValueError:"
- "unmutable param sent through paramSubList")
- except ValueError:
- pass
-
-
- # test feedbackController Solution when the model gets cloned
- @unittest.skipIf(not scipy_available, "scipy is required for this test")
- @unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
- @unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
- def test_kaug_clonedModel_soln_kaug(self):
- m_orig = fc.create_model()
- fc.initialize_model(m_orig,100)
-
- m_orig.perturbed_a = Param(initialize=-0.25)
- m_orig.perturbed_H = Param(initialize=0.55)
-
- m_kaug = sensitivity_calculation('kaug', m_orig,[m_orig.a,m_orig.H],
- [m_orig.perturbed_a,m_orig.perturbed_H],
- cloneModel=True)
-
- # verify cloned model has _kaug_data block
- # and original model is untouched
- self.assertFalse(m_kaug == m_orig)
-
- self.assertTrue(hasattr(m_kaug,'_kaug_data') and
- m_kaug._kaug_data.ctype is Block)
-
- self.assertFalse(hasattr(m_orig,'_kaug_data'))
- self.assertFalse(hasattr(m_orig,'b'))
-
- # verify variable declaration
- self.assertTrue(hasattr(m_kaug._kaug_data,'a') and
- m_kaug._kaug_data.a.ctype is Var)
- self.assertTrue(hasattr(m_kaug._kaug_data,'H') and
- m_kaug._kaug_data.H.ctype is Var)
-
- # verify suffixes
- self.assertTrue(hasattr(m_kaug,'sens_state_0') and
- m_kaug.sens_state_0.ctype is Suffix and
- m_kaug.sens_state_0[m_kaug._kaug_data.H]==2 and
- m_kaug.sens_state_0[m_kaug._kaug_data.a]==1)
- self.assertTrue(hasattr(m_kaug,'sens_state_1') and
- m_kaug.sens_state_1.ctype is Suffix and
- m_kaug.sens_state_1[m_kaug._kaug_data.H]==2 and
- m_kaug.sens_state_1[m_kaug._kaug_data.a]==1)
- self.assertTrue(hasattr(m_kaug,'sens_state_value_1') and
- m_kaug.sens_state_value_1.ctype is Suffix and
- m_kaug.sens_state_value_1[
- m_kaug._kaug_data.H]==0.55 and
- m_kaug.sens_state_value_1[
- m_kaug._kaug_data.a]==-0.25)
- self.assertTrue(hasattr(m_kaug,'sens_init_constr') and
- m_kaug.sens_init_constr.ctype is Suffix and
- m_kaug.sens_init_constr[
- m_kaug._kaug_data.paramConst[1]]==1 and
- m_kaug.sens_init_constr[
- m_kaug._kaug_data.paramConst[2]]==2)
- self.assertTrue(hasattr(m_kaug,'DeltaP') and
- m_kaug.DeltaP.ctype is Suffix and
- m_kaug.DeltaP[m_kaug._kaug_data.paramConst[1]]==0.04999999999999999 and
- m_kaug.DeltaP[m_kaug._kaug_data.paramConst[2]]==-0.050000000000000044)
- self.assertTrue(hasattr(m_kaug,'dcdp') and
- m_kaug.dcdp.ctype is Suffix and
- m_kaug.dcdp[m_kaug._kaug_data.paramConst[1]]==1 and
- m_kaug.dcdp[m_kaug._kaug_data.paramConst[2]]==2)
- self.assertTrue(hasattr(m_kaug,'sens_sol_state_1') and
- m_kaug.sens_sol_state_1.ctype is Suffix)
-
- self.assertTrue(hasattr(m_kaug,'ipopt_zL_in') and
- m_kaug.ipopt_zL_in.ctype is Suffix)
- self.assertAlmostEqual(
- m_kaug.ipopt_zL_in[
- m_kaug.u[15]],7.162686166847096e-09,13)
-
- self.assertTrue(hasattr(m_kaug,'ipopt_zU_in') and
- m_kaug.ipopt_zU_in.ctype is Suffix)
- self.assertAlmostEqual(
- m_kaug.ipopt_zU_in[
- m_kaug.u[15]],-1.2439730261288605e-08,13)
- # verify deactivated constraints for cloned model
- self.assertFalse(m_kaug.FDiffCon[0].active and
- m_kaug.FDiffCon[7.5].active and
- m_kaug.FDiffCon[15].active )
-
- self.assertFalse(m_kaug.x_dot[0].active and
- m_kaug.x_dot[7.5].active and
- m_kaug.x_dot[15].active )
-
- # verify constraints on original model are still active
- self.assertTrue(m_orig.FDiffCon[0].active and
- m_orig.FDiffCon[7.5].active and
- m_orig.FDiffCon[15].active )
-
- self.assertTrue(m_orig.x_dot[0].active and
- m_orig.x_dot[7.5].active and
- m_orig.x_dot[15].active )
-
- # verify solution
- self.assertAlmostEqual(value(m_kaug.J),0.002633263921107476,8)
-
- @unittest.skipIf(not scipy_available, "scipy is required for this test")
- @unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
- @unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
- def test_noClone_soln_kaug(self):
-
- m_orig = fc.create_model()
- fc.initialize_model(m_orig,100)
-
- m_orig.perturbed_a = Param(initialize=-0.25)
- m_orig.perturbed_H = Param(initialize=0.55)
-
- m_kaug = sensitivity_calculation('kaug', m_orig,[m_orig.a,m_orig.H],
- [m_orig.perturbed_a,m_orig.perturbed_H],
- cloneModel=False)
-
- self.assertTrue(m_kaug == m_orig)
-
- # verify suffixes
- self.assertTrue(hasattr(m_kaug,'sens_state_0') and
- m_kaug.sens_state_0.ctype is Suffix and
- m_kaug.sens_state_0[m_kaug._kaug_data.H]==2 and
- m_kaug.sens_state_0[m_kaug._kaug_data.a]==1)
- self.assertTrue(hasattr(m_kaug,'sens_state_1') and
- m_kaug.sens_state_1.ctype is Suffix and
- m_kaug.sens_state_1[m_kaug._kaug_data.H]==2 and
- m_kaug.sens_state_1[m_kaug._kaug_data.a]==1)
- self.assertTrue(hasattr(m_kaug,'sens_state_value_1') and
- m_kaug.sens_state_value_1.ctype is Suffix and
- m_kaug.sens_state_value_1[
- m_kaug._kaug_data.H]==0.55 and
- m_kaug.sens_state_value_1[
- m_kaug._kaug_data.a]==-0.25)
- self.assertTrue(hasattr(m_kaug,'sens_init_constr') and
- m_kaug.sens_init_constr.ctype is Suffix and
- m_kaug.sens_init_constr[
- m_kaug._kaug_data.paramConst[1]]==1 and
- m_kaug.sens_init_constr[
- m_kaug._kaug_data.paramConst[2]]==2)
- self.assertTrue(hasattr(m_kaug,'DeltaP') and
- m_kaug.DeltaP.ctype is Suffix and
- m_kaug.DeltaP[m_kaug._kaug_data.paramConst[1]]==0.04999999999999999 and
- m_kaug.DeltaP[m_kaug._kaug_data.paramConst[2]]==-0.050000000000000044)
- self.assertTrue(hasattr(m_kaug,'dcdp') and
- m_kaug.dcdp.ctype is Suffix and
- m_kaug.dcdp[m_kaug._kaug_data.paramConst[1]]==1 and
- m_kaug.dcdp[m_kaug._kaug_data.paramConst[2]]==2)
- self.assertTrue(hasattr(m_kaug,'sens_sol_state_1') and
- m_kaug.sens_sol_state_1.ctype is Suffix)
-
- self.assertTrue(hasattr(m_kaug,'ipopt_zL_in') and
- m_kaug.ipopt_zL_in.ctype is Suffix)
- self.assertAlmostEqual(
- m_kaug.ipopt_zL_in[
- m_kaug.u[15]],7.162686166847096e-09,13)
-
- self.assertTrue(hasattr(m_kaug,'ipopt_zU_in') and
- m_kaug.ipopt_zU_in.ctype is Suffix)
- self.assertAlmostEqual(
- m_kaug.ipopt_zU_in[
- m_kaug.u[15]],-1.2439730261288605e-08,13)
- # verify deactivated constraints for cloned model
- self.assertFalse(m_kaug.FDiffCon[0].active and
- m_kaug.FDiffCon[7.5].active and
- m_kaug.FDiffCon[15].active )
-
- self.assertFalse(m_kaug.x_dot[0].active and
- m_kaug.x_dot[7.5].active and
- m_kaug.x_dot[15].active )
-
-
- # verify solution
- self.assertAlmostEqual(value(m_kaug.J),0.002633263921107476,8)
-
-
- # test indexed param mapping to var and perturbed values
- @unittest.skipIf(not scipy_available, "scipy is required for this test")
- @unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
- @unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
- def test_indexedParamsMapping_kaug(self):
-
- m = hiv.create_model()
- hiv.initialize_model(m,10,5,1)
-
- m.epsDelta = Param(initialize = 0.75001)
-
- q_del = {}
- q_del[(0,0)] = 1.001
- q_del[(0,1)] = 1.002
- q_del[(1,0)] = 1.003
- q_del[(1,1)] = 1.004
- q_del[(2,0)] = 0.83001
- q_del[(2,1)] = 0.83002
- q_del[(3,0)] = 0.42001
- q_del[(4,0)] = 0.17001
- m.qqDelta = Param(m.ij, initialize = q_del)
-
- m.aaDelta = Param(initialize =0.0001001)
-
- m_kaug = sensitivity_calculation('kaug', m, [m.eps,m.qq,m.aa],
- [m.epsDelta,m.qqDelta,m.aaDelta])
-
- # param to var data
- self.assertEqual(
- m_kaug._kaug_data.paramConst[1].lower.local_name, 'eps')
- self.assertEqual(
- m_kaug._kaug_data.paramConst[1].body.local_name, 'eps')
- self.assertEqual(
- m_kaug._kaug_data.paramConst[1].upper.local_name, 'eps')
- self.assertEqual(
- m_kaug._kaug_data.paramConst[6].lower.local_name, 'qq[2,0]')
- self.assertEqual(
- m_kaug._kaug_data.paramConst[6].body.local_name, 'qq[2,0]')
- self.assertEqual(
- m_kaug._kaug_data.paramConst[6].upper.local_name, 'qq[2,0]')
- self.assertEqual(
- m_kaug._kaug_data.paramConst[10].lower.local_name, 'aa')
- self.assertEqual(
- m_kaug._kaug_data.paramConst[10].body.local_name, 'aa')
- self.assertEqual(
- m_kaug._kaug_data.paramConst[10].upper.local_name, 'aa')
-
-
- # test Constraint substitution
- @unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
- @unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
- def test_constraintSub_kaug(self):
- m = ri.create_model()
-
- m.pert_a = Param(initialize=0.01)
- m.pert_b = Param(initialize=1.01)
-
- # m_kaug = kaug(m,[m.a,m.b], [m.pert_a,m.pert_b])
- # verify ValueError thrown when param list has an unmutable param
- with self.assertRaises(Exception) as context:
- m_kaug = sensitivity_calculation('kaug', m,[m.a,m.b], [m.pert_a,m.pert_b])
- self.assertTrue('kaug does not support inequality constraints.' in str(context.exception))
-
- # Test example `parameter_kaug.py`
- @unittest.skipIf(not opt_kaug.available(False), "k_aug is not available")
- @unittest.skipIf(not opt_dotsens.available(False), "dot_sens is not available")
- def test_parameter_example_kaug(self):
-
-
- m = ConcreteModel()
-
- m.x1 = Var(initialize = 0.15, within=NonNegativeReals)
- m.x2 = Var(initialize = 0.15, within=NonNegativeReals)
- m.x3 = Var(initialize = 0.0, within=NonNegativeReals)
-
- m.eta1 = Param(initialize=4.5, mutable=True)
- m.eta2 = Param(initialize=1.0, mutable=True)
-
- m.const1 = Constraint(expr=6*m.x1+3*m.x2+2*m.x3-m.eta1 ==0)
- m.const2 = Constraint(expr=m.eta2*m.x1+m.x2-m.x3-1 ==0)
- m.cost = Objective(expr=m.x1**2+m.x2**2+m.x3**2)
-
- m.perturbed_eta1 = Param(initialize = 4.0)
- m.perturbed_eta2 = Param(initialize = 1.0)
-
-
- m_kaug_dsdp = sensitivity_calculation('kaug', m,[m.eta1,m.eta2],
- [m.perturbed_eta1,m.perturbed_eta2],
- streamSoln=True)
-
- d = dict()
- d['eta1'] = m.eta1()
- d['eta2'] = m.eta2()
- d['x1_init'] = m.x1()
- d['x2_init'] = m.x2()
- d['x3_init'] = m.x3()
- d['eta1_pert'] = m_kaug_dsdp.perturbed_eta1()
- d['eta2_pert'] = m_kaug_dsdp.perturbed_eta2()
- d['cost_pert'] = m_kaug_dsdp.cost()
- d['x1_pert'] = m_kaug_dsdp.x1()
- d['x2_pert'] = m_kaug_dsdp.x2()
- d['x3_pert'] = m_kaug_dsdp.x3()
-
- d_correct = {'eta1':4.5, 'eta2':1.0, 'x1_init':0.15, 'x2_init':0.15, 'x3_init':0.0,
- 'eta1_pert':4.0, 'eta2_pert':1.0, 'x1_pert':0.3333333,'x2_pert':0.6666667,
- 'x3_pert':0.0, 'cost_pert':0.55555556}
-
- for k in d_correct.keys():
- # Check each element of the 'correct' dictionary against the returned
- # dictionary to 3 decimal places
- self.assertAlmostEqual(d[k],d_correct[k],3)
-
-if __name__=="__main__":
- unittest.main()
diff --git a/pyomo/contrib/trustregion/GeometryGenerator.py b/pyomo/contrib/trustregion/GeometryGenerator.py
index d973838e29d..86b9bb1bedd 100644
--- a/pyomo/contrib/trustregion/GeometryGenerator.py
+++ b/pyomo/contrib/trustregion/GeometryGenerator.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import logging
# This is an auto geometry generator for quadratic ROM
@@ -72,7 +82,7 @@ def generate_quadratic_rom_geometry(lx, NUM_SEEDS=None):
print(" LX: single number or range in the form nn:nn")
print(" COUNT: number of random matricies to generate")
- from os.path import abspath, dirname, exists, join
+ from os.path import abspath, dirname, join
from inspect import getfile, currentframe
CACHE_FILE = join(dirname(abspath(getfile(currentframe()))), 'cache.py')
if not os.path.isfile (CACHE_FILE) or not os.access(CACHE_FILE, os.W_OK):
diff --git a/pyomo/contrib/trustregion/Logger.py b/pyomo/contrib/trustregion/Logger.py
index 70855c9213e..1ea7be25570 100644
--- a/pyomo/contrib/trustregion/Logger.py
+++ b/pyomo/contrib/trustregion/Logger.py
@@ -1,6 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import numpy as np
from numpy.linalg import norm
-from pyomo.contrib.trustregion.helper import *
+from pyomo.contrib.trustregion.helper import packXYZ
class IterLog:
# # Todo: Include the following in high printlevel
diff --git a/pyomo/contrib/trustregion/PyomoInterface.py b/pyomo/contrib/trustregion/PyomoInterface.py
index 51a03be1557..6d82d6247de 100644
--- a/pyomo/contrib/trustregion/PyomoInterface.py
+++ b/pyomo/contrib/trustregion/PyomoInterface.py
@@ -1,23 +1,31 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import logging
-import os
import numpy as np
from pyutilib.math import infinity
from pyomo.common.collections import ComponentSet
-from pyomo.common.modeling import randint, unique_component_name
+from pyomo.common.modeling import unique_component_name
from pyomo.core import (
- Block, Var, Param, Set, VarList, ConstraintList, Constraint, Objective,
- RangeSet, value, ConcreteModel, Reals, sqrt, minimize, maximize
+ Block, Var, Param, VarList, ConstraintList, Constraint, Objective,
+ RangeSet, value, ConcreteModel, Reals, sqrt, minimize, maximize,
)
from pyomo.core.expr import current as EXPR
from pyomo.core.base.external import PythonCallbackFunction
-from pyomo.core.base.var import _VarData
from pyomo.core.base.numvalue import nonpyomo_leaf_types
from pyomo.opt import SolverFactory, SolverStatus, TerminationCondition
from pyomo.contrib.trustregion.GeometryGenerator import (
generate_quadratic_rom_geometry
)
-from pyomo.contrib.trustregion.helper import *
+from pyomo.contrib.trustregion.helper import maxIgnoreNone, minIgnoreNone
logger = logging.getLogger('pyomo.contrib.trustregion')
diff --git a/pyomo/contrib/trustregion/TRF.py b/pyomo/contrib/trustregion/TRF.py
index e3548b270e1..e504411a610 100644
--- a/pyomo/contrib/trustregion/TRF.py
+++ b/pyomo/contrib/trustregion/TRF.py
@@ -1,12 +1,20 @@
-import numpy as np
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from math import pow
from numpy import inf
from numpy.linalg import norm
from pyomo.contrib.trustregion.filterMethod import (
FilterElement, Filter)
-from pyomo.contrib.trustregion.helper import (cloneXYZ, packXYZ,
- minIgnoreNone, maxIgnoreNone)
-from pyomo.contrib.trustregion.Logger import (IterLog, Logger)
+from pyomo.contrib.trustregion.helper import (cloneXYZ, packXYZ)
+from pyomo.contrib.trustregion.Logger import Logger
from pyomo.contrib.trustregion.PyomoInterface import (
PyomoInterface, ROMType)
diff --git a/pyomo/contrib/trustregion/examples/Example1.py b/pyomo/contrib/trustregion/examples/Example1.py
index 123efee5003..b95078ccf1a 100644
--- a/pyomo/contrib/trustregion/examples/Example1.py
+++ b/pyomo/contrib/trustregion/examples/Example1.py
@@ -1,6 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
-from pyomo.environ import *
-from pyomo.opt import SolverFactory, SolverStatus, TerminationCondition
+from pyomo.environ import ConcreteModel, Var, Reals, ExternalFunction, sin, sqrt, Constraint, Objective
+from pyomo.opt import SolverFactory
m = ConcreteModel()
m.z = Var(range(3), domain=Reals, initialize=2.)
diff --git a/pyomo/contrib/trustregion/readgjh.py b/pyomo/contrib/trustregion/readgjh.py
index b4ae8c35304..2c0ed797480 100644
--- a/pyomo/contrib/trustregion/readgjh.py
+++ b/pyomo/contrib/trustregion/readgjh.py
@@ -1,5 +1,14 @@
-
-import os, glob, six
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+import glob, six
# build obj gradient and constraint Jacobian
# from a gjh file written by the ASL gjh 'solver'
diff --git a/pyomo/contrib/trustregion/tests/TestPyomoInterface.py b/pyomo/contrib/trustregion/tests/TestPyomoInterface.py
index 20a66b5f0e7..9ea1aff7ea7 100644
--- a/pyomo/contrib/trustregion/tests/TestPyomoInterface.py
+++ b/pyomo/contrib/trustregion/tests/TestPyomoInterface.py
@@ -1,16 +1,26 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
#!/usr/bin/env python
import pyutilib.th as unittest
from pyutilib.misc.config import ConfigBlock
from pyomo.core.expr.current import identify_variables
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Reals, Objective, Constraint, ExternalFunction, SolverFactory, value, sqrt, sin
from pyomo.opt import check_available_solvers
try:
import numpy
numpy_available = True
- from pyomo.contrib.trustregion.PyomoInterface import *
+ from pyomo.contrib.trustregion.PyomoInterface import PyomoInterface
except:
numpy_available = False
diff --git a/pyomo/contrib/trustregion/tests/TestTRConfig.py b/pyomo/contrib/trustregion/tests/TestTRConfig.py
index 461f7881f60..807da1ce267 100644
--- a/pyomo/contrib/trustregion/tests/TestTRConfig.py
+++ b/pyomo/contrib/trustregion/tests/TestTRConfig.py
@@ -1,15 +1,21 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
#!/usr/python/env python
import pyutilib.th as unittest
-from pyutilib.misc.config import ConfigBlock, ConfigValue, ConfigList
-from pyomo.common.config import (
- PositiveInt, PositiveFloat, NonNegativeFloat, In)
from pyomo.common.dependencies import numpy_available
-from pyomo.core import Var, value
-from pyomo.environ import *
-from pyomo.opt import SolverFactory, SolverStatus, TerminationCondition
+from pyomo.environ import (Var, ConcreteModel, Reals, ExternalFunction,
+ Objective, Constraint, sqrt, sin, SolverFactory)
@unittest.skipIf(not SolverFactory('ipopt').available(False), "The IPOPT solver is not available")
@unittest.skipIf(not SolverFactory('gjh').available(False), "The GJH solver is not available")
diff --git a/pyomo/contrib/viewer/model_browser.py b/pyomo/contrib/viewer/model_browser.py
index 73e8772b35c..f4ecc2c3b2d 100644
--- a/pyomo/contrib/viewer/model_browser.py
+++ b/pyomo/contrib/viewer/model_browser.py
@@ -16,9 +16,7 @@
__author__ = "John Eslick"
import os
-import warnings
import logging
-import re
_log = logging.getLogger(__name__)
@@ -28,8 +26,6 @@
from pyomo.core.base.block import _BlockData
from pyomo.core.base.var import _VarData
from pyomo.core.base.constraint import _ConstraintData
-from pyomo.core.base.expression import _ExpressionData
-from pyomo.network.port import SimplePort
from pyomo.core.base.param import _ParamData
from pyomo.environ import Block, Var, Constraint, Param, Expression, value
@@ -119,7 +115,7 @@ def __init__(self, ui_data, parent=None, standard="Var"):
self.setWindowTitle("Constraints")
elif standard == "Param":
components = Param
- columns = ["name", "value", "_mutable"]
+ columns = ["name", "value", "mutable"]
editable = ["value"]
self.setWindowTitle("Parameters")
elif standard == "Expression":
@@ -263,7 +259,7 @@ def _set_value_callback(self, val):
except:
return
elif isinstance(self.data, _ParamData):
- if not self.data._mutable: return
+ if not self.data.parent_component().mutable: return
try:
self.data.value = val
except:
diff --git a/pyomo/contrib/viewer/report.py b/pyomo/contrib/viewer/report.py
index 6ad2f6267e3..73531b13393 100644
--- a/pyomo/contrib/viewer/report.py
+++ b/pyomo/contrib/viewer/report.py
@@ -8,10 +8,9 @@
#
# This software is distributed under the 3-clause BSD License.
##############################################################################
-from pyomo.environ import *
from pyomo.common.collections import ComponentSet
from pyomo.core.expr.current import identify_variables
-from pyomo.network.port import _PortData, SimplePort
+from pyomo.environ import Constraint, value
def value_no_exception(c, div0=None):
"""
diff --git a/pyomo/contrib/viewer/residual_table.py b/pyomo/contrib/viewer/residual_table.py
index 7fbced8817d..dbb69c4579f 100644
--- a/pyomo/contrib/viewer/residual_table.py
+++ b/pyomo/contrib/viewer/residual_table.py
@@ -74,7 +74,7 @@ def update_model(self):
else:
ac = True
self._items = list(self.ui_data.model.component_data_objects(
- pyo.Constraint, active=ac))
+ pyo.Constraint, active=ac))
def sort(self):
self._items.sort(key=
diff --git a/pyomo/contrib/viewer/tests/pytest_qt.py b/pyomo/contrib/viewer/tests/pytest_qt.py
index 8049f58549e..5194d54a9fe 100644
--- a/pyomo/contrib/viewer/tests/pytest_qt.py
+++ b/pyomo/contrib/viewer/tests/pytest_qt.py
@@ -12,10 +12,8 @@
UI Tests
"""
import pyutilib.th as unittest
-import time
-import pytest
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Param, Constraint, Objective, Reals, Block, Expression, ExternalFunction, sin, sqrt, log
from pyomo.contrib.viewer.qt import qt_available
from pyomo.contrib.viewer.qt import QtCore, QMessageBox
from pyomo.contrib.viewer.ui import get_mainwindow, ModelBrowser
diff --git a/pyomo/contrib/viewer/tests/test_data_model_item.py b/pyomo/contrib/viewer/tests/test_data_model_item.py
index 3399cead22d..9b997282b50 100644
--- a/pyomo/contrib/viewer/tests/test_data_model_item.py
+++ b/pyomo/contrib/viewer/tests/test_data_model_item.py
@@ -14,7 +14,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Block, Param, Expression, Constraint, Objective, ExternalFunction, Reals, log, sin, sqrt, expr
from pyomo.contrib.viewer.model_browser import ComponentDataItem
from pyomo.contrib.viewer.ui_data import UIData
diff --git a/pyomo/contrib/viewer/tests/test_data_model_tree.py b/pyomo/contrib/viewer/tests/test_data_model_tree.py
index 5a0047d1eec..eee6b437cda 100644
--- a/pyomo/contrib/viewer/tests/test_data_model_tree.py
+++ b/pyomo/contrib/viewer/tests/test_data_model_tree.py
@@ -13,7 +13,7 @@
"""
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Constraint, Objective, Reals, Block, Expression, ExternalFunction, sin, sqrt
from pyomo.contrib.viewer.model_browser import ComponentDataModel
try:
no_pyqt = False
diff --git a/pyomo/contrib/viewer/tests/test_qt.py b/pyomo/contrib/viewer/tests/test_qt.py
index fd53b451515..6c4791e56aa 100644
--- a/pyomo/contrib/viewer/tests/test_qt.py
+++ b/pyomo/contrib/viewer/tests/test_qt.py
@@ -14,7 +14,6 @@
from subprocess import Popen
import os
import time
-from pyomo.environ import *
import pyutilib.th as unittest
test_file = os.path.join(os.path.dirname(__file__), "pytest_qt.py")
diff --git a/pyomo/contrib/viewer/ui.py b/pyomo/contrib/viewer/ui.py
index 841cdd954e3..5a3bb087a12 100644
--- a/pyomo/contrib/viewer/ui.py
+++ b/pyomo/contrib/viewer/ui.py
@@ -15,21 +15,15 @@
__author__ = "John Eslick"
-import time
import os
-import warnings
import logging
-import threading
-import datetime
-import json
-import sys
try:
from IPython import get_ipython
except ImportError:
def get_ipython():
raise AttributeError("IPython not available")
import pyomo.contrib.viewer.report as rpt
-import pyomo.environ as pe
+import pyomo.environ as pyo
_log = logging.getLogger(__name__)
@@ -70,7 +64,7 @@ def get_mainwindow(model=None, show=True, testing=False):
model. If no model is provided a new ConcreteModel is created
"""
if model is None:
- model = pe.ConcreteModel(name="Default")
+ model = pyo.ConcreteModel(name="Default")
ui = MainWindow(model=model, testing=testing)
try:
get_ipython().events.register('post_execute', ui.refresh_on_execute)
diff --git a/pyomo/contrib/viewer/ui_data.py b/pyomo/contrib/viewer/ui_data.py
index 9e2d5278f19..bb6579b3f01 100644
--- a/pyomo/contrib/viewer/ui_data.py
+++ b/pyomo/contrib/viewer/ui_data.py
@@ -8,6 +8,7 @@
#
# This software is distributed under the 3-clause BSD License.
##############################################################################
+
"""
UI data objects for sharing data and settings between different parts of the UI.
"""
@@ -18,7 +19,7 @@
import logging
from pyomo.common.collections import ComponentMap
from pyomo.contrib.viewer.qt import *
-import pyomo.environ as pe
+import pyomo.environ as pyo
_log = logging.getLogger(__name__)
@@ -82,17 +83,17 @@ def model(self, value):
self.emit_update()
def calculate_constraints(self):
- for o in self.model.component_data_objects(pe.Constraint, active=True):
+ for o in self.model.component_data_objects(pyo.Constraint, active=True):
try:
- self.value_cache[o] = pe.value(o.body, exception=False)
+ self.value_cache[o] = pyo.value(o.body, exception=False)
except ZeroDivisionError:
self.value_cache[o] = "Divide_by_0"
self.emit_exec_refresh()
def calculate_expressions(self):
- for o in self.model.component_data_objects(pe.Expression, active=True):
+ for o in self.model.component_data_objects(pyo.Expression, active=True):
try:
- self.value_cache[o] = pe.value(o, exception=False)
+ self.value_cache[o] = pyo.value(o, exception=False)
except ZeroDivisionError:
self.value_cache[o] = "Divide_by_0"
self.emit_exec_refresh()
diff --git a/pyomo/core/__init__.py b/pyomo/core/__init__.py
index 7e640859918..92b2c269afe 100644
--- a/pyomo/core/__init__.py
+++ b/pyomo/core/__init__.py
@@ -8,9 +8,146 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core.expr import *
+from six import iteritems, iterkeys
+from pyomo.core.expr.numvalue import (
+ value, is_constant, is_fixed, is_variable_type,
+ is_potentially_variable, NumericValue, ZeroConstant,
+ native_numeric_types, native_types, polynomial_degree,
+)
+
+from pyomo.core.expr.boolean_value import BooleanValue
+
+from pyomo.core.expr.numeric_expr import linear_expression, nonlinear_expression
+from pyomo.core.expr.logical_expr import (land, lor, equivalent, exactly,
+ atleast, atmost, implies, lnot,
+ xor, inequality)
+
+from pyomo.core.expr.current import (
+ log, log10, sin, cos, tan, cosh, sinh, tanh,
+ asin, acos, atan, exp, sqrt, asinh, acosh,
+ atanh, ceil, floor,
+ Expr_if,
+)
+
+from pyomo.core.expr.calculus.derivatives import differentiate
+from pyomo.core.expr.taylor_series import taylor_series_expansion
+
import pyomo.core.kernel
import pyomo.core.base._pyomo
-from pyomo.core.base import *
+
+from pyomo.common.collections import ComponentMap
+from pyomo.core.expr.symbol_map import SymbolMap
+from pyomo.core.expr import (numvalue, numeric_expr, boolean_value,
+ logical_expr, current, symbol_map, sympy_tools,
+ taylor_series, visitor, expr_common, expr_errors,
+ calculus)
+from pyomo.core import expr, preprocess, util, kernel
+
+from pyomo.core.expr.numvalue import (nonpyomo_leaf_types,
+ PyomoObject,
+ native_numeric_types,
+ value, is_constant,
+ is_fixed, is_variable_type,
+ is_potentially_variable,
+ polynomial_degree,
+ NumericValue,
+ ZeroConstant)
+from pyomo.core.expr.boolean_value import (
+ as_boolean, BooleanConstant, BooleanValue,
+ native_logical_values)
+from pyomo.core.kernel.objective import (minimize,
+ maximize)
+from pyomo.core.base.config import PyomoOptions
+
+from pyomo.core.base.expression import Expression
+from pyomo.core.base.label import (CuidLabeler,
+ CounterLabeler, NumericLabeler,
+ CNameLabeler, TextLabeler,
+ AlphaNumericTextLabeler, NameLabeler,
+ ShortNameLabeler)
+
+#
+# Components
+#
+from pyomo.core.base.component import (name, Component, ComponentUID)
+import pyomo.core.base.indexed_component
+from pyomo.core.base.action import BuildAction
+from pyomo.core.base.check import BuildCheck
+from pyomo.core.base.set import (
+ Set, SetOf, simple_set_rule, RangeSet,
+)
+from pyomo.core.base.param import Param
+from pyomo.core.base.var import (Var, SimpleVar, VarList)
+from pyomo.core.base.boolean_var import (
+ BooleanVar, BooleanVarList, SimpleBooleanVar)
+from pyomo.core.base.constraint import (logical_expr,
+ simple_constraint_rule,
+ simple_constraintlist_rule,
+ ConstraintList, Constraint)
+from pyomo.core.base.logical_constraint import (
+ LogicalConstraint, LogicalConstraintList)
+from pyomo.core.base.objective import (simple_objective_rule,
+ simple_objectivelist_rule,
+ Objective, ObjectiveList)
+from pyomo.core.base.connector import Connector
+from pyomo.core.base.sos import SOSConstraint
+from pyomo.core.base.piecewise import Piecewise
+from pyomo.core.base.suffix import (active_export_suffix_generator,
+ active_import_suffix_generator,
+ Suffix)
+from pyomo.core.base.external import ExternalFunction
+from pyomo.core.base.symbol_map import symbol_map_from_instance
+from pyomo.core.base.reference import Reference
+
+from pyomo.core.base.set import (Reals, PositiveReals, NonPositiveReals,
+ NegativeReals, NonNegativeReals, Integers,
+ PositiveIntegers, NonPositiveIntegers,
+ NegativeIntegers, NonNegativeIntegers,
+ Boolean, Binary, Any, AnyWithNone, EmptySet,
+ UnitInterval, PercentFraction, RealInterval,
+ IntegerInterval)
+from pyomo.core.base.misc import display
+from pyomo.core.base.block import (SortComponents, TraversalStrategy,
+ Block, SimpleBlock,
+ active_components,
+ components, active_components_data,
+ components_data)
+from pyomo.core.base.PyomoModel import (global_option,
+ Model, ConcreteModel,
+ AbstractModel)
+from pyomo.core.base.plugin import (pyomo_callback,
+ IPyomoExpression, ExpressionFactory,
+ ExpressionRegistration, IPyomoPresolver,
+ IPyomoPresolveAction,
+ IParamRepresentation,
+ ParamRepresentationFactory,
+ IPyomoScriptPreprocess,
+ IPyomoScriptCreateModel,
+ IPyomoScriptCreateDataPortal,
+ IPyomoScriptModifyInstance,
+ IPyomoScriptPrintModel,
+ IPyomoScriptPrintInstance,
+ IPyomoScriptSaveInstance,
+ IPyomoScriptPrintResults,
+ IPyomoScriptSaveResults,
+ IPyomoScriptPostprocess,
+ ModelComponentFactory, Transformation,
+ TransformationFactory)
+#
+import pyomo.core.base._pyomo
+#
+from pyomo.core.base import util
+
+from pyomo.core.base.instance2dat import instance2dat
+
+# These APIs are deprecated and should be removed in the near future
+from pyomo.core.base.set import (
+ set_options, RealSet, IntegerSet, BooleanSet,
+)
+
import pyomo.core.preprocess
-from pyomo.core.util import *
+
+from pyomo.core.util import (prod, quicksum, sum_product, dot_product,
+ summation, sequence)
+
+from weakref import ref as weakref_ref
diff --git a/pyomo/core/base/PyomoModel.py b/pyomo/core/base/PyomoModel.py
index c238d08dca0..dbc338c9bce 100644
--- a/pyomo/core/base/PyomoModel.py
+++ b/pyomo/core/base/PyomoModel.py
@@ -16,45 +16,40 @@
import gc
import time
import math
-import functools
try:
from collections import OrderedDict
except ImportError: #pragma:nocover
from ordereddict import OrderedDict
-from pyutilib.math import *
-from pyutilib.misc import Container, PauseGC, Bunch
+from pyutilib.misc import Container, PauseGC
-import pyomo.common
+from pyomo.common import timing, PyomoAPIFactory
from pyomo.common.dependencies import pympler, pympler_available
from pyomo.common.deprecation import deprecation_warning
from pyomo.common.plugin import ExtensionPoint
-from pyomo.common._task import pyomo_api
from pyomo.core.expr import expr_common
from pyomo.core.expr.symbol_map import SymbolMap
+from pyomo.core.expr.numeric_expr import clone_counter
from pyomo.core.base.var import Var
from pyomo.core.base.constraint import Constraint
from pyomo.core.base.objective import Objective
-from pyomo.core.base.set_types import *
from pyomo.core.base.suffix import active_import_suffix_generator
from pyomo.core.base.indexed_component import IndexedComponent
from pyomo.dataportal.DataPortal import DataPortal
-from pyomo.core.base.plugin import *
-from pyomo.core.base.numvalue import *
+from pyomo.core.base.plugin import IPyomoPresolver
+from pyomo.core.base.numvalue import value
from pyomo.core.base.block import SimpleBlock
-from pyomo.core.base.set import Set, UnknownSetDimen
+from pyomo.core.base.set import Set
from pyomo.core.base.component import Component, ComponentUID
from pyomo.core.base.plugin import ModelComponentFactory, TransformationFactory
from pyomo.core.base.label import CNameLabeler, CuidLabeler
-import pyomo.opt
-from pyomo.opt.results import SolverResults, Solution, SolutionStatus, UndefinedData
+from pyomo.opt.results import SolverResults, Solution, SolverStatus, UndefinedData
from six import itervalues, iteritems, StringIO, string_types
-from six.moves import xrange
try:
unicode
except:
@@ -221,7 +216,7 @@ def load_from(self,
#
# If there is a warning, then print a warning message.
#
- if (results.solver.status == pyomo.opt.SolverStatus.warning):
+ if (results.solver.status == SolverStatus.warning):
logger.warning(
'Loading a SolverResults object with a '
'warning status into model=%s;\n'
@@ -230,8 +225,8 @@ def load_from(self,
#
# If the solver status not one of either OK or Warning, then generate an error.
#
- elif results.solver.status != pyomo.opt.SolverStatus.ok:
- if (results.solver.status == pyomo.opt.SolverStatus.aborted) and \
+ elif results.solver.status != SolverStatus.ok:
+ if (results.solver.status == SolverStatus.aborted) and \
(len(results.solution) > 0):
logger.warning(
"Loading a SolverResults object with "
@@ -684,7 +679,7 @@ def create_instance( self, filename=None, data=None, name=None,
return self.clone()
if report_timing:
- pyomo.common.timing.report_timing()
+ timing.report_timing()
if name is None:
name = self.name
@@ -743,7 +738,7 @@ def preprocess(self, preprocessor=None):
with PauseGC() as pgc:
if preprocessor is None:
preprocessor = self.config.preprocessor
- pyomo.common.PyomoAPIFactory(preprocessor)(self.config, model=self)
+ PyomoAPIFactory(preprocessor)(self.config, model=self)
def load(self, arg, namespaces=[None], profile_memory=0, report_timing=None):
"""
diff --git a/pyomo/core/base/__init__.py b/pyomo/core/base/__init__.py
index 023a4e6cede..72ad13b8223 100644
--- a/pyomo/core/base/__init__.py
+++ b/pyomo/core/base/__init__.py
@@ -10,9 +10,43 @@
# TODO: this import is for historical backwards compatibility and should
# probably be removed
+
+from six import iteritems, iterkeys
+import pyomo.core.expr.numvalue
+import pyomo.core.expr.logical_expr
from pyomo.common.collections import ComponentMap
+from pyomo.core.expr.symbol_map import SymbolMap
+import pyomo.core.base.action
+import pyomo.core.base.boolean_var
+import pyomo.core.base.check
+import pyomo.core.base.component
+import pyomo.core.base.config
+import pyomo.core.base.constraint
+import pyomo.core.base.expression
+import pyomo.core.base.global_set
+import pyomo.core.base.indexed_component
+import pyomo.core.base.indexed_component_slice
+import pyomo.core.base.label
+import pyomo.core.base.logical_constraint
+import pyomo.core.base.misc
+import pyomo.core.base.param
+import pyomo.core.base.plugin
+import pyomo.core.base.range
+import pyomo.core.base.set_types
+import pyomo.core.base.set
+import pyomo.core.base.units_container
+import pyomo.core.base.util
+import pyomo.core.base.var
-from pyomo.core.expr.numvalue import *
+from pyomo.core.expr.numvalue import (nonpyomo_leaf_types,
+ native_types,
+ native_numeric_types,
+ value, is_constant,
+ is_fixed, is_variable_type,
+ is_potentially_variable,
+ polynomial_degree,
+ NumericValue,
+ ZeroConstant)
from pyomo.core.expr.boolean_value import (
as_boolean, BooleanConstant, BooleanValue,
native_logical_values)
@@ -20,53 +54,96 @@
maximize)
from pyomo.core.base.config import PyomoOptions
-from pyomo.core.base.expression import *
-from pyomo.core.base.label import *
+from pyomo.core.base.expression import (Expression, _ExpressionData)
+from pyomo.core.base.label import (CuidLabeler,
+ CounterLabeler, NumericLabeler,
+ CNameLabeler, TextLabeler,
+ AlphaNumericTextLabeler, NameLabeler,
+ ShortNameLabeler)
#
# Components
#
-from pyomo.core.base.component import *
-import pyomo.core.base.indexed_component
-from pyomo.core.base.action import *
-from pyomo.core.base.check import *
+from pyomo.core.base.component import (name, Component, ComponentUID)
+from pyomo.core.base.action import BuildAction
+from pyomo.core.base.check import BuildCheck
from pyomo.core.base.set import (
Set, SetOf, simple_set_rule, RangeSet,
)
-from pyomo.core.base.param import *
-from pyomo.core.base.var import *
+from pyomo.core.base.param import Param
+from pyomo.core.base.var import (Var, _VarData, _GeneralVarData,
+ SimpleVar, VarList)
from pyomo.core.base.boolean_var import (
- BooleanVar, _BooleanVarData, _GeneralBooleanVarData,
+ BooleanVar, _BooleanVarData, _GeneralBooleanVarData,
BooleanVarList, SimpleBooleanVar)
-from pyomo.core.base.constraint import *
+from pyomo.core.base.constraint import (simple_constraint_rule,
+ simple_constraintlist_rule,
+ ConstraintList, Constraint,
+ _ConstraintData)
from pyomo.core.base.logical_constraint import (
LogicalConstraint, LogicalConstraintList, _LogicalConstraintData)
-from pyomo.core.base.objective import *
-from pyomo.core.base.connector import *
-from pyomo.core.base.sos import *
-from pyomo.core.base.piecewise import *
-from pyomo.core.base.suffix import *
-from pyomo.core.base.external import *
-from pyomo.core.base.symbol_map import *
+from pyomo.core.base.objective import (simple_objective_rule,
+ simple_objectivelist_rule,
+ Objective, ObjectiveList,
+ _ObjectiveData)
+from pyomo.core.base.connector import Connector
+from pyomo.core.base.sos import SOSConstraint
+from pyomo.core.base.piecewise import Piecewise
+from pyomo.core.base.suffix import (active_export_suffix_generator,
+ active_import_suffix_generator,
+ Suffix)
+from pyomo.core.base.external import ExternalFunction
+from pyomo.core.base.symbol_map import symbol_map_from_instance
from pyomo.core.base.reference import Reference
-#
-from pyomo.core.base.set_types import *
-from pyomo.core.base.misc import *
-from pyomo.core.base.block import *
-from pyomo.core.base.PyomoModel import *
-from pyomo.core.base.plugin import *
+
+from pyomo.core.base.set import (Reals, PositiveReals, NonPositiveReals,
+ NegativeReals, NonNegativeReals, Integers,
+ PositiveIntegers, NonPositiveIntegers,
+ NegativeIntegers, NonNegativeIntegers,
+ Boolean, Binary, Any, AnyWithNone, EmptySet,
+ UnitInterval, PercentFraction, RealInterval,
+ IntegerInterval)
+from pyomo.core.base.misc import display
+from pyomo.core.base.block import (SortComponents, TraversalStrategy,
+ Block, SimpleBlock, active_components,
+ components, active_components_data,
+ components_data)
+from pyomo.core.base.PyomoModel import (global_option,
+ ModelSolution,
+ ModelSolutions, Model, ConcreteModel,
+ AbstractModel)
+from pyomo.core.base.plugin import (pyomo_callback,
+ IPyomoExpression, ExpressionFactory,
+ ExpressionRegistration, IPyomoPresolver,
+ IPyomoPresolveAction,
+ IParamRepresentation,
+ ParamRepresentationFactory,
+ IPyomoScriptPreprocess,
+ IPyomoScriptCreateModel,
+ IPyomoScriptCreateDataPortal,
+ IPyomoScriptModifyInstance,
+ IPyomoScriptPrintModel,
+ IPyomoScriptPrintInstance,
+ IPyomoScriptSaveInstance,
+ IPyomoScriptPrintResults,
+ IPyomoScriptSaveResults,
+ IPyomoScriptPostprocess,
+ ModelComponentFactory, Transformation,
+ TransformationFactory)
#
import pyomo.core.base._pyomo
#
import pyomo.core.base.util
-from pyomo.core.base.instance2dat import *
+from pyomo.core.base.instance2dat import instance2dat
# These APIs are deprecated and should be removed in the near future
from pyomo.core.base.set import (
set_options, RealSet, IntegerSet, BooleanSet,
)
+from weakref import ref as weakref_ref
+
#
# This is a hack to strip out modules, which shouldn't have been included in these imports
#
diff --git a/pyomo/core/base/_pyomo.py b/pyomo/core/base/_pyomo.py
index e217eeaae37..8337882283c 100644
--- a/pyomo/core/base/_pyomo.py
+++ b/pyomo/core/base/_pyomo.py
@@ -9,7 +9,29 @@
# ___________________________________________________________________________
from six import iteritems
-from pyomo.core.base.plugin import *
+from pyomo.core.base.plugin import (unique_component_name, Factory, implements,
+ Interface, Plugin, CreatePluginFactory,
+ ExtensionPoint, TransformationTimer,
+ registered_callback, pyomo_callback,
+ IPyomoExpression, ExpressionFactory,
+ ExpressionRegistration, IPyomoPresolver,
+ IPyomoPresolveAction, IParamRepresentation,
+ ParamRepresentationFactory,
+ IPyomoScriptPreprocess,
+ IPyomoScriptCreateModel,
+ IPyomoScriptCreateDataPortal,
+ IPyomoScriptModifyInstance,
+ IPyomoScriptPrintModel,
+ IPyomoScriptPrintInstance,
+ IPyomoScriptSaveInstance,
+ IPyomoScriptPrintResults,
+ IPyomoScriptSaveResults,
+ IPyomoScriptPostprocess,
+ ModelComponentFactory, Transformation,
+ TransformationFactory,
+ ModelComponentFactoryClass,
+ TransformationInfo, TransformationData,
+ apply_transformation)
def predefined_sets():
from pyomo.core.base.set import GlobalSets
diff --git a/pyomo/core/base/alias.py b/pyomo/core/base/alias.py
index 29ab613ec8b..f7e69cccbd1 100644
--- a/pyomo/core/base/alias.py
+++ b/pyomo/core/base/alias.py
@@ -1,6 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import weakref
import logging
-from copy import deepcopy
from pyomo.common.timing import ConstructionTimer
from pyomo.core.base.component import Component, ComponentData
diff --git a/pyomo/core/base/block.py b/pyomo/core/base/block.py
index 3655f4fc5a0..41ad6a893c6 100644
--- a/pyomo/core/base/block.py
+++ b/pyomo/core/base/block.py
@@ -20,7 +20,7 @@
import textwrap
from inspect import isclass
-from operator import itemgetter, attrgetter
+from operator import itemgetter
from six import iteritems, iterkeys, itervalues, StringIO, string_types, \
advance_iterator, PY3
@@ -33,14 +33,16 @@
from pyomo.common.collections import ComponentMap
from pyomo.common.timing import ConstructionTimer
-from pyomo.core.base.plugin import * # ModelComponentFactory
-from pyomo.core.base.component import Component, ActiveComponentData, \
- ComponentUID
-from pyomo.core.base.set import Set, RangeSet, GlobalSetBase, _SetDataBase
+from pyomo.core.base.plugin import ModelComponentFactory
+from pyomo.core.base.component import (
+ Component, ActiveComponentData, ComponentUID,
+)
+from pyomo.core.base.set import GlobalSetBase, _SetDataBase
from pyomo.core.base.var import Var
from pyomo.core.base.misc import apply_indexed_rule
-from pyomo.core.base.indexed_component import IndexedComponent, \
- ActiveIndexedComponent, UnindexedComponent_set
+from pyomo.core.base.indexed_component import (
+ ActiveIndexedComponent, UnindexedComponent_set,
+)
from pyomo.opt.base import ProblemFormat, guess_format
from pyomo.opt import WriterFactory
@@ -2153,21 +2155,15 @@ def components_data(block, ctype,
class _IndexedCustomBlockMeta(type):
- """Metaclass for creating an indexed block with
- a custom block data type."""
-
- def __new__(meta, name, bases, dct):
- def __init__(self, *args, **kwargs):
- bases[0].__init__(self, *args, **kwargs)
+ """Metaclass for creating an indexed custom block.
+ """
- dct["__init__"] = __init__
- return type.__new__(meta, name, bases, dct)
+ pass
class _ScalarCustomBlockMeta(type):
- '''Metaclass used to create a scalar block with a
- custom block data type
- '''
+ """Metaclass for creating a scalar custom block.
+ """
def __new__(meta, name, bases, dct):
def __init__(self, *args, **kwargs):
@@ -2182,9 +2178,14 @@ def __init__(self, *args, **kwargs):
class CustomBlock(Block):
- ''' This CustomBlock is the base class that allows
- for easy creation of specialized derived blocks
- '''
+ """ The base class used by instances of custom block components
+ """
+
+ def __init__(self, *args, **kwds):
+ if self._default_ctype is not None:
+ kwds.setdefault('ctype', self._default_ctype)
+ Block.__init__(self, *args, **kwds)
+
def __new__(cls, *args, **kwds):
if cls.__name__.startswith('_Indexed') or \
@@ -2193,37 +2194,65 @@ def __new__(cls, *args, **kwds):
# therefore, we need to create what we have
return super(CustomBlock, cls).__new__(cls)
if not args or (args[0] is UnindexedComponent_set and len(args) == 1):
- bname = "_Scalar{}".format(cls.__name__)
- n = _ScalarCustomBlockMeta(bname, (cls._ComponentDataClass, cls), {})
+ n = _ScalarCustomBlockMeta(
+ "_Scalar%s" % (cls.__name__,),
+ (cls._ComponentDataClass, cls),
+ {}
+ )
return n.__new__(n)
else:
- bname = "_Indexed{}".format(cls.__name__)
- n = _IndexedCustomBlockMeta(bname, (cls,), {})
+ n = _IndexedCustomBlockMeta(
+ "_Indexed%s" % (cls.__name__,),
+ (cls,),
+ {}
+ )
return n.__new__(n)
-def declare_custom_block(name):
- ''' Decorator to declare the custom component
- that goes along with a custom block data
+def declare_custom_block(name, new_ctype=None):
+ """ Decorator to declare components for a custom block data class
- @declare_custom_block(name=FooBlock)
- class FooBlockData(_BlockData):
- # custom block data class
- '''
+ >>> @declare_custom_block(name=FooBlock)
+ ... class FooBlockData(_BlockData):
+ ... # custom block data class
+ ... pass
+ """
def proc_dec(cls):
# this is the decorator function that
# creates the block component class
+
+ # Default (derived) Block attributes
+ clsbody = {
+ "__module__": cls.__module__, # magic to fix the module
+ # Default IndexedComponent data object is the decorated class:
+ "_ComponentDataClass": cls,
+ # By default this new block does not declare a new ctype
+ "_default_ctype": None,
+ }
+
c = type(
- name,
- # name of new class
- (CustomBlock,),
- # base classes
- {"__module__": cls.__module__,
- "_ComponentDataClass": cls}) # magic to fix the module
+ name, # name of new class
+ (CustomBlock,), # base classes
+ clsbody, # class body definitions (will populate __dict__)
+ )
- # are these necessary?
+ if new_ctype is not None:
+ if new_ctype is True:
+ c._default_ctype = c
+ elif type(new_ctype) is type:
+ c._default_ctype = new_ctype
+ else:
+ raise ValueError("Expected new_ctype to be either type "
+ "or 'True'; received: %s" % (new_ctype,))
+
+ # Register the new Block type in the same module as the BlockData
setattr(sys.modules[cls.__module__], name, c)
+ # TODO: can we also register concrete Indexed* and Scalar*
+ # classes into the original BlockData module (instead of relying
+ # on metaclasses)?
+
+ # are these necessary?
setattr(cls, '_orig_name', name)
setattr(cls, '_orig_module', cls.__module__)
return cls
diff --git a/pyomo/core/base/config.py b/pyomo/core/base/config.py
index 247452d6042..7a77b267d70 100644
--- a/pyomo/core/base/config.py
+++ b/pyomo/core/base/config.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import os
import json
diff --git a/pyomo/core/base/connector.py b/pyomo/core/base/connector.py
index 94968de5666..b4a145e3a7a 100644
--- a/pyomo/core/base/connector.py
+++ b/pyomo/core/base/connector.py
@@ -12,8 +12,7 @@
import logging
import sys
-from six import iteritems, itervalues, iterkeys
-from six.moves import xrange
+from six import iteritems, itervalues
from weakref import ref as weakref_ref
from pyomo.common import deprecated
diff --git a/pyomo/core/base/constraint.py b/pyomo/core/base/constraint.py
index df7556d75e0..415c03a549d 100644
--- a/pyomo/core/base/constraint.py
+++ b/pyomo/core/base/constraint.py
@@ -24,8 +24,7 @@
value,
as_numeric,
is_constant,
- native_numeric_types,
- _sub)
+ native_numeric_types)
from pyomo.core.base.plugin import ModelComponentFactory
from pyomo.core.base.component import ActiveComponentData
from pyomo.core.base.indexed_component import \
@@ -494,15 +493,14 @@ def set_value(self, expr):
self._upper = None
self._equality = False
- if expr is Constraint.Infeasible:
+ if expr is Constraint.Skip:
+ del self.parent_component()[self.index()]
+ return
+ elif expr is Constraint.Infeasible:
del self.parent_component()[self.index()]
raise ValueError(
"Constraint '%s' is always infeasible"
% (self.name,) )
- elif ( expr is Constraint.Skip or
- expr is Constraint.Feasible ):
- del self.parent_component()[self.index()]
- return
else:
raise ValueError(
"Constraint '%s' does not have a proper "
@@ -760,7 +758,7 @@ class Constraint(ActiveIndexedComponent):
_ComponentDataClass = _GeneralConstraintData
class Infeasible(object): pass
- class Feasible(object): pass
+ Feasible = ActiveIndexedComponent.Skip
NoConstraint = ActiveIndexedComponent.Skip
Violated = Infeasible
Satisfied = Feasible
diff --git a/pyomo/core/base/expression.py b/pyomo/core/base/expression.py
index 456c287fffb..1aef485e1e3 100644
--- a/pyomo/core/base/expression.py
+++ b/pyomo/core/base/expression.py
@@ -16,7 +16,6 @@
from pyomo.common.timing import ConstructionTimer
-from pyomo.core.expr import current as EXPR
from pyomo.core.base.component import ComponentData
from pyomo.core.base.plugin import ModelComponentFactory
from pyomo.core.base.indexed_component import (
diff --git a/pyomo/core/base/indexed_component.py b/pyomo/core/base/indexed_component.py
index 607a934a105..8b6027d2884 100644
--- a/pyomo/core/base/indexed_component.py
+++ b/pyomo/core/base/indexed_component.py
@@ -10,7 +10,7 @@
__all__ = ['IndexedComponent', 'ActiveIndexedComponent']
-import pyutilib.misc
+import logging
from pyomo.core.expr.expr_errors import TemplateExpressionError
from pyomo.core.expr.numvalue import native_types
@@ -26,6 +26,8 @@
from collections.abc import Sequence as collections_Sequence
else:
from collections import Sequence as collections_Sequence
+
+logger = logging.getLogger('pyomo.core')
sequence_types = {tuple, list}
def normalize_index(x):
diff --git a/pyomo/core/base/indexed_component_slice.py b/pyomo/core/base/indexed_component_slice.py
index 3cc2271e52b..6d67d5bb597 100644
--- a/pyomo/core/base/indexed_component_slice.py
+++ b/pyomo/core/base/indexed_component_slice.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
import copy
-from six import PY3, iteritems, iterkeys, advance_iterator
+from six import iteritems, iterkeys, advance_iterator
from pyomo.common import DeveloperError
class IndexedComponent_slice(object):
@@ -276,6 +276,14 @@ def expanded_items(self):
return ((_iter.get_last_index(), _) for _ in _iter)
+def _tuple_from_possible_scalar(source):
+ if type(source) is not tuple:
+ # This will behave poorly for non-tuple,
+ # non-string iterables, but we do not
+ # expect non-tuple, non-string iterables.
+ return (source,)
+ return source
+
def _freeze(info):
if info[0] == IndexedComponent_slice.slice_info:
return (
@@ -286,17 +294,17 @@ def _freeze(info):
info[1][3] # elipsis index
)
elif info[0] & IndexedComponent_slice.ITEM_MASK:
+ index = _tuple_from_possible_scalar(info[1])
return (
info[0],
tuple( (x.start,x.stop,x.step) if type(x) is slice else x
- for x in info[1] ),
+ for x in index ),
info[2:],
)
else:
return info
-
class _slice_generator(object):
"""Utility (iterator) for generating the elements of one slice
diff --git a/pyomo/core/base/instance2dat.py b/pyomo/core/base/instance2dat.py
index 569e309c2e9..9df7e9af6d2 100644
--- a/pyomo/core/base/instance2dat.py
+++ b/pyomo/core/base/instance2dat.py
@@ -29,21 +29,21 @@ def instance2dat(instance, output_filename):
if set_object.dim() == 0:
if len(set_object) == 0:
continue
- print >>output_file, "set "+set_name+" := "
+ output_file.write("set " + set_name + " := \n")
for element in set_object:
- print >>output_file, element
- print >>output_file, ";"
+ output_file.write(element,)
+ output_file.write(";\n")
elif set_object.dim() == 1:
for index in set_object:
- print >>output_file, "set "+set_name+"[\""+str(index)+"\"]"+" := ",
+ output_file.write("set " + set_name + "[\""+str(index) + "\"]"+" :=")
for element in set_object[index]:
- print >>output_file, element,
- print >>output_file, ";"
+ output_file.write(element,)
+ output_file.write(";\n")
else:
- print >>output_file, "***MULTIPLY INDEXED SETS NOT IMPLEMENTED!!!"
+ output_file.write("***MULTIPLY INDEXED SETS NOT IMPLEMENTED!!!\n")
pass
- print >>output_file, ""
+ output_file.write("\n")
for param_name, param_object in iteritems(instance.component_map(Param, active=True)):
if (param_object._initialize is not None) and (type(param_object._initialize) is types.FunctionType):
@@ -52,19 +52,20 @@ def instance2dat(instance, output_filename):
continue
if None in param_object:
- print >>output_file, "param "+param_name+" := "+str(value(param_object[None]))+" ;"
- print >>output_file, ""
+ output_file.write("param "+param_name+" := "
+ + str(value(param_object[None])) + " ;\n")
+ output_file.write("\n")
else:
- print >>output_file, "param "+param_name+" := "
+ output_file.write("param " + param_name + " := \n")
if param_object.dim() == 1:
for index in param_object:
- print >>output_file, index, str(value(param_object[index]))
+ output_file.write(str(index) + str(value(param_object[index])) + "\n")
else:
for index in param_object:
for i in index:
- print >>output_file, i,
- print >>output_file, str(value(param_object[index]))
- print >>output_file, ";"
- print >>output_file, ""
+ output_file.write(i,)
+ output_file.write(str(value(param_object[index])) + "\n")
+ output_file.write(";\n")
+ output_file.write("\n")
output_file.close()
diff --git a/pyomo/core/base/logical_constraint.py b/pyomo/core/base/logical_constraint.py
index 623bc717888..cf96a5c89b3 100644
--- a/pyomo/core/base/logical_constraint.py
+++ b/pyomo/core/base/logical_constraint.py
@@ -17,7 +17,7 @@
import pyutilib.math
from pyomo.common.timing import ConstructionTimer
-from pyomo.core.base import Constraint
+from pyomo.core.base.constraint import Constraint
from pyomo.core.expr import logical_expr
from pyomo.core.expr.boolean_value import as_boolean, BooleanConstant
from pyomo.core.expr.numvalue import native_types, native_logical_types
diff --git a/pyomo/core/base/objective.py b/pyomo/core/base/objective.py
index 3a90221181b..d9b171ee74f 100644
--- a/pyomo/core/base/objective.py
+++ b/pyomo/core/base/objective.py
@@ -23,11 +23,11 @@
from pyomo.common.timing import ConstructionTimer
from pyomo.core.expr.numvalue import value
-from pyomo.core.expr import current as EXPR
from pyomo.core.base.plugin import ModelComponentFactory
from pyomo.core.base.component import ActiveComponentData
from pyomo.core.base.indexed_component import (ActiveIndexedComponent,
- UnindexedComponent_set)
+ UnindexedComponent_set,
+ _get_indexed_component_data_name)
from pyomo.core.base.expression import (_ExpressionData,
_GeneralExpressionDataImpl)
from pyomo.core.base.misc import apply_indexed_rule, tabular_writer
diff --git a/pyomo/core/base/param.py b/pyomo/core/base/param.py
index 6d0bc2c7754..177de9fbe94 100644
--- a/pyomo/core/base/param.py
+++ b/pyomo/core/base/param.py
@@ -225,8 +225,11 @@ class Param(IndexedComponent):
initialize
A dictionary or rule for setting up this parameter with existing
model data
- unit: pyomo unit expression
+ unit: pyomo unit expression
An expression containing the units for the parameter
+ mutable: `boolean`
+ Flag indicating if the value of the parameter may change between
+ calls to a solver. Defaults to `False`
"""
DefaultMutable = False
@@ -248,8 +251,8 @@ def __init__(self, *args, **kwd):
self._mutable = kwd.pop('mutable', Param.DefaultMutable )
self._default_val = kwd.pop('default', _NotValid )
self._dense_initialize = kwd.pop('initialize_as_dense', False)
- self._units = kwd.pop('units', None)
- if self._units is not None:
+ self._units = kwd.pop('units', None)
+ if self._units is not None:
self._mutable = True
#
if 'repn' in kwd:
@@ -290,6 +293,10 @@ def __iter__(self):
return self._data.__iter__()
return self._index.__iter__()
+ @property
+ def mutable(self):
+ return self._mutable
+
#
# These are "sparse equivalent" access / iteration methods that
# only loop over the defined data.
diff --git a/pyomo/core/base/plugin.py b/pyomo/core/base/plugin.py
index 5ca11f04e9f..87ae2076a06 100644
--- a/pyomo/core/base/plugin.py
+++ b/pyomo/core/base/plugin.py
@@ -29,13 +29,11 @@
]
import logging
-import pyutilib.misc
from pyomo.common.deprecation import deprecated
from pyomo.common.modeling import unique_component_name
from pyomo.common import Factory
from pyomo.common.plugin import (
- alias, implements, Interface, Plugin, PluginFactory, CreatePluginFactory,
- PluginError, ExtensionPoint )
+ implements, Interface, Plugin, CreatePluginFactory, ExtensionPoint )
from pyomo.common.timing import TransformationTimer
logger = logging.getLogger('pyomo.core')
diff --git a/pyomo/core/base/set.py b/pyomo/core/base/set.py
index 71ada7f23a5..8e381a56359 100644
--- a/pyomo/core/base/set.py
+++ b/pyomo/core/base/set.py
@@ -16,7 +16,7 @@
import sys
import weakref
-from six import iteritems, iterkeys
+from six import iteritems
from six.moves import xrange
from pyomo.common.deprecation import deprecated, deprecation_warning
@@ -27,8 +27,8 @@
)
from pyomo.core.base.plugin import ModelComponentFactory
from pyomo.core.base.util import (
- disable_methods, InitializerBase, Initializer, ConstantInitializer,
- CountedCallInitializer, ItemInitializer, IndexedCallInitializer,
+ disable_methods, InitializerBase, Initializer,
+ CountedCallInitializer, IndexedCallInitializer,
)
from pyomo.core.base.range import (
NumericRange, NonNumericRange, AnyRange, RangeProduct,
@@ -411,7 +411,7 @@ def __call__(self, parent, index):
return _val
elif _val is Set.Skip:
return _val
- elif not _val:
+ elif _val is None:
return _val
if not isinstance(_val, collections_Sequence):
@@ -3990,7 +3990,7 @@ class GlobalSet(GlobalSetBase, obj.__class__):
global_name = None
- def __new__(cls, **kwds):
+ def __new__(cls, *args, **kwds):
"""Hijack __new__ to mock up old RealSet el al. interface
In the original Set implementation (Pyomo<=5.6.7), the
@@ -4003,6 +4003,17 @@ def __new__(cls, **kwds):
"""
if cls is GlobalSet and GlobalSet.global_name \
and issubclass(GlobalSet, RangeSet):
+ deprecation_warning(
+ "The use of RealSet, IntegerSet, BinarySet and "
+ "BooleanSet as Pyomo Set class generators is "
+ "deprecated. Please either use one of the pre-declared "
+ "global Sets (e.g., Reals, NonNegativeReals, Integers, "
+ "PositiveIntegers, Binary), or create a custom RangeSet.",
+ version='5.7.1')
+ # Note: we will completely ignore any positional
+ # arguments. In this situation, these could be the
+ # parent_block and any indices; e.g.,
+ # Var(m.I, within=RealSet)
base_set = GlobalSets[GlobalSet.global_name]
bounds = kwds.pop('bounds', None)
range_init = SetInitializer(base_set)
@@ -4021,7 +4032,7 @@ def __new__(cls, **kwds):
cls_name is not None or bounds is not None):
ans._name += str(ans.bounds())
else:
- ans = super(GlobalSet, cls).__new__(cls, **kwds)
+ ans = super(GlobalSet, cls).__new__(cls, *args, **kwds)
if kwds:
raise RuntimeError("Unexpected keyword arguments: %s" % (kwds,))
return ans
diff --git a/pyomo/core/base/suffix.py b/pyomo/core/base/suffix.py
index 03fa8ba8588..9c6d9134f2b 100644
--- a/pyomo/core/base/suffix.py
+++ b/pyomo/core/base/suffix.py
@@ -13,7 +13,6 @@
'active_import_suffix_generator')
import logging
-import pprint
from pyomo.common.collections import ComponentMap
from pyomo.common.timing import ConstructionTimer
diff --git a/pyomo/core/base/symbol_map.py b/pyomo/core/base/symbol_map.py
index 9a23252c7e5..9fd0fc30021 100644
--- a/pyomo/core/base/symbol_map.py
+++ b/pyomo/core/base/symbol_map.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core.expr.symbol_map import *
+from pyomo.core.expr.symbol_map import SymbolMap
from pyomo.core.base.label import TextLabeler
def symbol_map_from_instance(instance):
diff --git a/pyomo/core/base/symbolic.py b/pyomo/core/base/symbolic.py
index 9631c6159af..6fa3969ffdc 100644
--- a/pyomo/core/base/symbolic.py
+++ b/pyomo/core/base/symbolic.py
@@ -10,7 +10,8 @@
from pyomo.common.deprecation import deprecated
import pyomo.core.expr.calculus.derivatives as diff_core
-from pyomo.core.expr.calculus.diff_with_sympy import differentiate_available, NondifferentiableError
+from pyomo.core.expr.calculus.diff_with_sympy import differentiate_available
+from pyomo.common.errors import NondifferentiableError
@deprecated(msg=('The differentiate function in pyomo.core.base.symbolic has been deprecated. Please use the ' +
diff --git a/pyomo/core/base/units_container.py b/pyomo/core/base/units_container.py
index 1161d0073b9..3527c79b5c8 100644
--- a/pyomo/core/base/units_container.py
+++ b/pyomo/core/base/units_container.py
@@ -24,6 +24,7 @@
this module using common notation.
.. doctest::
+ :skipif: not pint_available
>>> from pyomo.environ import units as u
>>> print(3.0*u.kg)
@@ -37,6 +38,7 @@
There are other methods there that may be helpful for verifying correct units on a model.
.. doctest::
+ :skipif: not pint_available
>>> from pyomo.environ import ConcreteModel, Var, Objective
>>> from pyomo.environ import units as u
@@ -106,6 +108,7 @@
# * Extend external function interface to support units for the arguments in addition to the function itself
import six
+import sys
from pyomo.common.dependencies import attempt_import
from pyomo.core.expr.numvalue import NumericValue, nonpyomo_leaf_types, value, native_numeric_types
@@ -1106,7 +1109,7 @@ def exitNode(self, node, data):
return (pyomo_unit, pint_unit)
raise TypeError('An unhandled expression node type: {} was encountered while retrieving the'
- ' units of expression'.format(str(node_type), str(node)))
+ ' units of expression {}'.format(str(type(node)), str(node)))
class PyomoUnitsContainer(object):
@@ -1154,6 +1157,7 @@ def load_definitions_from_file(self, definition_file):
Then we can add this to the container with:
.. doctest::
+ :skipif: not pint_available
:hide:
# get a local units object (to avoid duplicate registration
@@ -1164,6 +1168,7 @@ def load_definitions_from_file(self, definition_file):
... tmp = FILE.write("USD = [currency]\\n")
.. doctest::
+ :skipif: not pint_available
>>> u.load_definitions_from_file('my_additional_units.txt')
>>> print(u.USD)
@@ -1184,6 +1189,7 @@ def load_definitions_from_strings(self, definition_string_list):
unit, use
.. doctest::
+ :skipif: not pint_available
:hide:
# get a local units object (to avoid duplicate registration
@@ -1192,6 +1198,7 @@ def load_definitions_from_strings(self, definition_string_list):
>>> u = _units.PyomoUnitsContainer()
.. doctest::
+ :skipif: not pint_available
>>> u.load_definitions_from_strings(['USD = [currency]'])
>>> print(u.USD)
diff --git a/pyomo/core/base/util.py b/pyomo/core/base/util.py
index f2cd15ee231..519577c9c34 100644
--- a/pyomo/core/base/util.py
+++ b/pyomo/core/base/util.py
@@ -11,7 +11,6 @@
#
# Utility functions
#
-import collections
import functools
import inspect
import six
diff --git a/pyomo/core/expr/__init__.py b/pyomo/core/expr/__init__.py
index 66af3deb4c4..e2845871788 100644
--- a/pyomo/core/expr/__init__.py
+++ b/pyomo/core/expr/__init__.py
@@ -16,29 +16,27 @@
# symbols that are used by developers.
#
-from . import numvalue, numeric_expr, boolean_value, logical_expr, current
+from pyomo.core.expr import numvalue, numeric_expr, boolean_value, logical_expr, current
-from .numvalue import (
+from pyomo.core.expr.numvalue import (
value, is_constant, is_fixed, is_variable_type,
is_potentially_variable, NumericValue, ZeroConstant,
native_numeric_types, native_types, polynomial_degree,
)
-from .boolean_value import BooleanValue
+from pyomo.core.expr.boolean_value import BooleanValue
-from .numeric_expr import linear_expression, nonlinear_expression
-from .logical_expr import inequality
+from pyomo.core.expr.numeric_expr import linear_expression, nonlinear_expression
+from pyomo.core.expr.logical_expr import (land, lor, equivalent, exactly,
+ atleast, atmost, implies, lnot,
+ xor, inequality)
-from .logical_expr import (
- land, lor, equivalent, exactly, atleast, atmost, implies, lnot, xor
-)
-
-from .current import (
+from pyomo.core.expr.current import (
log, log10, sin, cos, tan, cosh, sinh, tanh,
asin, acos, atan, exp, sqrt, asinh, acosh,
atanh, ceil, floor,
Expr_if,
)
-from .calculus.derivatives import differentiate
-from .taylor_series import taylor_series_expansion
+from pyomo.core.expr.calculus.derivatives import differentiate
+from pyomo.core.expr.taylor_series import taylor_series_expansion
diff --git a/pyomo/core/expr/calculus/derivatives.py b/pyomo/core/expr/calculus/derivatives.py
index 2537b6d78bd..a41e4bc5e67 100644
--- a/pyomo/core/expr/calculus/derivatives.py
+++ b/pyomo/core/expr/calculus/derivatives.py
@@ -1,5 +1,14 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import enum
-from pyomo.common.collections import ComponentMap
from .diff_with_sympy import differentiate as sympy_diff
from .diff_with_pyomo import reverse_sd, reverse_ad
diff --git a/pyomo/core/expr/calculus/diff_with_pyomo.py b/pyomo/core/expr/calculus/diff_with_pyomo.py
index b08b253f401..cb4d12182fe 100644
--- a/pyomo/core/expr/calculus/diff_with_pyomo.py
+++ b/pyomo/core/expr/calculus/diff_with_pyomo.py
@@ -1,8 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from pyomo.common.collections import ComponentMap
from pyomo.core.expr import current as _expr
from pyomo.core.expr.visitor import ExpressionValueVisitor, nonpyomo_leaf_types
from pyomo.core.expr.numvalue import value
-from pyomo.core.expr.current import exp, log, sin, cos, tan, asin, acos, atan
+from pyomo.core.expr.current import exp, log, sin, cos
import math
@@ -53,6 +63,15 @@ def _diff_SumExpression(node, val_dict, der_dict):
der_dict[arg] += der
+def _diff_LinearExpression(node, val_dict, der_dict):
+ der = der_dict[node]
+ for ndx, v in enumerate(node.linear_vars):
+ coef = node.linear_coefs[ndx]
+ der_dict[v] += der * val_dict[coef]
+ der_dict[coef] += der * val_dict[v]
+
+ der_dict[node.constant] += der
+
def _diff_PowExpression(node, val_dict, der_dict):
"""
@@ -325,6 +344,16 @@ def _diff_ExternalFunctionExpression(node, val_dict, der_dict):
_diff_map[_expr.NegationExpression] = _diff_NegationExpression
_diff_map[_expr.UnaryFunctionExpression] = _diff_UnaryFunctionExpression
_diff_map[_expr.ExternalFunctionExpression] = _diff_ExternalFunctionExpression
+_diff_map[_expr.LinearExpression] = _diff_LinearExpression
+
+_diff_map[_expr.NPV_ProductExpression] = _diff_ProductExpression
+_diff_map[_expr.NPV_DivisionExpression] = _diff_DivisionExpression
+_diff_map[_expr.NPV_ReciprocalExpression] = _diff_ReciprocalExpression
+_diff_map[_expr.NPV_PowExpression] = _diff_PowExpression
+_diff_map[_expr.NPV_SumExpression] = _diff_SumExpression
+_diff_map[_expr.NPV_NegationExpression] = _diff_NegationExpression
+_diff_map[_expr.NPV_UnaryFunctionExpression] = _diff_UnaryFunctionExpression
+_diff_map[_expr.NPV_ExternalFunctionExpression] = _diff_ExternalFunctionExpression
class _NamedExpressionCollector(ExpressionValueVisitor):
@@ -393,6 +422,18 @@ def visiting_potential_leaf(self, node):
self.der_dict[node] = 0
return True, node
+ if node.__class__ is _expr.LinearExpression:
+ for v in node.linear_vars + node.linear_coefs + [node.constant]:
+ val = value(v)
+ self.val_dict[v] = val
+ if v not in self.der_dict:
+ self.der_dict[v] = 0
+ val = value(node)
+ self.val_dict[node] = val
+ if node not in self.der_dict:
+ self.der_dict[node] = 0
+ return True, val
+
if not node.is_expression_type():
val = value(node)
self.val_dict[node] = val
@@ -488,6 +529,18 @@ def visiting_potential_leaf(self, node):
self.der_dict[node] = 0
return True, node
+ if node.__class__ is _expr.LinearExpression:
+ for v in node.linear_vars + node.linear_coefs + [node.constant]:
+ val = v
+ self.val_dict[v] = val
+ if v not in self.der_dict:
+ self.der_dict[v] = 0
+ val = node
+ self.val_dict[node] = val
+ if node not in self.der_dict:
+ self.der_dict[node] = 0
+ return True, val
+
if not node.is_expression_type():
val = node
self.val_dict[node] = val
diff --git a/pyomo/core/expr/calculus/diff_with_sympy.py b/pyomo/core/expr/calculus/diff_with_sympy.py
index 3e290da8db8..bc4c58c89c1 100644
--- a/pyomo/core/expr/calculus/diff_with_sympy.py
+++ b/pyomo/core/expr/calculus/diff_with_sympy.py
@@ -9,7 +9,6 @@
# ___________________________________________________________________________
from pyomo.core.expr.sympy_tools import sympy_available, sympyify_expression, sympy2pyomo_expression
-from pyomo.common.errors import NondifferentiableError
# A "public" attribute indicating that differentiate() can be called
# ... this provides a bit of future-proofing for alternative approaches
diff --git a/pyomo/core/expr/current.py b/pyomo/core/expr/current.py
index d36f3c4ac12..590e00092ac 100755
--- a/pyomo/core/expr/current.py
+++ b/pyomo/core/expr/current.py
@@ -11,6 +11,11 @@
from __future__ import division
import math
+#
+# Common intrinsic functions
+#
+from pyomo.core.expr import expr_common as common
+
#
# Provide a global value that indicates which expression system is being used
#
@@ -18,10 +23,6 @@ class Mode(object):
pyomo5_trees = (3,)
_mode = Mode.pyomo5_trees
-#
-# Common intrinsic functions
-#
-from pyomo.core.expr import expr_common as common
#
# Pull symbols from the appropriate expression system
#
@@ -31,22 +32,111 @@ class Mode(object):
# Pyomo5
if _mode == Mode.pyomo5_trees:
from pyomo.core.expr import numeric_expr as _numeric_expr
- from pyomo.core.expr.numeric_expr import *
- from pyomo.core.expr.numeric_expr import (
- _generate_sum_expression,
- _generate_mul_expression,
- _generate_other_expression,
- _generate_intrinsic_function_expression,
- )
+ from pyomo.core.expr.numeric_expr import (_add, _sub, _mul, _div, _pow,
+ _neg, _abs, _inplace, _unary,
+ NumericValue, native_types,
+ nonpyomo_leaf_types,
+ native_numeric_types,
+ as_numeric, value,
+ evaluate_expression,
+ expression_to_string,
+ polynomial_degree,
+ clone_expression,
+ sizeof_expression,
+ _expression_is_fixed,
+ clone_counter,
+ nonlinear_expression,
+ linear_expression, ExpressionBase,
+ NegationExpression,
+ NPV_NegationExpression,
+ ExternalFunctionExpression,
+ NPV_ExternalFunctionExpression,
+ PowExpression, NPV_PowExpression,
+ ProductExpression,
+ NPV_ProductExpression,
+ MonomialTermExpression,
+ DivisionExpression,
+ NPV_DivisionExpression,
+ ReciprocalExpression,
+ NPV_ReciprocalExpression,
+ _LinearOperatorExpression,
+ SumExpressionBase,
+ NPV_SumExpression, SumExpression,
+ _MutableSumExpression,
+ Expr_ifExpression,
+ UnaryFunctionExpression,
+ NPV_UnaryFunctionExpression,
+ AbsExpression, NPV_AbsExpression,
+ LinearExpression,
+ _MutableLinearExpression,
+ decompose_term,
+ LinearDecompositionError,
+ _decompose_linear_terms,
+ _process_arg,
+ _generate_sum_expression,
+ _generate_mul_expression,
+ _generate_other_expression,
+ _generate_intrinsic_function_expression,
+ _balanced_parens,
+ NPV_expression_types)
from pyomo.core.expr import logical_expr as _logical_expr
- from pyomo.core.expr.logical_expr import *
- from pyomo.core.expr.logical_expr import (
- _generate_relational_expression,
- _chainedInequality,
- )
- from pyomo.core.expr.template_expr import *
+ from pyomo.core.expr.logical_expr import (native_logical_types, BooleanValue,
+ BooleanConstant, _lt, _le, _eq,
+ _and, _or, _equiv, _inv, _xor,
+ _impl, _chainedInequality,
+ RangedExpression,
+ InequalityExpression, inequality,
+ EqualityExpression,
+ _generate_relational_expression,
+ _generate_logical_proposition,
+ BooleanExpressionBase, lnot,
+ equivalent, xor, implies,
+ _flattened, land, lor, exactly,
+ atmost, atleast,
+ UnaryBooleanExpression,
+ NotExpression,
+ BinaryBooleanExpression,
+ EquivalenceExpression,
+ XorExpression,
+ ImplicationExpression,
+ NaryBooleanExpression,
+ _add_to_and_or_expression,
+ AndExpression, OrExpression,
+ ExactlyExpression,
+ AtMostExpression,
+ AtLeastExpression,
+ special_boolean_atom_types)
+ from pyomo.core.expr.template_expr import (TemplateExpressionError,
+ _NotSpecified, GetItemExpression,
+ GetAttrExpression,
+ _TemplateSumExpression_argList,
+ TemplateSumExpression,
+ IndexTemplate, resolve_template,
+ ReplaceTemplateExpression,
+ substitute_template_expression,
+ _GetItemIndexer,
+ substitute_getitem_with_param,
+ substitute_template_with_value,
+ _set_iterator_template_generator,
+ _template_iter_context,
+ templatize_rule,
+ templatize_constraint)
from pyomo.core.expr import visitor as _visitor
- from pyomo.core.expr.visitor import *
+ from pyomo.core.expr.visitor import (SymbolMap, StreamBasedExpressionVisitor,
+ SimpleExpressionVisitor,
+ ExpressionValueVisitor,
+ replace_expressions,
+ ExpressionReplacementVisitor,
+ _EvaluationVisitor,
+ FixedExpressionError,
+ NonConstantExpressionError,
+ _EvaluateConstantExpressionVisitor,
+ _ComponentVisitor, identify_components,
+ _VariableVisitor, identify_variables,
+ _MutableParamVisitor,
+ identify_mutable_parameters,
+ _PolynomialDegreeVisitor,
+ _IsFixedVisitor, _ToStringVisitor)
# FIXME: we shouldn't need circular dependencies between modules
_visitor.LinearExpression = _numeric_expr.LinearExpression
_visitor.MonomialTermExpression = _numeric_expr.MonomialTermExpression
diff --git a/pyomo/core/expr/logical_expr.py b/pyomo/core/expr/logical_expr.py
index dda4d89bd93..f15a41e49f0 100644
--- a/pyomo/core/expr/logical_expr.py
+++ b/pyomo/core/expr/logical_expr.py
@@ -34,11 +34,7 @@
)
from .expr_common import (
- _add, _sub, _mul, _div,
- _pow, _neg, _abs, _inplace,
- _unary, _radd, _rsub, _rmul,
- _rdiv, _rpow, _iadd, _isub,
- _imul, _idiv, _ipow, _lt, _le,
+ _lt, _le,
_eq,
_and, _or, _equiv, _inv, _xor, _impl)
diff --git a/pyomo/core/expr/numeric_expr.py b/pyomo/core/expr/numeric_expr.py
index 418061dad2c..0fe25d98139 100644
--- a/pyomo/core/expr/numeric_expr.py
+++ b/pyomo/core/expr/numeric_expr.py
@@ -13,25 +13,19 @@
import math
import logging
from itertools import islice
-from six import itervalues
logger = logging.getLogger('pyomo.core')
from pyutilib.math.util import isclose
from pyomo.common.deprecation import deprecated
-from pyomo.common.errors import DeveloperError
from .expr_common import (
_add, _sub, _mul, _div,
_pow, _neg, _abs, _inplace,
- _unary, _radd, _rsub, _rmul,
- _rdiv, _rpow, _iadd, _isub,
- _imul, _idiv, _ipow, _lt, _le,
- _eq,
+ _unary
)
from .numvalue import (
NumericValue,
- NumericConstant,
native_types,
nonpyomo_leaf_types,
native_numeric_types,
diff --git a/pyomo/core/expr/numvalue.py b/pyomo/core/expr/numvalue.py
index 4ce25f5019a..b516f729e5a 100644
--- a/pyomo/core/expr/numvalue.py
+++ b/pyomo/core/expr/numvalue.py
@@ -15,11 +15,11 @@
import sys
import logging
-from six import iteritems, PY3, string_types, text_type, binary_type
+from six import iteritems, PY3
from pyomo.core.expr.expr_common import \
(_add, _sub, _mul, _div, _pow,
- _neg, _abs, _inplace, _radd,
+ _neg, _abs, _radd,
_rsub, _rmul, _rdiv, _rpow,
_iadd, _isub, _imul, _idiv,
_ipow, _lt, _le, _eq)
@@ -118,6 +118,7 @@ def __setstate__(self, state):
else:
native_types.add(unicode)
native_boolean_types.add(unicode)
+
native_types.update( native_numeric_types )
native_types.update( native_integer_types )
native_types.update( native_boolean_types )
diff --git a/pyomo/core/expr/symbol_map.py b/pyomo/core/expr/symbol_map.py
index 8f73181e981..15f7979fc22 100644
--- a/pyomo/core/expr/symbol_map.py
+++ b/pyomo/core/expr/symbol_map.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
from weakref import ref as weakref_ref
-from six import iteritems, iterkeys
+from six import iteritems
class SymbolMap(object):
"""
diff --git a/pyomo/core/expr/sympy_tools.py b/pyomo/core/expr/sympy_tools.py
index 568debcf098..b1cba66f67a 100644
--- a/pyomo/core/expr/sympy_tools.py
+++ b/pyomo/core/expr/sympy_tools.py
@@ -8,13 +8,11 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from six import StringIO, iterkeys
-import pyutilib.misc
+from six import iterkeys
from pyomo.common import DeveloperError
from pyomo.common.collections import ComponentMap
from pyomo.common.dependencies import attempt_import
from pyomo.common.errors import NondifferentiableError
-from pyomo.core.expr import current
from pyomo.core.expr import current as EXPR, native_types
from pyomo.core.expr.numvalue import value
@@ -35,23 +33,23 @@ def _configure_sympy(sympy, available):
sympy.Add: _sum,
sympy.Mul: _prod,
sympy.Pow: lambda x, y: x**y,
- sympy.exp: lambda x: current.exp(x),
- sympy.log: lambda x: current.log(x),
- sympy.sin: lambda x: current.sin(x),
- sympy.asin: lambda x: current.asin(x),
- sympy.sinh: lambda x: current.sinh(x),
- sympy.asinh: lambda x: current.asinh(x),
- sympy.cos: lambda x: current.cos(x),
- sympy.acos: lambda x: current.acos(x),
- sympy.cosh: lambda x: current.cosh(x),
- sympy.acosh: lambda x: current.acosh(x),
- sympy.tan: lambda x: current.tan(x),
- sympy.atan: lambda x: current.atan(x),
- sympy.tanh: lambda x: current.tanh(x),
- sympy.atanh: lambda x: current.atanh(x),
- sympy.ceiling: lambda x: current.ceil(x),
- sympy.floor: lambda x: current.floor(x),
- sympy.sqrt: lambda x: current.sqrt(x),
+ sympy.exp: lambda x: EXPR.exp(x),
+ sympy.log: lambda x: EXPR.log(x),
+ sympy.sin: lambda x: EXPR.sin(x),
+ sympy.asin: lambda x: EXPR.asin(x),
+ sympy.sinh: lambda x: EXPR.sinh(x),
+ sympy.asinh: lambda x: EXPR.asinh(x),
+ sympy.cos: lambda x: EXPR.cos(x),
+ sympy.acos: lambda x: EXPR.acos(x),
+ sympy.cosh: lambda x: EXPR.cosh(x),
+ sympy.acosh: lambda x: EXPR.acosh(x),
+ sympy.tan: lambda x: EXPR.tan(x),
+ sympy.atan: lambda x: EXPR.atan(x),
+ sympy.tanh: lambda x: EXPR.tanh(x),
+ sympy.atanh: lambda x: EXPR.atanh(x),
+ sympy.ceiling: lambda x: EXPR.ceil(x),
+ sympy.floor: lambda x: EXPR.floor(x),
+ sympy.sqrt: lambda x: EXPR.sqrt(x),
sympy.Abs: lambda x: abs(x),
sympy.Derivative: _nondifferentiable,
sympy.Tuple: lambda *x: x,
diff --git a/pyomo/core/expr/template_expr.py b/pyomo/core/expr/template_expr.py
index 6c45fa6f07e..72420d5df97 100644
--- a/pyomo/core/expr/template_expr.py
+++ b/pyomo/core/expr/template_expr.py
@@ -12,12 +12,12 @@
import itertools
import logging
import sys
-from six import iteritems, itervalues
+from six import itervalues
from six.moves import builtins
from pyomo.core.expr.expr_errors import TemplateExpressionError
from pyomo.core.expr.numvalue import (
- NumericValue, native_numeric_types, native_types, nonpyomo_leaf_types,
+ NumericValue, native_types, nonpyomo_leaf_types,
as_numeric, value,
)
from pyomo.core.expr.numeric_expr import ExpressionBase, SumExpression
diff --git a/pyomo/core/expr/visitor.py b/pyomo/core/expr/visitor.py
index 33b241318f1..c74b324539e 100644
--- a/pyomo/core/expr/visitor.py
+++ b/pyomo/core/expr/visitor.py
@@ -25,9 +25,6 @@
logger = logging.getLogger('pyomo.core')
-from pyutilib.misc.visitor import SimpleVisitor, ValueVisitor
-from pyutilib.math.util import isclose
-
from .symbol_map import SymbolMap
from . import expr_common as common
from .expr_errors import TemplateExpressionError
diff --git a/pyomo/core/kernel/__init__.py b/pyomo/core/kernel/__init__.py
index 45845531093..331280a1477 100644
--- a/pyomo/core/kernel/__init__.py
+++ b/pyomo/core/kernel/__init__.py
@@ -8,7 +8,26 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core.expr import *
+from pyomo.core.expr import numvalue, numeric_expr, boolean_value, logical_expr, current
+from pyomo.core.expr.numvalue import (
+ value, is_constant, is_fixed, is_variable_type,
+ is_potentially_variable, NumericValue, ZeroConstant,
+ native_numeric_types, native_types, polynomial_degree,
+)
+from pyomo.core.expr.boolean_value import BooleanValue
+from pyomo.core.expr.numeric_expr import linear_expression, nonlinear_expression
+from pyomo.core.expr.logical_expr import (land, lor, equivalent, exactly,
+ atleast, atmost, implies, lnot,
+ xor, inequality)
+from pyomo.core.expr.current import (
+ log, log10, sin, cos, tan, cosh, sinh, tanh,
+ asin, acos, atan, exp, sqrt, asinh, acosh,
+ atanh, ceil, floor,
+ Expr_if,
+)
+from pyomo.core.expr.calculus.derivatives import differentiate
+from pyomo.core.expr.taylor_series import taylor_series_expansion
+
import pyomo.core.kernel.register_numpy_types
import pyomo.core.kernel.base
import pyomo.core.kernel.homogeneous_container
diff --git a/pyomo/core/kernel/block.py b/pyomo/core/kernel/block.py
index 6b804f407c3..18190888e10 100644
--- a/pyomo/core/kernel/block.py
+++ b/pyomo/core/kernel/block.py
@@ -357,7 +357,6 @@ def load_solution(self,
value in the solution is consistent with the
value of a fixed variable.
"""
- import pyomo.opt
from pyomo.core.kernel.suffix import \
import_suffix_generator
diff --git a/pyomo/core/kernel/component_map.py b/pyomo/core/kernel/component_map.py
index 6485385d42c..e4cc4f8b172 100644
--- a/pyomo/core/kernel/component_map.py
+++ b/pyomo/core/kernel/component_map.py
@@ -13,4 +13,4 @@
deprecation_warning(
'The pyomo.core.kernel.component_map module is deprecated. '
'Import ComponentMap from pyomo.common.collections.',
- version='TBD')
+ version='5.7.1')
diff --git a/pyomo/core/kernel/component_set.py b/pyomo/core/kernel/component_set.py
index b789aaefe97..db830400a2c 100644
--- a/pyomo/core/kernel/component_set.py
+++ b/pyomo/core/kernel/component_set.py
@@ -13,4 +13,4 @@
deprecation_warning(
'The pyomo.core.kernel.component_set module is deprecated. '
'Import ComponentSet from pyomo.common.collections.',
- version='TBD')
+ version='5.7.1')
diff --git a/pyomo/core/kernel/constraint.py b/pyomo/core/kernel/constraint.py
index 93d3a92728a..4e23f4188a1 100644
--- a/pyomo/core/kernel/constraint.py
+++ b/pyomo/core/kernel/constraint.py
@@ -9,22 +9,17 @@
# ___________________________________________________________________________
from pyomo.core.expr.numvalue import (ZeroConstant,
- is_constant,
as_numeric,
- native_types,
is_potentially_variable,
is_numeric_data,
- value,
- _sub)
+ value)
from pyomo.core.expr import logical_expr
from pyomo.core.kernel.base import \
(ICategorizedObject,
- _abstract_readwrite_property,
_abstract_readonly_property)
from pyomo.core.kernel.container_utils import \
define_simple_containers
-import six
from six.moves import zip
_pos_inf = float('inf')
diff --git a/pyomo/core/kernel/dict_container.py b/pyomo/core/kernel/dict_container.py
index cfc3d4485e1..eebf65b205a 100644
--- a/pyomo/core/kernel/dict_container.py
+++ b/pyomo/core/kernel/dict_container.py
@@ -24,7 +24,7 @@
IHomogeneousContainer
import six
-from six import itervalues, iteritems
+from six import itervalues
if six.PY3:
from collections.abc import MutableMapping as collections_MutableMapping
diff --git a/pyomo/core/kernel/expression.py b/pyomo/core/kernel/expression.py
index 2a98c8e7ebd..7fda9f49ff5 100644
--- a/pyomo/core/kernel/expression.py
+++ b/pyomo/core/kernel/expression.py
@@ -8,26 +8,19 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import sys
-
-from pyomo.core.expr import expr_common
from pyomo.core.expr import current as EXPR
from pyomo.core.kernel.base import \
(ICategorizedObject,
- _abstract_readwrite_property,
- _abstract_readonly_property)
+ _abstract_readwrite_property)
from pyomo.core.kernel.container_utils import \
define_simple_containers
from pyomo.core.expr.numvalue import (NumericValue,
is_fixed,
is_constant,
- is_variable_type,
is_potentially_variable,
is_numeric_data,
value)
-import six
-
class IIdentityExpression(NumericValue):
"""The interface for classes that simply wrap another
expression and perform no additional operations.
diff --git a/pyomo/core/kernel/homogeneous_container.py b/pyomo/core/kernel/homogeneous_container.py
index 1ead62255ef..8cdb855ebf5 100644
--- a/pyomo/core/kernel/homogeneous_container.py
+++ b/pyomo/core/kernel/homogeneous_container.py
@@ -8,10 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core.kernel.base import \
- (_no_ctype,
- _convert_descend_into,
- ICategorizedObjectContainer)
+from pyomo.core.kernel.base import ICategorizedObjectContainer
class IHomogeneousContainer(ICategorizedObjectContainer):
"""
diff --git a/pyomo/core/kernel/matrix_constraint.py b/pyomo/core/kernel/matrix_constraint.py
index 044631cf4a4..9b081c1534f 100644
--- a/pyomo/core/kernel/matrix_constraint.py
+++ b/pyomo/core/kernel/matrix_constraint.py
@@ -12,13 +12,11 @@
numpy, numpy_available as has_numpy,
scipy, scipy_available as has_scipy,
)
-import pyomo.core.expr
from pyomo.core.expr.numvalue import NumericValue
from pyomo.core.kernel.constraint import \
(IConstraint,
constraint_tuple)
-import six
from six.moves import zip, xrange
_noarg = object()
diff --git a/pyomo/core/kernel/objective.py b/pyomo/core/kernel/objective.py
index 15cae0b0e39..b5d006a18f9 100644
--- a/pyomo/core/kernel/objective.py
+++ b/pyomo/core/kernel/objective.py
@@ -9,20 +9,15 @@
# ___________________________________________________________________________
from pyomo.core.expr.numvalue import as_numeric
-from pyomo.core.kernel.base import \
- (ICategorizedObject,
- _abstract_readwrite_property,
- _abstract_readonly_property)
-from pyomo.core.kernel.container_utils import \
- define_simple_containers
+from pyomo.core.kernel.base import _abstract_readwrite_property
+from pyomo.core.kernel.container_utils import define_simple_containers
from pyomo.core.kernel.expression import IExpression
-import six
-
# Constants used to define the optimization sense
minimize=1
maximize=-1
+
class IObjective(IExpression):
"""
The interface for optimization objectives.
@@ -46,6 +41,7 @@ class IObjective(IExpression):
def is_minimizing(self):
return self.sense == minimize
+
class objective(IObjective):
"""An optimization objective."""
_ctype = IObjective
@@ -73,6 +69,7 @@ def __init__(self, expr=None, sense=minimize):
@property
def expr(self):
return self._expr
+
@expr.setter
def expr(self, expr):
self._expr = as_numeric(expr) if (expr is not None) else None
@@ -84,6 +81,7 @@ def expr(self, expr):
@property
def sense(self):
return self._sense
+
@sense.setter
def sense(self, sense):
"""Set the sense (direction) of this objective."""
@@ -96,6 +94,7 @@ def sense(self, sense):
"[minimize (%s), maximize (%s)]. Invalid "
"value: %s'" % (minimize, maximize, sense))
+
# inserts class definitions for simple _tuple, _list, and
# _dict containers into this module
define_simple_containers(globals(),
diff --git a/pyomo/core/kernel/parameter.py b/pyomo/core/kernel/parameter.py
index c6bde55277c..a985e3205dd 100644
--- a/pyomo/core/kernel/parameter.py
+++ b/pyomo/core/kernel/parameter.py
@@ -8,17 +8,11 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import pyomo.core.expr
from pyomo.core.expr.numvalue import (is_numeric_data,
NumericValue)
-from pyomo.core.kernel.base import \
- (ICategorizedObject,
- _abstract_readwrite_property,
- _abstract_readonly_property)
-from pyomo.core.kernel.container_utils import \
- define_simple_containers
+from pyomo.core.kernel.base import ICategorizedObject
+from pyomo.core.kernel.container_utils import define_simple_containers
-import six
class IParameter(ICategorizedObject, NumericValue):
"""The interface for mutable numeric data."""
@@ -64,6 +58,7 @@ def polynomial_degree(self):
variables."""
return 0
+
class parameter(IParameter):
"""A object for storing a mutable, numeric value that
can be used to build a symbolic expression."""
@@ -95,10 +90,12 @@ def __call__(self, exception=True):
def value(self):
"""The value of the paramater"""
return self._value
+
@value.setter
def value(self, value):
self._value = value
+
class functional_value(IParameter):
"""An object for storing a numeric function that can be
used in a symbolic expression.
@@ -146,10 +143,12 @@ def __call__(self, exception=True):
def fn(self):
"""The function stored with this object"""
return self._fn
+
@fn.setter
def fn(self, fn):
self._fn = fn
+
# inserts class definitions for simple _tuple, _list, and
# _dict containers into this module
define_simple_containers(globals(),
diff --git a/pyomo/core/kernel/piecewise_library/transforms.py b/pyomo/core/kernel/piecewise_library/transforms.py
index db5f1df8928..dcc588b6bf6 100644
--- a/pyomo/core/kernel/piecewise_library/transforms.py
+++ b/pyomo/core/kernel/piecewise_library/transforms.py
@@ -39,8 +39,7 @@
variable_tuple,
variable_dict,
variable)
-from pyomo.core.kernel.constraint import (constraint,
- constraint_list,
+from pyomo.core.kernel.constraint import (constraint_list,
constraint_tuple,
linear_constraint)
from pyomo.core.kernel.sos import sos2
@@ -52,8 +51,7 @@
generate_gray_code,
PiecewiseValidationError)
-import six
-from six.moves import xrange, zip
+from six.moves import xrange
logger = logging.getLogger('pyomo.core')
diff --git a/pyomo/core/kernel/piecewise_library/util.py b/pyomo/core/kernel/piecewise_library/util.py
index 14072d10323..5c389e852dc 100644
--- a/pyomo/core/kernel/piecewise_library/util.py
+++ b/pyomo/core/kernel/piecewise_library/util.py
@@ -11,7 +11,6 @@
import operator
import itertools
-import six
from six.moves import xrange
from six import advance_iterator
diff --git a/pyomo/core/kernel/set_types.py b/pyomo/core/kernel/set_types.py
index c77cb970d52..ca82d2fcca1 100644
--- a/pyomo/core/kernel/set_types.py
+++ b/pyomo/core/kernel/set_types.py
@@ -9,11 +9,6 @@
# ___________________________________________________________________________
import logging
-from weakref import ref as weakref_ref
-
-from pyomo.core.expr.numvalue import (native_numeric_types,
- native_integer_types,
- native_boolean_types)
logger = logging.getLogger('pyomo.core')
diff --git a/pyomo/core/kernel/sos.py b/pyomo/core/kernel/sos.py
index fd8798b1821..fdb2401b849 100644
--- a/pyomo/core/kernel/sos.py
+++ b/pyomo/core/kernel/sos.py
@@ -8,16 +8,13 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import pyomo.core.expr
from pyomo.core.expr.numvalue import is_numeric_data
from pyomo.core.kernel.base import \
(ICategorizedObject,
- _abstract_readwrite_property,
- _abstract_readonly_property)
+ _abstract_readwrite_property)
from pyomo.core.kernel.container_utils import \
define_simple_containers
-import six
from six.moves import zip
class ISOS(ICategorizedObject):
diff --git a/pyomo/core/kernel/suffix.py b/pyomo/core/kernel/suffix.py
index 6c2488f5637..90592cf665e 100644
--- a/pyomo/core/kernel/suffix.py
+++ b/pyomo/core/kernel/suffix.py
@@ -12,9 +12,7 @@
from pyomo.common.collections import ComponentMap
from pyomo.core.kernel.base import (
- ICategorizedObject,
- _abstract_readwrite_property,
- _abstract_readonly_property,
+ ICategorizedObject, _abstract_readonly_property
)
from pyomo.core.kernel.dict_container import DictContainer
from pyomo.core.kernel.container_utils import (
diff --git a/pyomo/core/kernel/tuple_container.py b/pyomo/core/kernel/tuple_container.py
index e37d108e090..34b32cbdf4d 100644
--- a/pyomo/core/kernel/tuple_container.py
+++ b/pyomo/core/kernel/tuple_container.py
@@ -12,7 +12,6 @@
IHomogeneousContainer
import six
-from six.moves import xrange as range
if six.PY3:
from collections.abc import Sequence as collections_Sequence
diff --git a/pyomo/core/kernel/variable.py b/pyomo/core/kernel/variable.py
index bd22bdcdd12..382aad7e70e 100644
--- a/pyomo/core/kernel/variable.py
+++ b/pyomo/core/kernel/variable.py
@@ -13,8 +13,7 @@
value)
from pyomo.core.kernel.base import \
(ICategorizedObject,
- _abstract_readwrite_property,
- _abstract_readonly_property)
+ _abstract_readwrite_property)
from pyomo.core.kernel.container_utils import \
define_simple_containers
from pyomo.core.kernel.set_types import (RealSet,
diff --git a/pyomo/core/plugins/transform/add_slack_vars.py b/pyomo/core/plugins/transform/add_slack_vars.py
index 6ce699121c5..16c13edb582 100644
--- a/pyomo/core/plugins/transform/add_slack_vars.py
+++ b/pyomo/core/plugins/transform/add_slack_vars.py
@@ -1,15 +1,26 @@
-import pyomo.environ
-from pyomo.core import *
-from pyomo.gdp import *
-from pyomo.opt import SolverFactory
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import TransformationFactory, Var, NonNegativeReals, Constraint, Objective, Block, value
+
+from six import iterkeys
from pyomo.common.modeling import unique_component_name
from pyomo.core.plugins.transform.hierarchy import NonIsomorphicTransformation
from pyomo.common.config import ConfigBlock, ConfigValue
from pyomo.core.base.component import ComponentUID
-from pyomo.core.base import Constraint, _ConstraintData
+from pyomo.core.base import _ConstraintData
from pyomo.common.deprecation import deprecation_warning
+NAME_BUFFER = {}
+
def target_list(x):
deprecation_msg = ("In future releases ComponentUID targets will no "
"longer be supported in the core.add_slack_variables "
@@ -46,6 +57,9 @@ def target_list(x):
"Expected Constraint or list of Constraints."
"\n\tRecieved %s" % (type(x),))
+import logging
+logger = logging.getLogger('pyomo.core')
+
@TransformationFactory.register('core.add_slack_variables', \
doc="Create a model where we add slack variables to every constraint "
@@ -72,6 +86,13 @@ def __init__(self, **kwds):
super(AddSlackVariables, self).__init__(**kwds)
def _apply_to(self, instance, **kwds):
+ try:
+ assert not NAME_BUFFER
+ self._apply_to_impl(instance, **kwds)
+ finally:
+ NAME_BUFFER.clear()
+
+ def _apply_to_impl(self, instance, **kwds):
config = self.CONFIG(kwds.pop('options', {}))
config.set_value(kwds)
targets = config.targets
@@ -116,10 +137,12 @@ def _apply_to(self, instance, **kwds):
raise RuntimeError("Lower bound exceeds upper bound in "
"constraint %s" % cons.name)
if not cons.active: continue
+ cons_name = cons.getname(fully_qualified=True,
+ name_buffer=NAME_BUFFER)
if cons.lower is not None:
# we add positive slack variable to body:
# declare positive slack
- varName = "_slack_plus_" + cons.name
+ varName = "_slack_plus_" + cons_name
posSlack = Var(within=NonNegativeReals)
xblock.add_component(varName, posSlack)
# add positive slack to body expression
@@ -129,7 +152,7 @@ def _apply_to(self, instance, **kwds):
if cons.upper is not None:
# we subtract a positive slack variable from the body:
# declare slack
- varName = "_slack_minus_" + cons.name
+ varName = "_slack_minus_" + cons_name
negSlack = Var(within=NonNegativeReals)
xblock.add_component(varName, negSlack)
# add negative slack to body expression
diff --git a/pyomo/core/plugins/transform/eliminate_fixed_vars.py b/pyomo/core/plugins/transform/eliminate_fixed_vars.py
index 4844604b625..138c2f9c878 100644
--- a/pyomo/core/plugins/transform/eliminate_fixed_vars.py
+++ b/pyomo/core/plugins/transform/eliminate_fixed_vars.py
@@ -10,7 +10,7 @@
from pyomo.core.expr.current import ExpressionBase
from pyomo.core.expr.numvalue import as_numeric
-from pyomo.core import Constraint, Objective
+from pyomo.core import Constraint, Objective, TransformationFactory
from pyomo.core.base.var import Var, _VarData
from pyomo.core.base.util import sequence
from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
diff --git a/pyomo/core/plugins/transform/equality_transform.py b/pyomo/core/plugins/transform/equality_transform.py
index 9356217af6e..8f45851ed52 100644
--- a/pyomo/core/plugins/transform/equality_transform.py
+++ b/pyomo/core/plugins/transform/equality_transform.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core import *
+from pyomo.core import TransformationFactory, Var, NonNegativeReals
from pyomo.core.base.misc import create_name
from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
diff --git a/pyomo/core/plugins/transform/expand_connectors.py b/pyomo/core/plugins/transform/expand_connectors.py
index 30cc718397a..c606e59b90b 100644
--- a/pyomo/core/plugins/transform/expand_connectors.py
+++ b/pyomo/core/plugins/transform/expand_connectors.py
@@ -16,7 +16,7 @@
from pyomo.common.collections import ComponentMap, ComponentSet
from pyomo.core.expr import current as EXPR
from pyomo.core.base import Transformation, TransformationFactory, Connector, Constraint, \
- ConstraintList, Var, VarList, TraversalStrategy, SortComponents
+ ConstraintList, Var, SortComponents
from pyomo.core.base.connector import _ConnectorData, SimpleConnector
diff --git a/pyomo/core/plugins/transform/nonnegative_transform.py b/pyomo/core/plugins/transform/nonnegative_transform.py
index f50dd4490fd..d3afa2e38a6 100644
--- a/pyomo/core/plugins/transform/nonnegative_transform.py
+++ b/pyomo/core/plugins/transform/nonnegative_transform.py
@@ -8,13 +8,14 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import copy
-
from pyomo.core.expr import current as EXPR
-from pyomo.core import *
-from pyomo.core.base.expression import _ExpressionData
-from pyomo.core.base.var import SimpleVar, _VarData
+from pyomo.core import (nonpyomo_leaf_types, TransformationFactory, IntegerSet,
+ Integers, PositiveIntegers, NonPositiveIntegers,
+ NegativeIntegers, NonNegativeIntegers, Reals, PositiveReals,
+ NonNegativeReals, NegativeReals, NonPositiveReals,
+ PercentFraction, RealSet, Var, Set, value, Binary,
+ Constraint, Objective)
from pyomo.core.base.misc import create_name
from pyomo.core.plugins.transform.util import partial
from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
diff --git a/pyomo/core/plugins/transform/radix_linearization.py b/pyomo/core/plugins/transform/radix_linearization.py
index 252ec2e2778..c428e1a53f2 100644
--- a/pyomo/core/plugins/transform/radix_linearization.py
+++ b/pyomo/core/plugins/transform/radix_linearization.py
@@ -11,6 +11,7 @@
from pyomo.core.expr.current import ProductExpression, PowExpression
from pyomo.core import Binary, value
from pyomo.core.base import Transformation, TransformationFactory, Var, Constraint, ConstraintList, Block, RangeSet
+from pyomo.core.base.numvalue import as_numeric
from pyomo.core.base.var import _VarData
from six import iteritems
diff --git a/pyomo/core/plugins/transform/standard_form.py b/pyomo/core/plugins/transform/standard_form.py
index f20a2d53796..0125173f8a6 100644
--- a/pyomo/core/plugins/transform/standard_form.py
+++ b/pyomo/core/plugins/transform/standard_form.py
@@ -8,16 +8,16 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core import *
+from pyomo.core import TransformationFactory
from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
-from pyomo.core.plugins.transform.nonnegative_transform import *
-from pyomo.core.plugins.transform.equality_transform import *
+from pyomo.core.plugins.transform.nonnegative_transform import NonNegativeTransformation
+from pyomo.core.plugins.transform.equality_transform import EqualityTransform
@TransformationFactory.register("core.standard_form", doc="Create an equivalent LP model in standard form.")
class StandardForm(IsomorphicTransformation):
"""
- Produces a standard-form representation of the model. This form has
+ Produces a standard-form representation of the model. This form has
the coefficient matrix (A), the cost vector (c), and the
constraint vector (b), where the 'standard form' problem is
diff --git a/pyomo/core/plugins/transform/util.py b/pyomo/core/plugins/transform/util.py
index e7f997ff32c..958f0ac7982 100644
--- a/pyomo/core/plugins/transform/util.py
+++ b/pyomo/core/plugins/transform/util.py
@@ -13,7 +13,7 @@
# """
from inspect import isroutine
-from pyomo.core import *
+from pyomo.core import Var, Objective, Constraint, Set, Param
def collectAbstractComponents(model):
diff --git a/pyomo/core/tests/data/test_odbc_ini.py b/pyomo/core/tests/data/test_odbc_ini.py
index 50e63c701aa..7202c243283 100644
--- a/pyomo/core/tests/data/test_odbc_ini.py
+++ b/pyomo/core/tests/data/test_odbc_ini.py
@@ -12,19 +12,17 @@
#
import os
-
import pyutilib.th as unittest
-from pyomo.environ import *
-
try:
import pyodbc
pyodbc_available = True
- from pyomo.core.plugins.data.db_table import ODBCConfig, ODBCError
+ from pyomo.dataportal.plugins.db_table import ODBCConfig, ODBCError
except ImportError:
pyodbc_available = False
+
@unittest.skipIf(not pyodbc_available, "PyODBC is not installed.")
class TestODBCIni(unittest.TestCase):
@@ -66,33 +64,33 @@ def test_create(self):
def test_init_empty_data(self):
config = ODBCConfig()
- self.assertEquals({}, config.sources)
- self.assertEquals({}, config.source_specs)
- self.assertEquals({}, config.odbc_info)
+ self.assertEqual({}, config.sources)
+ self.assertEqual({}, config.source_specs)
+ self.assertEqual({}, config.odbc_info)
def test_init_simple_data(self):
config = ODBCConfig(data=self.simple_data)
- self.assertEquals({'testdb' : self.ACCESS_CONFIGSTR}, config.sources)
- self.assertEquals({'testdb' : {'Database' : "testdb.mdb"}}, config.source_specs)
- self.assertEquals({}, config.odbc_info)
+ self.assertEqual({'testdb' : self.ACCESS_CONFIGSTR}, config.sources)
+ self.assertEqual({'testdb' : {'Database' : "testdb.mdb"}}, config.source_specs)
+ self.assertEqual({}, config.odbc_info)
def test_init_complex_data(self):
config = ODBCConfig(data=self.complex_data)
- self.assertEquals({'test1' : self.ACCESS_CONFIGSTR, 'test2' : self.EXCEL_CONFIGSTR}, config.sources)
- self.assertEquals({'test1' : {'Database' : "test1.db", 'LogonID' : "Admin", 'pwd' : "secret_pass"}, 'test2' : {'Database' : "test2.xls"}}, config.source_specs)
- self.assertEquals({'UNICODE' : "UTF-8"}, config.odbc_info)
+ self.assertEqual({'test1' : self.ACCESS_CONFIGSTR, 'test2' : self.EXCEL_CONFIGSTR}, config.sources)
+ self.assertEqual({'test1' : {'Database' : "test1.db", 'LogonID' : "Admin", 'pwd' : "secret_pass"}, 'test2' : {'Database' : "test2.xls"}}, config.source_specs)
+ self.assertEqual({'UNICODE' : "UTF-8"}, config.odbc_info)
def test_add_source(self):
config = ODBCConfig()
config.add_source("testdb", self.ACCESS_CONFIGSTR)
- self.assertEquals({'testdb' : self.ACCESS_CONFIGSTR}, config.sources)
- self.assertEquals({}, config.source_specs)
- self.assertEquals({}, config.odbc_info)
+ self.assertEqual({'testdb' : self.ACCESS_CONFIGSTR}, config.sources)
+ self.assertEqual({}, config.source_specs)
+ self.assertEqual({}, config.odbc_info)
def test_del_source(self):
config = ODBCConfig(data=self.simple_data)
config.del_source('testdb')
- self.assertEquals({}, config.sources)
+ self.assertEqual({}, config.sources)
def test_add_source_reserved(self):
config = ODBCConfig()
@@ -105,7 +103,7 @@ def test_add_source_spec(self):
config = ODBCConfig()
config.add_source("testdb", self.ACCESS_CONFIGSTR)
config.add_source_spec("testdb", {'Database' : "testdb.mdb"})
- self.assertEquals({'testdb' : {'Database' : "testdb.mdb"}}, config.source_specs)
+ self.assertEqual({'testdb' : {'Database' : "testdb.mdb"}}, config.source_specs)
def test_add_spec_bad(self):
config = ODBCConfig()
@@ -117,13 +115,13 @@ def test_del_source_dependent(self):
config.add_source("testdb", self.ACCESS_CONFIGSTR)
config.add_source_spec("testdb", {'Database' : "testdb.mdb"})
config.del_source("testdb")
- self.assertEquals({}, config.sources)
- self.assertEquals({}, config.source_specs)
+ self.assertEqual({}, config.sources)
+ self.assertEqual({}, config.source_specs)
def test_set_odbc_info(self):
config = ODBCConfig()
config.set_odbc_info("UNICODE", "UTF-8")
- self.assertEquals({'UNICODE' : "UTF-8"}, config.odbc_info)
+ self.assertEqual({'UNICODE' : "UTF-8"}, config.odbc_info)
def test_odbc_repr(self):
config = ODBCConfig(data=self.simple_data)
@@ -140,7 +138,7 @@ def test_baselines(self):
config.write(outPath)
written = ODBCConfig(filename = outPath)
- self.assertEquals(config, written)
+ self.assertEqual(config, written)
try:
os.remove(outPath)
@@ -148,13 +146,13 @@ def test_baselines(self):
pass
def test_eq(self):
- self.assertEquals(ODBCConfig(), ODBCConfig())
+ self.assertEqual(ODBCConfig(), ODBCConfig())
configA = ODBCConfig(data=self.simple_data)
configB = ODBCConfig()
configB.sources = {'testdb' : self.ACCESS_CONFIGSTR}
configB.source_specs = {'testdb' : {'Database' : 'testdb.mdb'}}
- self.assertEquals(configA, configB)
+ self.assertEqual(configA, configB)
if __name__ == "__main__":
unittest.main()
diff --git a/pyomo/core/tests/examples/pmedian.py b/pyomo/core/tests/examples/pmedian.py
index d3ce86b9485..5e7071fa33b 100644
--- a/pyomo/core/tests/examples/pmedian.py
+++ b/pyomo/core/tests/examples/pmedian.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Param, RangeSet, Var, Reals, Binary, PositiveIntegers, Constraint, Objective
import math
model = AbstractModel()
diff --git a/pyomo/core/tests/examples/pmedian4.py b/pyomo/core/tests/examples/pmedian4.py
index c34b39b1c42..ad1bb0b1337 100644
--- a/pyomo/core/tests/examples/pmedian4.py
+++ b/pyomo/core/tests/examples/pmedian4.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, RangeSet, Param, Var, Reals, Binary, Objective, Constraint, ConstraintList
import math
N = 5
diff --git a/pyomo/core/tests/examples/test_book.py b/pyomo/core/tests/examples/test_book.py
index c5d9e282953..dfcd07617d9 100644
--- a/pyomo/core/tests/examples/test_book.py
+++ b/pyomo/core/tests/examples/test_book.py
@@ -22,7 +22,6 @@
os.chdir(test_dir)
sys.path.append(test_dir)
-#from test_book_examples import *
if __name__ == "__main__":
unittest.main()
diff --git a/pyomo/core/tests/examples/test_kernel_examples.py b/pyomo/core/tests/examples/test_kernel_examples.py
index 54f44001f66..ff8c7faa139 100644
--- a/pyomo/core/tests/examples/test_kernel_examples.py
+++ b/pyomo/core/tests/examples/test_kernel_examples.py
@@ -12,7 +12,6 @@
# Tests for Pyomo kernel examples
#
-import os
import glob
import sys
from os.path import basename, dirname, abspath, join
diff --git a/pyomo/core/tests/examples/test_tutorials.py b/pyomo/core/tests/examples/test_tutorials.py
index 8811c091734..c797d252180 100644
--- a/pyomo/core/tests/examples/test_tutorials.py
+++ b/pyomo/core/tests/examples/test_tutorials.py
@@ -17,11 +17,9 @@
currdir = dirname(abspath(__file__))+os.sep
tutorial_dir=topdir+os.sep+"examples"+os.sep+"pyomo"+os.sep+"tutorials"+os.sep
-import pyutilib.misc
+from pyutilib.misc import run_file
import pyutilib.th as unittest
-from pyomo.environ import *
-
try:
from win32com.client.dynamic import Dispatch
_win32com=True
@@ -59,24 +57,24 @@ def construct(self,filename):
pass
def test_data(self):
- pyutilib.misc.run_file(tutorial_dir+"data.py", logfile=currdir+"data.log", execdir=tutorial_dir)
+ run_file(tutorial_dir+"data.py", logfile=currdir+"data.log", execdir=tutorial_dir)
self.assertFileEqualsBaseline(currdir+"data.log", tutorial_dir+"data.out")
@unittest.skipIf(not ((_win32com and _excel_available) or _xlrd or _openpyxl), "Cannot read excel file.")
def test_excel(self):
- pyutilib.misc.run_file(tutorial_dir+"excel.py", logfile=currdir+"excel.log", execdir=tutorial_dir)
+ run_file(tutorial_dir+"excel.py", logfile=currdir+"excel.log", execdir=tutorial_dir)
self.assertFileEqualsBaseline(currdir+"excel.log", tutorial_dir+"excel.out")
def test_set(self):
- pyutilib.misc.run_file(tutorial_dir+"set.py", logfile=currdir+"set.log", execdir=tutorial_dir)
+ run_file(tutorial_dir+"set.py", logfile=currdir+"set.log", execdir=tutorial_dir)
self.assertFileEqualsBaseline(currdir+"set.log", tutorial_dir+"set.out")
def test_table(self):
- pyutilib.misc.run_file(tutorial_dir+"table.py", logfile=currdir+"table.log", execdir=tutorial_dir)
+ run_file(tutorial_dir+"table.py", logfile=currdir+"table.log", execdir=tutorial_dir)
self.assertFileEqualsBaseline(currdir+"table.log", tutorial_dir+"table.out")
def test_param(self):
- pyutilib.misc.run_file(tutorial_dir+"param.py", logfile=currdir+"param.log", execdir=tutorial_dir)
+ run_file(tutorial_dir+"param.py", logfile=currdir+"param.log", execdir=tutorial_dir)
self.assertFileEqualsBaseline(currdir+"param.log", tutorial_dir+"param.out")
if __name__ == "__main__":
diff --git a/pyomo/core/tests/transform/test_add_slacks.py b/pyomo/core/tests/transform/test_add_slacks.py
index ace1126704f..e8d7c80f580 100644
--- a/pyomo/core/tests/transform/test_add_slacks.py
+++ b/pyomo/core/tests/transform/test_add_slacks.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import os
from os.path import abspath, dirname
currdir = dirname(abspath(__file__))+os.sep
@@ -6,14 +16,17 @@
from pyomo.common.log import LoggingIntercept
import pyutilib.th as unittest
-import pyutilib.services
import random
-import pyomo.opt
-from pyomo.environ import *
+from pyomo.opt import check_available_solvers
+from pyomo.environ import (ConcreteModel, Set, Objective,
+ Constraint, Var, Block, Param,
+ NonNegativeReals, TransformationFactory, ComponentUID,
+ inequality)
+
import pyomo.core.expr.current as EXPR
-solvers = pyomo.opt.check_available_solvers('glpk')
+solvers = check_available_solvers('glpk')
class TestAddSlacks(unittest.TestCase):
diff --git a/pyomo/core/tests/transform/test_scaling.py b/pyomo/core/tests/transform/test_scaling.py
index 64023bdbff7..49c8691e7ce 100644
--- a/pyomo/core/tests/transform/test_scaling.py
+++ b/pyomo/core/tests/transform/test_scaling.py
@@ -2,30 +2,30 @@
#
# Pyomo: Python Optimization Modeling Objects
# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
-# Under the terms of Contract DE-NA0003525 with National Technology and
-# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
#
-
import pyutilib.th as unittest
-import pyomo.environ as pe
+import pyomo.environ as pyo
from pyomo.opt.base.solvers import UnknownSolver
+
class TestScaleModelTransformation(unittest.TestCase):
def test_linear_scaling(self):
- model = pe.ConcreteModel()
- model.x = pe.Var([1,2,3], bounds=(-10,10), initialize=5.0)
- model.z = pe.Var(bounds=(10,20))
- model.obj = pe.Objective(expr=model.z + model.x[1])
+ model = pyo.ConcreteModel()
+ model.x = pyo.Var([1, 2, 3], bounds=(-10, 10), initialize=5.0)
+ model.z = pyo.Var(bounds=(10, 20))
+ model.obj = pyo.Objective(expr=model.z + model.x[1])
# test scaling of duals as well
- model.dual = pe.Suffix(direction=pe.Suffix.IMPORT)
- model.rc = pe.Suffix(direction=pe.Suffix.IMPORT)
-
+ model.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT)
+ model.rc = pyo.Suffix(direction=pyo.Suffix.IMPORT)
+
def con_rule(m, i):
if i == 1:
return m.x[1] + 2*m.x[2] + 1*m.x[3] == 4.0
@@ -33,8 +33,8 @@ def con_rule(m, i):
return m.x[1] + 2*m.x[2] + 2*m.x[3] == 5.0
if i == 3:
return m.x[1] + 3.0*m.x[2] + 1*m.x[3] == 5.0
- model.con = pe.Constraint([1,2,3], rule=con_rule)
- model.zcon = pe.Constraint(expr=model.z >= model.x[2])
+ model.con = pyo.Constraint([1,2,3], rule=con_rule)
+ model.zcon = pyo.Constraint(expr=model.z >= model.x[2])
x_scale = 0.5
obj_scale = 2.0
@@ -43,9 +43,9 @@ def con_rule(m, i):
con_scale2 = 2.0
con_scale3 = -5.0
zcon_scale = -3.0
-
+
unscaled_model = model.clone()
- unscaled_model.scaling_factor = pe.Suffix(direction=pe.Suffix.EXPORT)
+ unscaled_model.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT)
unscaled_model.scaling_factor[unscaled_model.obj] = obj_scale
unscaled_model.scaling_factor[unscaled_model.x] = x_scale
unscaled_model.scaling_factor[unscaled_model.z] = z_scale
@@ -53,15 +53,15 @@ def con_rule(m, i):
unscaled_model.scaling_factor[unscaled_model.con[2]] = con_scale2
unscaled_model.scaling_factor[unscaled_model.con[3]] = con_scale3
unscaled_model.scaling_factor[unscaled_model.zcon] = zcon_scale
-
- scaled_model = pe.TransformationFactory('core.scale_model').create_using(unscaled_model)
+
+ scaled_model = pyo.TransformationFactory('core.scale_model').create_using(unscaled_model)
# print('*** unscaled ***')
# unscaled_model.pprint()
# print('*** scaled ***')
# scaled_model.pprint()
- glpk_solver = pe.SolverFactory('glpk')
+ glpk_solver = pyo.SolverFactory('glpk')
if isinstance(glpk_solver, UnknownSolver) or \
(not glpk_solver.available()):
raise unittest.SkipTest("glpk solver not available")
@@ -70,63 +70,64 @@ def con_rule(m, i):
glpk_solver.solve(scaled_model)
# check vars
- self.assertAlmostEqual(pe.value(unscaled_model.x[1]), pe.value(scaled_model.scaled_x[1])/x_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.x[2]), pe.value(scaled_model.scaled_x[2])/x_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.x[3]), pe.value(scaled_model.scaled_x[3])/x_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.z), pe.value(scaled_model.scaled_z)/z_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.x[1]), pyo.value(scaled_model.scaled_x[1])/x_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.x[2]), pyo.value(scaled_model.scaled_x[2])/x_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.x[3]), pyo.value(scaled_model.scaled_x[3])/x_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.z), pyo.value(scaled_model.scaled_z)/z_scale, 4)
# check var lb
- self.assertAlmostEqual(pe.value(unscaled_model.x[1].lb), pe.value(scaled_model.scaled_x[1].lb)/x_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.x[2].lb), pe.value(scaled_model.scaled_x[2].lb)/x_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.x[3].lb), pe.value(scaled_model.scaled_x[3].lb)/x_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.x[1].lb), pyo.value(scaled_model.scaled_x[1].lb)/x_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.x[2].lb), pyo.value(scaled_model.scaled_x[2].lb)/x_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.x[3].lb), pyo.value(scaled_model.scaled_x[3].lb)/x_scale, 4)
# note: z_scale is negative, therefore, the inequality directions swap
- self.assertAlmostEqual(pe.value(unscaled_model.z.lb), pe.value(scaled_model.scaled_z.ub)/z_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.z.lb), pyo.value(scaled_model.scaled_z.ub)/z_scale, 4)
# check var ub
- self.assertAlmostEqual(pe.value(unscaled_model.x[1].ub), pe.value(scaled_model.scaled_x[1].ub)/x_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.x[2].ub), pe.value(scaled_model.scaled_x[2].ub)/x_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.x[3].ub), pe.value(scaled_model.scaled_x[3].ub)/x_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.x[1].ub), pyo.value(scaled_model.scaled_x[1].ub)/x_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.x[2].ub), pyo.value(scaled_model.scaled_x[2].ub)/x_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.x[3].ub), pyo.value(scaled_model.scaled_x[3].ub)/x_scale, 4)
# note: z_scale is negative, therefore, the inequality directions swap
- self.assertAlmostEqual(pe.value(unscaled_model.z.ub), pe.value(scaled_model.scaled_z.lb)/z_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.z.ub), pyo.value(scaled_model.scaled_z.lb)/z_scale, 4)
# check var multipliers (rc)
- self.assertAlmostEqual(pe.value(unscaled_model.rc[unscaled_model.x[1]]), pe.value(scaled_model.rc[scaled_model.scaled_x[1]])*x_scale/obj_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.rc[unscaled_model.x[2]]), pe.value(scaled_model.rc[scaled_model.scaled_x[2]])*x_scale/obj_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.rc[unscaled_model.x[3]]), pe.value(scaled_model.rc[scaled_model.scaled_x[3]])*x_scale/obj_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.rc[unscaled_model.z]), pe.value(scaled_model.rc[scaled_model.scaled_z])*z_scale/obj_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.rc[unscaled_model.x[1]]), pyo.value(scaled_model.rc[scaled_model.scaled_x[1]])*x_scale/obj_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.rc[unscaled_model.x[2]]), pyo.value(scaled_model.rc[scaled_model.scaled_x[2]])*x_scale/obj_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.rc[unscaled_model.x[3]]), pyo.value(scaled_model.rc[scaled_model.scaled_x[3]])*x_scale/obj_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.rc[unscaled_model.z]), pyo.value(scaled_model.rc[scaled_model.scaled_z])*z_scale/obj_scale, 4)
# check constraint multipliers
- self.assertAlmostEqual(pe.value(unscaled_model.dual[unscaled_model.con[1]]),pe.value(scaled_model.dual[scaled_model.scaled_con[1]])*con_scale1/obj_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.dual[unscaled_model.con[2]]),pe.value(scaled_model.dual[scaled_model.scaled_con[2]])*con_scale2/obj_scale, 4)
- self.assertAlmostEqual(pe.value(unscaled_model.dual[unscaled_model.con[3]]),pe.value(scaled_model.dual[scaled_model.scaled_con[3]])*con_scale3/obj_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.dual[unscaled_model.con[1]]),pyo.value(scaled_model.dual[scaled_model.scaled_con[1]])*con_scale1/obj_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.dual[unscaled_model.con[2]]),pyo.value(scaled_model.dual[scaled_model.scaled_con[2]])*con_scale2/obj_scale, 4)
+ self.assertAlmostEqual(pyo.value(unscaled_model.dual[unscaled_model.con[3]]),pyo.value(scaled_model.dual[scaled_model.scaled_con[3]])*con_scale3/obj_scale, 4)
# put the solution from the scaled back into the original
- pe.TransformationFactory('core.scale_model').propagate_solution(scaled_model, model)
+ pyo.TransformationFactory('core.scale_model').propagate_solution(scaled_model, model)
# compare var values and rc with the unscaled soln
- for vm in model.component_objects(ctype=pe.Var, descend_into=True):
- cuid = pe.ComponentUID(vm)
+ for vm in model.component_objects(ctype=pyo.Var, descend_into=True):
+ cuid = pyo.ComponentUID(vm)
vum = cuid.find_component_on(unscaled_model)
self.assertEqual((vm in model.rc), (vum in unscaled_model.rc))
if vm in model.rc:
- self.assertAlmostEqual(pe.value(model.rc[vm]), pe.value(unscaled_model.rc[vum]), 4)
+ self.assertAlmostEqual(pyo.value(model.rc[vm]), pyo.value(unscaled_model.rc[vum]), 4)
for k in vm:
vmk = vm[k]
vumk = vum[k]
- self.assertAlmostEqual(pe.value(vmk), pe.value(vumk), 4)
+ self.assertAlmostEqual(pyo.value(vmk), pyo.value(vumk), 4)
self.assertEqual((vmk in model.rc), (vumk in unscaled_model.rc))
if vmk in model.rc:
- self.assertAlmostEqual(pe.value(model.rc[vmk]), pe.value(unscaled_model.rc[vumk]), 4)
+ self.assertAlmostEqual(pyo.value(model.rc[vmk]), pyo.value(unscaled_model.rc[vumk]), 4)
# compare constraint duals and value
- for model_con in model.component_objects(ctype=pe.Constraint, descend_into=True):
- cuid = pe.ComponentUID(model_con)
+ for model_con in model.component_objects(ctype=pyo.Constraint, descend_into=True):
+ cuid = pyo.ComponentUID(model_con)
unscaled_model_con = cuid.find_component_on(unscaled_model)
self.assertEqual((model_con in model.rc), (unscaled_model_con in unscaled_model.rc))
if model_con in model.dual:
- self.assertAlmostEqual(pe.value(model.dual[model_con]), pe.value(unscaled_model.dual[unscaled_model_con]), 4)
+ self.assertAlmostEqual(pyo.value(model.dual[model_con]), pyo.value(unscaled_model.dual[unscaled_model_con]), 4)
for k in model_con:
mk = model_con[k]
umk = unscaled_model_con[k]
self.assertEqual((mk in model.dual), (umk in unscaled_model.dual))
if mk in model.dual:
- self.assertAlmostEqual(pe.value(model.dual[mk]), pe.value(unscaled_model.dual[umk]), 4)
-
+ self.assertAlmostEqual(pyo.value(model.dual[mk]), pyo.value(unscaled_model.dual[umk]), 4)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/pyomo/core/tests/transform/test_transform.py b/pyomo/core/tests/transform/test_transform.py
index 15eb6ff97ec..5a9ff0a9f20 100644
--- a/pyomo/core/tests/transform/test_transform.py
+++ b/pyomo/core/tests/transform/test_transform.py
@@ -16,13 +16,21 @@
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
-import pyutilib.services
+from pyutilib.services import TempfileManager
-import pyomo.opt
-from pyomo.environ import *
+from pyomo.opt import check_available_solvers
+from pyomo.environ import (AbstractModel, Set, RangeSet, Objective,
+ Constraint, Var, Block, Integers, Boolean,
+ Binary, Reals, RealSet, NonNegativeIntegers,
+ NonNegativeReals, NegativeReals, NegativeIntegers,
+ PositiveReals, PositiveIntegers, NonPositiveIntegers,
+ NonPositiveReals, TransformationFactory, SolverFactory,
+ sum_product)
+from pyomo.core.plugins.transform.standard_form import StandardForm
+from pyomo.core.plugins.transform.nonnegative_transform import NonNegativeTransformation
-solvers = pyomo.opt.check_available_solvers('glpk')
+solvers = check_available_solvers('glpk')
class Test(unittest.TestCase):
@@ -33,7 +41,7 @@ def setUp(self):
def tearDown(self):
if os.path.exists("unknown.lp"):
os.unlink("unknown.lp")
- pyutilib.services.TempfileManager.clear_tempfiles()
+ TempfileManager.clear_tempfiles()
if os.path.exists(os.path.join(currdir,'result.yml')):
os.remove(os.path.join(currdir,'result.yml'))
self.model = None
diff --git a/pyomo/core/tests/unit/kernel/test_block.py b/pyomo/core/tests/unit/kernel/test_block.py
index ecefb7d1b16..f72f6549b52 100644
--- a/pyomo/core/tests/unit/kernel/test_block.py
+++ b/pyomo/core/tests/unit/kernel/test_block.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import tempfile
import os
import pickle
@@ -50,7 +60,6 @@
from pyomo.core.kernel.sos import sos
from pyomo.opt.results import Solution
-import six
from six import StringIO
def _path_to_object_exists(obj, descendent):
diff --git a/pyomo/core/tests/unit/kernel/test_conic.py b/pyomo/core/tests/unit/kernel/test_conic.py
index a05d534ac35..fb3bd045d12 100644
--- a/pyomo/core/tests/unit/kernel/test_conic.py
+++ b/pyomo/core/tests/unit/kernel/test_conic.py
@@ -1,8 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
import math
import pyutilib.th as unittest
-import pyomo.kernel
+from pyomo.kernel import pprint, IntegerSet
from pyomo.core.kernel.base import ICategorizedObject
from pyomo.core.kernel.constraint import (IConstraint,
linear_constraint,
@@ -23,7 +33,6 @@
primal_power,
dual_exponential,
dual_power)
-from pyomo.kernel import IntegerSet
class _conic_tester_base(object):
@@ -33,21 +42,20 @@ def setUp(self):
assert self._object_factory is not None
def test_pprint(self):
- import pyomo.kernel
# Not really testing what the output is, just that
# an error does not occur. The pprint functionality
# is still in the early stages.
c = self._object_factory()
- pyomo.kernel.pprint(c)
+ pprint(c)
b = block()
b.c = c
- pyomo.kernel.pprint(c)
- pyomo.kernel.pprint(b)
+ pprint(c)
+ pprint(b)
m = block()
m.b = b
- pyomo.kernel.pprint(c)
- pyomo.kernel.pprint(b)
- pyomo.kernel.pprint(m)
+ pprint(c)
+ pprint(b)
+ pprint(m)
def test_type(self):
c = self._object_factory()
diff --git a/pyomo/core/tests/unit/kernel/test_constraint.py b/pyomo/core/tests/unit/kernel/test_constraint.py
index 27cc1bd2dcf..ed10d014430 100644
--- a/pyomo/core/tests/unit/kernel/test_constraint.py
+++ b/pyomo/core/tests/unit/kernel/test_constraint.py
@@ -1,8 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
import pyutilib.th as unittest
from pyomo.core.expr import logical_expr
-import pyomo.kernel
+from pyomo.kernel import pprint
from pyomo.core.tests.unit.kernel.test_dict_container import \
_TestActiveDictContainerBase
from pyomo.core.tests.unit.kernel.test_tuple_container import \
@@ -21,28 +31,25 @@
from pyomo.core.kernel.expression import (expression,
data_expression)
from pyomo.core.kernel.block import block
-from pyomo.core.kernel.set_types import (RealSet,
- IntegerSet)
class Test_constraint(unittest.TestCase):
def test_pprint(self):
- import pyomo.kernel
# Not really testing what the output is, just that
# an error does not occur. The pprint functionality
# is still in the early stages.
v = variable()
c = constraint((1, v**2, 2))
- pyomo.kernel.pprint(c)
+ pprint(c)
b = block()
b.c = c
- pyomo.kernel.pprint(c)
- pyomo.kernel.pprint(b)
+ pprint(c)
+ pprint(b)
m = block()
m.b = b
- pyomo.kernel.pprint(c)
- pyomo.kernel.pprint(b)
- pyomo.kernel.pprint(m)
+ pprint(c)
+ pprint(b)
+ pprint(m)
def test_ctype(self):
c = constraint()
@@ -1588,16 +1595,16 @@ def test_pprint(self):
# is still in the early stages.
v = variable()
c = linear_constraint(lb=1, terms=[(v,1)], ub=1)
- pyomo.kernel.pprint(c)
+ pprint(c)
b = block()
b.c = c
- pyomo.kernel.pprint(c)
- pyomo.kernel.pprint(b)
+ pprint(c)
+ pprint(b)
m = block()
m.b = b
- pyomo.kernel.pprint(c)
- pyomo.kernel.pprint(b)
- pyomo.kernel.pprint(m)
+ pprint(c)
+ pprint(b)
+ pprint(m)
def test_ctype(self):
c = linear_constraint([],[])
diff --git a/pyomo/core/tests/unit/kernel/test_dict_container.py b/pyomo/core/tests/unit/kernel/test_dict_container.py
index a74b387fe48..3ac7fdff12c 100644
--- a/pyomo/core/tests/unit/kernel/test_dict_container.py
+++ b/pyomo/core/tests/unit/kernel/test_dict_container.py
@@ -19,8 +19,7 @@
from pyomo.core.kernel.homogeneous_container import \
IHomogeneousContainer
from pyomo.core.kernel.dict_container import DictContainer
-from pyomo.core.kernel.block import (IBlock,
- block,
+from pyomo.core.kernel.block import (block,
block_dict)
import six
@@ -46,9 +45,11 @@
# and weakref (bas
_pickle_test_protocol = pickle.HIGHEST_PROTOCOL
+
class _bad_ctype(object):
ctype = "_this_is_definitely_not_the_ctype_being_tested"
+
class _TestDictContainerBase(object):
# set by derived class
@@ -102,7 +103,7 @@ def test_init1(self):
cdict = self._container_type()
def test_init2(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
self._container_type((i, self._ctype_factory())
for i in index)
self._container_type(((i, self._ctype_factory())
@@ -155,7 +156,7 @@ def test_len2(self):
def test_setitem(self):
cdict = self._container_type()
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
for i in index:
self.assertTrue(i not in cdict)
for cnt, i in enumerate(index, 1):
@@ -168,13 +169,13 @@ def test_setitem(self):
# examined more carefully before supporting it.
# For now just test that implicit assignment raises an exception
def test_wrong_type_init(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
with self.assertRaises(TypeError):
c = self._container_type(
(i, _bad_ctype()) for i in index)
def test_wrong_type_update(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
c = self._container_type()
with self.assertRaises(TypeError):
c.update((i, _bad_ctype()) for i in index)
@@ -221,7 +222,7 @@ def test_has_parent_setitem(self):
# make sure an existing Data object IS replaced
# by a call to setitem and not simply updated.
def test_setitem_exists_overwrite(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
c = self._container_type((i, self._ctype_factory())
for i in index)
self.assertEqual(len(c), len(index))
@@ -235,7 +236,7 @@ def test_setitem_exists_overwrite(self):
self.assertEqual(cdata.parent, None)
def test_delitem(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
c = self._container_type((i, self._ctype_factory())
for i in index)
self.assertEqual(len(c), len(index))
@@ -250,7 +251,7 @@ def test_delitem(self):
self.assertEqual(cdata.parent, None)
def test_iter(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
c = self._container_type((i, self._ctype_factory())
for i in index)
self.assertEqual(len(c), len(index))
@@ -260,7 +261,7 @@ def test_iter(self):
self.assertTrue(idx in index)
def test_pickle(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
cdict = self._container_type((i, self._ctype_factory())
for i in index)
cdict[0] = self._container_type()
@@ -279,7 +280,7 @@ def test_pickle(self):
self.assertTrue(cdict[i].parent is cdict)
def test_keys(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
raw_constraint_dict = {i:self._ctype_factory() for i in index}
c = self._container_type(raw_constraint_dict)
self.assertEqual(sorted(list(raw_constraint_dict.keys()),
@@ -287,7 +288,7 @@ def test_keys(self):
sorted(list(c.keys()), key=str))
def test_values(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
raw_constraint_dict = {i:self._ctype_factory() for i in index}
c = self._container_type(raw_constraint_dict)
self.assertEqual(
@@ -299,7 +300,7 @@ def test_values(self):
key=str))
def test_items(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
raw_constraint_dict = {i:self._ctype_factory() for i in index}
c = self._container_type(raw_constraint_dict)
self.assertEqual(
@@ -311,7 +312,7 @@ def test_items(self):
key=str))
def test_update(self):
- index = ['a', 1, None, (1,), (1,2)]
+ index = ['a', 1, None, (1,), (1, 2)]
raw_constraint_dict = {i:self._ctype_factory() for i in index}
c = self._container_type()
c.update(raw_constraint_dict)
@@ -596,6 +597,7 @@ def descend(x):
[id(c) for c in descend.seen])
return cdict, traversal
+
class _TestActiveDictContainerBase(_TestDictContainerBase):
def test_active_type(self):
@@ -613,7 +615,7 @@ def test_active(self):
children[1] = self._ctype_factory()
children[None] = self._ctype_factory()
children[(1,)] = self._ctype_factory()
- children[(1,2)] = self._ctype_factory()
+ children[(1, 2)] = self._ctype_factory()
children['(1,2)'] = self._ctype_factory()
cdict = self._container_type()
@@ -956,5 +958,6 @@ def descend(x):
self.assertEqual(len(descend.seen), 1)
self.assertIs(descend.seen[0], cdict)
+
if __name__ == "__main__":
unittest.main()
diff --git a/pyomo/core/tests/unit/kernel/test_expression.py b/pyomo/core/tests/unit/kernel/test_expression.py
index c5c9e773248..4ab8c904fa9 100644
--- a/pyomo/core/tests/unit/kernel/test_expression.py
+++ b/pyomo/core/tests/unit/kernel/test_expression.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
import pyutilib.th as unittest
@@ -26,11 +36,8 @@
from pyomo.core.kernel.parameter import parameter
from pyomo.core.kernel.objective import objective
from pyomo.core.kernel.block import block
-from pyomo.core.kernel.set_types import (RealSet,
- IntegerSet)
import six
-from six import StringIO
try:
import numpy
diff --git a/pyomo/core/tests/unit/kernel/test_kernel.py b/pyomo/core/tests/unit/kernel/test_kernel.py
index a10a831bc60..817e595fd37 100644
--- a/pyomo/core/tests/unit/kernel/test_kernel.py
+++ b/pyomo/core/tests/unit/kernel/test_kernel.py
@@ -1,5 +1,12 @@
-import pickle
-import itertools
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
import pyutilib.th as unittest
import pyomo.kernel as pmo
@@ -7,9 +14,6 @@
from pyomo.core.kernel.variable import IVariable
from pyomo.core.kernel.constraint import IConstraint
-import six
-from six import StringIO
-
class IJunk(IBlock):
__slots__ = ()
diff --git a/pyomo/core/tests/unit/kernel/test_list_container.py b/pyomo/core/tests/unit/kernel/test_list_container.py
index 07970435c08..1613886a96c 100644
--- a/pyomo/core/tests/unit/kernel/test_list_container.py
+++ b/pyomo/core/tests/unit/kernel/test_list_container.py
@@ -19,8 +19,7 @@
from pyomo.core.kernel.homogeneous_container import \
IHomogeneousContainer
from pyomo.core.kernel.list_container import ListContainer
-from pyomo.core.kernel.block import (IBlock,
- block,
+from pyomo.core.kernel.block import (block,
block_list)
import six
diff --git a/pyomo/core/tests/unit/kernel/test_matrix_constraint.py b/pyomo/core/tests/unit/kernel/test_matrix_constraint.py
index d03d45b63dd..b675c2c8f58 100644
--- a/pyomo/core/tests/unit/kernel/test_matrix_constraint.py
+++ b/pyomo/core/tests/unit/kernel/test_matrix_constraint.py
@@ -1,13 +1,17 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
import pyutilib.th as unittest
import pyomo.kernel as pmo
-from pyomo.core.tests.unit.kernel.test_dict_container import \
- _TestActiveDictContainerBase
-from pyomo.core.tests.unit.kernel.test_tuple_container import \
- _TestActiveTupleContainerBase
-from pyomo.core.tests.unit.kernel.test_list_container import \
- _TestActiveListContainerBase
from pyomo.core.kernel.base import \
(ICategorizedObject,
ICategorizedObjectContainer)
@@ -16,7 +20,6 @@
from pyomo.core.kernel.tuple_container import TupleContainer
from pyomo.core.kernel.constraint import (IConstraint,
constraint,
- linear_constraint,
constraint_dict,
constraint_tuple,
constraint_list)
@@ -26,12 +29,9 @@
from pyomo.core.kernel.variable import (variable,
variable_list)
from pyomo.core.kernel.parameter import parameter
-from pyomo.core.kernel.expression import (expression,
- data_expression)
+from pyomo.core.kernel.expression import expression
from pyomo.core.kernel.block import (block,
block_list)
-from pyomo.core.kernel.set_types import (RealSet,
- IntegerSet)
try:
import numpy
@@ -47,6 +47,7 @@
has_scipy = False
_scipy_ver = (0,0)
+
def _create_variable_list(size, **kwds):
assert size > 0
vlist = variable_list()
@@ -54,12 +55,12 @@ def _create_variable_list(size, **kwds):
vlist.append(variable(**kwds))
return vlist
+
@unittest.skipUnless(has_numpy and has_scipy,
"NumPy or SciPy is not available")
class Test_matrix_constraint(unittest.TestCase):
def test_pprint(self):
- import pyomo.kernel
# Not really testing what the output is, just that
# an error does not occur. The pprint functionality
# is still in the early stages.
diff --git a/pyomo/core/tests/unit/kernel/test_objective.py b/pyomo/core/tests/unit/kernel/test_objective.py
index 858b3b7f0f1..75b3db2177e 100644
--- a/pyomo/core/tests/unit/kernel/test_objective.py
+++ b/pyomo/core/tests/unit/kernel/test_objective.py
@@ -1,8 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
import pyutilib.th as unittest
from pyomo.core.expr.numvalue import NumericValue
-import pyomo.kernel
+from pyomo.kernel import pprint
from pyomo.core.tests.unit.kernel.test_dict_container import \
_TestActiveDictContainerBase
from pyomo.core.tests.unit.kernel.test_tuple_container import \
@@ -19,28 +29,25 @@
maximize)
from pyomo.core.kernel.variable import variable
from pyomo.core.kernel.block import block
-from pyomo.core.kernel.set_types import (RealSet,
- IntegerSet)
class Test_objective(unittest.TestCase):
def test_pprint(self):
- import pyomo.kernel
# Not really testing what the output is, just that
# an error does not occur. The pprint functionality
# is still in the early stages.
v = variable()
o = objective(expr=v**2)
- pyomo.kernel.pprint(o)
+ pprint(o)
b = block()
b.o = o
- pyomo.kernel.pprint(o)
- pyomo.kernel.pprint(b)
+ pprint(o)
+ pprint(b)
m = block()
m.b = b
- pyomo.kernel.pprint(o)
- pyomo.kernel.pprint(b)
- pyomo.kernel.pprint(m)
+ pprint(o)
+ pprint(b)
+ pprint(m)
def test_ctype(self):
o = objective()
diff --git a/pyomo/core/tests/unit/kernel/test_parameter.py b/pyomo/core/tests/unit/kernel/test_parameter.py
index c8015479df8..90058439247 100644
--- a/pyomo/core/tests/unit/kernel/test_parameter.py
+++ b/pyomo/core/tests/unit/kernel/test_parameter.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
import pyutilib.th as unittest
@@ -7,7 +17,7 @@
is_fixed,
is_constant,
is_potentially_variable)
-import pyomo.kernel
+from pyomo.kernel import pprint
from pyomo.core.tests.unit.kernel.test_dict_container import \
_TestActiveDictContainerBase
from pyomo.core.tests.unit.kernel.test_tuple_container import \
@@ -23,27 +33,24 @@
parameter_list)
from pyomo.core.kernel.variable import variable
from pyomo.core.kernel.block import block
-from pyomo.core.kernel.set_types import (RealSet,
- IntegerSet)
class Test_parameter(unittest.TestCase):
def test_pprint(self):
- import pyomo.kernel
# Not really testing what the output is, just that
# an error does not occur. The pprint functionality
# is still in the early stages.
p = parameter()
- pyomo.kernel.pprint(p)
+ pprint(p)
b = block()
b.p = p
- pyomo.kernel.pprint(p)
- pyomo.kernel.pprint(b)
+ pprint(p)
+ pprint(b)
m = block()
m.b = b
- pyomo.kernel.pprint(p)
- pyomo.kernel.pprint(b)
- pyomo.kernel.pprint(m)
+ pprint(p)
+ pprint(b)
+ pprint(m)
def test_ctype(self):
p = parameter()
@@ -134,21 +141,20 @@ def test_is_parameter_type(self):
class Test_functional_value(unittest.TestCase):
def test_pprint(self):
- import pyomo.kernel
# Not really testing what the output is, just that
# an error does not occur. The pprint functionality
# is still in the early stages.
f = functional_value()
- pyomo.kernel.pprint(f)
+ pprint(f)
b = block()
b.f = f
- pyomo.kernel.pprint(f)
- pyomo.kernel.pprint(b)
+ pprint(f)
+ pprint(b)
m = block()
m.b = b
- pyomo.kernel.pprint(f)
- pyomo.kernel.pprint(b)
- pyomo.kernel.pprint(m)
+ pprint(f)
+ pprint(b)
+ pprint(m)
def test_ctype(self):
f = functional_value()
diff --git a/pyomo/core/tests/unit/kernel/test_piecewise.py b/pyomo/core/tests/unit/kernel/test_piecewise.py
index 2b197200b67..da2aa26cbc0 100644
--- a/pyomo/core/tests/unit/kernel/test_piecewise.py
+++ b/pyomo/core/tests/unit/kernel/test_piecewise.py
@@ -1,5 +1,14 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
-import abc
import pyutilib.th as unittest
import pyomo.kernel as pmo
@@ -29,7 +38,6 @@
import pyomo.core.kernel.piecewise_library.transforms_nd as \
transforms_nd
import pyomo.core.kernel.piecewise_library.util as util
-from pyomo.core.base.block import Block
# for the multi-dimensional piecewise tests
_test_v = None
diff --git a/pyomo/core/tests/unit/kernel/test_sos.py b/pyomo/core/tests/unit/kernel/test_sos.py
index 33884a1b9c7..8bb5e1f1063 100644
--- a/pyomo/core/tests/unit/kernel/test_sos.py
+++ b/pyomo/core/tests/unit/kernel/test_sos.py
@@ -1,7 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
import pyutilib.th as unittest
-import pyomo.kernel
from pyomo.core.tests.unit.kernel.test_dict_container import \
_TestActiveDictContainerBase
from pyomo.core.tests.unit.kernel.test_tuple_container import \
diff --git a/pyomo/core/tests/unit/kernel/test_suffix.py b/pyomo/core/tests/unit/kernel/test_suffix.py
index 2a17759e3f2..b715d275d3d 100644
--- a/pyomo/core/tests/unit/kernel/test_suffix.py
+++ b/pyomo/core/tests/unit/kernel/test_suffix.py
@@ -1,8 +1,17 @@
-import sys
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
import pyutilib.th as unittest
-import pyomo.kernel
+from pyomo.kernel import pprint
from pyomo.core.tests.unit.kernel.test_dict_container import \
_TestActiveDictContainerBase
from pyomo.core.kernel.base import ICategorizedObject
@@ -13,17 +22,13 @@
import_suffix_generator,
local_suffix_generator,
suffix_generator)
-from pyomo.core.kernel.variable import (variable,
- variable_dict)
+from pyomo.core.kernel.variable import variable
from pyomo.core.kernel.constraint import (constraint,
constraint_list)
from pyomo.core.kernel.block import (block,
block_dict)
-from pyomo.core.kernel.set_types import (RealSet,
- IntegerSet)
import six
-from six import StringIO
if six.PY3:
from collections.abc import Mapping as collections_Mapping
@@ -36,7 +41,6 @@
class Test_suffix(unittest.TestCase):
def test_pprint(self):
- import pyomo.kernel
# Not really testing what the output is, just that
# an error does not occur. The pprint functionality
# is still in the early stages.
@@ -45,18 +49,18 @@ def test_pprint(self):
s = suffix()
s[v] = 1
s[clist] = None
- pyomo.kernel.pprint(s)
+ pprint(s)
b = block()
b.s = s
- pyomo.kernel.pprint(s)
- pyomo.kernel.pprint(b)
+ pprint(s)
+ pprint(b)
m = block()
m.b = b
- pyomo.kernel.pprint(s)
- pyomo.kernel.pprint(b)
- pyomo.kernel.pprint(m)
+ pprint(s)
+ pprint(b)
+ pprint(m)
- pyomo.kernel.pprint({'a': 1, 'b': 2})
+ pprint({'a': 1, 'b': 2})
def test_str(self):
s = suffix()
diff --git a/pyomo/core/tests/unit/kernel/test_tuple_container.py b/pyomo/core/tests/unit/kernel/test_tuple_container.py
index e94bc3cebbe..156e83a22cc 100644
--- a/pyomo/core/tests/unit/kernel/test_tuple_container.py
+++ b/pyomo/core/tests/unit/kernel/test_tuple_container.py
@@ -18,8 +18,7 @@
from pyomo.core.kernel.homogeneous_container import \
IHomogeneousContainer
from pyomo.core.kernel.tuple_container import TupleContainer
-from pyomo.core.kernel.block import (IBlock,
- block,
+from pyomo.core.kernel.block import (block,
block_list)
import six
diff --git a/pyomo/core/tests/unit/kernel/test_variable.py b/pyomo/core/tests/unit/kernel/test_variable.py
index 46a124da364..5f484070d72 100644
--- a/pyomo/core/tests/unit/kernel/test_variable.py
+++ b/pyomo/core/tests/unit/kernel/test_variable.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pickle
import pyutilib.th as unittest
@@ -5,7 +15,6 @@
is_fixed,
is_constant,
is_potentially_variable)
-import pyomo.kernel
from pyomo.core.tests.unit.kernel.test_dict_container import \
_TestActiveDictContainerBase
from pyomo.core.tests.unit.kernel.test_tuple_container import \
@@ -29,15 +38,11 @@
NonNegativeReals,
NegativeReals,
Reals,
- Integers,
NonNegativeIntegers,
NegativeIntegers,
RealInterval,
IntegerInterval)
-import six
-from six import StringIO
-
class Test_variable(unittest.TestCase):
def test_pprint(self):
diff --git a/pyomo/core/tests/unit/test_action.py b/pyomo/core/tests/unit/test_action.py
index ef2cc3df09d..9723de5e687 100644
--- a/pyomo/core/tests/unit/test_action.py
+++ b/pyomo/core/tests/unit/test_action.py
@@ -20,7 +20,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Param, Set, BuildAction, value
def action1_fn(model):
diff --git a/pyomo/core/tests/unit/test_block.py b/pyomo/core/tests/unit/test_block.py
index a5223e59d82..76c4a49dd11 100644
--- a/pyomo/core/tests/unit/test_block.py
+++ b/pyomo/core/tests/unit/test_block.py
@@ -16,7 +16,7 @@
import six
import types
-from six import StringIO
+from six import StringIO, iterkeys
from copy import deepcopy
from os.path import abspath, dirname, join
@@ -24,13 +24,13 @@
currdir = dirname( abspath(__file__) )
import pyutilib.th as unittest
-import pyutilib.services
+from pyutilib.services import TempfileManager
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, ConcreteModel, Var, Set, Param, Block, Suffix, Constraint, Component, Objective, Expression, SOSConstraint, SortComponents, NonNegativeIntegers, TraversalStrategy, RangeSet, SolverFactory, value, sum_product
from pyomo.common.log import LoggingIntercept
from pyomo.core.base.block import SimpleBlock, SubclassOf, _BlockData, declare_custom_block
from pyomo.core.expr import current as EXPR
-from pyomo.opt import *
+from pyomo.opt import check_available_solvers
from pyomo.gdp import Disjunct
@@ -535,7 +535,7 @@ def tearDown(self):
self.block = None
if os.path.exists("unknown.lp"):
os.unlink("unknown.lp")
- pyutilib.services.TempfileManager.clear_tempfiles()
+ TempfileManager.clear_tempfiles()
def test_collect_ctypes(self):
b = Block(concrete=True)
diff --git a/pyomo/core/tests/unit/test_block_model.py b/pyomo/core/tests/unit/test_block_model.py
index efe8fbf23e3..5288e2a9fb7 100644
--- a/pyomo/core/tests/unit/test_block_model.py
+++ b/pyomo/core/tests/unit/test_block_model.py
@@ -20,7 +20,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Param, Block, Set, Var, RangeSet, Constraint, Connector, value
class Test(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_bounds.py b/pyomo/core/tests/unit/test_bounds.py
index ec0b97dff19..991e295a028 100644
--- a/pyomo/core/tests/unit/test_bounds.py
+++ b/pyomo/core/tests/unit/test_bounds.py
@@ -17,7 +17,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Param, Var, Constraint
class Test(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_check.py b/pyomo/core/tests/unit/test_check.py
index a67d77930c9..4b40103ab45 100644
--- a/pyomo/core/tests/unit/test_check.py
+++ b/pyomo/core/tests/unit/test_check.py
@@ -20,7 +20,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, BuildCheck, Param, Set, value
class PyomoModel(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_component.py b/pyomo/core/tests/unit/test_component.py
index f5639caf091..28c061cf029 100644
--- a/pyomo/core/tests/unit/test_component.py
+++ b/pyomo/core/tests/unit/test_component.py
@@ -16,7 +16,7 @@
from pyomo.common import DeveloperError
import pyomo.core.base._pyomo
from pyomo.core.base.block import generate_cuid_names
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Component, Block, Var, Set, Param, ComponentUID
class TestComponent(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_con.py b/pyomo/core/tests/unit/test_con.py
index 139b8d264e4..f7e919a13de 100644
--- a/pyomo/core/tests/unit/test_con.py
+++ b/pyomo/core/tests/unit/test_con.py
@@ -14,7 +14,6 @@
# TestArrayCon Class for testing array of constraint
#
-import logging
import sys
import os
from os.path import abspath, dirname
@@ -28,8 +27,6 @@
from pyomo.core.expr import logical_expr
from pyomo.core.base.constraint import _GeneralConstraintData
-from six import StringIO
-
class TestConstraintCreation(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_concrete.py b/pyomo/core/tests/unit/test_concrete.py
index 9b69ce8a44e..30a9baa570f 100644
--- a/pyomo/core/tests/unit/test_concrete.py
+++ b/pyomo/core/tests/unit/test_concrete.py
@@ -17,10 +17,10 @@
import pyutilib.th as unittest
-import pyomo.opt
-from pyomo.environ import *
+from pyomo.opt import check_available_solvers
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint, SolverFactory
-solvers = pyomo.opt.check_available_solvers('glpk')
+solvers = check_available_solvers('glpk')
@unittest.skipIf(not 'glpk' in solvers, "glpk solver is not available")
class Test(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_connector.py b/pyomo/core/tests/unit/test_connector.py
index 1283dddac2d..9e5be8ed21e 100644
--- a/pyomo/core/tests/unit/test_connector.py
+++ b/pyomo/core/tests/unit/test_connector.py
@@ -21,7 +21,7 @@
import pyutilib.th as unittest
from six import StringIO
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, AbstractModel, Connector, Var, NonNegativeReals, Set, Constraint, TransformationFactory, Binary, Reals, VarList
class TestConnector(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_deprecation.py b/pyomo/core/tests/unit/test_deprecation.py
index b461abdf784..3da118032a7 100644
--- a/pyomo/core/tests/unit/test_deprecation.py
+++ b/pyomo/core/tests/unit/test_deprecation.py
@@ -8,12 +8,11 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import os
import pyutilib.th as unittest
import sys
from importlib import import_module
-from six import StringIO, PY3
+from six import StringIO
from pyomo.common.log import LoggingIntercept
diff --git a/pyomo/core/tests/unit/test_derivs.py b/pyomo/core/tests/unit/test_derivs.py
index 812e50555eb..d3f3721c677 100644
--- a/pyomo/core/tests/unit/test_derivs.py
+++ b/pyomo/core/tests/unit/test_derivs.py
@@ -1,7 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as pe
+import pyomo.environ as pyo
from pyomo.core.expr.calculus.diff_with_pyomo import reverse_ad, reverse_sd
from pyomo.common.getGSL import find_GSL
+from pyomo.core.expr.numeric_expr import LinearExpression
tol = 6
@@ -10,176 +21,176 @@
def approx_deriv(expr, wrt, delta=0.001):
numerator = 0
wrt.value += 2*delta
- numerator -= pe.value(expr)
+ numerator -= pyo.value(expr)
wrt.value -= delta
- numerator += 8*pe.value(expr)
+ numerator += 8*pyo.value(expr)
wrt.value -= 2*delta
- numerator -= 8*pe.value(expr)
+ numerator -= 8*pyo.value(expr)
wrt.value -= delta
- numerator += pe.value(expr)
+ numerator += pyo.value(expr)
wrt.value += 2*delta
return numerator / (12*delta)
class TestDerivs(unittest.TestCase):
def test_prod(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- m.y = pe.Var(initialize=3.0)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ m.y = pyo.Var(initialize=3.0)
e = m.x * m.y
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
- self.assertAlmostEqual(derivs[m.y], pe.value(symbolic[m.y]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.y], pyo.value(symbolic[m.y]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
def test_sum(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- m.y = pe.Var(initialize=3.0)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ m.y = pyo.Var(initialize=3.0)
e = 2.0*m.x + 3.0*m.y - m.x*m.y
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
- self.assertAlmostEqual(derivs[m.y], pe.value(symbolic[m.y]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.y], pyo.value(symbolic[m.y]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
def test_div(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- m.y = pe.Var(initialize=3.0)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ m.y = pyo.Var(initialize=3.0)
e = m.x / m.y
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
- self.assertAlmostEqual(derivs[m.y], pe.value(symbolic[m.y]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.y], pyo.value(symbolic[m.y]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
def test_pow(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- m.y = pe.Var(initialize=3.0)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ m.y = pyo.Var(initialize=3.0)
e = m.x ** m.y
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
- self.assertAlmostEqual(derivs[m.y], pe.value(symbolic[m.y]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.y], pyo.value(symbolic[m.y]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
def test_sqrt(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- m.y = pe.Var(initialize=3.0)
- e = pe.sqrt(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ m.y = pyo.Var(initialize=3.0)
+ e = pyo.sqrt(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_exp(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- e = pe.exp(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ e = pyo.exp(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_log(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- e = pe.log(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ e = pyo.log(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_log10(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- e = pe.log10(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ e = pyo.log10(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_sin(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- e = pe.sin(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ e = pyo.sin(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_cos(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- e = pe.cos(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ e = pyo.cos(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_tan(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- e = pe.tan(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ e = pyo.tan(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_asin(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=0.5)
- e = pe.asin(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=0.5)
+ e = pyo.asin(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_acos(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=0.5)
- e = pe.acos(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=0.5)
+ e = pyo.acos(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_atan(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2.0)
- e = pe.atan(m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ e = pyo.atan(m.x)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
def test_nested(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=2)
- m.y = pe.Var(initialize=3)
- m.p = pe.Param(initialize=0.5, mutable=True)
- e = pe.exp(m.x**m.p + 3.2*m.y - 12)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2)
+ m.y = pyo.Var(initialize=3)
+ m.p = pyo.Param(initialize=0.5, mutable=True)
+ e = pyo.exp(m.x**m.p + 3.2*m.y - 12)
derivs = reverse_ad(e)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol+3)
- self.assertAlmostEqual(derivs[m.y], pe.value(symbolic[m.y]), tol+3)
- self.assertAlmostEqual(derivs[m.p], pe.value(symbolic[m.p]), tol+3)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol+3)
+ self.assertAlmostEqual(derivs[m.y], pyo.value(symbolic[m.y]), tol+3)
+ self.assertAlmostEqual(derivs[m.p], pyo.value(symbolic[m.p]), tol+3)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
self.assertAlmostEqual(derivs[m.p], approx_deriv(e, m.p), tol)
def test_expressiondata(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=3)
- m.e = pe.Expression(expr=m.x * 2)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=3)
+ m.e = pyo.Expression(expr=m.x * 2)
@m.Expression([1, 2])
def e2(m, i):
@@ -187,36 +198,58 @@ def e2(m, i):
return m.x + 4
else:
return m.x ** 2
- m.o = pe.Objective(expr=m.e + 1 + m.e2[1] + m.e2[2])
+ m.o = pyo.Objective(expr=m.e + 1 + m.e2[1] + m.e2[2])
derivs = reverse_ad(m.o.expr)
symbolic = reverse_sd(m.o.expr)
- self.assertAlmostEqual(derivs[m.x], pe.value(symbolic[m.x]), tol)
+ self.assertAlmostEqual(derivs[m.x], pyo.value(symbolic[m.x]), tol)
def test_multiple_named_expressions(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
m.x.value = 1
m.y.value = 1
- m.E = pe.Expression(expr=m.x*m.y)
+ m.E = pyo.Expression(expr=m.x*m.y)
e = m.E - m.E
derivs = reverse_ad(e)
self.assertAlmostEqual(derivs[m.x], 0)
self.assertAlmostEqual(derivs[m.y], 0)
symbolic = reverse_sd(e)
- self.assertAlmostEqual(pe.value(symbolic[m.x]), 0)
- self.assertAlmostEqual(pe.value(symbolic[m.y]), 0)
+ self.assertAlmostEqual(pyo.value(symbolic[m.x]), 0)
+ self.assertAlmostEqual(pyo.value(symbolic[m.y]), 0)
def test_external(self):
DLL = find_GSL()
if not DLL:
self.skipTest('Could not find the amplgsl.dll library')
- m = pe.ConcreteModel()
- m.hypot = pe.ExternalFunction(library=DLL, function='gsl_hypot')
- m.x = pe.Var(initialize=0.5)
- m.y = pe.Var(initialize=1.5)
+ m = pyo.ConcreteModel()
+ m.hypot = pyo.ExternalFunction(library=DLL, function='gsl_hypot')
+ m.x = pyo.Var(initialize=0.5)
+ m.y = pyo.Var(initialize=1.5)
e = 2 * m.hypot(m.x, m.x*m.y)
derivs = reverse_ad(e)
self.assertAlmostEqual(derivs[m.x], approx_deriv(e, m.x), tol)
self.assertAlmostEqual(derivs[m.y], approx_deriv(e, m.y), tol)
+
+ def test_linear_expression(self):
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=2.0)
+ m.y = pyo.Var(initialize=3.0)
+ m.p = pyo.Param(initialize=2.5, mutable=True)
+ e = LinearExpression(constant=m.p, linear_vars=[m.x, m.y], linear_coefs=[1.8, m.p])
+ e = pyo.log(e)
+ derivs = reverse_ad(e)
+ symbolic = reverse_sd(e)
+ for v in [m.x, m.y, m.p]:
+ self.assertAlmostEqual(derivs[v], pyo.value(symbolic[v]), tol)
+ self.assertAlmostEqual(derivs[v], approx_deriv(e, v), tol)
+
+ def test_NPV(self):
+ m = pyo.ConcreteModel()
+ m.p = pyo.Param(initialize=2.0, mutable=True)
+ e = pyo.log(m.p)
+ derivs = reverse_ad(e)
+ symbolic = reverse_sd(e)
+ self.assertAlmostEqual(derivs[m.p], pyo.value(symbolic[m.p]), tol)
+ self.assertAlmostEqual(derivs[m.p], approx_deriv(e, m.p), tol)
diff --git a/pyomo/core/tests/unit/test_expr_misc.py b/pyomo/core/tests/unit/test_expr_misc.py
index 4a7a2c9544f..3866169b037 100644
--- a/pyomo/core/tests/unit/test_expr_misc.py
+++ b/pyomo/core/tests/unit/test_expr_misc.py
@@ -15,10 +15,9 @@
from os.path import abspath, dirname
currdir = dirname(abspath(__file__))+os.sep
-import pyomo.core.expr.current as EXPR
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, ConcreteModel, ConstraintList, Set, Param, Var, Constraint, Objective, sum_product, quicksum, sequence, prod
def obj_rule(model):
return sum(model.x[a] + model.y[a] for a in model.A)
diff --git a/pyomo/core/tests/unit/test_expression.py b/pyomo/core/tests/unit/test_expression.py
index 920a6b532f8..218a0dfd495 100644
--- a/pyomo/core/tests/unit/test_expression.py
+++ b/pyomo/core/tests/unit/test_expression.py
@@ -17,11 +17,9 @@
import pyutilib.th as unittest
from pyutilib.misc.redirect_io import capture_output
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, AbstractModel, Expression, Var, Set, Param, Objective, value, sum_product
from pyomo.core.base.expression import _GeneralExpressionData
-import six
-
class TestExpressionData(unittest.TestCase):
def test_exprdata_get_set(self):
diff --git a/pyomo/core/tests/unit/test_external.py b/pyomo/core/tests/unit/test_external.py
index 2adf354c343..be71a1cd0fb 100644
--- a/pyomo/core/tests/unit/test_external.py
+++ b/pyomo/core/tests/unit/test_external.py
@@ -8,12 +8,13 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
#
-import os
+
import pyutilib.th as unittest
from pyomo.common.getGSL import find_GSL
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, SolverFactory, value
from pyomo.core.base.external import (PythonCallbackFunction,
+ ExternalFunction,
AMPLExternalFunction)
from pyomo.opt import check_available_solvers
diff --git a/pyomo/core/tests/unit/test_indexed.py b/pyomo/core/tests/unit/test_indexed.py
index 846c18b07ed..680f761d553 100644
--- a/pyomo/core/tests/unit/test_indexed.py
+++ b/pyomo/core/tests/unit/test_indexed.py
@@ -17,7 +17,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Param, Set
from pyomo.core.base.indexed_component import normalize_index
class TestSimpleVar(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_indexed_slice.py b/pyomo/core/tests/unit/test_indexed_slice.py
index c0d7b627f53..63604a00ba4 100644
--- a/pyomo/core/tests/unit/test_indexed_slice.py
+++ b/pyomo/core/tests/unit/test_indexed_slice.py
@@ -11,12 +11,11 @@
# Unit Tests for indexed components
#
-import os
import pickle
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import Var, Block, ConcreteModel, RangeSet, Set
from pyomo.core.base.block import _BlockData
from pyomo.core.base.indexed_component_slice import IndexedComponent_slice
@@ -680,6 +679,19 @@ def test_flatten_false(self):
finally:
normalize_index.flatten = _old_flatten
+ def test_compare_1dim_slice(self):
+ m = ConcreteModel()
+ m.I = Set(initialize=range(2))
+ m.J = Set(initialize=range(2,4))
+ m.K = Set(initialize=['a','b'])
+
+ @m.Block(m.I, m.J)
+ def b(b, i, j):
+ b.v = Var(m.K)
+
+ self.assertEqual(m.b[0,:].v[:], m.b[0,:].v[:])
+ self.assertNotEqual(m.b[0,:].v[:], m.b[0,:].v['a'])
+
if __name__ == "__main__":
unittest.main()
diff --git a/pyomo/core/tests/unit/test_labelers.py b/pyomo/core/tests/unit/test_labelers.py
index 12e509c53cf..1f3c0c80849 100644
--- a/pyomo/core/tests/unit/test_labelers.py
+++ b/pyomo/core/tests/unit/test_labelers.py
@@ -10,7 +10,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, RangeSet, Block, Constraint, CounterLabeler, NumericLabeler, TextLabeler, ComponentUID, ShortNameLabeler, CNameLabeler, CuidLabeler, AlphaNumericTextLabeler, NameLabeler
class LabelerTests(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_logical_expr.py b/pyomo/core/tests/unit/test_logical_expr.py
index 356de9414b7..fd3fe61913a 100644
--- a/pyomo/core/tests/unit/test_logical_expr.py
+++ b/pyomo/core/tests/unit/test_logical_expr.py
@@ -20,7 +20,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, ConcreteModel, Set, Var, Param, Constraint, inequality, display
import pyomo.core.expr.logical_expr as logical_expr
from pyomo.core.expr.logical_expr import (
InequalityExpression, EqualityExpression, RangedExpression,
diff --git a/pyomo/core/tests/unit/test_matrix_constraint.py b/pyomo/core/tests/unit/test_matrix_constraint.py
index 8b21c661c88..54f38843979 100644
--- a/pyomo/core/tests/unit/test_matrix_constraint.py
+++ b/pyomo/core/tests/unit/test_matrix_constraint.py
@@ -1,15 +1,22 @@
-import pickle
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
import pyutilib.th as unittest
-import pyomo.environ as aml
+import pyomo.environ as pyo
from pyomo.core.base.matrix_constraint import MatrixConstraint
-from pyomo.core.kernel.set_types import (RealSet,
- IntegerSet)
+
def _create_variable_list(size, **kwds):
assert size > 0
- return aml.Var(aml.RangeSet(0,size-1), **kwds)
+ return pyo.Var(pyo.RangeSet(0,size-1), **kwds)
def _get_csr(m, n, value):
data = [value] * (m * n)
@@ -22,7 +29,7 @@ def _get_csr(m, n, value):
class TestMatrixConstraint(unittest.TestCase):
def test_init(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
m.v = _create_variable_list(3, initialize=1.0)
data, indices, indptr = _get_csr(3,3,0.0)
lb = [None] * 3
@@ -48,7 +55,7 @@ def test_init(self):
self.assertEqual(c.has_lb(), False)
self.assertEqual(c.has_ub(), False)
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
m.v = _create_variable_list(3, initialize=3)
data, indices, indptr = _get_csr(2,3,1.0)
m.c = MatrixConstraint(data, indices, indptr,
@@ -69,7 +76,7 @@ def test_init(self):
self.assertEqual(c.equality, False)
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
m.v = _create_variable_list(3, initialize=3)
data, indices, indptr = _get_csr(2,3,1.0)
m.c = MatrixConstraint(data, indices, indptr,
diff --git a/pyomo/core/tests/unit/test_misc.py b/pyomo/core/tests/unit/test_misc.py
index c27b0ec355c..9737b369cbc 100644
--- a/pyomo/core/tests/unit/test_misc.py
+++ b/pyomo/core/tests/unit/test_misc.py
@@ -19,7 +19,7 @@
from pyomo.opt import check_available_solvers
import pyomo.scripting.pyomo_command as main
-from pyomo.core import *
+from pyomo.core import AbstractModel, ConcreteModel, Block, Set, Param, Var, Objective, Constraint, Reals, display
from six import StringIO
diff --git a/pyomo/core/tests/unit/test_model.py b/pyomo/core/tests/unit/test_model.py
index 52cd82965c0..b0aaa268c96 100644
--- a/pyomo/core/tests/unit/test_model.py
+++ b/pyomo/core/tests/unit/test_model.py
@@ -14,7 +14,6 @@
#
import os
-import sys
from os.path import abspath, dirname, join
currdir = dirname(abspath(__file__))
import pickle
@@ -24,8 +23,8 @@
from pyomo.common.dependencies import yaml_available
from pyomo.core.expr import current as EXPR
-from pyomo.environ import *
-from pyomo.opt import SolutionStatus, check_available_solvers
+from pyomo.environ import RangeSet, ConcreteModel, Var, Param, Block, AbstractModel, Set, Constraint, Objective, value, sum_product, SolverFactory, VarList, ObjectiveList, ConstraintList
+from pyomo.opt import check_available_solvers
from pyomo.opt.parallel.local import SolverManager_Serial
solvers = check_available_solvers('glpk')
diff --git a/pyomo/core/tests/unit/test_mutable.py b/pyomo/core/tests/unit/test_mutable.py
index 0520098dca6..8403b9a0e17 100644
--- a/pyomo/core/tests/unit/test_mutable.py
+++ b/pyomo/core/tests/unit/test_mutable.py
@@ -20,7 +20,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Param, Var, Constraint, value
class TestMutable(unittest.TestCase):
def test_mutable_constraint_upper(self):
diff --git a/pyomo/core/tests/unit/test_numeric_expr.py b/pyomo/core/tests/unit/test_numeric_expr.py
index 7026515bf15..af4cab4dfb0 100644
--- a/pyomo/core/tests/unit/test_numeric_expr.py
+++ b/pyomo/core/tests/unit/test_numeric_expr.py
@@ -15,50 +15,37 @@
import pickle
import math
import os
-import re
from collections import defaultdict
-import six
-import sys
from os.path import abspath, dirname
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
from pyutilib.th import nottest
-from pyomo.environ import *
-import pyomo.kernel
-from pyomo.core.expr.numvalue import (
- native_types, nonpyomo_leaf_types, NumericConstant, as_numeric,
- is_potentially_variable,
-)
+from pyomo.environ import ConcreteModel, AbstractModel, RangeSet, Var, Param, Set, Constraint, ConstraintList, Expression, Objective, Reals, ExternalFunction, PositiveReals, log10, exp, floor, ceil, log, cos, sin, tan, acos, asin, atan, sinh, cosh, tanh, acosh, asinh, atanh, sqrt, value, quicksum, sum_product, is_fixed, is_constant
+from pyomo.kernel import variable, expression, objective
+from pyomo.core.expr.numvalue import (NumericConstant, as_numeric,
+ native_numeric_types,
+ is_potentially_variable, polynomial_degree)
from pyomo.core.expr.numeric_expr import (
ExpressionBase, UnaryFunctionExpression, SumExpression, PowExpression,
- ProductExpression, ReciprocalExpression, NegationExpression,
+ ProductExpression, NegationExpression, linear_expression,
MonomialTermExpression, LinearExpression, DivisionExpression,
- NPV_NegationExpression, NPV_ProductExpression, NPV_ReciprocalExpression,
+ NPV_NegationExpression, NPV_ProductExpression,
NPV_PowExpression, NPV_DivisionExpression,
- decompose_term, clone_counter,
+ decompose_term, clone_counter, nonlinear_expression,
_MutableLinearExpression, _MutableSumExpression, _decompose_linear_terms,
LinearDecompositionError,
)
import pyomo.core.expr.logical_expr as logical_expr
-from pyomo.core.expr.logical_expr import (
- InequalityExpression, EqualityExpression, RangedExpression,
-)
-from pyomo.core.expr.visitor import (
- FixedExpressionError, NonConstantExpressionError,
- StreamBasedExpressionVisitor, ExpressionReplacementVisitor,
- evaluate_expression, expression_to_string, replace_expressions,
- clone_expression, sizeof_expression,
- identify_variables, identify_components, identify_mutable_parameters,
-)
+from pyomo.core.expr.visitor import (expression_to_string,
+ clone_expression)
from pyomo.core.expr.current import Expr_if
-from pyomo.core.base.var import SimpleVar
-from pyomo.core.base.param import _ParamData, SimpleParam
-from pyomo.core.base.label import *
+from pyomo.core.base.label import NumericLabeler
from pyomo.core.expr.template_expr import IndexTemplate
-from pyomo.core.expr.expr_errors import TemplateExpressionError
+from pyomo.core.expr import expr_common
+from pyomo.core.base.var import _GeneralVarData
from pyomo.repn import generate_standard_repn
@@ -229,7 +216,6 @@ def test_arithmetic(self):
class TestExpression_EvaluateVarData(TestExpression_EvaluateNumericConstant):
def setUp(self):
- import pyomo.core.base.var
#
# Create Model
#
@@ -241,7 +227,7 @@ def setUp(self):
self.expectConstExpression = False
def create(self, val, domain):
- tmp=pyomo.core.base.var._GeneralVarData()
+ tmp=_GeneralVarData()
tmp.domain = domain
tmp.value=val
return tmp
@@ -250,7 +236,6 @@ def create(self, val, domain):
class TestExpression_EvaluateVar(TestExpression_EvaluateNumericConstant):
def setUp(self):
- import pyomo.core.base.var
#
# Create Model
#
@@ -271,7 +256,6 @@ def create(self, val, domain):
class TestExpression_EvaluateFixedVar(TestExpression_EvaluateNumericConstant):
def setUp(self):
- import pyomo.core.base.var
#
# Create Model
#
@@ -293,7 +277,6 @@ def create(self, val, domain):
class TestExpression_EvaluateImmutableParam(TestExpression_EvaluateNumericConstant):
def setUp(self):
- import pyomo.core.base.var
#
# Create Model
#
@@ -313,7 +296,6 @@ def create(self, val, domain):
class TestExpression_Evaluate_MutableParam(TestExpression_EvaluateNumericConstant):
def setUp(self):
- import pyomo.core.base.var
#
# Create Model
#
@@ -5099,14 +5081,14 @@ def test_ExpressionIndex(self):
self.check_api(M.e[0])
def test_expression(self):
- x = pyomo.kernel.variable()
- e = pyomo.kernel.expression()
+ x = variable()
+ e = expression()
e.expr = x
self.check_api(e)
def test_objective(self):
- x = pyomo.kernel.variable()
- e = pyomo.kernel.objective()
+ x = variable()
+ e = objective()
e.expr = x
self.check_api(e)
@@ -5151,7 +5133,7 @@ def test_VarIndex(self):
self.check_api(M.x[0])
def test_variable(self):
- x = pyomo.kernel.variable()
+ x = variable()
self.check_api(x)
class TestDirect_LinearExpression(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_numvalue.py b/pyomo/core/tests/unit/test_numvalue.py
index 7965d569e8b..2d50cd71b8c 100644
--- a/pyomo/core/tests/unit/test_numvalue.py
+++ b/pyomo/core/tests/unit/test_numvalue.py
@@ -15,10 +15,12 @@
from os.path import abspath, dirname
currdir = dirname(abspath(__file__))+os.sep
-import pyutilib.math
+from pyutilib.math import nan, infinity
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import (value, ConcreteModel, Param, Var,
+ polynomial_degree, is_constant, is_fixed,
+ is_potentially_variable, is_variable_type)
from pyomo.core.expr.numvalue import (NumericConstant,
as_numeric,
is_numeric_data)
@@ -163,11 +165,11 @@ def test_long(self):
self.assertEqual(val, value(val))
def test_nan(self):
- val = pyutilib.math.nan
+ val = nan
self.assertEqual(id(val), id(value(val)))
def test_inf(self):
- val = pyutilib.math.infinity
+ val = infinity
self.assertEqual(id(val), id(value(val)))
def test_string(self):
@@ -179,12 +181,12 @@ def test_const1(self):
self.assertEqual(1.0, value(val))
def test_const3(self):
- val = NumericConstant(pyutilib.math.nan)
- self.assertEqual(id(pyutilib.math.nan), id(value(val)))
+ val = NumericConstant(nan)
+ self.assertEqual(id(nan), id(value(val)))
def test_const4(self):
- val = NumericConstant(pyutilib.math.infinity)
- self.assertEqual(id(pyutilib.math.infinity), id(value(val)))
+ val = NumericConstant(infinity)
+ self.assertEqual(id(infinity), id(value(val)))
def test_param1(self):
m = ConcreteModel()
@@ -255,11 +257,11 @@ def test_long(self):
self.assertEqual(0, polynomial_degree(val))
def test_nan(self):
- val = pyutilib.math.nan
+ val = nan
self.assertEqual(0, polynomial_degree(val))
def test_inf(self):
- val = pyutilib.math.infinity
+ val = infinity
self.assertEqual(0, polynomial_degree(val))
def test_string(self):
@@ -271,11 +273,11 @@ def test_const1(self):
self.assertEqual(0, polynomial_degree(val))
def test_const3(self):
- val = NumericConstant(pyutilib.math.nan)
+ val = NumericConstant(nan)
self.assertEqual(0, polynomial_degree(val))
def test_const4(self):
- val = NumericConstant(pyutilib.math.infinity)
+ val = NumericConstant(infinity)
self.assertEqual(0, polynomial_degree(val))
def test_param1(self):
diff --git a/pyomo/core/tests/unit/test_obj.py b/pyomo/core/tests/unit/test_obj.py
index 9216a1f2ae0..3a7c03447d9 100644
--- a/pyomo/core/tests/unit/test_obj.py
+++ b/pyomo/core/tests/unit/test_obj.py
@@ -20,7 +20,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, AbstractModel, Objective, ObjectiveList, Var, Param, Set, RangeSet, value, maximize, minimize, simple_objective_rule, simple_objectivelist_rule
class TestSimpleObj(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_param.py b/pyomo/core/tests/unit/test_param.py
index 7c079694200..d949ea5d354 100644
--- a/pyomo/core/tests/unit/test_param.py
+++ b/pyomo/core/tests/unit/test_param.py
@@ -22,12 +22,12 @@
import os
import sys
-import pyutilib.services
+from pyutilib.services import TempfileManager
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import Set, RangeSet, Param, ConcreteModel, AbstractModel, Constraint, Var, NonNegativeIntegers, Integers, NonNegativeReals, Boolean, Reals, Any, display, value, set_options, sin, cos, tan, log, log10, exp, sqrt, ceil, floor, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh
from pyomo.common.log import LoggingIntercept
-from pyomo.core.base.param import _NotValid
+from pyomo.core.base.param import _NotValid, _ParamData
from six import iteritems, itervalues, StringIO
@@ -121,7 +121,7 @@ def test_getitem(self):
def test_setitem_index_error(self):
try:
self.instance.A[2] = 4.3
- if not self.instance.A._mutable:
+ if not self.instance.A.mutable:
self.fail("Expected setitem[%s] to fail for immutable Params"
% (idx,))
self.fail("Expected KeyError because 2 is not a valid key")
@@ -129,7 +129,7 @@ def test_setitem_index_error(self):
pass
except TypeError:
# immutable Params should raise a TypeError exception
- if self.instance.A._mutable:
+ if self.instance.A.mutable:
raise
def test_setitem_preexisting(self):
@@ -139,28 +139,28 @@ def test_setitem_preexisting(self):
idx = sorted(keys)[0]
self.assertEqual(self.instance.A[idx], self.data[idx])
- if self.instance.A._mutable:
+ if self.instance.A.mutable:
self.assertTrue( isinstance( self.instance.A[idx],
- pyomo.core.base.param._ParamData ) )
+ _ParamData ) )
else:
self.assertEqual(type(self.instance.A[idx]), float)
try:
self.instance.A[idx] = 4.3
- if not self.instance.A._mutable:
+ if not self.instance.A.mutable:
self.fail("Expected setitem[%s] to fail for immutable Params"
% (idx,))
self.assertEqual( self.instance.A[idx], 4.3)
self.assertTrue( isinstance(self.instance.A[idx],
- pyomo.core.base.param._ParamData ) )
+ _ParamData ) )
except TypeError:
# immutable Params should raise a TypeError exception
- if self.instance.A._mutable:
+ if self.instance.A.mutable:
raise
try:
self.instance.A[idx] = -4.3
- if not self.instance.A._mutable:
+ if not self.instance.A.mutable:
self.fail("Expected setitem[%s] to fail for immutable Params"
% (idx,))
if self.expectNegativeDomainError:
@@ -174,12 +174,12 @@ def test_setitem_preexisting(self):
% ( str(sys.exc_info()[1]), idx ) )
except TypeError:
# immutable Params should raise a TypeError exception
- if self.instance.A._mutable:
+ if self.instance.A.mutable:
raise
try:
self.instance.A[idx] = 'x'
- if not self.instance.A._mutable:
+ if not self.instance.A.mutable:
self.fail("Expected setitem[%s] to fail for immutable Params"
% (idx,))
if self.expectTextDomainError:
@@ -193,7 +193,7 @@ def test_setitem_preexisting(self):
% ( str(sys.exc_info()[1]), idx ) )
except TypeError:
# immutable Params should raise a TypeError exception
- if self.instance.A._mutable:
+ if self.instance.A.mutable:
raise
def test_setitem_default_override(self):
@@ -213,29 +213,29 @@ def test_setitem_default_override(self):
self.assertEqual( value(self.instance.A[idx]),
self.instance.A._default_val )
- if self.instance.A._mutable:
+ if self.instance.A.mutable:
self.assertIsInstance( self.instance.A[idx],
- pyomo.core.base.param._ParamData )
+ _ParamData )
else:
self.assertEqual(type(self.instance.A[idx]),
type(value(self.instance.A._default_val)))
try:
self.instance.A[idx] = 4.3
- if not self.instance.A._mutable:
+ if not self.instance.A.mutable:
self.fail("Expected setitem[%s] to fail for immutable Params"
% (idx,))
self.assertEqual( self.instance.A[idx], 4.3)
self.assertIsInstance( self.instance.A[idx],
- pyomo.core.base.param._ParamData )
+ _ParamData )
except TypeError:
# immutable Params should raise a TypeError exception
- if self.instance.A._mutable:
+ if self.instance.A.mutable:
raise
try:
self.instance.A[idx] = -4.3
- if not self.instance.A._mutable:
+ if not self.instance.A.mutable:
self.fail("Expected setitem[%s] to fail for immutable Params"
% (idx,))
if self.expectNegativeDomainError:
@@ -249,12 +249,12 @@ def test_setitem_default_override(self):
% ( str(sys.exc_info()[1]), idx ) )
except TypeError:
# immutable Params should raise a TypeError exception
- if self.instance.A._mutable:
+ if self.instance.A.mutable:
raise
try:
self.instance.A[idx] = 'x'
- if not self.instance.A._mutable:
+ if not self.instance.A.mutable:
self.fail("Expected setitem[%s] to fail for immutable Params"
% (idx,))
if self.expectTextDomainError:
@@ -268,7 +268,7 @@ def test_setitem_default_override(self):
% ( str(sys.exc_info()[1]), idx) )
except TypeError:
# immutable Params should raise a TypeError exception
- if self.instance.A._mutable:
+ if self.instance.A.mutable:
raise
def test_dim(self):
@@ -293,7 +293,7 @@ def test_keys(self):
def test_values(self):
expectException = False
# len(self.sparse_data) < len(self.data) and \
- # not self.instance.A._mutable
+ # not self.instance.A.mutable
try:
test = self.instance.A.values()
#self.assertEqual( type(test), list )
@@ -311,7 +311,7 @@ def test_items(self):
expectException = False
# len(self.sparse_data) < len(self.data) and \
# not self.instance.A._default_val is _NotValid and \
- # not self.instance.A._mutable
+ # not self.instance.A.mutable
try:
test = self.instance.A.items()
#self.assertEqual( type(test), list )
@@ -332,7 +332,7 @@ def test_itervalues(self):
expectException = False
# len(self.sparse_data) < len(self.data) and \
# not self.instance.A._default_val is None and \
- # not self.instance.A._mutable
+ # not self.instance.A.mutable
try:
test = itervalues(self.instance.A)
test = zip(self.instance.A.keys(), test)
@@ -349,7 +349,7 @@ def test_iteritems(self):
expectException = False
# len(self.sparse_data) < len(self.data) and \
# not self.instance.A._default_val is None and \
- # not self.instance.A._mutable
+ # not self.instance.A.mutable
try:
test = iteritems(self.instance.A)
if self.instance.A._default_val is _NotValid:
@@ -416,7 +416,7 @@ def test_get_default(self):
return
idx = list(set(self.data) - set(self.sparse_data))[0]
expectException = self.instance.A._default_val is _NotValid \
- and not self.instance.A._mutable
+ and not self.instance.A.mutable
try:
test = self.instance.A[idx]
if expectException:
@@ -1465,7 +1465,7 @@ def test_mutable_self(self):
# Test that display actually displays the correct param value
def test_mutable_display(self):
- tmp_stream = pyutilib.services.TempfileManager.create_tempfile(suffix = '.param_display.test')
+ tmp_stream = TempfileManager.create_tempfile(suffix = '.param_display.test')
model = ConcreteModel()
model.Q = Param(initialize=0.0, mutable=True)
self.assertEqual(model.Q, 0.0)
@@ -1634,7 +1634,7 @@ def test_mutable_self4(self):
# Test that display actually displays the correct param value
def test_mutable_display(self):
- tmp_stream = pyutilib.services.TempfileManager.create_tempfile(suffix = '.param_display.test')
+ tmp_stream = TempfileManager.create_tempfile(suffix = '.param_display.test')
model = ConcreteModel()
model.P = Param([1,2],default=0.0, mutable=True)
model.Q = Param([1,2],initialize=0.0, mutable=True)
@@ -1697,7 +1697,7 @@ def test_mutable_display(self):
# Test that pprint actually displays the correct param value
def test_mutable_pprint(self):
- tmp_stream = pyutilib.services.TempfileManager.create_tempfile(suffix = '.param_display.test')
+ tmp_stream = TempfileManager.create_tempfile(suffix = '.param_display.test')
model = ConcreteModel()
model.P = Param([1,2],default=0.0, mutable=True)
model.Q = Param([1,2],initialize=0.0, mutable=True)
diff --git a/pyomo/core/tests/unit/test_pickle.py b/pyomo/core/tests/unit/test_pickle.py
index 74a58a10ea8..8e1061ca12f 100644
--- a/pyomo/core/tests/unit/test_pickle.py
+++ b/pyomo/core/tests/unit/test_pickle.py
@@ -20,8 +20,7 @@
import platform
import pyutilib.th as unittest
-from pyomo.environ import *
-import pyomo.core.expr.current as EXPR
+from pyomo.environ import AbstractModel, ConcreteModel, Set, Param, Var, Constraint, Objective, Reals, NonNegativeReals, sum_product
using_pypy = platform.python_implementation() == "PyPy"
diff --git a/pyomo/core/tests/unit/test_piecewise.py b/pyomo/core/tests/unit/test_piecewise.py
index c0847c3cbc3..e4004ef289f 100644
--- a/pyomo/core/tests/unit/test_piecewise.py
+++ b/pyomo/core/tests/unit/test_piecewise.py
@@ -17,7 +17,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, ConcreteModel, Set, Var, Piecewise, Constraint
class TestMiscPiecewise(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_preprocess.py b/pyomo/core/tests/unit/test_preprocess.py
index d37d9f6aa1d..319f08d2b38 100644
--- a/pyomo/core/tests/unit/test_preprocess.py
+++ b/pyomo/core/tests/unit/test_preprocess.py
@@ -17,7 +17,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Set, Param, Var, Objective
class TestPreprocess(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_reference.py b/pyomo/core/tests/unit/test_reference.py
index 883b2442f5a..7086e795a96 100644
--- a/pyomo/core/tests/unit/test_reference.py
+++ b/pyomo/core/tests/unit/test_reference.py
@@ -16,9 +16,9 @@
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
-from six import itervalues, StringIO
+from six import itervalues, StringIO, iterkeys, iteritems
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Block, Var, Set, RangeSet, Param, value
from pyomo.core.base.var import IndexedVar
from pyomo.core.base.set import SetProduct, UnorderedSetOf
from pyomo.core.base.indexed_component import (
diff --git a/pyomo/core/tests/unit/test_set.py b/pyomo/core/tests/unit/test_set.py
index acf0d65dcc0..9dd848799e5 100644
--- a/pyomo/core/tests/unit/test_set.py
+++ b/pyomo/core/tests/unit/test_set.py
@@ -25,6 +25,7 @@
from pyomo.common import DeveloperError
from pyomo.common.dependencies import numpy as np, numpy_available
+from pyomo.common.dependencies import pandas as pd, pandas_available
from pyomo.common.log import LoggingIntercept
from pyomo.core.expr import native_numeric_types, native_types
import pyomo.core.base.set as SetModule
@@ -37,12 +38,12 @@
AnyRange, _AnySet, Any, AnyWithNone, _EmptySet, EmptySet, Binary,
Reals, NonNegativeReals, PositiveReals, NonPositiveReals, NegativeReals,
Integers, PositiveIntegers, NegativeIntegers,
- NonPositiveIntegers, NonNegativeIntegers,
+ NonNegativeIntegers,
Set,
SetOf, OrderedSetOf, UnorderedSetOf,
RangeSet, _FiniteRangeSetData, _InfiniteRangeSetData,
FiniteSimpleRangeSet, InfiniteSimpleRangeSet,
- AbstractFiniteSimpleRangeSet, AbstractInfiniteSimpleRangeSet,
+ AbstractFiniteSimpleRangeSet,
SetUnion_InfiniteSet, SetUnion_FiniteSet, SetUnion_OrderedSet,
SetIntersection_InfiniteSet, SetIntersection_FiniteSet,
SetIntersection_OrderedSet,
@@ -1768,6 +1769,34 @@ def x_init(m,i):
self.assertEqual(i.x[1].domain, i.A*i.B)
self.assertEqual(i.x[1], [])
+ @unittest.skipIf(not pandas_available, "pandas is not available")
+ def test_pandas_multiindex_set_init(self):
+ # Test that TuplizeValuesInitializer does not assume truthiness
+ # If it does, pandas will complain with the following error:
+ # ValueError: The truth value of a MultiIndex is ambiguous.
+ # Use a.empty, a.bool(), a.item(), a.any() or a.all().
+ iterables = [['bar', 'baz', 'foo', 'qux'], ['one', 'two']]
+ pandas_index = pd.MultiIndex.from_product(
+ iterables,
+ names=['first', 'second']
+ )
+
+ model = ConcreteModel()
+ model.a = Set(initialize=pandas_index,
+ dimen=pandas_index.nlevels)
+
+ # we will confirm that dimension is inferred correctly
+ model.b = Set(initialize=pandas_index)
+
+ self.assertIsInstance(model.a, Set)
+ self.assertEquals(list(model.a), list(pandas_index))
+ self.assertEquals(model.a.dimen, pandas_index.nlevels)
+
+ self.assertIsInstance(model.b, Set)
+ self.assertEquals(list(model.b), list(pandas_index))
+ self.assertEquals(model.b.dimen, pandas_index.nlevels)
+
+
class TestSetUnion(unittest.TestCase):
def test_pickle(self):
a = SetOf([1,3,5]) | SetOf([2,3,4])
@@ -3333,21 +3362,50 @@ def test_exceptions(self):
RangeSet( name='foo', ranges=(NR(0,2,1),) ), NS)
def test_RealSet_IntegerSet(self):
- a = SetModule.RealSet()
+ output = StringIO()
+ with LoggingIntercept(output, 'pyomo.core'):
+ a = SetModule.RealSet()
+ self.assertIn('DEPRECATED: The use of RealSet,', output.getvalue())
self.assertEqual(a, Reals)
self.assertIsNot(a, Reals)
- a = SetModule.RealSet(bounds=(1,3))
+ output = StringIO()
+ with LoggingIntercept(output, 'pyomo.core'):
+ a = SetModule.RealSet(bounds=(1,3))
+ self.assertIn('DEPRECATED: The use of RealSet,', output.getvalue())
self.assertEqual(a.bounds(), (1,3))
- a = SetModule.IntegerSet()
+ output = StringIO()
+ with LoggingIntercept(output, 'pyomo.core'):
+ a = SetModule.IntegerSet()
+ self.assertIn('DEPRECATED: The use of RealSet,', output.getvalue())
self.assertEqual(a, Integers)
self.assertIsNot(a, Integers)
- a = SetModule.IntegerSet(bounds=(1,3))
+ output = StringIO()
+ with LoggingIntercept(output, 'pyomo.core'):
+ a = SetModule.IntegerSet(bounds=(1,3))
+ self.assertIn('DEPRECATED: The use of RealSet,', output.getvalue())
self.assertEqual(a.bounds(), (1,3))
self.assertEqual(list(a), [1,2,3])
+ m = ConcreteModel()
+
+ output = StringIO()
+ with LoggingIntercept(output, 'pyomo.core'):
+ m.x = Var(within=SetModule.RealSet)
+ self.assertIn('DEPRECATED: The use of RealSet,', output.getvalue())
+
+ output = StringIO()
+ with LoggingIntercept(output, 'pyomo.core'):
+ m.y = Var(within=SetModule.RealSet())
+ self.assertIn('DEPRECATED: The use of RealSet,', output.getvalue())
+
+ output = StringIO()
+ with LoggingIntercept(output, 'pyomo.core'):
+ m.z = Var(within=SetModule.RealSet(bounds=(0,None)))
+ self.assertIn('DEPRECATED: The use of RealSet,', output.getvalue())
+
with self.assertRaisesRegex(
RuntimeError, "Unexpected keyword arguments: \{'foo': 5\}"):
IntegerSet(foo=5)
diff --git a/pyomo/core/tests/unit/test_sets.py b/pyomo/core/tests/unit/test_sets.py
index 97176726285..d25245f9a2d 100644
--- a/pyomo/core/tests/unit/test_sets.py
+++ b/pyomo/core/tests/unit/test_sets.py
@@ -38,9 +38,16 @@
import pyutilib.th as unittest
import pyomo.core.base
-from pyomo.environ import *
+from pyomo.environ import (Set, SetOf, RangeSet, Param, ConcreteModel,
+ AbstractModel, Expression, EmptySet, NonPositiveIntegers,
+ NonPositiveReals, PositiveReals, NegativeReals,
+ IntegerSet, NegativeIntegers,
+ PositiveIntegers, RealSet, BooleanSet,
+ IntegerInterval, RealInterval, Binary,
+ PercentFraction, UnitInterval, NonNegativeIntegers,
+ Integers, NonNegativeReals, Boolean, Reals,
+ Any, value, set_options, simple_set_rule)
from pyomo.core.base.set import _AnySet, RangeDifferenceError
-from pyomo.core.base.component import CloneError
_has_numpy = False
try:
diff --git a/pyomo/core/tests/unit/test_smap.py b/pyomo/core/tests/unit/test_smap.py
index c45e73d885a..dfb3dd77b64 100644
--- a/pyomo/core/tests/unit/test_smap.py
+++ b/pyomo/core/tests/unit/test_smap.py
@@ -11,10 +11,9 @@
# Unit Tests for SymbolMap
#
-from six import StringIO
-import os
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Set, Var, Objective, Constraint, Block, SymbolMap, TextLabeler
+from pyomo.core.base.symbol_map import symbol_map_from_instance
class Test(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_sos.py b/pyomo/core/tests/unit/test_sos.py
index 3a1d88b2f9c..fb3d31172c8 100644
--- a/pyomo/core/tests/unit/test_sos.py
+++ b/pyomo/core/tests/unit/test_sos.py
@@ -16,8 +16,7 @@
currdir = dirname(abspath(__file__))+os.sep
from six.moves import xrange
import pyutilib.th as unittest
-from pyomo.core.base import IntegerSet
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, AbstractModel, SOSConstraint, Var, Set
class TestErrors(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_suffix.py b/pyomo/core/tests/unit/test_suffix.py
index 957f35a3b64..0f3fc5d33d7 100644
--- a/pyomo/core/tests/unit/test_suffix.py
+++ b/pyomo/core/tests/unit/test_suffix.py
@@ -27,7 +27,7 @@
local_suffix_generator,
active_suffix_generator,
suffix_generator)
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Suffix, Var, Param, Set, Objective, Constraint, Block, sum_product
from six import StringIO
diff --git a/pyomo/core/tests/unit/test_symbol_map.py b/pyomo/core/tests/unit/test_symbol_map.py
index 11d6a059898..16645fd7029 100644
--- a/pyomo/core/tests/unit/test_symbol_map.py
+++ b/pyomo/core/tests/unit/test_symbol_map.py
@@ -1,7 +1,14 @@
-import pickle
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
import pyutilib.th as unittest
-import pyomo.environ
from pyomo.core.expr.symbol_map import SymbolMap
from pyomo.core.kernel.variable import variable
diff --git a/pyomo/core/tests/unit/test_symbolic.py b/pyomo/core/tests/unit/test_symbolic.py
index c0ba5055efb..82cc7ef959d 100644
--- a/pyomo/core/tests/unit/test_symbolic.py
+++ b/pyomo/core/tests/unit/test_symbolic.py
@@ -10,9 +10,11 @@
import pyutilib.th as unittest
-import pyomo.environ
from pyomo.common.errors import DeveloperError, NondifferentiableError
-from pyomo.core import *
+from pyomo.environ import (ConcreteModel, Var, Param, Set, NonNegativeReals,
+ Expression, RangeSet, sin, cos, tan, sinh, cosh,
+ tanh, asin, acos, atan, asinh, acosh, atanh,
+ log, log10, exp, sqrt, ceil, floor)
from pyomo.core.expr.calculus.diff_with_sympy import differentiate
from pyomo.core.expr.sympy_tools import PyomoSympyBimap, sympy_available, sympy2pyomo_expression
diff --git a/pyomo/core/tests/unit/test_taylor_series.py b/pyomo/core/tests/unit/test_taylor_series.py
index acd251e401b..fe6d2a93506 100644
--- a/pyomo/core/tests/unit/test_taylor_series.py
+++ b/pyomo/core/tests/unit/test_taylor_series.py
@@ -1,5 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as pe
+import pyomo.environ as pyo
from pyomo.core.expr.taylor_series import taylor_series_expansion
from pyomo.core.expr.current import polynomial_degree
from pyomo.core.expr.calculus.derivatives import differentiate
@@ -7,20 +17,20 @@
class TestTaylorSeries(unittest.TestCase):
def test_first_order_taylor_series(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
m.x.value = 1
- exprs_to_test = [m.x**2, pe.exp(m.x), (m.x + 2)**2]
+ exprs_to_test = [m.x**2, pyo.exp(m.x), (m.x + 2)**2]
for e in exprs_to_test:
tsa = taylor_series_expansion(e)
- self.assertAlmostEqual(pe.differentiate(e, wrt=m.x), pe.differentiate(tsa, wrt=m.x))
- self.assertAlmostEqual(pe.value(e), pe.value(tsa))
+ self.assertAlmostEqual(pyo.differentiate(e, wrt=m.x), pyo.differentiate(tsa, wrt=m.x))
+ self.assertAlmostEqual(pyo.value(e), pyo.value(tsa))
self.assertEqual(polynomial_degree(tsa), 1)
def test_higher_order_taylor_series(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(initialize=0.5)
- m.y = pe.Var(initialize=1.5)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(initialize=0.5)
+ m.y = pyo.Var(initialize=1.5)
e = m.x * m.y
tse = taylor_series_expansion(e, diff_mode=differentiate.Modes.reverse_symbolic, order=2)
@@ -28,7 +38,7 @@ def test_higher_order_taylor_series(self):
for _y in [-2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2]:
m.x.value = _x
m.y.value = _y
- self.assertAlmostEqual(pe.value(e), pe.value(tse))
+ self.assertAlmostEqual(pyo.value(e), pyo.value(tse))
e = m.x**3 + m.y**3
tse = taylor_series_expansion(e, diff_mode=differentiate.Modes.reverse_symbolic, order=3)
@@ -36,7 +46,7 @@ def test_higher_order_taylor_series(self):
for _y in [-2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2]:
m.x.value = _x
m.y.value = _y
- self.assertAlmostEqual(pe.value(e), pe.value(tse))
+ self.assertAlmostEqual(pyo.value(e), pyo.value(tse))
e = (m.x*m.y)**2
tse = taylor_series_expansion(e, diff_mode=differentiate.Modes.reverse_symbolic, order=4)
@@ -44,4 +54,4 @@ def test_higher_order_taylor_series(self):
for _y in [-2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2]:
m.x.value = _x
m.y.value = _y
- self.assertAlmostEqual(pe.value(e), pe.value(tse))
+ self.assertAlmostEqual(pyo.value(e), pyo.value(tse))
diff --git a/pyomo/core/tests/unit/test_template_expr.py b/pyomo/core/tests/unit/test_template_expr.py
index 159c4646d62..f2c9ac22182 100644
--- a/pyomo/core/tests/unit/test_template_expr.py
+++ b/pyomo/core/tests/unit/test_template_expr.py
@@ -27,7 +27,6 @@
substitute_template_with_value,
)
-import six
class TestTemplateExpressions(unittest.TestCase):
def setUp(self):
diff --git a/pyomo/core/tests/unit/test_units.py b/pyomo/core/tests/unit/test_units.py
index 8a2e647b9f1..3d34a9188ff 100644
--- a/pyomo/core/tests/unit/test_units.py
+++ b/pyomo/core/tests/unit/test_units.py
@@ -12,9 +12,8 @@
#
import pyutilib.th as unittest
-from pyomo.environ import *
-from pyomo.util.check_units import assert_units_consistent, assert_units_equivalent
-from pyomo.core.base.template_expr import IndexTemplate
+from pyomo.environ import ConcreteModel, Var, Param, Set, Constraint, Objective, Expression, ExternalFunction, value, log, log10, exp, sqrt, cos, sin, tan, asin, acos, atan, cosh, sinh, tanh, asinh, acosh, atanh, ceil, floor, sum_product, maximize, units
+from pyomo.util.check_units import assert_units_consistent
from pyomo.core.expr import inequality
import pyomo.core.expr.current as EXPR
from pyomo.core.base.units_container import (
diff --git a/pyomo/core/tests/unit/test_var.py b/pyomo/core/tests/unit/test_var.py
index 5faf0c44ef8..12408734167 100644
--- a/pyomo/core/tests/unit/test_var.py
+++ b/pyomo/core/tests/unit/test_var.py
@@ -21,7 +21,7 @@
import pyutilib.th as unittest
from pyomo.core.base import IntegerSet
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, ConcreteModel, Set, Param, Var, VarList, RangeSet, Suffix, Expression, NonPositiveReals, PositiveReals, Reals, RealSet, NonNegativeReals, Integers, Binary, value
class PyomoModel(unittest.TestCase):
diff --git a/pyomo/core/tests/unit/test_var_set_bounds.py b/pyomo/core/tests/unit/test_var_set_bounds.py
index 7b19dfebc74..21b9292169a 100644
--- a/pyomo/core/tests/unit/test_var_set_bounds.py
+++ b/pyomo/core/tests/unit/test_var_set_bounds.py
@@ -18,10 +18,10 @@
import pyutilib.th as unittest
from six.moves import xrange
-import pyomo.opt
-from pyomo.environ import *
+from pyomo.opt import check_available_solvers
+from pyomo.environ import ConcreteModel, RangeSet, Var, Set, Objective, Constraint, SolverFactory, AbstractModel
-solvers = pyomo.opt.check_available_solvers('glpk')
+solvers = check_available_solvers('glpk')
# GAH: These tests been temporarily disabled. It is no longer the job of Var
# to validate its domain at the time of construction. It only needs to
diff --git a/pyomo/core/tests/unit/test_visitor.py b/pyomo/core/tests/unit/test_visitor.py
index 9c3227f88be..2e26e62ee37 100644
--- a/pyomo/core/tests/unit/test_visitor.py
+++ b/pyomo/core/tests/unit/test_visitor.py
@@ -11,53 +11,30 @@
# Unit Tests for expression generation
#
-import copy
-import pickle
-import math
import os
-import re
-import six
-import sys
from os.path import abspath, dirname
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
from pyutilib.th import nottest
-from pyomo.environ import *
-import pyomo.kernel
-from pyomo.common.log import LoggingIntercept
-from pyomo.core.expr.numvalue import (
- native_types, nonpyomo_leaf_types, NumericConstant, as_numeric,
- is_potentially_variable,
-)
+from pyomo.environ import ConcreteModel, RangeSet, Param, Var, Expression, ExternalFunction, VarList, sum_product, inequality, quicksum, sin, tanh
+from pyomo.core.expr.numvalue import nonpyomo_leaf_types
from pyomo.core.expr.numeric_expr import (
- ExpressionBase, UnaryFunctionExpression, SumExpression, PowExpression,
- ProductExpression, DivisionExpression, NegationExpression,
- MonomialTermExpression, LinearExpression,
- NPV_NegationExpression, NPV_ProductExpression, NPV_DivisionExpression,
- NPV_PowExpression,
- decompose_term, clone_counter,
- _MutableLinearExpression, _MutableSumExpression, _decompose_linear_terms,
- LinearDecompositionError,
-)
-import pyomo.core.expr.logical_expr as logical_expr
-from pyomo.core.expr.logical_expr import (
- InequalityExpression, EqualityExpression, RangedExpression,
-)
+ SumExpression, ProductExpression,
+ MonomialTermExpression, LinearExpression)
from pyomo.core.expr.visitor import (
FixedExpressionError, NonConstantExpressionError,
StreamBasedExpressionVisitor, ExpressionReplacementVisitor,
evaluate_expression, expression_to_string, replace_expressions,
- clone_expression, sizeof_expression,
+ sizeof_expression,
identify_variables, identify_components, identify_mutable_parameters,
)
-from pyomo.core.expr.current import Expr_if
-from pyomo.core.base.var import SimpleVar
from pyomo.core.base.param import _ParamData, SimpleParam
-from pyomo.core.base.label import *
from pyomo.core.expr.template_expr import IndexTemplate
from pyomo.core.expr.expr_errors import TemplateExpressionError
+from pyomo.common.log import LoggingIntercept
+from six import StringIO
class TestExpressionUtilities(unittest.TestCase):
@@ -758,7 +735,7 @@ def before(node, child):
if type(child) in nonpyomo_leaf_types \
or not child.is_expression_type():
return False, [child]
- os = six.StringIO()
+ os = StringIO()
with LoggingIntercept(os, 'pyomo'):
walker = StreamBasedExpressionVisitor(beforeChild=before)
self.assertIn(
@@ -938,7 +915,7 @@ def accept(node, data, child_result):
def after(node, child):
counts[2] += 1
- os = six.StringIO()
+ os = StringIO()
with LoggingIntercept(os, 'pyomo'):
walker = StreamBasedExpressionVisitor(
beforeChild=before, acceptChildResult=accept, afterChild=after)
@@ -1170,7 +1147,7 @@ def afterChild(self, node, child):
% (name(child), name(node)))
def finalizeResult(self, result):
self.ans.append("Finalize")
- os = six.StringIO()
+ os = StringIO()
with LoggingIntercept(os, 'pyomo'):
walker = all_callbacks()
self.assertIn(
diff --git a/pyomo/core/tests/unit/test_xfrm_discrete_vars.py b/pyomo/core/tests/unit/test_xfrm_discrete_vars.py
index 713a1778d10..f6a5905799a 100644
--- a/pyomo/core/tests/unit/test_xfrm_discrete_vars.py
+++ b/pyomo/core/tests/unit/test_xfrm_discrete_vars.py
@@ -12,9 +12,10 @@
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Constraint, Objective, Suffix, Binary, TransformationFactory, SolverFactory, Reals
+from pyomo.opt import check_available_solvers
-solvers = pyomo.opt.check_available_solvers('cplex', 'gurobi', 'glpk')
+solvers = check_available_solvers('cplex', 'gurobi', 'glpk')
def _generateModel():
model = ConcreteModel()
diff --git a/pyomo/core/tests/unit/uninstantiated_model_linear.py b/pyomo/core/tests/unit/uninstantiated_model_linear.py
index b5900b085b0..3f2f6ef9d47 100644
--- a/pyomo/core/tests/unit/uninstantiated_model_linear.py
+++ b/pyomo/core/tests/unit/uninstantiated_model_linear.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Set, Param, Var, Objective, minimize
model = AbstractModel()
diff --git a/pyomo/core/tests/unit/uninstantiated_model_quadratic.py b/pyomo/core/tests/unit/uninstantiated_model_quadratic.py
index 503f907bd65..0a512c043a8 100644
--- a/pyomo/core/tests/unit/uninstantiated_model_quadratic.py
+++ b/pyomo/core/tests/unit/uninstantiated_model_quadratic.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, Objective, minimize
model = AbstractModel()
diff --git a/pyomo/core/util.py b/pyomo/core/util.py
index 0ddc98317e7..7a4e992e3d2 100644
--- a/pyomo/core/util.py
+++ b/pyomo/core/util.py
@@ -15,12 +15,11 @@
__all__ = ['sum_product', 'summation', 'dot_product', 'sequence', 'prod', 'quicksum']
from six.moves import xrange
-from functools import reduce
-import operator
from pyomo.core.expr.numvalue import native_numeric_types
from pyomo.core.expr.numeric_expr import decompose_term
from pyomo.core.expr import current as EXPR
-import pyomo.core.base.var
+from pyomo.core.base.var import Var
+from pyomo.core.base.expression import Expression
def prod(terms):
@@ -176,11 +175,11 @@ def sum_product(*args, **kwds):
else:
if nargs > 0:
iarg=args[-1]
- if not isinstance(iarg,pyomo.core.base.var.Var) and not isinstance(iarg, pyomo.core.base.expression.Expression):
+ if not isinstance(iarg,Var) and not isinstance(iarg, Expression):
raise ValueError("Error executing sum_product(): The last argument value must be a variable or expression object if no 'index' option is specified")
else:
iarg=denom[-1]
- if not isinstance(iarg,pyomo.core.base.var.Var) and not isinstance(iarg, pyomo.core.base.expression.Expression):
+ if not isinstance(iarg,Var) and not isinstance(iarg, Expression):
raise ValueError("Error executing sum_product(): The last denom argument value must be a variable or expression object if no 'index' option is specified")
index = iarg.index_set()
@@ -188,7 +187,7 @@ def sum_product(*args, **kwds):
vars_ = []
params_ = []
for arg in args:
- if isinstance(arg, pyomo.core.base.var.Var):
+ if isinstance(arg, Var):
vars_.append(arg)
else:
params_.append(arg)
diff --git a/pyomo/dae/contset.py b/pyomo/dae/contset.py
index db8564e0c75..e3f81eb6c43 100644
--- a/pyomo/dae/contset.py
+++ b/pyomo/dae/contset.py
@@ -11,7 +11,6 @@
import logging
import bisect
from pyomo.common.timing import ConstructionTimer
-from pyomo.core import *
from pyomo.core.base.plugin import ModelComponentFactory
from pyomo.core.base.set import SortedSimpleSet
from pyomo.core.base.numvalue import native_numeric_types
diff --git a/pyomo/dae/diffvar.py b/pyomo/dae/diffvar.py
index 0184e86167d..2428862f4cb 100644
--- a/pyomo/dae/diffvar.py
+++ b/pyomo/dae/diffvar.py
@@ -11,7 +11,7 @@
import weakref
from pyomo.common.collections import ComponentMap
from pyomo.core.base.set import UnknownSetDimen
-from pyomo.core.base.var import Var, _VarData
+from pyomo.core.base.var import Var
from pyomo.core.base.plugin import ModelComponentFactory
from pyomo.dae.contset import ContinuousSet
from six import iterkeys
diff --git a/pyomo/dae/initialization.py b/pyomo/dae/initialization.py
index 7ee2b10895f..8386af7edb5 100644
--- a/pyomo/dae/initialization.py
+++ b/pyomo/dae/initialization.py
@@ -87,7 +87,8 @@ def get_inconsistent_initial_conditions(model, time, tol=1e-8, t0=None,
return list(inconsistent)
-def solve_consistent_initial_conditions(model, time, solver, tee=False):
+def solve_consistent_initial_conditions(model, time, solver, tee=False,
+ allow_skip=True, suppress_warnings=False):
"""
Solves a model with all Constraints and Blocks deactivated except
at the initial value of the Set time. Reactivates Constraints and
@@ -98,6 +99,11 @@ def solve_consistent_initial_conditions(model, time, solver, tee=False):
time: Set whose initial conditions will remain active for solve
solver: Something that implements a solve method that accepts
a model and tee keyword as arguments
+ tee: tee argument that will be sent to solver's solve method
+ allow_skip: If True, KeyErrors due to Constraint.Skip being
+ used will be ignored
+ suppress_warnings: If True, warnings due to ignored
+ KeyErrors will be suppressed
Returns:
The object returned by the solver's solve method
@@ -119,9 +125,13 @@ def solve_consistent_initial_conditions(model, time, solver, tee=False):
raise NotImplementedError(
'%s discretization scheme is not supported' % scheme)
- t0 = time.first()
timelist = list(time)[1:]
- deactivated_dict = deactivate_model_at(model, time, timelist)
+ deactivated_dict = deactivate_model_at(
+ model,
+ time,
+ timelist,
+ allow_skip=allow_skip,
+ suppress_warnings=suppress_warnings)
result = solver.solve(model, tee=tee)
diff --git a/pyomo/dae/integral.py b/pyomo/dae/integral.py
index 9e531e5ce0d..cd56998b035 100644
--- a/pyomo/dae/integral.py
+++ b/pyomo/dae/integral.py
@@ -15,7 +15,6 @@
_GeneralExpressionData,
SimpleExpression,
IndexedExpression)
-from pyomo.dae.misc import create_access_function, create_partial_expression
__all__ = ('Integral', )
diff --git a/pyomo/dae/misc.py b/pyomo/dae/misc.py
index 25044370538..a5511d189b7 100644
--- a/pyomo/dae/misc.py
+++ b/pyomo/dae/misc.py
@@ -10,17 +10,15 @@
import logging
+from pyomo.common.collections import ComponentMap
+from pyomo.common.log import LoggingIntercept
from pyomo.core import Suffix, Var, Constraint, Piecewise, Block
from pyomo.core import Expression, Param
-from pyomo.core.base.indexed_component import IndexedComponent
from pyomo.core.base.misc import apply_indexed_rule
-from pyomo.core.base.block import _BlockData, IndexedBlock
-from pyomo.dae import ContinuousSet, DerivativeVar, DAE_Error
-from pyomo.common.collections import ComponentMap
-from pyomo.core.base.block import SortComponents
-from pyomo.common.log import LoggingIntercept
+from pyomo.core.base.block import IndexedBlock, SortComponents
+from pyomo.dae import ContinuousSet, DAE_Error
-from six import iterkeys, itervalues, iteritems, StringIO
+from six import iterkeys, itervalues, StringIO
logger = logging.getLogger('pyomo.dae')
@@ -171,7 +169,7 @@ def expand_components(block):
N = len(redo_expansion)
- except Exception as e:
+ except Exception:
logger.error(buf.getvalue())
raise
@@ -451,7 +449,6 @@ def get_index_information(var, ds):
# Find index order of ContinuousSet in the variable
indargs = []
dsindex = 0
- tmpds2 = None
if var.dim() != 1:
indCount = 0
diff --git a/pyomo/dae/set_utils.py b/pyomo/dae/set_utils.py
index dbd19ea71d3..40698e3f535 100644
--- a/pyomo/dae/set_utils.py
+++ b/pyomo/dae/set_utils.py
@@ -116,7 +116,6 @@ def get_index_set_except(comp, *sets):
and a value for each set excluded. These values must be provided
in the same order their Sets were provided in the sets argument.
"""
- n_set = len(sets)
s_set = ComponentSet(sets)
try:
total_s_dim = sum([s.dimen for s in sets])
diff --git a/pyomo/dae/simulator.py b/pyomo/dae/simulator.py
index 9d4659c860e..12ea70c3a66 100644
--- a/pyomo/dae/simulator.py
+++ b/pyomo/dae/simulator.py
@@ -6,20 +6,16 @@
# the U.S. Government retains certain rights in this software.
# This software is distributed under the BSD License.
# _________________________________________________________________________
-from pyomo.core.base import Constraint, Param, Var, value, Suffix, Block
+from pyomo.core.base import Constraint, Param, value, Suffix, Block
from pyomo.dae import ContinuousSet, DerivativeVar
from pyomo.dae.diffvar import DAE_Error
from pyomo.core.expr import current as EXPR
-from pyomo.core.expr.numvalue import (
- NumericValue, native_numeric_types, nonpyomo_leaf_types,
-)
+from pyomo.core.expr.numvalue import native_numeric_types
from pyomo.core.expr.template_expr import IndexTemplate, _GetItemIndexer
-from pyomo.core.base.indexed_component_slice import IndexedComponent_slice
-from pyomo.core.base.reference import Reference
-from six import iterkeys, itervalues
+from six import iterkeys
import logging
diff --git a/pyomo/dae/tests/test_colloc.py b/pyomo/dae/tests/test_colloc.py
index 688ffe7fe8a..6c4ad431fdd 100644
--- a/pyomo/dae/tests/test_colloc.py
+++ b/pyomo/dae/tests/test_colloc.py
@@ -11,17 +11,14 @@
from __future__ import print_function
import pyutilib.th as unittest
-from pyomo.environ import (Var, Set, ConcreteModel, value, Constraint,
+from pyomo.environ import (Var, Set, ConcreteModel,
TransformationFactory, pyomo)
from pyomo.dae import ContinuousSet, DerivativeVar
from pyomo.dae.diffvar import DAE_Error
from pyomo.repn import generate_standard_repn
-import os
from six import StringIO
-from pyutilib.misc import setup_redirect, reset_redirect
-from pyutilib.misc import import_file
from pyomo.common.log import LoggingIntercept
diff --git a/pyomo/dae/tests/test_diffvar.py b/pyomo/dae/tests/test_diffvar.py
index 98c8b110d63..381957aa954 100644
--- a/pyomo/dae/tests/test_diffvar.py
+++ b/pyomo/dae/tests/test_diffvar.py
@@ -20,7 +20,6 @@
from pyomo.environ import ConcreteModel, Var, Set, TransformationFactory
from pyomo.dae import ContinuousSet, DerivativeVar
from pyomo.dae.diffvar import DAE_Error
-from six import StringIO
currdir = dirname(abspath(__file__)) + os.sep
diff --git a/pyomo/dae/tests/test_finite_diff.py b/pyomo/dae/tests/test_finite_diff.py
index dbe20a44f7c..05964fd5538 100644
--- a/pyomo/dae/tests/test_finite_diff.py
+++ b/pyomo/dae/tests/test_finite_diff.py
@@ -11,15 +11,12 @@
from __future__ import print_function
import pyutilib.th as unittest
-from pyomo.environ import (Var, Set, ConcreteModel, value, Constraint,
- TransformationFactory, pyomo)
+from pyomo.environ import (Var, Set, ConcreteModel,
+ TransformationFactory)
from pyomo.dae import ContinuousSet, DerivativeVar
from pyomo.dae.diffvar import DAE_Error
-import os
from six import StringIO
-from pyutilib.misc import setup_redirect, reset_redirect
-from pyutilib.misc import import_file
from pyomo.common.log import LoggingIntercept
diff --git a/pyomo/dae/tests/test_initialization.py b/pyomo/dae/tests/test_initialization.py
index c0419b78e97..fdb1026f6ee 100644
--- a/pyomo/dae/tests/test_initialization.py
+++ b/pyomo/dae/tests/test_initialization.py
@@ -14,16 +14,12 @@
import os
from os.path import abspath, dirname
-from six import StringIO
import pyutilib.th as unittest
-from pyomo.core.base import *
-from pyomo.environ import SolverFactory
-from pyomo.common.collections import ComponentMap
-from pyomo.common.log import LoggingIntercept
-from pyomo.dae import *
-from pyomo.dae.initialization import *
+from pyomo.environ import SolverFactory, ConcreteModel, Set, Block, Var, Constraint, TransformationFactory
+from pyomo.dae import ContinuousSet, DerivativeVar
+from pyomo.dae.initialization import solve_consistent_initial_conditions, get_inconsistent_initial_conditions
currdir = dirname(abspath(__file__)) + os.sep
@@ -77,6 +73,12 @@ def con2(fs, x):
return fs.b1.v[m.time.first(), x] == fs.v0[x]
# will be consistent
+ @m.fs.Constraint(m.time, m.space)
+ def con3(fs, t, x):
+ if x == m.space.first():
+ return Constraint.Skip
+ return fs.b2[t, x].v['a'] == 7.
+
disc = TransformationFactory('dae.collocation')
disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU')
disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU')
@@ -101,7 +103,7 @@ def test_get_inconsistent_initial_conditions(self):
def test_solve_consistent_initial_conditions(self):
m = make_model()
solver = SolverFactory('ipopt')
- solve_consistent_initial_conditions(m, m.time, solver)
+ solve_consistent_initial_conditions(m, m.time, solver, allow_skip=True)
inconsistent = get_inconsistent_initial_conditions(m, m.time)
self.assertFalse(inconsistent)
@@ -110,6 +112,14 @@ def test_solve_consistent_initial_conditions(self):
self.assertTrue(m.fs.b1.con[m.time[1], m.space[1]].active)
self.assertTrue(m.fs.b1.con[m.time[3], m.space[1]].active)
+ with self.assertRaises(KeyError):
+ solve_consistent_initial_conditions(
+ m,
+ m.time,
+ solver,
+ allow_skip=False,
+ )
+
if __name__ == "__main__":
unittest.main()
diff --git a/pyomo/dae/tests/test_integral.py b/pyomo/dae/tests/test_integral.py
index dc5fd2f1312..dec26c332c5 100644
--- a/pyomo/dae/tests/test_integral.py
+++ b/pyomo/dae/tests/test_integral.py
@@ -24,7 +24,6 @@
from pyomo.repn import generate_standard_repn
-from six import StringIO
currdir = dirname(abspath(__file__)) + os.sep
diff --git a/pyomo/dae/tests/test_misc.py b/pyomo/dae/tests/test_misc.py
index ba078b4b06d..0d3ba0db5f4 100644
--- a/pyomo/dae/tests/test_misc.py
+++ b/pyomo/dae/tests/test_misc.py
@@ -14,15 +14,23 @@
import os
from os.path import abspath, dirname
-from six import StringIO
+from six import StringIO, iterkeys
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import (
+ ConcreteModel, Set, Param, Var, Constraint, Expression, Block,
+ TransformationFactory, Piecewise, Objective, ExternalFunction,
+ Suffix, value,
+)
from pyomo.common.collections import ComponentMap
from pyomo.common.log import LoggingIntercept
-from pyomo.dae import *
-from pyomo.dae.misc import *
+from pyomo.dae import ContinuousSet, DerivativeVar
+from pyomo.dae.misc import (
+ generate_finite_elements, generate_colloc_points,
+ update_contset_indexed_component, expand_components,
+ get_index_information,
+)
currdir = dirname(abspath(__file__)) + os.sep
diff --git a/pyomo/dae/tests/test_set_utils.py b/pyomo/dae/tests/test_set_utils.py
index 2efe22a8b0f..902d0f534e5 100644
--- a/pyomo/dae/tests/test_set_utils.py
+++ b/pyomo/dae/tests/test_set_utils.py
@@ -14,16 +14,16 @@
import os
from os.path import abspath, dirname
-from six import StringIO
-
import pyutilib.th as unittest
-from pyomo.core.base import (Block, Constraint, ConcreteModel, Var, Set,
- TransformationFactory)
-from pyomo.common.collections import ComponentMap
-from pyomo.common.log import LoggingIntercept
-from pyomo.dae import *
-from pyomo.dae.set_utils import *
+from pyomo.core.base import (
+ Block, Constraint, ConcreteModel, Var, Set, TransformationFactory
+)
+from pyomo.dae import ContinuousSet, DerivativeVar
+from pyomo.dae.set_utils import (
+ is_explicitly_indexed_by, is_in_block_indexed_by, get_index_set_except,
+ deactivate_model_at,
+)
currdir = dirname(abspath(__file__)) + os.sep
diff --git a/pyomo/dae/tests/test_simulator.py b/pyomo/dae/tests/test_simulator.py
index 9d4a9906443..e62c0b581ea 100644
--- a/pyomo/dae/tests/test_simulator.py
+++ b/pyomo/dae/tests/test_simulator.py
@@ -13,7 +13,7 @@
from pyomo.core.expr import current as EXPR
from pyomo.environ import (
- ConcreteModel, RangeSet, Param, Var, Set, value, Constraint,
+ ConcreteModel, Param, Var, Set, Constraint,
sin, log, sqrt, TransformationFactory)
from pyomo.dae import ContinuousSet, DerivativeVar
from pyomo.dae.diffvar import DAE_Error
diff --git a/pyomo/dataportal/factory.py b/pyomo/dataportal/factory.py
index d17fa139e3a..5760c819ca0 100644
--- a/pyomo/dataportal/factory.py
+++ b/pyomo/dataportal/factory.py
@@ -14,8 +14,8 @@
]
import logging
-import pyutilib.misc
from pyomo.common import Factory
+from pyutilib.component.core import PluginError
logger = logging.getLogger('pyomo.core')
diff --git a/pyomo/dataportal/parse_datacmds.py b/pyomo/dataportal/parse_datacmds.py
index a38f356563a..272cf6bd8dd 100644
--- a/pyomo/dataportal/parse_datacmds.py
+++ b/pyomo/dataportal/parse_datacmds.py
@@ -20,10 +20,8 @@
from inspect import getfile, currentframe
from six.moves import xrange
-from pyutilib.misc import flatten_list, import_file
-
-from pyomo.common import config
-from pyomo.common.fileutils import this_file_dir, this_file
+from pyutilib.misc import flatten_list
+from pyomo.common.fileutils import this_file
_re_number = r'[-+]?(?:[0-9]+\.?[0-9]*|\.[0-9]+)(?:[eE][-+]?[0-9]+)?'
diff --git a/pyomo/dataportal/process_data.py b/pyomo/dataportal/process_data.py
index 34a941c2e22..e1d534cdc2c 100644
--- a/pyomo/dataportal/process_data.py
+++ b/pyomo/dataportal/process_data.py
@@ -11,10 +11,9 @@
import sys
import re
import copy
-import math
import logging
-from pyutilib.misc import quote_split, Options
+from pyutilib.misc import Options
import pyutilib.common
from pyutilib.misc import flatten
@@ -258,7 +257,6 @@ def _process_set_data(cmd, sname, _model):
logger.debug("DEBUG: _process_set_data(start) %s",cmd)
if len(cmd) == 0:
return []
- sd = sname
ans=[]
i=0
template=None
@@ -549,7 +547,7 @@ def _apply_templates(cmd):
nindex = len(tmp)
template=tmp
ilist = set()
- for kk in range(len(tmp)):
+ for kk in range(nindex):
if tmp[kk] == '*':
ilist.add(kk)
elif len(ilist) == 0:
@@ -868,7 +866,6 @@ def _process_load(cmd, _model, _data, _default, options=None):
isinstance(data, UnknownDataManager):
raise pyutilib.common.ApplicationError("Data manager '%s' is not available." % options.using)
set_name=None
- param_name=None
#
# Create symbol map
#
diff --git a/pyomo/dataportal/tests/test_dataportal.py b/pyomo/dataportal/tests/test_dataportal.py
index e985374c3c0..360bf047ae7 100644
--- a/pyomo/dataportal/tests/test_dataportal.py
+++ b/pyomo/dataportal/tests/test_dataportal.py
@@ -19,7 +19,7 @@
import pyutilib.th as unittest
from pyomo.dataportal.factory import DataManagerFactory
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, ConcreteModel, Set, DataPortal, Param, Boolean, Any, value
currdir=dirname(abspath(__file__))+os.sep
example_dir=pyomo_dir+os.sep+".."+os.sep+"examples"+os.sep+"pyomo"+os.sep+"tutorials"+os.sep+"tab"+os.sep
diff --git a/pyomo/duality/lagrangian_dual.py b/pyomo/duality/lagrangian_dual.py
index f5252f0d208..df4d630279c 100644
--- a/pyomo/duality/lagrangian_dual.py
+++ b/pyomo/duality/lagrangian_dual.py
@@ -12,11 +12,11 @@
# NOTE: deprecated code
#
from pyomo.common.deprecation import deprecated
-from pyomo.core import *
+from pyomo.core import TransformationFactory, Constraint, Set, Var, Objective, AbstractModel, maximize
+from pyomo.repn import generate_standard_repn
from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
from pyomo.core.plugins.transform.standard_form import StandardForm
from pyomo.core.plugins.transform.util import partial, process_canonical_repn
-from pyomo.common.deprecation import deprecated
@TransformationFactory.register("core.lagrangian_dual", doc="Create the LP dual model.")
diff --git a/pyomo/duality/plugins.py b/pyomo/duality/plugins.py
index f81e7d1b98a..74534e209ad 100644
--- a/pyomo/duality/plugins.py
+++ b/pyomo/duality/plugins.py
@@ -17,7 +17,6 @@
Var,
Constraint,
Objective,
- Set,
minimize,
NonNegativeReals,
NonPositiveReals,
@@ -26,7 +25,6 @@
Model,
ConcreteModel)
from pyomo.duality.collect import collect_linear_terms
-from pyomo.common.deprecation import deprecated
def load():
pass
diff --git a/pyomo/duality/tests/test_linear_dual.py b/pyomo/duality/tests/test_linear_dual.py
index 33eb47d42e5..28e88391b4d 100644
--- a/pyomo/duality/tests/test_linear_dual.py
+++ b/pyomo/duality/tests/test_linear_dual.py
@@ -20,8 +20,6 @@
import pyutilib.th as unittest
from pyomo.common.dependencies import yaml, yaml_available, yaml_load_args
-import pyomo.opt
-from pyomo.environ import *
from pyomo.scripting.util import cleanup
import pyomo.scripting.pyomo_main as main
diff --git a/pyomo/environ/__init__.py b/pyomo/environ/__init__.py
index 062841abc43..1ef0c6563ad 100644
--- a/pyomo/environ/__init__.py
+++ b/pyomo/environ/__init__.py
@@ -65,8 +65,8 @@ def _import_packages():
#
# Import required packages
#
- for name in _packages:
- pname = name+'.plugins'
+ for _package in _packages:
+ pname = _package + '.plugins'
try:
_do_import(pname)
except ImportError:
@@ -87,8 +87,8 @@ def _import_packages():
#
# Import optional packages
#
- for name in _optional_packages:
- pname = name+'.plugins'
+ for _package in _optional_packages:
+ pname = _package + '.plugins'
try:
_do_import(pname)
except ImportError:
@@ -102,10 +102,87 @@ def _import_packages():
# Expose the symbols from pyomo.core
#
from pyomo.dataportal import DataPortal
-from pyomo.core import *
+import pyomo.core.kernel
+import pyomo.core.base._pyomo
+from pyomo.common.collections import ComponentMap
+import pyomo.core.base.indexed_component
+import pyomo.core.base._pyomo
+from six import iterkeys, iteritems
+import pyomo.core.base.util
+from pyomo.core import expr, base, beta, kernel, plugins, preprocess
+from pyomo.core.base import util
+import pyomo.core.preprocess
+
+from pyomo.core import (numvalue, numeric_expr, boolean_value,
+ current, symbol_map, sympy_tools,
+ taylor_series, visitor, expr_common, expr_errors,
+ calculus, native_types,
+ linear_expression, nonlinear_expression,
+ land, lor, equivalent, exactly,
+ atleast, atmost, implies, lnot,
+ xor, inequality, log, log10, sin, cos, tan, cosh,
+ sinh, tanh, asin, acos, atan, exp, sqrt, asinh, acosh,
+ atanh, ceil, floor, Expr_if, differentiate,
+ taylor_series_expansion, SymbolMap, PyomoObject,
+ nonpyomo_leaf_types, native_numeric_types,
+ value, is_constant, is_fixed, is_variable_type,
+ is_potentially_variable, polynomial_degree,
+ NumericValue, ZeroConstant, as_boolean, BooleanConstant,
+ BooleanValue, native_logical_values, minimize,
+ maximize, PyomoOptions, Expression, CuidLabeler,
+ CounterLabeler, NumericLabeler,
+ CNameLabeler, TextLabeler,
+ AlphaNumericTextLabeler, NameLabeler, ShortNameLabeler,
+ name, Component, ComponentUID, BuildAction,
+ BuildCheck, Set, SetOf, simple_set_rule, RangeSet,
+ Param, Var, VarList, SimpleVar,
+ BooleanVar, BooleanVarList, SimpleBooleanVar,
+ logical_expr, simple_constraint_rule,
+ simple_constraintlist_rule, ConstraintList,
+ Constraint, LogicalConstraint,
+ LogicalConstraintList, simple_objective_rule,
+ simple_objectivelist_rule, Objective,
+ ObjectiveList, Connector, SOSConstraint,
+ Piecewise, active_export_suffix_generator,
+ active_import_suffix_generator, Suffix,
+ ExternalFunction, symbol_map_from_instance,
+ Reference, Reals, PositiveReals, NonPositiveReals,
+ NegativeReals, NonNegativeReals, Integers,
+ PositiveIntegers, NonPositiveIntegers,
+ NegativeIntegers, NonNegativeIntegers,
+ Boolean, Binary, Any, AnyWithNone, EmptySet,
+ UnitInterval, PercentFraction, RealInterval,
+ IntegerInterval, display, SortComponents,
+ TraversalStrategy, Block, SimpleBlock,
+ active_components, components,
+ active_components_data, components_data,
+ global_option, Model, ConcreteModel,
+ AbstractModel, pyomo_callback,
+ IPyomoExpression, ExpressionFactory,
+ ExpressionRegistration, IPyomoPresolver,
+ IPyomoPresolveAction,
+ IParamRepresentation,
+ ParamRepresentationFactory,
+ IPyomoScriptPreprocess,
+ IPyomoScriptCreateModel,
+ IPyomoScriptCreateDataPortal,
+ IPyomoScriptModifyInstance,
+ IPyomoScriptPrintModel,
+ IPyomoScriptPrintInstance,
+ IPyomoScriptSaveInstance,
+ IPyomoScriptPrintResults,
+ IPyomoScriptSaveResults,
+ IPyomoScriptPostprocess,
+ ModelComponentFactory, Transformation,
+ TransformationFactory, instance2dat,
+ set_options, RealSet, IntegerSet, BooleanSet,
+ prod, quicksum, sum_product, dot_product,
+ summation, sequence)
+
from pyomo.opt import (
SolverFactory, SolverManagerFactory, UnknownSolver,
TerminationCondition, SolverStatus, check_optimal_termination,
assert_optimal_termination
)
from pyomo.core.base.units_container import units
+from weakref import ref as weakref_ref
diff --git a/pyomo/environ/tests/test_environ.py b/pyomo/environ/tests/test_environ.py
index 59a96c413be..24901dc247d 100644
--- a/pyomo/environ/tests/test_environ.py
+++ b/pyomo/environ/tests/test_environ.py
@@ -122,7 +122,7 @@ def test_tpl_import_time(self):
# of slow-loading TPLs can vary from platform to platform.
ref = {'tempfile', 'logging', 'ctypes', 'ssl', 'argparse',
'textwrap', 'inspect', 'xml', 'platform', 'uuid',
- 'optparse'}
+ 'optparse', 'filecmp'}
# Non-standard-library TPLs that Pyomo will load unconditionally
ref.add('six')
ref.add('ply')
diff --git a/pyomo/gdp/disjunct.py b/pyomo/gdp/disjunct.py
index 8308c9b2971..8d8f884826b 100644
--- a/pyomo/gdp/disjunct.py
+++ b/pyomo/gdp/disjunct.py
@@ -24,7 +24,7 @@
from pyomo.core.base.component import (
ActiveComponent, ActiveComponentData, ComponentData
)
-from pyomo.core.base.numvalue import native_types
+from pyomo.core.base.numvalue import native_types, value
from pyomo.core.base.block import _BlockData
from pyomo.core.base.misc import apply_indexed_rule
from pyomo.core.base.indexed_component import ActiveIndexedComponent
diff --git a/pyomo/gdp/plugins/bigm.py b/pyomo/gdp/plugins/bigm.py
index bb895fcdef3..79574f86f21 100644
--- a/pyomo/gdp/plugins/bigm.py
+++ b/pyomo/gdp/plugins/bigm.py
@@ -11,22 +11,18 @@
"""Big-M Generalized Disjunctive Programming transformation module."""
import logging
-import textwrap
from pyomo.common.collections import ComponentMap, ComponentSet
from pyomo.common.config import ConfigBlock, ConfigValue
from pyomo.common.modeling import unique_component_name
-from pyomo.common.deprecation import deprecation_warning
+from pyomo.common.deprecation import deprecated
from pyomo.contrib.fbbt.fbbt import compute_bounds_on_expr
-from pyomo.contrib.fbbt.interval import inf
from pyomo.core import (
Block, BooleanVar, Connector, Constraint, Param, Set, SetOf, Suffix, Var,
Expression, SortComponents, TraversalStrategy, value,
RangeSet, NonNegativeIntegers, LogicalConstraint, )
from pyomo.core.base.external import ExternalFunction
from pyomo.core.base import Transformation, TransformationFactory, Reference
-from pyomo.core.base.component import ComponentUID, ActiveComponent
-from pyomo.core.base.PyomoModel import ConcreteModel, AbstractModel
import pyomo.core.expr.current as EXPR
from pyomo.gdp import Disjunct, Disjunction, GDP_Error
from pyomo.gdp.util import (
@@ -172,7 +168,6 @@ def _get_bigm_suffix_list(self, block, stopping_block=None):
# SimpleBlocks. Though it is possible at this point to stick them
# on whatever components you want, we won't pick them up.
suffix_list = []
- orig_block = block
# go searching above block in the tree, stop when we hit stopping_block
# (This is so that we can search on each Disjunct once, but get any
@@ -440,11 +435,15 @@ def _transform_disjunct(self, obj, transBlock, bigM, arg_list, suffix_list):
relaxedDisjuncts = transBlock.relaxedDisjuncts
relaxationBlock = relaxedDisjuncts[len(relaxedDisjuncts)]
# we will keep a map of constraints (hashable, ha!) to a tuple to
- # indicate where their m value came from, either (arg dict, key) if it
- # came from args, (Suffix, key) if it came from Suffixes, or (M_lower,
- # M_upper) if we calcualted it ourselves. I am keeping it here because I
- # want it to move with the disjunct transformation blocks in the case of
- # nested constraints, to make it easier to query.
+ # indicate what their M value is and where it came from, of the form:
+ # ((lower_value, lower_source, lower_key), (upper_value, upper_source,
+ # upper_key)), where the first tuple is the information for the lower M,
+ # the second tuple is the info for the upper M, source is the Suffix or
+ # argument dictionary and None if the value was calculated, and key is
+ # the key in the Suffix or argument dictionary, and None if it was
+ # calculated. (Note that it is possible the lower or upper is
+ # user-specified and the other is not, hence the need to store
+ # information for both.)
relaxationBlock.bigm_src = {}
relaxationBlock.localVarReferences = Block()
obj._transformation_block = weakref_ref(relaxationBlock)
@@ -574,6 +573,27 @@ def _get_constraint_map_dict(self, transBlock):
'transformedConstraints': ComponentMap()}
return transBlock._constraintMap
+ def _convert_M_to_tuple(self, M, constraint_name):
+ if not isinstance(M, (tuple, list)):
+ if M is None:
+ M = (None, None)
+ else:
+ try:
+ M = (-M, M)
+ except:
+ logger.error("Error converting scalar M-value %s "
+ "to (-M,M). Is %s not a numeric type?"
+ % (M, type(M)))
+ raise
+ if len(M) != 2:
+ raise GDP_Error("Big-M %s for constraint %s is not of "
+ "length two. "
+ "Expected either a single value or "
+ "tuple or list of length two for M."
+ % (str(M), constraint_name))
+
+ return M
+
def _transform_constraint(self, obj, disjunct, bigMargs, arg_list,
disjunct_suffix_list):
# add constraint to the transformation block, we'll transform it there.
@@ -607,10 +627,15 @@ def _transform_constraint(self, obj, disjunct, bigMargs, arg_list,
if not c.active:
continue
+ lower = (None, None, None)
+ upper = (None, None, None)
+
# first, we see if an M value was specified in the arguments.
# (This returns None if not)
- M = self._get_M_from_args(c, bigMargs, arg_list, bigm_src)
-
+ lower, upper = self._get_M_from_args(c, bigMargs, arg_list, lower,
+ upper)
+ M = (lower[0], upper[0])
+
if __debug__ and logger.isEnabledFor(logging.DEBUG):
_name = obj.getname(
fully_qualified=True, name_buffer=NAME_BUFFER)
@@ -618,14 +643,17 @@ def _transform_constraint(self, obj, disjunct, bigMargs, arg_list,
"from the BigM argument is %s." % (cons_name,
str(M)))
- # if we didn't get something from args, try suffixes:
- if M is None:
+ # if we didn't get something we need from args, try suffixes:
+ if (M[0] is None and c.lower is not None) or \
+ (M[1] is None and c.upper is not None):
# first get anything parent to c but below disjunct
suffix_list = self._get_bigm_suffix_list(c.parent_block(),
stopping_block=disjunct)
# prepend that to what we already collected for the disjunct.
suffix_list.extend(disjunct_suffix_list)
- M = self._get_M_from_suffixes(c, suffix_list, bigm_src)
+ lower, upper = self._update_M_from_suffixes(c, suffix_list,
+ lower, upper)
+ M = (lower[0], upper[0])
if __debug__ and logger.isEnabledFor(logging.DEBUG):
_name = obj.getname(
@@ -634,30 +662,12 @@ def _transform_constraint(self, obj, disjunct, bigMargs, arg_list,
"after checking suffixes is %s." % (cons_name,
str(M)))
- if not isinstance(M, (tuple, list)):
- if M is None:
- M = (None, None)
- else:
- try:
- M = (-M, M)
- except:
- logger.error("Error converting scalar M-value %s "
- "to (-M,M). Is %s not a numeric type?"
- % (M, type(M)))
- raise
- if len(M) != 2:
- raise GDP_Error("Big-M %s for constraint %s is not of "
- "length two. "
- "Expected either a single value or "
- "tuple or list of length two for M."
- % (str(M), name))
-
if c.lower is not None and M[0] is None:
M = (self._estimate_M(c.body, name)[0] - c.lower, M[1])
- bigm_src[c] = M
+ lower = (M[0], None, None)
if c.upper is not None and M[1] is None:
M = (M[0], self._estimate_M(c.body, name)[1] - c.upper)
- bigm_src[c] = M
+ upper = (M[1], None, None)
if __debug__ and logger.isEnabledFor(logging.DEBUG):
_name = obj.getname(
@@ -666,6 +676,9 @@ def _transform_constraint(self, obj, disjunct, bigMargs, arg_list,
"after estimating (if needed) is %s." %
(cons_name, str(M)))
+ # save the source information
+ bigm_src[c] = (lower, upper)
+
# Handle indices for both SimpleConstraint and IndexedConstraint
if i.__class__ is tuple:
i_lb = i + ('lb',)
@@ -704,56 +717,128 @@ def _transform_constraint(self, obj, disjunct, bigMargs, arg_list,
# deactivate because we relaxed
c.deactivate()
- def _get_M_from_args(self, constraint, bigMargs, arg_list, bigm_src):
+ def _process_M_value(self, m, lower, upper, need_lower, need_upper, src,
+ key, constraint_name, from_args=False):
+ m = self._convert_M_to_tuple(m, constraint_name)
+ if need_lower and m[0] is not None:
+ if from_args:
+ self.used_args[key] = m
+ lower = (m[0], src, key)
+ need_lower = False
+ if need_upper and m[1] is not None:
+ if from_args:
+ self.used_args[key] = m
+ upper = (m[1], src, key)
+ need_upper = False
+ return lower, upper, need_lower, need_upper
+
+ def _get_M_from_args(self, constraint, bigMargs, arg_list, lower, upper):
# check args: we first look in the keys for constraint and
# constraintdata. In the absence of those, we traverse up the blocks,
# and as a last resort check for a value for None
if bigMargs is None:
- return None
+ return (lower, upper)
+
+ # since we check for args first, we know lower[0] and upper[0] are both
+ # None
+ need_lower = constraint.lower is not None
+ need_upper = constraint.upper is not None
+ constraint_name = constraint.getname(fully_qualified=True,
+ name_buffer=NAME_BUFFER)
# check for the constraint itself and its container
parent = constraint.parent_component()
if constraint in bigMargs:
m = bigMargs[constraint]
- self.used_args[constraint] = m
- bigm_src[constraint] = (bigMargs, constraint)
- return m
+ (lower, upper,
+ need_lower, need_upper) = self._process_M_value(m, lower, upper,
+ need_lower,
+ need_upper,
+ bigMargs,
+ constraint,
+ constraint_name,
+ from_args=True)
+ if not need_lower and not need_upper:
+ return lower, upper
elif parent in bigMargs:
m = bigMargs[parent]
- self.used_args[parent] = m
- bigm_src[constraint] = (bigMargs, parent)
- return m
+ (lower, upper,
+ need_lower, need_upper) = self._process_M_value(m, lower, upper,
+ need_lower,
+ need_upper,
+ bigMargs, parent,
+ constraint_name,
+ from_args=True)
+ if not need_lower and not need_upper:
+ return lower, upper
# use the precomputed traversal up the blocks
for arg in arg_list:
for block, val in iteritems(arg):
- self.used_args[block] = val
- bigm_src[constraint] = (bigMargs, block)
- return val
+ (lower, upper,
+ need_lower, need_upper) = self._process_M_value(val, lower,
+ upper,
+ need_lower,
+ need_upper,
+ bigMargs,
+ block,
+ constraint_name,
+ from_args=True)
+ if not need_lower and not need_upper:
+ return lower, upper
# last check for value for None!
if None in bigMargs:
m = bigMargs[None]
- self.used_args[None] = m
- bigm_src[constraint] = (bigMargs, None)
- return m
- return None
-
- def _get_M_from_suffixes(self, constraint, suffix_list, bigm_src):
+ (lower, upper,
+ need_lower, need_upper) = self._process_M_value(m, lower, upper,
+ need_lower,
+ need_upper,
+ bigMargs, None,
+ constraint_name,
+ from_args=True)
+ if not need_lower and not need_upper:
+ return lower, upper
+
+ return lower, upper
+
+ def _update_M_from_suffixes(self, constraint, suffix_list, lower, upper):
+ # It's possible we found half the answer in args, but we are still
+ # looking for half the answer.
+ need_lower = constraint.lower is not None and lower[0] is None
+ need_upper = constraint.upper is not None and upper[0] is None
+ constraint_name = constraint.getname(fully_qualified=True,
+ name_buffer=NAME_BUFFER)
M = None
# first we check if the constraint or its parent is a key in any of the
# suffix lists
for bigm in suffix_list:
if constraint in bigm:
M = bigm[constraint]
- bigm_src[constraint] = (bigm, constraint)
- break
+ (lower, upper,
+ need_lower, need_upper) = self._process_M_value(M, lower,
+ upper,
+ need_lower,
+ need_upper,
+ bigm,
+ constraint,
+ constraint_name)
+ if not need_lower and not need_upper:
+ return lower, upper
# if c is indexed, check for the parent component
if constraint.parent_component() in bigm:
- M = bigm[constraint.parent_component()]
- bigm_src[constraint] = (bigm, constraint.parent_component())
- break
+ parent = constraint.parent_component()
+ M = bigm[parent]
+ (lower, upper,
+ need_lower, need_upper) = self._process_M_value(M, lower,
+ upper,
+ need_lower,
+ need_upper,
+ bigm, parent,
+ constraint_name)
+ if not need_lower and not need_upper:
+ return lower, upper
# if we didn't get an M that way, traverse upwards through the blocks
# and see if None has a value on any of them.
@@ -761,9 +846,15 @@ def _get_M_from_suffixes(self, constraint, suffix_list, bigm_src):
for bigm in suffix_list:
if None in bigm:
M = bigm[None]
- bigm_src[constraint] = (bigm, None)
- break
- return M
+ (lower, upper,
+ need_lower,
+ need_upper) = self._process_M_value(M, lower, upper,
+ need_lower, need_upper,
+ bigm, None,
+ constraint_name)
+ if not need_lower and not need_upper:
+ return lower, upper
+ return lower, upper
def _estimate_M(self, expr, name):
# If there are fixed variables here, unfix them for this calculation,
@@ -839,22 +930,52 @@ def get_src_constraint(self, transformedConstraint):
def get_transformed_constraints(self, srcConstraint):
return get_transformed_constraints(srcConstraint)
+ @deprecated("The get_m_value_src function is deprecated. Use "
+ "the get_M_value_src function is you need source "
+ "information or the get_M_value function if you "
+ "only need values.", version='5.7.1')
def get_m_value_src(self, constraint):
+ transBlock = _get_constraint_transBlock(constraint)
+ ((lower_val, lower_source, lower_key),
+ (upper_val, upper_source, upper_key)) = transBlock.bigm_src[constraint]
+
+ if constraint.lower is not None and constraint.upper is not None and \
+ (not lower_source is upper_source or not lower_key is upper_key):
+ raise GDP_Error("This is why this method is deprecated: The lower "
+ "and upper M values for constraint %s came from "
+ "different sources, please use the get_M_value_src "
+ "method." % constraint.name)
+ # if source and key are equal for the two, this is representable in the
+ # old format.
+ if constraint.lower is not None and lower_source is not None:
+ return (lower_source, lower_key)
+ if constraint.upper is not None and upper_source is not None:
+ return (upper_source, upper_key)
+ # else it was calculated:
+ return (lower_val, upper_val)
+
+ def get_M_value_src(self, constraint):
"""Return a tuple indicating how the M value used to transform
constraint was specified. (In particular, this can be used to
verify which BigM Suffixes were actually necessary to the
transformation.)
- If the M value came from an arg, returns (bigm_arg_dict, key), where
- bigm_arg_dict is the dictionary itself and key is the key in that
- dictionary which gave us the M value.
+ Return is of the form: ((lower_M_val, lower_M_source, lower_M_key),
+ (upper_M_val, upper_M_source, upper_M_key))
+
+ If the constraint does not have a lower bound (or an upper bound),
+ the first (second) element will be (None, None, None). Note that if
+ a constraint is of the form a <= expr <= b or is an equality constraint,
+ it is not necessarily true that the source of lower_M and upper_M
+ are the same.
- If the M value came from a Suffix, returns (suffix, key) where suffix
- is the BigM suffix used and key is the key in that Suffix.
+ If the M value came from an arg, source is the dictionary itself and
+ key is the key in that dictionary which gave us the M value.
- If the transformation calculated the value, returns (M_lower, M_upper),
- where M_lower is the float we calculated for the lower bound constraint
- and M_upper is the value calculated for the upper bound constraint.
+ If the M value came from a Suffix, source is the BigM suffix used and
+ key is the key in that Suffix.
+
+ If the transformation calculated the value, both source and key are None.
Parameters
----------
@@ -865,3 +986,19 @@ def get_m_value_src(self, constraint):
# This is a KeyError if it fails, but it is also my fault if it
# fails... (That is, it's a bug in the mapping.)
return transBlock.bigm_src[constraint]
+
+ def get_M_value(self, constraint):
+ """Returns the M values used to transform constraint. Return is a tuple:
+ (lower_M_value, upper_M_value). Either can be None if constraint does
+ not have a lower or upper bound, respectively.
+
+ Parameters
+ ----------
+ constraint: Constraint, which must be in the subtree of a transformed
+ Disjunct
+ """
+ transBlock = _get_constraint_transBlock(constraint)
+ # This is a KeyError if it fails, but it is also my fault if it
+ # fails... (That is, it's a bug in the mapping.)
+ lower, upper = transBlock.bigm_src[constraint]
+ return (lower[0], upper[0])
diff --git a/pyomo/gdp/plugins/bilinear.py b/pyomo/gdp/plugins/bilinear.py
index 08fabe84e2c..82a96fb503f 100644
--- a/pyomo/gdp/plugins/bilinear.py
+++ b/pyomo/gdp/plugins/bilinear.py
@@ -9,12 +9,9 @@
# ___________________________________________________________________________
import logging
-from six import iteritems
-from pyomo.core.expr.current import ProductExpression
-from pyomo.core import *
-from pyomo.core.base.var import _VarData
-from pyomo.gdp import *
+from pyomo.core import TransformationFactory, Transformation, Block, VarList, Set, SortComponents, Objective, Constraint
+from pyomo.gdp import Disjunct, Disjunction
from pyomo.repn import generate_standard_repn
logger = logging.getLogger('pyomo.gdp')
@@ -27,7 +24,6 @@ def __init__(self):
super(Bilinear_Transformation, self).__init__()
def _apply_to(self, instance, **kwds):
- options = kwds.pop('options', {})
# TODO: This data should be stored differently. We cannot nest this transformation with itself
if getattr(instance, 'bilinear_data_', None) is None:
instance.bilinear_data_ = Block()
diff --git a/pyomo/gdp/plugins/chull.py b/pyomo/gdp/plugins/chull.py
index ab9393900fc..6901a2ead52 100644
--- a/pyomo/gdp/plugins/chull.py
+++ b/pyomo/gdp/plugins/chull.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from pyomo.common.deprecation import deprecation_warning
deprecation_warning(
'The pyomo.gdp.plugins.chull module is deprecated. '
diff --git a/pyomo/gdp/plugins/cuttingplane.py b/pyomo/gdp/plugins/cuttingplane.py
index d650bd471c5..f8e979c0c2f 100644
--- a/pyomo/gdp/plugins/cuttingplane.py
+++ b/pyomo/gdp/plugins/cuttingplane.py
@@ -23,16 +23,16 @@
from pyomo.common.modeling import unique_component_name
from pyomo.core import (
Any, Block, Constraint, Objective, Param, Var, SortComponents,
- Transformation, TransformationFactory, value, TransformationFactory
+ Transformation, TransformationFactory, value
)
from pyomo.opt import SolverFactory
-from pyomo.gdp import Disjunct, Disjunction, GDP_Error
+from pyomo.gdp import Disjunct, GDP_Error
from pyomo.gdp.util import (
- verify_successful_solve, NORMAL, INFEASIBLE, NONOPTIMAL
+ verify_successful_solve, NORMAL
)
-from six import iterkeys, itervalues
+from six import iterkeys
import math
import logging
diff --git a/pyomo/gdp/plugins/gdp_var_mover.py b/pyomo/gdp/plugins/gdp_var_mover.py
index fd9c03d1b8d..39d1f2b5e35 100644
--- a/pyomo/gdp/plugins/gdp_var_mover.py
+++ b/pyomo/gdp/plugins/gdp_var_mover.py
@@ -15,8 +15,6 @@
"""
import logging
-import textwrap
-from pyomo.common.plugin import alias
from pyomo.core.base import Transformation, Block, Constraint
from pyomo.gdp import Disjunct, GDP_Error, Disjunction
from pyomo.core import TraversalStrategy, TransformationFactory
diff --git a/pyomo/gdp/tests/common_tests.py b/pyomo/gdp/tests/common_tests.py
index acf30dd155c..7823cc52853 100644
--- a/pyomo/gdp/tests/common_tests.py
+++ b/pyomo/gdp/tests/common_tests.py
@@ -1,9 +1,20 @@
-from pyomo.environ import *
-from pyomo.gdp import *
-from pyomo.core.base import constraint
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+
+from pyomo.environ import TransformationFactory, ConcreteModel, Constraint, Var, Objective, Block, Any, RangeSet, Expression, value
+from pyomo.gdp import Disjunct, Disjunction, GDP_Error
+from pyomo.core.base import constraint, ComponentUID
from pyomo.repn import generate_standard_repn
import pyomo.gdp.tests.models as models
-from six import StringIO
+from six import StringIO, iteritems
import random
# utitility functions
diff --git a/pyomo/gdp/tests/test_bigm.py b/pyomo/gdp/tests/test_bigm.py
index 0b70196019d..e493ddbcc1d 100644
--- a/pyomo/gdp/tests/test_bigm.py
+++ b/pyomo/gdp/tests/test_bigm.py
@@ -10,10 +10,9 @@
import pyutilib.th as unittest
-from pyomo.environ import *
-from pyomo.gdp import *
+from pyomo.environ import TransformationFactory, Block, Set, Constraint, ComponentMap, Suffix, ConcreteModel, Var, Any, value
+from pyomo.gdp import Disjunct, Disjunction, GDP_Error
from pyomo.core.base import constraint, _ConstraintData
-from pyomo.core.expr import current as EXPR
from pyomo.repn import generate_standard_repn
from pyomo.common.log import LoggingIntercept
import logging
@@ -22,9 +21,8 @@
import pyomo.gdp.tests.common_tests as ct
import random
-import sys
-from six import iteritems, StringIO
+from six import StringIO
class CommonTests:
def diff_apply_to_and_create_using(self, model):
@@ -779,18 +777,53 @@ def test_suffix_M_onBlock(self):
self.checkMs(m, -34, 34, 34, -3, 1.5)
# check the source of the values
- (src, key) = bigm.get_m_value_src(m.simpledisj.c)
- self.assertEqual(src, -3)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.simpledisj2.c)
- self.assertIsNone(src)
- self.assertEqual(key, 1.5)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[0].c)
- self.assertIs(src, m.b.BigM)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[1].c)
- self.assertIs(src, m.b.BigM)
- self.assertIsNone(key)
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj.c)
+ self.assertIsNone(l_src)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -3)
+ self.assertIsNone(u_val)
+ (l_val, u_val) = bigm.get_M_value(m.simpledisj.c)
+ self.assertEqual(l_val, -3)
+ self.assertIsNone(u_val)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj2.c)
+ self.assertIsNone(l_src)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 1.5)
+ (l_val, u_val) = bigm.get_M_value(m.simpledisj2.c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 1.5)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[0].c)
+ self.assertIs(l_src, m.b.BigM)
+ self.assertIs(u_src, m.b.BigM)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -34)
+ self.assertEqual(u_val, 34)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[0].c)
+ self.assertEqual(l_val, -34)
+ self.assertEqual(u_val, 34)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[1].c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, m.b.BigM)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 34)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[1].c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 34)
def test_block_M_arg(self):
m = models.makeTwoTermDisjOnBlock()
@@ -801,18 +834,53 @@ def test_block_M_arg(self):
self.checkMs(m, -100, 100, 13, -3, 1.5)
# check the source of the values
- (src, key) = bigm.get_m_value_src(m.simpledisj.c)
- self.assertEqual(src, -3)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.simpledisj2.c)
- self.assertIsNone(src)
- self.assertEqual(key, 1.5)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[0].c)
- self.assertIs(src, bigms)
- self.assertIs(key, m.b)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[1].c)
- self.assertIs(src, bigms)
- self.assertIs(key, m.b.disjunct[1].c)
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj.c)
+ self.assertIsNone(l_src)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -3)
+ self.assertIsNone(u_val)
+ (l_val, u_val) = bigm.get_M_value(m.simpledisj.c)
+ self.assertEqual(l_val, -3)
+ self.assertIsNone(u_val)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj2.c)
+ self.assertIsNone(l_src)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 1.5)
+ (l_val, u_val) = bigm.get_M_value(m.simpledisj2.c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 1.5)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[0].c)
+ self.assertIs(l_src, bigms)
+ self.assertIs(u_src, bigms)
+ self.assertIs(l_key, m.b)
+ self.assertIs(u_key, m.b)
+ self.assertEqual(l_val, -100)
+ self.assertEqual(u_val, 100)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[0].c)
+ self.assertEqual(l_val, -100)
+ self.assertEqual(u_val, 100)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[1].c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, bigms)
+ self.assertIsNone(l_key)
+ self.assertIs(u_key, m.b.disjunct[1].c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 13)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[1].c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 13)
def test_disjunct_M_arg(self):
m = models.makeTwoTermDisjOnBlock()
@@ -823,40 +891,111 @@ def test_disjunct_M_arg(self):
self.checkMs(m, -100, 100, 13, -3, 1.5)
# check the source of the values
- (src, key) = bigm.get_m_value_src(m.simpledisj.c)
- self.assertEqual(src, -3)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.simpledisj2.c)
- self.assertIsNone(src)
- self.assertEqual(key, 1.5)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[0].c)
- self.assertIs(src, bigms)
- self.assertIs(key, m.b)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[1].c)
- self.assertIs(src, bigms)
- self.assertIs(key, m.b.disjunct[1])
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj.c)
+ self.assertIsNone(l_src)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -3)
+ self.assertIsNone(u_val)
+ (l_val, u_val) = bigm.get_M_value(m.simpledisj.c)
+ self.assertEqual(l_val, -3)
+ self.assertIsNone(u_val)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj2.c)
+ self.assertIsNone(l_src)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 1.5)
+ (l_val, u_val) = bigm.get_M_value(m.simpledisj2.c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 1.5)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[0].c)
+ self.assertIs(l_src, bigms)
+ self.assertIs(u_src, bigms)
+ self.assertIs(l_key, m.b)
+ self.assertIs(u_key, m.b)
+ self.assertEqual(l_val, -100)
+ self.assertEqual(u_val, 100)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[0].c)
+ self.assertEqual(l_val, -100)
+ self.assertEqual(u_val, 100)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[1].c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, bigms)
+ self.assertIsNone(l_key)
+ self.assertIs(u_key, m.b.disjunct[1])
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 13)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[1].c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 13)
def test_block_M_arg_with_default(self):
m = models.makeTwoTermDisjOnBlock()
m = models.add_disj_not_on_block(m)
bigm = TransformationFactory('gdp.bigm')
- bigms = {m.b: 100, m.b.disjunct[1].c: 13, None: 34}
+ bigms = {m.b: 100, m.b.disjunct[1].c: 13,
+ m.b.disjunct[0].c: (None, 50), None: 34}
bigm.apply_to(m, bigM=bigms)
- self.checkMs(m, -100, 100, 13, -34, 34)
+ self.checkMs(m, -100, 50, 13, -34, 34)
# check the source of the values
- (src, key) = bigm.get_m_value_src(m.simpledisj.c)
- self.assertIs(src, bigms)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.simpledisj2.c)
- self.assertIs(src, bigms)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[0].c)
- self.assertIs(src, bigms)
- self.assertIs(key, m.b)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[1].c)
- self.assertIs(src, bigms)
- self.assertIs(key, m.b.disjunct[1].c)
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj.c)
+ self.assertIs(l_src, bigms)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -34)
+ self.assertIsNone(u_val)
+ l_val, u_val = bigm.get_M_value(m.simpledisj.c)
+ self.assertEqual(l_val, -34)
+ self.assertIsNone(u_val)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj2.c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, bigms)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 34)
+ l_val, u_val = bigm.get_M_value(m.simpledisj2.c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 34)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[0].c)
+ self.assertIs(l_src, bigms)
+ self.assertIs(u_src, bigms)
+ self.assertIs(l_key, m.b)
+ self.assertIs(u_key, m.b.disjunct[0].c)
+ self.assertEqual(l_val, -100)
+ self.assertEqual(u_val, 50)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[0].c)
+ self.assertEqual(l_val, -100)
+ self.assertEqual(u_val, 50)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[1].c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, bigms)
+ self.assertIsNone(l_key)
+ self.assertIs(u_key, m.b.disjunct[1].c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 13)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[1].c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 13)
def test_model_M_arg(self):
m = models.makeTwoTermDisjOnBlock()
@@ -955,18 +1094,53 @@ def test_suffix_M_simple_disj(self):
self.checkMs(m, -20, 20, 20, -45, 20)
# check source of the m values
- (src, key) = bigm.get_m_value_src(m.simpledisj.c)
- self.assertIs(src, m.simpledisj.BigM)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.simpledisj2.c)
- self.assertIs(src, m.BigM)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[0].c)
- self.assertIs(src, m.BigM)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[1].c)
- self.assertIs(src, m.BigM)
- self.assertIsNone(key)
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj.c)
+ self.assertIs(l_src, m.simpledisj.BigM)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -45)
+ self.assertIsNone(u_val)
+ l_val, u_val = bigm.get_M_value(m.simpledisj.c)
+ self.assertEqual(l_val, -45)
+ self.assertIsNone(u_val)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj2.c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, m.BigM)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 20)
+ l_val, u_val = bigm.get_M_value(m.simpledisj2.c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 20)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[0].c)
+ self.assertIs(l_src, m.BigM)
+ self.assertIs(u_src, m.BigM)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -20)
+ self.assertEqual(u_val, 20)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[0].c)
+ self.assertEqual(l_val, -20)
+ self.assertEqual(u_val, 20)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[1].c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, m.BigM)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 20)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[1].c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 20)
def test_suffix_M_constraintKeyOnBlock(self):
m = models.makeTwoTermDisjOnBlock()
@@ -996,9 +1170,74 @@ def test_suffix_M_constraintKeyOnSimpleDisj(self):
m.BigM = Suffix(direction=Suffix.LOCAL)
m.BigM[None] = 20
+ bigms = {m.b.disjunct[0].c: (-15, None)}
bigm = TransformationFactory('gdp.bigm')
- bigm.apply_to(m)
- self.checkMs(m, -20, 20, 20, -87, 20)
+
+ bigm.apply_to(m, bigM=bigms)
+ self.checkMs(m, -15, 20, 20, -87, 20)
+
+ # check source of the m values
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj.c)
+ self.assertIs(l_src, m.simpledisj.BigM)
+ self.assertIsNone(u_src)
+ self.assertIs(l_key, m.simpledisj.c)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -87)
+ self.assertIsNone(u_val)
+ l_val, u_val = bigm.get_M_value(m.simpledisj.c)
+ self.assertEqual(l_val, -87)
+ self.assertIsNone(u_val)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.simpledisj2.c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, m.BigM)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 20)
+ l_val, u_val = bigm.get_M_value(m.simpledisj2.c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 20)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[0].c)
+ self.assertIs(l_src, bigms)
+ self.assertIs(u_src, m.BigM)
+ self.assertIs(l_key, m.b.disjunct[0].c)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -15)
+ self.assertEqual(u_val, 20)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[0].c)
+ self.assertEqual(l_val, -15)
+ self.assertEqual(u_val, 20)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.b.disjunct[1].c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, m.BigM)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 20)
+ l_val, u_val = bigm.get_M_value(m.b.disjunct[1].c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 20)
+
+ def test_suffix_M_constraintKeyOnSimpleDisj_deprecated_m_src_method(self):
+ m = models.makeTwoTermDisjOnBlock()
+ m = models.add_disj_not_on_block(m)
+ m.simpledisj.BigM = Suffix(direction=Suffix.LOCAL)
+ m.simpledisj.BigM[None] = 45
+ m.simpledisj.BigM[m.simpledisj.c] = 87
+ m.BigM = Suffix(direction=Suffix.LOCAL)
+ m.BigM[None] = 20
+
+ bigms = {m.b.disjunct[0].c: (-15, None)}
+ bigm = TransformationFactory('gdp.bigm')
+
+ bigm.apply_to(m, bigM=bigms)
# check source of the m values
(src, key) = bigm.get_m_value_src(m.simpledisj.c)
@@ -1007,13 +1246,40 @@ def test_suffix_M_constraintKeyOnSimpleDisj(self):
(src, key) = bigm.get_m_value_src(m.simpledisj2.c)
self.assertIs(src, m.BigM)
self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.b.disjunct[0].c)
- self.assertIs(src, m.BigM)
- self.assertIsNone(key)
+ self.assertRaisesRegexp(
+ GDP_Error,
+ "This is why this method is deprecated: The lower "
+ "and upper M values for constraint b.disjunct\[0\].c "
+ "came from different sources, please use the "
+ "get_M_value_src method.",
+ bigm.get_m_value_src,
+ m.b.disjunct[0].c)
(src, key) = bigm.get_m_value_src(m.b.disjunct[1].c)
self.assertIs(src, m.BigM)
self.assertIsNone(key)
+ def test_disjunct_M_arg_deprecated_m_src_method(self):
+ m = models.makeTwoTermDisjOnBlock()
+ m = models.add_disj_not_on_block(m)
+ bigm = TransformationFactory('gdp.bigm')
+ bigms = {m.b: 100, m.b.disjunct[1]: 13}
+ bigm.apply_to(m, bigM=bigms)
+ self.checkMs(m, -100, 100, 13, -3, 1.5)
+
+ # check the source of the values
+ (src, key) = bigm.get_m_value_src(m.simpledisj.c)
+ self.assertEqual(src, -3)
+ self.assertIsNone(key)
+ (src, key) = bigm.get_m_value_src(m.simpledisj2.c)
+ self.assertIsNone(src)
+ self.assertEqual(key, 1.5)
+ (src, key) = bigm.get_m_value_src(m.b.disjunct[0].c)
+ self.assertIs(src, bigms)
+ self.assertIs(key, m.b)
+ (src, key) = bigm.get_m_value_src(m.b.disjunct[1].c)
+ self.assertIs(src, bigms)
+ self.assertIs(key, m.b.disjunct[1])
+
def test_block_targets_inactive(self):
ct.check_block_targets_inactive(self, 'bigm')
@@ -1506,24 +1772,63 @@ def test_m_value_mappings(self):
bigms = {m.disjunct[1].innerdisjunct[0]: 89}
bigm.apply_to(m, bigM=bigms)
- (src, key) = bigm.get_m_value_src(m.disjunct[1].innerdisjunct[0].c)
- self.assertIs(src, bigms)
- self.assertIs(key, m.disjunct[1].innerdisjunct[0])
- (src, key) = bigm.get_m_value_src(m.disjunct[1].innerdisjunct[1].c)
- self.assertEqual(src, -5)
- self.assertIsNone(key)
- (src, key) = bigm.get_m_value_src(m.disjunct[0].c)
- self.assertEqual(src, -11)
- self.assertEqual(key, 7)
- (src, key) = bigm.get_m_value_src(m.disjunct[1].c)
- self.assertIsNone(src)
- self.assertEqual(key, 21)
- (src, key) = bigm.get_m_value_src(m.simpledisjunct.innerdisjunct0.c)
- self.assertIs(src, m.simpledisjunct.BigM)
- self.assertIs(key, m.simpledisjunct.innerdisjunct0.c)
- (src, key) = bigm.get_m_value_src(m.simpledisjunct.innerdisjunct1.c)
- self.assertIs(src, m.simpledisjunct.BigM)
- self.assertIsNone(key)
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(
+ m.disjunct[1].innerdisjunct[0].c)
+ self.assertIs(l_src, bigms)
+ self.assertIs(u_src, bigms)
+ self.assertIs(l_key, m.disjunct[1].innerdisjunct[0])
+ self.assertIs(u_key, m.disjunct[1].innerdisjunct[0])
+ self.assertEqual(l_val, -89)
+ self.assertEqual(u_val, 89)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(
+ m.disjunct[1].innerdisjunct[1].c)
+ self.assertIsNone(l_src)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -5)
+ self.assertIsNone(u_val)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.disjunct[0].c)
+ self.assertIsNone(l_src)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -11)
+ self.assertEqual(u_val, 7)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(m.disjunct[1].c)
+ self.assertIsNone(l_src)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 21)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(
+ m.simpledisjunct.innerdisjunct0.c)
+ self.assertIsNone(l_src)
+ self.assertIs(u_src, m.simpledisjunct.BigM)
+ self.assertIsNone(l_key)
+ self.assertIs(u_key, m.simpledisjunct.innerdisjunct0.c)
+ self.assertIsNone(l_val)
+ self.assertEqual(u_val, 42)
+
+ ((l_val, l_src, l_key),
+ (u_val, u_src, u_key)) = bigm.get_M_value_src(
+ m.simpledisjunct.innerdisjunct1.c)
+ self.assertIs(l_src, m.simpledisjunct.BigM)
+ self.assertIsNone(u_src)
+ self.assertIsNone(l_key)
+ self.assertIsNone(u_key)
+ self.assertEqual(l_val, -58)
+ self.assertIsNone(u_val)
# many of the transformed constraints look like this, so can call this
# function to test them.
diff --git a/pyomo/gdp/tests/test_cuttingplane.py b/pyomo/gdp/tests/test_cuttingplane.py
index e8d4b449ad7..94ccbaf4ea7 100644
--- a/pyomo/gdp/tests/test_cuttingplane.py
+++ b/pyomo/gdp/tests/test_cuttingplane.py
@@ -10,17 +10,14 @@
import pyutilib.th as unittest
-from pyomo.environ import *
-from pyomo.gdp import *
+from pyomo.environ import ConcreteModel, Var, Constraint, Objective, Block, TransformationFactory
+from pyomo.gdp import Disjunct, Disjunction, GDP_Error
import pyomo.opt
from pyomo.repn import generate_standard_repn
-import random
from six import StringIO
-from nose.tools import set_trace
-
solvers = pyomo.opt.check_available_solvers('ipopt')
# TODO:
diff --git a/pyomo/gdp/tests/test_disjunct.py b/pyomo/gdp/tests/test_disjunct.py
index bf0ed065b73..332a68b5c69 100644
--- a/pyomo/gdp/tests/test_disjunct.py
+++ b/pyomo/gdp/tests/test_disjunct.py
@@ -10,10 +10,8 @@
import pyutilib.th as unittest
-from pyomo.core import ConcreteModel, Var, Constraint, Block, \
- TransformationFactory
-from pyomo.gdp import Disjunction, Disjunct, GDP_Error
-import pyomo.gdp.plugins.bigm
+from pyomo.core import ConcreteModel, Var, Constraint
+from pyomo.gdp import Disjunction, Disjunct
from six import iterkeys
diff --git a/pyomo/gdp/tests/test_fix_disjuncts.py b/pyomo/gdp/tests/test_fix_disjuncts.py
index eaa01fd58d1..dab265c4f3e 100644
--- a/pyomo/gdp/tests/test_fix_disjuncts.py
+++ b/pyomo/gdp/tests/test_fix_disjuncts.py
@@ -1,9 +1,20 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+
# -*- coding: UTF-8 -*-
"""Tests disjunct fixing."""
import pyutilib.th as unittest
from pyomo.environ import (Block,
Constraint, ConcreteModel, TransformationFactory,
- RangeSet, NonNegativeReals)
+ NonNegativeReals)
from pyomo.gdp import Disjunct, Disjunction, GDP_Error
diff --git a/pyomo/gdp/tests/test_gdp.py b/pyomo/gdp/tests/test_gdp.py
index 86c4b4b7c89..1bbc2dcee5d 100644
--- a/pyomo/gdp/tests/test_gdp.py
+++ b/pyomo/gdp/tests/test_gdp.py
@@ -28,8 +28,7 @@
from pyomo.common.dependencies import yaml, yaml_available, yaml_load_args
import pyomo.opt
-import pyomo.scripting.pyomo_main as main
-from pyomo.environ import *
+from pyomo.environ import SolverFactory, TransformationFactory
from six import iteritems
diff --git a/pyomo/gdp/tests/test_gdp_reclassification_error.py b/pyomo/gdp/tests/test_gdp_reclassification_error.py
index 18a4419019a..3377f34fbce 100644
--- a/pyomo/gdp/tests/test_gdp_reclassification_error.py
+++ b/pyomo/gdp/tests/test_gdp_reclassification_error.py
@@ -1,6 +1,17 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as pe
-import pyomo.gdp as gdp
+
+import pyomo.environ as pyo
+from pyomo.gdp import Disjunct, Disjunction
from pyomo.gdp.util import check_model_algebraic
from pyomo.common.log import LoggingIntercept
import logging
@@ -9,13 +20,14 @@
class TestGDPReclassificationError(unittest.TestCase):
def test_disjunct_not_in_disjunction(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.d1 = gdp.Disjunct()
- m.d1.c = pe.Constraint(expr=m.x == 1)
- m.d2 = gdp.Disjunct()
- m.d2.c = pe.Constraint(expr=m.x == 0)
- pe.TransformationFactory('gdp.bigm').apply_to(m)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.d1 = Disjunct()
+ m.d1.c = pyo.Constraint(expr=m.x == 1)
+ m.d2 = Disjunct()
+ m.d2.c = pyo.Constraint(expr=m.x == 0)
+
+ pyo.TransformationFactory('gdp.bigm').apply_to(m)
log = StringIO()
with LoggingIntercept(log, 'pyomo.gdp', logging.WARNING):
check_model_algebraic(m)
@@ -23,15 +35,15 @@ def test_disjunct_not_in_disjunction(self):
'.*not found in any Disjunctions.*')
def test_disjunct_not_in_active_disjunction(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.d1 = gdp.Disjunct()
- m.d1.c = pe.Constraint(expr=m.x == 1)
- m.d2 = gdp.Disjunct()
- m.d2.c = pe.Constraint(expr=m.x == 0)
- m.disjunction = gdp.Disjunction(expr=[m.d1, m.d2])
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.d1 = Disjunct()
+ m.d1.c = pyo.Constraint(expr=m.x == 1)
+ m.d2 = Disjunct()
+ m.d2.c = pyo.Constraint(expr=m.x == 0)
+ m.disjunction = Disjunction(expr=[m.d1, m.d2])
m.disjunction.deactivate()
- pe.TransformationFactory('gdp.bigm').apply_to(m)
+ pyo.TransformationFactory('gdp.bigm').apply_to(m)
log = StringIO()
with LoggingIntercept(log, 'pyomo.gdp', logging.WARNING):
check_model_algebraic(m)
diff --git a/pyomo/gdp/tests/test_hull.py b/pyomo/gdp/tests/test_hull.py
index 4aa852754d8..8d05d62040d 100644
--- a/pyomo/gdp/tests/test_hull.py
+++ b/pyomo/gdp/tests/test_hull.py
@@ -12,11 +12,10 @@
from pyomo.common.log import LoggingIntercept
import logging
-from pyomo.environ import *
-from pyomo.core.base import constraint
+from pyomo.environ import TransformationFactory, Block, Set, Constraint, Var, RealSet, ComponentMap, value, log, ConcreteModel, Any, Suffix, SolverFactory
from pyomo.repn import generate_standard_repn
-from pyomo.gdp import *
+from pyomo.gdp import Disjunct, Disjunction, GDP_Error
import pyomo.gdp.tests.models as models
import pyomo.gdp.tests.common_tests as ct
@@ -25,7 +24,7 @@
'glpk','cbc','gurobi','cplex')
import random
-from six import iteritems, iterkeys, StringIO
+from six import iteritems, StringIO
EPS = TransformationFactory('gdp.hull').CONFIG.EPS
diff --git a/pyomo/gdp/tests/test_reclassify.py b/pyomo/gdp/tests/test_reclassify.py
index 99c456e16da..7356d7918af 100644
--- a/pyomo/gdp/tests/test_reclassify.py
+++ b/pyomo/gdp/tests/test_reclassify.py
@@ -3,8 +3,6 @@
import pyutilib.th as unittest
from pyomo.core import (Block, ConcreteModel, TransformationFactory, RangeSet, Constraint, Var)
from pyomo.gdp import Disjunct, Disjunction, GDP_Error
-from pyomo.gdp.plugins.gdp_var_mover import HACK_GDP_Disjunct_Reclassifier
-from pyomo.gdp.plugins import bigm
class TestDisjunctReclassify(unittest.TestCase):
diff --git a/pyomo/gdp/util.py b/pyomo/gdp/util.py
index 97544e51f76..2c9e6d098d0 100644
--- a/pyomo/gdp/util.py
+++ b/pyomo/gdp/util.py
@@ -8,20 +8,15 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from six import string_types
-
import pyomo.core.expr.current as EXPR
-from pyomo.core.expr.numvalue import nonpyomo_leaf_types, native_numeric_types
from pyomo.gdp import GDP_Error, Disjunction
from pyomo.gdp.disjunct import _DisjunctData, Disjunct
-from copy import deepcopy
-from pyomo.core.base.component import _ComponentBase, ComponentUID
+from pyomo.core.base.component import _ComponentBase
+
from pyomo.core import Block, TraversalStrategy
from pyomo.opt import TerminationCondition, SolverStatus
-from pyomo.common.deprecation import deprecation_warning
from six import iterkeys
-import sys
from weakref import ref as weakref_ref
import logging
diff --git a/pyomo/kernel/__init__.py b/pyomo/kernel/__init__.py
index d0b296b2458..9db31cead1b 100644
--- a/pyomo/kernel/__init__.py
+++ b/pyomo/kernel/__init__.py
@@ -23,7 +23,36 @@
# Define the modeling namespace
#
from pyomo.common.collections import ComponentMap, ComponentSet
-from pyomo.core.expr import *
+from pyomo.core.expr import (
+ numvalue, numeric_expr, boolean_value, logical_expr, current,
+ calculus, symbol_map, expr_errors, visitor, sympy_tools, taylor_series,
+ expr_common, cnf_walker, template_expr
+)
+
+
+from pyomo.core.expr.numvalue import (
+ value, is_constant, is_fixed, is_variable_type,
+ is_potentially_variable, NumericValue, ZeroConstant,
+ native_numeric_types, native_types, polynomial_degree,
+)
+
+from pyomo.core.expr.boolean_value import BooleanValue
+
+from pyomo.core.expr.numeric_expr import linear_expression, nonlinear_expression
+
+from pyomo.core.expr.logical_expr import (land, lor, equivalent, exactly,
+ atleast, atmost, implies, lnot,
+ xor, inequality)
+
+from pyomo.core.expr.current import (
+ log, log10, sin, cos, tan, cosh, sinh, tanh,
+ asin, acos, atan, exp, sqrt, asinh, acosh,
+ atanh, ceil, floor,
+ Expr_if,
+)
+
+from pyomo.core.expr.calculus.derivatives import differentiate
+from pyomo.core.expr.taylor_series import taylor_series_expansion
import pyomo.core.kernel
from pyomo.kernel.util import (generate_names,
preorder_traversal,
diff --git a/pyomo/kernel/util.py b/pyomo/kernel/util.py
index f436896c937..c6e2405879d 100644
--- a/pyomo/kernel/util.py
+++ b/pyomo/kernel/util.py
@@ -20,7 +20,6 @@
_no_ctype,
_convert_ctype,
_convert_descend_into)
-from pyomo.core.kernel.block import block
import six
diff --git a/pyomo/mpec/complementarity.py b/pyomo/mpec/complementarity.py
index 72accd3be0e..0b2f0fa818a 100644
--- a/pyomo/mpec/complementarity.py
+++ b/pyomo/mpec/complementarity.py
@@ -8,18 +8,14 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import sys
-import inspect
-from six import iteritems, StringIO
+from six import iteritems
from collections import namedtuple
from pyomo.common.timing import ConstructionTimer
from pyomo.core.expr import current as EXPR
-from pyomo.core.expr.numvalue import ZeroConstant, _sub, native_numeric_types, as_numeric
-from pyomo.core import *
+from pyomo.core.expr.numvalue import ZeroConstant, native_numeric_types, as_numeric
+from pyomo.core import Constraint, Var, Block, Set
from pyomo.core.base.plugin import ModelComponentFactory
-from pyomo.core.base.numvalue import ZeroConstant, _sub
-from pyomo.core.base.misc import apply_indexed_rule, tabular_writer
from pyomo.core.base.block import _BlockData
from pyomo.core.base.util import (
disable_methods, Initializer, IndexedCallInitializer, CountedCallInitializer
diff --git a/pyomo/mpec/plugins/mpec2.py b/pyomo/mpec/plugins/mpec2.py
index 84c69765ab0..40d8b3875be 100644
--- a/pyomo/mpec/plugins/mpec2.py
+++ b/pyomo/mpec/plugins/mpec2.py
@@ -33,7 +33,6 @@ def __init__(self):
super(MPEC2_Transformation, self).__init__()
def _apply_to(self, instance, **kwds):
- options = kwds.pop('options', {})
#
# Setup transformation data
#
diff --git a/pyomo/mpec/plugins/mpec3.py b/pyomo/mpec/plugins/mpec3.py
index 92930fe7eb8..adef87ce994 100644
--- a/pyomo/mpec/plugins/mpec3.py
+++ b/pyomo/mpec/plugins/mpec3.py
@@ -12,7 +12,6 @@
from pyomo.core.base import (Transformation,
TransformationFactory,
- Constraint,
Block,
SortComponents)
from pyomo.mpec.complementarity import Complementarity
@@ -35,7 +34,6 @@ def __init__(self):
super(MPEC3_Transformation, self).__init__()
def _apply_to(self, instance, **kwds):
- options = kwds.pop('options', {})
#
# Iterate over the model finding Complementarity components
#
diff --git a/pyomo/mpec/plugins/mpec4.py b/pyomo/mpec/plugins/mpec4.py
index a6aa7f0b57e..7b2b924b6c3 100644
--- a/pyomo/mpec/plugins/mpec4.py
+++ b/pyomo/mpec/plugins/mpec4.py
@@ -36,7 +36,6 @@ def __init__(self):
super(MPEC4_Transformation, self).__init__()
def _apply_to(self, instance, **kwds):
- options = kwds.pop('options', {})
#
# Find the free variables
#
@@ -55,7 +54,6 @@ def _apply_to(self, instance, **kwds):
for cobj in instance.component_objects(Complementarity, active=True,
descend_into=(Block, Disjunct),
sort=SortComponents.deterministic):
- bdata = cobj.parent_block()
cobjs.append(cobj)
for index in sorted(iterkeys(cobj)):
_cdata = cobj[index]
diff --git a/pyomo/mpec/plugins/pathampl.py b/pyomo/mpec/plugins/pathampl.py
index d9023ef03a4..4a5f573b2da 100644
--- a/pyomo/mpec/plugins/pathampl.py
+++ b/pyomo/mpec/plugins/pathampl.py
@@ -9,16 +9,11 @@
# ___________________________________________________________________________
import logging
-import os
-import six
-import pyutilib.services
-import pyutilib.misc
+from pyutilib.misc import Options
from pyomo.opt.base.solvers import SolverFactory
-from pyomo.opt.base import *
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.common import Executable
from pyomo.solvers.plugins.solvers.ASL import ASL
logger = logging.getLogger('pyomo.solvers')
@@ -38,11 +33,11 @@ def __init__(self, **kwds):
#
# Define solver capabilities, which default to 'None'
#
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
def _default_executable(self):
- executable = pyomo.common.Executable("pathampl")
+ executable = Executable("pathampl")
if not executable: #pragma:nocover
logger.warning("Could not locate the 'pathampl' executable, "
"which is required for solver %s" % self.name)
diff --git a/pyomo/mpec/tests/test_complementarity.py b/pyomo/mpec/tests/test_complementarity.py
index d25b1cb04e5..3e06b654eaa 100644
--- a/pyomo/mpec/tests/test_complementarity.py
+++ b/pyomo/mpec/tests/test_complementarity.py
@@ -23,7 +23,7 @@
from pyutilib.misc import setup_redirect, reset_redirect
from pyomo.opt import ProblemFormat
-from pyomo.core import *
+from pyomo.core import ConcreteModel, Var, Constraint, TransformationFactory, Objective, Block, inequality
from pyomo.mpec import Complementarity, complements, ComplementarityList
from pyomo.gdp import Disjunct, Disjunction
diff --git a/pyomo/mpec/tests/test_minlp.py b/pyomo/mpec/tests/test_minlp.py
index 0f66f765d00..fd46233fd78 100644
--- a/pyomo/mpec/tests/test_minlp.py
+++ b/pyomo/mpec/tests/test_minlp.py
@@ -12,7 +12,6 @@
# Test the mpec_minlp solver
#
-import sys
import os
from os.path import abspath, dirname, normpath, join
currdir = dirname(abspath(__file__))
@@ -24,7 +23,6 @@
import pyomo.opt
import pyomo.scripting.pyomo_main as pyomo_main
from pyomo.scripting.util import cleanup
-from pyomo.environ import *
from six import iteritems
diff --git a/pyomo/mpec/tests/test_nlp.py b/pyomo/mpec/tests/test_nlp.py
index 0ec56c616a0..6db9f206ee3 100644
--- a/pyomo/mpec/tests/test_nlp.py
+++ b/pyomo/mpec/tests/test_nlp.py
@@ -12,11 +12,10 @@
# Test the mpec_nlp solver
#
-import sys
import os
from os.path import abspath, dirname, normpath, join
currdir = dirname(abspath(__file__))
-exdir = normpath(join(currdir,'..','..','..','examples','mpec'))
+exdir = normpath(join(currdir, '..', '..', '..', 'examples', 'mpec'))
import pyutilib.th as unittest
@@ -24,12 +23,12 @@
import pyomo.opt
import pyomo.scripting.pyomo_main as pyomo_main
from pyomo.scripting.util import cleanup
-from pyomo.environ import *
from six import iteritems
solvers = pyomo.opt.check_available_solvers('ipopt')
+
class CommonTests:
solve = True
diff --git a/pyomo/mpec/tests/test_path.py b/pyomo/mpec/tests/test_path.py
index 37484d6bb62..58bee669d0a 100644
--- a/pyomo/mpec/tests/test_path.py
+++ b/pyomo/mpec/tests/test_path.py
@@ -12,7 +12,6 @@
# Test the path solver
#
-import sys
import os
from os.path import abspath, dirname, normpath, join
currdir = dirname(abspath(__file__))
@@ -25,7 +24,6 @@
import pyomo.opt
import pyomo.scripting.pyomo_main as pyomo_main
from pyomo.scripting.util import cleanup
-from pyomo.environ import *
from six import iteritems
diff --git a/pyomo/neos/kestrel.py b/pyomo/neos/kestrel.py
index 3db7f7640fb..1fc6d805215 100644
--- a/pyomo/neos/kestrel.py
+++ b/pyomo/neos/kestrel.py
@@ -316,7 +316,7 @@ def formXML(self,stub):
if six.PY2:
nl_string = base64.encodestring(zipped_nl_file.getvalue())
else:
- nl_string = (base64.encodestring(zipped_nl_file.getvalue())).decode('utf-8')
+ nl_string = (base64.encodebytes(zipped_nl_file.getvalue())).decode('utf-8')
xml = """
kestrel
diff --git a/pyomo/neos/plugins/NEOS.py b/pyomo/neos/plugins/NEOS.py
index 6678658f2af..56731a505bc 100644
--- a/pyomo/neos/plugins/NEOS.py
+++ b/pyomo/neos/plugins/NEOS.py
@@ -10,12 +10,11 @@
import logging
-import pyutilib.misc
-import pyutilib.services
+from pyutilib.misc import Bunch
+from pyutilib.services import TempfileManager
-from pyomo.opt.base import *
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.opt.base import SolverFactory, ProblemFormat, ResultsFormat
+from pyomo.opt.solver import SystemCallSolver
logger = logging.getLogger('pyomo.neos')
@@ -38,10 +37,10 @@ def create_command_line(self, executable, problem_files):
populated by NEOS.
"""
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix=".neos.log")
if self._soln_file is None:
- self._soln_file = pyutilib.services.TempfileManager.\
+ self._soln_file = TempfileManager.\
create_tempfile(suffix=".neos.sol")
self._results_file = self._soln_file
@@ -55,7 +54,7 @@ def create_command_line(self, executable, problem_files):
if self._problem_files is not []:
logger.info("Solver problem files: %s" % (self._problem_files,))
- return pyutilib.misc.Bunch(cmd="", log_file=self._log_file, env="")
+ return Bunch(cmd="", log_file=self._log_file, env="")
def _default_executable(self):
return True
diff --git a/pyomo/neos/plugins/kestrel_plugin.py b/pyomo/neos/plugins/kestrel_plugin.py
index 2146bf63569..8a8c0681f6c 100644
--- a/pyomo/neos/plugins/kestrel_plugin.py
+++ b/pyomo/neos/plugins/kestrel_plugin.py
@@ -15,11 +15,10 @@
from pyomo.common.dependencies import attempt_import
from pyomo.opt import SolverFactory, SolverManagerFactory, OptSolver
-from pyomo.opt.parallel.manager import ActionManagerError
+from pyomo.opt.parallel.manager import ActionManagerError, ActionStatus
from pyomo.opt.parallel.async_solver import (
- AsynchronousSolverManager, ActionStatus
+ AsynchronousSolverManager
)
-from pyomo.opt.base import OptSolver
from pyomo.core.base import Block
import pyomo.neos.kestrel
diff --git a/pyomo/neos/tests/t1.py b/pyomo/neos/tests/t1.py
index 2662b8af625..9f71c7c3bb4 100644
--- a/pyomo/neos/tests/t1.py
+++ b/pyomo/neos/tests/t1.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint, maximize
M = ConcreteModel()
M.x = Var(bounds=(0,1))
diff --git a/pyomo/neos/tests/test_neos.py b/pyomo/neos/tests/test_neos.py
index 3fbd7b04d13..8925b08d6cb 100644
--- a/pyomo/neos/tests/test_neos.py
+++ b/pyomo/neos/tests/test_neos.py
@@ -12,7 +12,7 @@
#
import os
-from os.path import abspath, dirname, join
+from os.path import abspath, dirname
currdir = dirname(abspath(__file__))
import pyutilib.th as unittest
@@ -24,8 +24,6 @@
import pyomo.environ as pyo
-from six import iteritems
-
neos_available = False
try:
# Attempt a connection to NEOS. Any failure will result in skipping
diff --git a/pyomo/network/__init__.py b/pyomo/network/__init__.py
index 20988328875..d7972d22f58 100644
--- a/pyomo/network/__init__.py
+++ b/pyomo/network/__init__.py
@@ -8,6 +8,6 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.network.arc import *
-from pyomo.network.port import *
-from pyomo.network.decomposition import *
+from pyomo.network.arc import Arc
+from pyomo.network.port import Port
+from pyomo.network.decomposition import SequentialDecomposition
diff --git a/pyomo/network/arc.py b/pyomo/network/arc.py
index 0de604722e7..d30e06bf801 100644
--- a/pyomo/network/arc.py
+++ b/pyomo/network/arc.py
@@ -15,8 +15,7 @@
from pyomo.core.base.indexed_component import (ActiveIndexedComponent,
UnindexedComponent_set)
from pyomo.core.base.misc import apply_indexed_rule
-from pyomo.core.base.plugin import (ModelComponentFactory,
- IPyomoScriptModifyInstance, TransformationFactory)
+from pyomo.core.base.plugin import ModelComponentFactory
from pyomo.common.timing import ConstructionTimer
from six import iteritems
from weakref import ref as weakref_ref
diff --git a/pyomo/network/decomposition.py b/pyomo/network/decomposition.py
index 8c093a07ea2..c81fb9a0b69 100644
--- a/pyomo/network/decomposition.py
+++ b/pyomo/network/decomposition.py
@@ -18,8 +18,8 @@
from pyomo.core.expr.current import identify_variables
from pyomo.repn import generate_standard_repn
from pyutilib.misc import Options
-import copy, logging, time
-from six import iteritems, itervalues
+import logging, time
+from six import iteritems
from pyomo.common.dependencies import (
networkx as nx, networkx_available,
diff --git a/pyomo/network/plugins/expand_arcs.py b/pyomo/network/plugins/expand_arcs.py
index 8b45da64deb..4044afca11a 100644
--- a/pyomo/network/plugins/expand_arcs.py
+++ b/pyomo/network/plugins/expand_arcs.py
@@ -11,13 +11,13 @@
import logging
logger = logging.getLogger('pyomo.network')
-from six import next, iteritems, itervalues
+from six import iteritems, itervalues
from pyomo.common.modeling import unique_component_name
from pyomo.common.collections import ComponentMap, ComponentSet
from pyomo.core.base.indexed_component import UnindexedComponent_set
-from pyomo.core.base import Transformation, Var, Block, SortComponents, TransformationFactory
+from pyomo.core.base import Transformation, Block, SortComponents, TransformationFactory
from pyomo.network import Arc
from pyomo.network.util import replicate_var
@@ -72,7 +72,6 @@ def _collect_ports(self, instance):
matched_ports = ComponentMap()
for arc in instance.component_data_objects(**obj_iter_kwds):
- ports = ComponentSet(arc.ports)
ref = None
for p in arc.ports:
diff --git a/pyomo/network/port.py b/pyomo/network/port.py
index 0fe53893a8a..8af09cb7291 100644
--- a/pyomo/network/port.py
+++ b/pyomo/network/port.py
@@ -11,9 +11,10 @@
__all__ = [ 'Port' ]
import logging, sys
-from six import iteritems, itervalues
+from six import iteritems
from weakref import ref as weakref_ref
+from pyomo.common.collections import ComponentMap
from pyomo.common.timing import ConstructionTimer
from pyomo.common.modeling import unique_component_name
@@ -26,9 +27,7 @@
from pyomo.core.base.numvalue import as_numeric, value
from pyomo.core.expr.current import identify_variables
from pyomo.core.base.label import alphanum_label_from_name
-from pyomo.core.base.plugin import ModelComponentFactory, \
- IPyomoScriptModifyInstance, TransformationFactory
-from pyomo.common.collections import ComponentMap
+from pyomo.core.base.plugin import ModelComponentFactory
from pyomo.network.util import create_var, tighten_var_domain
diff --git a/pyomo/network/tests/test_arc.py b/pyomo/network/tests/test_arc.py
index e2964a81cac..a438d47a5bf 100644
--- a/pyomo/network/tests/test_arc.py
+++ b/pyomo/network/tests/test_arc.py
@@ -15,8 +15,8 @@
from six import StringIO
import logging
-from pyomo.environ import *
-from pyomo.network import *
+from pyomo.environ import ConcreteModel, AbstractModel, Var, Set, Constraint, RangeSet, NonNegativeReals, Reals, Binary, TransformationFactory, Block
+from pyomo.network import Arc, Port
class TestArc(unittest.TestCase):
diff --git a/pyomo/network/tests/test_decomposition.py b/pyomo/network/tests/test_decomposition.py
index 38aeaa634d5..dc18a4ddc8d 100644
--- a/pyomo/network/tests/test_decomposition.py
+++ b/pyomo/network/tests/test_decomposition.py
@@ -14,8 +14,8 @@
import pyutilib.th as unittest
from pyomo.common.dependencies import numpy_available, networkx_available
-from pyomo.environ import *
-from pyomo.network import *
+from pyomo.environ import SolverFactory, value, ConcreteModel, Set, Block, Var, TransformationFactory, Reference
+from pyomo.network import Port, SequentialDecomposition, Arc
from types import MethodType
import_available = numpy_available and networkx_available
diff --git a/pyomo/network/tests/test_port.py b/pyomo/network/tests/test_port.py
index 4054491ec17..caf70424f59 100644
--- a/pyomo/network/tests/test_port.py
+++ b/pyomo/network/tests/test_port.py
@@ -14,8 +14,8 @@
import pyutilib.th as unittest
from six import StringIO
-from pyomo.environ import *
-from pyomo.network import *
+from pyomo.environ import ConcreteModel, AbstractModel, Var, Set, NonNegativeReals, Binary, Reals, Integers, RangeSet
+from pyomo.network import Port, Arc
class TestPort(unittest.TestCase):
diff --git a/pyomo/opt/__init__.py b/pyomo/opt/__init__.py
index 6d46edea0c1..e1988d69dab 100644
--- a/pyomo/opt/__init__.py
+++ b/pyomo/opt/__init__.py
@@ -8,9 +8,37 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.opt.base import *
-from pyomo.opt.results import *
+import pyomo.opt.base.opt_config
import pyomo.opt.solver
-from pyomo.opt.problem import *
-from pyomo.opt.parallel import *
+
+from pyomo.opt.base import (
+ check_available_solvers, convert, convert_problem, error, formats,
+ guess_format, opt_config, solvers,
+ AbstractProblemWriter, AbstractResultsReader, BaseProblemConfig,
+ BranchDirection, ConverterError, OptSolver, ProblemConfigFactory,
+ ProblemFormat, ReaderFactory, ResultsFormat, SolverFactory,
+ UnknownSolver, WriterFactory,
+)
+
+from pyomo.opt.results import (
+ container, problem, solution,
+ ScalarData, ScalarType,
+ default_print_options,
+ ListContainer, MapContainer,
+ UndefinedData, undefined, ignore,
+ SolverStatus, TerminationCondition,
+ check_optimal_termination, assert_optimal_termination,
+ ProblemSense,
+ SolutionStatus, Solution, results_,
+ SolverResults
+)
+
+from pyomo.opt.problem import (
+ ampl, AmplModel
+)
+
+from pyomo.opt.parallel import (
+ pyro, manager, async_solver, local,
+ SolverManagerFactory, AsynchronousSolverManager
+)
diff --git a/pyomo/opt/base/__init__.py b/pyomo/opt/base/__init__.py
index 49d36bebed5..3b56aff8854 100644
--- a/pyomo/opt/base/__init__.py
+++ b/pyomo/opt/base/__init__.py
@@ -10,9 +10,16 @@
import pyomo.opt.base.opt_config
-from pyomo.opt.base.error import *
-from pyomo.opt.base.convert import *
-from pyomo.opt.base.solvers import *
-from pyomo.opt.base.results import *
-from pyomo.opt.base.problem import *
-from pyomo.opt.base.formats import *
+from pyomo.opt.base.error import ConverterError
+from pyomo.opt.base.convert import convert_problem
+from pyomo.opt.base.solvers import (
+ UnknownSolver, SolverFactory, check_available_solvers, OptSolver,
+)
+from pyomo.opt.base.results import ReaderFactory, AbstractResultsReader
+from pyomo.opt.base.problem import (
+ ProblemConfigFactory, BaseProblemConfig, AbstractProblemWriter,
+ BranchDirection, WriterFactory
+)
+from pyomo.opt.base.formats import (
+ ProblemFormat, ResultsFormat, guess_format,
+)
diff --git a/pyomo/opt/base/solvers.py b/pyomo/opt/base/solvers.py
index 85378114d23..2ff919d2b3e 100644
--- a/pyomo/opt/base/solvers.py
+++ b/pyomo/opt/base/solvers.py
@@ -14,16 +14,14 @@
'check_available_solvers')
import re
-import os
import sys
import time
import logging
from pyutilib.misc.config import ConfigBlock, ConfigList, ConfigValue
from pyomo.common import Factory
-import pyutilib.common
-import pyutilib.misc
-import pyutilib.services
+from pyutilib.common import ApplicationError
+from pyutilib.misc import Options, quote_split
from pyomo.opt.base.problem import ProblemConfigFactory
from pyomo.opt.base.convert import convert_problem
@@ -95,8 +93,7 @@ def __exit__(self, t, v, traceback):
def available(self, exception_flag=True):
"""Determine if this optimizer is available."""
if exception_flag:
- from pyutilib.common import ApplicationError
- raise pyutilib.common.ApplicationError("Solver (%s) not available" % str(self.name))
+ raise ApplicationError("Solver (%s) not available" % str(self.name))
return False
def warm_start_capable(self):
@@ -343,7 +340,7 @@ def __init__(self, **kwds):
# through the solve command. Everything else is reset inside
# presolve
#
- self.options = pyutilib.misc.Options()
+ self.options = Options()
if 'options' in kwds and not kwds['options'] is None:
for key in kwds['options']:
setattr(self.options, key, kwds['options'][key])
@@ -392,7 +389,7 @@ def __init__(self, **kwds):
# We define no capabilities for the generic solver; base
# classes must override this
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
@staticmethod
def _options_string_to_dict(istr):
@@ -402,7 +399,7 @@ def _options_string_to_dict(istr):
return ans
if istr[0] == "'" or istr[0] == '"':
istr = eval(istr)
- tokens = pyutilib.misc.quote_split('[ ]+',istr)
+ tokens = quote_split('[ ]+',istr)
for token in tokens:
index = token.find('=')
if index == -1:
@@ -560,7 +557,7 @@ def solve(self, *args, **kwds):
orig_options = self.options
- self.options = pyutilib.misc.Options()
+ self.options = Options()
self.options.update(orig_options)
self.options.update(kwds.pop('options', {}))
self.options.update(
@@ -596,7 +593,7 @@ def solve(self, *args, **kwds):
"See the solver log above for diagnostic information." )
elif hasattr(_status, 'log') and _status.log:
logger.error("Solver log:\n" + str(_status.log))
- raise pyutilib.common.ApplicationError(
+ raise ApplicationError(
"Solver (%s) did not exit normally" % self.name)
solve_completion_time = time.time()
if self._report_timing:
@@ -787,7 +784,7 @@ def fn(solver, model):
a Pyomo model instance object.
"""
if not self._allow_callbacks:
- raise pyutilib.common.ApplicationError(
+ raise ApplicationError(
"Callbacks disabled for solver %s" % self.name)
if callback_fn is None:
if name in self._callback:
diff --git a/pyomo/opt/blackbox/__init__.py b/pyomo/opt/blackbox/__init__.py
index 4749cab5f7c..14b59881e8d 100644
--- a/pyomo/opt/blackbox/__init__.py
+++ b/pyomo/opt/blackbox/__init__.py
@@ -8,6 +8,8 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.opt.blackbox.point import *
-from pyomo.opt.blackbox.problem import *
+from pyomo.opt.blackbox.point import MixedIntVars, RealVars
+from pyomo.opt.blackbox.problem import (BlackBoxOptProblemIOFactory,
+ response_enum, OptProblem,
+ MixedIntOptProblem, RealOptProblem)
import pyomo.opt.blackbox.solver
diff --git a/pyomo/opt/blackbox/solver.py b/pyomo/opt/blackbox/solver.py
index f8c57c8c63f..1c01e3f62cf 100644
--- a/pyomo/opt/blackbox/solver.py
+++ b/pyomo/opt/blackbox/solver.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.opt.base import *
+from pyomo.opt.base import OptSolver, ProblemFormat, ResultsFormat
class COLINSolver(OptSolver):
diff --git a/pyomo/opt/parallel/__init__.py b/pyomo/opt/parallel/__init__.py
index 8518e0078f6..5fe03e3ed04 100644
--- a/pyomo/opt/parallel/__init__.py
+++ b/pyomo/opt/parallel/__init__.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.opt.parallel.async_solver import *
+from pyomo.opt.parallel.async_solver import (Factory, AsynchronousActionManager, SolverManagerFactory, AsynchronousSolverManager)
import pyomo.opt.parallel.manager
import pyomo.opt.parallel.pyro
import pyomo.opt.parallel.local
diff --git a/pyomo/opt/parallel/async_solver.py b/pyomo/opt/parallel/async_solver.py
index f006b02a71b..cb1e28d1b4c 100644
--- a/pyomo/opt/parallel/async_solver.py
+++ b/pyomo/opt/parallel/async_solver.py
@@ -12,7 +12,7 @@
__all__ = ['AsynchronousSolverManager', 'SolverManagerFactory']
from pyomo.common import Factory
-from pyomo.opt.parallel.manager import *
+from pyomo.opt.parallel.manager import AsynchronousActionManager
diff --git a/pyomo/opt/parallel/local.py b/pyomo/opt/parallel/local.py
index 442dc1d42db..b667eefacfa 100644
--- a/pyomo/opt/parallel/local.py
+++ b/pyomo/opt/parallel/local.py
@@ -24,7 +24,6 @@
ActionHandle)
from pyomo.opt.parallel.async_solver import AsynchronousSolverManager, SolverManagerFactory
-import six
from six import string_types
diff --git a/pyomo/opt/parallel/pyro.py b/pyomo/opt/parallel/pyro.py
index b9128372d58..8428a3a36f1 100644
--- a/pyomo/opt/parallel/pyro.py
+++ b/pyomo/opt/parallel/pyro.py
@@ -18,8 +18,6 @@
from pyomo.common.dependencies import attempt_import
from pyomo.opt.parallel.manager import \
(AsynchronousActionManager,
- ActionManagerError,
- ActionHandle,
ActionStatus)
pyu_pyro = attempt_import('pyutilib.pyro', alt_names=['pyu_pyro'])[0]
diff --git a/pyomo/opt/plugins/problem_config.py b/pyomo/opt/plugins/problem_config.py
index 9e67a5216d6..9204fdb62d0 100644
--- a/pyomo/opt/plugins/problem_config.py
+++ b/pyomo/opt/plugins/problem_config.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
from pyutilib.misc.config import ConfigBlock, ConfigList, ConfigValue
-from pyomo.opt.base.problem import *
+from pyomo.opt.base.problem import ProblemConfigFactory, BaseProblemConfig
@ProblemConfigFactory.register('default')
diff --git a/pyomo/opt/plugins/sol.py b/pyomo/opt/plugins/sol.py
index 19873008268..889c7b97b66 100644
--- a/pyomo/opt/plugins/sol.py
+++ b/pyomo/opt/plugins/sol.py
@@ -200,8 +200,8 @@ def _load(self, fin, res, soln, suffixes):
if (unmasked_kind & 4) == 4:
convert_function = float
nvalues = int(line[2])
- namelen = int(line[3])
- tablen = int(line[4])
+ # namelen = int(line[3])
+ # tablen = int(line[4])
tabline = int(line[5])
suffix_name = fin.readline().strip()
if any(re.match(suf,suffix_name) for suf in suffixes):
diff --git a/pyomo/opt/problem/__init__.py b/pyomo/opt/problem/__init__.py
index 5b52c12dbc2..2953259e21e 100644
--- a/pyomo/opt/problem/__init__.py
+++ b/pyomo/opt/problem/__init__.py
@@ -8,4 +8,5 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.opt.problem.ampl import *
+from pyomo.opt.problem.ampl import (ProblemFormat, convert_problem,
+ guess_format, AmplModel)
diff --git a/pyomo/opt/results/__init__.py b/pyomo/opt/results/__init__.py
index 0d5a66eb363..696711e8bb4 100644
--- a/pyomo/opt/results/__init__.py
+++ b/pyomo/opt/results/__init__.py
@@ -8,8 +8,10 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-#from old_results import *
-from pyomo.opt.results.container import *
+from pyomo.opt.results.container import (ScalarData, ScalarType,
+ default_print_options, strict,
+ ListContainer, MapContainer,
+ UndefinedData, undefined, ignore)
import pyomo.opt.results.problem
from pyomo.opt.results.solver import SolverStatus, TerminationCondition, \
check_optimal_termination, assert_optimal_termination
diff --git a/pyomo/opt/results/container.py b/pyomo/opt/results/container.py
index 1ff70f9c041..7d52354320a 100644
--- a/pyomo/opt/results/container.py
+++ b/pyomo/opt/results/container.py
@@ -11,13 +11,13 @@
__all__ = ['UndefinedData', 'undefined', 'ignore', 'ScalarData', 'ListContainer', 'MapContainer', 'default_print_options', 'ScalarType']
import copy
-import math
-import pyutilib.math
+from pyutilib.math import infinity
from pyutilib.misc import Bunch
import enum
-from six import iterkeys, itervalues, iteritems, advance_iterator, StringIO
+from six import StringIO
from six.moves import xrange
+
try:
unicode
except NameError:
@@ -106,9 +106,9 @@ def pprint(self, ostream, option, prefix="", repn=None):
value = self.yaml_fix(self.get_value())
- if value is pyutilib.math.infinity:
+ if value is infinity:
value = '.inf'
- elif value is - pyutilib.math.infinity:
+ elif value is - infinity:
value = '-.inf'
if not option.schema and self.description is None and self.units is None:
diff --git a/pyomo/opt/results/problem.py b/pyomo/opt/results/problem.py
index 7dc0f3a5eae..014f8a552bf 100644
--- a/pyomo/opt/results/problem.py
+++ b/pyomo/opt/results/problem.py
@@ -11,7 +11,7 @@
__all__ = ['ProblemInformation', 'ProblemSense']
import enum
-from pyomo.opt.results.container import *
+from pyomo.opt.results.container import MapContainer
class ProblemSense(str, enum.Enum):
unknown='unknown'
diff --git a/pyomo/opt/results/solution.py b/pyomo/opt/results/solution.py
index 86224c53dcd..5bd8506c621 100644
--- a/pyomo/opt/results/solution.py
+++ b/pyomo/opt/results/solution.py
@@ -15,12 +15,12 @@
from collections import OrderedDict
except:
from ordereddict import OrderedDict
-from six import iterkeys, advance_iterator, itervalues, iteritems
+from six import iterkeys, iteritems
from six.moves import xrange
from pyutilib.misc import Bunch
import enum
from pyutilib.math import as_number
-from pyomo.opt.results.container import *
+from pyomo.opt.results.container import MapContainer, ListContainer, ignore
default_print_options = Bunch(schema=False,
sparse=True,
diff --git a/pyomo/opt/results/solver.py b/pyomo/opt/results/solver.py
index 6dbf226faaf..8904a9bd082 100644
--- a/pyomo/opt/results/solver.py
+++ b/pyomo/opt/results/solver.py
@@ -81,6 +81,50 @@ class TerminationCondition(str, enum.Enum):
def __str__(self):
return self.value
+ @staticmethod
+ def to_solver_status(tc):
+ """Maps a TerminationCondition to SolverStatus based on enum value
+
+ Parameters
+ ----------
+ tc: TerminationCondition
+
+ Returns
+ -------
+ SolverStatus
+ """
+ if tc in {
+ TerminationCondition.maxTimeLimit,
+ TerminationCondition.maxIterations,
+ TerminationCondition.minFunctionValue,
+ TerminationCondition.minStepLength,
+ TerminationCondition.globallyOptimal,
+ TerminationCondition.locallyOptimal,
+ TerminationCondition.feasible,
+ TerminationCondition.optimal,
+ TerminationCondition.maxEvaluations,
+ TerminationCondition.other }:
+ return SolverStatus.ok
+ if tc in {
+ TerminationCondition.unbounded,
+ TerminationCondition.infeasible,
+ TerminationCondition.infeasibleOrUnbounded,
+ TerminationCondition.invalidProblem,
+ TerminationCondition.intermediateNonInteger,
+ TerminationCondition.noSolution }:
+ return SolverStatus.warning
+ if tc in {
+ TerminationCondition.solverFailure,
+ TerminationCondition.internalSolverError,
+ TerminationCondition.error }:
+ return SolverStatus.error
+ if tc in {
+ TerminationCondition.userInterrupt,
+ TerminationCondition.resourceInterrupt,
+ TerminationCondition.licensingProblems }:
+ return SolverStatus.aborted
+ return SolverStatus.unknown
+
def check_optimal_termination(results):
"""
diff --git a/pyomo/opt/solver/__init__.py b/pyomo/opt/solver/__init__.py
index 67b09e8aa67..4bbe1283d53 100644
--- a/pyomo/opt/solver/__init__.py
+++ b/pyomo/opt/solver/__init__.py
@@ -8,5 +8,6 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.opt.solver.shellcmd import *
-from pyomo.opt.solver.ilmcmd import *
+from pyomo.opt.solver.shellcmd import (ResultsFormat, OptSolver, SolverStatus,
+ SolverResults, SystemCallSolver)
+from pyomo.opt.solver.ilmcmd import ILMLicensedSystemCallSolver
diff --git a/pyomo/opt/solver/shellcmd.py b/pyomo/opt/solver/shellcmd.py
index ef824d794cd..bb69b623aee 100644
--- a/pyomo/opt/solver/shellcmd.py
+++ b/pyomo/opt/solver/shellcmd.py
@@ -15,15 +15,14 @@
import time
import logging
-import pyutilib.misc
from pyutilib.common import ApplicationError, WindowsError
from pyutilib.misc import Bunch
from pyutilib.services import TempfileManager
from pyutilib.subprocess import run
import pyomo.common
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import *
+from pyomo.opt.base import ResultsFormat
+from pyomo.opt.base.solvers import OptSolver
from pyomo.opt.results import SolverStatus, SolverResults
logger = logging.getLogger('pyomo.opt')
diff --git a/pyomo/opt/testing/__init__.py b/pyomo/opt/testing/__init__.py
index b0840150dd9..6c0dde2519d 100644
--- a/pyomo/opt/testing/__init__.py
+++ b/pyomo/opt/testing/__init__.py
@@ -8,4 +8,4 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.opt.testing.pyunit import *
+from pyomo.opt.testing.pyunit import (_failIfPyomoResultsDiffer, TestCase)
\ No newline at end of file
diff --git a/pyomo/opt/testing/pyunit.py b/pyomo/opt/testing/pyunit.py
index de61b8dc3f0..a08f76c4017 100644
--- a/pyomo/opt/testing/pyunit.py
+++ b/pyomo/opt/testing/pyunit.py
@@ -38,7 +38,7 @@ def _failIfPyomoResultsDiffer(self, cmd=None, baseline=None, cwd=None):
if output[0] != 0:
self.fail("Command terminated with nonzero status: '%s'" % cmd)
- results = extract_results( re.split('\n',output[1]) )
+ results = extract_results(re.split('\n',output[1]))
try:
compare_results(results, baseline)
except IOError:
diff --git a/pyomo/pysp/annotations.py b/pyomo/pysp/annotations.py
index 0395e0c981f..04e8aec6a02 100644
--- a/pyomo/pysp/annotations.py
+++ b/pyomo/pysp/annotations.py
@@ -18,7 +18,6 @@
from pyomo.core.base.objective import Objective, _ObjectiveData
from pyomo.core.base.block import Block, _BlockData
-import pyomo.pysp
logger = logging.getLogger('pyomo.pysp')
def locate_annotations(model, annotation_type, max_allowed=None):
diff --git a/pyomo/pysp/bbph/brancher.py b/pyomo/pysp/bbph/brancher.py
index 4f489aebe1a..a63848fc38a 100644
--- a/pyomo/pysp/bbph/brancher.py
+++ b/pyomo/pysp/bbph/brancher.py
@@ -7,20 +7,17 @@
outputfilename = "brancherout.p"
-import sys
import time
import os
import pickle # so we can send index across with its type (I hope)
import pyomo.common.plugin
-from pyomo.core import *
from pyomo.pysp import phextension
-from pyomo.pysp.phutils import *
-from pyomo.pysp.generators import \
- scenario_tree_node_variables_generator_noinstances
import pyomo.solvers.plugins.smanager.phpyro
from pyomo.pysp import phsolverserverutils
+from six import iteritems
+
thisfile = os.path.abspath(__file__)
#
diff --git a/pyomo/pysp/benders.py b/pyomo/pysp/benders.py
index 71a9ded9d25..0cc0b165087 100644
--- a/pyomo/pysp/benders.py
+++ b/pyomo/pysp/benders.py
@@ -9,8 +9,54 @@
# ___________________________________________________________________________
from pyomo.common import pyomo_command
-from pyomo.pysp.solvers.benders import *
+from pyomo.opt import (SolverFactory,
+ TerminationCondition,
+ undefined)
+from pyomo.core import (value, minimize, Set,
+ Objective, SOSConstraint,
+ Constraint, Var, RangeSet,
+ Expression, Suffix, Reals, Param)
+from pyomo.core.base.constraint import _GeneralConstraintData
+from pyomo.core.beta.list_objects import XConstraintList
+from pyomo.pysp.util.configured_object import PySPConfiguredObject
+from pyomo.pysp.util.config import (PySPConfigValue,
+ PySPConfigBlock,
+ safe_register_common_option,
+ safe_declare_common_option,
+ safe_declare_unique_option,
+ _domain_percent,
+ _domain_nonnegative,
+ _domain_positive_integer,
+ _domain_must_be_str,
+ _domain_unit_interval,
+ _domain_tuple_of_str,
+ _domain_tuple_of_str_or_dict)
+from pyomo.pysp.util.misc import (parse_command_line,
+ launch_command)
+from pyomo.pysp.scenariotree.manager import \
+ (InvocationType,
+ ScenarioTreeManager,
+ ScenarioTreeManagerFactory)
+from pyomo.pysp.scenariotree.manager_solver import \
+ ScenarioTreeManagerSolverFactory
+from pyomo.pysp.phutils import find_active_objective
+from pyomo.pysp.ef import create_ef_instance
+from pyomo.pysp.solvers.spsolver import (SPSolver,
+ SPSolverResults,
+ SPSolverFactory)
+from pyomo.pysp.solvers.benders import (EXTERNAL_deactivate_rootnode_costs,
+ EXTERNAL_activate_rootnode_costs,
+ EXTERNAL_activate_fix_constraints,
+ EXTERNAL_deactivate_fix_constraints,
+ EXTERNAL_cleanup_from_benders,
+ EXTERNAL_initialize_for_benders,
+ EXTERNAL_update_fix_constraints,
+ EXTERNAL_collect_cut_data,
+ BendersOptimalityCut, BendersAlgorithm,
+ BendersSolver,
+ runbenders_register_options, runbenders,
+ main as b_main)
@pyomo_command('runbenders', 'Optimize with the Benders solver')
def Benders_main(args=None):
- return main(args=args)
+ return b_main(args=args)
diff --git a/pyomo/pysp/computeconf.py b/pyomo/pysp/computeconf.py
index 9bca1c0efad..a92663dd2df 100755
--- a/pyomo/pysp/computeconf.py
+++ b/pyomo/pysp/computeconf.py
@@ -15,9 +15,9 @@
import time
import traceback
-import pyutilib.common
+from pyutilib.common import ApplicationError
-from pyomo.core import *
+from pyomo.core import minimize
# this is a hack, in order to pick up the UndefinedData class. this is
# needed currently, as CPLEX is periodically barfing on cvar
# formulations, yielding an undefined gap. technically, the gap is
@@ -33,13 +33,10 @@
PHAlgorithmBuilder,
PHFromScratch,
PHCleanup)
-from pyomo.pysp.ef import (create_ef_instance,
- solve_ef)
from pyomo.pysp.ef_writer_script import ExtensiveFormAlgorithm
from pyomo.pysp.phutils import _OLD_OUTPUT
-import pyomo.pysp.phboundbase
-from six import iteritems, iterkeys, advance_iterator
+from six import iteritems, iterkeys
# to avoid the pain of user lookup of parameter in t-tables, we
# provide decent coverage automatically. feel free to add more
@@ -807,7 +804,7 @@ def main(args=None):
except IOError as str:
print("IO ERROR:")
print(str)
- except pyutilib.common.ApplicationError as str:
+ except ApplicationError as str:
print("APPLICATION ERROR:")
print(str)
except RuntimeError as str:
diff --git a/pyomo/pysp/convergence.py b/pyomo/pysp/convergence.py
index f2f5349f3fc..96e32035a72 100644
--- a/pyomo/pysp/convergence.py
+++ b/pyomo/pysp/convergence.py
@@ -14,7 +14,7 @@
from pyomo.pysp.generators import \
scenario_tree_node_variables_generator_noinstances
-from six import iteritems, iterkeys
+from six import iterkeys
#
# This module contains a hierarchy of convergence "computers" for PH
diff --git a/pyomo/pysp/convert/ddsip.py b/pyomo/pysp/convert/ddsip.py
index 9c71e1f14eb..2675ef02919 100644
--- a/pyomo/pysp/convert/ddsip.py
+++ b/pyomo/pysp/convert/ddsip.py
@@ -18,10 +18,7 @@
from pyomo.opt import WriterFactory
from pyomo.common.collections import ComponentMap
from pyomo.core.base.numvalue import value, as_numeric
-from pyomo.core.base.block import (Block,
- _BlockData,
- SortComponents)
-from pyomo.core.base.var import Var, _VarData
+from pyomo.core.base.var import _VarData
from pyomo.core.base.constraint import Constraint, _ConstraintData
from pyomo.core.base import TextLabeler, NumericLabeler
from pyomo.pysp.scenariotree.manager import InvocationType
@@ -36,8 +33,7 @@
_safe_remove_file,
_no_negative_zero,
_deterministic_check_value,
- _deterministic_check_constant,
- ProblemStats)
+ _deterministic_check_constant)
from pyomo.pysp.util.config import (PySPConfigValue,
PySPConfigBlock,
safe_register_common_option,
@@ -47,8 +43,9 @@
(ScenarioTreeManagerClientSerial,
ScenarioTreeManagerClientPyro)
from pyomo.pysp.util.misc import launch_command
+import pyomo.environ
-from six import iteritems, itervalues
+from six import iteritems
thisfile = os.path.abspath(__file__)
@@ -106,7 +103,6 @@ def _convert_external_setup_without_cleanup(
firststage_var_suffix,
enforce_derived_nonanticipativity,
io_options):
- import pyomo.environ
assert os.path.exists(output_directory)
io_options = dict(io_options)
@@ -1065,7 +1061,6 @@ def convertddsip_register_options(options=None):
#
def run_convertddsip(options):
- import pyomo.environ
if not os.path.exists(options.output_directory):
os.makedirs(options.output_directory)
diff --git a/pyomo/pysp/convert/schuripopt.py b/pyomo/pysp/convert/schuripopt.py
index e07c0588019..b3b8b56f85d 100644
--- a/pyomo/pysp/convert/schuripopt.py
+++ b/pyomo/pysp/convert/schuripopt.py
@@ -327,7 +327,6 @@ def convertschuripopt(options):
Construct a senario tree manager and write the
schuripopt input files.
"""
- import pyomo.environ
start_time = time.time()
diff --git a/pyomo/pysp/convert/smps.py b/pyomo/pysp/convert/smps.py
index c53303df048..2c551086605 100644
--- a/pyomo/pysp/convert/smps.py
+++ b/pyomo/pysp/convert/smps.py
@@ -22,9 +22,7 @@
from pyomo.common.collections import ComponentMap
from pyomo.opt import WriterFactory
from pyomo.core.base.numvalue import value, as_numeric
-from pyomo.core.base.block import (Block,
- _BlockData,
- SortComponents)
+from pyomo.core.base.block import SortComponents
from pyomo.core.base.objective import Objective
from pyomo.core.base.var import Var, _VarData
from pyomo.core.base.constraint import Constraint, _ConstraintData
diff --git a/pyomo/pysp/dualphmodel.py b/pyomo/pysp/dualphmodel.py
index 64dd745b6c0..f392144e293 100644
--- a/pyomo/pysp/dualphmodel.py
+++ b/pyomo/pysp/dualphmodel.py
@@ -10,7 +10,7 @@
import copy
-from pyomo.core import *
+from pyomo.core import ConcreteModel, Suffix, Var, Block, Set, RangeSet, Objective, Constraint, NonNegativeReals, sum_product, value
from pyomo.opt import SolverFactory
from pyomo.core.expr.current import ExpressionBase
from pyomo.pysp.phutils import update_all_rhos, find_active_objective
diff --git a/pyomo/pysp/ef.py b/pyomo/pysp/ef.py
index a0464827362..4b264480217 100644
--- a/pyomo/pysp/ef.py
+++ b/pyomo/pysp/ef.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core.base import *
+from pyomo.core import ConcreteModel, Var, Set, Objective, Constraint, ConstraintList, NonNegativeReals, NonPositiveReals, Expression, ComponentMap, maximize, minimize
from pyomo.opt import (ProblemFormat,
SolverFactory,
SolverManagerFactory,
diff --git a/pyomo/pysp/ef_writer_script.py b/pyomo/pysp/ef_writer_script.py
index 4fe3267dfff..72718483a72 100644
--- a/pyomo/pysp/ef_writer_script.py
+++ b/pyomo/pysp/ef_writer_script.py
@@ -12,17 +12,12 @@
import logging
import sys
import time
-import itertools
-import math
-
-import pyutilib.misc
-from pyutilib.pyro import shutdown_pyro_components
+import argparse
import pyomo.solvers
from pyomo.common.dependencies import yaml
from pyomo.common import pyomo_command
from pyomo.opt import (SolverFactory,
- TerminationCondition,
undefined,
UndefinedData,
ProblemFormat,
@@ -36,14 +31,10 @@
safe_register_unique_option,
safe_declare_common_option,
safe_declare_unique_option,
- _domain_percent,
_domain_nonnegative,
- _domain_nonnegative_integer,
- _domain_positive_integer,
_domain_must_be_str,
_domain_unit_interval,
_domain_tuple_of_str,
- _domain_tuple_of_str_or_dict,
_output_options_group_title,
_extension_options_group_title,
_deprecated_options_group_title)
@@ -52,8 +43,7 @@
sort_extensions_by_precedence)
from pyomo.pysp.phutils import find_active_objective
from pyomo.pysp.scenariotree.manager_solver import \
- (ScenarioTreeManager,
- ScenarioTreeManagerClientSerial)
+ (ScenarioTreeManagerClientSerial)
from pyomo.pysp.solutionioextensions import \
(IPySPSolutionSaverExtension,
IPySPSolutionLoaderExtension)
@@ -629,8 +619,7 @@ def runef_register_options(options=None):
safe_register_common_option(options,
"pyro_shutdown_workers")
- class _DeprecatedActivateJSONIOSolutionSaver(
- pyutilib.misc.config.argparse.Action):
+ class _DeprecatedActivateJSONIOSolutionSaver(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
if nargs is not None:
raise ValueError("nargs not allowed")
diff --git a/pyomo/pysp/embeddedsp.py b/pyomo/pysp/embeddedsp.py
index f74024cf0f3..fcfcc5127df 100644
--- a/pyomo/pysp/embeddedsp.py
+++ b/pyomo/pysp/embeddedsp.py
@@ -16,13 +16,11 @@
from pyomo.common.collections import ComponentMap
from pyomo.core.expr import current as EXPR
-import pyomo.core.base.param
from pyomo.core.base import ComponentUID
-from pyomo.core.base.numvalue import is_fixed, is_constant
from pyomo.core.base.block import (Block,
SortComponents,
generate_cuid_names)
-from pyomo.core.base.var import Var, _VarData
+from pyomo.core.base.var import Var
from pyomo.core.base.objective import (Objective,
_ObjectiveData)
from pyomo.core.base.constraint import (Constraint,
@@ -37,7 +35,6 @@
StochasticConstraintBodyAnnotation,
StochasticObjectiveAnnotation,
StochasticVariableBoundsAnnotation)
-from pyomo.pysp.scenariotree.tree_structure import ScenarioTree
from pyomo.pysp.scenariotree.tree_structure_model import \
CreateAbstractScenarioTreeModel
from pyomo.pysp.scenariotree.manager import \
diff --git a/pyomo/pysp/evaluate_xhat.py b/pyomo/pysp/evaluate_xhat.py
index d35388608a4..f479833e31e 100644
--- a/pyomo/pysp/evaluate_xhat.py
+++ b/pyomo/pysp/evaluate_xhat.py
@@ -8,13 +8,11 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import sys
import time
import copy
from pyomo.common import pyomo_command
from pyomo.common.dependencies import yaml
-from pyomo.core import minimize
from pyomo.pysp.util.config import (PySPConfigValue,
PySPConfigBlock,
safe_register_common_option,
@@ -151,10 +149,8 @@ def run_evaluate_xhat(options,
solution_loaders=(),
solution_savers=()):
- import pyomo.environ
-
start_time = time.time()
-
+ import pyomo.environ
solution_loaders = sort_extensions_by_precedence(solution_loaders)
solution_savers = sort_extensions_by_precedence(solution_savers)
diff --git a/pyomo/pysp/lagrangeutils.py b/pyomo/pysp/lagrangeutils.py
index 815959f68a1..61a581e27a3 100644
--- a/pyomo/pysp/lagrangeutils.py
+++ b/pyomo/pysp/lagrangeutils.py
@@ -9,17 +9,11 @@
# ___________________________________________________________________________
import sys
-import os
import time
from pyomo.core import minimize
from pyomo.pysp.ef_writer_script import ExtensiveFormAlgorithm
from pyomo.pysp.phinit import run_ph
-from pyomo.pysp.phutils import (reset_nonconverged_variables,
- extractVariableNameAndIndex,
- reset_stage_cost_variables)
-from pyomo.pysp.solutionwriter import ISolutionWriterExtension
-from pyomo.common.plugin import ExtensionPoint
# Tear the scenario instances off the ef instance when it is no longer required
# so warnings are not generated next time scenarios instances are placed inside
diff --git a/pyomo/pysp/ph.py b/pyomo/pysp/ph.py
index e8b22071128..b852a522404 100644
--- a/pyomo/pysp/ph.py
+++ b/pyomo/pysp/ph.py
@@ -10,12 +10,10 @@
import gc
import logging
-import pickle
import sys
import time
import inspect
import uuid
-from operator import itemgetter
from math import fabs, sqrt
try:
@@ -26,15 +24,13 @@
import pyutilib.common
-from pyomo.core import *
+from pyomo.core import Var, Set, BooleanSet, IntegerSet, Suffix, value, minimize, maximize
from pyomo.opt import (UndefinedData,
- ProblemFormat,
undefined,
SolverFactory,
SolverStatus,
TerminationCondition,
- SolutionStatus,
- SolverStatus)
+ SolutionStatus)
import pyomo.pysp.convergence
from pyomo.pysp.phboundbase import (_PHBoundBase,
@@ -1945,10 +1941,10 @@ def __init__(self, options):
# and in that order.
def convert_value_string_to_number(s):
try:
- return float(s)
+ return int(s)
except ValueError:
try:
- return int(s)
+ return float(s)
except ValueError:
return s
diff --git a/pyomo/pysp/phboundbase.py b/pyomo/pysp/phboundbase.py
index 15a89f014e6..76616ce75f3 100644
--- a/pyomo/pysp/phboundbase.py
+++ b/pyomo/pysp/phboundbase.py
@@ -17,7 +17,7 @@
from six import iteritems
from operator import itemgetter
-from pyomo.pysp.phutils import *
+from pyomo.pysp.phutils import indexToString
from pyomo.opt import UndefinedData
logger = logging.getLogger('pyomo.pysp')
diff --git a/pyomo/pysp/phinit.py b/pyomo/pysp/phinit.py
index 12063c490aa..08484e01413 100644
--- a/pyomo/pysp/phinit.py
+++ b/pyomo/pysp/phinit.py
@@ -8,7 +8,6 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import gc
import sys
import time
import contextlib
@@ -41,7 +40,6 @@
from pyomo.pysp.solutionwriter import ISolutionWriterExtension
from pyomo.pysp.util.misc import (launch_command,
load_extensions)
-import pyomo.pysp.phsolverserverutils
#
# utility method to construct an option parser for ph arguments,
@@ -1257,9 +1255,8 @@ def run_ph(options, ph):
def exec_runph(options):
- import pyomo.environ
-
start_time = time.time()
+ import pyomo.environ
try:
diff --git a/pyomo/pysp/phobjective.py b/pyomo/pysp/phobjective.py
index 16675b37c50..8f588bcf5a5 100644
--- a/pyomo/pysp/phobjective.py
+++ b/pyomo/pysp/phobjective.py
@@ -13,8 +13,9 @@
from math import fabs, log, exp
from six.moves import xrange
+import sys
-from pyomo.core import *
+from pyomo.core import Set, Constraint, Expression, BooleanSet, value
from pyomo.pysp.phutils import indexToString
# IMPT: In general, the breakpoint computation codes can return a
diff --git a/pyomo/pysp/phsolverserver.py b/pyomo/pysp/phsolverserver.py
index bc0e078393f..ecf3a8afb6a 100644
--- a/pyomo/pysp/phsolverserver.py
+++ b/pyomo/pysp/phsolverserver.py
@@ -8,7 +8,6 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import gc # garbage collection control.
import os
import socket
import sys
@@ -23,7 +22,7 @@
TaskWorkerServer,
shutdown_pyro_components)
-from pyomo.core import *
+from pyomo.core import Var, Suffix, Constraint
from pyomo.opt import UndefinedData
from pyomo.common import pyomo_command
from pyomo.common.plugin import ExtensionPoint, SingletonPlugin
@@ -38,7 +37,6 @@
from pyomo.pysp.ph import _PHBase
from pyomo.pysp.phutils import (reset_nonconverged_variables,
reset_stage_cost_variables,
- find_active_objective,
extract_solve_times)
from pyomo.pysp.util.misc import launch_command
@@ -1359,7 +1357,7 @@ def exec_phsolverserver(options):
if module_to_find.rfind(".py"):
module_to_find = module_to_find.rstrip(".py")
if module_to_find.find("/") != -1:
- module_to_find = string.split(module_to_find,"/")[-1]
+ module_to_find = module_to_find.split("/")[-1]
for name, obj in inspect.getmembers(sys.modules[module_to_find], inspect.isclass):
# the second condition gets around goofyness related to issubclass returning
diff --git a/pyomo/pysp/phsolverserverutils.py b/pyomo/pysp/phsolverserverutils.py
index b92e98a2cec..d1545d8c108 100644
--- a/pyomo/pysp/phsolverserverutils.py
+++ b/pyomo/pysp/phsolverserverutils.py
@@ -15,7 +15,7 @@
import itertools
import enum
-from pyomo.core import *
+from pyomo.core import Var
from six import iteritems, itervalues
diff --git a/pyomo/pysp/phutils.py b/pyomo/pysp/phutils.py
index aa6fa175884..6f0243e0a50 100644
--- a/pyomo/pysp/phutils.py
+++ b/pyomo/pysp/phutils.py
@@ -8,10 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import sys
-
-from pyomo.core import *
-from pyomo.opt import ProblemFormat
+from pyomo.core import Var, Block, Set, Objective, Constraint, SortComponents, SOSConstraint, Piecewise, BuildAction, Param, Any, Binary
from pyomo.repn.standard_repn import (preprocess_block_objectives,
preprocess_block_constraints,
diff --git a/pyomo/pysp/plugins/adaptive_rho_converger.py b/pyomo/pysp/plugins/adaptive_rho_converger.py
index 5ac95554d02..d07060c759b 100644
--- a/pyomo/pysp/plugins/adaptive_rho_converger.py
+++ b/pyomo/pysp/plugins/adaptive_rho_converger.py
@@ -1,13 +1,21 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import logging
import copy
import math
-import pyomo.common.plugin
+from pyomo.common.plugin import implements, alias, SingletonPlugin
from pyomo.pysp import phextension
from pyomo.pysp.phutils import indexToString
-from pyomo.pysp.plugins.phboundextension import _PHBoundExtensionImpl
-
logger = logging.getLogger('pyomo.pysp')
class _AdaptiveRhoBase(object):
@@ -189,12 +197,12 @@ def ph_convergence_check(self, ph):
def post_ph_execution(self, ph):
pass
-class admm(pyomo.common.plugin.SingletonPlugin,
+class admm(SingletonPlugin,
_AdaptiveRhoBase):
- pyomo.common.plugin.implements(phextension.IPHExtension)
+ implements(phextension.IPHExtension)
- pyomo.common.plugin.alias("admm")
+ alias("admm")
def __init__(self):
_AdaptiveRhoBase.__init__(self)
diff --git a/pyomo/pysp/plugins/convexhullboundextension.py b/pyomo/pysp/plugins/convexhullboundextension.py
index aa5120bbd3d..1fdfd4ed074 100644
--- a/pyomo/pysp/plugins/convexhullboundextension.py
+++ b/pyomo/pysp/plugins/convexhullboundextension.py
@@ -14,7 +14,7 @@
import pyomo.common.plugin
from pyomo.opt import SolverFactory
-from pyomo.core import *
+from pyomo.core import ConcreteModel, Var, Reals, Param, Objective, ConstraintList, minimize
from pyomo.pysp import phextension
from pyomo.pysp.plugins.phboundextension import (_PHBoundBase,
ExtractInternalNodeSolutionsforInner)
diff --git a/pyomo/pysp/plugins/ddextensionnew.py b/pyomo/pysp/plugins/ddextensionnew.py
index 9b86a3f74b5..1abb459ea20 100644
--- a/pyomo/pysp/plugins/ddextensionnew.py
+++ b/pyomo/pysp/plugins/ddextensionnew.py
@@ -16,13 +16,12 @@
import csv
import sys
-import itertools
from operator import itemgetter
import os
thisfile = os.path.abspath(__file__)
import pyomo.common.plugin
-from pyomo.core import *
+from pyomo.core import TextLabeler, Var, Constraint, Piecewise, Expression, SOSConstraint
from pyomo.core.base.var import _VarData
from pyomo.core.base.piecewise import _PiecewiseData
from pyomo.pysp import phextension
diff --git a/pyomo/pysp/plugins/ddextensionold.py b/pyomo/pysp/plugins/ddextensionold.py
index 458306fb262..27e0675bfda 100644
--- a/pyomo/pysp/plugins/ddextensionold.py
+++ b/pyomo/pysp/plugins/ddextensionold.py
@@ -16,16 +16,16 @@
import os
import csv
import sys
-import itertools
thisfile = os.path.abspath(__file__)
-from pyomo.core.base import *
-from pyomo.core.base.set_types import *
+from pyomo.core.base import Var, TextLabeler, Expression, Piecewise, _PiecewiseData, SOSConstraint, Constraint, components_data
from pyomo.pysp.plugins.ddextensionnew import (MatrixEntriesClass,
LPFileObjClass,
LPFileConstraintClass)
+from pyomo.pysp.phutils import create_block_symbol_maps
+from pyomo.solvers.plugins.smanager.phpyro import SolverManager_PHPyro
from six import iteritems
@@ -98,8 +98,7 @@ def post_ph_initialization(self, ph):
print(("\nUsing %s as reference scenario" % (scenario_name)))
- if isinstance(ph._solver_manager,
- pyomo.solvers.plugins.smanager.phpyro.SolverManager_PHPyro):
+ if isinstance(ph._solver_manager, SolverManager_PHPyro):
# If this is parallel ph, the instances do not exist on
# this process, so let's construct the one we need
singleton_tree = ph._scenario_tree._scenario_instance_factory.generate_scenario_tree()
diff --git a/pyomo/pysp/plugins/ecksteincombettesextension.py b/pyomo/pysp/plugins/ecksteincombettesextension.py
index da7a4c9c1e7..5d9f4aec249 100644
--- a/pyomo/pysp/plugins/ecksteincombettesextension.py
+++ b/pyomo/pysp/plugins/ecksteincombettesextension.py
@@ -10,14 +10,14 @@
import pyomo.common.plugin
-from six import iteritems, itervalues, print_
+from six import iteritems, print_
import random
from pyomo.pysp import phextension
from pyomo.pysp.convergence import ConvergenceBase
-from pyomo.core.base import minimize, maximize
+from pyomo.core.base import minimize
import math
diff --git a/pyomo/pysp/plugins/examplephextension.py b/pyomo/pysp/plugins/examplephextension.py
index c11464b45cb..b106a7f156c 100644
--- a/pyomo/pysp/plugins/examplephextension.py
+++ b/pyomo/pysp/plugins/examplephextension.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.common.plugin import *
+from pyomo.common.plugin import implements, SingletonPlugin
from pyomo.pysp import phextension
diff --git a/pyomo/pysp/plugins/interscenario.py b/pyomo/pysp/plugins/interscenario.py
index f29ff9091ee..c61b89186eb 100644
--- a/pyomo/pysp/plugins/interscenario.py
+++ b/pyomo/pysp/plugins/interscenario.py
@@ -14,8 +14,8 @@
from six.moves import xrange
import weakref
-import pyutilib
-from pyutilib.misc.timing import tic, toc
+from pyutilib.misc import reset_redirect, setup_redirect
+from pyutilib.misc.timing import toc
from pyomo.core import (
minimize, value, TransformationFactory,
@@ -31,10 +31,7 @@
from pyomo.repn.standard_repn import (preprocess_block_constraints,
preprocess_block_objectives)
-from pyomo.pysp.phsolverserverutils import (
- InvocationType,
- transmit_external_function_invocation,
- transmit_external_function_invocation_to_worker )
+from pyomo.pysp.phsolverserverutils import InvocationType
from pyomo.pysp.convergence import NormalizedTermDiffConvergence
import logging
@@ -277,7 +274,7 @@ def solve_separation_problem(solver, model, fallback):
#SOLVE
output_buffer = StringIO()
- pyutilib.misc.setup_redirect(output_buffer)
+ setup_redirect(output_buffer)
try:
results = solver.solve(model, tee=True)
except:
@@ -286,7 +283,7 @@ def solve_separation_problem(solver, model, fallback):
logger.warning("Solver log:\n%s" % output_buffer.getvalue())
raise
finally:
- pyutilib.misc.reset_redirect()
+ reset_redirect()
ss = results.solver.status
tc = results.solver.termination_condition
@@ -364,7 +361,7 @@ def add_new_cuts( ph, scenario_tree, scenario_or_bundle,
for i, (_sep, _par) in iteritems(cut)
if abs(_sep) > epsilon*max(1,_par)
)
- if expr is not 0:
+ if expr != 0:
_cutlist.add( expr >= 0 )
for cut in incumbent_cuts:
@@ -479,7 +476,7 @@ def solve_fixed_scenario_solutions(
toc("preprocessed scenario %s" % ( scenario_or_bundle._name, ))
output_buffer = StringIO()
- pyutilib.misc.setup_redirect(output_buffer)
+ setup_redirect(output_buffer)
try:
results = ph._solver.solve(model, tee=True) # warmstart=True)
except:
@@ -488,7 +485,7 @@ def solve_fixed_scenario_solutions(
logger.warning("Solver log:\n%s" % output_buffer.getvalue())
raise
finally:
- pyutilib.misc.reset_redirect()
+ reset_redirect()
toc("solved solution from scenario set %s on scenario %s" %
( scenario_name_list, scenario_or_bundle._name, ))
diff --git a/pyomo/pysp/plugins/jsonsolutionwriter.py b/pyomo/pysp/plugins/jsonsolutionwriter.py
index 231e6dac173..a084d1ed3f3 100644
--- a/pyomo/pysp/plugins/jsonsolutionwriter.py
+++ b/pyomo/pysp/plugins/jsonsolutionwriter.py
@@ -8,9 +8,9 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.common.plugin import *
+from pyomo.common.plugin import SingletonPlugin, implements
from pyomo.pysp import solutionwriter
-from pyomo.pysp.scenariotree import *
+from pyomo.pysp.scenariotree import ScenarioTree
from pyomo.pysp.plugins.phhistoryextension \
import extract_scenario_tree_structure, \
extract_scenario_solutions, \
diff --git a/pyomo/pysp/plugins/phboundextension.py b/pyomo/pysp/plugins/phboundextension.py
index 1a845e031e9..c5e709d9f5e 100644
--- a/pyomo/pysp/plugins/phboundextension.py
+++ b/pyomo/pysp/plugins/phboundextension.py
@@ -14,16 +14,10 @@
from __future__ import division
import os
-import logging
-import copy
-import pyomo.common.plugin
+from pyomo.common.plugin import implements, alias, SingletonPlugin
from pyomo.pysp import phextension
from pyomo.core.base import minimize
-from pyomo.opt import UndefinedData
-
-from operator import itemgetter
-from six import iteritems
from pyomo.pysp.phboundbase import (_PHBoundBase,
ExtractInternalNodeSolutionsforInner)
@@ -319,11 +313,11 @@ def post_ph_execution(self, ph):
self.ReportBoundHistory()
self.ReportBestBound()
-class phboundextension(pyomo.common.plugin.SingletonPlugin, _PHBoundExtensionImpl):
+class phboundextension(SingletonPlugin, _PHBoundExtensionImpl):
- pyomo.common.plugin.implements(phextension.IPHExtension)
+ implements(phextension.IPHExtension)
- pyomo.common.plugin.alias("phboundextension")
+ alias("phboundextension")
def __init__(self):
diff --git a/pyomo/pysp/plugins/phhistoryextension.py b/pyomo/pysp/plugins/phhistoryextension.py
index 0aa190b813c..efdde8eca5c 100644
--- a/pyomo/pysp/plugins/phhistoryextension.py
+++ b/pyomo/pysp/plugins/phhistoryextension.py
@@ -17,7 +17,7 @@
from pyutilib.misc import ArchiveReaderFactory
-from pyomo.common.plugin import *
+from pyomo.common.plugin import implements, alias, SingletonPlugin
from pyomo.pysp import phextension
from pyomo.pysp.phutils import indexToString
from pyomo.pysp.phsolverserverutils import TransmitType
diff --git a/pyomo/pysp/plugins/schuripwriter.py b/pyomo/pysp/plugins/schuripwriter.py
index 6d6d81e5e12..21c64339b8d 100644
--- a/pyomo/pysp/plugins/schuripwriter.py
+++ b/pyomo/pysp/plugins/schuripwriter.py
@@ -8,13 +8,11 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyutilib.misc import *
-
-from pyomo.common.plugin import *
+from pyomo.common.plugin import implements, SingletonPlugin
from pyomo.pysp import phextension
-from pyomo.core import *
-import pyomo.opt
+from pyomo.core import Suffix
+from pyomo.opt import WriterFactory
import os
import sys
@@ -50,7 +48,7 @@ def post_ph_initialization(self, ph):
os.system("rm -rf "+output_directory_name)
os.mkdir(output_directory_name)
- nl_writer = pyomo.opt.WriterFactory('nl')
+ nl_writer = WriterFactory('nl')
root_node = ph._scenario_tree.findRootNode()
diff --git a/pyomo/pysp/plugins/sorgw.py b/pyomo/pysp/plugins/sorgw.py
index 6d2064f3179..60a4258c375 100755
--- a/pyomo/pysp/plugins/sorgw.py
+++ b/pyomo/pysp/plugins/sorgw.py
@@ -18,22 +18,21 @@
import sys
-import pyomo.common.plugin
-from pyomo.core import *
+from pyomo.common.plugin import implements, alias, SingletonPlugin
from pyomo.pysp import phextension
-from pyomo.pysp.phutils import *
+from pyomo.pysp.phutils import indexToString
from pyomo.pysp.generators import \
scenario_tree_node_variables_generator_noinstances
#==================================================
-class sorgwextension(pyomo.common.plugin.SingletonPlugin):
+class sorgwextension(SingletonPlugin):
- pyomo.common.plugin.implements(phextension.IPHExtension)
+ implements(phextension.IPHExtension)
# the below is a hack to get this extension into the
# set of IPHExtension objects, so it can be queried
# automagically by PH.
- pyomo.common.plugin.alias("sorgwextension")
+ alias("sorgwextension")
def __init__(self, *args, **kwds):
diff --git a/pyomo/pysp/plugins/testphextension.py b/pyomo/pysp/plugins/testphextension.py
index 2b6ea0dea8f..6b767f9475e 100644
--- a/pyomo/pysp/plugins/testphextension.py
+++ b/pyomo/pysp/plugins/testphextension.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.common.plugin import *
+from pyomo.common.plugin import SingletonPlugin, implements
from pyomo.pysp import phextension
diff --git a/pyomo/pysp/plugins/wwphextension.py b/pyomo/pysp/plugins/wwphextension.py
index 5ce1929cd98..faedc699f66 100644
--- a/pyomo/pysp/plugins/wwphextension.py
+++ b/pyomo/pysp/plugins/wwphextension.py
@@ -17,12 +17,11 @@
from pyomo.common.dependencies import yaml, yaml_load_args
import pyomo.common.plugin
from pyomo.pysp import phextension
-from pyomo.pysp.phutils import *
+from pyomo.pysp.phutils import isVariableNameIndexed, extractVariableNameAndIndex, indexMatchesTemplate, indexToString
from pyomo.pysp.phsolverserverutils import \
transmit_external_function_invocation_to_worker
from pyomo.pysp.generators import \
scenario_tree_node_variables_generator_noinstances
-from pyomo.core.base import *
import six
from six import iteritems
diff --git a/pyomo/pysp/scenariotree/__init__.py b/pyomo/pysp/scenariotree/__init__.py
index f5cd1081f46..3d5be968212 100644
--- a/pyomo/pysp/scenariotree/__init__.py
+++ b/pyomo/pysp/scenariotree/__init__.py
@@ -9,9 +9,38 @@
# ___________________________________________________________________________
import pyomo.pysp.scenariotree.util
-from pyomo.pysp.scenariotree.tree_structure_model import *
-from pyomo.pysp.scenariotree.tree_structure import *
-from pyomo.pysp.scenariotree.instance_factory import *
+from pyomo.pysp.scenariotree.tree_structure_model import (
+ CreateAbstractScenarioTreeModel, CreateConcreteTwoStageScenarioTreeModel,
+ ScenarioTreeModelFromNetworkX)
+from pyomo.common.collections import ComponentMap
+from pyomo.core import (value, minimize, maximize,
+ Var, Expression, Block,
+ Objective, SOSConstraint,
+ ComponentUID)
+from pyomo.core.base.block import generate_cuid_names
+from pyomo.core.base.sos import _SOSConstraintData
+from pyomo.repn import generate_standard_repn
+from pyomo.pysp.phutils import (BasicSymbolMap,
+ indexToString,
+ isVariableNameIndexed,
+ extractVariableNameAndIndex,
+ extractComponentIndices,
+ find_active_objective)
+from pyomo.pysp.scenariotree.tree_structure import (_CUIDLabeler,
+ ScenarioTreeNode,
+ ScenarioTreeStage,
+ Scenario,
+ ScenarioTreeBundle,
+ ScenarioTree)
+from pyomo.pysp.scenariotree.instance_factory import (DataPortal, Block,
+ IPyomoScriptModifyInstance,
+ AbstractModel, _BlockData,
+ ExtensionPoint,
+ load_external_module,
+ _extract_pathspec,
+ _find_reference_model_or_callback,
+ _find_scenariotree,
+ ScenarioTreeInstanceFactory)
import pyomo.pysp.scenariotree.action_manager_pyro
import pyomo.pysp.scenariotree.server_pyro
diff --git a/pyomo/pysp/scenariotree/instance_factory.py b/pyomo/pysp/scenariotree/instance_factory.py
index cf4710a205a..47521417607 100644
--- a/pyomo/pysp/scenariotree/instance_factory.py
+++ b/pyomo/pysp/scenariotree/instance_factory.py
@@ -11,7 +11,6 @@
__all__ = ('ScenarioTreeInstanceFactory',)
import os
-import time
import posixpath
import tempfile
import shutil
@@ -29,7 +28,6 @@
from pyomo.core.base.block import _BlockData
from pyomo.common.dependencies import yaml, yaml_available, yaml_load_args
from pyomo.common.plugin import ExtensionPoint
-from pyomo.pysp.phutils import _OLD_OUTPUT
from pyomo.pysp.util.misc import load_external_module
from pyomo.pysp.scenariotree.tree_structure_model import \
(CreateAbstractScenarioTreeModel,
diff --git a/pyomo/pysp/scenariotree/manager.py b/pyomo/pysp/scenariotree/manager.py
index 0b753dc89e1..9054f848959 100644
--- a/pyomo/pysp/scenariotree/manager.py
+++ b/pyomo/pysp/scenariotree/manager.py
@@ -34,8 +34,7 @@
SolutionStatus)
from pyomo.opt.parallel.manager import ActionHandle
from pyomo.pysp.util.configured_object import PySPConfiguredObject
-from pyomo.pysp.util.config import (PySPConfigValue,
- PySPConfigBlock,
+from pyomo.pysp.util.config import (PySPConfigBlock,
safe_declare_common_option,
safe_register_common_option,
_domain_must_be_str,
@@ -3485,7 +3484,7 @@ def _invoke_function_impl(
(invocation_type == InvocationType.OnBundles):
_get_worker_func = None
- _inocation_type = None
+ _invocation_type = None
if invocation_type == InvocationType.OnScenarios:
_get_worker_func = self.get_worker_for_scenario
_invocation_type = InvocationType.OnScenarios
@@ -3563,7 +3562,7 @@ def _invoke_function_impl(
% (invocation_type))
_get_worker_func = None
- _inocation_type = None
+ _invocation_type = None
if invocation_type == InvocationType.OnScenariosChained:
_get_worker_func = self.get_worker_for_scenario
_invocation_type = InvocationType.OnScenariosChained
diff --git a/pyomo/pysp/scenariotree/manager_solver.py b/pyomo/pysp/scenariotree/manager_solver.py
index 21c1ce2a6b0..574934cf1eb 100644
--- a/pyomo/pysp/scenariotree/manager_solver.py
+++ b/pyomo/pysp/scenariotree/manager_solver.py
@@ -15,21 +15,17 @@
# TODO: handle pyro as the solver manager when even when the
# pyro scenario tree manager is used
-import math
import time
import sys
from pyutilib.pyro import shutdown_pyro_components
from pyomo.opt import (SolverFactory,
SolverStatus,
- TerminationCondition,
SolutionStatus)
from pyomo.opt.base.solvers import OptSolver
from pyomo.opt.parallel import SolverManagerFactory
-from pyomo.pysp.util.config import (PySPConfigValue,
- PySPConfigBlock,
- safe_declare_common_option,
- safe_register_common_option)
+from pyomo.pysp.util.config import (PySPConfigBlock,
+ safe_declare_common_option)
from pyomo.pysp.util.configured_object import \
PySPConfiguredObject
from pyomo.pysp.scenariotree.preprocessor import \
@@ -43,7 +39,7 @@
ScenarioTreeManagerClientPyro,
ScenarioTreeSolveResults)
-from six import itervalues, iteritems
+from six import itervalues
#
# The ScenarioTreeManagerSolver interface adds additional
diff --git a/pyomo/pysp/scenariotree/manager_solver_worker_pyro.py b/pyomo/pysp/scenariotree/manager_solver_worker_pyro.py
index a1f2d989c88..0ab810926df 100644
--- a/pyomo/pysp/scenariotree/manager_solver_worker_pyro.py
+++ b/pyomo/pysp/scenariotree/manager_solver_worker_pyro.py
@@ -10,13 +10,9 @@
__all__ = ("ScenarioTreeManagerSolverWorkerPyro",)
-import time
-
-from pyomo.opt import (SolverFactory,
- undefined)
+from pyomo.opt import undefined
from pyomo.pysp.util.configured_object import PySPConfiguredObject
-from pyomo.pysp.util.config import (PySPConfigBlock,
- safe_declare_common_option)
+from pyomo.pysp.util.config import PySPConfigBlock
from pyomo.pysp.scenariotree.manager_worker_pyro import \
ScenarioTreeManagerWorkerPyro
from pyomo.pysp.scenariotree.manager_solver import \
diff --git a/pyomo/pysp/scenariotree/preprocessor.py b/pyomo/pysp/scenariotree/preprocessor.py
index 4a2350b085d..33137f8d539 100644
--- a/pyomo/pysp/scenariotree/preprocessor.py
+++ b/pyomo/pysp/scenariotree/preprocessor.py
@@ -19,11 +19,7 @@
# simple_preprocessor, which in turn is invoked by the preprocess()
# method of PyomoModel.
from pyomo.core.base.objective import Objective
-from pyomo.core.base.var import Var
from pyomo.core.base.constraint import Constraint
-from pyomo.core.base.sos import SOSConstraint
-from pyomo.opt import ProblemFormat
-from pyomo.solvers.plugins.solvers.persistent_solver import PersistentSolver
from pyomo.repn.standard_repn import (preprocess_block_objectives,
preprocess_block_constraints,
preprocess_constraint_data)
diff --git a/pyomo/pysp/scenariotree/server_pyro.py b/pyomo/pysp/scenariotree/server_pyro.py
index 6e90403d170..55135f3d86d 100644
--- a/pyomo/pysp/scenariotree/server_pyro.py
+++ b/pyomo/pysp/scenariotree/server_pyro.py
@@ -13,11 +13,8 @@
import os
import six
-from six import iteritems
import sys
import socket
-import copy
-import argparse
import logging
import traceback
import base64
@@ -26,26 +23,18 @@
except: #pragma:nocover
import pickle
-import pyutilib.misc
-from pyutilib.misc import PauseGC
+from pyutilib.misc import Bunch
from pyomo.common.dependencies import attempt_import, dill, dill_available
from pyomo.common import pyomo_command
-from pyomo.opt import (SolverFactory,
- TerminationCondition,
- SolutionStatus)
-
-from pyomo.opt.parallel.manager import ActionManagerError
from pyomo.pysp.util.misc import (parse_command_line,
launch_command,
load_external_module)
from pyomo.pysp.util.config import (PySPConfigValue,
PySPConfigBlock,
- safe_declare_common_option,
safe_register_common_option,
safe_register_unique_option,
_domain_tuple_of_str)
-from pyomo.pysp.util.configured_object import PySPConfiguredObject
from pyomo.pysp.scenariotree.tree_structure import \
ScenarioTree
from pyomo.pysp.scenariotree.instance_factory import \
@@ -158,7 +147,7 @@ def process(self, data):
traceback.format_exc()))
def _process(self, data):
- data = pyutilib.misc.Bunch(**data)
+ data = Bunch(**data)
result = None
if not data.action.startswith('ScenarioTreeServerPyro_'):
#with PauseGC() as pgc:
diff --git a/pyomo/pysp/scenariotree/tree_structure.py b/pyomo/pysp/scenariotree/tree_structure.py
index 1c7d74dd874..f4b1fb2f53a 100644
--- a/pyomo/pysp/scenariotree/tree_structure.py
+++ b/pyomo/pysp/scenariotree/tree_structure.py
@@ -28,11 +28,9 @@
from pyomo.common.collections import ComponentMap
from pyomo.core import (value, minimize, maximize,
Var, Expression, Block,
- CounterLabeler,
- Objective, SOSConstraint, Set,
+ Objective, SOSConstraint,
ComponentUID)
-from pyomo.core.base.block import (_BlockData,
- generate_cuid_names)
+from pyomo.core.base.block import generate_cuid_names
from pyomo.core.base.sos import _SOSConstraintData
from pyomo.repn import generate_standard_repn
from pyomo.pysp.phutils import (BasicSymbolMap,
@@ -42,7 +40,6 @@
extractComponentIndices,
find_active_objective)
-import six
from six import iterkeys, iteritems, itervalues
from six.moves import xrange
@@ -1529,12 +1526,12 @@ def __init__(self,
if tree_node_name not in node_stage_ids:
raise ValueError("No stage is assigned to tree node=%s"
- % (tree_node.name))
+ % (tree_node_name))
stage_name = value(node_stage_ids[tree_node_name])
if stage_name not in self._stage_map:
raise ValueError("Unknown stage=%s assigned to tree node=%s"
- % (stage_name, tree_node.name))
+ % (stage_name, tree_node_name))
node_stage = self._stage_map[stage_name]
new_tree_node = ScenarioTreeNode(
diff --git a/pyomo/pysp/scenariotree/util.py b/pyomo/pysp/scenariotree/util.py
index 1cb7535cb80..98acc695922 100644
--- a/pyomo/pysp/scenariotree/util.py
+++ b/pyomo/pysp/scenariotree/util.py
@@ -1,8 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import hashlib
import uuid
-import six
-
pysp_namespace_hash = hashlib.md5('pysp'.encode())
def _compute_namespace(node_name):
node_namespace_hash = pysp_namespace_hash.copy()
diff --git a/pyomo/pysp/solvers/admm.py b/pyomo/pysp/solvers/admm.py
index 91d4924557a..ab29b66532a 100644
--- a/pyomo/pysp/solvers/admm.py
+++ b/pyomo/pysp/solvers/admm.py
@@ -11,7 +11,6 @@
import sys
import time
import math
-import array
# TODO: run y update on the server side so that bounds can be
# returned efficiently if enabled
diff --git a/pyomo/pysp/solvers/benders.py b/pyomo/pysp/solvers/benders.py
index 9950288971e..049b05e1831 100644
--- a/pyomo/pysp/solvers/benders.py
+++ b/pyomo/pysp/solvers/benders.py
@@ -46,7 +46,6 @@
from pyomo.pysp.util.config import (PySPConfigValue,
PySPConfigBlock,
safe_register_common_option,
- safe_register_unique_option,
safe_declare_common_option,
safe_declare_unique_option,
_domain_percent,
@@ -94,7 +93,7 @@ def EXTERNAL_activate_rootnode_costs(manager,
assert len(manager.scenario_tree.stages) == 2
assert scenario in manager.scenario_tree.scenarios
rootnode = manager.scenario_tree.findRootNode()
- nodecost_var = instance.find_component(
+ nodecost_var = scenario._instance.find_component(
rootnode._cost_variable[0])[rootnode._cost_variable[1]]
scenario._instance.find_component(
"PYSP_BENDERS_NODE_COST_TERM_"+rootnode.name).set_value(nodecost_var)
diff --git a/pyomo/pysp/solvers/ddsip.py b/pyomo/pysp/solvers/ddsip.py
index 62dd4979083..953d57257cc 100644
--- a/pyomo/pysp/solvers/ddsip.py
+++ b/pyomo/pysp/solvers/ddsip.py
@@ -16,14 +16,12 @@
import os
import sys
import time
-import shutil
import logging
import traceback
import pyutilib.subprocess
import pyutilib.services
-from pyomo.core import maximize
from pyomo.opt import (TerminationCondition,
SolverStatus,
SolutionStatus)
@@ -38,11 +36,8 @@
_domain_must_be_str)
from pyomo.pysp.util.misc import (parse_command_line,
launch_command)
-from pyomo.pysp.scenariotree.manager import \
- (InvocationType,
- ScenarioTreeManagerFactory)
+from pyomo.pysp.scenariotree.manager import ScenarioTreeManagerFactory
import pyomo.pysp.convert.ddsip
-from pyomo.pysp.embeddedsp import EmbeddedSP
from pyomo.pysp.solvers.spsolver import (SPSolverResults,
SPSolverFactory)
from pyomo.pysp.solvers.spsolvershellcommand import \
diff --git a/pyomo/pysp/solvers/ef.py b/pyomo/pysp/solvers/ef.py
index 9f415e85b7a..256358a3fb5 100755
--- a/pyomo/pysp/solvers/ef.py
+++ b/pyomo/pysp/solvers/ef.py
@@ -11,17 +11,11 @@
import logging
import sys
import time
-import itertools
-import math
-
-import pyutilib.misc
-from pyutilib.pyro import shutdown_pyro_components
+import argparse
import pyomo.solvers
from pyomo.common.dependencies import yaml
-from pyomo.core.base import ComponentUID
from pyomo.opt import (SolverFactory,
- TerminationCondition,
UndefinedData,
ProblemFormat,
UnknownSolver,
@@ -34,14 +28,10 @@
safe_register_unique_option,
safe_declare_common_option,
safe_declare_unique_option,
- _domain_percent,
_domain_nonnegative,
- _domain_nonnegative_integer,
- _domain_positive_integer,
_domain_must_be_str,
_domain_unit_interval,
_domain_tuple_of_str,
- _domain_tuple_of_str_or_dict,
_output_options_group_title,
_extension_options_group_title,
_deprecated_options_group_title)
@@ -49,9 +39,7 @@
launch_command,
sort_extensions_by_precedence)
from pyomo.pysp.phutils import find_active_objective
-from pyomo.pysp.scenariotree.manager_solver import \
- (ScenarioTreeManager,
- ScenarioTreeManagerClientSerial)
+from pyomo.pysp.scenariotree.manager_solver import ScenarioTreeManagerClientSerial
from pyomo.pysp.solutionioextensions import \
(IPySPSolutionSaverExtension,
IPySPSolutionLoaderExtension)
@@ -704,8 +692,7 @@ def runef_register_options(options=None):
# Deprecated
#
- class _DeprecatedActivateJSONIOSolutionSaver(
- pyutilib.misc.config.argparse.Action):
+ class _DeprecatedActivateJSONIOSolutionSaver(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
if nargs is not None:
raise ValueError("nargs not allowed")
@@ -786,6 +773,7 @@ def runef(options,
if options.output_file is not None:
with ExtensiveFormAlgorithm(sp, options) as ef:
ef.build_ef()
+ ## !!THIS SEEMS LIKE A BUG!! - mrmundt #
ef.write(filename)
else:
print("")
diff --git a/pyomo/pysp/solvers/schuripopt.py b/pyomo/pysp/solvers/schuripopt.py
index eefdc55b9b9..06eaf5c365a 100644
--- a/pyomo/pysp/solvers/schuripopt.py
+++ b/pyomo/pysp/solvers/schuripopt.py
@@ -23,16 +23,12 @@
from pyomo.core import ComponentUID
from pyomo.opt import (ReaderFactory,
ResultsFormat,
- ProblemFormat,
UndefinedData)
from pyomo.pysp.util.configured_object import PySPConfiguredObject
from pyomo.pysp.util.config import (PySPConfigValue,
PySPConfigBlock,
safe_register_common_option,
safe_register_unique_option,
- safe_declare_common_option,
- safe_declare_unique_option,
- _domain_must_be_str,
_domain_tuple_of_str_or_dict)
from pyomo.pysp.util.misc import (parse_command_line,
launch_command)
@@ -52,9 +48,6 @@
_write_scenario_nl,
_write_problem_list_file)
-from six.moves import xrange
-# use fast version of pickle (python 2 or 3)
-from six.moves import cPickle as pickle
# generate an absolute path to this file
thisfile = os.path.abspath(__file__)
diff --git a/pyomo/pysp/solvers/sd.py b/pyomo/pysp/solvers/sd.py
index fffa70b24e5..49636ed86f9 100644
--- a/pyomo/pysp/solvers/sd.py
+++ b/pyomo/pysp/solvers/sd.py
@@ -40,13 +40,11 @@
from pyomo.pysp.util.config import (PySPConfigValue,
PySPConfigBlock,
safe_register_common_option,
- safe_register_unique_option,
safe_declare_common_option,
safe_declare_unique_option,
_domain_positive,
_domain_positive_integer,
- _domain_nonnegative_integer,
- _domain_must_be_str)
+ _domain_nonnegative_integer)
from pyomo.pysp.util.misc import (parse_command_line,
launch_command)
from pyomo.pysp.scenariotree.manager import \
diff --git a/pyomo/pysp/solvers/spsolver.py b/pyomo/pysp/solvers/spsolver.py
index 6dc0c38bad3..592899c8512 100644
--- a/pyomo/pysp/solvers/spsolver.py
+++ b/pyomo/pysp/solvers/spsolver.py
@@ -16,8 +16,6 @@
import time
import logging
-import pyutilib.misc
-
from pyomo.opt import UndefinedData
from pyomo.core import ComponentUID
from pyomo.pysp.embeddedsp import EmbeddedSP
diff --git a/pyomo/pysp/tests/benders/test_benders.py b/pyomo/pysp/tests/benders/test_benders.py
index 66f76bc087c..5b7c8f39830 100644
--- a/pyomo/pysp/tests/benders/test_benders.py
+++ b/pyomo/pysp/tests/benders/test_benders.py
@@ -8,23 +8,17 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import sys
-import socket
import os
from os.path import join, dirname, abspath
import time
import subprocess
-import pyutilib.services
import pyutilib.th as unittest
from pyutilib.pyro import using_pyro3, using_pyro4
from pyomo.pysp.util.misc import (_get_test_nameserver,
_get_test_dispatcher,
_poll,
_kill)
-from pyomo.environ import *
-
-from six import StringIO
thisdir = dirname(abspath(__file__))
baselineDir = join(thisdir, "baselines")
diff --git a/pyomo/pysp/tests/convert/piecewise_model.py b/pyomo/pysp/tests/convert/piecewise_model.py
index a21ad8d7b8a..15612776f02 100644
--- a/pyomo/pysp/tests/convert/piecewise_model.py
+++ b/pyomo/pysp/tests/convert/piecewise_model.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Param, Expression, Objective, Constraint, Piecewise, sum_product, inequality
from pyomo.pysp.annotations import (StochasticConstraintBoundsAnnotation,
StochasticConstraintBodyAnnotation,
StochasticObjectiveAnnotation)
diff --git a/pyomo/pysp/tests/convert/piecewise_model_alt.py b/pyomo/pysp/tests/convert/piecewise_model_alt.py
index 9b949ff7d8f..115d4710b78 100644
--- a/pyomo/pysp/tests/convert/piecewise_model_alt.py
+++ b/pyomo/pysp/tests/convert/piecewise_model_alt.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import Constraint
from pyomo.pysp.annotations import (StochasticConstraintBoundsAnnotation,
StochasticConstraintBodyAnnotation,
StochasticObjectiveAnnotation)
diff --git a/pyomo/pysp/tests/convert/piecewise_model_embedded.py b/pyomo/pysp/tests/convert/piecewise_model_embedded.py
index 37ad37cb417..ae3fc4f6266 100644
--- a/pyomo/pysp/tests/convert/piecewise_model_embedded.py
+++ b/pyomo/pysp/tests/convert/piecewise_model_embedded.py
@@ -1,4 +1,14 @@
-import pyomo.environ as aml
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+import pyomo.environ as pyo
from pyomo.pysp.embeddedsp import (EmbeddedSP,
StochasticDataAnnotation,
TableDistribution,
@@ -7,47 +17,47 @@
def create_embedded():
- model = aml.ConcreteModel()
- model.d1 = aml.Param(mutable=True, initialize=0)
- model.d2 = aml.Param(mutable=True, initialize=0)
- model.d3 = aml.Param(mutable=True, initialize=0)
- model.d4 = aml.Param(mutable=True, initialize=0)
+ model = pyo.ConcreteModel()
+ model.d1 = pyo.Param(mutable=True, initialize=0)
+ model.d2 = pyo.Param(mutable=True, initialize=0)
+ model.d3 = pyo.Param(mutable=True, initialize=0)
+ model.d4 = pyo.Param(mutable=True, initialize=0)
# first stage
- model.x = aml.Var(bounds=(0,10))
+ model.x = pyo.Var(bounds=(0,10))
# first stage derived
- model.y = aml.Expression(expr=model.x + 1)
- model.fx = aml.Var()
+ model.y = pyo.Expression(expr=model.x + 1)
+ model.fx = pyo.Var()
# second stage
- model.z = aml.Var(bounds=(-10, 10))
+ model.z = pyo.Var(bounds=(-10, 10))
# second stage derived
- model.q = aml.Expression(expr=model.z**2)
- model.fz = aml.Var()
- model.r = aml.Var()
+ model.q = pyo.Expression(expr=model.z**2)
+ model.fz = pyo.Var()
+ model.r = pyo.Var()
# stage costs
- model.StageCost = aml.Expression([1,2])
+ model.StageCost = pyo.Expression([1,2])
model.StageCost.add(1, model.fx)
model.StageCost.add(2, -model.fz + model.r + model.d1)
- model.o = aml.Objective(expr=aml.sum_product(model.StageCost))
+ model.o = pyo.Objective(expr=pyo.sum_product(model.StageCost))
- model.c_first_stage = aml.Constraint(expr= model.x >= 0)
+ model.c_first_stage = pyo.Constraint(expr= model.x >= 0)
# test our handling of intermediate variables that
# are created by Piecewise but can not necessarily
# be declared on the scenario tree
- model.p_first_stage = aml.Piecewise(model.fx, model.x,
+ model.p_first_stage = pyo.Piecewise(model.fx, model.x,
pw_pts=[0.,2.,5.,7.,10.],
pw_constr_type='EQ',
pw_repn='INC',
f_rule=[10.,10.,9.,10.,10.],
force_pw=True)
- model.c_second_stage = aml.Constraint(expr= model.x + model.r * model.d2 >= -100)
- model.cL_second_stage = aml.Constraint(expr= model.d3 >= -model.r)
- model.cU_second_stage = aml.Constraint(expr= model.r <= 0)
+ model.c_second_stage = pyo.Constraint(expr= model.x + model.r * model.d2 >= -100)
+ model.cL_second_stage = pyo.Constraint(expr= model.d3 >= -model.r)
+ model.cU_second_stage = pyo.Constraint(expr= model.r <= 0)
# exercise more of the code by making this an indexed
# block
- model.p_second_stage = aml.Piecewise([1], model.fz, model.z,
+ model.p_second_stage = pyo.Piecewise([1], model.fz, model.z,
pw_pts=[-10,-5.,0.,5.,10.],
pw_constr_type='EQ',
pw_repn='INC',
diff --git a/pyomo/pysp/tests/convert/test_schuripopt.py b/pyomo/pysp/tests/convert/test_schuripopt.py
index f42ebef5a3c..09ff3bf7b68 100644
--- a/pyomo/pysp/tests/convert/test_schuripopt.py
+++ b/pyomo/pysp/tests/convert/test_schuripopt.py
@@ -11,7 +11,6 @@
import os
from os.path import join, dirname, abspath
import time
-import difflib
import filecmp
import shutil
import subprocess
@@ -22,9 +21,6 @@
_get_test_dispatcher,
_poll,
_kill)
-import pyomo.environ
-
-from six import StringIO
thisdir = dirname(abspath(__file__))
baselinedir = os.path.join(thisdir, "schuripopt_baselines")
diff --git a/pyomo/pysp/tests/convert/test_smps.py b/pyomo/pysp/tests/convert/test_smps.py
index 6ca6b65299a..b29c3ac463d 100644
--- a/pyomo/pysp/tests/convert/test_smps.py
+++ b/pyomo/pysp/tests/convert/test_smps.py
@@ -17,15 +17,13 @@
import shutil
import subprocess
import sys
-import pyutilib.subprocess
-import pyutilib.services
+from pyutilib.subprocess import run
import pyutilib.th as unittest
from pyutilib.pyro import using_pyro3, using_pyro4
from pyomo.pysp.util.misc import (_get_test_nameserver,
_get_test_dispatcher,
_poll,
_kill)
-from pyomo.environ import *
from six import StringIO
@@ -90,7 +88,7 @@ def _get_cmd(self,
def _run_bad_conversion_test(self, *args, **kwds):
cmd, output_dir = self._get_cmd(*args, **kwds)
outfile = output_dir+".out"
- rc = pyutilib.subprocess.run(cmd, outfile=outfile)
+ rc = run(cmd, outfile=outfile)
self.assertNotEqual(rc[0], 0)
self._assert_contains(
outfile,
@@ -153,7 +151,7 @@ def test_too_many_declarations(self):
cmd, output_dir = self._get_cmd(
join(thisdir, "model_too_many_declarations.py"))
outfile = output_dir+".out"
- rc = pyutilib.subprocess.run(cmd, outfile=outfile)
+ rc = run(cmd, outfile=outfile)
self.assertNotEqual(rc[0], 0)
self._assert_contains(
outfile,
@@ -172,7 +170,7 @@ def test_bad_component_type(self):
cmd, output_dir = self._get_cmd(
join(thisdir, "model_bad_component_type.py"))
outfile = output_dir+".out"
- rc = pyutilib.subprocess.run(cmd, outfile=outfile)
+ rc = run(cmd, outfile=outfile)
self.assertNotEqual(rc[0], 0)
self._assert_contains(
outfile,
@@ -188,7 +186,7 @@ def test_unsupported_variable_bounds(self):
cmd, output_dir = self._get_cmd(
join(thisdir, "model_unsupported_variable_bounds.py"))
outfile = output_dir+".out"
- rc = pyutilib.subprocess.run(cmd, outfile=outfile)
+ rc = run(cmd, outfile=outfile)
self.assertNotEqual(rc[0], 0)
self._assert_contains(
outfile,
diff --git a/pyomo/pysp/tests/convert/test_smps_embedded.py b/pyomo/pysp/tests/convert/test_smps_embedded.py
index fe19ace5096..f28151c5d6c 100644
--- a/pyomo/pysp/tests/convert/test_smps_embedded.py
+++ b/pyomo/pysp/tests/convert/test_smps_embedded.py
@@ -9,7 +9,6 @@
# ___________________________________________________________________________
import sys
-import re
import os
import tempfile
from os.path import join, dirname, abspath
@@ -17,7 +16,7 @@
import filecmp
import shutil
-import pyutilib.misc
+from pyutilib.misc import import_file
import pyutilib.th as unittest
from six import StringIO
@@ -27,14 +26,14 @@
pysp_examples_dir = \
join(dirname(dirname(dirname(dirname(thisdir)))), "examples", "pysp")
-import pyomo.environ
-import pyomo.environ as aml
+import pyomo.environ as pyo
from pyomo.pysp.embeddedsp import (EmbeddedSP,
StochasticDataAnnotation,
TableDistribution,
UniformDistribution,
StageCostAnnotation,
VariableStageAnnotation)
+from pyomo.pysp.convert.smps import convert_embedded
baa99_basemodel = None
piecewise_model_embedded = None
@@ -46,13 +45,13 @@ def setUpModule():
fname = os.path.join(pysp_examples_dir, "baa99", "baa99_basemodel.py")
if os.path.exists(fname+"c"):
os.remove(fname+"c")
- baa99_basemodel = pyutilib.misc.import_file(fname)
+ baa99_basemodel = import_file(fname)
if "piecewise_model_embedded" in sys.modules:
del sys.modules["piecewise_model_embedded"]
fname = os.path.join(thisdir, "piecewise_model_embedded.py")
if os.path.exists(fname+"c"):
os.remove(fname+"c")
- piecewise_model_embedded = pyutilib.misc.import_file(fname)
+ piecewise_model_embedded = import_file(fname)
def tearDownModule():
global baa99_basemodel
@@ -78,18 +77,18 @@ def tearDownClass(cls):
cls.tmpdir = None
def _get_base_model(self):
- model = aml.ConcreteModel()
- model.x = aml.Var()
- model.y = aml.Var()
- model.d1 = aml.Param(mutable=True, initialize=0.0)
- model.d2 = aml.Param(mutable=True, initialize=0.0)
- model.d3 = aml.Param(mutable=True, initialize=0.0)
- model.cost = aml.Expression([1,2])
+ model = pyo.ConcreteModel()
+ model.x = pyo.Var()
+ model.y = pyo.Var()
+ model.d1 = pyo.Param(mutable=True, initialize=0.0)
+ model.d2 = pyo.Param(mutable=True, initialize=0.0)
+ model.d3 = pyo.Param(mutable=True, initialize=0.0)
+ model.cost = pyo.Expression([1,2])
model.cost[1].expr = model.x
model.cost[2].expr = model.d1*model.y
- model.o = aml.Objective(expr= model.cost[1]+model.cost[2])
- model.c1 = aml.Constraint(expr= model.x >= 0)
- model.c2 = aml.Constraint(expr= model.y*model.d2 >= model.d3)
+ model.o = pyo.Objective(expr= model.cost[1]+model.cost[2])
+ model.c1 = pyo.Constraint(expr= model.x >= 0)
+ model.c2 = pyo.Constraint(expr= model.y*model.d2 >= model.d3)
model.varstage = VariableStageAnnotation()
model.varstage.declare(model.x, 1)
model.varstage.declare(model.y, 2)
@@ -115,9 +114,7 @@ def test_makes_directory(self):
shutil.rmtree(tmpdir, ignore_errors=True)
self.assertFalse(os.path.exists(tmpdir))
sp = EmbeddedSP(self._get_base_model())
- pyomo.pysp.convert.smps.convert_embedded(tmpdir,
- 'test',
- sp)
+ convert_embedded(tmpdir, 'test', sp)
self.assertTrue(os.path.exists(tmpdir))
shutil.rmtree(tmpdir, ignore_errors=True)
@@ -125,9 +122,7 @@ def test_too_many_stages(self):
sp = EmbeddedSP(self._get_base_model())
sp.time_stages = [1,2,3]
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(str(cm.exception),
("SMPS conversion does not yet handle more "
"than 2 time-stages"))
@@ -144,9 +139,7 @@ class _Junk(object):
sp.has_stochastic_variable_bounds = True
self.assertEqual(sp.has_stochastic_variable_bounds, True)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(str(cm.exception),
("Problems with stochastic variables bounds "
"can not be converted into an embedded "
@@ -157,9 +150,7 @@ def test_nonlinear_stoch_objective(self):
model.cost[2].expr = model.y**2 + model.d1
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertTrue(str(cm.exception).startswith(
"Cannot output embedded SP representation for component "
"'o'. The embedded SMPS writer does not yet handle "
@@ -170,9 +161,7 @@ def test_stoch_data_too_many_uses_objective(self):
model.cost[2].expr = model.d1*model.y + model.d1
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(
str(cm.exception),
("Cannot output embedded SP representation for component "
@@ -190,9 +179,7 @@ def test_stoch_data_nontrivial_expression_objective1(self):
model.cost[2].expr = -model.d1*model.y
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertTrue(str(cm.exception).startswith(
"Cannot output embedded SP representation for component "
"'o'. The embedded SMPS writer does not yet handle the "
@@ -204,16 +191,14 @@ def test_stoch_data_nontrivial_expression_objective1(self):
def test_stoch_data_nontrivial_expression_objective2(self):
model = self._get_base_model()
- model.q = aml.Param(mutable=True, initialize=0.0)
+ model.q = pyo.Param(mutable=True, initialize=0.0)
model.stochdata.declare(
model.q,
distribution=TableDistribution([0.0,1.0]))
model.cost[2].expr = (model.d1+model.q)*model.y
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(
str(cm.exception),
("Cannot output embedded SP representation for component "
@@ -232,9 +217,7 @@ def test_bad_distribution_objective(self):
distribution=UniformDistribution(0.0,1.0))
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(
str(cm.exception),
("Invalid distribution type 'UniformDistribution' for stochastic "
@@ -247,9 +230,7 @@ def test_nonlinear_stoch_constraint(self):
model.c2._body = model.d2*model.y**2
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertTrue(str(cm.exception).startswith(
"Cannot output embedded SP representation for component "
"'c2'. The embedded SMPS writer does not yet handle "
@@ -257,16 +238,14 @@ def test_nonlinear_stoch_constraint(self):
def test_stoch_constraint_body_constant(self):
model = self._get_base_model()
- model.q = aml.Param(mutable=True, initialize=0.0)
+ model.q = pyo.Param(mutable=True, initialize=0.0)
model.stochdata.declare(
model.q,
distribution=TableDistribution([0.0,1.0]))
model.c2._body = model.d2*model.y + model.q
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(
str(cm.exception),
("Cannot output embedded SP representation for component "
@@ -279,16 +258,14 @@ def test_stoch_constraint_body_constant(self):
def test_stoch_range_constraint(self):
model = self._get_base_model()
- model.q = aml.Param(mutable=True, initialize=0.0)
+ model.q = pyo.Param(mutable=True, initialize=0.0)
model.stochdata.declare(
model.q,
distribution=TableDistribution([0.0,1.0]))
- model.c3 = aml.Constraint(expr=aml.inequality(model.q, model.y, 0))
+ model.c3 = pyo.Constraint(expr=pyo.inequality(model.q, model.y, 0))
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(
str(cm.exception),
("Cannot output embedded SP representation for component "
@@ -300,9 +277,7 @@ def test_stoch_data_too_many_uses_constraint(self):
model.c2._lower = model.d2
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(
str(cm.exception),
("Cannot output embedded SP representation for component "
@@ -320,9 +295,7 @@ def test_stoch_data_nontrivial_expression_constraint1(self):
model.c2._body = -model.d2*model.y
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertTrue(str(cm.exception).startswith(
"Cannot output embedded SP representation for component "
"'c2'. The embedded SMPS writer does not yet handle the "
@@ -334,16 +307,14 @@ def test_stoch_data_nontrivial_expression_constraint1(self):
def test_stoch_data_nontrivial_expression_constraint2(self):
model = self._get_base_model()
- model.q = aml.Param(mutable=True, initialize=0.0)
+ model.q = pyo.Param(mutable=True, initialize=0.0)
model.stochdata.declare(
model.q,
distribution=TableDistribution([0.0,1.0]))
model.c2._body = (model.d2+model.q)*model.y
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(
str(cm.exception),
("Cannot output embedded SP representation for component "
@@ -362,9 +333,7 @@ def test_bad_distribution_constraint(self):
distribution=UniformDistribution(0.0,1.0))
sp = EmbeddedSP(model)
with self.assertRaises(ValueError) as cm:
- pyomo.pysp.convert.smps.convert_embedded(self.tmpdir,
- 'test',
- sp)
+ convert_embedded(self.tmpdir, 'test', sp)
self.assertEqual(
str(cm.exception),
("Invalid distribution type 'UniformDistribution' for stochastic "
@@ -419,10 +388,7 @@ def _run(self, sp, basename, **kwds):
shutil.rmtree(output_directory,
ignore_errors=True)
os.makedirs(output_directory)
- pyomo.pysp.convert.smps.convert_embedded(output_directory,
- basename,
- sp,
- **kwds)
+ convert_embedded(output_directory, basename, sp, **kwds)
return output_directory
def _get_baa99_sp(self):
diff --git a/pyomo/pysp/tests/convert/utils.py b/pyomo/pysp/tests/convert/utils.py
index 29b38e59aa6..b5e7d17435c 100644
--- a/pyomo/pysp/tests/convert/utils.py
+++ b/pyomo/pysp/tests/convert/utils.py
@@ -1,12 +1,21 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
from pyomo.core import *
from pyomo.pysp.scenariotree.tree_structure_model import \
ScenarioTreeModelFromNetworkX
-from pyomo.pysp.annotations import \
- (ConstraintStageAnnotation,
- StochasticConstraintBoundsAnnotation,
- StochasticConstraintBodyAnnotation,
- StochasticObjectiveAnnotation,
- StochasticVariableBoundsAnnotation)
+from pyomo.pysp.annotations import (ConstraintStageAnnotation,
+ StochasticConstraintBoundsAnnotation,
+ StochasticConstraintBodyAnnotation,
+ StochasticObjectiveAnnotation,
+ StochasticVariableBoundsAnnotation)
def simple_twostage_scenario_tree():
from pyomo.pysp.scenariotree.tree_structure_model \
@@ -53,7 +62,7 @@ def simple_threestage_scenario_tree():
st_model.StageCost[second_stage] = 'StageCost[2]'
st_model.StageVariables[second_stage].add('y')
# Third Stage
- st_model.StageCost[thrid_stage] = 'StageCost[3]'
+ st_model.StageCost[third_stage] = 'StageCost[3]'
st_model.StageVariables[second_stage].add('z')
return st_model
diff --git a/pyomo/pysp/tests/evalxhat/test_evaluate_xhat.py b/pyomo/pysp/tests/evalxhat/test_evaluate_xhat.py
index ef91d1fc337..b2660d1c87b 100644
--- a/pyomo/pysp/tests/evalxhat/test_evaluate_xhat.py
+++ b/pyomo/pysp/tests/evalxhat/test_evaluate_xhat.py
@@ -8,24 +8,18 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import sys
-import socket
import os
from os.path import join, dirname, abspath
import time
import subprocess
import shutil
-import pyutilib.services
import pyutilib.th as unittest
from pyutilib.pyro import using_pyro3, using_pyro4
from pyomo.pysp.util.misc import (_get_test_nameserver,
_get_test_dispatcher,
_poll,
_kill)
-from pyomo.environ import *
-
-from six import StringIO
networkx_available = False
try:
diff --git a/pyomo/pysp/tests/examples/ef_checker.py b/pyomo/pysp/tests/examples/ef_checker.py
index 265bbb430d0..60b880e82af 100644
--- a/pyomo/pysp/tests/examples/ef_checker.py
+++ b/pyomo/pysp/tests/examples/ef_checker.py
@@ -325,5 +325,4 @@ def main(args=None):
if __name__ == "__main__":
- import sys
main(args=sys.argv[1:])
diff --git a/pyomo/pysp/tests/examples/ph_checker.py b/pyomo/pysp/tests/examples/ph_checker.py
index 0caffd2ab36..416ebc02c68 100644
--- a/pyomo/pysp/tests/examples/ph_checker.py
+++ b/pyomo/pysp/tests/examples/ph_checker.py
@@ -625,5 +625,4 @@ def main(args=None):
if __name__ == "__main__":
- import sys
sys.exit(main(args=sys.argv[1:]))
diff --git a/pyomo/pysp/tests/examples/rapper_based.py b/pyomo/pysp/tests/examples/rapper_based.py
index 222203b7445..69a0ee40b0f 100644
--- a/pyomo/pysp/tests/examples/rapper_based.py
+++ b/pyomo/pysp/tests/examples/rapper_based.py
@@ -9,19 +9,13 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import collections
-import math
import sys
-
import pyutilib.th as unittest
import tempfile
-import sys
import os
import shutil
-import json
import pyomo.environ as pyo
import pyomo.pysp.util.rapper as rapper
-from pyomo.pysp.scenariotree.tree_structure_model import CreateAbstractScenarioTreeModel
import pyomo as pyomoroot
solvername = "ipopt" # could use almost any solver
diff --git a/pyomo/pysp/tests/examples/test_ef.py b/pyomo/pysp/tests/examples/test_ef.py
index 380a0c417c5..910a199cecf 100644
--- a/pyomo/pysp/tests/examples/test_ef.py
+++ b/pyomo/pysp/tests/examples/test_ef.py
@@ -11,7 +11,6 @@
import sys
import fnmatch
import os
-import subprocess
from os.path import abspath, dirname, join, basename
try:
@@ -356,7 +355,6 @@ def setUpClass(cls):
_disable_stdout_test = False
- import sys
if '--include' in sys.argv:
_test_name_wildcard_include = []
while '--include' in sys.argv:
diff --git a/pyomo/pysp/tests/examples/test_examples.py b/pyomo/pysp/tests/examples/test_examples.py
index f52872a9984..ec61beba5f7 100644
--- a/pyomo/pysp/tests/examples/test_examples.py
+++ b/pyomo/pysp/tests/examples/test_examples.py
@@ -13,13 +13,10 @@
from os.path import join, dirname, abspath
import time
import subprocess
-import difflib
-import filecmp
import shutil
import sys
from pyutilib.pyro import using_pyro3, using_pyro4
-import pyutilib.services
import pyutilib.th as unittest
from pyomo.common.dependencies import networkx_available as have_networkx
@@ -27,10 +24,8 @@
_get_test_dispatcher,
_poll,
_kill)
-import pyomo.environ
from pyomo.opt import check_available_solvers
-from six import StringIO
have_dot = True
try:
diff --git a/pyomo/pysp/tests/examples/test_model/continuous/ReferenceModel.py b/pyomo/pysp/tests/examples/test_model/continuous/ReferenceModel.py
index 66272a8949e..e4696ea798d 100644
--- a/pyomo/pysp/tests/examples/test_model/continuous/ReferenceModel.py
+++ b/pyomo/pysp/tests/examples/test_model/continuous/ReferenceModel.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, Param, Expression
model = AbstractModel()
diff --git a/pyomo/pysp/tests/examples/test_model/discrete/ReferenceModel.py b/pyomo/pysp/tests/examples/test_model/discrete/ReferenceModel.py
index a887c6cf6b8..3dc9798adc4 100644
--- a/pyomo/pysp/tests/examples/test_model/discrete/ReferenceModel.py
+++ b/pyomo/pysp/tests/examples/test_model/discrete/ReferenceModel.py
@@ -8,12 +8,11 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, Param, Constraint, Objective, Expression, Boolean
model = AbstractModel()
model.x = Var(within=Boolean)
-
model.y = Var()
model.c = Param()
diff --git a/pyomo/pysp/tests/examples/test_model/feas/ReferenceModel.py b/pyomo/pysp/tests/examples/test_model/feas/ReferenceModel.py
index ee800411975..d1ffe11d3a8 100644
--- a/pyomo/pysp/tests/examples/test_model/feas/ReferenceModel.py
+++ b/pyomo/pysp/tests/examples/test_model/feas/ReferenceModel.py
@@ -7,52 +7,52 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-
-from pyomo.environ import *
-
-model = AbstractModel()
-
-model.xIndex = RangeSet(2)
-
-model.x = Var(model.xIndex, within=Boolean)
-model.y = Var()
-model.slackbool = Var(within=Boolean)
-
-model.a = Param()
-model.b = Param()
-model.c = Param()
-model.M = Param()
-
-# Making x1=0 infeasible in scenario 2. Note that default is b1 = 0, b2 = 1, so this is
-# trivially true in scenario 1 and makes x1=0 infeasible in scenario 2.
-def test_rule(model):
- return model.b <= model.b * model.x[1]
-model.test = Constraint(rule=test_rule)
-
-# you can get y=one with anything, but for y=zero, you need all x zero
-def y_is_geq_x_rule(model, i):
- return model.y >= model.x[i]
-model.y_is_geq_x = Constraint(model.xIndex, rule=y_is_geq_x_rule)
-
-# you can get y=zero with anything, but for y=one, you need at least one one
-# but if you don't have at least one one, you have to have y=0
-def y_is_leq_sum_x_rule(model):
- return model.y <= sum_product(model.x)
-model.y_is_leq_sum_x = Constraint(rule=y_is_leq_sum_x_rule)
-
-def slacker_rule(model):
- return model.a * model.y + model.slackbool >= model.b
-model.slacker = Constraint(rule=slacker_rule)
-
-def FirstStageCost_rule(model):
- return 0
-model.FirstStageCost = Expression(rule=FirstStageCost_rule)
-
-def SecondStageCost_rule(model):
- return model.c * model.y + model.M * model.slackbool + sum_product(model.x)
-model.SecondStageCost = Expression(rule=SecondStageCost_rule)
-
-def Obj_rule(model):
- #return model.FirstStageCost + model.SecondStageCost
- return model.FirstStageCost + model.SecondStageCost
-model.Obj = Objective(rule=Obj_rule)
+
+from pyomo.environ import AbstractModel, RangeSet, Var, Param, Constraint, Objective, Expression, Boolean, sum_product
+
+model = AbstractModel()
+
+model.xIndex = RangeSet(2)
+
+model.x = Var(model.xIndex, within=Boolean)
+model.y = Var()
+model.slackbool = Var(within=Boolean)
+
+model.a = Param()
+model.b = Param()
+model.c = Param()
+model.M = Param()
+
+# Making x1=0 infeasible in scenario 2. Note that default is b1 = 0, b2 = 1, so this is
+# trivially true in scenario 1 and makes x1=0 infeasible in scenario 2.
+def test_rule(model):
+ return model.b <= model.b * model.x[1]
+model.test = Constraint(rule=test_rule)
+
+# you can get y=one with anything, but for y=zero, you need all x zero
+def y_is_geq_x_rule(model, i):
+ return model.y >= model.x[i]
+model.y_is_geq_x = Constraint(model.xIndex, rule=y_is_geq_x_rule)
+
+# you can get y=zero with anything, but for y=one, you need at least one one
+# but if you don't have at least one one, you have to have y=0
+def y_is_leq_sum_x_rule(model):
+ return model.y <= sum_product(model.x)
+model.y_is_leq_sum_x = Constraint(rule=y_is_leq_sum_x_rule)
+
+def slacker_rule(model):
+ return model.a * model.y + model.slackbool >= model.b
+model.slacker = Constraint(rule=slacker_rule)
+
+def FirstStageCost_rule(model):
+ return 0
+model.FirstStageCost = Expression(rule=FirstStageCost_rule)
+
+def SecondStageCost_rule(model):
+ return model.c * model.y + model.M * model.slackbool + sum_product(model.x)
+model.SecondStageCost = Expression(rule=SecondStageCost_rule)
+
+def Obj_rule(model):
+ #return model.FirstStageCost + model.SecondStageCost
+ return model.FirstStageCost + model.SecondStageCost
+model.Obj = Objective(rule=Obj_rule)
diff --git a/pyomo/pysp/tests/examples/test_model/slackpenalty/ReferenceModel.py b/pyomo/pysp/tests/examples/test_model/slackpenalty/ReferenceModel.py
index b42fd79f40a..6e563c3b991 100644
--- a/pyomo/pysp/tests/examples/test_model/slackpenalty/ReferenceModel.py
+++ b/pyomo/pysp/tests/examples/test_model/slackpenalty/ReferenceModel.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Var, Param, Constraint, Objective, Expression, Boolean
model = AbstractModel()
diff --git a/pyomo/pysp/tests/examples/test_model/twovarslack/ReferenceModel.py b/pyomo/pysp/tests/examples/test_model/twovarslack/ReferenceModel.py
index 261f4e9f273..1b0592ffb03 100644
--- a/pyomo/pysp/tests/examples/test_model/twovarslack/ReferenceModel.py
+++ b/pyomo/pysp/tests/examples/test_model/twovarslack/ReferenceModel.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, RangeSet, Var, Param, Constraint, Objective, Expression, Boolean, sum_product
model = AbstractModel()
diff --git a/pyomo/pysp/tests/examples/test_ph.py b/pyomo/pysp/tests/examples/test_ph.py
index a081f332542..3bd3c382386 100644
--- a/pyomo/pysp/tests/examples/test_ph.py
+++ b/pyomo/pysp/tests/examples/test_ph.py
@@ -26,7 +26,6 @@
import pyutilib.th as unittest
from pyutilib.misc.comparison import open_possibly_compressed_file
-import pyutilib.services
from pyomo.common.dependencies import yaml_available
from pyomo.pysp.util.misc import (_get_test_nameserver,
_get_test_dispatcher,
diff --git a/pyomo/pysp/tests/rapper/abstract_rapper_tester.py b/pyomo/pysp/tests/rapper/abstract_rapper_tester.py
index 26abd574ae8..8ac05a23e9c 100644
--- a/pyomo/pysp/tests/rapper/abstract_rapper_tester.py
+++ b/pyomo/pysp/tests/rapper/abstract_rapper_tester.py
@@ -1,22 +1,28 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
# Provide some test for rapper
# Author: David L. Woodruff (Sept 2018)
import pyutilib.th as unittest
-import tempfile
import sys
import os
-import shutil
-import json
-import pyomo.environ as pyo
+from pyomo.environ import SolverFactory, TerminationCondition
import pyomo.pysp.util.rapper as rapper
-from pyomo.pysp.scenariotree.tree_structure_model import CreateAbstractScenarioTreeModel
import pyomo as pyomoroot
__author__ = 'David L. Woodruff '
__version__ = 1.5
solvername = "ipopt" # could use almost any solver
-solver_available = pyo.SolverFactory(solvername).available(False)
+solver_available = SolverFactory(solvername).available(False)
class Test_abstract_rapper(unittest.TestCase):
""" Test the rapper code."""
@@ -67,7 +73,7 @@ def test_Abstract_ef(self):
phopts = None)
ef_sol = stsolver.solve_ef(solvername)
assert(ef_sol.solver.termination_condition \
- == pyo.TerminationCondition.optimal)
+ == TerminationCondition.optimal)
# see also foo.py
if __name__ == '__main__':
diff --git a/pyomo/pysp/tests/rapper/rapper_tester.py b/pyomo/pysp/tests/rapper/rapper_tester.py
index c428b0d3f34..8813ad7358e 100644
--- a/pyomo/pysp/tests/rapper/rapper_tester.py
+++ b/pyomo/pysp/tests/rapper/rapper_tester.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
# Provide some test for rapper; most are smoke because PySP is tested elsewhere
# Author: David L. Woodruff (circa March 2017; Sept 2018; Feb 2020)
@@ -6,8 +16,7 @@
import sys
import os
import shutil
-import json
-import pyomo.environ as pyo
+from pyomo.environ import SolverFactory, TerminationCondition
import pyomo.pysp.util.rapper as rapper
from pyomo.pysp.scenariotree.tree_structure_model import CreateAbstractScenarioTreeModel
import pyomo.pysp.plugins.csvsolutionwriter as csvw
@@ -23,7 +32,7 @@
__version__ = 1.7
solvername = "ipopt" # could use almost any solver
-solver_available = pyo.SolverFactory(solvername).available(False)
+solver_available = SolverFactory(solvername).available(False)
class Testrapper(unittest.TestCase):
""" Test the rapper code."""
@@ -109,7 +118,7 @@ def test_ef_solve(self):
tree_model = self.farmer_concrete_tree)
ef_sol = stsolver.solve_ef(solvername)
assert(ef_sol.solver.termination_condition \
- == pyo.TerminationCondition.optimal)
+ == TerminationCondition.optimal)
for name, varval in stsolver.root_Var_solution():
#print (name, str(varval))
pass
diff --git a/pyomo/pysp/tests/scenariotreemanager/dummy_model.py b/pyomo/pysp/tests/scenariotreemanager/dummy_model.py
index 937db42bf07..d82ed037594 100644
--- a/pyomo/pysp/tests/scenariotreemanager/dummy_model.py
+++ b/pyomo/pysp/tests/scenariotreemanager/dummy_model.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Expression, ConstraintList, Objective, sum_product
def pysp_scenario_tree_model_callback():
from pyomo.pysp.scenariotree.tree_structure_model \
diff --git a/pyomo/pysp/tests/scenariotreemanager/test_scenariotreemanager.py b/pyomo/pysp/tests/scenariotreemanager/test_scenariotreemanager.py
index 015d16822ee..d12ff13d46e 100644
--- a/pyomo/pysp/tests/scenariotreemanager/test_scenariotreemanager.py
+++ b/pyomo/pysp/tests/scenariotreemanager/test_scenariotreemanager.py
@@ -24,7 +24,6 @@
_ordered_dict_ = ordereddict.OrderedDict
from pyutilib.pyro import using_pyro3, using_pyro4
-import pyutilib.services
import pyutilib.th as unittest
from pyomo.common.dependencies import dill, dill_available
@@ -49,7 +48,7 @@
from pyomo.pysp.scenariotree.instance_factory import \
ScenarioTreeInstanceFactory
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Expression, Constraint, Objective, sum_product
thisfile = os.path.abspath(__file__)
thisdir = os.path.dirname(thisfile)
diff --git a/pyomo/pysp/tests/scenariotreemanager/test_scenariotreemanagersolver.py b/pyomo/pysp/tests/scenariotreemanager/test_scenariotreemanagersolver.py
index 527b527240d..828fcdf9c56 100644
--- a/pyomo/pysp/tests/scenariotreemanager/test_scenariotreemanagersolver.py
+++ b/pyomo/pysp/tests/scenariotreemanager/test_scenariotreemanagersolver.py
@@ -14,7 +14,6 @@
import subprocess
from pyutilib.pyro import using_pyro3, using_pyro4
-import pyutilib.services
import pyutilib.th as unittest
from pyomo.common.dependencies import dill, dill_available as has_dill
@@ -22,7 +21,6 @@
_get_test_dispatcher,
_poll,
_kill)
-from pyomo.pysp.util.config import PySPConfigBlock
from pyomo.pysp.scenariotree.manager import \
(ScenarioTreeManagerClientSerial,
ScenarioTreeManagerClientPyro)
@@ -31,9 +29,8 @@
from pyomo.pysp.scenariotree.manager_solver import \
(ScenarioTreeManagerSolverFactory,
PySPFailedSolveStatus)
-from pyomo.opt import undefined
-import pyomo.environ as aml
+import pyomo.environ as pyo
from pyomo.common.dependencies import (
networkx, networkx_available as has_networkx
@@ -143,17 +140,17 @@ def get_factory():
cost="t1_cost")
tree.add_edge("r", "s"+str(i), weight=1.0/3)
- model = aml.ConcreteModel()
- model.x = aml.Var()
- model.Y = aml.Var([1])
- model.stale = aml.Var(initialize=0.0)
- model.fixed = aml.Var(initialize=0.0)
+ model = pyo.ConcreteModel()
+ model.x = pyo.Var()
+ model.Y = pyo.Var([1])
+ model.stale = pyo.Var(initialize=0.0)
+ model.fixed = pyo.Var(initialize=0.0)
model.fixed.fix()
- model.p = aml.Param(mutable=True)
- model.t0_cost = aml.Expression(expr=model.x)
- model.t1_cost = aml.Expression(expr=model.Y[1])
- model.o = aml.Objective(expr=model.t0_cost + model.t1_cost)
- model.c = aml.ConstraintList()
+ model.p = pyo.Param(mutable=True)
+ model.t0_cost = pyo.Expression(expr=model.x)
+ model.t1_cost = pyo.Expression(expr=model.Y[1])
+ model.o = pyo.Objective(expr=model.t0_cost + model.t1_cost)
+ model.c = pyo.ConstraintList()
model.c.add(model.x >= 1)
model.c.add(model.Y[1] >= model.p)
@@ -227,17 +224,17 @@ def get_factory():
cost="t1_cost")
tree.add_edge("r", "s"+str(i), weight=1.0/3)
- model = aml.ConcreteModel()
- model.x = aml.Var()
- model.Y = aml.Var([1], bounds=(None, 1))
- model.stale = aml.Var(initialize=0.0)
- model.fixed = aml.Var(initialize=0.0)
+ model = pyo.ConcreteModel()
+ model.x = pyo.Var()
+ model.Y = pyo.Var([1], bounds=(None, 1))
+ model.stale = pyo.Var(initialize=0.0)
+ model.fixed = pyo.Var(initialize=0.0)
model.fixed.fix()
- model.p = aml.Param(mutable=True)
- model.t0_cost = aml.Expression(expr=model.x)
- model.t1_cost = aml.Expression(expr=model.Y[1])
- model.o = aml.Objective(expr=model.t0_cost + model.t1_cost)
- model.c = aml.ConstraintList()
+ model.p = pyo.Param(mutable=True)
+ model.t0_cost = pyo.Expression(expr=model.x)
+ model.t1_cost = pyo.Expression(expr=model.Y[1])
+ model.o = pyo.Objective(expr=model.t0_cost + model.t1_cost)
+ model.c = pyo.ConstraintList()
model.c.add(model.x >= 1)
model.c.add(model.Y[1] >= model.p)
@@ -341,17 +338,17 @@ def get_factory():
bundle="b"+str(i))
tree.add_edge("r", "s"+str(i), weight=1.0/3)
- model = aml.ConcreteModel()
- model.x = aml.Var()
- model.Y = aml.Var([1])
- model.stale = aml.Var(initialize=0.0)
- model.fixed = aml.Var(initialize=0.0)
+ model = pyo.ConcreteModel()
+ model.x = pyo.Var()
+ model.Y = pyo.Var([1])
+ model.stale = pyo.Var(initialize=0.0)
+ model.fixed = pyo.Var(initialize=0.0)
model.fixed.fix()
- model.p = aml.Param(mutable=True)
- model.t0_cost = aml.Expression(expr=model.x)
- model.t1_cost = aml.Expression(expr=model.Y[1])
- model.o = aml.Objective(expr=model.t0_cost + model.t1_cost)
- model.c = aml.ConstraintList()
+ model.p = pyo.Param(mutable=True)
+ model.t0_cost = pyo.Expression(expr=model.x)
+ model.t1_cost = pyo.Expression(expr=model.Y[1])
+ model.o = pyo.Objective(expr=model.t0_cost + model.t1_cost)
+ model.c = pyo.ConstraintList()
model.c.add(model.x >= 1)
model.c.add(model.Y[1] >= model.p)
@@ -435,17 +432,17 @@ def get_factory():
bundle="b"+str(i))
tree.add_edge("r", "s"+str(i), weight=1.0/3)
- model = aml.ConcreteModel()
- model.x = aml.Var()
- model.Y = aml.Var([1], bounds=(None, 1))
- model.stale = aml.Var(initialize=0.0)
- model.fixed = aml.Var(initialize=0.0)
+ model = pyo.ConcreteModel()
+ model.x = pyo.Var()
+ model.Y = pyo.Var([1], bounds=(None, 1))
+ model.stale = pyo.Var(initialize=0.0)
+ model.fixed = pyo.Var(initialize=0.0)
model.fixed.fix()
- model.p = aml.Param(mutable=True)
- model.t0_cost = aml.Expression(expr=model.x)
- model.t1_cost = aml.Expression(expr=model.Y[1])
- model.o = aml.Objective(expr=model.t0_cost + model.t1_cost)
- model.c = aml.ConstraintList()
+ model.p = pyo.Param(mutable=True)
+ model.t0_cost = pyo.Expression(expr=model.x)
+ model.t1_cost = pyo.Expression(expr=model.Y[1])
+ model.o = pyo.Objective(expr=model.t0_cost + model.t1_cost)
+ model.c = pyo.ConstraintList()
model.c.add(model.x >= 1)
model.c.add(model.Y[1] >= model.p)
diff --git a/pyomo/pysp/tests/test_benders.py b/pyomo/pysp/tests/test_benders.py
index 4ba3ce7351f..d4d8b8b5f1d 100644
--- a/pyomo/pysp/tests/test_benders.py
+++ b/pyomo/pysp/tests/test_benders.py
@@ -27,8 +27,6 @@
#
import pyutilib.th as unittest
-import pyomo.opt
-
def filter_fn(line):
tmp = line.strip()
return tmp.startswith('WARNING') and 'CBC' in tmp
diff --git a/pyomo/pysp/tests/unit/test_annotations.py b/pyomo/pysp/tests/unit/test_annotations.py
index 8ecb46591b3..791c5cc7782 100644
--- a/pyomo/pysp/tests/unit/test_annotations.py
+++ b/pyomo/pysp/tests/unit/test_annotations.py
@@ -7,9 +7,10 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as aml
+import pyomo.environ as pyo
from pyomo.pysp.annotations import (locate_annotations,
StageCostAnnotation,
PySP_StageCostAnnotation,
@@ -49,40 +50,40 @@ def test_deprecated(self):
type(PySP_StochasticObjectiveAnnotation()))
def _populate_block_with_vars_expressions(self, b):
- b.x = aml.Var()
- b.X1 = aml.Var([1])
- b.X2 = aml.Var([1])
- b.e = aml.Expression()
- b.E1 = aml.Expression([1])
- b.E2 = aml.Expression([1])
+ b.x = pyo.Var()
+ b.X1 = pyo.Var([1])
+ b.X2 = pyo.Var([1])
+ b.e = pyo.Expression()
+ b.E1 = pyo.Expression([1])
+ b.E2 = pyo.Expression([1])
def _populate_block_with_vars(self, b):
- b.x = aml.Var()
- b.X1 = aml.Var([1])
- b.X2 = aml.Var([1])
+ b.x = pyo.Var()
+ b.X1 = pyo.Var([1])
+ b.X2 = pyo.Var([1])
def _populate_block_with_constraints(self, b):
- b.x = aml.Var()
- b.c = aml.Constraint(expr= b.x == 1)
- b.C1 = aml.Constraint([1], rule=lambda m, i: m.x == 1)
- b.C2 = aml.Constraint([1], rule=lambda m, i: m.x == 1)
- b.C3 = aml.ConstraintList()
+ b.x = pyo.Var()
+ b.c = pyo.Constraint(expr= b.x == 1)
+ b.C1 = pyo.Constraint([1], rule=lambda m, i: m.x == 1)
+ b.C2 = pyo.Constraint([1], rule=lambda m, i: m.x == 1)
+ b.C3 = pyo.ConstraintList()
b.C3.add(b.x == 1)
def _populate_block_with_objectives(self, b):
- b.x = aml.Var()
- b.o = aml.Objective(expr= b.x + 1)
- b.O1 = aml.Objective([1], rule=lambda m, i: m.x + 1)
- b.O2 = aml.Objective([1], rule=lambda m, i: m.x + 1)
+ b.x = pyo.Var()
+ b.o = pyo.Objective(expr= b.x + 1)
+ b.O1 = pyo.Objective([1], rule=lambda m, i: m.x + 1)
+ b.O2 = pyo.Objective([1], rule=lambda m, i: m.x + 1)
def _populate_block_with_params(self, b):
- b.p = aml.Param(mutable=True ,initialize=0)
- b.P1 = aml.Param([1], mutable=True, initialize=0)
- b.P2 = aml.Param([1], mutable=True, initialize=0)
+ b.p = pyo.Param(mutable=True ,initialize=0)
+ b.P1 = pyo.Param([1], mutable=True, initialize=0)
+ b.P2 = pyo.Param([1], mutable=True, initialize=0)
def test_multiple_declarations(self):
- m = aml.ConcreteModel()
- m.x = aml.Var()
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
a = StageCostAnnotation()
a.declare(m, 1)
a.declare(m.x, 1)
@@ -90,9 +91,9 @@ def test_multiple_declarations(self):
a.expand_entries()
def test_locate_annotations(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
m.a = StageCostAnnotation()
- m.b = aml.Block()
+ m.b = pyo.Block()
m.b.a = StageCostAnnotation()
self.assertEqual(locate_annotations(m, StageCostAnnotation),
[('a', m.a), ('a', m.b.a)])
@@ -105,14 +106,14 @@ def test_locate_annotations(self):
[])
def test_stage_cost(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
self._populate_block_with_vars_expressions(m)
- m.b = aml.Block()
+ m.b = pyo.Block()
self._populate_block_with_vars_expressions(m.b)
- m.b_inactive = aml.Block()
+ m.b_inactive = pyo.Block()
self._populate_block_with_vars_expressions(m.b_inactive)
m.b_inactive.deactivate()
- m.B = aml.Block([1],
+ m.B = pyo.Block([1],
rule=lambda b: \
self._populate_block_with_vars_expressions(b))
@@ -151,14 +152,14 @@ def test_stage_cost(self):
('B[1].e', 2), ('B[1].E1', 2), ('B[1].E2', 2)]))
def test_variable_stage(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
self._populate_block_with_vars_expressions(m)
- m.b = aml.Block()
+ m.b = pyo.Block()
self._populate_block_with_vars_expressions(m.b)
- m.b_inactive = aml.Block()
+ m.b_inactive = pyo.Block()
self._populate_block_with_vars_expressions(m.b_inactive)
m.b_inactive.deactivate()
- m.B = aml.Block([1],
+ m.B = pyo.Block([1],
rule=lambda b: \
self._populate_block_with_vars_expressions(b))
@@ -197,14 +198,14 @@ def test_variable_stage(self):
('B[1].e', (2,True)), ('B[1].E1', (2,True)), ('B[1].E2', (2,True))]))
def test_constraint_stage(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
self._populate_block_with_constraints(m)
- m.b = aml.Block()
+ m.b = pyo.Block()
self._populate_block_with_constraints(m.b)
- m.b_inactive = aml.Block()
+ m.b_inactive = pyo.Block()
self._populate_block_with_constraints(m.b_inactive)
m.b_inactive.deactivate()
- m.B = aml.Block([1],
+ m.B = pyo.Block([1],
rule=lambda b: \
self._populate_block_with_constraints(b))
@@ -235,14 +236,14 @@ def test_constraint_stage(self):
('B[1].c', 2), ('B[1].C1', 2), ('B[1].C2', 2), ('B[1].C3', 2)]))
def test_stochastic_data(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
self._populate_block_with_params(m)
- m.b = aml.Block()
+ m.b = pyo.Block()
self._populate_block_with_params(m.b)
- m.b_inactive = aml.Block()
+ m.b_inactive = pyo.Block()
self._populate_block_with_params(m.b_inactive)
m.b_inactive.deactivate()
- m.B = aml.Block([1],
+ m.B = pyo.Block([1],
rule=lambda b: \
self._populate_block_with_params(b))
@@ -270,14 +271,14 @@ def test_stochastic_data(self):
('B[1].p', 2), ('B[1].P1', 2), ('B[1].P2', 2)]))
def test_constraint_bounds(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
self._populate_block_with_constraints(m)
- m.b = aml.Block()
+ m.b = pyo.Block()
self._populate_block_with_constraints(m.b)
- m.b_inactive = aml.Block()
+ m.b_inactive = pyo.Block()
self._populate_block_with_constraints(m.b_inactive)
m.b_inactive.deactivate()
- m.B = aml.Block([1],
+ m.B = pyo.Block([1],
rule=lambda b: \
self._populate_block_with_constraints(b))
@@ -308,14 +309,14 @@ def test_constraint_bounds(self):
('B[1].C2', (False,True)), ('B[1].C3', (False,True))]))
def test_stochastic_constraint_body(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
self._populate_block_with_constraints(m)
- m.b = aml.Block()
+ m.b = pyo.Block()
self._populate_block_with_constraints(m.b)
- m.b_inactive = aml.Block()
+ m.b_inactive = pyo.Block()
self._populate_block_with_constraints(m.b_inactive)
m.b_inactive.deactivate()
- m.B = aml.Block([1],
+ m.B = pyo.Block([1],
rule=lambda b: \
self._populate_block_with_constraints(b))
@@ -344,14 +345,14 @@ def test_stochastic_constraint_body(self):
('B[1].c', 2), ('B[1].C1', 2), ('B[1].C2', 2), ('B[1].C3', 2)]))
def test_stochastic_objective(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
self._populate_block_with_objectives(m)
- m.b = aml.Block()
+ m.b = pyo.Block()
self._populate_block_with_objectives(m.b)
- m.b_inactive = aml.Block()
+ m.b_inactive = pyo.Block()
self._populate_block_with_objectives(m.b_inactive)
m.b_inactive.deactivate()
- m.B = aml.Block([1],
+ m.B = pyo.Block([1],
rule=lambda b: \
self._populate_block_with_objectives(b))
@@ -379,14 +380,14 @@ def test_stochastic_objective(self):
('B[1].o', (1,False)), ('B[1].O1', (1,False)), ('B[1].O2', (1,False))]))
def test_stochastic_variable_bounds(self):
- m = aml.ConcreteModel()
+ m = pyo.ConcreteModel()
self._populate_block_with_vars(m)
- m.b = aml.Block()
+ m.b = pyo.Block()
self._populate_block_with_vars(m.b)
- m.b_inactive = aml.Block()
+ m.b_inactive = pyo.Block()
self._populate_block_with_vars(m.b_inactive)
m.b_inactive.deactivate()
- m.B = aml.Block([1],
+ m.B = pyo.Block([1],
rule=lambda b: \
self._populate_block_with_vars(b))
diff --git a/pyomo/pysp/tests/unit/test_ph.py b/pyomo/pysp/tests/unit/test_ph.py
index 111969e9267..7893a97f7cb 100644
--- a/pyomo/pysp/tests/unit/test_ph.py
+++ b/pyomo/pysp/tests/unit/test_ph.py
@@ -15,7 +15,6 @@
import os
import sys
import subprocess
-import time
from os.path import abspath, dirname
try:
@@ -38,7 +37,6 @@
#
import pyutilib.misc
import pyutilib.th as unittest
-import pyutilib.services
from pyutilib.pyro import using_pyro3, using_pyro4
from pyomo.pysp.util.misc import (_get_test_nameserver,
@@ -49,6 +47,7 @@
import pyomo.pysp
import pyomo.pysp.phinit
import pyomo.pysp.ef_writer_script
+import pyomo.environ
_diff_tolerance = 1e-5
_diff_tolerance_relaxed = 1e-3
diff --git a/pyomo/pysp/tests/unit/testdata/ReferenceModel.py b/pyomo/pysp/tests/unit/testdata/ReferenceModel.py
index d0015c24935..dd34bdc1e4e 100644
--- a/pyomo/pysp/tests/unit/testdata/ReferenceModel.py
+++ b/pyomo/pysp/tests/unit/testdata/ReferenceModel.py
@@ -1,4 +1,14 @@
-from pyomo.environ import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.environ import AbstractModel, Var, Param, Expression, Objective, Constraint
model = AbstractModel()
model.x = Var()
diff --git a/pyomo/pysp/tests/unit/testdata/both_callbacks.py b/pyomo/pysp/tests/unit/testdata/both_callbacks.py
index 3ea3fb3d6cb..f7cd1861ea6 100644
--- a/pyomo/pysp/tests/unit/testdata/both_callbacks.py
+++ b/pyomo/pysp/tests/unit/testdata/both_callbacks.py
@@ -1,4 +1,14 @@
-from pyomo.environ import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.environ import AbstractModel, Var, Param, Expression, Objective, Constraint
model = AbstractModel()
model.x = Var()
diff --git a/pyomo/pysp/tests/unit/testdata/reference_test_model.py b/pyomo/pysp/tests/unit/testdata/reference_test_model.py
index d0015c24935..dd34bdc1e4e 100644
--- a/pyomo/pysp/tests/unit/testdata/reference_test_model.py
+++ b/pyomo/pysp/tests/unit/testdata/reference_test_model.py
@@ -1,4 +1,14 @@
-from pyomo.environ import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.environ import AbstractModel, Var, Param, Expression, Objective, Constraint
model = AbstractModel()
model.x = Var()
diff --git a/pyomo/pysp/tests/unit/testdata/reference_test_model_with_callback.py b/pyomo/pysp/tests/unit/testdata/reference_test_model_with_callback.py
index 996bcd23984..36ebb7023ad 100644
--- a/pyomo/pysp/tests/unit/testdata/reference_test_model_with_callback.py
+++ b/pyomo/pysp/tests/unit/testdata/reference_test_model_with_callback.py
@@ -1,4 +1,14 @@
-from pyomo.environ import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.environ import AbstractModel, Var, Param, Expression, Objective, Constraint
model = AbstractModel()
model.x = Var()
diff --git a/pyomo/pysp/tests/unit/testdata/reference_test_scenario_tree_model.py b/pyomo/pysp/tests/unit/testdata/reference_test_scenario_tree_model.py
index 3dd8635d928..429c0e00fa4 100644
--- a/pyomo/pysp/tests/unit/testdata/reference_test_scenario_tree_model.py
+++ b/pyomo/pysp/tests/unit/testdata/reference_test_scenario_tree_model.py
@@ -1,7 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import os
import tempfile
-from pyomo.environ import *
from pyomo.pysp.scenariotree.tree_structure_model import \
CreateAbstractScenarioTreeModel
diff --git a/pyomo/pysp/util/configured_object.py b/pyomo/pysp/util/configured_object.py
index ecf81ca53c7..53e3a05739c 100644
--- a/pyomo/pysp/util/configured_object.py
+++ b/pyomo/pysp/util/configured_object.py
@@ -11,13 +11,10 @@
__all__ = ('PySPConfiguredObject', 'PySPConfiguredExtension')
import inspect
-import copy
-import sys
from collections import defaultdict
from pyomo.common.plugin import SingletonPlugin
-from pyomo.pysp.util.config import (PySPConfigValue,
- PySPConfigBlock,
+from pyomo.pysp.util.config import (PySPConfigBlock,
safe_declare_option,
check_options_match,
safe_declare_common_option,
diff --git a/pyomo/pysp/util/misc.py b/pyomo/pysp/util/misc.py
index d19c6ee9c39..9a904c030aa 100644
--- a/pyomo/pysp/util/misc.py
+++ b/pyomo/pysp/util/misc.py
@@ -17,23 +17,12 @@
import six
import sys
import subprocess
-import traceback
import inspect
import argparse
-# for profiling
-try:
- import cProfile as profile
-except ImportError:
- import profile
-try:
- import pstats
- pstats_available=True
-except ImportError:
- pstats_available=False
from pyutilib.misc import PauseGC, import_file
from pyutilib.services import TempfileManager
-import pyutilib.common
+from pyutilib.common import ApplicationError
from pyomo.opt.base import ConverterError
from pyomo.common.dependencies import attempt_import
from pyomo.common.plugin import (ExtensionPoint,
@@ -307,7 +296,20 @@ def launch_command(command,
rc = 0
- if pstats_available and (profile_count > 0):
+ if profile_count > 0:
+ # Defer import of profiling packages until we know that they
+ # are needed
+ try:
+ try:
+ import cProfile as profile
+ except ImportError:
+ import profile
+ import pstats
+ except ImportError:
+ configure_loggers(shutdown=True)
+ raise ValueError(
+ "Cannot use the 'profile' option: the Python "
+ "'profile' or 'pstats' package cannot be imported!")
#
# Call the main routine with profiling.
#
@@ -372,7 +374,7 @@ def launch_command(command,
sys.stderr.write(error_label+"CONVERTER ERROR:\n")
sys.stderr.write(str(sys.exc_info()[1])+"\n")
raise
- except pyutilib.common.ApplicationError:
+ except ApplicationError:
sys.stderr.write(error_label+"APPLICATION ERROR:\n")
sys.stderr.write(str(sys.exc_info()[1])+"\n")
raise
diff --git a/pyomo/pysp/util/rapper.py b/pyomo/pysp/util/rapper.py
index ee588e7b2b8..87d972c1696 100644
--- a/pyomo/pysp/util/rapper.py
+++ b/pyomo/pysp/util/rapper.py
@@ -6,17 +6,12 @@
"""
import inspect
-from pyomo.environ import *
+from pyomo.environ import SolverFactory
from pyomo.pysp.scenariotree.instance_factory \
import ScenarioTreeInstanceFactory
-import pyomo.pysp.ef as pyspef # import (create_ef_instance, solve_ef)
-from pyomo.pysp.ef_writer_script import ExtensiveFormAlgorithm
-from pyomo.pysp.scenariotree.tree_structure_model import CreateAbstractScenarioTreeModel
-from pyomo.pysp.scenariotree.instance_factory import \
- ScenarioTreeInstanceFactory
+from pyomo.pysp.ef import create_ef_instance
-import pyomo.pysp.phinit as phinit
-import os
+from pyomo.pysp.phinit import construct_ph_options_parser, GenerateScenarioTreeForPH, PHAlgorithmBuilder
def _optiondict_2_list(phopts, args_list = None):
""" A little utility to change the format of options"""
@@ -100,7 +95,7 @@ def __init__(self, fsfile,
if fsfct is None:
# Changed in October 2018: None implies AbstractModel
args_list = _optiondict_2_list(phopts)
- parser = phinit.construct_ph_options_parser("")
+ parser = construct_ph_options_parser("")
options = parser.parse_args(args_list)
scenario_instance_factory = \
@@ -108,7 +103,7 @@ def __init__(self, fsfile,
try:
self.scenario_tree = \
- phinit.GenerateScenarioTreeForPH(options,
+ GenerateScenarioTreeForPH(options,
scenario_instance_factory)
except:
print ("ERROR in StochSolver called from",inspect.stack()[1][3])
@@ -169,7 +164,7 @@ def make_ef(self,
Returns:
ef_instance: the ef object
"""
- return pyspef.create_ef_instance(self.scenario_tree,
+ return create_ef_instance(self.scenario_tree,
verbose_output=verbose,
generate_weighted_cvar = generate_weighted_cvar,
cvar_weight = cvar_weight,
@@ -268,7 +263,7 @@ def solve_ph(self, subsolver, default_rho, phopts = None, sopts = None):
ph = None
# Build up the options for PH.
- parser = phinit.construct_ph_options_parser("")
+ parser = construct_ph_options_parser("")
phargslist = ['--default-rho',str(default_rho)]
phargslist.append('--solver')
phargslist.append(str(subsolver))
@@ -285,7 +280,7 @@ def solve_ph(self, subsolver, default_rho, phopts = None, sopts = None):
# construct the PH solver object
try:
- ph = phinit.PHAlgorithmBuilder(phoptions, self.scenario_tree)
+ ph = PHAlgorithmBuilder(phoptions, self.scenario_tree)
except:
print ("Internal error: ph construction failed.")
if ph is not None:
diff --git a/pyomo/repn/__init__.py b/pyomo/repn/__init__.py
index df023a13d6a..8dc77c6c02b 100644
--- a/pyomo/repn/__init__.py
+++ b/pyomo/repn/__init__.py
@@ -8,5 +8,5 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.repn.standard_repn import *
-from pyomo.repn.standard_aux import *
+from pyomo.repn.standard_repn import StandardRepn, generate_standard_repn
+from pyomo.repn.standard_aux import compute_standard_repn
diff --git a/pyomo/repn/beta/matrix.py b/pyomo/repn/beta/matrix.py
index ef7d3724769..2d0e3daeb82 100644
--- a/pyomo/repn/beta/matrix.py
+++ b/pyomo/repn/beta/matrix.py
@@ -18,8 +18,7 @@
from pyomo.core.base.set_types import Any
from pyomo.core.base import (SortComponents,
- Var,
- Constraint)
+ Var)
from pyomo.core.base.numvalue import (is_fixed,
value,
ZeroConstant)
@@ -511,7 +510,6 @@ def index(self):
def variables(self):
"""A tuple of variables comprising the constraint body."""
comp = self.parent_component()
- index = self.index()
prows = comp._prows
jcols = comp._jcols
varmap = comp._varmap
@@ -528,7 +526,6 @@ def variables(self):
def coefficients(self):
"""A tuple of coefficients associated with the variables."""
comp = self.parent_component()
- index = self.index()
prows = comp._prows
jcols = comp._jcols
vals = comp._vals
@@ -548,7 +545,6 @@ def coefficients(self):
def constant(self):
"""The constant value associated with the constraint body."""
comp = self.parent_component()
- index = self.index()
prows = comp._prows
jcols = comp._jcols
vals = comp._vals
diff --git a/pyomo/repn/plugins/ampl/__init__.py b/pyomo/repn/plugins/ampl/__init__.py
index d5cdd62fbe1..24d85f1f4eb 100644
--- a/pyomo/repn/plugins/ampl/__init__.py
+++ b/pyomo/repn/plugins/ampl/__init__.py
@@ -8,4 +8,4 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.repn.plugins.ampl.ampl_ import *
+from pyomo.repn.plugins.ampl.ampl_ import ProblemWriter_nl
diff --git a/pyomo/repn/plugins/ampl/ampl_.py b/pyomo/repn/plugins/ampl/ampl_.py
index b3a054fadff..e53f147a045 100644
--- a/pyomo/repn/plugins/ampl/ampl_.py
+++ b/pyomo/repn/plugins/ampl/ampl_.py
@@ -28,20 +28,15 @@
from pyutilib.math.util import isclose
from pyutilib.misc import PauseGC
-from pyomo.opt import ProblemFormat
-from pyomo.opt.base import *
+from pyomo.opt import ProblemFormat, AbstractProblemWriter, WriterFactory
from pyomo.core.expr import current as EXPR
from pyomo.core.expr.numvalue import (NumericConstant,
native_numeric_types,
- value)
-from pyomo.core.base import *
-from pyomo.core.base import SymbolMap, Block
-from pyomo.core.base.var import Var
-from pyomo.core.base import _ExpressionData, Expression, SortComponents
-from pyomo.core.base import var
-from pyomo.core.base import param
+ value,
+ is_fixed)
+from pyomo.core.base import SymbolMap, NameLabeler, _ExpressionData, SortComponents, var, param, Var, ExternalFunction, ComponentMap, Objective, Constraint, SOSConstraint, Suffix
import pyomo.core.base.suffix
-from pyomo.repn.standard_repn import StandardRepn, generate_standard_repn
+from pyomo.repn.standard_repn import generate_standard_repn
import pyomo.core.kernel.suffix
from pyomo.core.kernel.block import IBlock
diff --git a/pyomo/repn/plugins/baron_writer.py b/pyomo/repn/plugins/baron_writer.py
index d53f59a36a3..a4d49a6cb7e 100644
--- a/pyomo/repn/plugins/baron_writer.py
+++ b/pyomo/repn/plugins/baron_writer.py
@@ -15,15 +15,13 @@
import itertools
import logging
import math
-from six import iteritems, StringIO, iterkeys
-from six.moves import xrange
-from pyutilib.math import isclose
+from six import iteritems, StringIO
from pyomo.common.collections import OrderedSet
from pyomo.opt import ProblemFormat
from pyomo.opt.base import AbstractProblemWriter, WriterFactory
from pyomo.core.expr.numvalue import (
- is_fixed, value, native_numeric_types, native_types, nonpyomo_leaf_types,
+ value, native_numeric_types, native_types, nonpyomo_leaf_types,
)
from pyomo.core.expr import current as EXPR
from pyomo.core.base import (SortComponents,
@@ -32,10 +30,8 @@
NumericLabeler,
Constraint,
Objective,
- Var, Param)
+ Param)
from pyomo.core.base.component import ActiveComponent
-from pyomo.core.base.set_types import *
-from pyomo.core.kernel.base import ICategorizedObject
#CLH: EXPORT suffixes "constraint_types" and "branching_priorities"
# pass their respective information to the .bar file
import pyomo.core.base.suffix
@@ -364,7 +360,7 @@ def _skip_trivial(constraint_data):
else:
def mutable_param_gen(b):
for param in block.component_objects(Param):
- if param._mutable and param.is_indexed():
+ if param.mutable and param.is_indexed():
param_data_iter = \
(param_data for index, param_data
in iteritems(param))
@@ -635,7 +631,7 @@ def __call__(self,
# GAH: Not sure this is necessary, and also it would break for
# non-mutable indexed params so I am commenting out for now.
#for param_data in active_components_data(block, Param, sort=sorter):
- #instead of checking if param_data._mutable:
+ #instead of checking if param_data.mutable:
#if not param_data.is_constant():
# create_symbol_func(symbol_map, param_data, labeler)
diff --git a/pyomo/repn/plugins/cpxlp.py b/pyomo/repn/plugins/cpxlp.py
index f0262b1e508..d0ef1e9d4f4 100644
--- a/pyomo/repn/plugins/cpxlp.py
+++ b/pyomo/repn/plugins/cpxlp.py
@@ -13,11 +13,8 @@
#
import logging
-import math
-import operator
-from six import iterkeys, iteritems, StringIO
-from six.moves import xrange
+from six import iteritems
from pyutilib.misc import PauseGC
from pyomo.opt import ProblemFormat
diff --git a/pyomo/repn/plugins/gams_writer.py b/pyomo/repn/plugins/gams_writer.py
index 091054fdaaf..1c3000a6d30 100644
--- a/pyomo/repn/plugins/gams_writer.py
+++ b/pyomo/repn/plugins/gams_writer.py
@@ -13,18 +13,17 @@
#
from six import StringIO, string_types, iteritems
-from six.moves import xrange
from pyutilib.misc import PauseGC
from pyomo.core.expr import current as EXPR
from pyomo.core.expr.numvalue import (
- is_fixed, value, as_numeric, native_types, native_numeric_types,
+ value, as_numeric, native_types, native_numeric_types,
nonpyomo_leaf_types,
)
from pyomo.core.base import (
- SymbolMap, ShortNameLabeler, NumericLabeler, Block, Constraint, Expression,
- Objective, Var, Param, minimize, Suffix, SortComponents)
+ SymbolMap, ShortNameLabeler, NumericLabeler, Constraint,
+ Objective, Var, minimize, SortComponents)
from pyomo.core.base.component import ActiveComponent
from pyomo.core.kernel.base import ICategorizedObject
from pyomo.opt import ProblemFormat
diff --git a/pyomo/repn/plugins/mps.py b/pyomo/repn/plugins/mps.py
index 8e3651b6e35..d5131c8bf24 100644
--- a/pyomo/repn/plugins/mps.py
+++ b/pyomo/repn/plugins/mps.py
@@ -13,10 +13,8 @@
#
import logging
-import math
-import operator
-from six import iteritems, iterkeys, StringIO
+from six import iteritems, StringIO
from six.moves import xrange
from pyutilib.misc import PauseGC
diff --git a/pyomo/repn/standard_repn.py b/pyomo/repn/standard_repn.py
index b543f264e59..447d27f0c59 100644
--- a/pyomo/repn/standard_repn.py
+++ b/pyomo/repn/standard_repn.py
@@ -15,14 +15,12 @@
import sys
import logging
-import math
import itertools
from pyomo.core.base import (Constraint,
Objective,
ComponentMap)
-from pyutilib.misc import Bunch
from pyutilib.math.util import isclose as isclose_default
from pyomo.core.expr import current as EXPR
@@ -33,20 +31,15 @@
from pyomo.core.base.var import (SimpleVar,
Var,
_GeneralVarData,
- _VarData,
value)
-from pyomo.core.base.param import _ParamData
from pyomo.core.base.numvalue import (NumericConstant,
- native_numeric_types,
- is_fixed)
-from pyomo.core.kernel.expression import IIdentityExpression, expression, noclone
-from pyomo.core.kernel.variable import IVariable
+ native_numeric_types)
+from pyomo.core.kernel.expression import expression, noclone
+from pyomo.core.kernel.variable import IVariable, variable
from pyomo.core.kernel.objective import objective
-import six
-from six import iteritems
-from six import itervalues, iteritems, StringIO
-from six.moves import xrange, zip
+from six import iteritems, StringIO, PY3
+from six.moves import zip
try:
basestring
except:
@@ -54,10 +47,8 @@
logger = logging.getLogger('pyomo.core')
-using_py3 = six.PY3
+using_py3 = PY3
-from pyomo.core.base import _VarData, _GeneralVarData, SimpleVar
-from pyomo.core.kernel.variable import IVariable, variable
#
@@ -621,10 +612,10 @@ def _collect_prod(exp, multiplier, idMap, compute_values, verbose, quadratic):
ans = Results()
ans.constant = multiplier*lhs.constant * rhs.constant
if not (lhs.constant.__class__ in native_numeric_types and lhs.constant == 0):
- for key, coef in six.iteritems(rhs.linear):
+ for key, coef in iteritems(rhs.linear):
ans.linear[key] = multiplier*coef*lhs.constant
if not (rhs.constant.__class__ in native_numeric_types and rhs.constant == 0):
- for key, coef in six.iteritems(lhs.linear):
+ for key, coef in iteritems(lhs.linear):
if key in ans.linear:
ans.linear[key] += multiplier*coef*rhs.constant
else:
@@ -632,26 +623,26 @@ def _collect_prod(exp, multiplier, idMap, compute_values, verbose, quadratic):
if quadratic:
if not (lhs.constant.__class__ in native_numeric_types and lhs.constant == 0):
- for key, coef in six.iteritems(rhs.quadratic):
+ for key, coef in iteritems(rhs.quadratic):
ans.quadratic[key] = multiplier*coef*lhs.constant
if not (rhs.constant.__class__ in native_numeric_types and rhs.constant == 0):
- for key, coef in six.iteritems(lhs.quadratic):
+ for key, coef in iteritems(lhs.quadratic):
if key in ans.quadratic:
ans.quadratic[key] += multiplier*coef*rhs.constant
else:
ans.quadratic[key] = multiplier*coef*rhs.constant
- for lkey, lcoef in six.iteritems(lhs.linear):
- for rkey, rcoef in six.iteritems(rhs.linear):
+ for lkey, lcoef in iteritems(lhs.linear):
+ for rkey, rcoef in iteritems(rhs.linear):
ndx = (lkey, rkey) if lkey <= rkey else (rkey, lkey)
if ndx in ans.quadratic:
ans.quadratic[ndx] += multiplier*lcoef*rcoef
else:
ans.quadratic[ndx] = multiplier*lcoef*rcoef
# TODO - Use quicksum here?
- el_linear = multiplier*sum(coef*idMap[key] for key, coef in six.iteritems(lhs.linear))
- er_linear = multiplier*sum(coef*idMap[key] for key, coef in six.iteritems(rhs.linear))
- el_quadratic = multiplier*sum(coef*idMap[key[0]]*idMap[key[1]] for key, coef in six.iteritems(lhs.quadratic))
- er_quadratic = multiplier*sum(coef*idMap[key[0]]*idMap[key[1]] for key, coef in six.iteritems(rhs.quadratic))
+ el_linear = multiplier*sum(coef*idMap[key] for key, coef in iteritems(lhs.linear))
+ er_linear = multiplier*sum(coef*idMap[key] for key, coef in iteritems(rhs.linear))
+ el_quadratic = multiplier*sum(coef*idMap[key[0]]*idMap[key[1]] for key, coef in iteritems(lhs.quadratic))
+ er_quadratic = multiplier*sum(coef*idMap[key[0]]*idMap[key[1]] for key, coef in iteritems(rhs.quadratic))
ans.nonl += el_linear*er_quadratic + el_quadratic*er_linear
return ans
@@ -908,7 +899,7 @@ def _collect_comparison(exp, multiplier, idMap, compute_values, verbose, quadrat
def _collect_external_fn(exp, multiplier, idMap, compute_values, verbose, quadratic):
if compute_values and exp.is_fixed():
- return Results(nonl=multiplier*value(exp))
+ return Results(constant=multiplier*value(exp))
return Results(nonl=multiplier*exp)
diff --git a/pyomo/repn/tests/ampl/small10_testCase.py b/pyomo/repn/tests/ampl/small10_testCase.py
index 069d78fd66c..fca443d6470 100644
--- a/pyomo/repn/tests/ampl/small10_testCase.py
+++ b/pyomo/repn/tests/ampl/small10_testCase.py
@@ -18,7 +18,7 @@
# will not solve if sent to a real optimizer.
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Param, Objective, Constraint, simple_constraint_rule
model = ConcreteModel()
diff --git a/pyomo/repn/tests/ampl/small11_testCase.py b/pyomo/repn/tests/ampl/small11_testCase.py
index 34d2b4a3c30..3f9159312f4 100644
--- a/pyomo/repn/tests/ampl/small11_testCase.py
+++ b/pyomo/repn/tests/ampl/small11_testCase.py
@@ -20,7 +20,7 @@
# will not solve if sent to a real optimizer.
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint, RangeSet
model = ConcreteModel()
n=3
diff --git a/pyomo/repn/tests/ampl/small12_testCase.py b/pyomo/repn/tests/ampl/small12_testCase.py
index 7dc5e5b980d..33e49d89142 100644
--- a/pyomo/repn/tests/ampl/small12_testCase.py
+++ b/pyomo/repn/tests/ampl/small12_testCase.py
@@ -16,7 +16,7 @@
# will not solve if sent to a real optimizer.
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Param, Objective, Constraint, inequality
from pyomo.core.expr.current import Expr_if
diff --git a/pyomo/repn/tests/ampl/small13_testCase.py b/pyomo/repn/tests/ampl/small13_testCase.py
index c08c59b2c53..93fe17338cc 100644
--- a/pyomo/repn/tests/ampl/small13_testCase.py
+++ b/pyomo/repn/tests/ampl/small13_testCase.py
@@ -16,7 +16,7 @@
# will not solve if sent to a real optimizer.
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint, maximize
model = ConcreteModel()
diff --git a/pyomo/repn/tests/ampl/small14_testCase.py b/pyomo/repn/tests/ampl/small14_testCase.py
index 822be0f3f64..c83ca30b945 100644
--- a/pyomo/repn/tests/ampl/small14_testCase.py
+++ b/pyomo/repn/tests/ampl/small14_testCase.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint, log, log10, sin, cos, tan, sinh, cosh, tanh, asin, acos, atan, asinh, acosh, atanh, exp, sqrt, ceil, floor
from math import e, pi
model = ConcreteModel()
diff --git a/pyomo/repn/tests/ampl/small15_testCase.py b/pyomo/repn/tests/ampl/small15_testCase.py
index d600fe525f3..08d18d03fa4 100644
--- a/pyomo/repn/tests/ampl/small15_testCase.py
+++ b/pyomo/repn/tests/ampl/small15_testCase.py
@@ -17,7 +17,7 @@
# Test if variables in deactivated blocks are found
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Block, Objective, Constraint
model = ConcreteModel()
diff --git a/pyomo/repn/tests/ampl/small1_testCase.py b/pyomo/repn/tests/ampl/small1_testCase.py
index 7d3ba631cc8..afd3379c71c 100644
--- a/pyomo/repn/tests/ampl/small1_testCase.py
+++ b/pyomo/repn/tests/ampl/small1_testCase.py
@@ -15,7 +15,7 @@
# '# nonlinear vars in constraints, objectives, both'
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint
model = ConcreteModel()
diff --git a/pyomo/repn/tests/ampl/small2_testCase.py b/pyomo/repn/tests/ampl/small2_testCase.py
index 300c3b2d58b..add77c8053d 100644
--- a/pyomo/repn/tests/ampl/small2_testCase.py
+++ b/pyomo/repn/tests/ampl/small2_testCase.py
@@ -15,7 +15,7 @@
# '# nonlinear vars in constraints, objectives, both'
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint
model = ConcreteModel()
diff --git a/pyomo/repn/tests/ampl/small3_testCase.py b/pyomo/repn/tests/ampl/small3_testCase.py
index b1ebbe59060..e945a4d60e8 100644
--- a/pyomo/repn/tests/ampl/small3_testCase.py
+++ b/pyomo/repn/tests/ampl/small3_testCase.py
@@ -15,7 +15,7 @@
# '# nonlinear vars in constraints, objectives, both'
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint
model = ConcreteModel()
diff --git a/pyomo/repn/tests/ampl/small4_testCase.py b/pyomo/repn/tests/ampl/small4_testCase.py
index 34d9b028d78..a1d8defe56a 100644
--- a/pyomo/repn/tests/ampl/small4_testCase.py
+++ b/pyomo/repn/tests/ampl/small4_testCase.py
@@ -16,7 +16,7 @@
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint
model = ConcreteModel()
diff --git a/pyomo/repn/tests/ampl/small5_testCase.py b/pyomo/repn/tests/ampl/small5_testCase.py
index c5345b19568..a9a4ff147c4 100644
--- a/pyomo/repn/tests/ampl/small5_testCase.py
+++ b/pyomo/repn/tests/ampl/small5_testCase.py
@@ -22,7 +22,7 @@
# will not solve if sent to a real optimizer.
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Param, Objective, Constraint
model = ConcreteModel()
model.x = Var(bounds=(-1.0,1.0),initialize=1.0)
diff --git a/pyomo/repn/tests/ampl/small6_testCase.py b/pyomo/repn/tests/ampl/small6_testCase.py
index 7051c24867b..80b8349c16f 100644
--- a/pyomo/repn/tests/ampl/small6_testCase.py
+++ b/pyomo/repn/tests/ampl/small6_testCase.py
@@ -22,7 +22,7 @@
# will not solve if sent to a real optimizer.
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint
model = ConcreteModel()
model.x = Var(bounds=(-1.0,1.0),initialize=1.0)
diff --git a/pyomo/repn/tests/ampl/small7_testCase.py b/pyomo/repn/tests/ampl/small7_testCase.py
index 33eea2c5f01..6f110a8c235 100644
--- a/pyomo/repn/tests/ampl/small7_testCase.py
+++ b/pyomo/repn/tests/ampl/small7_testCase.py
@@ -22,7 +22,7 @@
# will not solve if sent to a real optimizer.
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Param, Objective, Constraint
model = ConcreteModel()
model.x = Var(bounds=(-1.0,1.0),initialize=1.0)
diff --git a/pyomo/repn/tests/ampl/small8_testCase.py b/pyomo/repn/tests/ampl/small8_testCase.py
index 7da9fbb44b3..0cca02bac46 100644
--- a/pyomo/repn/tests/ampl/small8_testCase.py
+++ b/pyomo/repn/tests/ampl/small8_testCase.py
@@ -18,7 +18,7 @@
# will not solve if sent to a real optimizer.
#
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, Param, Var, NonNegativeReals, Objective, Constraint, minimize
model = AbstractModel()
diff --git a/pyomo/repn/tests/ampl/small9_testCase.py b/pyomo/repn/tests/ampl/small9_testCase.py
index f93971739b3..9856e8f4ea0 100644
--- a/pyomo/repn/tests/ampl/small9_testCase.py
+++ b/pyomo/repn/tests/ampl/small9_testCase.py
@@ -18,7 +18,7 @@
# will not solve if sent to a real optimizer.
#
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Param, Objective, Constraint, simple_constraint_rule
model = ConcreteModel()
diff --git a/pyomo/repn/tests/ampl/test_ampl_nl.py b/pyomo/repn/tests/ampl/test_ampl_nl.py
index 60155a8ba31..cab2319f543 100644
--- a/pyomo/repn/tests/ampl/test_ampl_nl.py
+++ b/pyomo/repn/tests/ampl/test_ampl_nl.py
@@ -12,13 +12,11 @@
#
import os
-import random
import pyutilib.th as unittest
from pyomo.common.getGSL import find_GSL
-from pyomo.environ import *
-import pyomo.opt
+from pyomo.environ import ConcreteModel, Var, Constraint, Objective, Param, Block, ExternalFunction, value
thisdir = os.path.dirname(os.path.abspath(__file__))
diff --git a/pyomo/repn/tests/ampl/test_ampl_repn.py b/pyomo/repn/tests/ampl/test_ampl_repn.py
index a80efa54125..8dc2674fe80 100644
--- a/pyomo/repn/tests/ampl/test_ampl_repn.py
+++ b/pyomo/repn/tests/ampl/test_ampl_repn.py
@@ -1,6 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-from pyomo.core import *
+from pyomo.core import ConcreteModel, Var, Param, Constraint, Objective, exp
from pyomo.repn.standard_repn import generate_standard_repn as gar
diff --git a/pyomo/repn/tests/ampl/test_suffixes.py b/pyomo/repn/tests/ampl/test_suffixes.py
index beb4bc0920f..f9d0e63c74f 100644
--- a/pyomo/repn/tests/ampl/test_suffixes.py
+++ b/pyomo/repn/tests/ampl/test_suffixes.py
@@ -18,7 +18,7 @@
import pyutilib.th as unittest
from pyomo.opt import ProblemFormat
-from pyomo.core import *
+from pyomo.core import ConcreteModel, Suffix, Var, Objective, Constraint, SOSConstraint, sum_product
class TestSuffix(unittest.TestCase):
diff --git a/pyomo/repn/tests/baron/small14a_testCase.py b/pyomo/repn/tests/baron/small14a_testCase.py
index bd0ee1d6d98..8fbec10ddd4 100644
--- a/pyomo/repn/tests/baron/small14a_testCase.py
+++ b/pyomo/repn/tests/baron/small14a_testCase.py
@@ -8,8 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
-from math import e, pi
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint, log, log10, exp, sqrt
model = ConcreteModel()
diff --git a/pyomo/repn/tests/baron/test_baron.py b/pyomo/repn/tests/baron/test_baron.py
index 52fe1ad0467..52faafbbf0d 100644
--- a/pyomo/repn/tests/baron/test_baron.py
+++ b/pyomo/repn/tests/baron/test_baron.py
@@ -15,8 +15,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
-import pyomo.opt
+from pyomo.environ import ConcreteModel, Var, Param, Constraint, Objective, Block, sin
thisdir = os.path.dirname(os.path.abspath(__file__))
diff --git a/pyomo/repn/tests/baron/test_baron_comparison.py b/pyomo/repn/tests/baron/test_baron_comparison.py
index 35fe5808f76..1b89126bff8 100644
--- a/pyomo/repn/tests/baron/test_baron_comparison.py
+++ b/pyomo/repn/tests/baron/test_baron_comparison.py
@@ -19,7 +19,6 @@
datadir = abspath(join(currdir, "..", "ampl"))+os.sep
import pyutilib.th as unittest
-import pyutilib.subprocess
import pyomo.scripting.pyomo_main as main
diff --git a/pyomo/repn/tests/cpxlp/test_cpxlp.py b/pyomo/repn/tests/cpxlp/test_cpxlp.py
index 1efcf7d116c..848deb64705 100644
--- a/pyomo/repn/tests/cpxlp/test_cpxlp.py
+++ b/pyomo/repn/tests/cpxlp/test_cpxlp.py
@@ -16,8 +16,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
-import pyomo.opt
+from pyomo.environ import ConcreteModel, Var, Constraint, Objective, Block, ComponentMap
thisdir = os.path.dirname(os.path.abspath(__file__))
diff --git a/pyomo/repn/tests/gams/small14a_testCase.py b/pyomo/repn/tests/gams/small14a_testCase.py
index c4e1edf194f..5c9e2cc3525 100644
--- a/pyomo/repn/tests/gams/small14a_testCase.py
+++ b/pyomo/repn/tests/gams/small14a_testCase.py
@@ -8,8 +8,8 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
-from math import e, pi
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint, log, log10, sin, cos, tan, sinh, cosh, tanh, asin, acos, atan, exp, sqrt, ceil, floor
+from math import pi
model = ConcreteModel()
diff --git a/pyomo/repn/tests/gams/test_gams_comparison.py b/pyomo/repn/tests/gams/test_gams_comparison.py
index 75eaedf94c2..fc44c5280b3 100644
--- a/pyomo/repn/tests/gams/test_gams_comparison.py
+++ b/pyomo/repn/tests/gams/test_gams_comparison.py
@@ -19,7 +19,6 @@
datadir = abspath(join(currdir, "..", "ampl"))+os.sep
import pyutilib.th as unittest
-import pyutilib.subprocess
import pyomo.scripting.pyomo_main as main
diff --git a/pyomo/repn/tests/mps/test_mps.py b/pyomo/repn/tests/mps/test_mps.py
index 62403c0fb3f..a3984863e22 100644
--- a/pyomo/repn/tests/mps/test_mps.py
+++ b/pyomo/repn/tests/mps/test_mps.py
@@ -16,8 +16,7 @@
import pyutilib.th as unittest
-from pyomo.environ import *
-import pyomo.opt
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint, ComponentMap
thisdir = os.path.dirname(os.path.abspath(__file__))
diff --git a/pyomo/repn/tests/test_standard.py b/pyomo/repn/tests/test_standard.py
index fd12f26de7a..98cc5d0ba36 100644
--- a/pyomo/repn/tests/test_standard.py
+++ b/pyomo/repn/tests/test_standard.py
@@ -17,12 +17,11 @@
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
-import pyutilib.services
from pyomo.core.expr.current import Expr_if
-from pyomo.core.expr import expr_common, current as EXPR
-from pyomo.repn import *
-from pyomo.environ import *
+from pyomo.core.expr import current as EXPR
+from pyomo.repn import generate_standard_repn
+from pyomo.environ import AbstractModel, ConcreteModel, Var, Param, Set, Expression, RangeSet, ExternalFunction, quicksum, cos, sin, summation, sum_product
import pyomo.kernel
from pyomo.core.base.numvalue import native_numeric_types, as_numeric
@@ -4147,14 +4146,21 @@ def _g(*args):
e = 100*m.g(1,2.0,'3')
rep = generate_standard_repn(e, compute_values=True)
self.assertEqual(str(rep.to_expression()), "300")
+ self.assertEqual(rep.polynomial_degree(), 0)
rep = generate_standard_repn(e, compute_values=False)
+ self.assertEqual(rep.polynomial_degree(), 0)
# The function ID is inconsistent, so we don't do a test
#self.assertEqual(str(rep.to_expression()), "100*g(0, 1, 2.0, '3')")
e = 100*m.g(1,2.0,'3',m.v)
rep = generate_standard_repn(e, compute_values=True)
self.assertEqual(str(rep.to_expression()), "400")
+ self.assertEqual(rep.polynomial_degree(), 0)
rep = generate_standard_repn(e, compute_values=False)
+ # FIXME: this is a lie: the degree should be 0, but because
+ # compute_falues=False creates a "structural" standard repn, the
+ # computed degree appears to be general nonlinear.
+ self.assertEqual(rep.polynomial_degree(), None)
# The function ID is inconsistent, so we don't do a test
#self.assertEqual(str(rep.to_expression()), "100*g(0, 1, 2.0, '3', v)")
diff --git a/pyomo/scripting/convert.py b/pyomo/scripting/convert.py
index a4458130bab..4d175c5e73f 100644
--- a/pyomo/scripting/convert.py
+++ b/pyomo/scripting/convert.py
@@ -15,14 +15,12 @@
from pyutilib.misc import Options, Container
-from pyomo.common import pyomo_command
from pyomo.opt import ProblemFormat
from pyomo.core.base import (Objective,
Var,
Constraint,
value,
ConcreteModel)
-import pyomo.scripting.util
_format = None
diff --git a/pyomo/scripting/driver_help.py b/pyomo/scripting/driver_help.py
index 2d81e47fae7..5f3f476f14f 100644
--- a/pyomo/scripting/driver_help.py
+++ b/pyomo/scripting/driver_help.py
@@ -15,7 +15,6 @@
import datetime
import textwrap
import logging
-import argparse
import socket
import pyutilib.subprocess
@@ -221,7 +220,6 @@ def help_api(options):
print(" "+line)
def help_environment():
- cmddir = os.path.dirname(os.path.abspath(sys.executable))+os.sep
info = Options()
#
info.python = Options()
diff --git a/pyomo/scripting/plugins/build_ext.py b/pyomo/scripting/plugins/build_ext.py
index ad3d5fc6578..bab611d0301 100644
--- a/pyomo/scripting/plugins/build_ext.py
+++ b/pyomo/scripting/plugins/build_ext.py
@@ -10,7 +10,6 @@
import logging
import sys
-from six import iteritems
from pyomo.common.extensions import ExtensionBuilderFactory
from pyomo.scripting.pyomo_parser import add_subparser
diff --git a/pyomo/scripting/plugins/convert.py b/pyomo/scripting/plugins/convert.py
index 2654e2b2796..061392a545f 100644
--- a/pyomo/scripting/plugins/convert.py
+++ b/pyomo/scripting/plugins/convert.py
@@ -13,7 +13,7 @@
import argparse
from pyutilib.misc import Options
-from pyomo.opt import ProblemFormat, ProblemConfigFactory, guess_format
+from pyomo.opt import ProblemConfigFactory, guess_format
from pyomo.scripting.pyomo_parser import add_subparser, CustomHelpFormatter
diff --git a/pyomo/scripting/plugins/download.py b/pyomo/scripting/plugins/download.py
index 8e2034ac5aa..e271c2fa847 100644
--- a/pyomo/scripting/plugins/download.py
+++ b/pyomo/scripting/plugins/download.py
@@ -10,7 +10,6 @@
import logging
import sys
-import traceback
from pyomo.common.download import FileDownloader, DownloadFactory
from pyomo.scripting.pyomo_parser import add_subparser
diff --git a/pyomo/scripting/plugins/extras.py b/pyomo/scripting/plugins/extras.py
index 6b5bab1150a..18dcc664dfe 100644
--- a/pyomo/scripting/plugins/extras.py
+++ b/pyomo/scripting/plugins/extras.py
@@ -36,7 +36,7 @@ def get_packages():
"Use of the pyomo install-extras is deprecated."
"The current recommended course of action is to manually install "
"optional dependencies as needed.",
- version='TBD')
+ version='5.7.1')
def install_extras(args=[], quiet=False):
#
# Verify that pip is installed
diff --git a/pyomo/scripting/pyomo_command.py b/pyomo/scripting/pyomo_command.py
index 9090eae1b99..150215fb962 100644
--- a/pyomo/scripting/pyomo_command.py
+++ b/pyomo/scripting/pyomo_command.py
@@ -8,12 +8,9 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import sys
-import argparse
from pyutilib.misc import Options, Container
-from pyomo.common import pyomo_command
from pyomo.common.dependencies import pympler_available
import pyomo.scripting.util
from pyomo.core import ConcreteModel
@@ -309,7 +306,7 @@ def run_pyomo(options=Options(), parser=None):
# model(=None) results in an a different error related to
# task port values. Not sure how to interpret that.
pyomo.scripting.util.finalize(data,
- model=ConcretModel(),
+ model=ConcreteModel(),
instance=None,
results=None)
return Container() #pragma:nocover
diff --git a/pyomo/scripting/pyomo_parser.py b/pyomo/scripting/pyomo_parser.py
index 151da763237..79754902a7a 100644
--- a/pyomo/scripting/pyomo_parser.py
+++ b/pyomo/scripting/pyomo_parser.py
@@ -11,7 +11,6 @@
__all__ = ['add_subparser', 'get_parser', 'subparsers']
import argparse
-import warnings
import sys
#
diff --git a/pyomo/scripting/pyro_mip_server.py b/pyomo/scripting/pyro_mip_server.py
index 75aed32a481..61787bb0b50 100755
--- a/pyomo/scripting/pyro_mip_server.py
+++ b/pyomo/scripting/pyro_mip_server.py
@@ -29,7 +29,7 @@
import pyutilib.services
import pyutilib.pyro
-from pyutilib.pyro import using_pyro4
+from pyutilib.pyro import using_pyro4, TaskProcessingError
import pyutilib.common
from pyomo.common import pyomo_command
from pyomo.opt.base import SolverFactory, ConverterError
diff --git a/pyomo/scripting/runtests.py b/pyomo/scripting/runtests.py
index e0cf765db7b..e5fee5d42cd 100644
--- a/pyomo/scripting/runtests.py
+++ b/pyomo/scripting/runtests.py
@@ -31,136 +31,136 @@ def runPyomoTests(argv=None):
return pyutilib.dev.runtests.run(targets, basedir, argv)
-def OLD_runPyomoTests():
- parser = optparse.OptionParser(usage='test.pyomo [options] ')
-
- parser.add_option('-d','--dir',
- action='store',
- dest='dir',
- default=None,
- help='Top-level source directory where the tests are applied.')
- parser.add_option('-e','--exclude',
- action='append',
- dest='exclude',
- default=[],
- help='Top-level source directories that are excluded.')
- parser.add_option('--cat','--category',
- action='store',
- dest='cat',
- default='smoke',
- help='Specify test category.')
- parser.add_option('--cov','--coverage',
- action='store_true',
- dest='coverage',
- default=False,
- help='Indicate that coverage information is collected')
- parser.add_option('-v','--verbose',
- action='store_true',
- dest='verbose',
- default=False,
- help='Verbose output')
- parser.add_option('-o','--output',
- action='store',
- dest='output',
- default=None,
- help='Redirect output to a file')
- parser.add_option('--with-doctest',
- action='store_true',
- dest='doctests',
- default=False,
- help='Run tests included in Sphinx documentation')
- parser.add_option('--doc-dir',
- action='store',
- dest='docdir',
- default=None,
- help='Top-level source directory for Sphinx documentation')
-
- _options, args = parser.parse_args(sys.argv)
-
- if _options.output:
- outfile = os.path.abspath(_options.output)
- else:
- outfile = None
-
- if _options.docdir:
- docdir = os.path.abspath(_options.docdir)
- if not os.path.exists(docdir):
- raise ValueError("Invalid documentation directory, "
- "path does not exist")
- elif _options.doctests:
- docdir = os.path.join('pyomo','doc','OnlineDocs')
- else:
- docdir = None
-
- if _options.dir is None:
- # the /src directory (for development installations)
- os.chdir( os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) )
- else:
- if os.path.exists(_options.dir):
- os.chdir( _options.dir )
-
- print("Running tests in directory %s" % os.getcwd())
- _options.cat = os.environ.get('PYUTILIB_UNITTEST_CATEGORY', _options.cat)
- if _options.cat == 'all':
- if 'PYUTILIB_UNITTEST_CATEGORY' in os.environ:
- del os.environ['PYUTILIB_UNITTEST_CATEGORY']
- elif _options.cat:
- os.environ['PYUTILIB_UNITTEST_CATEGORY'] = _options.cat
- print(" ... for test category: %s" % os.environ['PYUTILIB_UNITTEST_CATEGORY'])
-
- options=[]
- if _options.coverage:
- options.append('--coverage')
- if _options.verbose:
- options.append('-v')
- if _options.doctests:
- options.append('--with-doctest')
- if outfile:
- options.append('-o')
- options.append(outfile)
-
- if len(args) > 1:
- mydirs = args[1:]
- else:
- mydirs = [os.path.join('pyomo','pyomo'), 'pyomo-model-libraries']
- #
- dirs=[]
- for dir in mydirs:
- if dir in _options.exclude:
- continue
- if dir.startswith('-'):
- options.append(dir)
- if dir.startswith('pyomo'):
- if os.path.exists(dir):
- dirs.append(dir)
- elif '.' in dir:
- dirs.append(os.path.join('pyomo','pyomo',dir.split('.')[1]))
- else:
- if os.path.exists('pyomo.'+dir):
- dirs.append('pyomo.'+dir)
- else:
- dirs.append(os.path.join('pyomo','pyomo',dir))
- #
- excluding = set()
- for e in _options.exclude:
- excluding.add(os.path.join('pyomo','pyomo',e))
- testdirs = []
- for topdir in dirs:
- for root, subdirs, files in os.walk(topdir):
- if not '__init__.py' in files:
- # Skip directories that do not contain a __init__.py file.
- continue
- for f in files:
- if f.startswith("test"):
- skip=False
- for e in excluding:
- if root.startswith(e):
- skip=True
- if not skip:
- testdirs.append(root)
- break
- #
- if docdir:
- testdirs.append(docdir)
-
- return pyutilib.dev.runtests.run('pyomo', ['runtests']+options+['-p','pyomo']+testdirs)
+# def OLD_runPyomoTests():
+# parser = optparse.OptionParser(usage='test.pyomo [options] ')
+
+# parser.add_option('-d','--dir',
+# action='store',
+# dest='dir',
+# default=None,
+# help='Top-level source directory where the tests are applied.')
+# parser.add_option('-e','--exclude',
+# action='append',
+# dest='exclude',
+# default=[],
+# help='Top-level source directories that are excluded.')
+# parser.add_option('--cat','--category',
+# action='store',
+# dest='cat',
+# default='smoke',
+# help='Specify test category.')
+# parser.add_option('--cov','--coverage',
+# action='store_true',
+# dest='coverage',
+# default=False,
+# help='Indicate that coverage information is collected')
+# parser.add_option('-v','--verbose',
+# action='store_true',
+# dest='verbose',
+# default=False,
+# help='Verbose output')
+# parser.add_option('-o','--output',
+# action='store',
+# dest='output',
+# default=None,
+# help='Redirect output to a file')
+# parser.add_option('--with-doctest',
+# action='store_true',
+# dest='doctests',
+# default=False,
+# help='Run tests included in Sphinx documentation')
+# parser.add_option('--doc-dir',
+# action='store',
+# dest='docdir',
+# default=None,
+# help='Top-level source directory for Sphinx documentation')
+
+# _options, args = parser.parse_args(sys.argv)
+
+# if _options.output:
+# outfile = os.path.abspath(_options.output)
+# else:
+# outfile = None
+
+# if _options.docdir:
+# docdir = os.path.abspath(_options.docdir)
+# if not os.path.exists(docdir):
+# raise ValueError("Invalid documentation directory, "
+# "path does not exist")
+# elif _options.doctests:
+# docdir = os.path.join('pyomo','doc','OnlineDocs')
+# else:
+# docdir = None
+
+# if _options.dir is None:
+# # the /src directory (for development installations)
+# os.chdir( os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) )
+# else:
+# if os.path.exists(_options.dir):
+# os.chdir( _options.dir )
+
+# print("Running tests in directory %s" % os.getcwd())
+# _options.cat = os.environ.get('PYUTILIB_UNITTEST_CATEGORY', _options.cat)
+# if _options.cat == 'all':
+# if 'PYUTILIB_UNITTEST_CATEGORY' in os.environ:
+# del os.environ['PYUTILIB_UNITTEST_CATEGORY']
+# elif _options.cat:
+# os.environ['PYUTILIB_UNITTEST_CATEGORY'] = _options.cat
+# print(" ... for test category: %s" % os.environ['PYUTILIB_UNITTEST_CATEGORY'])
+
+# options=[]
+# if _options.coverage:
+# options.append('--coverage')
+# if _options.verbose:
+# options.append('-v')
+# if _options.doctests:
+# options.append('--with-doctest')
+# if outfile:
+# options.append('-o')
+# options.append(outfile)
+
+# if len(args) > 1:
+# mydirs = args[1:]
+# else:
+# mydirs = [os.path.join('pyomo','pyomo'), 'pyomo-model-libraries']
+# #
+# dirs=[]
+# for dir in mydirs:
+# if dir in _options.exclude:
+# continue
+# if dir.startswith('-'):
+# options.append(dir)
+# if dir.startswith('pyomo'):
+# if os.path.exists(dir):
+# dirs.append(dir)
+# elif '.' in dir:
+# dirs.append(os.path.join('pyomo','pyomo',dir.split('.')[1]))
+# else:
+# if os.path.exists('pyomo.'+dir):
+# dirs.append('pyomo.'+dir)
+# else:
+# dirs.append(os.path.join('pyomo','pyomo',dir))
+# #
+# excluding = set()
+# for e in _options.exclude:
+# excluding.add(os.path.join('pyomo','pyomo',e))
+# testdirs = []
+# for topdir in dirs:
+# for root, subdirs, files in os.walk(topdir):
+# if not '__init__.py' in files:
+# # Skip directories that do not contain a __init__.py file.
+# continue
+# for f in files:
+# if f.startswith("test"):
+# skip=False
+# for e in excluding:
+# if root.startswith(e):
+# skip=True
+# if not skip:
+# testdirs.append(root)
+# break
+# #
+# if docdir:
+# testdirs.append(docdir)
+
+# return pyutilib.dev.runtests.run('pyomo', ['runtests']+options+['-p','pyomo']+testdirs)
diff --git a/pyomo/scripting/tests/test_pms.py b/pyomo/scripting/tests/test_pms.py
index 9bd9b0a88bc..6b40d1ff7f9 100644
--- a/pyomo/scripting/tests/test_pms.py
+++ b/pyomo/scripting/tests/test_pms.py
@@ -14,7 +14,6 @@
import base64
import ast
import os
-import sys
from os.path import abspath, dirname
from pyutilib.pyro import using_pyro4
@@ -22,10 +21,9 @@
import pyutilib.services
from pyutilib.misc import Options
import pyomo.opt
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, RangeSet, Var, Objective, Constraint, sum_product
import pyomo.scripting.pyro_mip_server
-import six
currdir = dirname(abspath(__file__))+os.sep
diff --git a/pyomo/scripting/util.py b/pyomo/scripting/util.py
index 0734f4ccf3c..2beeb08a61f 100644
--- a/pyomo/scripting/util.py
+++ b/pyomo/scripting/util.py
@@ -17,20 +17,9 @@
import types
import time
import json
-from six import itervalues, iterkeys, iteritems
-from six.moves import xrange
+from six import iteritems
from pyomo.common import pyomo_api
-try:
- import cProfile as profile
-except ImportError:
- import profile
-try:
- import pstats
- pstats_available=True
-except ImportError:
- pstats_available=False
-
from pyutilib.misc import Options
memory_data = Options()
@@ -47,9 +36,8 @@
from pyomo.opt.base import SolverFactory
from pyomo.opt.parallel import SolverManagerFactory
from pyomo.dataportal import DataPortal
-from pyomo.core import *
-from pyomo.core.base import TextLabeler
-import pyomo.core.base
+from pyomo.core import IPyomoScriptCreateModel, IPyomoScriptCreateDataPortal, IPyomoScriptPrintModel, IPyomoScriptModifyInstance, IPyomoScriptPrintInstance, IPyomoScriptSaveInstance, IPyomoScriptPrintResults, IPyomoScriptSaveResults, IPyomoScriptPostprocess, IPyomoScriptPreprocess, Model, TransformationFactory, Suffix, display
+
# Importing IPython is slow; defer the import to the point that it is
# actually needed.
@@ -926,11 +914,19 @@ def run_command(command=None, parser=None, args=None, name='unknown', data=None,
TempfileManager.push()
pcount = options.runtime.profile_count
if pcount > 0:
- if not pstats_available:
- msg = "Cannot use the 'profile' option. The Python 'pstats' " \
- 'package cannot be imported!'
+ # Defer import of profiling packages until we know that they
+ # are needed
+ try:
+ try:
+ import cProfile as profile
+ except ImportError:
+ import profile
+ import pstats
+ except ImportError:
configure_loggers(shutdown=True)
- raise ValueError(msg)
+ raise ValueError(
+ "Cannot use the 'profile' option: the Python "
+ "'profile' or 'pstats' package cannot be imported!")
tfile = TempfileManager.create_tempfile(suffix=".profile")
tmp = profile.runctx(
command.__name__ + '(options=options,parser=parser)', command.__globals__, locals(), tfile
diff --git a/pyomo/solvers/plugins/converter/ampl.py b/pyomo/solvers/plugins/converter/ampl.py
index 490076b28bc..7012eb4bd0e 100644
--- a/pyomo/solvers/plugins/converter/ampl.py
+++ b/pyomo/solvers/plugins/converter/ampl.py
@@ -13,7 +13,7 @@
import pyutilib.common
import pyomo.common
-from pyomo.opt.base import *
+from pyomo.opt.base import ProblemFormat, ConverterError
from pyomo.opt.base.convert import ProblemConverterFactory
try:
diff --git a/pyomo/solvers/plugins/converter/glpsol.py b/pyomo/solvers/plugins/converter/glpsol.py
index 120d893482b..b61eb167f8c 100644
--- a/pyomo/solvers/plugins/converter/glpsol.py
+++ b/pyomo/solvers/plugins/converter/glpsol.py
@@ -14,7 +14,7 @@
import pyutilib.subprocess
import pyutilib.common
import pyomo.common
-from pyomo.opt.base import *
+from pyomo.opt.base import ProblemFormat, ConverterError
from pyomo.opt.base.convert import ProblemConverterFactory
diff --git a/pyomo/solvers/plugins/converter/model.py b/pyomo/solvers/plugins/converter/model.py
index 06b50d566e5..ab604d6db99 100644
--- a/pyomo/solvers/plugins/converter/model.py
+++ b/pyomo/solvers/plugins/converter/model.py
@@ -13,7 +13,7 @@
from six import iteritems, PY3
import pyutilib.services
-from pyomo.opt.base import *
+from pyomo.opt.base import ProblemFormat
from pyomo.opt.base.convert import ProblemConverterFactory
from pyomo.solvers.plugins.converter.pico import PicoMIPConverter
from pyomo.core.kernel.block import IBlock
diff --git a/pyomo/solvers/plugins/converter/pico.py b/pyomo/solvers/plugins/converter/pico.py
index 8fafe70fe4a..fd9562128dc 100644
--- a/pyomo/solvers/plugins/converter/pico.py
+++ b/pyomo/solvers/plugins/converter/pico.py
@@ -16,7 +16,7 @@
import pyutilib.subprocess
import pyomo.common
-from pyomo.opt.base import *
+from pyomo.opt.base import ProblemFormat, ConverterError
class PicoMIPConverter(object):
diff --git a/pyomo/solvers/plugins/smanager/phpyro.py b/pyomo/solvers/plugins/smanager/phpyro.py
index 5fbb0b3ad23..cab0759ea84 100644
--- a/pyomo/solvers/plugins/smanager/phpyro.py
+++ b/pyomo/solvers/plugins/smanager/phpyro.py
@@ -11,7 +11,6 @@
__all__ = ["SolverManager_PHPyro"]
-import sys
import time
import itertools
from collections import defaultdict
@@ -20,12 +19,10 @@
from pyutilib.pyro import using_pyro3, using_pyro4
from pyutilib.pyro import Pyro as _pyro
from pyutilib.pyro.util import _connection_problem
-from pyomo.opt.parallel.manager import *
-from pyomo.opt.parallel.async_solver import *
+from pyomo.opt.parallel.manager import AsynchronousActionManager, ActionStatus
+from pyomo.opt.parallel.async_solver import SolverManagerFactory, AsynchronousSolverManager
-import six
from six import advance_iterator, iteritems, itervalues
-from six.moves import xrange
#
# a specialized asynchronous solver manager for Progressive Hedging.
diff --git a/pyomo/solvers/plugins/smanager/pyro.py b/pyomo/solvers/plugins/smanager/pyro.py
index e00c55f1044..5905c0c440d 100644
--- a/pyomo/solvers/plugins/smanager/pyro.py
+++ b/pyomo/solvers/plugins/smanager/pyro.py
@@ -21,7 +21,7 @@
import pyutilib.pyro
from pyutilib.pyro import using_pyro4, TaskProcessingError
import pyutilib.misc
-from pyomo.opt.base import OptSolver
+from pyomo.opt.base import OptSolver, SolverFactory
from pyomo.opt.parallel.manager import ActionManagerError, ActionStatus
from pyomo.opt.parallel.async_solver import (AsynchronousSolverManager,
SolverManagerFactory)
diff --git a/pyomo/solvers/plugins/solvers/ASL.py b/pyomo/solvers/plugins/solvers/ASL.py
index 0bb1717b992..ecb75c3d737 100644
--- a/pyomo/solvers/plugins/solvers/ASL.py
+++ b/pyomo/solvers/plugins/solvers/ASL.py
@@ -12,17 +12,18 @@
import os
import six
-import pyomo.common
-import pyutilib.common
-import pyutilib.misc
-
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
-from pyomo.core.base import TransformationFactory
+from pyomo.common import Executable
+from pyutilib.common import ApplicationError
+from pyutilib.misc import Options, Bunch
+from pyutilib.services import TempfileManager
+from pyutilib.subprocess import run
+
+from pyomo.opt.base import ProblemFormat, ResultsFormat
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.solver import SystemCallSolver
from pyomo.core.kernel.block import IBlock
from pyomo.solvers.mockmip import MockMIP
+from pyomo.core import TransformationFactory
import logging
logger = logging.getLogger('pyomo.solvers')
@@ -53,7 +54,7 @@ def __init__(self, **kwds):
#
# Note: Undefined capabilities default to 'None'
#
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
self._capabilities.integer = True
self._capabilities.quadratic_objective = True
@@ -76,7 +77,7 @@ def _default_executable(self):
logger.warning(
"No solver option specified for ASL solver interface")
return None
- executable = pyomo.common.Executable(self.options.solver)
+ executable = Executable(self.options.solver)
if not executable:
logger.warning(
"Could not locate the '%s' executable, which is required "
@@ -92,7 +93,7 @@ def _get_version(self):
solver_exec = self.executable()
if solver_exec is None:
return _extract_version('')
- results = pyutilib.subprocess.run( [solver_exec,"-v"], timelimit=1 )
+ results = run( [solver_exec,"-v"], timelimit=1 )
return _extract_version(results[1])
def create_command_line(self, executable, problem_files):
@@ -103,7 +104,7 @@ def create_command_line(self, executable, problem_files):
#
solver_name = os.path.basename(self.options.solver)
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix="_%s.log" % solver_name)
#
@@ -171,7 +172,7 @@ def create_command_line(self, executable, problem_files):
# Merge with any options coming in through the environment
env[envstr] = " ".join(opt)
- return pyutilib.misc.Bunch(cmd=cmd, log_file=self._log_file, env=env)
+ return Bunch(cmd=cmd, log_file=self._log_file, env=env)
def _presolve(self, *args, **kwds):
if (not isinstance(args[0], six.string_types)) and \
@@ -214,7 +215,7 @@ class MockASL(ASL,MockMIP):
def __init__(self, **kwds):
try:
ASL.__init__(self,**kwds)
- except pyutilib.common.ApplicationError: #pragma:nocover
+ except ApplicationError: #pragma:nocover
pass #pragma:nocover
MockMIP.__init__(self,"asl")
self._assert_available = True
diff --git a/pyomo/solvers/plugins/solvers/BARON.py b/pyomo/solvers/plugins/solvers/BARON.py
index 57cd04b1836..ac5de1eabb7 100644
--- a/pyomo/solvers/plugins/solvers/BARON.py
+++ b/pyomo/solvers/plugins/solvers/BARON.py
@@ -8,28 +8,23 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import itertools
import logging
import os
import subprocess
import re
import tempfile
-import pyomo.common
-import pyutilib
-from pyutilib.misc import Options
+from pyomo.common import Executable
+from pyutilib.misc import Options, Bunch
+from pyutilib.services import TempfileManager
+from pyutilib.subprocess import run
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
-from pyomo.core.base import SortComponents
-from pyomo.core.base.objective import Objective
-from pyomo.core.base import Constraint
-from pyomo.core.base.set_types import *
-from pyomo.repn.plugins.baron_writer import ProblemWriter_bar
+from pyomo.opt.base import ProblemFormat, ResultsFormat, OptSolver
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverResults, Solution, SolverStatus, TerminationCondition, SolutionStatus
+from pyomo.opt.solver import SystemCallSolver
-from six.moves import xrange, zip
+from six.moves import zip
logger = logging.getLogger('pyomo.solvers')
@@ -154,7 +149,7 @@ def license_is_valid(executable='baron'):
return True
def _default_executable(self):
- executable = pyomo.common.Executable("baron")
+ executable = Executable("baron")
if not executable:
logger.warning("Could not locate the 'baron' executable, "
"which is required for solver %s" % self.name)
@@ -173,7 +168,7 @@ def _get_version(self):
else:
fnames = self._get_dummy_input_files(check_license=False)
try:
- results = pyutilib.subprocess.run([solver_exec, fnames[0]])
+ results = run([solver_exec, fnames[0]])
return _extract_version(results[1])
finally:
self._remove_dummy_input_files(fnames)
@@ -189,7 +184,7 @@ def create_command_line(self, executable, problem_files):
cmd = [executable, problem_files[0]]
if self._timer:
cmd.insert(0, self._timer)
- return pyutilib.misc.Bunch( cmd=cmd,
+ return Bunch( cmd=cmd,
log_file=self._log_file,
env=None )
@@ -215,17 +210,17 @@ def _convert_problem(self,
# Define log file
#
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix = '.baron.log')
#
# Define solution file
#
if self._soln_file is None:
- self._soln_file = pyutilib.services.TempfileManager.\
+ self._soln_file = TempfileManager.\
create_tempfile(suffix = '.baron.soln')
- self._tim_file = pyutilib.services.TempfileManager.\
+ self._tim_file = TempfileManager.\
create_tempfile(suffix = '.baron.tim')
#
@@ -324,7 +319,7 @@ def _process_soln_file(self, results, TimFile, INPUT):
# file will be excluded from the results object.
#
- # TODO: Is there a way to hanle non-zero return values from baron?
+ # TODO: Is there a way to handle non-zero return values from baron?
# Example: the "NonLinearity Error if POW expression"
# (caused by x ^ y) when both x and y are variables
# causes an ugly python error and the solver log has a single
diff --git a/pyomo/solvers/plugins/solvers/CBCplugin.py b/pyomo/solvers/plugins/solvers/CBCplugin.py
index f08b84e0b34..58012569ab3 100644
--- a/pyomo/solvers/plugins/solvers/CBCplugin.py
+++ b/pyomo/solvers/plugins/solvers/CBCplugin.py
@@ -15,20 +15,20 @@
import time
import logging
-from six import iteritems
-from six import string_types
+from six import iteritems, string_types
-import pyomo.common
-import pyutilib.misc
-import pyutilib.common
-import pyutilib.subprocess
+from pyomo.common import Executable
+from pyutilib.common import ApplicationError
+from pyutilib.misc import Options, Bunch
+from pyutilib.services import TempfileManager
+from pyutilib.subprocess import run
-from pyomo.core.base import Var
from pyomo.core.kernel.block import IBlock
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.core import Var
+from pyomo.opt.base import ProblemFormat, ResultsFormat, OptSolver
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverResults, SolverStatus, TerminationCondition, SolutionStatus, ProblemSense, Solution
+from pyomo.opt.solver import SystemCallSolver
from pyomo.solvers.mockmip import MockMIP
logger = logging.getLogger('pyomo.solvers')
@@ -49,13 +49,13 @@ def configure_cbc():
return
# manually look for the cbc executable to prevent the
# CBC.execute() from logging an error when CBC is missing
- executable = pyomo.common.Executable("cbc")
+ executable = Executable("cbc")
if not executable:
return
cbc_exec = executable.path()
- results = pyutilib.subprocess.run( [cbc_exec,"-stop"], timelimit=1 )
+ results = run( [cbc_exec,"-stop"], timelimit=1 )
_cbc_version = _extract_version(results[1])
- results = pyutilib.subprocess.run(
+ results = run(
[cbc_exec,"dummy","-AMPL","-stop"], timelimit=1 )
_cbc_compiled_with_asl = not ('No match for AMPL' in results[1])
if _cbc_version is not None:
@@ -158,7 +158,7 @@ def __init__(self, **kwds):
self._valid_result_formats[ProblemFormat.mps] = [ResultsFormat.soln]
# Note: Undefined capabilities default to 'None'
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
self._capabilities.integer = True
# The quadratic capabilities may be true but there is
@@ -234,7 +234,7 @@ def _presolve(self, *args, **kwds):
# create a context in the temporary file manager for
# this plugin - is "pop"ed in the _postsolve method.
- pyutilib.services.TempfileManager.push()
+ TempfileManager.push()
# if the first argument is a string (representing a filename),
# then we don't have an instance => the solver is being applied
@@ -260,7 +260,7 @@ def _presolve(self, *args, **kwds):
# and the warm start file-name is (obviously) needed there.
if self._warm_start_file_name is None:
assert not user_warmstart
- self._warm_start_file_name = pyutilib.services.TempfileManager.\
+ self._warm_start_file_name = TempfileManager.\
create_tempfile(suffix = '.cbc.soln')
# let the base class handle any remaining keywords/actions.
@@ -289,7 +289,7 @@ def _presolve(self, *args, **kwds):
def _default_executable(self):
- executable = pyomo.common.Executable("cbc")
+ executable = Executable("cbc")
if not executable:
logger.warning(
"Could not locate the 'cbc' executable, which is "
@@ -311,7 +311,7 @@ def create_command_line(self, executable, problem_files):
# Define the log file
#
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.create_tempfile(suffix=".cbc.log")
+ self._log_file = TempfileManager.create_tempfile(suffix=".cbc.log")
#
# Define the solution file
@@ -404,7 +404,7 @@ def _check_and_escape_options(options):
"-solve",
"-solu", self._soln_file])
- return pyutilib.misc.Bunch(cmd=cmd, log_file=self._log_file, env=None)
+ return Bunch(cmd=cmd, log_file=self._log_file, env=None)
def process_logfile(self):
"""
@@ -873,7 +873,7 @@ def _postsolve(self):
# manager, created populated *directly* by this plugin. does not
# include, for example, the execution script. but does include
# the warm-start file.
- pyutilib.services.TempfileManager.pop(remove=not self._keepfiles)
+ TempfileManager.pop(remove=not self._keepfiles)
return results
@@ -886,7 +886,7 @@ class MockCBC(CBCSHELL,MockMIP):
def __init__(self, **kwds):
try:
CBCSHELL.__init__(self,**kwds)
- except pyutilib.common.ApplicationError: #pragma:nocover
+ except ApplicationError: #pragma:nocover
pass #pragma:nocover
MockMIP.__init__(self,"cbc")
diff --git a/pyomo/solvers/plugins/solvers/CONOPT.py b/pyomo/solvers/plugins/solvers/CONOPT.py
index 998d871aed8..a61cf9551c8 100644
--- a/pyomo/solvers/plugins/solvers/CONOPT.py
+++ b/pyomo/solvers/plugins/solvers/CONOPT.py
@@ -10,13 +10,15 @@
import os
-import pyomo.common
-import pyutilib.misc
+from pyomo.common import Executable
+from pyutilib.misc import Options, Bunch
+from pyutilib.services import TempfileManager
+from pyutilib.subprocess import run
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.opt.base import ProblemFormat, ResultsFormat
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverStatus
+from pyomo.opt.solver import SystemCallSolver
import logging
logger = logging.getLogger('pyomo.solvers')
@@ -50,7 +52,7 @@ def __init__(self, **kwds):
self.set_problem_format(ProblemFormat.nl)
# Note: Undefined capabilities default to 'None'
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
self._capabilities.integer = True
self._capabilities.quadratic_objective = True
@@ -62,7 +64,7 @@ def _default_results_format(self, prob_format):
return ResultsFormat.sol
def _default_executable(self):
- executable = pyomo.common.Executable("conopt")
+ executable = Executable("conopt")
if not executable:
logger.warning("Could not locate the 'conopt' executable, "
"which is required for solver %s" % self.name)
@@ -77,7 +79,7 @@ def _get_version(self):
solver_exec = self.executable()
if solver_exec is None:
return _extract_version('')
- results = pyutilib.subprocess.run( [solver_exec], timelimit=1 )
+ results = run( [solver_exec], timelimit=1 )
return _extract_version(results[1])
def create_command_line(self, executable, problem_files):
@@ -89,7 +91,7 @@ def create_command_line(self, executable, problem_files):
# Define log file
#
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix="_conopt.log")
fname = problem_files[0]
@@ -147,7 +149,7 @@ def create_command_line(self, executable, problem_files):
# Merge with any options coming in through the environment
env[envstr] = " ".join(opt)
- return pyutilib.misc.Bunch(cmd=cmd, log_file=self._log_file, env=env)
+ return Bunch(cmd=cmd, log_file=self._log_file, env=env)
def _postsolve(self):
results = super(CONOPT, self)._postsolve()
diff --git a/pyomo/solvers/plugins/solvers/CPLEX.py b/pyomo/solvers/plugins/solvers/CPLEX.py
index a596f4e4691..6b103dd5c17 100644
--- a/pyomo/solvers/plugins/solvers/CPLEX.py
+++ b/pyomo/solvers/plugins/solvers/CPLEX.py
@@ -14,17 +14,25 @@
import time
import logging
-import pyomo.common
-import pyutilib.common
-import pyutilib.misc
+from pyomo.common import Executable
+from pyutilib.common import ApplicationError
+from pyutilib.misc import Options, Bunch, yaml_fix
+from pyutilib.services import TempfileManager
+from pyutilib.subprocess import run
from pyomo.common.collections import ComponentMap
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.opt.base import (
+ ProblemFormat, ResultsFormat, OptSolver, BranchDirection,
+)
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import (
+ SolverResults, SolverStatus, TerminationCondition, SolutionStatus,
+ ProblemSense, Solution,
+)
+from pyomo.opt.solver import ILMLicensedSystemCallSolver
from pyomo.solvers.mockmip import MockMIP
from pyomo.core.base import Var, Suffix, active_export_suffix_generator
+from pyomo.core.kernel.suffix import export_suffix_generator
from pyomo.core.kernel.block import IBlock
from pyomo.util.components import iter_component
@@ -166,7 +174,7 @@ def __init__(self, **kwds):
self.set_problem_format(ProblemFormat.cpxlp)
# Note: Undefined capabilities default to 'None'
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
self._capabilities.quadratic_objective = True
self._capabilities.quadratic_constraint = True
@@ -237,7 +245,7 @@ def _get_suffixes(self, instance):
if isinstance(instance, IBlock):
suffixes = (
(suf.name, suf)
- for suf in pyomo.core.kernel.suffix.export_suffix_generator(
+ for suf in export_suffix_generator(
instance, datatype=Suffix.INT, active=True, descend_into=False
)
)
@@ -294,7 +302,7 @@ def _presolve(self, *args, **kwds):
# create a context in the temporary file manager for
# this plugin - is "pop"ed in the _postsolve method.
- pyutilib.services.TempfileManager.push()
+ TempfileManager.push()
# if the first argument is a string (representing a filename),
# then we don't have an instance => the solver is being applied
@@ -319,7 +327,7 @@ def _presolve(self, *args, **kwds):
# and the warm start file-name is (obviously) needed there.
if self._warm_start_file_name is None:
assert not user_warmstart
- self._warm_start_file_name = pyutilib.services.TempfileManager.\
+ self._warm_start_file_name = TempfileManager.\
create_tempfile(suffix = '.cplex.mst')
self._priorities_solve = kwds.pop("priorities", False)
@@ -333,7 +341,7 @@ def _presolve(self, *args, **kwds):
and not isinstance(args[0], basestring)
and not user_priorities
):
- self._priorities_file_name = pyutilib.services.TempfileManager.create_tempfile(
+ self._priorities_file_name = TempfileManager.create_tempfile(
suffix=".cplex.ord"
)
@@ -373,7 +381,7 @@ def _presolve(self, *args, **kwds):
)
def _default_executable(self):
- executable = pyomo.common.Executable("cplex")
+ executable = Executable("cplex")
if not executable:
logger.warning("Could not locate the 'cplex' executable"
", which is required for solver %s"
@@ -389,7 +397,7 @@ def _get_version(self):
solver_exec = self.executable()
if solver_exec is None:
return _extract_version('')
- results = pyutilib.subprocess.run( [solver_exec,'-c','quit'], timelimit=1 )
+ results = run( [solver_exec,'-c','quit'], timelimit=1 )
return _extract_version(results[1])
def create_command_line(self, executable, problem_files):
@@ -399,7 +407,7 @@ def create_command_line(self, executable, problem_files):
# The log file in CPLEX contains the solution trace, but the solver status can be found in the solution file.
#
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix = '.cplex.log')
self._log_file = _validate_file_name(self, self._log_file, "log")
@@ -408,7 +416,7 @@ def create_command_line(self, executable, problem_files):
# As indicated above, contains (in XML) both the solution and solver status.
#
if self._soln_file is None:
- self._soln_file = pyutilib.services.TempfileManager.\
+ self._soln_file = TempfileManager.\
create_tempfile(suffix = '.cplex.sol')
self._soln_file = _validate_file_name(self, self._soln_file, "solution")
@@ -455,7 +463,7 @@ def create_command_line(self, executable, problem_files):
# dump the script and warm-start file names for the
# user if we're keeping files around.
if self._keepfiles:
- script_fname = pyutilib.services.TempfileManager.\
+ script_fname = TempfileManager.\
create_tempfile(suffix = '.cplex.script')
tmp = open(script_fname,'w')
tmp.write(script)
@@ -476,7 +484,7 @@ def create_command_line(self, executable, problem_files):
cmd = [executable]
if self._timer:
cmd.insert(0, self._timer)
- return pyutilib.misc.Bunch(cmd=cmd, script=script,
+ return Bunch(cmd=cmd, script=script,
log_file=self._log_file, env=None)
def process_logfile(self):
@@ -613,7 +621,7 @@ def process_logfile(self):
results.solver.termination_message = ' '.join(tokens)
try:
- results.solver.termination_message = pyutilib.misc.yaml_fix(results.solver.termination_message)
+ results.solver.termination_message = yaml_fix(results.solver.termination_message)
except:
pass
return results
@@ -889,7 +897,7 @@ def _postsolve(self):
# manager, created populated *directly* by this plugin. does not
# include, for example, the execution script. but does include
# the warm-start file.
- pyutilib.services.TempfileManager.pop(remove=not self._keepfiles)
+ TempfileManager.pop(remove=not self._keepfiles)
return results
@@ -902,7 +910,7 @@ class MockCPLEX(CPLEXSHELL,MockMIP):
def __init__(self, **kwds):
try:
CPLEXSHELL.__init__(self, **kwds)
- except pyutilib.common.ApplicationError: #pragma:nocover
+ except ApplicationError: #pragma:nocover
pass #pragma:nocover
MockMIP.__init__(self,"cplex")
diff --git a/pyomo/solvers/plugins/solvers/GLPK.py b/pyomo/solvers/plugins/solvers/GLPK.py
index 597ddbd03ef..b7c4722c4cc 100644
--- a/pyomo/solvers/plugins/solvers/GLPK.py
+++ b/pyomo/solvers/plugins/solvers/GLPK.py
@@ -18,7 +18,7 @@
from pyutilib.services import TempfileManager
from pyomo.common import Executable
-from pyomo.opt import *
+from pyomo.opt import SolverFactory, OptSolver, ProblemFormat, ResultsFormat, SolverResults, TerminationCondition, SolutionStatus, ProblemSense
from pyomo.opt.base.solvers import _extract_version
from pyomo.opt.solver import SystemCallSolver
diff --git a/pyomo/solvers/plugins/solvers/GLPK_old.py b/pyomo/solvers/plugins/solvers/GLPK_old.py
index b404bbc8b38..b529014da7f 100644
--- a/pyomo/solvers/plugins/solvers/GLPK_old.py
+++ b/pyomo/solvers/plugins/solvers/GLPK_old.py
@@ -18,11 +18,11 @@
from pyutilib.services import TempfileManager
import pyutilib.subprocess
-import pyomo.common
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.common import Executable
+from pyomo.opt.base import ProblemFormat, ResultsFormat
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverResults, SolverStatus, TerminationCondition, SolutionStatus, ProblemSense
+from pyomo.opt.solver import SystemCallSolver
from pyomo.solvers.mockmip import MockMIP
from pyomo.solvers.plugins.solvers.GLPK import _glpk_version, configure_glpk
@@ -85,7 +85,7 @@ def _default_results_format(self, prob_format):
return ResultsFormat.soln
def _default_executable(self):
- executable = pyomo.common.Executable('glpsol')
+ executable = Executable('glpsol')
if not executable:
msg = ("Could not locate the 'glpsol' executable, which is "
"required for solver '%s'")
@@ -439,7 +439,7 @@ def _default_results_format(self, prob_format):
return ResultsFormat.soln
def _default_executable(self):
- executable = pyomo.common.Executable('glpsol')
+ executable = Executable('glpsol')
if not executable:
msg = "Could not locate the 'glpsol' executable, which is " \
"required for solver '%s'"
@@ -722,7 +722,7 @@ def process_soln_file(self, results):
("***ERROR: Unexpected constraint index " + \
"encountered on line=%s; expected " + \
"value=%s; actual value=%s") % \
- (line, str(number_of_consrtaints_read),
+ (line, str(number_of_constraints_read),
str(index)))
else:
index = None
diff --git a/pyomo/solvers/plugins/solvers/GUROBI.py b/pyomo/solvers/plugins/solvers/GUROBI.py
index 859d057e824..5c927b9104c 100644
--- a/pyomo/solvers/plugins/solvers/GUROBI.py
+++ b/pyomo/solvers/plugins/solvers/GUROBI.py
@@ -15,13 +15,15 @@
import logging
import subprocess
-import pyomo.common
-import pyutilib.misc
-
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.common import Executable
+from pyutilib.misc import Options, Bunch
+from pyutilib.services import TempfileManager
+from pyutilib.subprocess import run
+
+from pyomo.opt.base import ProblemFormat, ResultsFormat, OptSolver
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverStatus, TerminationCondition, SolutionStatus, ProblemSense, Solution
+from pyomo.opt.solver import ILMLicensedSystemCallSolver
from pyomo.core.kernel.block import IBlock
logger = logging.getLogger('pyomo.solvers')
@@ -108,7 +110,7 @@ def __init__(self, **kwds):
self.set_problem_format(ProblemFormat.cpxlp)
# Note: Undefined capabilities default to 'None'
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
self._capabilities.quadratic_objective = True
self._capabilities.quadratic_constraint = True
@@ -190,7 +192,7 @@ def _presolve(self, *args, **kwds):
# create a context in the temporary file manager for
# this plugin - is "pop"ed in the _postsolve method.
- pyutilib.services.TempfileManager.push()
+ TempfileManager.push()
# if the first argument is a string (representing a filename),
# then we don't have an instance => the solver is being applied
@@ -216,7 +218,7 @@ def _presolve(self, *args, **kwds):
# and the warm start file-name is (obviously) needed there.
if self._warm_start_file_name is None:
assert not user_warmstart
- self._warm_start_file_name = pyutilib.services.TempfileManager.\
+ self._warm_start_file_name = TempfileManager.\
create_tempfile(suffix = '.gurobi.mst')
# let the base class handle any remaining keywords/actions.
@@ -244,9 +246,9 @@ def _presolve(self, *args, **kwds):
def _default_executable(self):
if sys.platform == 'win32':
- executable = pyomo.common.Executable("gurobi.bat")
+ executable = Executable("gurobi.bat")
else:
- executable = pyomo.common.Executable("gurobi.sh")
+ executable = Executable("gurobi.sh")
if not executable:
logger.warning("Could not locate the 'gurobi' executable, "
"which is required for solver %s" % self.name)
@@ -262,7 +264,7 @@ def _get_version(self):
if solver_exec is None:
return _extract_version('')
f = StringIO()
- results = pyutilib.subprocess.run([solver_exec],
+ results = run([solver_exec],
stdin=('from gurobipy import *; '
'print(gurobi.version()); exit()'),
ostream=f)
@@ -285,7 +287,7 @@ def create_command_line(self,executable,problem_files):
# The log file in CPLEX contains the solution trace, but the solver status can be found in the solution file.
#
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix = '.gurobi.log')
#
@@ -293,7 +295,7 @@ def create_command_line(self,executable,problem_files):
# As indicated above, contains (in XML) both the solution and solver status.
#
if self._soln_file is None:
- self._soln_file = pyutilib.services.TempfileManager.\
+ self._soln_file = TempfileManager.\
create_tempfile(suffix = '.gurobi.txt')
#
@@ -336,7 +338,7 @@ def create_command_line(self,executable,problem_files):
# dump the script and warm-start file names for the
# user if we're keeping files around.
if self._keepfiles:
- script_fname = pyutilib.services.TempfileManager.create_tempfile(suffix = '.gurobi.script')
+ script_fname = TempfileManager.create_tempfile(suffix = '.gurobi.script')
script_file = open(script_fname, 'w')
script_file.write( script )
script_file.close()
@@ -353,7 +355,7 @@ def create_command_line(self,executable,problem_files):
cmd = [executable]
if self._timer:
cmd.insert(0, self._timer)
- return pyutilib.misc.Bunch(cmd=cmd, script=script,
+ return Bunch(cmd=cmd, script=script,
log_file=self._log_file, env=None)
def process_logfile(self):
@@ -532,6 +534,6 @@ def _postsolve(self):
# manager, created populated *directly* by this plugin. does not
# include, for example, the execution script. but does include
# the warm-start file.
- pyutilib.services.TempfileManager.pop(remove=not self._keepfiles)
+ TempfileManager.pop(remove=not self._keepfiles)
return results
diff --git a/pyomo/solvers/plugins/solvers/GUROBI_RUN.py b/pyomo/solvers/plugins/solvers/GUROBI_RUN.py
index ff6f14b1152..cfd9d41a0b8 100644
--- a/pyomo/solvers/plugins/solvers/GUROBI_RUN.py
+++ b/pyomo/solvers/plugins/solvers/GUROBI_RUN.py
@@ -16,7 +16,7 @@
This script is run using the Gurobi/system python. Do not assume any third party packages
are available!
"""
-from gurobipy import *
+from gurobipy import gurobi, read, GRB
import sys
if sys.version_info[0] < 3:
from itertools import izip as zip
diff --git a/pyomo/solvers/plugins/solvers/IPOPT.py b/pyomo/solvers/plugins/solvers/IPOPT.py
index b5b40342a88..a46915ec36a 100644
--- a/pyomo/solvers/plugins/solvers/IPOPT.py
+++ b/pyomo/solvers/plugins/solvers/IPOPT.py
@@ -10,13 +10,15 @@
import os
-import pyomo.common
-import pyutilib.misc
+from pyomo.common import Executable
+from pyutilib.misc import Options, Bunch
+from pyutilib.services import TempfileManager
+from pyutilib.subprocess import run
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.opt.base import ProblemFormat, ResultsFormat
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverStatus, SolverResults, TerminationCondition
+from pyomo.opt.solver import SystemCallSolver
import logging
logger = logging.getLogger('pyomo.solvers')
@@ -49,7 +51,7 @@ def __init__(self, **kwds):
self.set_problem_format(ProblemFormat.nl)
# Note: Undefined capabilities default to 'None'
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
self._capabilities.integer = False
self._capabilities.quadratic_objective = True
@@ -61,7 +63,7 @@ def _default_results_format(self, prob_format):
return ResultsFormat.sol
def _default_executable(self):
- executable = pyomo.common.Executable("ipopt")
+ executable = Executable("ipopt")
if not executable:
logger.warning("Could not locate the 'ipopt' executable, "
"which is required for solver %s" % self.name)
@@ -76,7 +78,7 @@ def _get_version(self):
solver_exec = self.executable()
if solver_exec is None:
return _extract_version('')
- results = pyutilib.subprocess.run( [solver_exec,"-v"], timelimit=1 )
+ results = run( [solver_exec,"-v"], timelimit=1 )
return _extract_version(results[1])
def create_command_line(self, executable, problem_files):
@@ -88,7 +90,7 @@ def create_command_line(self, executable, problem_files):
# Define log file
#
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix="_ipopt.log")
fname = problem_files[0]
@@ -170,7 +172,7 @@ def create_command_line(self, executable, problem_files):
default_of_name))
# Now write the new options file
- options_filename = pyutilib.services.TempfileManager.\
+ options_filename = TempfileManager.\
create_tempfile(suffix="_ipopt.opt")
with open(options_filename, "w") as f:
for key, val in of_opt:
@@ -185,7 +187,7 @@ def create_command_line(self, executable, problem_files):
# Merge with any options coming in through the environment
env[envstr] = " ".join(env_opt)
- return pyutilib.misc.Bunch(cmd=cmd, log_file=self._log_file, env=env)
+ return Bunch(cmd=cmd, log_file=self._log_file, env=env)
def process_output(self, rc):
if os.path.exists(self._results_file):
diff --git a/pyomo/solvers/plugins/solvers/PICO.py b/pyomo/solvers/plugins/solvers/PICO.py
index ba552849d89..0884f995c55 100644
--- a/pyomo/solvers/plugins/solvers/PICO.py
+++ b/pyomo/solvers/plugins/solvers/PICO.py
@@ -8,21 +8,21 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-
import re
import os
from six import iteritems
-import pyomo.common
-import pyutilib.common
-import pyutilib.common
-import pyutilib.misc
+from pyomo.common import Executable
+from pyutilib.common import ApplicationError
+from pyutilib.misc import Options, Bunch
+from pyutilib.services import TempfileManager
+from pyutilib.subprocess import run
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.opt.base import ProblemFormat, ResultsFormat, OptSolver
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverResults, SolverStatus, TerminationCondition, SolutionStatus, ProblemSense, Solution
+from pyomo.opt.solver import SystemCallSolver
from pyomo.solvers.mockmip import MockMIP
import logging
@@ -92,7 +92,7 @@ def __init__(self, **kwds):
self.set_problem_format(ProblemFormat.cpxlp)
# Note: Undefined capabilities default to 'None'
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
self._capabilities.integer = True
#self._capabilities.sos1 = True
@@ -119,7 +119,7 @@ def _default_results_format(self, prob_format):
return ResultsFormat.soln
def _default_executable(self):
- executable = pyomo.common.Executable("PICO_deprecated_not_supported")
+ executable = Executable("PICO_deprecated_not_supported")
if not executable:
logger.warning("Could not locate the 'PICO' executable, "
"which is required for solver %s" % self.name)
@@ -134,7 +134,7 @@ def _get_version(self):
solver_exec = self.executable()
if solver_exec is None:
return _extract_version('')
- results = pyutilib.subprocess.run([solver_exec, "--version"], timelimit=1)
+ results = run([solver_exec, "--version"], timelimit=1)
# 'PICO --version' seems to print 'pebble , PICO
# we don't wan't the pebble version being advertised so we split
# the string at the comma before extracting a version number. It
@@ -151,7 +151,7 @@ def create_command_line(self,executable,problem_files):
# Define log file
#
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix="PICO.log")
problem_filename_prefix = problem_files[0]
@@ -240,7 +240,7 @@ def _check_and_escape_options(options):
cmd.extend(['--output', self._soln_file,
problem_files[0]])
- return pyutilib.misc.Bunch(cmd=cmd, log_file=self._log_file, env=env)
+ return Bunch(cmd=cmd, log_file=self._log_file, env=env)
def process_logfile(self):
"""
@@ -423,7 +423,7 @@ class MockPICO(PICOSHELL,MockMIP):
def __init__(self, **kwds):
try:
PICOSHELL.__init__(self,**kwds)
- except pyutilib.common.ApplicationError: #pragma:nocover
+ except ApplicationError: #pragma:nocover
pass #pragma:nocover
MockMIP.__init__(self,"pico")
diff --git a/pyomo/solvers/plugins/solvers/SCIPAMPL.py b/pyomo/solvers/plugins/solvers/SCIPAMPL.py
index f0f15dbf8e3..76ad8e00959 100644
--- a/pyomo/solvers/plugins/solvers/SCIPAMPL.py
+++ b/pyomo/solvers/plugins/solvers/SCIPAMPL.py
@@ -10,13 +10,15 @@
import os
-import pyomo.common
-import pyutilib.misc
+from pyomo.common import Executable
+from pyutilib.misc import Options, Bunch
+from pyutilib.services import TempfileManager
+from pyutilib.subprocess import run
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.opt.base import ProblemFormat, ResultsFormat
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverStatus, TerminationCondition, SolutionStatus
+from pyomo.opt.solver import SystemCallSolver
import logging
logger = logging.getLogger('pyomo.solvers')
@@ -48,7 +50,7 @@ def __init__(self, **kwds):
self.set_problem_format(ProblemFormat.nl)
# Note: Undefined capabilities default to 'None'
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
self._capabilities.integer = True
self._capabilities.quadratic_objective = True
@@ -60,7 +62,7 @@ def _default_results_format(self, prob_format):
return ResultsFormat.sol
def _default_executable(self):
- executable = pyomo.common.Executable("scipampl")
+ executable = Executable("scipampl")
if not executable:
logger.warning("Could not locate the 'scipampl' executable, "
"which is required for solver %s" % self.name)
@@ -75,7 +77,7 @@ def _get_version(self):
solver_exec = self.executable()
if solver_exec is None:
return _extract_version('')
- results = pyutilib.subprocess.run( [solver_exec], timelimit=1 )
+ results = run( [solver_exec], timelimit=1 )
return _extract_version(results[1])
def create_command_line(self, executable, problem_files):
@@ -87,7 +89,7 @@ def create_command_line(self, executable, problem_files):
# Define log file
#
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix="_scipampl.log")
fname = problem_files[0]
@@ -156,7 +158,7 @@ def create_command_line(self, executable, problem_files):
% (default_of_name, default_of_name))
# Now write the new options file
- options_filename = pyutilib.services.TempfileManager.\
+ options_filename = TempfileManager.\
create_tempfile(suffix="_scip.set")
with open(options_filename, "w") as f:
for line in of_opt:
@@ -164,7 +166,7 @@ def create_command_line(self, executable, problem_files):
cmd.append(options_filename)
- return pyutilib.misc.Bunch(cmd=cmd, log_file=self._log_file, env=env)
+ return Bunch(cmd=cmd, log_file=self._log_file, env=env)
def _postsolve(self):
results = super(SCIPAMPL, self)._postsolve()
diff --git a/pyomo/solvers/plugins/solvers/XPRESS.py b/pyomo/solvers/plugins/solvers/XPRESS.py
index 70fda964626..e7518481ea8 100644
--- a/pyomo/solvers/plugins/solvers/XPRESS.py
+++ b/pyomo/solvers/plugins/solvers/XPRESS.py
@@ -13,14 +13,15 @@
import re
import logging
-import pyomo.common
-import pyutilib.common
-import pyutilib.misc
-
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.common import Executable
+from pyutilib.common import ApplicationError
+from pyutilib.misc import Options, Bunch, yaml_fix
+from pyutilib.services import TempfileManager
+
+from pyomo.opt.base import ProblemFormat, ResultsFormat, OptSolver
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverResults, SolverStatus, TerminationCondition, ProblemSense, Solution
+from pyomo.opt.solver import ILMLicensedSystemCallSolver
from pyomo.solvers.mockmip import MockMIP
logger = logging.getLogger('pyomo.solvers')
@@ -98,7 +99,7 @@ def __init__(self, **kwds):
#
# Note: Undefined capabilities default to 'None'
- self._capabilities = pyutilib.misc.Options()
+ self._capabilities = Options()
self._capabilities.linear = True
self._capabilities.quadratic_objective = True
self._capabilities.quadratic_constraint = True
@@ -117,7 +118,7 @@ def warm_start_capable(self):
return False
def _default_executable(self):
- executable = pyomo.common.Executable("optimizer")
+ executable = Executable("optimizer")
if not executable:
logger.warning("Could not locate the 'optimizer' executable, "
"which is required for solver %s" % self.name)
@@ -140,14 +141,14 @@ def create_command_line(self, executable, problem_files):
# The log file in XPRESS contains the solution trace, but the solver status can be found in the solution file.
#
if self._log_file is None:
- self._log_file = pyutilib.services.TempfileManager.\
+ self._log_file = TempfileManager.\
create_tempfile(suffix = '.xpress.log')
#
# Define solution file
# As indicated above, contains (in XML) both the solution and solver status.
#
- self._soln_file = pyutilib.services.TempfileManager.\
+ self._soln_file = TempfileManager.\
create_tempfile(suffix = '.xpress.wrtsol')
#
@@ -190,7 +191,7 @@ def create_command_line(self, executable, problem_files):
# dump the script and warm-start file names for the
# user if we're keeping files around.
if self._keepfiles:
- script_fname = pyutilib.services.TempfileManager.create_tempfile(suffix = '.xpress.script')
+ script_fname = TempfileManager.create_tempfile(suffix = '.xpress.script')
tmp = open(script_fname,'w')
tmp.write(script)
tmp.close()
@@ -203,7 +204,7 @@ def create_command_line(self, executable, problem_files):
cmd = [executable]
if self._timer:
cmd.insert(0, self._timer)
- return pyutilib.misc.Bunch(cmd=cmd, script=script,
+ return Bunch(cmd=cmd, script=script,
log_file=self._log_file, env=None)
def process_logfile(self):
@@ -301,7 +302,7 @@ def process_logfile(self):
results.solver.termination_message = ' '.join(tokens)
try:
- results.solver.termination_message = pyutilib.misc.yaml_fix(results.solver.termination_message)
+ results.solver.termination_message = yaml_fix(results.solver.termination_message)
except:
pass
return results
@@ -368,7 +369,8 @@ def process_soln_file(self, results):
variable_name = name
variable_value = primary_value
variable_reduced_cost = None
-
+ ### TODO: What is going on here with field_name, and shortly thereafter, with variable_status and whatnot? They've never been defined.
+ ### It seems like this is trying to mimic the CPLEX solver but has some issues
if (extract_reduced_costs is True) and (field_name == "reducedCost"):
variable_reduced_cost = tertiary_value
@@ -426,7 +428,7 @@ class MockXPRESS(XPRESS_shell,MockMIP):
def __init__(self, **kwds):
try:
XPRESS_shell.__init__(self, **kwds)
- except pyutilib.common.ApplicationError: #pragma:nocover
+ except ApplicationError: #pragma:nocover
pass #pragma:nocover
MockMIP.__init__(self,"cplex")
diff --git a/pyomo/solvers/plugins/solvers/cplex_direct.py b/pyomo/solvers/plugins/solvers/cplex_direct.py
index 20baff38df7..06d222d6c84 100644
--- a/pyomo/solvers/plugins/solvers/cplex_direct.py
+++ b/pyomo/solvers/plugins/solvers/cplex_direct.py
@@ -10,11 +10,13 @@
import logging
import re
+import six
import sys
-import pyomo.common
+
from pyutilib.misc import Bunch
from pyutilib.services import TempfileManager
from pyomo.common.collections import ComponentSet, ComponentMap
+from pyomo.core.base import Suffix, Var, Constraint, SOSConstraint, Objective
from pyomo.core.expr.numvalue import is_fixed
from pyomo.core.expr.numvalue import value
from pyomo.repn import generate_standard_repn
@@ -157,20 +159,29 @@ def _init(self):
def _apply_solver(self):
if not self._save_results:
for block in self._pyomo_model.block_data_objects(descend_into=True, active=True):
- for var in block.component_data_objects(ctype=pyomo.core.base.var.Var, descend_into=False, active=True, sort=False):
+ for var in block.component_data_objects(ctype=Var, descend_into=False, active=True, sort=False):
var.stale = True
- _log_file = self._log_file
- if self.version() >= (12, 10):
- _log_file = open(self._log_file, 'w')
+ # In recent versions of CPLEX it is helpful to manually open the
+ # log file and then explicitly close it after CPLEX is finished.
+ # This ensures that the file is closed (and unlocked) on Windows
+ # before the TempfileManager (or user) attempts to delete the
+ # log file. Passing in an opened file object is supported at
+ # least as far back as CPLEX 12.5.1 [the oldest version
+ # supported by IBM as of 1 Oct 2020]
+ if self.version() >= (12, 5, 1) \
+ and isinstance(self._log_file, six.string_types):
+ _log_file = (open(self._log_file, 'a'),)
+ _close_log_file = True
+ else:
+ _log_file = (self._log_file,)
+ _close_log_file = False
+ if self._tee:
+ def _process_stream(arg):
+ sys.stdout.write(arg)
+ return arg
+ _log_file += (_process_stream,)
try:
- if self._tee:
- def _process_stream(arg):
- sys.stdout.write(arg)
- return arg
- self._solver_model.set_results_stream(_log_file, _process_stream)
- else:
- self._solver_model.set_results_stream(_log_file)
-
+ self._solver_model.set_results_stream(*_log_file)
if self._keepfiles:
print("Solver log file: "+self._log_file)
@@ -240,8 +251,9 @@ def _process_stream(arg):
t1 = time.time()
self._wallclock_time = t1 - t0
finally:
- if self.version() >= (12, 10):
- _log_file.close()
+ self._solver_model.set_results_stream(None)
+ if _close_log_file:
+ _log_file[0].close()
# FIXME: can we get a return code indicating if CPLEX had a significant failure?
return Bunch(rc=None, log=None)
@@ -359,7 +371,7 @@ def _set_instance(self, model, kwds={}):
def _add_block(self, block):
var_data = _VariableData(self._solver_model)
for var in block.component_data_objects(
- ctype=pyomo.core.base.var.Var, descend_into=True, active=True, sort=True
+ ctype=Var, descend_into=True, active=True, sort=True
):
self._add_var(var, var_data)
var_data.store_in_cplex()
@@ -367,7 +379,7 @@ def _add_block(self, block):
lin_con_data = _LinearConstraintData(self._solver_model)
for sub_block in block.block_data_objects(descend_into=True, active=True):
for con in sub_block.component_data_objects(
- ctype=pyomo.core.base.constraint.Constraint,
+ ctype=Constraint,
descend_into=False,
active=True,
sort=True,
@@ -379,7 +391,7 @@ def _add_block(self, block):
self._add_constraint(con, lin_con_data)
for con in sub_block.component_data_objects(
- ctype=pyomo.core.base.sos.SOSConstraint,
+ ctype=SOSConstraint,
descend_into=False,
active=True,
sort=True,
@@ -388,7 +400,7 @@ def _add_block(self, block):
obj_counter = 0
for obj in sub_block.component_data_objects(
- ctype=pyomo.core.base.objective.Objective,
+ ctype=Objective,
descend_into=False,
active=True,
):
diff --git a/pyomo/solvers/plugins/solvers/cplex_persistent.py b/pyomo/solvers/plugins/solvers/cplex_persistent.py
index d9866f27542..e91346548c6 100644
--- a/pyomo/solvers/plugins/solvers/cplex_persistent.py
+++ b/pyomo/solvers/plugins/solvers/cplex_persistent.py
@@ -9,10 +9,6 @@
# ___________________________________________________________________________
from pyomo.core.expr.numvalue import value
-from pyomo.core.base.PyomoModel import ConcreteModel
-from pyomo.core.base.constraint import Constraint
-from pyomo.core.base.var import Var
-from pyomo.core.base.sos import SOSConstraint
from pyomo.solvers.plugins.solvers.cplex_direct import CPLEXDirect
from pyomo.solvers.plugins.solvers.persistent_solver import PersistentSolver
from pyomo.opt.base import SolverFactory
diff --git a/pyomo/solvers/plugins/solvers/direct_solver.py b/pyomo/solvers/plugins/solvers/direct_solver.py
index 9b7641af07e..2e0a48008b8 100644
--- a/pyomo/solvers/plugins/solvers/direct_solver.py
+++ b/pyomo/solvers/plugins/solvers/direct_solver.py
@@ -8,15 +8,18 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+import time
+import logging
+
from pyomo.solvers.plugins.solvers.direct_or_persistent_solver import DirectOrPersistentSolver
from pyomo.core.base.block import _BlockData
from pyomo.core.kernel.block import IBlock
from pyomo.core.base.suffix import active_import_suffix_generator
from pyomo.core.kernel.suffix import import_suffix_generator
-import pyutilib.misc
-import pyutilib.common
-import time
+from pyutilib.common import ApplicationError
+from pyutilib.misc import Options
+logger = logging.getLogger('pyomo.solvers')
class DirectSolver(DirectOrPersistentSolver):
"""
@@ -103,7 +106,7 @@ def solve(self, *args, **kwds):
orig_options = self.options
- self.options = pyutilib.misc.Options()
+ self.options = Options()
self.options.update(orig_options)
self.options.update(kwds.pop('options', {}))
self.options.update(
@@ -139,7 +142,7 @@ def solve(self, *args, **kwds):
"See the solver log above for diagnostic information." )
elif hasattr(_status, 'log') and _status.log:
logger.error("Solver log:\n" + str(_status.log))
- raise pyutilib.common.ApplicationError(
+ raise ApplicationError(
"Solver (%s) did not exit normally" % self.name)
solve_completion_time = time.time()
if self._report_timing:
diff --git a/pyomo/solvers/plugins/solvers/glpk_direct.py b/pyomo/solvers/plugins/solvers/glpk_direct.py
index 6f37d2d616f..a6cfb1d5a63 100644
--- a/pyomo/solvers/plugins/solvers/glpk_direct.py
+++ b/pyomo/solvers/plugins/solvers/glpk_direct.py
@@ -40,10 +40,9 @@ def configure_glpk_direct():
from pyutilib.misc import Bunch, Options
-from pyomo.opt.base import *
-from pyomo.opt.base.solvers import _extract_version
-from pyomo.opt.results import *
-from pyomo.opt.solver import *
+from pyomo.opt.base import OptSolver
+from pyomo.opt.base.solvers import _extract_version, SolverFactory
+from pyomo.opt.results import SolverResults, SolverStatus, SolutionStatus, ProblemSense
from pyomo.core.base.numvalue import value
import logging
diff --git a/pyomo/solvers/plugins/solvers/gurobi_direct.py b/pyomo/solvers/plugins/solvers/gurobi_direct.py
index 533ad22a701..cdb2a56d5d8 100644
--- a/pyomo/solvers/plugins/solvers/gurobi_direct.py
+++ b/pyomo/solvers/plugins/solvers/gurobi_direct.py
@@ -244,7 +244,7 @@ def _set_instance(self, model, kwds={}):
e = sys.exc_info()[1]
msg = ("Unable to create Gurobi model. "
"Have you installed the Python "
- "bindings for Gurboi?\n\n\t"+
+ "bindings for Gurobi?\n\n\t"+
"Error message: {0}".format(e))
raise Exception(msg)
diff --git a/pyomo/solvers/plugins/solvers/gurobi_persistent.py b/pyomo/solvers/plugins/solvers/gurobi_persistent.py
index 32bc59d1fbc..7b127a50fe4 100644
--- a/pyomo/solvers/plugins/solvers/gurobi_persistent.py
+++ b/pyomo/solvers/plugins/solvers/gurobi_persistent.py
@@ -8,7 +8,6 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core.base.PyomoModel import ConcreteModel
from pyomo.solvers.plugins.solvers.gurobi_direct import GurobiDirect
from pyomo.solvers.plugins.solvers.persistent_solver import PersistentSolver
from pyomo.core.expr.numvalue import value, is_fixed
diff --git a/pyomo/solvers/plugins/solvers/persistent_solver.py b/pyomo/solvers/plugins/solvers/persistent_solver.py
index 98e23b6c9b0..d7d599774aa 100644
--- a/pyomo/solvers/plugins/solvers/persistent_solver.py
+++ b/pyomo/solvers/plugins/solvers/persistent_solver.py
@@ -9,22 +9,20 @@
# ___________________________________________________________________________
from pyomo.solvers.plugins.solvers.direct_or_persistent_solver import DirectOrPersistentSolver
-from pyomo.core.base.PyomoModel import ConcreteModel
-from pyomo.core.base.block import _BlockData, Block
-from pyomo.core.base.objective import Objective
+from pyomo.core.base.block import _BlockData
from pyomo.core.kernel.block import IBlock
from pyomo.core.base.suffix import active_import_suffix_generator
from pyomo.core.kernel.suffix import import_suffix_generator
-from pyomo.core.expr import current as EXPR
from pyomo.core.expr.numvalue import native_numeric_types
-import pyutilib.misc
-import pyutilib.common
-import time
-import logging
from pyomo.core.base.constraint import Constraint
from pyomo.core.base.var import Var
from pyomo.core.base.sos import SOSConstraint
+from pyutilib.common import ApplicationError
+from pyutilib.misc import Options
+
+import time
+import logging
logger = logging.getLogger('pyomo.solvers')
@@ -450,7 +448,7 @@ def solve(self, *args, **kwds):
orig_options = self.options
- self.options = pyutilib.misc.Options()
+ self.options = Options()
self.options.update(orig_options)
self.options.update(kwds.pop('options', {}))
self.options.update(self._options_string_to_dict(kwds.pop('options_string', '')))
@@ -485,7 +483,7 @@ def solve(self, *args, **kwds):
"See the solver log above for diagnostic information.")
elif hasattr(_status, 'log') and _status.log:
logger.error("Solver log:\n" + str(_status.log))
- raise pyutilib.common.ApplicationError(
+ raise ApplicationError(
"Solver (%s) did not exit normally" % self.name)
solve_completion_time = time.time()
if self._report_timing:
diff --git a/pyomo/solvers/plugins/testdriver/mip.py b/pyomo/solvers/plugins/testdriver/mip.py
index 7f4fed597f1..0e28ad0e4a3 100644
--- a/pyomo/solvers/plugins/testdriver/mip.py
+++ b/pyomo/solvers/plugins/testdriver/mip.py
@@ -15,7 +15,7 @@
import pyomo.common
from pyutilib.misc import Options
-from pyomo.common.plugin import *
+from pyomo.common.plugin import Plugin, implements, alias
import pyomo.opt
old_tempdir = pyutilib.services.TempfileManager.tempdir
diff --git a/pyomo/solvers/tests/checks/test_CBCplugin.py b/pyomo/solvers/tests/checks/test_CBCplugin.py
index 38fd3283083..46c1a8d4661 100644
--- a/pyomo/solvers/tests/checks/test_CBCplugin.py
+++ b/pyomo/solvers/tests/checks/test_CBCplugin.py
@@ -7,14 +7,19 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
import os
import sys
from os.path import dirname, abspath
import pyutilib.th as unittest
-from pyomo.environ import *
-from pyomo.opt import *
+from pyomo.environ import (ConcreteModel, Var, Objective, RangeSet,
+ Constraint, Reals, NonNegativeIntegers,
+ NonNegativeReals, Integers, Binary,
+ maximize, minimize)
+from pyomo.opt import (SolverFactory, ProblemSense,
+ TerminationCondition, SolverStatus)
cbc_available = SolverFactory('cbc', solver_io='lp').available(exception_flag=False)
diff --git a/pyomo/solvers/tests/checks/test_CPLEXDirect.py b/pyomo/solvers/tests/checks/test_CPLEXDirect.py
index f1954885483..40e1cffd641 100644
--- a/pyomo/solvers/tests/checks/test_CPLEXDirect.py
+++ b/pyomo/solvers/tests/checks/test_CPLEXDirect.py
@@ -12,8 +12,11 @@
import pyutilib.th as unittest
-from pyomo.environ import *
-from pyomo.opt import *
+from pyomo.environ import (ConcreteModel, AbstractModel, Var, Objective,
+ Block, Constraint, Suffix, NonNegativeIntegers,
+ NonNegativeReals, Integers, Binary, is_fixed,
+ value)
+from pyomo.opt import SolverFactory, TerminationCondition, SolutionStatus
from pyomo.solvers.plugins.solvers.cplex_direct import (_CplexExpr,
_LinearConstraintData,
_VariableData)
diff --git a/pyomo/solvers/tests/checks/test_CPLEXPersistent.py b/pyomo/solvers/tests/checks/test_CPLEXPersistent.py
index f81e4a5310d..28f3b33610f 100644
--- a/pyomo/solvers/tests/checks/test_CPLEXPersistent.py
+++ b/pyomo/solvers/tests/checks/test_CPLEXPersistent.py
@@ -1,7 +1,19 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-from pyomo.environ import *
-from pyomo.opt import *
+import pyomo.environ
+from pyomo.core import (ConcreteModel, Var, Objective,
+ Constraint, NonNegativeReals)
+from pyomo.opt import SolverFactory
try:
import cplex
diff --git a/pyomo/solvers/tests/checks/test_GAMS.py b/pyomo/solvers/tests/checks/test_GAMS.py
index f7fe0655e62..b843a615c05 100644
--- a/pyomo/solvers/tests/checks/test_GAMS.py
+++ b/pyomo/solvers/tests/checks/test_GAMS.py
@@ -9,7 +9,9 @@
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Objective, Constraint, maximize, Expression, log10
+from pyomo.opt import SolverFactory, TerminationCondition
+
from pyomo.solvers.plugins.solvers.GAMS import (
GAMSShell, GAMSDirect, gdxcc_available
)
diff --git a/pyomo/solvers/tests/checks/test_cbc.py b/pyomo/solvers/tests/checks/test_cbc.py
index e77ecb0e63a..ab92b88b3f7 100644
--- a/pyomo/solvers/tests/checks/test_cbc.py
+++ b/pyomo/solvers/tests/checks/test_cbc.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import SolverFactory, ConcreteModel, Var, Constraint, Objective, Integers, Boolean
import pyutilib.th as unittest
from pyutilib.misc import capture_output
diff --git a/pyomo/solvers/tests/checks/test_cplex.py b/pyomo/solvers/tests/checks/test_cplex.py
index a0959fee9f4..877b1514397 100644
--- a/pyomo/solvers/tests/checks/test_cplex.py
+++ b/pyomo/solvers/tests/checks/test_cplex.py
@@ -10,12 +10,11 @@
import os
-import pyutilib
+from pyutilib.services import TempfileManager
import pyutilib.th as unittest
import pyomo.kernel as pmo
from pyomo.core import Binary, ConcreteModel, Constraint, Objective, Var, Integers, RangeSet, minimize, quicksum, Suffix
-from pyomo.environ import *
from pyomo.opt import ProblemFormat, convert_problem, SolverFactory, BranchDirection
from pyomo.solvers.plugins.solvers.CPLEX import CPLEXSHELL, MockCPLEX, _validate_file_name
@@ -69,12 +68,12 @@ class CPLEXShellWritePrioritiesFile(unittest.TestCase):
def setUp(self):
self.mock_model = self.get_mock_model()
self.mock_cplex_shell = self.get_mock_cplex_shell(self.mock_model)
- self.mock_cplex_shell._priorities_file_name = pyutilib.services.TempfileManager.create_tempfile(
+ self.mock_cplex_shell._priorities_file_name = TempfileManager.create_tempfile(
suffix=".cplex.ord"
)
def tearDown(self):
- pyutilib.services.TempfileManager.clear_tempfiles()
+ TempfileManager.clear_tempfiles()
def get_mock_model(self):
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/checks/test_gurobi_persistent.py b/pyomo/solvers/tests/checks/test_gurobi_persistent.py
index c723e7ff84b..091b9303584 100644
--- a/pyomo/solvers/tests/checks/test_gurobi_persistent.py
+++ b/pyomo/solvers/tests/checks/test_gurobi_persistent.py
@@ -1,5 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
-import pyomo.environ as pe
+import pyomo.environ as pyo
from pyomo.core.expr.taylor_series import taylor_series_expansion
try:
import gurobipy
@@ -12,13 +22,13 @@
class TestGurobiPersistent(unittest.TestCase):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_basics(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(-10, 10))
- m.y = pe.Var()
- m.obj = pe.Objective(expr=m.x**2 + m.y**2)
- m.c1 = pe.Constraint(expr=m.y >= 2*m.x + 1)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(-10, 10))
+ m.y = pyo.Var()
+ m.obj = pyo.Objective(expr=m.x**2 + m.y**2)
+ m.c1 = pyo.Constraint(expr=m.y >= 2*m.x + 1)
- opt = pe.SolverFactory('gurobi_persistent')
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
self.assertEqual(opt.get_model_attr('NumVars'), 2)
@@ -34,7 +44,7 @@ def test_basics(self):
self.assertAlmostEqual(m.dual[m.c1], -0.4)
del m.dual
- m.c2 = pe.Constraint(expr=m.y >= -m.x + 1)
+ m.c2 = pyo.Constraint(expr=m.y >= -m.x + 1)
opt.add_constraint(m.c2)
self.assertEqual(opt.get_model_attr('NumVars'), 2)
self.assertEqual(opt.get_model_attr('NumConstrs'), 2)
@@ -75,7 +85,7 @@ def test_basics(self):
self.assertEqual(opt.get_var_attr(m.x, 'LB'), -5)
self.assertEqual(opt.get_var_attr(m.x, 'UB'), 5)
- m.c2 = pe.Constraint(expr=m.y >= m.x**2)
+ m.c2 = pyo.Constraint(expr=m.y >= m.x**2)
opt.add_constraint(m.c2)
self.assertEqual(opt.get_model_attr('NumVars'), 2)
self.assertEqual(opt.get_model_attr('NumConstrs'), 1)
@@ -87,7 +97,7 @@ def test_basics(self):
self.assertEqual(opt.get_model_attr('NumConstrs'), 1)
self.assertEqual(opt.get_model_attr('NumQConstrs'), 0)
- m.z = pe.Var()
+ m.z = pyo.Var()
opt.add_var(m.z)
self.assertEqual(opt.get_model_attr('NumVars'), 3)
opt.remove_var(m.z)
@@ -96,14 +106,14 @@ def test_basics(self):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_update1(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.z = pe.Var()
- m.obj = pe.Objective(expr=m.z)
- m.c1 = pe.Constraint(expr=m.z >= m.x**2 + m.y**2)
-
- opt = pe.SolverFactory('gurobi_persistent')
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.z = pyo.Var()
+ m.obj = pyo.Objective(expr=m.z)
+ m.c1 = pyo.Constraint(expr=m.z >= m.x**2 + m.y**2)
+
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
self.assertEqual(opt._solver_model.getAttr('NumQConstrs'), 0)
@@ -118,14 +128,14 @@ def test_update1(self):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_update2(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.z = pe.Var()
- m.obj = pe.Objective(expr=m.z)
- m.c2 = pe.Constraint(expr=m.x + m.y == 1)
-
- opt = pe.SolverFactory('gurobi_persistent')
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.z = pyo.Var()
+ m.obj = pyo.Objective(expr=m.z)
+ m.c2 = pyo.Constraint(expr=m.x + m.y == 1)
+
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
self.assertEqual(opt._solver_model.getAttr('NumConstrs'), 0)
@@ -140,18 +150,18 @@ def test_update2(self):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_update3(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.z = pe.Var()
- m.obj = pe.Objective(expr=m.z)
- m.c1 = pe.Constraint(expr=m.z >= m.x**2 + m.y**2)
-
- opt = pe.SolverFactory('gurobi_persistent')
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.z = pyo.Var()
+ m.obj = pyo.Objective(expr=m.z)
+ m.c1 = pyo.Constraint(expr=m.z >= m.x**2 + m.y**2)
+
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
opt.update()
self.assertEqual(opt._solver_model.getAttr('NumQConstrs'), 1)
- m.c2 = pe.Constraint(expr=m.y >= m.x**2)
+ m.c2 = pyo.Constraint(expr=m.y >= m.x**2)
opt.add_constraint(m.c2)
self.assertEqual(opt._solver_model.getAttr('NumQConstrs'), 1)
opt.remove_constraint(m.c2)
@@ -160,18 +170,18 @@ def test_update3(self):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_update4(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.z = pe.Var()
- m.obj = pe.Objective(expr=m.z)
- m.c1 = pe.Constraint(expr=m.z >= m.x + m.y)
-
- opt = pe.SolverFactory('gurobi_persistent')
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.z = pyo.Var()
+ m.obj = pyo.Objective(expr=m.z)
+ m.c1 = pyo.Constraint(expr=m.z >= m.x + m.y)
+
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
opt.update()
self.assertEqual(opt._solver_model.getAttr('NumConstrs'), 1)
- m.c2 = pe.Constraint(expr=m.y >= m.x)
+ m.c2 = pyo.Constraint(expr=m.y >= m.x)
opt.add_constraint(m.c2)
self.assertEqual(opt._solver_model.getAttr('NumConstrs'), 1)
opt.remove_constraint(m.c2)
@@ -180,14 +190,14 @@ def test_update4(self):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_update5(self):
- m = pe.ConcreteModel()
- m.a = pe.Set(initialize=[1,2,3], ordered=True)
- m.x = pe.Var(m.a, within=pe.Binary)
- m.y = pe.Var(within=pe.Binary)
- m.obj = pe.Objective(expr=m.y)
- m.c1 = pe.SOSConstraint(var=m.x, sos=1)
-
- opt = pe.SolverFactory('gurobi_persistent')
+ m = pyo.ConcreteModel()
+ m.a = pyo.Set(initialize=[1,2,3], ordered=True)
+ m.x = pyo.Var(m.a, within=pyo.Binary)
+ m.y = pyo.Var(within=pyo.Binary)
+ m.obj = pyo.Objective(expr=m.y)
+ m.c1 = pyo.SOSConstraint(var=m.x, sos=1)
+
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
self.assertEqual(opt._solver_model.getAttr('NumSOS'), 0)
@@ -202,18 +212,18 @@ def test_update5(self):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_update6(self):
- m = pe.ConcreteModel()
- m.a = pe.Set(initialize=[1,2,3], ordered=True)
- m.x = pe.Var(m.a, within=pe.Binary)
- m.y = pe.Var(within=pe.Binary)
- m.obj = pe.Objective(expr=m.y)
- m.c1 = pe.SOSConstraint(var=m.x, sos=1)
-
- opt = pe.SolverFactory('gurobi_persistent')
+ m = pyo.ConcreteModel()
+ m.a = pyo.Set(initialize=[1,2,3], ordered=True)
+ m.x = pyo.Var(m.a, within=pyo.Binary)
+ m.y = pyo.Var(within=pyo.Binary)
+ m.obj = pyo.Objective(expr=m.y)
+ m.c1 = pyo.SOSConstraint(var=m.x, sos=1)
+
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
opt.update()
self.assertEqual(opt._solver_model.getAttr('NumSOS'), 1)
- m.c2 = pe.SOSConstraint(var=m.x, sos=2)
+ m.c2 = pyo.SOSConstraint(var=m.x, sos=2)
opt.add_sos_constraint(m.c2)
self.assertEqual(opt._solver_model.getAttr('NumSOS'), 1)
opt.remove_sos_constraint(m.c2)
@@ -222,11 +232,11 @@ def test_update6(self):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_update7(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
- opt = pe.SolverFactory('gurobi_persistent')
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
self.assertEqual(opt._solver_model.getAttr('NumVars'), 0)
@@ -248,44 +258,44 @@ def test_update7(self):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_linear_constraint_attr(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.c = pe.Constraint(expr=m.x + m.y == 1)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=m.x + m.y == 1)
- opt = pe.SolverFactory('gurobi_persistent')
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
opt.set_linear_constraint_attr(m.c, 'Lazy', 1)
self.assertEqual(opt.get_linear_constraint_attr(m.c, 'Lazy'), 1)
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_quadratic_constraint_attr(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.y = pe.Var()
- m.c = pe.Constraint(expr=m.y >= m.x**2)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.y = pyo.Var()
+ m.c = pyo.Constraint(expr=m.y >= m.x**2)
- opt = pe.SolverFactory('gurobi_persistent')
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
self.assertEqual(opt.get_quadratic_constraint_attr(m.c, 'QCRHS'), 0)
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_var_attr(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(within=pe.Binary)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(within=pyo.Binary)
- opt = pe.SolverFactory('gurobi_persistent')
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
opt.set_var_attr(m.x, 'Start', 1)
self.assertEqual(opt.get_var_attr(m.x, 'Start'), 1)
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_callback(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(bounds=(0, 4))
- m.y = pe.Var(within=pe.Integers, bounds=(0, None))
- m.obj = pe.Objective(expr=2*m.x + m.y)
- m.cons = pe.ConstraintList()
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(bounds=(0, 4))
+ m.y = pyo.Var(within=pyo.Integers, bounds=(0, None))
+ m.obj = pyo.Objective(expr=2*m.x + m.y)
+ m.cons = pyo.ConstraintList()
def _add_cut(xval):
m.x.value = xval
@@ -294,7 +304,7 @@ def _add_cut(xval):
_add_cut(0)
_add_cut(4)
- opt = pe.SolverFactory('gurobi_persistent')
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
opt.set_gurobi_param('PreCrush', 1)
opt.set_gurobi_param('LazyConstraints', 1)
@@ -312,17 +322,17 @@ def _my_callback(cb_m, cb_opt, cb_where):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_add_column(self):
- m = pe.ConcreteModel()
- m.x = pe.Var(within=pe.NonNegativeReals)
- m.c = pe.Constraint(expr=(0, m.x, 1))
- m.obj = pe.Objective(expr=-m.x)
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var(within=pyo.NonNegativeReals)
+ m.c = pyo.Constraint(expr=(0, m.x, 1))
+ m.obj = pyo.Objective(expr=-m.x)
- opt = pe.SolverFactory('gurobi_persistent')
+ opt = pyo.SolverFactory('gurobi_persistent')
opt.set_instance(m)
opt.solve()
self.assertAlmostEqual(m.x.value, 1)
- m.y = pe.Var(within=pe.NonNegativeReals)
+ m.y = pyo.Var(within=pyo.NonNegativeReals)
opt.add_column(m, m.y, -3, [m.c], [2])
opt.solve()
@@ -332,35 +342,35 @@ def test_add_column(self):
@unittest.skipIf(not gurobipy_available, "gurobipy is not available")
def test_add_column_exceptions(self):
- m = pe.ConcreteModel()
- m.x = pe.Var()
- m.c = pe.Constraint(expr=(0, m.x, 1))
- m.ci = pe.Constraint([1,2], rule=lambda m,i:(0,m.x,i+1))
- m.cd = pe.Constraint(expr=(0, -m.x, 1))
+ m = pyo.ConcreteModel()
+ m.x = pyo.Var()
+ m.c = pyo.Constraint(expr=(0, m.x, 1))
+ m.ci = pyo.Constraint([1,2], rule=lambda m,i:(0,m.x,i+1))
+ m.cd = pyo.Constraint(expr=(0, -m.x, 1))
m.cd.deactivate()
- m.obj = pe.Objective(expr=-m.x)
+ m.obj = pyo.Objective(expr=-m.x)
- opt = pe.SolverFactory('gurobi_persistent')
+ opt = pyo.SolverFactory('gurobi_persistent')
# set_instance not called
self.assertRaises(RuntimeError, opt.add_column, m, m.x, 0, [m.c], [1])
opt.set_instance(m)
- m2 = pe.ConcreteModel()
- m2.y = pe.Var()
- m2.c = pe.Constraint(expr=(0,m.x,1))
+ m2 = pyo.ConcreteModel()
+ m2.y = pyo.Var()
+ m2.c = pyo.Constraint(expr=(0,m.x,1))
# different model than attached to opt
self.assertRaises(RuntimeError, opt.add_column, m2, m2.y, 0, [], [])
# pyomo var attached to different model
self.assertRaises(RuntimeError, opt.add_column, m, m2.y, 0, [], [])
- z = pe.Var()
+ z = pyo.Var()
# pyomo var floating
self.assertRaises(RuntimeError, opt.add_column, m, z, -2, [m.c, z], [1])
- m.y = pe.Var()
+ m.y = pyo.Var()
# len(coefficents) == len(constraints)
self.assertRaises(RuntimeError, opt.add_column, m, m.y, -2, [m.c], [1,2])
self.assertRaises(RuntimeError, opt.add_column, m, m.y, -2, [m.c, z], [1])
diff --git a/pyomo/solvers/tests/checks/test_mosek.py b/pyomo/solvers/tests/checks/test_mosek.py
index e4e54fce903..3b19e60f5ee 100755
--- a/pyomo/solvers/tests/checks/test_mosek.py
+++ b/pyomo/solvers/tests/checks/test_mosek.py
@@ -1,9 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import pyutilib.th as unittest
from pyomo.opt import (TerminationCondition,
- SolutionStatus,
- SolverStatus)
-import pyomo.environ as aml
+ SolutionStatus)
+import pyomo.environ as pyo
import pyomo.kernel as pmo
import sys
@@ -31,13 +40,13 @@ def tearDown(self):
def test_infeasible_lp(self):
- model = aml.ConcreteModel()
- model.X = aml.Var(within=aml.NonNegativeReals)
- model.C1 = aml.Constraint(expr=model.X == 1)
- model.C2 = aml.Constraint(expr=model.X == 2)
- model.O = aml.Objective(expr=model.X)
+ model = pyo.ConcreteModel()
+ model.X = pyo.Var(within=pyo.NonNegativeReals)
+ model.C1 = pyo.Constraint(expr=model.X == 1)
+ model.C2 = pyo.Constraint(expr=model.X == 2)
+ model.O = pyo.Objective(expr=model.X)
- opt = aml.SolverFactory("mosek")
+ opt = pyo.SolverFactory("mosek")
results = opt.solve(model)
self.assertIn(results.solver.termination_condition,
@@ -46,11 +55,11 @@ def test_infeasible_lp(self):
def test_unbounded_lp(self):
- model = aml.ConcreteModel()
- model.X = aml.Var()
- model.O = aml.Objective(expr=model.X)
+ model = pyo.ConcreteModel()
+ model.X = pyo.Var()
+ model.O = pyo.Objective(expr=model.X)
- opt = aml.SolverFactory("mosek")
+ opt = pyo.SolverFactory("mosek")
results = opt.solve(model)
self.assertIn(results.solver.termination_condition,
@@ -59,11 +68,11 @@ def test_unbounded_lp(self):
def test_optimal_lp(self):
- model = aml.ConcreteModel()
- model.X = aml.Var(within=aml.NonNegativeReals)
- model.O = aml.Objective(expr=model.X)
+ model = pyo.ConcreteModel()
+ model.X = pyo.Var(within=pyo.NonNegativeReals)
+ model.O = pyo.Objective(expr=model.X)
- opt = aml.SolverFactory("mosek")
+ opt = pyo.SolverFactory("mosek")
results = opt.solve(model, load_solutions=False)
self.assertEqual(results.solution.status,
@@ -71,19 +80,19 @@ def test_optimal_lp(self):
def test_get_duals_lp(self):
- model = aml.ConcreteModel()
- model.X = aml.Var(within=aml.NonNegativeReals)
- model.Y = aml.Var(within=aml.NonNegativeReals)
+ model = pyo.ConcreteModel()
+ model.X = pyo.Var(within=pyo.NonNegativeReals)
+ model.Y = pyo.Var(within=pyo.NonNegativeReals)
- model.C1 = aml.Constraint(expr=2*model.X + model.Y >= 8)
- model.C2 = aml.Constraint(expr=model.X + 3*model.Y >= 6)
+ model.C1 = pyo.Constraint(expr=2*model.X + model.Y >= 8)
+ model.C2 = pyo.Constraint(expr=model.X + 3*model.Y >= 6)
- model.O = aml.Objective(expr=model.X + model.Y)
+ model.O = pyo.Objective(expr=model.X + model.Y)
- opt = aml.SolverFactory("mosek")
+ opt = pyo.SolverFactory("mosek")
results = opt.solve(model, suffixes=['dual'], load_solutions=False)
- model.dual = aml.Suffix(direction=aml.Suffix.IMPORT)
+ model.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT)
model.solutions.load_from(results)
self.assertAlmostEqual(model.dual[model.C1], 0.4, 4)
@@ -91,13 +100,13 @@ def test_get_duals_lp(self):
def test_infeasible_mip(self):
- model = aml.ConcreteModel()
- model.X = aml.Var(within=aml.NonNegativeIntegers)
- model.C1 = aml.Constraint(expr=model.X == 1)
- model.C2 = aml.Constraint(expr=model.X == 2)
- model.O = aml.Objective(expr=model.X)
+ model = pyo.ConcreteModel()
+ model.X = pyo.Var(within=pyo.NonNegativeIntegers)
+ model.C1 = pyo.Constraint(expr=model.X == 1)
+ model.C2 = pyo.Constraint(expr=model.X == 2)
+ model.O = pyo.Objective(expr=model.X)
- opt = aml.SolverFactory("mosek")
+ opt = pyo.SolverFactory("mosek")
results = opt.solve(model)
self.assertIn(results.solver.termination_condition,
@@ -106,12 +115,12 @@ def test_infeasible_mip(self):
def test_unbounded_mip(self):
- model = aml.AbstractModel()
- model.X = aml.Var(within=aml.Integers)
- model.O = aml.Objective(expr=model.X)
+ model = pyo.AbstractModel()
+ model.X = pyo.Var(within=pyo.Integers)
+ model.O = pyo.Objective(expr=model.X)
instance = model.create_instance()
- opt = aml.SolverFactory("mosek")
+ opt = pyo.SolverFactory("mosek")
results = opt.solve(instance)
self.assertIn(results.solver.termination_condition,
@@ -120,11 +129,11 @@ def test_unbounded_mip(self):
def test_optimal_mip(self):
- model = aml.ConcreteModel()
- model.X = aml.Var(within=aml.NonNegativeIntegers)
- model.O = aml.Objective(expr=model.X)
+ model = pyo.ConcreteModel()
+ model.X = pyo.Var(within=pyo.NonNegativeIntegers)
+ model.O = pyo.Objective(expr=model.X)
- opt = aml.SolverFactory("mosek")
+ opt = pyo.SolverFactory("mosek")
results = opt.solve(model, load_solutions=False)
self.assertEqual(results.solution.status,
@@ -132,11 +141,11 @@ def test_optimal_mip(self):
def test_optimal_mip(self):
- model = aml.ConcreteModel()
- model.X = aml.Var(within=aml.NonNegativeIntegers)
- model.O = aml.Objective(expr=model.X)
+ model = pyo.ConcreteModel()
+ model.X = pyo.Var(within=pyo.NonNegativeIntegers)
+ model.O = pyo.Objective(expr=model.X)
- opt = aml.SolverFactory("mosek")
+ opt = pyo.SolverFactory("mosek")
results = opt.solve(model, load_solutions=False)
self.assertEqual(results.solution.status,
diff --git a/pyomo/solvers/tests/checks/test_no_solution_behavior.py b/pyomo/solvers/tests/checks/test_no_solution_behavior.py
index 9a84696a06f..8e3c8bdda9f 100644
--- a/pyomo/solvers/tests/checks/test_no_solution_behavior.py
+++ b/pyomo/solvers/tests/checks/test_no_solution_behavior.py
@@ -22,7 +22,6 @@
from pyomo.solvers.tests.testcases import test_scenarios
from pyomo.common.log import LoggingIntercept
-import six
from six import StringIO
# The test directory
diff --git a/pyomo/solvers/tests/checks/test_pickle.py b/pyomo/solvers/tests/checks/test_pickle.py
index c9ec50867bb..5e903365d32 100644
--- a/pyomo/solvers/tests/checks/test_pickle.py
+++ b/pyomo/solvers/tests/checks/test_pickle.py
@@ -9,9 +9,6 @@
# ___________________________________________________________________________
import pickle
-import os
-from os.path import join, dirname, abspath
-import warnings
import types
try:
import new
diff --git a/pyomo/solvers/tests/core/diet1.py b/pyomo/solvers/tests/core/diet1.py
index 36e5dbd6ed1..b5560bcf526 100644
--- a/pyomo/solvers/tests/core/diet1.py
+++ b/pyomo/solvers/tests/core/diet1.py
@@ -1,10 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
#
# Imports
#
-import sys
-import os
-from pyomo.core import *
+from pyomo.core import AbstractModel, Set, Param, Var, PositiveReals, NonNegativeReals, NonNegativeIntegers, Constraint, Objective, minimize
infinity = float('inf')
diff --git a/pyomo/solvers/tests/core/plugins/__init__.py b/pyomo/solvers/tests/core/plugins/__init__.py
index 5961a8d1d96..8b137891791 100644
--- a/pyomo/solvers/tests/core/plugins/__init__.py
+++ b/pyomo/solvers/tests/core/plugins/__init__.py
@@ -1,2 +1 @@
-#from pyomo.data.core.plugins.lp import *
-#from pyomo.data.core.plugins.mip import *
+
diff --git a/pyomo/solvers/tests/core/plugins/lp.py b/pyomo/solvers/tests/core/plugins/lp.py
index 21fef0c4b64..220ee516f96 100644
--- a/pyomo/solvers/tests/core/plugins/lp.py
+++ b/pyomo/solvers/tests/core/plugins/lp.py
@@ -1,7 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
-import sys
-import pyutilib.math
-import pyomo.opt
+from pyutilib.math import approx_equal
+from pyomo.opt import undefined, SolutionStatus, SolverStatus, TerminationCondition
def lp_bounds(results, data, options):
@@ -13,14 +21,14 @@ def lp_bounds(results, data, options):
#
#
value = results.problem[0].lower_bound
- data['lower bound'] = pyutilib.math.approx_equal(value, options._baseline.problem[0].lower_bound, options.abstol, options.reltol), "'{0}' lower bound for {2} LP (baseline={1})".format(value, options._baseline.problem[0].lower_bound, name)
+ data['lower bound'] = approx_equal(value, options._baseline.problem[0].lower_bound, options.abstol, options.reltol), "'{0}' lower bound for {2} LP (baseline={1})".format(value, options._baseline.problem[0].lower_bound, name)
#
value = results.problem[0].upper_bound
- data['upper bound'] = pyutilib.math.approx_equal(value, options._baseline.problem[0].upper_bound, options.abstol, options.reltol), "'{0}' upper bound for {2} LP (baseline={1})".format(value, options._baseline.problem[0].upper_bound, name)
+ data['upper bound'] = approx_equal(value, options._baseline.problem[0].upper_bound, options.abstol, options.reltol), "'{0}' upper bound for {2} LP (baseline={1})".format(value, options._baseline.problem[0].upper_bound, name)
#
value = results.solution[0].gap
- if value != pyomo.opt.undefined:
- data['solution gap'] = pyutilib.math.approx_equal(value, 0.0, options.abstol, options.reltol), "'{0}' solution gap for {1} LP solution".format(value, name)
+ if value != undefined:
+ data['solution gap'] = approx_equal(value, 0.0, options.abstol, options.reltol), "'{0}' solution gap for {1} LP solution".format(value, name)
#
#
@@ -44,10 +52,10 @@ def lp_feasible_solution(results, data, options, name):
#
#
value = results.solver.status
- data['solver status'] = value==pyomo.opt.SolverStatus.ok, "'{0}' solver status for {1} LP".format(value, name)
+ data['solver status'] = value==SolverStatus.ok, "'{0}' solver status for {1} LP".format(value, name)
#
value = results.solver.termination_condition
- data['termination condition'] = value==pyomo.opt.TerminationCondition.optimal, "'{0}' termination condition for {1} LP".format(value, name)
+ data['termination condition'] = value==TerminationCondition.optimal, "'{0}' termination condition for {1} LP".format(value, name)
#
value = results.solver.get('error_rc',None)
data['error rc'] = value==0 or value==None, "'{0}' error rc for {1} LP".format(value, name)
@@ -57,7 +65,7 @@ def lp_feasible_solution(results, data, options, name):
data['single solution'] = value==1, '{0} solutions found for {1} LP'.format(value, name)
#
value = results.solution[0].status
- data['solution status'] = value==pyomo.opt.SolutionStatus.optimal or value==pyomo.opt.SolutionStatus.feasible, "'{0}' solution status for {1} LP solution".format(value, name)
+ data['solution status'] = value==SolutionStatus.optimal or value==SolutionStatus.feasible, "'{0}' solution status for {1} LP solution".format(value, name)
#
if len(results.solution[0].objective) > 0:
objname = results.solution[0].objective.keys()[0]
@@ -65,7 +73,7 @@ def lp_feasible_solution(results, data, options, name):
data['objective name'] = objname == _objname, "'{0}' objective name for {2} LP solution (baseline={1})".format(objname, _objname, name)
#
value = results.solution[0].objective[objname].value
- data['objective value'] = pyutilib.math.approx_equal(value, options._baseline.solution[0].objective[_objname].value, options.abstol, options.reltol), "'{0}' objective value for {2} LP solution (baseline={1})".format(value, options._baseline.solution[0].objective[_objname].value, name)
+ data['objective value'] = approx_equal(value, options._baseline.solution[0].objective[_objname].value, options.abstol, options.reltol), "'{0}' objective value for {2} LP solution (baseline={1})".format(value, options._baseline.solution[0].objective[_objname].value, name)
def lp_feasible(results, data, options):
@@ -88,10 +96,10 @@ def lp_unbounded(results, data, options):
data['no solution'] = value==0, '{0} solutions found for unbounded LP'.format(value)
#
value = results.solver.status
- data['solver status'] = value==pyomo.opt.SolverStatus.ok, "'{0}' solver status for unbounded LP".format(value)
+ data['solver status'] = value==SolverStatus.ok, "'{0}' solver status for unbounded LP".format(value)
#
value = results.solver.termination_condition
- data['termination condition'] = value==pyomo.opt.TerminationCondition.unbounded, "'{0}' termination condition for unbounded LP".format(value)
+ data['termination condition'] = value==TerminationCondition.unbounded, "'{0}' termination condition for unbounded LP".format(value)
def lp_infeasible(results, data, options):
@@ -104,10 +112,10 @@ def lp_infeasible(results, data, options):
data['single objective'] = value==1, '{0} objectives found for infeasible LP'.format(value)
#
value = results.solver.status
- data['solver status'] = value==pyomo.opt.SolverStatus.ok, "'{0}' solver status for infeasible LP".format(value)
+ data['solver status'] = value==SolverStatus.ok, "'{0}' solver status for infeasible LP".format(value)
#
value = results.solver.termination_condition
- data['termination condition'] = value==pyomo.opt.TerminationCondition.infeasible, "'{0}' termination condition for infeasible LP".format(value)
+ data['termination condition'] = value==TerminationCondition.infeasible, "'{0}' termination condition for infeasible LP".format(value)
def lp_unique_dual(results, data, options):
diff --git a/pyomo/solvers/tests/core/plugins/mip.py b/pyomo/solvers/tests/core/plugins/mip.py
index cb8fe1e1a4c..5c3b40353bb 100644
--- a/pyomo/solvers/tests/core/plugins/mip.py
+++ b/pyomo/solvers/tests/core/plugins/mip.py
@@ -1,7 +1,15 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
-import sys
-import pyutilib.math
-import pyomo.opt
+from pyutilib.math import approx_equal
+from pyomo.opt import undefined, SolutionStatus, SolverStatus, TerminationCondition
def mip_unique(results, data, options, name='unique-feasible'):
@@ -15,11 +23,11 @@ def mip_unique(results, data, options, name='unique-feasible'):
data['single solution'] = value==1, '{0} solutions found for {1} MIP'.format(value, name)
#
value = results.solution[0].gap
- if value != pyomo.opt.undefined:
- data['solution gap'] = pyutilib.math.approx_equal(value, 0.0, options.abstol, options.reltol), "'{0}' solution gap for {1} MIP solution".format(value, name)
+ if value != undefined:
+ data['solution gap'] = approx_equal(value, 0.0, options.abstol, options.reltol), "'{0}' solution gap for {1} MIP solution".format(value, name)
#
value = results.solution[0].status
- data['solution status'] = value==pyomo.opt.SolutionStatus.optimal, "'{0}' solution status for {1} MIP solution".format(value, name)
+ data['solution status'] = value==SolutionStatus.optimal, "'{0}' solution status for {1} MIP solution".format(value, name)
#
if len(results.solution[0].objective) > 0:
objname = results.solution[0].objective.keys()[0]
@@ -27,7 +35,7 @@ def mip_unique(results, data, options, name='unique-feasible'):
data['objective name'] = objname == _objname, "'{0}' objective name for {2} MIP solution (baseline={1})".format(objname, _objname, name)
#
value = results.solution[0].objective[objname].value
- data['objective value'] = pyutilib.math.approx_equal(value, options._baseline.solution[0].objective[_objname].value, options.abstol, options.reltol), "'{0}' objective value for {2} MIP solution (baseline={1})".format(value, options._baseline.solution[0].objective[_objname].value, name)
+ data['objective value'] = approx_equal(value, options._baseline.solution[0].objective[_objname].value, options.abstol, options.reltol), "'{0}' objective value for {2} MIP solution (baseline={1})".format(value, options._baseline.solution[0].objective[_objname].value, name)
#
@@ -46,20 +54,20 @@ def mip_feasible_solution(results, data, options, name):
data['single objective'] = value==1, '{0} objectives found for {1} MIP'.format(value, name)
#
value = results.problem[0].lower_bound
- data['lower bound'] = pyutilib.math.approx_equal(value, options._baseline.problem[0].lower_bound, options.abstol, options.reltol), "'{0}' lower bound for {2} MIP (baseline={1})".format(value, options._baseline.problem[0].lower_bound, name)
+ data['lower bound'] = approx_equal(value, options._baseline.problem[0].lower_bound, options.abstol, options.reltol), "'{0}' lower bound for {2} MIP (baseline={1})".format(value, options._baseline.problem[0].lower_bound, name)
#
value = results.problem[0].upper_bound
- data['upper bound'] = pyutilib.math.approx_equal(value, options._baseline.problem[0].upper_bound, options.abstol, options.reltol), "'{0}' upper bound for {2} MIP (baseline={1})".format(value, options._baseline.problem[0].upper_bound, name)
+ data['upper bound'] = approx_equal(value, options._baseline.problem[0].upper_bound, options.abstol, options.reltol), "'{0}' upper bound for {2} MIP (baseline={1})".format(value, options._baseline.problem[0].upper_bound, name)
#
value = str(results.problem[0].sense)
data['sense'] = value==options._baseline.problem[0].sense, "'{0}' sense for {2} MIP (baseline={1})".format(value, options._baseline.problem[0].sense, name)
#
#
value = results.solver.status
- data['solver status'] = value==pyomo.opt.SolverStatus.ok, "'{0}' solver status for {1} MIP".format(value, name)
+ data['solver status'] = value==SolverStatus.ok, "'{0}' solver status for {1} MIP".format(value, name)
#
value = results.solver.termination_condition
- data['termination condition'] = value==pyomo.opt.TerminationCondition.optimal, "'{0}' termination condition for {1} MIP".format(value, name)
+ data['termination condition'] = value==TerminationCondition.optimal, "'{0}' termination condition for {1} MIP".format(value, name)
#
value = results.solver.error_rc
data['error rc'] = value==0, "'{0}' error rc for {1} MIP".format(value, name)
@@ -89,10 +97,10 @@ def mip_unbounded(results, data, options):
data['no solution'] = value==0, '{0} solutions found for unbounded MIP'.format(value)
#
value = results.solver.status
- data['solver status'] = value==pyomo.opt.SolverStatus.ok, "'{0}' solver status for unbounded MIP".format(value)
+ data['solver status'] = value==SolverStatus.ok, "'{0}' solver status for unbounded MIP".format(value)
#
value = results.solver.termination_condition
- data['termination condition'] = value==pyomo.opt.TerminationCondition.unbounded, "'{0}' termination condition for unbounded MIP".format(value)
+ data['termination condition'] = value==TerminationCondition.unbounded, "'{0}' termination condition for unbounded MIP".format(value)
def mip_infeasible(results, data, options):
@@ -105,8 +113,8 @@ def mip_infeasible(results, data, options):
data['single objective'] = value==1, '{0} objectives found for infeasible MIP'.format(value)
#
value = results.solver.status
- data['solver status'] = value==pyomo.opt.SolverStatus.ok, "'{0}' solver status for infeasible MIP".format(value)
+ data['solver status'] = value==SolverStatus.ok, "'{0}' solver status for infeasible MIP".format(value)
#
value = results.solver.termination_condition
- data['termination condition'] = value==pyomo.opt.TerminationCondition.infeasible, "'{0}' termination condition for infeasible MIP".format(value)
+ data['termination condition'] = value==TerminationCondition.infeasible, "'{0}' termination condition for infeasible MIP".format(value)
diff --git a/pyomo/solvers/tests/core/problems/constant1a.py b/pyomo/solvers/tests/core/problems/constant1a.py
index 86e0d9ea595..e3bf181ae21 100644
--- a/pyomo/solvers/tests/core/problems/constant1a.py
+++ b/pyomo/solvers/tests/core/problems/constant1a.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective, Constraint
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/constant1b.py b/pyomo/solvers/tests/core/problems/constant1b.py
index b3bf3ac374d..77821fdb304 100644
--- a/pyomo/solvers/tests/core/problems/constant1b.py
+++ b/pyomo/solvers/tests/core/problems/constant1b.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, maximize
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/diet1.py b/pyomo/solvers/tests/core/problems/diet1.py
index 36e5dbd6ed1..cbee2b8241c 100644
--- a/pyomo/solvers/tests/core/problems/diet1.py
+++ b/pyomo/solvers/tests/core/problems/diet1.py
@@ -1,10 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
#
# Imports
#
-import sys
-import os
-from pyomo.core import *
+from pyomo.core import AbstractModel, Set, Param, Var, PositiveReals, NonNegativeIntegers, NonNegativeReals, Constraint, Objective, minimize
infinity = float('inf')
diff --git a/pyomo/solvers/tests/core/problems/infeasible1a.py b/pyomo/solvers/tests/core/problems/infeasible1a.py
index 29638c30e45..52c83b35d89 100644
--- a/pyomo/solvers/tests/core/problems/infeasible1a.py
+++ b/pyomo/solvers/tests/core/problems/infeasible1a.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective, Constraint
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/infeasible1b.py b/pyomo/solvers/tests/core/problems/infeasible1b.py
index beab9eba23c..d2b7626e995 100644
--- a/pyomo/solvers/tests/core/problems/infeasible1b.py
+++ b/pyomo/solvers/tests/core/problems/infeasible1b.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, maximize
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/lp_basic.py b/pyomo/solvers/tests/core/problems/lp_basic.py
index 2203457beda..63ca386dc3c 100644
--- a/pyomo/solvers/tests/core/problems/lp_basic.py
+++ b/pyomo/solvers/tests/core/problems/lp_basic.py
@@ -1,8 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
#
# A LP model adapted from the Wikipedia description of the simplex algorithm:
# http://en.wikipedia.org/wiki/Simplex_algorithm
#
-from pyomo.core import *
+
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, NonNegativeReals
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/lp_unique1.py b/pyomo/solvers/tests/core/problems/lp_unique1.py
index 46f3c7ea9ff..b3a7ab91030 100644
--- a/pyomo/solvers/tests/core/problems/lp_unique1.py
+++ b/pyomo/solvers/tests/core/problems/lp_unique1.py
@@ -1,6 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
# This problem has a unique primal and dual solution.
-from pyomo.core import *
+from pyomo.core import ConcreteModel, Param, RangeSet, Var, NonNegativeReals, Objective, Constraint, Suffix, sum_product
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/lp_unique1_proof.py b/pyomo/solvers/tests/core/problems/lp_unique1_proof.py
index fca1e306cde..69ce9bf3b7a 100644
--- a/pyomo/solvers/tests/core/problems/lp_unique1_proof.py
+++ b/pyomo/solvers/tests/core/problems/lp_unique1_proof.py
@@ -1,6 +1,16 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
# This is a computational proof that lp_unique1.py has a unique primal and dual solution.
-from pyomo.core import *
+from pyomo.core import ConcreteModel, Param, RangeSet, Var, Constraint, Objective, NonNegativeReals
from pyomo.opt import SolverFactory
def get_model(flag, fixprim, fixdual):
@@ -75,12 +85,12 @@ def primcons_rule(model, k, i):
model = get_model(True, i, 1)
results = opt.solve(model)
if results.solution[0].objective['ydiff'].value != 0:
- print "ERROR: nonzero difference i=%d ydiff=%f" % (i, results.solution[0].objective['ydiff'].value)
+ print("ERROR: nonzero difference i=%d ydiff=%f" % (i, results.solution[0].objective['ydiff'].value))
for i in range(1,8):
model = get_model(False, 1, i)
results = opt.solve(model)
if results.solution[0].objective['xdiff'].value != 0:
- print "ERROR: nonzero difference i=%d xdiff=%f" % (i, results.solution[0].objective['xdiff'].value)
+ print("ERROR: nonzero difference i=%d xdiff=%f" % (i, results.solution[0].objective['xdiff'].value))
-print "SUCCESS!"
+print("SUCCESS!")
diff --git a/pyomo/solvers/tests/core/problems/mip_constant1a.py b/pyomo/solvers/tests/core/problems/mip_constant1a.py
index 04cdb7263f8..0aeea0a523f 100644
--- a/pyomo/solvers/tests/core/problems/mip_constant1a.py
+++ b/pyomo/solvers/tests/core/problems/mip_constant1a.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, Integers
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/mip_infeasible1a.py b/pyomo/solvers/tests/core/problems/mip_infeasible1a.py
index 6752c015c2d..9c60342f4e5 100644
--- a/pyomo/solvers/tests/core/problems/mip_infeasible1a.py
+++ b/pyomo/solvers/tests/core/problems/mip_infeasible1a.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, Binary
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/mip_unbounded1a.py b/pyomo/solvers/tests/core/problems/mip_unbounded1a.py
index 153bdf2dfec..aa65356917d 100644
--- a/pyomo/solvers/tests/core/problems/mip_unbounded1a.py
+++ b/pyomo/solvers/tests/core/problems/mip_unbounded1a.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective, Integers
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/mip_unique1.py b/pyomo/solvers/tests/core/problems/mip_unique1.py
index 5391770e190..37bd0a1a922 100644
--- a/pyomo/solvers/tests/core/problems/mip_unique1.py
+++ b/pyomo/solvers/tests/core/problems/mip_unique1.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, Binary
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/multidimen_sos1.py b/pyomo/solvers/tests/core/problems/multidimen_sos1.py
index 95f6c8cf6a9..0798e13314f 100644
--- a/pyomo/solvers/tests/core/problems/multidimen_sos1.py
+++ b/pyomo/solvers/tests/core/problems/multidimen_sos1.py
@@ -1,4 +1,16 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Set, Var, Objective, Constraint, NonNegativeReals, SOSConstraint, maximize, sum_product
+
+from six.moves import xrange
INDEX_SET1 = [1,2]
INDEX_SET2 = [1,2,3]
diff --git a/pyomo/solvers/tests/core/problems/multidimen_sos2.py b/pyomo/solvers/tests/core/problems/multidimen_sos2.py
index 3014b00e56c..cbe2149baac 100644
--- a/pyomo/solvers/tests/core/problems/multidimen_sos2.py
+++ b/pyomo/solvers/tests/core/problems/multidimen_sos2.py
@@ -1,4 +1,16 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Set, Var, Objective, Constraint, NonNegativeReals, SOSConstraint, maximize, sum_product
+
+from six.moves import xrange
INDEX_SET1 = [1,2]
diff --git a/pyomo/solvers/tests/core/problems/simple1a.py b/pyomo/solvers/tests/core/problems/simple1a.py
index 61c4d0237be..2b16de975fa 100644
--- a/pyomo/solvers/tests/core/problems/simple1a.py
+++ b/pyomo/solvers/tests/core/problems/simple1a.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/simple1b.py b/pyomo/solvers/tests/core/problems/simple1b.py
index 51a36bd7ef1..1fa11526e1d 100644
--- a/pyomo/solvers/tests/core/problems/simple1b.py
+++ b/pyomo/solvers/tests/core/problems/simple1b.py
@@ -1,4 +1,15 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective, maximize
+
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/sos1.py b/pyomo/solvers/tests/core/problems/sos1.py
index fcd2e941756..88234d71f33 100644
--- a/pyomo/solvers/tests/core/problems/sos1.py
+++ b/pyomo/solvers/tests/core/problems/sos1.py
@@ -1,4 +1,16 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Set, Var, Objective, Constraint, NonNegativeReals, SOSConstraint, maximize, sum_product
+
+from six.moves import xrange
INDEX_SET = [1,2]
PIECEWISE_PTS = {1:[1,2,3], 2:[1,2,3]}
diff --git a/pyomo/solvers/tests/core/problems/sos2.py b/pyomo/solvers/tests/core/problems/sos2.py
index df87b5464d8..46efb837eca 100644
--- a/pyomo/solvers/tests/core/problems/sos2.py
+++ b/pyomo/solvers/tests/core/problems/sos2.py
@@ -1,4 +1,16 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Set, Var, Objective, Constraint, NonNegativeReals, SOSConstraint, maximize, sum_product
+
+from six.moves import xrange
INDEX_SET = [1,2]
PIECEWISE_PTS = {1:[1,2,3], 2:[1,2,3]}
diff --git a/pyomo/solvers/tests/core/problems/unbounded1a.py b/pyomo/solvers/tests/core/problems/unbounded1a.py
index 1074e1a1d1f..e94543de633 100644
--- a/pyomo/solvers/tests/core/problems/unbounded1a.py
+++ b/pyomo/solvers/tests/core/problems/unbounded1a.py
@@ -1,4 +1,14 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+from pyomo.core import ConcreteModel, Var, Objective
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/problems/unbounded1b.py b/pyomo/solvers/tests/core/problems/unbounded1b.py
index 15f3a98a899..b01db8d60b2 100644
--- a/pyomo/solvers/tests/core/problems/unbounded1b.py
+++ b/pyomo/solvers/tests/core/problems/unbounded1b.py
@@ -1,4 +1,15 @@
-from pyomo.core import *
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
+
+from pyomo.core import ConcreteModel, Var, Objective, maximize
model = ConcreteModel()
diff --git a/pyomo/solvers/tests/core/solvers.py b/pyomo/solvers/tests/core/solvers.py
index 39fa5e792a9..0c3a1a7f8af 100644
--- a/pyomo/solvers/tests/core/solvers.py
+++ b/pyomo/solvers/tests/core/solvers.py
@@ -1,14 +1,22 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
__all__ = ['test_solvers']
import re
import os
import sys
-import time
import csv
from os.path import abspath, dirname
import logging
-import pprint
+from functools import reduce
from pyutilib.misc import Bunch, Options
import pyutilib.th as unittest
diff --git a/pyomo/solvers/tests/core/test_baselines.py b/pyomo/solvers/tests/core/test_baselines.py
index 662c6f6032c..bec832044dd 100644
--- a/pyomo/solvers/tests/core/test_baselines.py
+++ b/pyomo/solvers/tests/core/test_baselines.py
@@ -1,3 +1,12 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
#
# Tests driven by test_baselines.yml
#
@@ -11,16 +20,13 @@
if __name__ == "__main__":
import os
- import sys
from os.path import abspath, dirname
currdir = dirname(abspath(__file__))+os.sep
- import pyutilib.th as unittest
- import pyutilib.services
- import pyomo.environ
+ from pyutilib.services import TempfileManager
- import pyutilib.autotest
- pyutilib.autotest.create_test_suites(filename=currdir+'test_baselines.yml', _globals=globals())
+ from pyutilib.autotest import create_test_suites
+ create_test_suites(filename=currdir+'test_baselines.yml', _globals=globals())
# GAH: The pyutilib.autotest.create_test_suites function
# does some strange things to the TempfileManager state
@@ -28,7 +34,7 @@
# updated (I grep'ed for TempfileManager inside pyomo.data
# and pyutilib.autotest - nothing). Is this a bug?
def tearDownModule():
- pyutilib.services.TempfileManager.clear_tempfiles()
- pyutilib.services.TempfileManager.tempdir = None
- pyutilib.services.TempfileManager.unique_files()
+ TempfileManager.clear_tempfiles()
+ TempfileManager.tempdir = None
+ TempfileManager.unique_files()
diff --git a/pyomo/solvers/tests/core/test_component_perf.py b/pyomo/solvers/tests/core/test_component_perf.py
index 70220aa65b9..8a4e0af86aa 100644
--- a/pyomo/solvers/tests/core/test_component_perf.py
+++ b/pyomo/solvers/tests/core/test_component_perf.py
@@ -1,4 +1,13 @@
-import gc
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import os
thisdir = os.path.dirname(os.path.abspath(__file__))
diff --git a/pyomo/solvers/tests/core/test_param_perf.py b/pyomo/solvers/tests/core/test_param_perf.py
index 3385f841ad5..3273c365e02 100644
--- a/pyomo/solvers/tests/core/test_param_perf.py
+++ b/pyomo/solvers/tests/core/test_param_perf.py
@@ -1,8 +1,18 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
import os
thisdir = os.path.dirname(os.path.abspath(__file__))
import time
-from pyomo.core import *
+from pyomo.core import ConcreteModel, RangeSet, Set, Param
import pyutilib.th as unittest
_plot_filename = os.path.join(thisdir, "param_performance.pdf")
diff --git a/pyomo/solvers/tests/core/test_perf.py b/pyomo/solvers/tests/core/test_perf.py
index 6dc207b9ac7..5edb6329651 100644
--- a/pyomo/solvers/tests/core/test_perf.py
+++ b/pyomo/solvers/tests/core/test_perf.py
@@ -1,14 +1,23 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
#
# Test the Pyomo command-line interface
#
import os
-import gc
# __file__ fails if script is called in different ways on Windows
# __file__ fails if someone does os.chdir() before
# sys.argv[0] also fails because it doesn't not always contains the path
-from os.path import abspath, dirname, exists, join
+from os.path import abspath, dirname, join
from inspect import getfile, currentframe
currdir = dirname(abspath(getfile(currentframe())))
datadir = os.path.normpath(join(
diff --git a/pyomo/solvers/tests/core/test_solvers.py b/pyomo/solvers/tests/core/test_solvers.py
index e333ea5ae76..100810ac560 100644
--- a/pyomo/solvers/tests/core/test_solvers.py
+++ b/pyomo/solvers/tests/core/test_solvers.py
@@ -1,3 +1,13 @@
+# ___________________________________________________________________________
+#
+# Pyomo: Python Optimization Modeling Objects
+# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
+# Under the terms of Contract DE-NA0003525 with National Technology and
+# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
+# rights in this software.
+# This software is distributed under the 3-clause BSD License.
+# ___________________________________________________________________________
+
#
# Tests driven by test_solvers.yml
#
@@ -7,14 +17,12 @@
if __name__ == "__main__":
import os
- import sys
from os.path import abspath, dirname
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
- import pyutilib.autotest
- #import pyomo.data.core
+ from pyutilib.autotest import create_test_suites
- pyutilib.autotest.create_test_suites(filename=currdir+'test_solvers.yml', _globals=globals())
+ create_test_suites(filename=currdir+'test_solvers.yml', _globals=globals())
unittest.main()
diff --git a/pyomo/solvers/tests/mip/model.py b/pyomo/solvers/tests/mip/model.py
index 7729c312cc8..efd22389ab0 100644
--- a/pyomo/solvers/tests/mip/model.py
+++ b/pyomo/solvers/tests/mip/model.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import AbstractModel, RangeSet, Var, Objective, sum_product
model = AbstractModel()
diff --git a/pyomo/solvers/tests/mip/test_asl.py b/pyomo/solvers/tests/mip/test_asl.py
index 7db7367d2d3..8c4388af86a 100644
--- a/pyomo/solvers/tests/mip/test_asl.py
+++ b/pyomo/solvers/tests/mip/test_asl.py
@@ -14,26 +14,24 @@
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
-import pyutilib.services
-import pyutilib.common
+from pyutilib.services import TempfileManager
from pyomo.core import ConcreteModel
-import pyomo.opt
-from pyomo.opt import ResultsFormat, ProblemFormat
+from pyomo.opt import ResultsFormat, SolverResults, SolverFactory
old_ignore_time = None
old_tempdir = None
def setUpModule():
global old_tempdir
global old_ignore_time
- old_tempdir = pyutilib.services.TempfileManager.tempdir
- old_ignore_time = pyomo.opt.SolverResults.default_print_options.ignore_time
- pyomo.opt.SolverResults.default_print_options.ignore_time = True
- pyutilib.services.TempfileManager.tempdir = currdir
+ old_tempdir = TempfileManager.tempdir
+ old_ignore_time = SolverResults.default_print_options.ignore_time
+ SolverResults.default_print_options.ignore_time = True
+ TempfileManager.tempdir = currdir
def tearDownModule():
- pyutilib.services.TempfileManager.tempdir = old_tempdir
- pyomo.opt.SolverResults.default_print_options.ignore_time = old_ignore_time
+ TempfileManager.tempdir = old_tempdir
+ SolverResults.default_print_options.ignore_time = old_ignore_time
cplexamp_available = False
class mock_all(unittest.TestCase):
@@ -52,18 +50,18 @@ def do_setup(self,flag):
global tmpdir
tmpdir = os.getcwd()
os.chdir(currdir)
- pyutilib.services.TempfileManager.sequential_files(0)
+ TempfileManager.sequential_files(0)
if flag:
if not cplexamp_available:
self.skipTest("The 'cplexamp' command is not available")
- self.asl = pyomo.opt.SolverFactory('asl:cplexamp')
+ self.asl = SolverFactory('asl:cplexamp')
else:
- self.asl = pyomo.opt.SolverFactory('_mock_asl:cplexamp')
+ self.asl = SolverFactory('_mock_asl:cplexamp')
def tearDown(self):
global tmpdir
- pyutilib.services.TempfileManager.clear_tempfiles()
- pyutilib.services.TempfileManager.unique_files()
+ TempfileManager.clear_tempfiles()
+ TempfileManager.unique_files()
os.chdir(tmpdir)
self.asl = None
diff --git a/pyomo/solvers/tests/mip/test_convert.py b/pyomo/solvers/tests/mip/test_convert.py
index ae7547a2c9b..8999a5b7bf9 100644
--- a/pyomo/solvers/tests/mip/test_convert.py
+++ b/pyomo/solvers/tests/mip/test_convert.py
@@ -19,10 +19,11 @@
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
-import pyutilib.services
-import pyutilib.common
+from pyutilib.services import TempfileManager
+from pyutilib.common import ApplicationError
-import pyomo.opt
+from pyomo.opt import ProblemFormat, ConverterError, convert_problem
+from pyomo.common import Executable
def filter(line):
return 'Problem' in line or line.startswith('NAME')
@@ -30,11 +31,11 @@ def filter(line):
old_tempdir = None
def setUpModule():
global old_tempdir
- old_tempdir = pyutilib.services.TempfileManager.tempdir
- pyutilib.services.TempfileManager.tempdir = currdir
+ old_tempdir = TempfileManager.tempdir
+ TempfileManager.tempdir = currdir
def tearDownModule():
- pyutilib.services.TempfileManager.tempdir = old_tempdir
+ TempfileManager.tempdir = old_tempdir
class MockArg(object):
@@ -42,7 +43,7 @@ def __init__(self):
pass
def valid_problem_types(self):
- return [pyomo.opt.ProblemFormat.pyomo]
+ return [ProblemFormat.pyomo]
def write(self,filename="", format=None, solver_capability=None, io_options={}):
return (filename,None)
@@ -50,7 +51,7 @@ def write(self,filename="", format=None, solver_capability=None, io_options={}):
class MockArg2(MockArg):
def valid_problem_types(self):
- return [pyomo.opt.ProblemFormat.nl]
+ return [ProblemFormat.nl]
def write(self,filename="", format=None, solver_capability=None, io_options={}):
OUTPUT=open(filename,"w")
@@ -64,7 +65,7 @@ def write(self,filename="", format=None, solver_capability=None, io_options={}):
class MockArg3(MockArg):
def valid_problem_types(self):
- return [pyomo.opt.ProblemFormat.mod]
+ return [ProblemFormat.mod]
def write(self,filename="", format=None, solver_capability=None, io_options={}):
return (filename,None)
@@ -88,31 +89,31 @@ def setUpClass(cls):
import pyomo.environ
def tearDown(self):
- pyutilib.services.TempfileManager.clear_tempfiles()
+ TempfileManager.clear_tempfiles()
def test_nl_nl1(self):
#""" Convert from NL to NL """
- ans = pyomo.opt.convert_problem( ("test4.nl",), None, [pyomo.opt.ProblemFormat.nl])
+ ans = convert_problem( ("test4.nl",), None, [ProblemFormat.nl])
self.assertEqual(ans[0],("test4.nl",))
def test_nl_nl2(self):
#""" Convert from NL to NL """
- ans = pyomo.opt.convert_problem( ("test4.nl","tmp.nl"), None, [pyomo.opt.ProblemFormat.nl])
+ ans = convert_problem( ("test4.nl","tmp.nl"), None, [ProblemFormat.nl])
self.assertEqual(ans[0],("test4.nl","tmp.nl"))
def test_nl_lp1(self):
#""" Convert from NL to LP """
try:
- ans = pyomo.opt.convert_problem( (currdir+"test4.nl",), None, [pyomo.opt.ProblemFormat.cpxlp])
- except pyutilib.common.ApplicationError:
+ ans = convert_problem( (currdir+"test4.nl",), None, [ProblemFormat.cpxlp])
+ except ApplicationError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("pico_convert").available():
+ if Executable("pico_convert").available():
self.fail("Unexpected ApplicationError - pico_convert is "
"enabled but not available: '%s'" % str(err))
return
- except pyomo.opt.ConverterError:
+ except ConverterError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("pico_convert").available():
+ if Executable("pico_convert").available():
self.fail("Unexpected ConverterError - pico_convert is "
"enabled but not available: '%s'" % str(err))
return
@@ -122,16 +123,16 @@ def test_nl_lp1(self):
def test_mod_lp1(self):
#""" Convert from MOD to LP """
try:
- ans = pyomo.opt.convert_problem( (currdir+"test3.mod",), None, [pyomo.opt.ProblemFormat.cpxlp])
- except pyutilib.common.ApplicationError:
+ ans = convert_problem( (currdir+"test3.mod",), None, [ProblemFormat.cpxlp])
+ except ApplicationError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("glpsol").available():
+ if Executable("glpsol").available():
self.fail("Unexpected ApplicationError - glpsol is "
"enabled but not available: '%s'" % str(err))
return
- except pyomo.opt.ConverterError:
+ except ConverterError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("glpsol").available():
+ if Executable("glpsol").available():
self.fail("Unexpected ConverterError - glpsol is "
"enabled but not available: '%s'" % str(err))
return
@@ -141,16 +142,16 @@ def test_mod_lp1(self):
def test_mod_lp2(self):
#""" Convert from MOD+DAT to LP """
try:
- ans = pyomo.opt.convert_problem( (currdir+"test5.mod",currdir+"test5.dat"), None, [pyomo.opt.ProblemFormat.cpxlp])
- except pyutilib.common.ApplicationError:
+ ans = convert_problem( (currdir+"test5.mod",currdir+"test5.dat"), None, [ProblemFormat.cpxlp])
+ except ApplicationError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("glpsol").available():
+ if Executable("glpsol").available():
self.fail("Unexpected ApplicationError - glpsol is "
"enabled but not available: '%s'" % str(err))
return
- except pyomo.opt.ConverterError:
+ except ConverterError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("glpsol").available():
+ if Executable("glpsol").available():
self.fail("Unexpected ConverterError - glpsol is "
"enabled but not available: '%s'" % str(err))
return
@@ -160,16 +161,16 @@ def test_mod_lp2(self):
def test_mod_nl1(self):
#""" Convert from MOD to NL """
try:
- ans = pyomo.opt.convert_problem( (currdir+"test3.mod",), None, [pyomo.opt.ProblemFormat.nl])
- except pyutilib.common.ApplicationError:
+ ans = convert_problem( (currdir+"test3.mod",), None, [ProblemFormat.nl])
+ except ApplicationError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("ampl").available():
+ if Executable("ampl").available():
self.fail("Unexpected ApplicationError - ampl is "
"enabled but not available: '%s'" % str(err))
return
- except pyomo.opt.ConverterError:
+ except ConverterError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("ampl").available():
+ if Executable("ampl").available():
self.fail("Unexpected ConverterError - ampl is "
"enabled but not available: '%s'" % str(err))
return
@@ -179,16 +180,16 @@ def test_mod_nl1(self):
def test_mod_nl2(self):
#""" Convert from MOD+DAT to NL """
try:
- ans = pyomo.opt.convert_problem( (currdir+"test5.mod",currdir+"test5.dat"), None, [pyomo.opt.ProblemFormat.nl])
- except pyutilib.common.ApplicationError:
+ ans = convert_problem( (currdir+"test5.mod",currdir+"test5.dat"), None, [ProblemFormat.nl])
+ except ApplicationError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("ampl").available():
+ if Executable("ampl").available():
self.fail("Unexpected ApplicationError - ampl is "
"enabled but not available: '%s'" % str(err))
return
- except pyomo.opt.ConverterError:
+ except ConverterError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("ampl").available():
+ if Executable("ampl").available():
self.fail("Unexpected ConverterError - ampl is "
"enabled but not available: '%s'" % str(err))
return
@@ -198,22 +199,22 @@ def test_mod_nl2(self):
def test_mock_lp1(self):
#""" Convert from Pyomo to LP """
arg=MockArg()
- ans = pyomo.opt.convert_problem( (arg,pyomo.opt.ProblemFormat.cpxlp,arg), None, [pyomo.opt.ProblemFormat.cpxlp])
+ ans = convert_problem( (arg, ProblemFormat.cpxlp,arg), None, [ProblemFormat.cpxlp])
self.assertNotEqual(re.match(".*tmp.*pyomo.lp$",ans[0][0]), None)
def test_pyomo_lp1(self):
#""" Convert from Pyomo to LP with file"""
- ans = pyomo.opt.convert_problem( (currdir+'model.py',pyomo.opt.ProblemFormat.cpxlp,), None, [pyomo.opt.ProblemFormat.cpxlp])
+ ans = convert_problem( (currdir+'model.py', ProblemFormat.cpxlp,), None, [ProblemFormat.cpxlp])
self.assertNotEqual(re.match(".*tmp.*pyomo.lp$",ans[0][0]), None)
def test_mock_lp2(self):
#""" Convert from NL to LP """
arg=MockArg2()
try:
- ans = pyomo.opt.convert_problem( (arg,), None, [pyomo.opt.ProblemFormat.cpxlp])
- except pyomo.opt.ConverterError:
+ ans = convert_problem( (arg,), None, [ProblemFormat.cpxlp])
+ except ConverterError:
err = sys.exc_info()[1]
- if not pyomo.common.Executable("pico_convert"):
+ if not Executable("pico_convert"):
return
else:
self.fail("Expected ApplicationError because pico_convert "
@@ -227,10 +228,10 @@ def Xtest_mock_mps1(self):
#""" Convert from Pyomo to MPS """
arg=MockArg4()
try:
- ans = pyomo.opt.convert_problem( (arg,pyomo.opt.ProblemFormat.mps,arg), None, [pyomo.opt.ProblemFormat.mps])
- except pyomo.opt.ConverterError:
+ ans = convert_problem((arg, ProblemFormat.mps,arg), None, [ProblemFormat.mps])
+ except ConverterError:
err = sys.exc_info()[1]
- if not pyomo.common.Executable("pico_convert"):
+ if not Executable("pico_convert"):
return
else:
self.fail("Expected ApplicationError because pico_convert "
@@ -241,10 +242,10 @@ def Xtest_mock_mps1(self):
def test_pyomo_mps1(self):
#""" Convert from Pyomo to MPS with file"""
try:
- ans = pyomo.opt.convert_problem( (currdir+'model.py',pyomo.opt.ProblemFormat.mps,), None, [pyomo.opt.ProblemFormat.mps])
- except pyomo.opt.ConverterError:
+ ans = convert_problem( (currdir+'model.py', ProblemFormat.mps,), None, [ProblemFormat.mps])
+ except ConverterError:
err = sys.exc_info()[1]
- if not pyomo.common.Executable("pico_convert"):
+ if not Executable("pico_convert"):
return
else:
self.fail("Expected ApplicationError because pico_convert "
@@ -254,111 +255,111 @@ def test_pyomo_mps1(self):
def test_mock_nl1(self):
#""" Convert from Pyomo to NL """
- arg=MockArg4()
- ans = pyomo.opt.convert_problem( (arg,pyomo.opt.ProblemFormat.nl,arg), None, [pyomo.opt.ProblemFormat.nl])
+ arg = MockArg4()
+ ans = convert_problem( (arg, ProblemFormat.nl,arg), None, [ProblemFormat.nl])
self.assertNotEqual(re.match(".*tmp.*pyomo.nl$",ans[0][0]), None)
os.remove(ans[0][0])
def test_pyomo_nl1(self):
#""" Convert from Pyomo to NL with file"""
- ans = pyomo.opt.convert_problem( (currdir+'model.py',pyomo.opt.ProblemFormat.nl,), None, [pyomo.opt.ProblemFormat.nl])
+ ans = convert_problem( (currdir+'model.py', ProblemFormat.nl,), None, [ProblemFormat.nl])
self.assertNotEqual(re.match(".*tmp.*pyomo.nl$",ans[0][0]), None)
os.remove(ans[0][0])
def test_error1(self):
#""" No valid problem types """
try:
- pyomo.opt.convert_problem( ("test4.nl","tmp.nl"), pyomo.opt.ProblemFormat.nl, [])
+ convert_problem( ("test4.nl","tmp.nl"), ProblemFormat.nl, [])
self.fail("Expected ConverterError exception")
- except pyomo.opt.ConverterError:
+ except ConverterError:
err = sys.exc_info()[1]
pass
def test_error2(self):
#""" Target problem type is not valid """
try:
- pyomo.opt.convert_problem( ("test4.nl","tmp.nl"), pyomo.opt.ProblemFormat.nl, [pyomo.opt.ProblemFormat.mps])
+ convert_problem( ("test4.nl","tmp.nl"), ProblemFormat.nl, [ProblemFormat.mps])
self.fail("Expected ConverterError exception")
- except pyomo.opt.ConverterError:
+ except ConverterError:
pass
def test_error3(self):
#""" Empty argument list """
try:
- pyomo.opt.convert_problem( (), None, [pyomo.opt.ProblemFormat.mps])
+ convert_problem( (), None, [ProblemFormat.mps])
self.fail("Expected ConverterError exception")
- except pyomo.opt.ConverterError:
+ except ConverterError:
pass
def test_error4(self):
#""" Unknown source type """
try:
- pyomo.opt.convert_problem( ("prob.foo",), None, [pyomo.opt.ProblemFormat.mps])
+ convert_problem( ("prob.foo",), None, [ProblemFormat.mps])
self.fail("Expected ConverterError exception")
- except pyomo.opt.ConverterError:
+ except ConverterError:
pass
def test_error5(self):
#""" Unknown source type """
try:
- pyomo.opt.convert_problem( ("prob.lp",), pyomo.opt.ProblemFormat.nl, [pyomo.opt.ProblemFormat.nl])
+ convert_problem( ("prob.lp",), ProblemFormat.nl, [ProblemFormat.nl])
self.fail("Expected ConverterError exception")
- except pyomo.opt.ConverterError:
+ except ConverterError:
pass
def test_error6(self):
#""" Cannot use pico_convert with more than one file """
try:
- ans = pyomo.opt.convert_problem( (currdir+"test4.nl","foo"), None, [pyomo.opt.ProblemFormat.cpxlp])
+ ans = convert_problem( (currdir+"test4.nl","foo"), None, [ProblemFormat.cpxlp])
self.fail("Expected ConverterError exception")
- except pyomo.opt.ConverterError:
+ except ConverterError:
pass
def test_error8(self):
#""" Error when source file cannot be found """
try:
- ans = pyomo.opt.convert_problem( (currdir+"unknown.nl",), None, [pyomo.opt.ProblemFormat.cpxlp])
+ ans = convert_problem( (currdir+"unknown.nl",), None, [ProblemFormat.cpxlp])
self.fail("Expected ConverterError exception")
- except pyutilib.common.ApplicationError:
+ except ApplicationError:
err = sys.exc_info()[1]
- if not pyomo.common.Executable("pico_convert"):
+ if not Executable("pico_convert"):
self.fail("Expected ApplicationError because pico_convert "
"is not available: '%s'" % str(err))
return
- except pyomo.opt.ConverterError:
+ except ConverterError:
pass
def test_error9(self):
#""" The Opt configuration has not been initialized """
- cmd = pyomo.common.Executable("pico_convert").disable()
+ cmd = Executable("pico_convert").disable()
try:
- ans = pyomo.opt.convert_problem( (currdir+"test4.nl",), None, [pyomo.opt.ProblemFormat.cpxlp])
+ ans = convert_problem( (currdir+"test4.nl",), None, [ProblemFormat.cpxlp])
self.fail("This test didn't fail, but pico_convert should not be defined.")
- except pyomo.opt.ConverterError:
+ except ConverterError:
pass
- cmd = pyomo.common.Executable("pico_convert").rehash()
+ cmd = Executable("pico_convert").rehash()
def test_error10(self):
#""" GLPSOL can only convert file data """
try:
arg = MockArg3()
- ans = pyomo.opt.convert_problem( (arg,pyomo.opt.ProblemFormat.cpxlp,arg), None, [pyomo.opt.ProblemFormat.cpxlp])
+ ans = convert_problem( (arg, ProblemFormat.cpxlp,arg), None, [ProblemFormat.cpxlp])
self.fail("This test didn't fail, but glpsol cannot handle objects.")
- except pyomo.opt.ConverterError:
+ except ConverterError:
pass
def test_error11(self):
#""" Cannot convert MOD that contains data """
try:
- ans = pyomo.opt.convert_problem( (currdir+"test3.mod",currdir+"test5.dat"), None, [pyomo.opt.ProblemFormat.cpxlp])
+ ans = convert_problem( (currdir+"test3.mod",currdir+"test5.dat"), None, [ProblemFormat.cpxlp])
self.fail("Expected ConverterError exception because we provided a MOD file with a 'data;' declaration")
- except pyutilib.common.ApplicationError:
+ except ApplicationError:
err = sys.exc_info()[1]
- if pyomo.common.Executable("glpsol"):
+ if Executable("glpsol"):
self.fail("Expected ApplicationError because glpsol "
"is not available: '%s'" % str(err))
return
- except pyomo.opt.ConverterError:
+ except ConverterError:
pass
if __name__ == "__main__":
diff --git a/pyomo/solvers/tests/mip/test_factory.py b/pyomo/solvers/tests/mip/test_factory.py
index 6a9415b941c..4f757356c44 100644
--- a/pyomo/solvers/tests/mip/test_factory.py
+++ b/pyomo/solvers/tests/mip/test_factory.py
@@ -17,39 +17,41 @@
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
-import pyutilib.services
+from pyutilib.services import TempfileManager
-import pyomo
-import pyomo.opt
+from pyomo.opt import AbstractProblemWriter, AbstractResultsReader, OptSolver, ReaderFactory, SolverFactory, WriterFactory
from pyomo.opt.base.solvers import UnknownSolver
+from pyomo.opt.plugins.sol import ResultsReader_sol
+from pyomo.solvers.plugins.solvers import PICO
+
old_tempdir = None
def setUpModule():
global old_tempdir
- old_tempdir = pyutilib.services.TempfileManager.tempdir
- pyutilib.services.TempfileManager.tempdir = currdir
+ old_tempdir = TempfileManager.tempdir
+ TempfileManager.tempdir = currdir
def tearDownModule():
- pyutilib.services.TempfileManager.tempdir = old_tempdir
+ TempfileManager.tempdir = old_tempdir
-class TestWriter(pyomo.opt.AbstractProblemWriter):
+class TestWriter(AbstractProblemWriter):
def __init__(self, name=None):
- pyomo.opt.AbstractProblemWriter.__init__(self,name)
+ AbstractProblemWriter.__init__(self,name)
-class TestReader(pyomo.opt.AbstractResultsReader):
+class TestReader(AbstractResultsReader):
def __init__(self, name=None):
- pyomo.opt.AbstractResultsReader.__init__(self,name)
+ AbstractResultsReader.__init__(self,name)
-class TestSolver(pyomo.opt.OptSolver):
+class TestSolver(OptSolver):
def __init__(self, **kwds):
kwds['type'] = 'stest_type'
kwds['doc'] = 'TestSolver Documentation'
- pyomo.opt.OptSolver.__init__(self,**kwds)
+ OptSolver.__init__(self,**kwds)
class OptFactoryDebug(unittest.TestCase):
@@ -57,20 +59,19 @@ class OptFactoryDebug(unittest.TestCase):
@classmethod
def setUpClass(cls):
import pyomo.environ
- import pyomo.solvers.plugins
def tearDown(self):
- pyutilib.services.TempfileManager.clear_tempfiles()
- pyomo.opt.ReaderFactory.unregister('rtest3')
- pyomo.opt.ReaderFactory.unregister('stest3')
- pyomo.opt.ReaderFactory.unregister('wtest3')
+ TempfileManager.clear_tempfiles()
+ ReaderFactory.unregister('rtest3')
+ ReaderFactory.unregister('stest3')
+ ReaderFactory.unregister('wtest3')
def test_solver_factory(self):
"""
Testing the pyomo.opt solver factory with MIP solvers
"""
- pyomo.opt.SolverFactory.register('stest3')(TestSolver)
- ans = sorted(pyomo.opt.SolverFactory)
+ SolverFactory.register('stest3')(TestSolver)
+ ans = sorted(SolverFactory)
tmp = ['_mock_asl', '_mock_cbc', '_mock_cplex', '_mock_glpk', '_mock_pico', 'cbc', 'cplex', 'glpk', 'pico', 'stest3', 'asl']
tmp.sort()
self.assertTrue(set(tmp) <= set(ans), msg="Set %s is not a subset of set %s" %(tmp,ans))
@@ -79,30 +80,30 @@ def test_solver_instance(self):
"""
Testing that we get a specific solver instance
"""
- ans = pyomo.opt.SolverFactory("none")
+ ans = SolverFactory("none")
self.assertTrue(isinstance(ans, UnknownSolver))
- ans = pyomo.opt.SolverFactory("_mock_pico")
- self.assertEqual(type(ans), pyomo.solvers.plugins.solvers.PICO.MockPICO)
- ans = pyomo.opt.SolverFactory("_mock_pico", name="mymock")
- self.assertEqual(type(ans), pyomo.solvers.plugins.solvers.PICO.MockPICO)
+ ans = SolverFactory("_mock_pico")
+ self.assertEqual(type(ans), PICO.MockPICO)
+ ans = SolverFactory("_mock_pico", name="mymock")
+ self.assertEqual(type(ans), PICO.MockPICO)
self.assertEqual(ans.name, "mymock")
def test_solver_registration(self):
"""
Testing methods in the solverwriter factory registration process
"""
- pyomo.opt.SolverFactory.unregister('stest3')
- self.assertTrue('stest3' not in pyomo.opt.SolverFactory)
- pyomo.opt.SolverFactory.register('stest3')(TestSolver)
- self.assertTrue('stest3' in pyomo.opt.SolverFactory)
- self.assertTrue('_mock_pico' in pyomo.opt.SolverFactory)
+ SolverFactory.unregister('stest3')
+ self.assertTrue('stest3' not in SolverFactory)
+ SolverFactory.register('stest3')(TestSolver)
+ self.assertTrue('stest3' in SolverFactory)
+ self.assertTrue('_mock_pico' in SolverFactory)
def test_writer_factory(self):
"""
Testing the pyomo.opt writer factory with MIP writers
"""
- pyomo.opt.WriterFactory.register('wtest3')(TestWriter)
- factory = pyomo.opt.WriterFactory
+ WriterFactory.register('wtest3')(TestWriter)
+ factory = WriterFactory
self.assertTrue(set(['wtest3']) <= set(factory))
def test_writer_instance(self):
@@ -112,27 +113,27 @@ def test_writer_instance(self):
Note: this simply provides code coverage right now, but
later it should be adapted to generate a specific writer.
"""
- ans = pyomo.opt.WriterFactory("none")
+ ans = WriterFactory("none")
self.assertEqual(ans, None)
- ans = pyomo.opt.WriterFactory("wtest3")
+ ans = WriterFactory("wtest3")
self.assertNotEqual(ans, None)
def test_writer_registration(self):
"""
Testing methods in the writer factory registration process
"""
- pyomo.opt.WriterFactory.unregister('wtest3')
- self.assertTrue(not 'wtest3' in pyomo.opt.WriterFactory)
- pyomo.opt.WriterFactory.register('wtest3')(TestWriter)
- self.assertTrue('wtest3' in pyomo.opt.WriterFactory)
+ WriterFactory.unregister('wtest3')
+ self.assertTrue(not 'wtest3' in WriterFactory)
+ WriterFactory.register('wtest3')(TestWriter)
+ self.assertTrue('wtest3' in WriterFactory)
def test_reader_factory(self):
"""
Testing the pyomo.opt reader factory
"""
- pyomo.opt.ReaderFactory.register('rtest3')(TestReader)
- ans = pyomo.opt.ReaderFactory
+ ReaderFactory.register('rtest3')(TestReader)
+ ans = ReaderFactory
#self.assertEqual(len(ans),4)
self.assertTrue(set(ans) >= set(["rtest3", "sol","yaml", "json"]))
@@ -140,10 +141,10 @@ def test_reader_instance(self):
"""
Testing that we get a specific reader instance
"""
- ans = pyomo.opt.ReaderFactory("none")
+ ans = ReaderFactory("none")
self.assertEqual(ans, None)
- ans = pyomo.opt.ReaderFactory("sol")
- self.assertEqual(type(ans), pyomo.opt.plugins.sol.ResultsReader_sol)
+ ans = ReaderFactory("sol")
+ self.assertEqual(type(ans), ResultsReader_sol)
#ans = pyomo.opt.ReaderFactory("osrl", "myreader")
#self.assertEqual(type(ans), pyomo.opt.reader.OS.ResultsReader_osrl)
#self.assertEqual(ans.name, "myreader")
@@ -152,10 +153,10 @@ def test_reader_registration(self):
"""
Testing methods in the reader factory registration process
"""
- pyomo.opt.ReaderFactory.unregister('rtest3')
- self.assertTrue(not 'rtest3' in pyomo.opt.ReaderFactory)
- pyomo.opt.ReaderFactory.register('rtest3')(TestReader)
- self.assertTrue('rtest3' in pyomo.opt.ReaderFactory)
+ ReaderFactory.unregister('rtest3')
+ self.assertTrue(not 'rtest3' in ReaderFactory)
+ ReaderFactory.register('rtest3')(TestReader)
+ self.assertTrue('rtest3' in ReaderFactory)
if __name__ == "__main__":
unittest.main()
diff --git a/pyomo/solvers/tests/mip/test_ipopt.py b/pyomo/solvers/tests/mip/test_ipopt.py
index 0b67aa83eea..91655b471de 100644
--- a/pyomo/solvers/tests/mip/test_ipopt.py
+++ b/pyomo/solvers/tests/mip/test_ipopt.py
@@ -16,7 +16,7 @@
import pyutilib.services
import pyomo.opt
-from pyomo.core import *
+from pyomo.core import ConcreteModel, RangeSet, Var, Param, Objective, ConstraintList, value, minimize
old_tempdir = None
def setUpModule():
diff --git a/pyomo/solvers/tests/mip/test_mip.py b/pyomo/solvers/tests/mip/test_mip.py
index 51ca63a34f8..f5991590d8f 100644
--- a/pyomo/solvers/tests/mip/test_mip.py
+++ b/pyomo/solvers/tests/mip/test_mip.py
@@ -16,8 +16,6 @@
currdir = dirname(abspath(__file__))+os.sep
import pyutilib.th as unittest
-import pyutilib.autotest
-#pyutilib.autotest.create_test_suites(filename=currdir+'test_mip.yml', _globals=globals())
if __name__ == "__main__":
unittest.main()
diff --git a/pyomo/solvers/tests/mip/test_scip.py b/pyomo/solvers/tests/mip/test_scip.py
index 71407495f2c..f536a43a15f 100644
--- a/pyomo/solvers/tests/mip/test_scip.py
+++ b/pyomo/solvers/tests/mip/test_scip.py
@@ -13,19 +13,18 @@
currdir = dirname(abspath(__file__))
import pyutilib.th as unittest
-import pyutilib.services
-
-import pyomo.opt
-from pyomo.core import *
+from pyutilib.services import TempfileManager
+from pyomo.opt import SolverFactory
+from pyomo.core import ConcreteModel, Var, Objective, Constraint
old_tempdir = None
def setUpModule():
global old_tempdir
- old_tempdir = pyutilib.services.TempfileManager.tempdir
- pyutilib.services.TempfileManager.tempdir = currdir
+ old_tempdir = TempfileManager.tempdir
+ TempfileManager.tempdir = currdir
def tearDownModule():
- pyutilib.services.TempfileManager.tempdir = old_tempdir
+ TempfileManager.tempdir = old_tempdir
scip_available = False
class Test(unittest.TestCase):
@@ -46,9 +45,9 @@ def do_setup(self):
global tmpdir
tmpdir = os.getcwd()
os.chdir(currdir)
- pyutilib.services.TempfileManager.sequential_files(0)
+ TempfileManager.sequential_files(0)
- self.scip = pyomo.opt.SolverFactory('scip', solver_io='nl')
+ self.scip = SolverFactory('scip', solver_io='nl')
m = self.model = ConcreteModel()
m.v = Var()
@@ -57,8 +56,8 @@ def do_setup(self):
def tearDown(self):
global tmpdir
- pyutilib.services.TempfileManager.clear_tempfiles()
- pyutilib.services.TempfileManager.unique_files()
+ TempfileManager.clear_tempfiles()
+ TempfileManager.unique_files()
os.chdir(tmpdir)
def test_version_scip(self):
diff --git a/pyomo/solvers/tests/models/LP_block.py b/pyomo/solvers/tests/models/LP_block.py
index 527bf44f3f6..535e5d53c7c 100644
--- a/pyomo/solvers/tests/models/LP_block.py
+++ b/pyomo/solvers/tests/models/LP_block.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, Block, NonNegativeReals
+from pyomo.core import ConcreteModel, Param, Var, Objective, Constraint, Block, NonNegativeReals
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/LP_compiled.py b/pyomo/solvers/tests/models/LP_compiled.py
index 88d63666c62..8c6a1b9e886 100644
--- a/pyomo/solvers/tests/models/LP_compiled.py
+++ b/pyomo/solvers/tests/models/LP_compiled.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, RangeSet, ConstraintList
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, RangeSet, ConstraintList
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
from pyomo.repn.beta.matrix import compile_block_linear_constraints
diff --git a/pyomo/solvers/tests/models/LP_constant_objective1.py b/pyomo/solvers/tests/models/LP_constant_objective1.py
index d6a7336020e..7fb0d51e80d 100644
--- a/pyomo/solvers/tests/models/LP_constant_objective1.py
+++ b/pyomo/solvers/tests/models/LP_constant_objective1.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, NonNegativeReals
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/LP_constant_objective2.py b/pyomo/solvers/tests/models/LP_constant_objective2.py
index eab6b5f2b23..32df7145f5c 100644
--- a/pyomo/solvers/tests/models/LP_constant_objective2.py
+++ b/pyomo/solvers/tests/models/LP_constant_objective2.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, NonNegativeReals
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/LP_duals_maximize.py b/pyomo/solvers/tests/models/LP_duals_maximize.py
index 496cc9815c8..da735eec5d9 100644
--- a/pyomo/solvers/tests/models/LP_duals_maximize.py
+++ b/pyomo/solvers/tests/models/LP_duals_maximize.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, RangeSet, maximize, ConstraintList
+from pyomo.core import ConcreteModel, Param, Var, Objective, Constraint, RangeSet, maximize, ConstraintList
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/LP_duals_minimize.py b/pyomo/solvers/tests/models/LP_duals_minimize.py
index 9a6a8d22d09..398830064a5 100644
--- a/pyomo/solvers/tests/models/LP_duals_minimize.py
+++ b/pyomo/solvers/tests/models/LP_duals_minimize.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, RangeSet, ConstraintList
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, RangeSet, ConstraintList
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/LP_inactive_index.py b/pyomo/solvers/tests/models/LP_inactive_index.py
index c6e98575851..dfd52ed381a 100644
--- a/pyomo/solvers/tests/models/LP_inactive_index.py
+++ b/pyomo/solvers/tests/models/LP_inactive_index.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, Set, ConstraintList, Block
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, Set, ConstraintList, Block
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
def inactive_index_LP_obj_rule(model,i):
diff --git a/pyomo/solvers/tests/models/LP_infeasible1.py b/pyomo/solvers/tests/models/LP_infeasible1.py
index 05258d6b59f..6114b94b6db 100644
--- a/pyomo/solvers/tests/models/LP_infeasible1.py
+++ b/pyomo/solvers/tests/models/LP_infeasible1.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals
+from pyomo.core import ConcreteModel, Var, Objective, Constraint
from pyomo.opt import TerminationCondition
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
diff --git a/pyomo/solvers/tests/models/LP_infeasible2.py b/pyomo/solvers/tests/models/LP_infeasible2.py
index fc11f51a1ad..f3f5f78e160 100644
--- a/pyomo/solvers/tests/models/LP_infeasible2.py
+++ b/pyomo/solvers/tests/models/LP_infeasible2.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals, maximize
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, maximize
from pyomo.opt import TerminationCondition
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
diff --git a/pyomo/solvers/tests/models/LP_piecewise.py b/pyomo/solvers/tests/models/LP_piecewise.py
index 545d68e7a48..48a63e146f4 100644
--- a/pyomo/solvers/tests/models/LP_piecewise.py
+++ b/pyomo/solvers/tests/models/LP_piecewise.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, Piecewise
+from pyomo.core import ConcreteModel, Var, Objective, Piecewise
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/LP_trivial_constraints.py b/pyomo/solvers/tests/models/LP_trivial_constraints.py
index 35e0b966127..ac3867aef1b 100644
--- a/pyomo/solvers/tests/models/LP_trivial_constraints.py
+++ b/pyomo/solvers/tests/models/LP_trivial_constraints.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, RealInterval, ConstraintList
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, RealInterval, ConstraintList
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/LP_unbounded.py b/pyomo/solvers/tests/models/LP_unbounded.py
index 33a1e6d1266..8099d469af7 100644
--- a/pyomo/solvers/tests/models/LP_unbounded.py
+++ b/pyomo/solvers/tests/models/LP_unbounded.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals
+from pyomo.core import ConcreteModel, Var, Objective
from pyomo.opt import TerminationCondition
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
diff --git a/pyomo/solvers/tests/models/LP_unique_duals.py b/pyomo/solvers/tests/models/LP_unique_duals.py
index 1fd416f358e..f9248dc41f4 100644
--- a/pyomo/solvers/tests/models/LP_unique_duals.py
+++ b/pyomo/solvers/tests/models/LP_unique_duals.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, RangeSet, ConstraintList, NonNegativeReals, Suffix, summation
+from pyomo.core import ConcreteModel, Param, Var, Objective, Constraint, RangeSet, NonNegativeReals, Suffix, sum_product
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
def c_rule(model, j):
diff --git a/pyomo/solvers/tests/models/LP_unused_vars.py b/pyomo/solvers/tests/models/LP_unused_vars.py
index fe898bba923..040b9874a79 100644
--- a/pyomo/solvers/tests/models/LP_unused_vars.py
+++ b/pyomo/solvers/tests/models/LP_unused_vars.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, Set, ConstraintList, sum_product, Block
+from pyomo.core import ConcreteModel, Var, Objective, Set, ConstraintList, sum_product, Block
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/MILP_discrete_var_bounds.py b/pyomo/solvers/tests/models/MILP_discrete_var_bounds.py
index 1f9095ece98..86c39a11774 100644
--- a/pyomo/solvers/tests/models/MILP_discrete_var_bounds.py
+++ b/pyomo/solvers/tests/models/MILP_discrete_var_bounds.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, Binary, Integers, NonNegativeReals
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, Binary, Integers
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/MILP_infeasible1.py b/pyomo/solvers/tests/models/MILP_infeasible1.py
index f7f7fb1ae90..85699ff2717 100644
--- a/pyomo/solvers/tests/models/MILP_infeasible1.py
+++ b/pyomo/solvers/tests/models/MILP_infeasible1.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, Integers, Binary, NonNegativeReals
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, Binary
from pyomo.opt import TerminationCondition
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
diff --git a/pyomo/solvers/tests/models/MILP_simple.py b/pyomo/solvers/tests/models/MILP_simple.py
index cb49de5b613..fcac9c2c618 100644
--- a/pyomo/solvers/tests/models/MILP_simple.py
+++ b/pyomo/solvers/tests/models/MILP_simple.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, Integers, Binary, NonNegativeReals
+from pyomo.core import ConcreteModel, Param, Var, Objective, Constraint, Binary, NonNegativeReals
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/MILP_unbounded.py b/pyomo/solvers/tests/models/MILP_unbounded.py
index 81a8274da50..832b537b776 100644
--- a/pyomo/solvers/tests/models/MILP_unbounded.py
+++ b/pyomo/solvers/tests/models/MILP_unbounded.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, Integers, Binary, NonNegativeReals, Integers
+from pyomo.core import ConcreteModel, Var, Objective, Integers
from pyomo.opt import TerminationCondition
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
diff --git a/pyomo/solvers/tests/models/MILP_unused_vars.py b/pyomo/solvers/tests/models/MILP_unused_vars.py
index cc23748aa66..d1f3e142253 100644
--- a/pyomo/solvers/tests/models/MILP_unused_vars.py
+++ b/pyomo/solvers/tests/models/MILP_unused_vars.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, ConstraintList, Set, Integers, RangeSet, sum_product, Block
+from pyomo.core import ConcreteModel, Var, Objective, ConstraintList, Set, Integers, RangeSet, sum_product, Block
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/MIQCP_simple.py b/pyomo/solvers/tests/models/MIQCP_simple.py
index d84601a48d0..4443b722e60 100644
--- a/pyomo/solvers/tests/models/MIQCP_simple.py
+++ b/pyomo/solvers/tests/models/MIQCP_simple.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, Binary, maximize
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, Binary, maximize
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/MIQP_simple.py b/pyomo/solvers/tests/models/MIQP_simple.py
index a621ff1ecfc..5d5ac3c2d37 100644
--- a/pyomo/solvers/tests/models/MIQP_simple.py
+++ b/pyomo/solvers/tests/models/MIQP_simple.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals, Binary
+from pyomo.core import ConcreteModel, Param, Var, Objective, Constraint, NonNegativeReals, Binary
from pyomo.opt import TerminationCondition
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
diff --git a/pyomo/solvers/tests/models/QCP_simple.py b/pyomo/solvers/tests/models/QCP_simple.py
index 606352ca449..9da9ddd4fc1 100644
--- a/pyomo/solvers/tests/models/QCP_simple.py
+++ b/pyomo/solvers/tests/models/QCP_simple.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals, maximize, ConstraintList
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, NonNegativeReals, maximize, ConstraintList
from pyomo.opt import TerminationCondition
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
diff --git a/pyomo/solvers/tests/models/QP_constant_objective.py b/pyomo/solvers/tests/models/QP_constant_objective.py
index 94cde97c5f3..0e0a306ef88 100644
--- a/pyomo/solvers/tests/models/QP_constant_objective.py
+++ b/pyomo/solvers/tests/models/QP_constant_objective.py
@@ -8,8 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals
+from pyomo.core import ConcreteModel, Var, Objective, Constraint, NonNegativeReals
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
# NOTE: We could test this problem on solvers that only handle
diff --git a/pyomo/solvers/tests/models/QP_simple.py b/pyomo/solvers/tests/models/QP_simple.py
index 86a783a9504..a9a15d7e540 100644
--- a/pyomo/solvers/tests/models/QP_simple.py
+++ b/pyomo/solvers/tests/models/QP_simple.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals
+from pyomo.core import ConcreteModel, Param, Var, Objective, Constraint, NonNegativeReals
from pyomo.opt import TerminationCondition
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
diff --git a/pyomo/solvers/tests/models/SOS1_simple.py b/pyomo/solvers/tests/models/SOS1_simple.py
index 4921e42950b..c35ddb70b5e 100644
--- a/pyomo/solvers/tests/models/SOS1_simple.py
+++ b/pyomo/solvers/tests/models/SOS1_simple.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, NonNegativeReals, SOSConstraint, sum_product
+from pyomo.core import ConcreteModel, Param, Var, Objective, Constraint, NonNegativeReals, SOSConstraint, sum_product
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/SOS2_simple.py b/pyomo/solvers/tests/models/SOS2_simple.py
index 320c8c71c8e..edee12b9f24 100644
--- a/pyomo/solvers/tests/models/SOS2_simple.py
+++ b/pyomo/solvers/tests/models/SOS2_simple.py
@@ -9,7 +9,7 @@
# ___________________________________________________________________________
import pyomo.kernel as pmo
-from pyomo.core import ConcreteModel, Param, Var, Expression, Objective, Constraint, SOSConstraint, NonNegativeReals, ConstraintList, sum_product
+from pyomo.core import ConcreteModel, Param, Var, Objective, Constraint, SOSConstraint, NonNegativeReals, ConstraintList, sum_product
from pyomo.solvers.tests.models.base import _BaseTestModel, register_model
@register_model
diff --git a/pyomo/solvers/tests/models/base.py b/pyomo/solvers/tests/models/base.py
index b7e25ff0692..0031a0dc8a4 100644
--- a/pyomo/solvers/tests/models/base.py
+++ b/pyomo/solvers/tests/models/base.py
@@ -19,7 +19,6 @@
from pyomo.core import Suffix, Var, Constraint, Objective
from pyomo.opt import ProblemFormat, SolverFactory, TerminationCondition
from pyomo.solvers.plugins.solvers.persistent_solver import PersistentSolver
-from pyomo.solvers.plugins.solvers.direct_solver import DirectSolver
thisDir = dirname(abspath( __file__ ))
@@ -366,7 +365,7 @@ def validate_current_solution(self, **kwds):
"Expected solution to be missing suffix %s"
% suffix_name)
elif not abs(solution[block.name][suffix_name] - \
- suffix.get(block)) < sefl.diff_tol:
+ suffix.get(block)) < self.diff_tol:
return (False,
error_str.format(
block.name,
diff --git a/pyomo/solvers/tests/piecewise_linear/kernel_problems/concave_var.py b/pyomo/solvers/tests/piecewise_linear/kernel_problems/concave_var.py
index 317ba440162..72bb42b5baf 100644
--- a/pyomo/solvers/tests/piecewise_linear/kernel_problems/concave_var.py
+++ b/pyomo/solvers/tests/piecewise_linear/kernel_problems/concave_var.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import pyomo.kernel as pmo
+from pyomo.kernel import block, variable, variable_list, block_list, piecewise, objective, constraint, constraint_list
breakpoints = list(range(-5,0))+list(range(1,5))
values = [-x**2 for x in breakpoints]
@@ -17,31 +17,31 @@ def define_model(**kwds):
sense = kwds.pop("sense")
- m = pmo.block()
+ m = block()
- m.x = pmo.variable_list()
- m.Fx = pmo.variable_list()
- m.piecewise = pmo.block_list()
+ m.x = variable_list()
+ m.Fx = variable_list()
+ m.piecewise = block_list()
for i in range(7):
- m.x.append(pmo.variable(lb=-5, ub=4))
- m.Fx.append(pmo.variable())
+ m.x.append(variable(lb=-5, ub=4))
+ m.Fx.append(variable())
m.piecewise.append(
- pmo.piecewise(breakpoints, values,
+ piecewise(breakpoints, values,
input=m.x[i],
output=m.Fx[i],
**kwds))
- m.obj = pmo.objective(expr=sum(m.Fx),
+ m.obj = objective(expr=sum(m.Fx),
sense=sense)
# fix the answer for testing purposes
- m.set_answer = pmo.constraint_list()
- m.set_answer.append(pmo.constraint(m.x[0] == -5.0))
- m.set_answer.append(pmo.constraint(m.x[1] == -3.0))
- m.set_answer.append(pmo.constraint(m.x[2] == -2.5))
- m.set_answer.append(pmo.constraint(m.x[3] == -1.5))
- m.set_answer.append(pmo.constraint(m.x[4] == 2.0))
- m.set_answer.append(pmo.constraint(m.x[5] == 3.5))
- m.set_answer.append(pmo.constraint(m.x[6] == 4.0))
+ m.set_answer = constraint_list()
+ m.set_answer.append(constraint(m.x[0] == -5.0))
+ m.set_answer.append(constraint(m.x[1] == -3.0))
+ m.set_answer.append(constraint(m.x[2] == -2.5))
+ m.set_answer.append(constraint(m.x[3] == -1.5))
+ m.set_answer.append(constraint(m.x[4] == 2.0))
+ m.set_answer.append(constraint(m.x[5] == 3.5))
+ m.set_answer.append(constraint(m.x[6] == 4.0))
return m
diff --git a/pyomo/solvers/tests/piecewise_linear/kernel_problems/convex_var.py b/pyomo/solvers/tests/piecewise_linear/kernel_problems/convex_var.py
index 3b59078a025..f4192ae945d 100644
--- a/pyomo/solvers/tests/piecewise_linear/kernel_problems/convex_var.py
+++ b/pyomo/solvers/tests/piecewise_linear/kernel_problems/convex_var.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import pyomo.kernel as pmo
+from pyomo.kernel import block, variable, variable_list, block_list, piecewise, objective, constraint, constraint_list
breakpoints = list(range(-5,0))+list(range(1,5))
values = [x**2 for x in breakpoints]
@@ -17,31 +17,31 @@ def define_model(**kwds):
sense = kwds.pop("sense")
- m = pmo.block()
+ m = block()
- m.x = pmo.variable_list()
- m.Fx = pmo.variable_list()
- m.piecewise = pmo.block_list()
+ m.x = variable_list()
+ m.Fx = variable_list()
+ m.piecewise = block_list()
for i in range(7):
- m.x.append(pmo.variable(lb=-5, ub=4))
- m.Fx.append(pmo.variable())
+ m.x.append(variable(lb=-5, ub=4))
+ m.Fx.append(variable())
m.piecewise.append(
- pmo.piecewise(breakpoints, values,
+ piecewise(breakpoints, values,
input=m.x[i],
output=m.Fx[i],
**kwds))
- m.obj = pmo.objective(expr=sum(m.Fx),
+ m.obj = objective(expr=sum(m.Fx),
sense=sense)
# fix the answer for testing purposes
- m.set_answer = pmo.constraint_list()
- m.set_answer.append(pmo.constraint(m.x[0] == -5.0))
- m.set_answer.append(pmo.constraint(m.x[1] == -3.0))
- m.set_answer.append(pmo.constraint(m.x[2] == -2.5))
- m.set_answer.append(pmo.constraint(m.x[3] == -1.5))
- m.set_answer.append(pmo.constraint(m.x[4] == 2.0))
- m.set_answer.append(pmo.constraint(m.x[5] == 3.5))
- m.set_answer.append(pmo.constraint(m.x[6] == 4.0))
+ m.set_answer = constraint_list()
+ m.set_answer.append(constraint(m.x[0] == -5.0))
+ m.set_answer.append(constraint(m.x[1] == -3.0))
+ m.set_answer.append(constraint(m.x[2] == -2.5))
+ m.set_answer.append(constraint(m.x[3] == -1.5))
+ m.set_answer.append(constraint(m.x[4] == 2.0))
+ m.set_answer.append(constraint(m.x[5] == 3.5))
+ m.set_answer.append(constraint(m.x[6] == 4.0))
return m
diff --git a/pyomo/solvers/tests/piecewise_linear/kernel_problems/piecewise_var.py b/pyomo/solvers/tests/piecewise_linear/kernel_problems/piecewise_var.py
index 2df219a1849..0e319fdc783 100644
--- a/pyomo/solvers/tests/piecewise_linear/kernel_problems/piecewise_var.py
+++ b/pyomo/solvers/tests/piecewise_linear/kernel_problems/piecewise_var.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import pyomo.kernel as pmo
+from pyomo.kernel import block, variable, variable_list, block_list, piecewise, objective, constraint, constraint_list
breakpoints = [0,1,3,5,6]
values = [0,2,3,-3,-1]
@@ -17,28 +17,28 @@ def define_model(**kwds):
sense = kwds.pop("sense")
- m = pmo.block()
+ m = block()
- m.x = pmo.variable_list()
- m.Fx = pmo.variable_list()
- m.piecewise = pmo.block_list()
+ m.x = variable_list()
+ m.Fx = variable_list()
+ m.piecewise = block_list()
for i in range(4):
- m.x.append(pmo.variable(lb=0, ub=6))
- m.Fx.append(pmo.variable())
+ m.x.append(variable(lb=0, ub=6))
+ m.Fx.append(variable())
m.piecewise.append(
- pmo.piecewise(breakpoints, values,
+ piecewise(breakpoints, values,
input=m.x[i],
output=m.Fx[i],
**kwds))
- m.obj = pmo.objective(expr=sum(m.Fx),
+ m.obj = objective(expr=sum(m.Fx),
sense=sense)
# fix the answer for testing purposes
- m.set_answer = pmo.constraint_list()
- m.set_answer.append(pmo.constraint(m.x[0] == 0.0))
- m.set_answer.append(pmo.constraint(m.x[1] == 3.0))
- m.set_answer.append(pmo.constraint(m.x[2] == 5.5))
- m.set_answer.append(pmo.constraint(m.x[3] == 6.0))
+ m.set_answer = constraint_list()
+ m.set_answer.append(constraint(m.x[0] == 0.0))
+ m.set_answer.append(constraint(m.x[1] == 3.0))
+ m.set_answer.append(constraint(m.x[2] == 5.5))
+ m.set_answer.append(constraint(m.x[3] == 6.0))
return m
diff --git a/pyomo/solvers/tests/piecewise_linear/kernel_problems/step_var.py b/pyomo/solvers/tests/piecewise_linear/kernel_problems/step_var.py
index 66166a62f20..8ef6b14ed64 100644
--- a/pyomo/solvers/tests/piecewise_linear/kernel_problems/step_var.py
+++ b/pyomo/solvers/tests/piecewise_linear/kernel_problems/step_var.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-import pyomo.kernel as pmo
+from pyomo.kernel import block, variable, variable_list, block_list, piecewise, objective, constraint, constraint_list
breakpoints = [0, 1, 1, 2, 3]
values = [0, 0, 1, 1, 2]
@@ -17,31 +17,31 @@ def define_model(**kwds):
sense = kwds.pop("sense")
- m = pmo.block()
+ m = block()
- m.x = pmo.variable_list()
- m.Fx = pmo.variable_list()
- m.piecewise = pmo.block_list()
+ m.x = variable_list()
+ m.Fx = variable_list()
+ m.piecewise = block_list()
for i in range(4):
- m.x.append(pmo.variable(lb=0, ub=3))
- m.Fx.append(pmo.variable())
+ m.x.append(variable(lb=0, ub=3))
+ m.Fx.append(variable())
m.piecewise.append(
- pmo.piecewise(breakpoints, values,
+ piecewise(breakpoints, values,
input=m.x[i],
output=m.Fx[i],
**kwds))
- m.obj = pmo.objective(expr=sum(m.Fx) + sum(m.x),
+ m.obj = objective(expr=sum(m.Fx) + sum(m.x),
sense=sense)
# fix the answer for testing purposes
- m.set_answer = pmo.constraint_list()
+ m.set_answer = constraint_list()
# Fx1 should solve to 0
- m.set_answer.append(pmo.constraint(expr= m.x[0] == 0.5))
- m.set_answer.append(pmo.constraint(expr= m.x[1] == 1.0))
- m.set_answer.append(pmo.constraint(expr= m.Fx[1] == 0.5))
+ m.set_answer.append(constraint(expr= m.x[0] == 0.5))
+ m.set_answer.append(constraint(expr= m.x[1] == 1.0))
+ m.set_answer.append(constraint(expr= m.Fx[1] == 0.5))
# Fx[2] should solve to 1
- m.set_answer.append(pmo.constraint(expr= m.x[2] == 1.5))
+ m.set_answer.append(constraint(expr= m.x[2] == 1.5))
# Fx[3] should solve to 1.5
- m.set_answer.append(pmo.constraint(expr= m.x[3] == 2.5))
+ m.set_answer.append(constraint(expr= m.x[3] == 2.5))
return m
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/concave_multi_vararray1.py b/pyomo/solvers/tests/piecewise_linear/problems/concave_multi_vararray1.py
index f6ffb43b434..7ec3e4f1782 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/concave_multi_vararray1.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/concave_multi_vararray1.py
@@ -19,7 +19,7 @@
\ -7x+12, 3 <= x <= 4
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Param, Piecewise, Constraint, maximize, sum_product
INDEX_SET1 = range(1,8) # There will be two copies of this function
INDEX_SET2 = range(0,2)
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/concave_multi_vararray2.py b/pyomo/solvers/tests/piecewise_linear/problems/concave_multi_vararray2.py
index 070eddd6d68..8244a55968d 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/concave_multi_vararray2.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/concave_multi_vararray2.py
@@ -19,7 +19,8 @@
\ -7x+12, 3 <= x <= 4
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Param, Piecewise, Constraint, maximize, sum_product
+
INDEX_SET = [(t1,t2) for t1 in range(1,8) for t2 in range(0,2)]
DOMAIN_PTS = dict([(t,[float(i) for i in (list(range(-5,0))+list(range(1,5)))]) for t in INDEX_SET])
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/concave_var.py b/pyomo/solvers/tests/piecewise_linear/problems/concave_var.py
index 78500e31af7..0ebdd54ba79 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/concave_var.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/concave_var.py
@@ -19,7 +19,7 @@
\ -7x+12, 3 <= x <= 4
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Piecewise, Constraint, maximize
DOMAIN_PTS = [float(i) for i in (list(range(-5,0))+list(range(1,5)))]
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/concave_vararray.py b/pyomo/solvers/tests/piecewise_linear/problems/concave_vararray.py
index 25441bd4013..36cf2f4fa2b 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/concave_vararray.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/concave_vararray.py
@@ -19,7 +19,7 @@
\ -7x+12, 3 <= x <= 4
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Param, Piecewise, Constraint, maximize, sum_product
INDEX_SET = range(1,8) # There will be two copies of this function
DOMAIN_PTS = dict([(t,[float(i) for i in (list(range(-5,0))+list(range(1,5)))]) for t in INDEX_SET])
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/convex_multi_vararray1.py b/pyomo/solvers/tests/piecewise_linear/problems/convex_multi_vararray1.py
index c3f2465c9f6..6e3c921b85e 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/convex_multi_vararray1.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/convex_multi_vararray1.py
@@ -20,7 +20,7 @@
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Param, Piecewise, Constraint, maximize, sum_product
INDEX_SET1 = range(1,8)
INDEX_SET2 = range(0,2)
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/convex_multi_vararray2.py b/pyomo/solvers/tests/piecewise_linear/problems/convex_multi_vararray2.py
index 170ec987a03..a2f8b5f98fe 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/convex_multi_vararray2.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/convex_multi_vararray2.py
@@ -20,7 +20,7 @@
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Param, Piecewise, Constraint, maximize, sum_product
INDEX_SET = [(t1,t2) for t1 in range(1,8) for t2 in range(0,2)]
DOMAIN_PTS = dict([(t,[float(i) for i in (list(range(-5,0))+list(range(1,5)))]) for t in INDEX_SET])
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/convex_var.py b/pyomo/solvers/tests/piecewise_linear/problems/convex_var.py
index 2add715f2bc..a82e9e7f00c 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/convex_var.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/convex_var.py
@@ -20,7 +20,7 @@
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Piecewise, Constraint, maximize
DOMAIN_PTS = [float(i) for i in (list(range(-5,0))+list(range(1,5)))]
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/convex_vararray.py b/pyomo/solvers/tests/piecewise_linear/problems/convex_vararray.py
index 3a9813d0c76..29af01767fe 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/convex_vararray.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/convex_vararray.py
@@ -20,7 +20,7 @@
"""
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Param, Piecewise, Constraint, Objective, sum_product, maximize
INDEX_SET = range(1,8) # There will be two copies of this function
DOMAIN_PTS = dict([(t,[float(i) for i in (list(range(-5,0))+list(range(1,5)))]) for t in INDEX_SET])
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/piecewise_multi_vararray.py b/pyomo/solvers/tests/piecewise_linear/problems/piecewise_multi_vararray.py
index b6ef0b30ad6..150e74bfe1d 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/piecewise_multi_vararray.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/piecewise_multi_vararray.py
@@ -15,7 +15,7 @@
\ 2x-13 , 5 <= x <= 6
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Param, Piecewise, Constraint, maximize, sum_product
INDEX_SET1 = ['1','2','3','40'] # There will be two copies of this function
INDEX_SET2 = [(t1,t2) for t1 in range(1,4) for t2 in range(1,5)]
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/piecewise_var.py b/pyomo/solvers/tests/piecewise_linear/problems/piecewise_var.py
index b27ff0c5741..f9b91a7242d 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/piecewise_var.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/piecewise_var.py
@@ -15,7 +15,7 @@
\ 2x-13 , 5 <= x <= 6
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Param, Piecewise, Constraint, maximize
DOMAIN_PTS = [float(i) for i in [0,1,3,5,6]]
RANGE_PTS = {0.0:0.0, 1.0:2.0, 3.0:3.0, 5.0:-3.0, 6.0:-1.0}
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/piecewise_vararray.py b/pyomo/solvers/tests/piecewise_linear/problems/piecewise_vararray.py
index dc74878eba0..4ffe5193c4c 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/piecewise_vararray.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/piecewise_vararray.py
@@ -15,7 +15,7 @@
\ 2x-13 , 5 <= x <= 6
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Param, Piecewise, Constraint, maximize, sum_product
INDEX_SET = [1,2,3,4] # There will be two copies of this function
DOMAIN_PTS = dict([(t,[float(i) for i in [0,1,3,5,6]]) for t in INDEX_SET])
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/step_var.py b/pyomo/solvers/tests/piecewise_linear/problems/step_var.py
index 133ca61abf3..288b9ca0ca5 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/step_var.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/step_var.py
@@ -16,7 +16,7 @@
\ x-1 , 2 < x <= 3
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Param, Piecewise, Constraint, maximize
DOMAIN_PTS = [0, 1, 1, 2, 3]
F = [0, 0, 1, 1, 2]
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/step_vararray.py b/pyomo/solvers/tests/piecewise_linear/problems/step_vararray.py
index ed4c81f8248..9437923d934 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/step_vararray.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/step_vararray.py
@@ -16,7 +16,7 @@
\ x-1 , 2 < x <= 3
"""
-from pyomo.environ import *
+from pyomo.core import ConcreteModel, Var, Objective, Piecewise, Constraint, maximize, sum_product
INDEX = [1,2,3,4]
DOMAIN_PTS = [0, 1, 1, 2, 3]
diff --git a/pyomo/solvers/tests/piecewise_linear/problems/tester.py b/pyomo/solvers/tests/piecewise_linear/problems/tester.py
index 2008690b929..1e2dcfabbcd 100644
--- a/pyomo/solvers/tests/piecewise_linear/problems/tester.py
+++ b/pyomo/solvers/tests/piecewise_linear/problems/tester.py
@@ -8,7 +8,7 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
-from pyomo.environ import *
+from pyomo.environ import Var, maximize, value
from pyomo.opt import SolverFactory
from six import itervalues
diff --git a/pyomo/solvers/tests/piecewise_linear/test_piecewise_linear_kernel.py b/pyomo/solvers/tests/piecewise_linear/test_piecewise_linear_kernel.py
index 33bf531c4dd..2f7170e6d7f 100644
--- a/pyomo/solvers/tests/piecewise_linear/test_piecewise_linear_kernel.py
+++ b/pyomo/solvers/tests/piecewise_linear/test_piecewise_linear_kernel.py
@@ -14,9 +14,9 @@
thisDir = dirname( abspath(__file__) )
import pyutilib.th as unittest
-import pyutilib.misc
+from pyutilib.misc import import_file
-import pyomo.kernel as pmo
+from pyomo.kernel import SolverFactory, variable, maximize, minimize
from pyomo.solvers.tests.solvers import test_solver_cases
problems = ['convex_var',
@@ -43,19 +43,19 @@ def testMethod(obj):
obj.skipTest("Solver %s (interface=%s) is not available"
% (solver, writer))
- m = pyutilib.misc.import_file(os.path.join(thisDir,
+ m = import_file(os.path.join(thisDir,
'kernel_problems',
problem),
clear_cache=True)
model = m.define_model(**kwds)
- opt = pmo.SolverFactory(solver, solver_io=writer)
+ opt = SolverFactory(solver, solver_io=writer)
results = opt.solve(model)
# non-recursive
new_results = ((var.name, var.value)
- for var in model.components(ctype=pmo.variable.ctype,
+ for var in model.components(ctype=variable.ctype,
active=True,
descend_into=False))
baseline_results = getattr(obj,problem+'_results')
@@ -79,18 +79,18 @@ def assignTests(cls, problem_list):
for AUX in aux_list:
for REPN in ['sos2','mc','inc','cc','dcc','dlog','log']:
for BOUND_TYPE in ['lb','ub','eq']:
- for SENSE in [pmo.maximize,pmo.minimize]:
- if not( ((BOUND_TYPE == 'lb') and (SENSE == pmo.maximize)) or \
- ((BOUND_TYPE == 'ub') and (SENSE == pmo.minimize)) or \
+ for SENSE in [maximize, minimize]:
+ if not( ((BOUND_TYPE == 'lb') and (SENSE == maximize)) or \
+ ((BOUND_TYPE == 'ub') and (SENSE == minimize)) or \
((REPN == 'mc') and ('step' in PROBLEM)) ):
kwds = {}
kwds['sense'] = SENSE
kwds['repn'] = REPN
kwds['bound'] = BOUND_TYPE
- if SENSE == pmo.maximize:
+ if SENSE == maximize:
attrName = "test_{0}_{1}_{2}_{3}_{4}_{5}".format(PROBLEM,REPN,BOUND_TYPE,'maximize',solver,writer)
else:
- assert SENSE == pmo.minimize
+ assert SENSE == minimize
attrName = "test_{0}_{1}_{2}_{3}_{4}_{5}".format(PROBLEM,REPN,BOUND_TYPE,'minimize',solver,writer)
assert len(AUX) == 1
kwds.update(AUX)
diff --git a/pyomo/solvers/tests/solvers.py b/pyomo/solvers/tests/solvers.py
index 17792895aff..5534d452387 100644
--- a/pyomo/solvers/tests/solvers.py
+++ b/pyomo/solvers/tests/solvers.py
@@ -10,7 +10,6 @@
__all__ = ['test_solver_cases', 'available_solvers']
-import os
import six
import logging
diff --git a/pyomo/solvers/tests/testcases.py b/pyomo/solvers/tests/testcases.py
index f2307c95ace..c12a880542d 100644
--- a/pyomo/solvers/tests/testcases.py
+++ b/pyomo/solvers/tests/testcases.py
@@ -17,7 +17,6 @@
from pyomo.opt import TerminationCondition
from pyomo.solvers.tests.models.base import test_models
from pyomo.solvers.tests.solvers import test_solver_cases
-import pyomo.kernel
from pyomo.core.kernel.block import IBlock
# For expected failures that appear in all known version
diff --git a/pyomo/util/tests/test_check_units.py b/pyomo/util/tests/test_check_units.py
index f9832bfc0b8..dd91ffb2741 100644
--- a/pyomo/util/tests/test_check_units.py
+++ b/pyomo/util/tests/test_check_units.py
@@ -12,10 +12,9 @@
#
import pyutilib.th as unittest
-from pyomo.environ import *
+from pyomo.environ import ConcreteModel, Var, Param, Set, Constraint, Objective, Expression, Suffix, RangeSet, ExternalFunction, units, maximize, sin, cos
from pyomo.network import Port, Arc
from pyomo.dae import ContinuousSet, DerivativeVar
-from pyomo.mpec import Complementarity, complements
from pyomo.gdp import Disjunct, Disjunction
from pyomo.core.base.units_container import (
pint_available, UnitsError,
diff --git a/pyomo/util/tests/test_components.py b/pyomo/util/tests/test_components.py
index a133e0c841d..c453fb0e569 100644
--- a/pyomo/util/tests/test_components.py
+++ b/pyomo/util/tests/test_components.py
@@ -7,31 +7,32 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
+
from six.moves import zip_longest
import pyutilib.th as unittest
-import pyomo.environ as pe
+import pyomo.environ as pyo
import pyomo.kernel as pmo
from pyomo.util.components import iter_component, rename_components
class TestUtilComponents(unittest.TestCase):
def test_rename_components(self):
- model = pe.ConcreteModel()
- model.x = pe.Var([1, 2, 3], bounds=(-10, 10), initialize=5.0)
- model.z = pe.Var(bounds=(10, 20))
- model.obj = pe.Objective(expr=model.z + model.x[1])
+ model = pyo.ConcreteModel()
+ model.x = pyo.Var([1, 2, 3], bounds=(-10, 10), initialize=5.0)
+ model.z = pyo.Var(bounds=(10, 20))
+ model.obj = pyo.Objective(expr=model.z + model.x[1])
def con_rule(m, i):
return m.x[i] + m.z == i
- model.con = pe.Constraint([1, 2, 3], rule=con_rule)
- model.zcon = pe.Constraint(expr=model.z >= model.x[2])
- model.b = pe.Block()
- model.b.bx = pe.Var([1,2,3], initialize=42)
- model.b.bz = pe.Var(initialize=42)
+ model.con = pyo.Constraint([1, 2, 3], rule=con_rule)
+ model.zcon = pyo.Constraint(expr=model.z >= model.x[2])
+ model.b = pyo.Block()
+ model.b.bx = pyo.Var([1,2,3], initialize=42)
+ model.b.bz = pyo.Var(initialize=42)
- c_list = list(model.component_objects(ctype=[pe.Var,pe.Constraint,pe.Objective]))
+ c_list = list(model.component_objects(ctype=[pyo.Var,pyo.Constraint,pyo.Objective]))
name_map = rename_components(model=model,
component_list=c_list,
prefix='scaled_')
@@ -54,15 +55,15 @@ def assertSameComponents(self, obj, other_obj):
self.assertEqual(id(i), id(j))
def test_iter_component_base(self):
- model = pe.ConcreteModel()
- model.x = pe.Var([1, 2, 3], initialize=0)
- model.z = pe.Var(initialize=0)
+ model = pyo.ConcreteModel()
+ model.x = pyo.Var([1, 2, 3], initialize=0)
+ model.z = pyo.Var(initialize=0)
def con_rule(m, i):
return m.x[i] + m.z == i
- model.con = pe.Constraint([1, 2, 3], rule=con_rule)
- model.zcon = pe.Constraint(expr=model.z >= model.x[2])
+ model.con = pyo.Constraint([1, 2, 3], rule=con_rule)
+ model.zcon = pyo.Constraint(expr=model.z >= model.x[2])
self.assertSameComponents(list(iter_component(model.x)), list(model.x.values()))
self.assertSameComponents(list(iter_component(model.z)), [model.z[None]])
diff --git a/pyomo/version/info.py b/pyomo/version/info.py
index 4544123c205..63ada308734 100644
--- a/pyomo/version/info.py
+++ b/pyomo/version/info.py
@@ -25,7 +25,7 @@
# master and needs a hard reference to "suitably new" development.
major=5
minor=7
-micro=1
+micro=2
releaselevel='invalid'
#releaselevel='final'
serial=0