Skip to content

Conversation

eminyouskn
Copy link
Contributor

Fixes NA

Summary/Motivation:

This PR introduced a new KNITRO direct solver interface.

Changes proposed in this PR:

Legal Acknowledgement

By contributing to this software project, I have read the contribution guide and agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the BSD license.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

Copy link

codecov bot commented Sep 18, 2025

Codecov Report

❌ Patch coverage is 92.39843% with 58 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.16%. Comparing base (740750d) to head (9e4f8bb).

Files with missing lines Patch % Lines
pyomo/contrib/solver/solvers/knitro/base.py 84.27% 25 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/engine.py 91.92% 23 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/package.py 88.00% 6 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/api.py 85.71% 1 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/direct.py 96.87% 1 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/solution.py 96.66% 1 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/utils.py 99.03% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3707      +/-   ##
==========================================
- Coverage   89.18%   89.16%   -0.03%     
==========================================
  Files         896      906      +10     
  Lines      103725   104488     +763     
==========================================
+ Hits        92508    93166     +658     
- Misses      11217    11322     +105     
Flag Coverage Δ
builders ?
default 85.81% <92.26%> (?)
expensive 35.76% <41.67%> (?)
linux 86.64% <39.73%> (-2.30%) ⬇️
linux_other 86.64% <39.73%> (-0.35%) ⬇️
osx 82.81% <39.73%> (-0.32%) ⬇️
win 84.89% <39.73%> (-0.34%) ⬇️
win_other 84.89% <39.73%> (-0.34%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mrmundt
Copy link
Contributor

mrmundt commented Sep 19, 2025

Hi @eminyouskn - okay, so, the tests are running but a large number of them are failing. Here is part of the stacktrace:

19:55:28 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
19:55:28 pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py:1963: in test_variables_elsewhere
19:55:28     self.assertAlmostEqual(res.incumbent_objective, 1)
19:55:28 E   AssertionError: 1.0000008993019858 != 1 within 7 places (8.993019857683748e-07 difference)
19:55:28 ----------------------------- Captured stdout call -----------------------------
19:55:28 
19:55:28 =======================================
19:55:28 *** NO CHECK MADE FOR LICENSE ***
19:55:28          Artelys Knitro 15.0.0
19:55:28 =======================================
19:55:28 
19:55:28 Knitro using 1 thread.
19:55:28 No start point provided -- Knitro computing one.
19:55:28 
19:55:28 Knitro performing finite-difference gradient computation with 1 thread.
19:55:28 Knitro presolve eliminated 0 variables and 0 constraints.
19:55:28 
19:55:28 concurrent_evals         0
19:55:28 feastol                  1e-06
19:55:28 feastol_abs              0.001
19:55:28 opttol                   1e-06
19:55:28 opttol_abs               0.001
19:55:28 outlev                   6
19:55:28 Knitro changing hessopt to exact (because the problem is an LP).
19:55:28 The problem is identified as an LP.
19:55:28 Knitro changing algorithm from AUTO to 1.
19:55:28 Knitro changing blasoption from AUTO to 1.
19:55:28 Knitro changing bar_initpt from AUTO to 1.
19:55:28 Knitro changing bar_murule from AUTO to 4.
19:55:28 Knitro changing bar_penaltycons from AUTO to 0.
19:55:28 Knitro changing bar_penaltyrule from AUTO to 2.
19:55:28 Knitro changing bar_switchrule from AUTO to 2.
19:55:28 Knitro changing hessopt from AUTO to 1.
19:55:28 Knitro changing initpt_strategy from AUTO to 1.
19:55:28 Knitro changing linesearch from AUTO to 1.
19:55:28 Knitro changing linsolver from AUTO to 2.
19:55:28 
19:55:28 Problem Characteristics                                 (   Presolved)
19:55:28 -----------------------
19:55:28 Objective goal:  Minimize
19:55:28 Objective type:  linear
19:55:28 Number of variables:                                  2 (           2)
19:55:28     bounded below only:                               0 (           0)
19:55:28     bounded above only:                               0 (           0)
19:55:28     bounded below and above:                          0 (           0)
19:55:28     fixed:                                            0 (           0)
19:55:28     free:                                             2 (           2)
19:55:28 Number of constraints:                                2 (           2)
19:55:28     linear equalities:                                0 (           0)
19:55:28     quadratic equalities:                             0 (           0)
19:55:28     gen. nonlinear equalities:                        0 (           0)
19:55:28     linear one-sided inequalities:                    2 (           2)
19:55:28     quadratic one-sided inequalities:                 0 (           0)
19:55:28     gen. nonlinear one-sided inequalities:            0 (           0)
19:55:28     linear two-sided inequalities:                    0 (           0)
19:55:28     quadratic two-sided inequalities:                 0 (           0)
19:55:28     gen. nonlinear two-sided inequalities:            0 (           0)
19:55:28 Number of nonzeros in Jacobian:                       4 (           4)
19:55:28 Number of nonzeros in Hessian:                        0 (           0)
19:55:28 
19:55:28 Knitro using the Interior-Point/Barrier Direct algorithm.
19:55:28 
19:55:28   Iter     fCount     Objective      FeasError   OptError    ||Step||    CGits 
19:55:28 --------  --------  --------------  ----------  ----------  ----------  -------
19:55:28        0         5    1.000000e-08   2.314e+00
19:55:28        1         7    1.000000e-08   2.314e+00   4.975e-01   1.652e+00        0
19:55:28        2         9    1.267867e+00   0.000e+00   1.336e-01   1.827e+00        0
19:55:28        3        11    1.001339e+00   0.000e+00   6.715e-04   2.665e-01        0
19:55:28        4        13    1.000001e+00   0.000e+00   4.509e-07   1.338e-03        0
19:55:28 
19:55:28 EXIT: Optimal solution found.
19:55:28 
19:55:28 Final Statistics
19:55:28 ----------------
19:55:28 Final objective value               =   1.00000089930199e+00
19:55:28 Final feasibility error (abs / rel) =   0.00e+00 / 0.00e+00
19:55:28 Final optimality error  (abs / rel) =   4.51e-07 / 4.51e-07
19:55:28 # of iterations                     =          4 
19:55:28 # of CG iterations                  =          0 
19:55:28 # of function evaluations           =         15
19:55:28 # of gradient evaluations           =          0
19:55:28 # of Hessian evaluations            =          0
19:55:28 Total program time (secs)           =       0.00132 (     0.002 CPU time)
19:55:28 Time spent in evaluations (secs)    =       0.00053
19:55:28 
19:55:28 Constraint Vector 		     Lagrange Multipliers
19:55:28 ----------------- 		     ---------------------
19:55:28 c[       0] =  -9.01802131636e-07,   lambda[       0] =                 0.5
19:55:28 c[       1] =  -8.96801839678e-07,   lambda[       1] =                 0.5
19:55:28 
19:55:28 Solution Vector
19:55:28 ---------------
19:55:28 x[       0] =        1.0000008993,   lambda[       2] =                   0
19:55:28 x[       1] =       -1.0000000025,   lambda[       3] =                   0
19:55:28 
19:55:28 ===============================================================================
19:55:28 
19:55:28 _________________ TestSolvers.test_with_numpy_5_knitro_direct __________________
19:55:28 
19:55:28 a = (<pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers testMethod=test_with_numpy_5_knitro_direct>,)
19:55:28 kw = {}
19:55:28 
19:55:28     @wraps(func)
19:55:28     def standalone_func(*a, **kw):
19:55:28 >       return func(*(a + p.args), **p.kwargs, **kw)
19:55:28 
19:55:28 python3.10/site-packages/parameterized/parameterized.py:620: 
19:55:28 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
19:55:28 pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py:1576: in test_with_numpy
19:55:28     self.assertAlmostEqual(m.x.value, (b2 - b1) / (a1 - a2))
19:55:28 E   AssertionError: -0.6666663318632648 != -0.6666666666666666 within 7 places (3.3480340178027035e-07 difference)
19:55:28 ----------------------------- Captured stdout call -----------------------------
19:55:28 
19:55:28 =======================================
19:55:28 *** NO CHECK MADE FOR LICENSE ***
19:55:28          Artelys Knitro 15.0.0
19:55:28 =======================================
19:55:28 
19:55:28 Knitro using 1 thread.
19:55:28 No start point provided -- Knitro computing one.
19:55:28 
19:55:28 Knitro performing finite-difference gradient computation with 1 thread.
19:55:28 Knitro presolve eliminated 0 variables and 0 constraints.
19:55:28 
19:55:28 concurrent_evals         0
19:55:28 feastol                  1e-06
19:55:28 feastol_abs              0.001
19:55:28 opttol                   1e-06
19:55:28 opttol_abs               0.001
19:55:28 outlev                   6
19:55:28 Knitro changing hessopt to exact (because the problem is an LP).
19:55:28 The problem is identified as an LP.
19:55:28 Knitro changing algorithm from AUTO to 1.
19:55:28 Knitro changing blasoption from AUTO to 1.
19:55:28 Knitro changing bar_initpt from AUTO to 1.
19:55:28 Knitro changing bar_murule from AUTO to 4.
19:55:28 Knitro changing bar_penaltycons from AUTO to 0.
19:55:28 Knitro changing bar_penaltyrule from AUTO to 2.
19:55:28 Knitro changing bar_switchrule from AUTO to 2.
19:55:28 Knitro changing hessopt from AUTO to 1.
19:55:28 Knitro changing initpt_strategy from AUTO to 1.
19:55:28 Knitro changing linesearch from AUTO to 1.
19:55:28 Knitro changing linsolver from AUTO to 2.
19:55:28 
19:55:28 Problem Characteristics                                 (   Presolved)
19:55:28 -----------------------
19:55:28 Objective goal:  Minimize
19:55:28 Objective type:  linear
19:55:28 Number of variables:                                  2 (           2)
19:55:28     bounded below only:                               0 (           0)
19:55:28     bounded above only:                               0 (           0)
19:55:28     bounded below and above:                          0 (           0)
19:55:28     fixed:                                            0 (           0)
19:55:28     free:                                             2 (           2)
19:55:28 Number of constraints:                                2 (           2)
19:55:28     linear equalities:                                0 (           0)
19:55:28     quadratic equalities:                             0 (           0)
19:55:28     gen. nonlinear equalities:                        0 (           0)
19:55:28     linear one-sided inequalities:                    2 (           2)
19:55:28     quadratic one-sided inequalities:                 0 (           0)
19:55:28     gen. nonlinear one-sided inequalities:            0 (           0)
19:55:28     linear two-sided inequalities:                    0 (           0)
19:55:28     quadratic two-sided inequalities:                 0 (           0)
19:55:28     gen. nonlinear two-sided inequalities:            0 (           0)
19:55:28 Number of nonzeros in Jacobian:                       4 (           4)
19:55:28 Number of nonzeros in Hessian:                        0 (           0)
19:55:28 
19:55:28 Knitro using the Interior-Point/Barrier Direct algorithm.
19:55:28 
19:55:28   Iter     fCount     Objective      FeasError   OptError    ||Step||    CGits 
19:55:28 --------  --------  --------------  ----------  ----------  ----------  -------
19:55:28        0         5    1.000000e-08   3.314e+00
19:55:28        1         7    1.000000e-08   3.314e+00   6.626e-01   2.531e+00        0
19:55:28        2         9    2.552612e+00   0.000e+00   1.372e-01   2.701e+00        0
19:55:28        3        11    2.334430e+00   0.000e+00   6.893e-04   2.386e-01        0
19:55:28        4        13    2.333334e+00   0.000e+00   4.751e-07   1.198e-03        0
19:55:28 
19:55:28 EXIT: Optimal solution found.
19:55:28 
19:55:28 Final Statistics
19:55:28 ----------------
19:55:28 Final objective value               =   2.33333408895725e+00
19:55:28 Final feasibility error (abs / rel) =   0.00e+00 / 0.00e+00
19:55:28 Final optimality error  (abs / rel) =   4.75e-07 / 4.75e-07
19:55:28 # of iterations                     =          4 
19:55:28 # of CG iterations                  =          0 
19:55:28 # of function evaluations           =         15
19:55:28 # of gradient evaluations           =          0
19:55:28 # of Hessian evaluations            =          0
19:55:28 Total program time (secs)           =       0.00127 (     0.001 CPU time)
19:55:28 Time spent in evaluations (secs)    =       0.00047
19:55:28 
19:55:28 Constraint Vector 		     Lagrange Multipliers
19:55:28 ----------------- 		     ---------------------
19:55:28 c[       0] =   4.20820514435e-07,   lambda[       0] =     -0.666666666667
19:55:28 c[       1] =  -1.42523071966e-06,   lambda[       1] =      0.333333333333
19:55:28 
19:55:28 Solution Vector
19:55:28 ---------------
19:55:28 x[       0] =       2.33333408896,   lambda[       2] =                   0
19:55:28 x[       1] =     -0.666666331863,   lambda[       3] =                   0
19:55:28 
19:55:38 =========================== short test summary info ============================
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_add_and_remove_vars_5_knitro_direct - AssertionError: 1.500000828607814 != 1.5 within 7 places (8.286078139185804e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_add_remove_cons_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_duals_5_knitro_direct - AssertionError: 1.000000882731383 != 1 within 7 places (8.827313831005767e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_fixed_vars_2_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_fixed_vars_4_2_knitro_direct - AssertionError: 1.4142134816662406 != 1.4142135623730951 within 7 places (8.070685453276383e-08 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_fixed_vars_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_immutable_param_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_no_objective_5_knitro_direct - AssertionError: 0.0 != None
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_objective_changes_5_knitro_direct - AssertionError: 1.0000008827313833 != 1 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_param_changes_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_results_infeasible_5_knitro_direct - AssertionError: <TerminationCondition.unknown: 42> not found in {<TerminationCondition.infeasibleOrUnbounded: 8>, <TerminationCondition.provenInfeasible: 6>}
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_scaling_5_knitro_direct - AssertionError: 1.000000882731383 != 1 within 7 places (8.827313831005767e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_stale_vars_5_knitro_direct - AssertionError: False is not true
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_variables_elsewhere2_5_knitro_direct - AssertionError: 8.993019857525455e-07 != 0 within 7 places (8.993019857525455e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_variables_elsewhere_5_knitro_direct - AssertionError: 1.0000008993019858 != 1 within 7 places (8.993019857683748e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_with_numpy_5_knitro_direct - AssertionError: -0.6666663318632648 != -0.6666666666666666 within 7 places (3.3480340178027035e-07 difference)

Most of the failures are just tolerance problems / the tolerance needs to be loosened.

@mrmundt
Copy link
Contributor

mrmundt commented Sep 19, 2025

One-off failures:

pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers.test_no_objective_5_knitro_direct (from pytest)

Error Message

AssertionError: 0.0 != None

Stacktrace

a = (<pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers testMethod=test_no_objective_5_knitro_direct>,)
kw = {}

    @wraps(func)
    def standalone_func(*a, **kw):
>       return func(*(a + p.args), **p.kwargs, **kw)

/python3.12/site-packages/parameterized/parameterized.py:620: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py:930: in test_no_objective
    self.assertEqual(res.incumbent_objective, None)
E   AssertionError: 0.0 != None

Second one-off:

pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers.test_stale_vars_5_knitro_direct (from pytest)

Error Message

AssertionError: False is not true

Stacktrace

a = (<pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers testMethod=test_stale_vars_5_knitro_direct>,)
kw = {}

    @wraps(func)
    def standalone_func(*a, **kw):
>       return func(*(a + p.args), **p.kwargs, **kw)
/python3.12/site-packages/parameterized/parameterized.py:620: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py:618: in test_stale_vars
    self.assertTrue(m.x.stale)
E   AssertionError: False is not true

@eminyouskn
Copy link
Contributor Author

Thanks @mrmundt for the report. I didn’t run these tests locally since I didn’t have NumPy installed, and in that case, the tests are skipped. I’ll make sure to check them before pushing code from now on.

I do have a question: is there a way to adjust the tolerance for all these tests at once? Ideally, we’d only change it for Knitro, but I imagine that might be more complicated.

Regarding the two remaining failures, I’ve already fixed the one related to the objective. However, I’m not sure how to address the stale one, it’s not clear to me what exactly that test is supposed to check.

@eminyouskn
Copy link
Contributor Author

@blnicho I think the issue with Jenkins was resolved with #3750. So I will update my branch and then we can rerun Jenkins.

@blnicho blnicho moved this from Review In Progress to Reviewer Approved in Pyomo 6.9.5 Release Oct 17, 2025
@mrmundt
Copy link
Contributor

mrmundt commented Oct 17, 2025

We want this in today's release, so we are going to merge it. However, we think there are some lingering opportunities for improvement that we'd like to address with a future PR. Thanks, @eminyouskn !

@mrmundt mrmundt merged commit a0f4339 into Pyomo:main Oct 17, 2025
38 checks passed
@github-project-automation github-project-automation bot moved this from Reviewer Approved to Done in Pyomo 6.9.5 Release Oct 17, 2025
Copy link
Member

@jsiirola jsiirola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great. Some notes for future development / improvements...

ConfigValue(
domain=Bool,
default=False,
doc="KNITRO solver does not allow variable removal. We can either make the variable a continuous free variable or rebuild the whole model when variable removal is attempted. When `rebuild_model_on_remove_var` is set to True, the model will be rebuilt.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to split this into multiple strings to keep line lengths <= 88 characters

ConfigValue(
domain=Bool,
default=False,
doc="To evaluate non-linear constraints, KNITRO solver sets explicit values on variables. This option controls whether to restore the original variable values after solving.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to split this into multiple strings to keep line lengths <= 88 characters

Comment on lines +47 to +50
if item.has_lb():
bounds_map[BoundType.LO][i] = value(item.lb)
if item.has_ub():
bounds_map[BoundType.UP][i] = value(item.ub)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be more efficient to do:

Suggested change
if item.has_lb():
bounds_map[BoundType.LO][i] = value(item.lb)
if item.has_ub():
bounds_map[BoundType.UP][i] = value(item.ub)
lb, ub = item.bounds
if lb is not None:
bounds_map[BoundType.LO][i] = lb
if ub is not None:
bounds_map[BoundType.UP][i] = ub

Comment on lines +52 to +58
if item.equality:
bounds_map[BoundType.EQ][i] = value(item.lower)
continue
if item.has_lb():
bounds_map[BoundType.LO][i] = value(item.lower)
if item.has_ub():
bounds_map[BoundType.UP][i] = value(item.upper)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Note: .lower returns an expression, .lb returns the value)

Also, it is more efficient to retrieve the bounds at once:

Suggested change
if item.equality:
bounds_map[BoundType.EQ][i] = value(item.lower)
continue
if item.has_lb():
bounds_map[BoundType.LO][i] = value(item.lower)
if item.has_ub():
bounds_map[BoundType.UP][i] = value(item.upper)
lb, body, ub = item.to_bounded_expression(evaluate_bounds=True)
if item.equality:
bounds_map[BoundType.EQ][i] = lb
continue
if lb is not None:
bounds_map[BoundType.LO][i] = lb
if ub is not None:
bounds_map[BoundType.UP][i] = ub

return knitro.KN_set_double_param
elif param_type == knitro.KN_PARAMTYPE_STRING:
return knitro.KN_set_char_param
raise DeveloperError()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great defensive programming, but it would be good for these exceptions to have informative messages to help us track things down if they are ever reported.


"""
generator = block.component_data_objects(
Constraint, descend_into=True, active=True, sort=True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be significantly more efficient to not use sort=True and instead use sort=SortComponents.deterministic

This method computes the gradient of the expression with respect to all
variables and stores the results in the grad attribute.
"""
derivative = reverse_sd(self.func_expr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: we should evaluate the computational performance of native python symbolic derivatives. Some alternatives:

  • compile the expressions into executable python code (to avoud needing to use the Pyomo expression evaluator
  • use AD instead of SD (particularly the APPSI c-extension?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects

Development

Successfully merging this pull request may close these issues.

5 participants