diff --git a/.github/workflows/test_branches.yml b/.github/workflows/test_branches.yml index 92c47b2d64b..c1029ff3d7b 100644 --- a/.github/workflows/test_branches.yml +++ b/.github/workflows/test_branches.yml @@ -75,13 +75,19 @@ jobs: other: [""] category: [""] + # win/3.8 conda builds no longer work due to environment not being able + # to resolve. We are skipping it now. + exclude: + - os: windows-latest + python: 3.8 + include: - os: ubuntu-latest python: '3.12' TARGET: linux PYENV: pip - - os: macos-13 + - os: macos-latest python: '3.10' TARGET: osx PYENV: pip @@ -215,6 +221,7 @@ jobs: if: matrix.TARGET == 'win' run: | echo "SETUPTOOLS_USE_DISTUTILS=local" >> $GITHUB_ENV + choco install pkgconfiglite - name: Set up Python ${{ matrix.python }} if: matrix.PYENV == 'pip' @@ -352,6 +359,10 @@ jobs: done echo "" echo "*** Install Pyomo dependencies ***" + # For windows, cannot use newer setuptools because of APPSI compilation issues + if test "${{matrix.TARGET}}" == 'win'; then + CONDA_DEPENDENCIES="$CONDA_DEPENDENCIES setuptools<74.0.0" + fi # Note: this will fail the build if any installation fails (or # possibly if it outputs messages to stderr) conda install --update-deps -q -y $CONDA_DEPENDENCIES diff --git a/.github/workflows/test_pr_and_main.yml b/.github/workflows/test_pr_and_main.yml index 34efa4a029b..33aacaa9e35 100644 --- a/.github/workflows/test_pr_and_main.yml +++ b/.github/workflows/test_pr_and_main.yml @@ -67,7 +67,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-13, windows-latest] + os: [ubuntu-latest, macos-latest, windows-latest] python: [ 3.8, 3.9, '3.10', '3.11', '3.12' ] other: [""] category: [""] @@ -77,12 +77,13 @@ jobs: exclude: - os: windows-latest python: 3.8 + include: - os: ubuntu-latest TARGET: linux PYENV: pip - - os: macos-13 + - os: macos-latest TARGET: osx PYENV: pip @@ -108,14 +109,6 @@ jobs: PYENV: conda PACKAGES: openmpi mpi4py - - os: ubuntu-latest - python: '3.11' - other: /singletest - category: "-m 'neos or importtest'" - skip_doctest: 1 - TARGET: linux - PYENV: pip - - os: ubuntu-latest python: '3.10' other: /cython @@ -132,6 +125,14 @@ jobs: TARGET: win PYENV: pip + - os: ubuntu-latest + python: '3.11' + other: /singletest + category: "-m 'neos or importtest'" + skip_doctest: 1 + TARGET: linux + PYENV: pip + - os: ubuntu-latest python: 3.8 other: /slim @@ -243,6 +244,7 @@ jobs: if: matrix.TARGET == 'win' run: | echo "SETUPTOOLS_USE_DISTUTILS=local" >> $GITHUB_ENV + choco install pkgconfiglite - name: Set up Python ${{ matrix.python }} if: matrix.PYENV == 'pip' @@ -380,6 +382,10 @@ jobs: done echo "" echo "*** Install Pyomo dependencies ***" + # For windows, cannot use newer setuptools because of APPSI compilation issues + if test "${{matrix.TARGET}}" == 'win'; then + CONDA_DEPENDENCIES="$CONDA_DEPENDENCIES setuptools<74.0.0" + fi # Note: this will fail the build if any installation fails (or # possibly if it outputs messages to stderr) conda install --update-deps -q -y $CONDA_DEPENDENCIES diff --git a/examples/pyomobook/gdp-ch/gdp_uc.py b/examples/pyomobook/gdp-ch/gdp_uc.py index 6268bcce068..ff3c554c039 100644 --- a/examples/pyomobook/gdp-ch/gdp_uc.py +++ b/examples/pyomobook/gdp-ch/gdp_uc.py @@ -116,3 +116,9 @@ def obj(m): @model.Constraint(model.GENERATORS) def nontrivial(m, g): return sum(m.Power[g, t] for t in m.TIME) >= len(m.TIME) / 2 * m.MinPower[g] + + +@model.ConstraintList() +def nondegenerate(m): + for i, g in enumerate(m.GENERATORS): + yield m.Power[g, i + 1] == 0 diff --git a/examples/pyomobook/gdp-ch/pyomo.gdp_uc.txt b/examples/pyomobook/gdp-ch/pyomo.gdp_uc.txt index 477336d48ba..f0b5a5c4795 100644 --- a/examples/pyomobook/gdp-ch/pyomo.gdp_uc.txt +++ b/examples/pyomobook/gdp-ch/pyomo.gdp_uc.txt @@ -22,9 +22,9 @@ Problem: Lower bound: 45.0 Upper bound: 45.0 Number of objectives: 1 - Number of constraints: 58 + Number of constraints: 60 Number of variables: 24 - Number of nonzeros: 124 + Number of nonzeros: 126 Sense: minimize # ---------------------------------------------------------- # Solver Information @@ -34,8 +34,8 @@ Solver: Termination condition: optimal Statistics: Branch and bound: - Number of bounded subproblems: 15 - Number of created subproblems: 15 + Number of bounded subproblems: 9 + Number of created subproblems: 9 Error rc: 0 Time: 0.007754325866699219 # ---------------------------------------------------------- @@ -51,24 +51,24 @@ Solution: obj: Value: 45 Variable: - GenOff[g1,2].binary_indicator_var: + GenOff[g1,1].binary_indicator_var: Value: 1 - GenOff[g2,1].binary_indicator_var: + GenOff[g2,2].binary_indicator_var: Value: 1 - GenOn[g1,1].binary_indicator_var: + GenOn[g1,3].binary_indicator_var: Value: 1 - GenOn[g2,3].binary_indicator_var: + GenOn[g2,1].binary_indicator_var: Value: 1 - GenStartup[g1,3].binary_indicator_var: + GenStartup[g1,2].binary_indicator_var: Value: 1 - GenStartup[g2,2].binary_indicator_var: + GenStartup[g2,3].binary_indicator_var: Value: 1 - Power[g1,1]: - Value: 10 - Power[g1,3]: + Power[g1,2]: Value: 5 - Power[g2,2]: + Power[g1,3]: Value: 10 - Power[g2,3]: + Power[g2,1]: Value: 20 + Power[g2,3]: + Value: 10 Constraint: No values diff --git a/pyomo/contrib/fme/tests/test_fourier_motzkin_elimination.py b/pyomo/contrib/fme/tests/test_fourier_motzkin_elimination.py index dc721488f74..961d34a68c7 100644 --- a/pyomo/contrib/fme/tests/test_fourier_motzkin_elimination.py +++ b/pyomo/contrib/fme/tests/test_fourier_motzkin_elimination.py @@ -562,7 +562,7 @@ def test_post_processing(self): fme = TransformationFactory('contrib.fourier_motzkin_elimination') fme.apply_to(m, vars_to_eliminate=disaggregatedVars, do_integer_arithmetic=True) # post-process - fme.post_process_fme_constraints(m, SolverFactory('glpk')) + fme.post_process_fme_constraints(m, SolverFactory('glpk'), tolerance=-1e-6) constraints = m._pyomo_contrib_fme_transformation.projected_constraints self.assertEqual(len(constraints), 11) diff --git a/pyomo/core/kernel/base.py b/pyomo/core/kernel/base.py index d599c76f6a1..0653868e109 100644 --- a/pyomo/core/kernel/base.py +++ b/pyomo/core/kernel/base.py @@ -156,7 +156,7 @@ def getname( Args: fully_qualified (bool): Generate a full name by - iterating through all anscestor containers. + iterating through all ancestor containers. Default is :const:`False`. convert (function): A function that converts a storage key into a string diff --git a/pyomo/core/tests/unit/kernel/test_piecewise.py b/pyomo/core/tests/unit/kernel/test_piecewise.py index 3d9cf66e39c..e376bdce8b3 100644 --- a/pyomo/core/tests/unit/kernel/test_piecewise.py +++ b/pyomo/core/tests/unit/kernel/test_piecewise.py @@ -209,19 +209,17 @@ def test_generate_delaunay(self): vlist.append(variable(lb=0, ub=1)) vlist.append(variable(lb=1, ub=2)) vlist.append(variable(lb=2, ub=3)) - if not (util.numpy_available and util.scipy_available): - with self.assertRaises(ImportError): - util.generate_delaunay(vlist) - else: - tri = util.generate_delaunay(vlist, num=2) - self.assertTrue(isinstance(tri, util.scipy.spatial.Delaunay)) - self.assertEqual(len(tri.simplices), 6) - self.assertEqual(len(tri.points), 8) - - tri = util.generate_delaunay(vlist, num=3) - self.assertTrue(isinstance(tri, util.scipy.spatial.Delaunay)) - self.assertEqual(len(tri.simplices), 62) - self.assertEqual(len(tri.points), 27) + tri = util.generate_delaunay(vlist, num=2) + self.assertTrue(isinstance(tri, util.scipy.spatial.Delaunay)) + self.assertEqual(len(tri.simplices), 6) + self.assertEqual(len(tri.points), 8) + + tri = util.generate_delaunay(vlist, num=3) + self.assertTrue(isinstance(tri, util.scipy.spatial.Delaunay)) + # we got some simplices + self.assertTrue(len(tri.simplices) > 1) + # all the given points are accounted for + self.assertEqual(len(tri.points) + len(tri.coplanar), 27) # # Check cases where not all variables are bounded diff --git a/pyomo/core/tests/unit/test_sets.py b/pyomo/core/tests/unit/test_sets.py index 52c4523eaba..e9f96a417f4 100644 --- a/pyomo/core/tests/unit/test_sets.py +++ b/pyomo/core/tests/unit/test_sets.py @@ -2979,7 +2979,7 @@ def test_initialize_and_clone_from_dict_keys(self): # # While deepcopying a model is generally not supported, this is # an easy way to ensure that this simple model is cleanly - # clonable. + # able to be cloned. ref = """1 Set Declarations INDEX : Size=1, Index=None, Ordered=Insertion Key : Dimen : Domain : Size : Members diff --git a/pyomo/neos/tests/test_neos.py b/pyomo/neos/tests/test_neos.py index 681856781be..f14600fdb84 100644 --- a/pyomo/neos/tests/test_neos.py +++ b/pyomo/neos/tests/test_neos.py @@ -79,9 +79,6 @@ def test_doc(self): doc = pyomo.neos.doc dockeys = set(doc.keys()) - # Octeract interface is disabled, see #3321 - amplsolvers.remove('octeract') - self.assertEqual(amplsolvers, dockeys) # gamssolvers = set(v[0].lower() for v in tmp if v[1]=='GAMS') @@ -152,8 +149,9 @@ def test_minto(self): def test_mosek(self): self._run('mosek') - # [16 Jul 24] Octeract is erroring. We will disable the interface + # [16 Jul 24]: Octeract is erroring. We will disable the interface # (and testing) until we have time to resolve #3321 + # [20 Sep 24]: and appears to have been removed from NEOS # # def test_octeract(self): # self._run('octeract')