Skip to content

Commit 3a083c3

Browse files
authored
Merge branch 'main' into pyomonlp-scaling
2 parents 946a42d + f46da7f commit 3a083c3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3565
-705
lines changed

.github/workflows/test_branches.yml

+1-7
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ jobs:
519519
$BARON_DIR = "${env:TPL_DIR}/baron"
520520
echo "$BARON_DIR" | `
521521
Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
522-
$URL = "https://www.minlp.com/downloads/xecs/baron/current/"
522+
$URL = "https://minlp.com/downloads/xecs/baron/current/"
523523
if ( "${{matrix.TARGET}}" -eq "win" ) {
524524
$INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.exe"
525525
$URL += "baron-win64.exe"
@@ -855,9 +855,6 @@ jobs:
855855
token: ${{ secrets.PYOMO_CODECOV_TOKEN }}
856856
name: ${{ matrix.TARGET }}
857857
flags: ${{ matrix.TARGET }}
858-
# downgrading after v0.7.0 broke tokenless upload
859-
# see codecov/codecov-action#1487
860-
version: v0.6.0
861858
fail_ci_if_error: true
862859

863860
- name: Upload other coverage reports
@@ -870,7 +867,4 @@ jobs:
870867
token: ${{ secrets.PYOMO_CODECOV_TOKEN }}
871868
name: ${{ matrix.TARGET }}/other
872869
flags: ${{ matrix.TARGET }},other
873-
# downgrading after v0.7.0 broke tokenless upload
874-
# see codecov/codecov-action#1487
875-
version: v0.6.0
876870
fail_ci_if_error: true

.github/workflows/test_pr_and_main.yml

+4-9
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ jobs:
6868
verbose: true
6969
# How many times to retry a failed request (defaults to 1)
7070
retry_count: 3
71-
# Exclude Jenkins because it's behind a firewall; ignore RTD because
72-
# a magically-generated string is triggering a failure
71+
# Exclude:
72+
# - Jenkins because it's behind a firewall
73+
# - RTD because a magically-generated string triggers failures
7374
exclude_urls: https://pyomo-jenkins.sandia.gov/,https://pyomo.readthedocs.io/en/%s/errors.html
7475

7576

@@ -561,7 +562,7 @@ jobs:
561562
$BARON_DIR = "${env:TPL_DIR}/baron"
562563
echo "$BARON_DIR" | `
563564
Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
564-
$URL = "https://www.minlp.com/downloads/xecs/baron/current/"
565+
$URL = "https://minlp.com/downloads/xecs/baron/current/"
565566
if ( "${{matrix.TARGET}}" -eq "win" ) {
566567
$INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.exe"
567568
$URL += "baron-win64.exe"
@@ -899,9 +900,6 @@ jobs:
899900
token: ${{ secrets.PYOMO_CODECOV_TOKEN }}
900901
name: ${{ matrix.TARGET }}
901902
flags: ${{ matrix.TARGET }}
902-
# downgrading after v0.7.0 broke tokenless upload
903-
# see codecov/codecov-action#1487
904-
version: v0.6.0
905903
fail_ci_if_error: true
906904

907905
- name: Upload other coverage reports
@@ -914,7 +912,4 @@ jobs:
914912
token: ${{ secrets.PYOMO_CODECOV_TOKEN }}
915913
name: ${{ matrix.TARGET }}/other
916914
flags: ${{ matrix.TARGET }},other
917-
# downgrading after v0.7.0 broke tokenless upload
918-
# see codecov/codecov-action#1487
919-
version: v0.6.0
920915
fail_ci_if_error: true

.github/workflows/typos.toml

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ caf = "caf"
3838
WRONLY = "WRONLY"
3939
# Ignore the name Hax
4040
Hax = "Hax"
41+
# Ignore dout (short for dual output in SAS solvers)
42+
dout = "dout"
4143
# Big Sur
4244
Sur = "Sur"
4345
# contrib package named mis and the acronym whence the name comes
@@ -67,4 +69,6 @@ RO = "RO"
6769
EOF = "EOF"
6870
# Ignore lst as shorthand for list
6971
lst = "lst"
72+
# Abbreviation of gamma (used in stochpdegas1_automatic.py)
73+
gam = "gam"
7074
# AS NEEDED: Add More Words Below

.jenkins.sh

+37-13
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
#
2121
# CODECOV_TOKEN: the token to use when uploading results to codecov.io
2222
#
23-
# CODECOV_ARGS: additional arguments to pass to the codecov uploader
24-
# (e.g., to support SSL certificates)
23+
# CODECOV_SOURCE_BRANCH: passed to the 'codecov-cli' command; branch of Pyomo
24+
# (e.g., to enable correct codecov uploads)
25+
#
26+
# CODECOV_REPO_OWNER: passed to the 'codecov-cli' command; owner of repo
27+
# (e.g., to enable correct codecov uploads)
2528
#
2629
# DISABLE_COVERAGE: if nonempty, then coverage analysis is disabled
2730
#
@@ -202,22 +205,43 @@ if test -z "$MODE" -o "$MODE" == test; then
202205
# Note, that the PWD should still be $WORKSPACE/pyomo
203206
#
204207
coverage combine || exit 1
205-
coverage report -i
208+
coverage report -i || exit 1
209+
coverage xml -i || exit 1
206210
export OS=`uname`
207-
if test -z "$CODECOV_TOKEN"; then
208-
coverage xml
209-
else
210-
CODECOV_JOB_NAME=`echo ${JOB_NAME} | sed -r 's/^(.*autotest_)?Pyomo_([^\/]+).*/\2/'`.$BUILD_NUMBER.$python
211+
if test -z "$PYOMO_SOURCE_SHA"; then
212+
PYOMO_SOURCE_SHA=$GIT_COMMIT
213+
fi
214+
if test -n "$CODECOV_TOKEN" -a -n "$PYOMO_SOURCE_SHA"; then
215+
CODECOV_JOB_NAME=$(echo ${JOB_NAME} \
216+
| sed -r 's/^(.*autotest_)?Pyomo_([^\/]+).*/\2/').$BUILD_NUMBER.$python
217+
if test -z "$CODECOV_REPO_OWNER"; then
218+
if test -n "$PYOMO_SOURCE_REPO"; then
219+
CODECOV_REPO_OWNER=$(echo "$PYOMO_SOURCE_REPO" | cut -d '/' -f 4)
220+
elif test -n "$GIT_URL"; then
221+
CODECOV_REPO_OWNER=$(echo "$GIT_URL" | cut -d '/' -f 4)
222+
else
223+
CODECOV_REPO_OWNER=""
224+
fi
225+
fi
226+
if test -z "$CODECOV_SOURCE_BRANCH"; then
227+
CODECOV_SOURCE_BRANCH=$(git branch -av --contains "$PYOMO_SOURCE_SHA" \
228+
| grep "${PYOMO_SOURCE_SHA:0:7}" | grep "/origin/" \
229+
| cut -d '/' -f 3 | cut -d' ' -f 1)
230+
if test -z "$CODECOV_SOURCE_BRANCH"; then
231+
CODECOV_SOURCE_BRANCH=main
232+
fi
233+
fi
211234
i=0
212235
while /bin/true; do
213236
i=$[$i+1]
214237
echo "Uploading coverage to codecov (attempt $i)"
215-
codecov -X gcovcodecov -X gcov -X s3 --no-color \
216-
-t $CODECOV_TOKEN --root `pwd` -e OS,python \
217-
--name $CODECOV_JOB_NAME $CODECOV_ARGS \
218-
| tee .cover.upload
219-
if test $? == 0 -a `grep -i error .cover.upload \
220-
| grep -v branch= | wc -l` -eq 0; then
238+
codecovcli -v upload-process --sha $PYOMO_SOURCE_SHA \
239+
--fail-on-error --git-service github --token $CODECOV_TOKEN \
240+
--slug pyomo/pyomo --file coverage.xml --disable-search \
241+
--name $CODECOV_JOB_NAME \
242+
--branch $CODECOV_REPO_OWNER:$CODECOV_SOURCE_BRANCH \
243+
--env OS,python --network-root-folder `pwd` --plugin noop
244+
if test $? == 0; then
221245
break
222246
elif test $i -ge 4; then
223247
exit 1

.codecov.yml codecov.yml

+15-13
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1+
codecov:
2+
notify:
3+
# GHA: 5, Jenkins: 11
4+
# Accurate as of July 3, 2024
5+
# Potential to change when Python versions change
6+
after_n_builds: 16
7+
wait_for_ci: true
18
coverage:
2-
range: "50...100"
9+
range:
10+
- 50.0
11+
- 100.0
312
status:
13+
patch:
14+
default:
15+
# Force patches to be covered at the level of the codebase
16+
threshold: 0.0
417
project:
518
default:
619
# Allow overall coverage to drop to avoid failures due to code
720
# cleanup or CI unavailability/lag
8-
threshold: 5%
9-
patch:
10-
default:
11-
# Force patches to be covered at the level of the codebase
12-
threshold: 0%
13-
# ci:
14-
# - !ci.appveyor.com
15-
codecov:
16-
notify:
17-
# GHA: 4, Jenkins: 8
18-
after_n_builds: 12 # all
19-
wait_for_ci: yes
21+
threshold: 5.0

doc/OnlineDocs/contributed_packages/gdpopt.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,10 @@ An example that includes the modeling approach may be found below.
9393
Variables:
9494
x : Size=1, Index=None
9595
Key : Lower : Value : Upper : Fixed : Stale : Domain
96-
None : -1.2 : 0.0 : 2 : False : False : Reals
96+
None : -1.2 : 0 : 2 : False : False : Reals
9797
y : Size=1, Index=None
9898
Key : Lower : Value : Upper : Fixed : Stale : Domain
99-
None : -10 : 1.0 : 10 : False : False : Reals
99+
None : -10 : 1 : 10 : False : False : Reals
100100
<BLANKLINE>
101101
Objectives:
102102
objective : Size=1, Index=None, Active=True
@@ -106,7 +106,7 @@ An example that includes the modeling approach may be found below.
106106
Constraints:
107107
c : Size=1
108108
Key : Lower : Body : Upper
109-
None : 1.0 : 1.0 : 1.0
109+
None : 1.0 : 1 : 1.0
110110

111111
.. note::
112112

examples/pyomo/tutorials/set.dat

+3
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ set S[5] := 2 3;
1616

1717
set T[2] := 1 3;
1818
set T[5] := 2 3;
19+
20+
set X[2] := 1;
21+
set X[5] := 2 3;

examples/pyomo/tutorials/set.out

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
23 Set Declarations
1+
24 Set Declarations
22
A : Size=1, Index=None, Ordered=Insertion
33
Key : Dimen : Domain : Size : Members
44
None : 1 : Any : 3 : {1, 2, 3}
@@ -89,5 +89,9 @@
8989
2 : 1 : Any : 5 : {1, 3, 5, 7, 9}
9090
3 : 1 : Any : 5 : {1, 4, 7, 10, 13}
9191
4 : 1 : Any : 5 : {1, 5, 9, 13, 17}
92+
X : Size=2, Index=B, Ordered=Insertion
93+
Key : Dimen : Domain : Size : Members
94+
2 : 1 : S[2] : 1 : {1,}
95+
5 : 1 : S[5] : 2 : {2, 3}
9296

93-
23 Declarations: A B C D E F G H Hsub I J K K_2 L M N O P R S T U V
97+
24 Declarations: A B C D E F G H Hsub I J K K_2 L M N O P R S X T U V

examples/pyomo/tutorials/set.py

+7
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,13 @@ def P_init(model, i, j):
171171
#
172172
model.S = Set(model.B, within=model.A)
173173

174+
#
175+
# Validation of a set array can also be linked to another set array. If so, the
176+
# elements under each index must also be found under the corresponding index in
177+
# the validation set array:
178+
#
179+
model.X = Set(model.B, within=model.S)
180+
174181

175182
#
176183
# Validation of set arrays can also be performed with the _validate_ option.

pyomo/common/config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ class will still create ``c`` instances that only have the single
996996
:py:meth:`generate_documentation()`. The simplest is
997997
:py:meth:`display()`, which prints out the current values of the
998998
configuration object (and if it is a container type, all of it's
999-
children). :py:meth:`generate_yaml_template` is simular to
999+
children). :py:meth:`generate_yaml_template` is similar to
10001000
:py:meth:`display`, but also includes the description fields as
10011001
formatted comments.
10021002

pyomo/common/tests/test_dependencies.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ def test_and_or(self):
209209
_and_or = avail0 & avail1 | avail2
210210
self.assertTrue(_and_or)
211211

212-
# Verify operator prescedence
212+
# Verify operator precedence
213213
_or_and = avail0 | avail2 & avail2
214214
self.assertTrue(_or_and)
215215
_or_and = (avail0 | avail2) & avail2

pyomo/contrib/appsi/base.py

+4-31
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ def add_constraints(self, cons: List[ConstraintData]):
10071007
raise ValueError(
10081008
'constraint {name} has already been added'.format(name=con.name)
10091009
)
1010-
self._active_constraints[con] = (con.lower, con.body, con.upper)
1010+
self._active_constraints[con] = con.expr
10111011
if self.use_extensions and cmodel_available:
10121012
tmp = cmodel.prep_for_repn(con.body, self._expr_types)
10131013
else:
@@ -1363,40 +1363,13 @@ def update(self, timer: HierarchicalTimer = None):
13631363
cons_to_remove_and_add = dict()
13641364
need_to_set_objective = False
13651365
if config.update_constraints:
1366-
cons_to_update = list()
1367-
sos_to_update = list()
13681366
for c in current_cons_dict.keys():
1369-
if c not in new_cons_set:
1370-
cons_to_update.append(c)
1367+
if c not in new_cons_set and c.expr is not self._active_constraints[c]:
1368+
cons_to_remove_and_add[c] = None
1369+
sos_to_update = []
13711370
for c in current_sos_dict.keys():
13721371
if c not in new_sos_set:
13731372
sos_to_update.append(c)
1374-
for c in cons_to_update:
1375-
lower, body, upper = self._active_constraints[c]
1376-
new_lower, new_body, new_upper = c.lower, c.body, c.upper
1377-
if new_body is not body:
1378-
cons_to_remove_and_add[c] = None
1379-
continue
1380-
if new_lower is not lower:
1381-
if (
1382-
type(new_lower) is NumericConstant
1383-
and type(lower) is NumericConstant
1384-
and new_lower.value == lower.value
1385-
):
1386-
pass
1387-
else:
1388-
cons_to_remove_and_add[c] = None
1389-
continue
1390-
if new_upper is not upper:
1391-
if (
1392-
type(new_upper) is NumericConstant
1393-
and type(upper) is NumericConstant
1394-
and new_upper.value == upper.value
1395-
):
1396-
pass
1397-
else:
1398-
cons_to_remove_and_add[c] = None
1399-
continue
14001373
self.remove_sos_constraints(sos_to_update)
14011374
self.add_sos_constraints(sos_to_update)
14021375
timer.stop('cons')

pyomo/contrib/appsi/cmodel/src/fbbt_model.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ void process_fbbt_constraints(FBBTModel *model, PyomoExprTypes &expr_types,
205205
py::handle con_body;
206206

207207
for (py::handle c : cons) {
208-
lower_body_upper = active_constraints[c];
208+
lower_body_upper = c.attr("to_bounded_expression")();
209209
con_lb = lower_body_upper[0];
210210
con_body = lower_body_upper[1];
211211
con_ub = lower_body_upper[2];

pyomo/contrib/appsi/cmodel/src/lp_writer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ void process_lp_constraints(py::list cons, py::object writer) {
289289
py::object nonlinear_expr;
290290
PyomoExprTypes expr_types = PyomoExprTypes();
291291
for (py::handle c : cons) {
292-
lower_body_upper = active_constraints[c];
292+
lower_body_upper = c.attr("to_bounded_expression")();
293293
cname = getSymbol(c, labeler);
294294
repn = generate_standard_repn(
295295
lower_body_upper[1], "compute_values"_a = false, "quadratic"_a = true);

pyomo/contrib/appsi/cmodel/src/nl_writer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ void process_nl_constraints(NLWriter *nl_writer, PyomoExprTypes &expr_types,
527527
py::handle repn_nonlinear_expr;
528528

529529
for (py::handle c : cons) {
530-
lower_body_upper = active_constraints[c];
530+
lower_body_upper = c.attr("to_bounded_expression")();
531531
repn = generate_standard_repn(
532532
lower_body_upper[1], "compute_values"_a = false, "quadratic"_a = false);
533533
_const = appsi_expr_from_pyomo_expr(repn.attr("constant"), var_map,

pyomo/contrib/appsi/solvers/highs.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ def _remove_constraints(self, cons: List[ConstraintData]):
481481
indices_to_remove.append(con_ndx)
482482
self._mutable_helpers.pop(con, None)
483483
self._solver_model.deleteRows(
484-
len(indices_to_remove), np.array(indices_to_remove)
484+
len(indices_to_remove), np.sort(np.array(indices_to_remove))
485485
)
486486
con_ndx = 0
487487
new_con_map = dict()

0 commit comments

Comments
 (0)