Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latex printer #2984

Merged
merged 42 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
23cc0d6
new latex branch
Aug 29, 2023
3523587
Merge remote-tracking branch 'upstream/main' into latex_printer
Aug 29, 2023
6cfd2bf
Merge remote-tracking branch 'upstream/main' into latex_printer
Aug 31, 2023
60cc641
printer is working
Aug 31, 2023
53caefb
Merge branch 'Pyomo:main' into latex_printer
codykarcher Aug 31, 2023
0783f41
doing typos and black
Aug 31, 2023
a697ff1
adding docs and unit tests for the latex printer
Aug 31, 2023
312bad4
removing DS_store
Aug 31, 2023
cfc45dd
adding variable features, fixing some bugs
Sep 1, 2023
bb2082a
removing the star capability and updating documentation
Sep 1, 2023
c9c3a64
adding black
Sep 1, 2023
d70bb95
Merge branch 'Pyomo:main' into latex_printer
codykarcher Sep 5, 2023
6526d77
fixes and adding features
Sep 6, 2023
79b95d6
adding an exception
Sep 6, 2023
5ec0858
minor changes
Sep 6, 2023
7e15c95
working on new features
Sep 7, 2023
51c8a71
adding variable bound capability
Sep 8, 2023
6cdff50
adding param support
Sep 8, 2023
3054a44
functionality working I think
Sep 8, 2023
6c6053f
fixing a bracket bug
Sep 11, 2023
69880ae
fixing a bracket issue and a minor bound print bug
Sep 11, 2023
c07a83e
Merge branch 'Pyomo:main' into latex_printer
codykarcher Sep 18, 2023
9a077d9
making updates to the single constraint printer
Sep 19, 2023
e417da6
reworking the latex printer
Sep 22, 2023
e9232d2
adding some paper sizing and font size features
Sep 26, 2023
d11667a
Merge branch 'Pyomo:main' into latex_printer
codykarcher Oct 11, 2023
923ed8b
working on unit tests
Oct 11, 2023
5e7c0b1
staging printer things
Oct 12, 2023
7ae81bf
removing the smart variable generator
Oct 12, 2023
5c3bedf
Merge branch 'Pyomo:main' into latex_printer
codykarcher Nov 2, 2023
87c4742
adding a numpy float to the latex printer
Nov 2, 2023
93fdf50
improving robustness of the printer
Nov 2, 2023
f53b635
applying black
Nov 2, 2023
3981f2f
updating the default behavior of failed templatization
Nov 7, 2023
5812e60
Merge branch 'Pyomo:main' into latex_printer
codykarcher Nov 8, 2023
b2a6a3e
fixing the doc examples pe->pyo
Nov 8, 2023
5ff4d14
making requested changes
Nov 23, 2023
9fdc225
Merge branch 'Pyomo:main' into latex_printer
codykarcher Nov 23, 2023
dee45eb
working on requested changes
Nov 27, 2023
317cd9d
finishing pr request triage
Nov 27, 2023
1a1f9a1
Merge branch 'Pyomo:main' into latex_printer
codykarcher Nov 27, 2023
c29439e
Add missing __init__.py file
blnicho Nov 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/OnlineDocs/model_debugging/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ Debugging Pyomo Models
model_interrogation.rst
FAQ.rst
getting_help.rst
latex_printing.rst
134 changes: 134 additions & 0 deletions doc/OnlineDocs/model_debugging/latex_printing.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
Latex Printing
==============

Pyomo models can be printed to a LaTeX compatible format using the ``pyomo.util.latex_printer`` function:

.. py:function:: latex_printer(pyomoElement, filename=None, useAlignEnvironment=False, splitContinuousSets=False)

Prints a pyomo element (Block, Model, Objective, Constraint, or Expression) to a LaTeX compatible string
Copy link
Contributor

Choose a reason for hiding this comment

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

"pyomo element" should be "pyomo component" (just for the sake of consistency)


:param pyomoElement: The pyomo element to be printed
:type pyomoElement: _BlockData or Model or Objective or Constraint or Expression
blnicho marked this conversation as resolved.
Show resolved Hide resolved
:param filename: An optional filename where the latex will be saved
:type filename: str
:param useAlignEnvironment: If False, the equation/aligned construction is used to create a single LaTeX equation. If True, then the align environment is used in LaTeX and each constraint and objective will be given an individual equation number
:type useAlignEnvironment: bool
:param splitContinuousSets: If False, all sums will be done over 'index in set' or similar. If True, sums will be done over 'i=1' to 'N' or similar if the set is a continuous set
Copy link
Contributor

Choose a reason for hiding this comment

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

If the set is a continuous set, we shouldn't be summing over it at all, should we? Where does this case come up?

:type splitContinuousSets: bool


:return: A LaTeX style string that represents the passed in pyomoElement
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
:return: A LaTeX style string that represents the passed in pyomoElement
:return: A LaTeX style string that represents the passed in Pyomo component

:rtype: str


.. note::

If operating in a Jupyter Notebook, it may be helpful to use:

``from IPython.display import display, Math``

``display(Math(latex_printer(m))``
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a cool note to include!


The LaTeX printer will auto detect the following structures in variable names:

* ``_``: underscores will get rendered as subscripts, ie ``x_var`` is rendered as ``x_{var}``
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the expected behavior for this_is_a_very_descriptive_variable_name? I ask because we encourage users to be more PEP8 than math when they write models: that is long descriptive names rather than m.x. So I'm actually not exaggerating too badly. I'm wondering if it might be easier to just generate variable names for the latex and return a map of the original var to the generated one. Or, even better, maybe the user could optionally provide their own map that you would use... I think I would like that option the best.

* ``_dot``: will format as a ``\dot{}`` and remove from the underscore formatting. Ex: ``x_dot_1`` becomes ``\dot{x}_1``
* ``_hat``: will format as a ``\hat{}`` and remove from the underscore formatting. Ex: ``x_hat_1`` becomes ``\hat{x}_1``
* ``_bar``: will format as a ``\bar{}`` and remove from the underscore formatting. Ex: ``x_bar_1`` becomes ``\bar{x}_1``
Copy link
Contributor

Choose a reason for hiding this comment

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

I think these make me be in favor of the map idea too. These are nice, but the problem is where do we stop. Why not mathcal or underline or the list goes on...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

smart variables are no longer the default behavior, and will implement a mapping as requested



Examples
--------

A Model
+++++++

.. doctest::

>>> # Note: this model is not mathematically sensible

>>> import pyomo.environ as pe
blnicho marked this conversation as resolved.
Show resolved Hide resolved
>>> from pyomo.core.expr import Expr_if
>>> from pyomo.core.base import ExternalFunction
>>> from pyomo.util.latex_printer import latex_printer

>>> m = pe.ConcreteModel(name = 'basicFormulation')
>>> m.x = pe.Var()
>>> m.y = pe.Var()
>>> m.z = pe.Var()
>>> m.objective = pe.Objective( expr = m.x + m.y + m.z )
>>> m.constraint_1 = pe.Constraint(expr = m.x**2 + m.y**-2.0 - m.x*m.y*m.z + 1 == 2.0)
>>> m.constraint_2 = pe.Constraint(expr = abs(m.x/m.z**-2) * (m.x + m.y) <= 2.0)
>>> m.constraint_3 = pe.Constraint(expr = pe.sqrt(m.x/m.z**-2) <= 2.0)
>>> m.constraint_4 = pe.Constraint(expr = (1,m.x,2))
>>> m.constraint_5 = pe.Constraint(expr = Expr_if(m.x<=1.0, m.z, m.y) <= 1.0)

>>> def blackbox(a, b): return sin(a - b)
>>> m.bb = ExternalFunction(blackbox)
>>> m.constraint_6 = pe.Constraint(expr= m.x + m.bb(m.x,m.y) == 2 )

>>> m.I = pe.Set(initialize=[1,2,3,4,5])
>>> m.J = pe.Set(initialize=[1,2,3])
>>> m.u = pe.Var(m.I*m.I)
>>> m.v = pe.Var(m.I)
>>> m.w = pe.Var(m.J)

>>> def ruleMaker(m,j): return (m.x + m.y) * sum( m.v[i] + m.u[i,j]**2 for i in m.I ) <= 0
>>> m.constraint_7 = pe.Constraint(m.I, rule = ruleMaker)

>>> def ruleMaker(m): return (m.x + m.y) * sum( m.w[j] for j in m.J )
>>> m.objective_2 = pe.Objective(rule = ruleMaker)

>>> pstr = latex_printer(m)
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 nice to not suppress the result here and instead include the output (it both tests that the output doesn't change, and documents the output for the user). Same for the other examples below...



A Constraint
++++++++++++

.. doctest::

>>> import pyomo.environ as pe
>>> from pyomo.util.latex_printer import latex_printer

>>> m = pe.ConcreteModel(name = 'basicFormulation')
>>> m.x = pe.Var()
>>> m.y = pe.Var()

>>> m.constraint_1 = pe.Constraint(expr = m.x**2 + m.y**2 <= 1.0)

>>> pstr = latex_printer(m.constraint_1)


An Expression
+++++++++++++

.. doctest::

>>> import pyomo.environ as pe
>>> from pyomo.util.latex_printer import latex_printer

>>> m = pe.ConcreteModel(name = 'basicFormulation')
>>> m.x = pe.Var()
>>> m.y = pe.Var()

>>> m.expression_1 = pe.Expression(expr = m.x**2 + m.y**2)

>>> pstr = latex_printer(m.expression_1)


A Simple Expression
+++++++++++++++++++

.. doctest::

>>> import pyomo.environ as pe
>>> from pyomo.util.latex_printer import latex_printer

>>> m = pe.ConcreteModel(name = 'basicFormulation')
>>> m.x = pe.Var()
>>> m.y = pe.Var()

>>> pstr = latex_printer(m.x + m.y)



Loading