pyomo
pyomo copied to clipboard
Interface to GiNaC for Simplification
Summary/Motivation:
This PR provides an interface to GiNaC for expression simplification (although sympy can be used as well).
In [1]: import pyomo.environ as pe
In [2]: from pyomo.core.expr import differentiate
In [3]: from pyomo.contrib.simplification import Simplifier
In [4]: from pyomo.contrib.fbbt.fbbt import compute_bounds_on_expr
In [5]: m = pe.ConcreteModel()
...: m.x = pe.Var(bounds=(0, None))
...: e = m.x * pe.log(m.x)
In [6]: der1 = differentiate(e, m.x, mode=differentiate.Modes.reverse_symbolic)
...: der2 = differentiate(der1, m.x, mode=differentiate.Modes.reverse_symbolic)
In [7]: simp = Simplifier()
In [8]: der2_simp = simp.simplify(der2)
In [9]: print(der2)
1/x - x/x**2 + 1/x
In [10]: print(der2_simp)
x**-1.0
In [11]: compute_bounds_on_expr(der2_simp)
Out[11]: (0.0, None)
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:
- I agree my contributions are submitted under the BSD license.
- 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.
Okay, I think tests will pass now. The GiNaC interface is only tested under "singletest" because it takes a while to install GiNaC.
Codecov Report
Attention: 50 lines in your changes are missing coverage. Please review.
Comparison is base (
85b63ab) 88.26% compared to head (125b7c7) 88.22%. Report is 87 commits behind head on main.
| Files | Patch % | Lines |
|---|---|---|
| pyomo/contrib/simplification/build.py | 18.33% | 49 Missing :warning: |
| pyomo/contrib/simplification/simplify.py | 97.36% | 1 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## main #3088 +/- ##
==========================================
- Coverage 88.26% 88.22% -0.05%
==========================================
Files 832 835 +3
Lines 92385 92484 +99
==========================================
+ Hits 81544 81593 +49
- Misses 10841 10891 +50
| Flag | Coverage Δ | |
|---|---|---|
| linux | 85.98% <50.00%> (-0.04%) |
:arrow_down: |
| osx | 75.49% <31.00%> (-0.05%) |
:arrow_down: |
| other | 86.16% <50.00%> (-0.04%) |
:arrow_down: |
| win | 83.37% <31.00%> (-0.06%) |
:arrow_down: |
Flags with carried forward coverage won't be shown. Click here to find out more.
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
FWIW, I got directed to this PR by John Siirola, and had an error:
Traceback (most recent call last):
File "C:\Users\[REDACTED]\.conda\envs\idaes\lib\pdb.py", line 1723, in main
pdb._runscript(mainpyfile)
File "C:\Users\[REDACTED]\.conda\envs\idaes\lib\pdb.py", line 1583, in _runscript
self.run(statement)
File "C:\Users\[REDACTED]\.conda\envs\idaes\lib\bdb.py", line 598, in run
exec(cmd, globals, locals)
File "<string>", line 1, in <module>
File "c:\users\[REDACTED]\repos\cesar_1\enrtl\enthalpy_validation_local_3.py", line 96, in <module>
diff = simp.simplify(
File "c:\users\[REDACTED]\repos\pyomo\pyomo\contrib\simplification\simplify.py", line 65, in simplify
return simplify_with_sympy(expr)
File "c:\users\[REDACTED]\repos\pyomo\pyomo\contrib\simplification\simplify.py", line 32, in simplify_with_sympy
se = se.simplify()
AttributeError: 'int' object has no attribute 'simplify'
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> c:\users\[REDACTED]\repos\pyomo\pyomo\contrib\simplification\simplify.py(32)simplify_with_sympy()
-> se = se.simplify()
(Pdb) print(se)
0
I see now that I didn't end up installing GiNaC, so that's why it's using Sympy, but thought I should let you know about the issue in the present implementation.
Edit: Is there any tutorial about how to install GiNaC and make it available to Pyomo? I see there's parts of the PR to add GiNaC install to the CI, but I'm not sure how to translate that to my (Windows) machine.
@dallan-keylogic - Thanks! Should be fixed now. Please let me know if my fix did not actually fix the problem.
Let me get back to you on installation.
@dallan-keylogic, I don't have any better installation instructions than what is here: https://www.ginac.de/Download.html. Once you have GiNaC installed, you need to make sure the libraries and header files for both CLN and GiNaC are "findable". Ultimately those get used here: https://github.com/michaelbynum/pyomo/blob/1b1f944dbd00ca0e0b27d2fd2b70ee681b8e44ae/pyomo/contrib/simplification/build.py#L60.
Unfortunately that fix didn't work:
Traceback (most recent call last):
File "C:\Users\[REDACTED]\.conda\envs\idaes\lib\pdb.py", line 1723, in main
pdb._runscript(mainpyfile)
File "C:\Users\[REDACTED]\.conda\envs\idaes\lib\pdb.py", line 1583, in _runscript
self.run(statement)
File "C:\Users\[REDACTED]\.conda\envs\idaes\lib\bdb.py", line 598, in run
exec(cmd, globals, locals)
File "<string>", line 1, in <module>
File "c:\users\[REDACTED]\repos\cesar_1\enrtl\enthalpy_validation_local_3.py", line 96, in <module>
diff = simp.simplify(
File "c:\users\[REDACTED]\repos\pyomo\pyomo\contrib\simplification\simplify.py", line 69, in simplify
return simplify_with_sympy(expr)
File "c:\users\[REDACTED]\repos\pyomo\pyomo\contrib\simplification\simplify.py", line 34, in simplify_with_sympy
se = se.simplify()
AttributeError: 'int' object has no attribute 'simplify'
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> c:\users\[REDACTED]\repos\pyomo\pyomo\contrib\simplification\simplify.py(34)simplify_with_sympy()
-> se = se.simplify()
(Pdb) is_constant(se)
True
(Pdb) is_constant(expr_
*** SyntaxError: '(' was never closed
(Pdb) is_constant(expr)
False
(Pdb) expr
<pyomo.core.base.expression.ExpressionData object at 0x0000022960608880>
(Pdb) expr.pprint()
{Member of Liq_dalpha_dT} : Non-randomness parameters
Size=28, Index=params.true_species_set*params.true_species_set
Key : Expression
('H2O', 'H2O') : 0.0
(Pdb) expr.is_constant()
False
(Pdb) type(expr)
<class 'pyomo.core.base.expression.ExpressionData'>
It looks like is_constant always returns false for ExpressionData.
Let me try installing GiNaC and get back to you on that.
The link for Windows builds of GiNaC is broken, so that probably ends this experiment for me.
@jsiirola, should sympyify_expression convert mutable parameters to sympy symbols like it does for variables? I think this is what is causing @dallan-keylogic's error (not 100% sure).
Another question for @jsiirola - right now, the simplification logic using sympy will remove mutable parameters from the expression. I'm not sure how I feel about that. I don't really know what the expected behavior should be. Thoughts?
Unfortunately, in my current model I have some "mutable" parameters that are equal to zero and that I never want to change, but they're forced to be mutable because they have units. I think that AD is fixed so I could just turn them into 0 multiplied by units, though.
There seem to be issues with get_tar_archive on windows
Thanks for all the help on this one, @jsiirola.
@dallan-keylogic, I believe we did fix the mutable parameter issue as part of the PR (with the sympy interface).