Log In
Email:
Password:
logResponse
Sign Up
Email:
Initially empty
Welcome Back
You are logged in
This page describes the requirements, capabilities, and limitations of the current version of tex2solver. Please consult the user manual below if you are having system issues. These materials will be updated/refined/improved as tex2solver matures.
Table of Contents:
tex2solver converts linear programming (LP) or mixed integer linear programming (MILP) models from LaTeX code to Python solver code.
There are 4 ways to input an LP or MILP model:
The input to tex2solver should be an LP or MILP formulation, consisting of an objective function, constraints, and decision variable definitions. This model should be written in LaTeX syntax. The image below depicts the five key elements of a model:
The model should be wrapped in any of the following environments:
\begin{align}
and \end{align}
\begin{flalign}
and \end{flalign}
\begin{array}
and \end{array}
\begin{gather}
and \end{gather}
\begin{equation}
and \end{equation}
\begin{eqnarray}
and \end{eqnarray}
You may also use the "starred" versions of these environments (e.g., \begin{align*}
and \end{align*}
) to hide the equation numbers. This is purely cosmetic, and won't change the output code.
The first line of the formulation must be the objective function. This should start with any of the following, which indicate the "sense" of the objective (i.e., maximization or minimization):
\min
\text{Min}
\text{Minimize}
\max
\text{Max}
\text{Maximize}
The "Min", "Minimize", "Max" and "Maximize" text strings are case insensitive. The \min
and \max
LaTeX tags are case sensitive.
The objective function should end with two backslashes (\\
). For example:
LaTeX Code | Rendered | |
---|---|---|
\text{Min } 2x + 3y \\ | \(\text{Min } 2x + 3y \) |
The first constraint should appear on the next line after the objective function. This constraint should begin with one of the following LaTeX tags:
\text{subject to}
\text{such that}
\text{s.t.}
The "subject to", "such that" and "s.t." text strings are case insensitive.
Subsequent constraints should not start with a "subject to" tag (i.e., your model should have exactly one "subject to" tag).
Each constraint should end with two backslashes (\\
). For example:
LaTeX Code | Rendered | |
---|---|---|
\text{s.t. } & x + y \ge 7 \\ & x - 2y \ge 13 \\ | $$ \begin{align*} \text{s.t. } & x + y \ge 7 \\ & x - 2y \ge 13 \\ \end{align*} $$ |
Decision variable definitions should appear after the constraints. The block of decision variable definitions must begin with the following LaTeX comment:
% _decvars_
%
symbol.
tex2solver will warn you if you forget to include this flag. The "Mark Decision Variables" button will help you place this flag in your model.
To generate usable solver code, tex2solver needs to know which elements of your model are decision variables. Thus, each decision variable should be explicitly defined after the % _decvars_
line.
Each decision variable definition should end with two backslashes (\\
). For example:
LaTeX Code | Rendered | |
---|---|---|
% _decvars_ x \ge 0 \\ y \ge 0 \\ | $$ \begin{align*} & x \ge 0 \\ & y \ge 0 \end{align*} $$ |
In this document we will use the following terms:
% _decars_
line so it can pass this information along to the solver.Q
.This section covers the expected LaTeX math syntax of a mathematical model and how it is interpreted. This includes what is supported in terms of notation, decision variable definitions, summations, and "forall" statements.
Before we continue, let's introduce tex2solver's terminology for describing parameter and decision variable notation. We'll do this using the example of \hat{x}^{ab}_{\sigma,c}
:
x
.\hat
is a decorator.Keep reading below for more details...but keep in mind these two very important things:
Parameters and decision variables are restricted to a base with a single character.
x
is acceptable.\alpha
is acceptable, because it is interpreted as being the single Greek letter \(\alpha\).
xy
is not acceptable. It will be interpreted as x*y
\text{cost}
is not currently acceptable as a "base" because it is a text string.Each index is also restricted to single characters. See examples below.
Indices of decision variables and parameters can be set as either subscripts (using the underscore, _
) or superscripts (using the ^
symbol). Note that each character inside the braces will be considered individually. For example, if the subscript consists of ij
, tex2solver will treat this as separate characters i
and j
.
tex2solver applies some rather specific rules to translate variable notation from LaTeX to Python. Subscripts and superscripts that are indices of a variable are converted as keys of a dictionary associated with the "base" variable. Non-indices are converted as part of the variable name separated by an underscore (_
).
The key issue is whether the contents in the subscripts and superscripts should be part of the variable name itself, or indices.
Let's start with the easy stuff.
\text{}
tag;+
, -
, or *
symbols, if they are not being used to perform a mathematical operation; and\min
and \max
tags.
x
is augmented. There are no indices in these examples.
LaTeX Input | Rendered | Python Output | |
---|---|---|---|
a decorator | \hat{x} | \(\hat{x}\) | x_hat |
double prime | x'' | \(x''\) | x_dprime |
a text label | x^{\text{alt}} | \(x^{\text{alt}}\) | x_alt |
arithmetic symbol | x_{+} | \(x_{+}\) | x_plus |
min tag | x_{\min} | \(x_{\min}\) | x_min |
combination | x_{*}^{\max} | \(x_{*}^{\max}\) | x_star_max |
Now, suppose we have a defined a decision variable named x_{i}
(\(x_i\)). Should this become an indexed data structure in Python (e.g., x[i]
) or should i
augment the base variable (e.g., x_i
)? It depends on exactly how the decision variable was defined.
x_i \ge 0
(\(x_i \ge 0\)), then the Python output is a single scalar variable named x_i
.x_i \ge 0 \forall i \in I
(\(x_i \ge 0 ~ \forall ~ i \in I\)), then the Python output will treat x
as an indexed data structure: x[i]
.What if there are multiple entries in a super/subscript? Will these be treated as indices or as modifiers of the base variable name? The answer, again, is "it depends". However, now there's another factor to consider: The presence of a comma ,
.
i
, j
, and k
) are also specified in the associated "forall" statement, then the entries will augment the base (in this case, x
):
LaTeX Input | Python Output | |
---|---|---|
x_{ijk} (\(x_{ijk}\)) | becomes | x_i_j_k |
x_{i,j,k} (\(x_{i,j,k}\)) | becomes | x_i_j_k |
x_{i jk} (\(x_{i jk}\)) | becomes | x_i_j_k |
x_{ij,k} (\(x_{ij,k}\)) | becomes | x_ij_k |
LaTeX Input | Python Output | |
---|---|---|
x_{ijk} (\(x_{ijk}\)) | becomes | x[i][j][k] |
x_{i,j,k} (\(x_{i,j,k}\)) | becomes | x[i][j][k] |
x_{i jk} (\(x_{i jk}\)) | becomes | x[i][j][k] |
x_{ij,k} (\(x_{ij,k}\)) | becomes | x[i*j][k] |
If a decision variable or parameter has one index as a single subscript or superscript, the argument does not have to be wrapped inside braces { }
. The following are allowable:
x_i
is equivalent to x_{i}
, and both are rendered as \(x_{i}\). The Python representation will be x[i]
.x^\alpha
is equivalent to x^{\alpha}
, and both are rendered as \(x^{\alpha}\). The Python representation will be x[alpha]
x_i^j
is equivalent to x_{i}^{j}
, and both are rendered as \(x_i^j\). The Python representation will be x[i][j]
.If both subscripts and superscripts are used, subscripts are given precedence. For example, x_i^j
and x^j_i
will be represented in Python as x[i][j]
.
If a decision variable or parameter has multiple indices described in subscripts or superscripts, the arguments must be wrapped inside braces { }
. The individual indices can be separated by commas, spaces, or not separated at all. For example:
x_{i,j}
is rendered as \(x_{i,j}\). x
is the "base", and i
and j
are considered to be the two indices of x
. The Python representation will be x[i][j]
.x_{i j}
is rendered as \(x_{i j}\). x
is the "base", and i
and j
are considered to be the two indices of x
. The Python representation will be x[i][j]
, which is the same as if we had defined x_{i,j}
with a comma separating the subscripts.y^{ijk}
is rendered as \(y^{ijk}\). y[i][j][k]
.Note what happens if we forget to wrap multiple indices inside braces: x^ijk
is rendered as \(x^ijk\) (indices \(j\) and \(k\) are not included in the superscript). The Python code will become x[i]*j*k
.
Nesting subscripts and superscripts is allowed, but only to modify the naming of an index or indices.
x_{i_\alpha}
is rendered as \(x_{i_\alpha}\). x[i_alpha]
, where x
is the name of the data structure (the "base") and i_alpha
is the index.x_{i^+}
is rendered as \(x_{i^+}\). x[i_plus]
.x^{i^{\alpha}j}
is rendered as \(x^{i^{\alpha}j}\). x[i_alpha][j]
All decision variables must be defined after the % _decvars_
comment in LaTeX. There should be no constraints after that comment.
In general, decision variables are defined in individual lines of the model. For example:
x \ge 0 \\ y \in \{0, 1\}
However, it is possible to "overload" decision variable definitions, as in:
x_{i}, y_{i} \geq 0 \forall i \in I
Overloading of decision variable definitions is only permissible if:
\geq 0
), and\forall i \in I
).In a single-bounded definition, the first value must be the decision variable, followed by a relational comparator and then a parameter. The parameter can be a number, a variable without indices, or a variable with indices. For example:
p \ge 30
(\(p \ge 30\))q \le b
(\(q \le b\))r \le \hat{c}
(\(r \le \hat{c}\))s_i \le d_i \forall i \in I
(\(s_i \le d_i ~ \forall ~ i \in I\))tex2solver currently supports only non-negative decision variables. If the relational comparator is \le
, then the decision variable is also assumed to be \ge 0
.
In a double-bounded definition, the middle value between relational comparators must be the decision variable. For example:
0 \le x \le 1
(\(0 \le x \le 1\))The default decision variable type is "continuous". You don't need to explicitly declare a variable to be continuous-valued.
Integer decision variables can be defined using any of the following LaTeX syntax:
\ge 0 \text{ and integer }
(rendered as \(\ge 0 \text{ and integer }\));\in \mathbb{Z}
(rendered as \(\in \mathbb{Z}\));\in \mathbb{Z}^{+}
(rendered as \(\in \mathbb{Z}^{+}\));\in \mathcal{Z}
(rendered as \(\in \mathcal{Z}\)); or \in \mathcal{Z}^{+}
(rendered as \(\in \mathcal{Z}^{+}\)).For example:
x_i >= \alpha \text{ and integer} c_{ijk} \in \mathcal{Z}
Any LaTeX text commands used to describe the type of decision variable must only come immediately before the \forall
tag (if applicable) or at the end of the line (if there's no \forall
tag). For example:
x_i \ge 0 \text{ and integer } \forall i \in I
y \ge 0 \text{ and integer}
Define binary decision using:
\in \{0, 1\}
(rendered as \(\in \{0, 1\}\)) or\ge 0 \text{ and binary }
(rendered as \(\ge 0 \text{ and binary }\)).Matching "escaped" braces (\{
and \}
) are the preferred way of defining ranges or collections of values. Non-escaped braces won't actually display when rendered: \in {0,1}
is rendered as \(\in {0, 1}\).
Sets may be defined as collections of individual values, ranges, or parameters. For example:
\{0, 3, 6, 10\}
(\(\{0, 3, 6, 10\}\)) represents a collection of values; \{2, 5, \ldots, n\}
(\(\{2, 5, \ldots, n\}\)) represents a range of values from 2 thru \(n\) in increments of 3; and I
could represent a set.You may use \ldots
(\(\ldots\)), \cdots
(\(\cdots\)), or three periods ...
to indicate a range.
\{2, 5, \ldots, n\}
), the difference between the second value and the first will be used to determine the step size.\{2, \ldots, 5\}
), the step size will be assumed to be 1.Python's range operator uses the form range(start, stop, [step])
, where the start value equals start
and the end value is up to but not including stop
. For this reason, the Python translation of \{1, 2, \ldots, n\}
is range(1, n+1)
(rather than range(1, n)
). The step size is optional. Each of the values must be integers.
Matching "escaped" braces (\{
and \}
) are the preferred way of defining ranges or collections of values. Non-escaped braces won't actually display when rendered: \in {0,1}
is rendered as \(\in {0, 1}\).
Supported set operators:
\in
(\(\in\))\notin
(\(\notin\))\cup
(\(\cup\)) or \bigcup
(\(\bigcup\)) represent set union\cap
(\(\cap\)) or \bigcap
(\(\bigcap\)) represent set intersection\setminus
(\(\setminus\)) is used to exclude one or more items from a setConditionals are represented by a colon :
, meaning "such that".
i \in \{A : i \ne j\}
i \in \{A : i \leq j\}
Conditionals may be applied within \forall
statements and summations.
tex2solver applies several rules to differentiate among absolute value, cardinality of a set, and a conditional expression. There are many different ways to convey these three mathematical constructs in LaTeX; the trick is in translating this to the correct solver code.
The list below provides a guide for choosing the LaTeX symbols that will result in solver code that does what you actually intended.
\abs{}
a
and b
would be written in LaTeX as \abs{a - b}
(rendered as \(|a - b|\)).|
(pipe) symbols. For example, the number of elements in set S
would be | S |
(rendered as \(| S |\)).\vert
tags, which also produce the pipe symbol in LaTeX. For example, \vert S \vert
(rendered as \(\vert S \vert\)).\lvert
and \rvert
tags to produce the pipe symbols in LaTeX. For example, \lvert S \rvert
(rendered as \(\lvert S \rvert\)).:
j
of a set J
such that j
is not equal to some scalar i
, write: \forall j \in \{J : j \ne i\}
, which is rendered as \(\forall j \in \{J : j \ne i\}\).
The conditional symbol (:
) cannot appear within escaped braces ( \{
and \}
) if set cardinality is also used within those braces. For example, \forall j \in \{1, \ldots, |N| : j \ne i\}
will cause an error. Instead, write this as \forall j \in \{1, \ldots, |N|\} : j \ne i
.
There are several tags that are not supported by tex2solver. These include:
\mid
,\norm{}
, and\|
(an "escaped" pipe symbol, which actually produces double pipes).If none of these options work for you, please email us with an explanation of your use case.
The \forall
(\(\forall\)) tag may be used in constraints and decision variable definitions (i.e., it cannot be used in the objective function).
When there are multiple indices that need to be defined in a \forall
statement, make sure the definitions are separated by a comma. For example:
x_{i,j} \geq 0 \forall i \in A, j \in B
tex2solver supports "overloaded" \forall
statements, which can simplify notation. For example:
x_{i,j} \ge 0 \forall i \in A, j \in A
can be re-written as x_{i,j} \ge 0 \forall i, j \in A
.The \sum
(\(\sum\)) tag may be used in the objective function and constraints (i.e., it cannot be used to define indices in the decision variable definitions).
Subscripts and superscripts are also applied to summations to define the index space. The index can be defined by setting lower and upper limits or by specifying a set. For example:
\sum_{i=0}^n
(\(\sum_{i=0}^n\))\sum_{i \in I}
(\(\sum_{i \in I}\))Conditionals inside the subscripts using the colon qualifier are also supported. For example:
\sum_{i \in \{A : i \neq j\}}
(\(\sum_{i \in \{A : i \neq j\}}\))The terms associated with a summation must be wrapped by the following bracket types:
( )
\( \)
\{ \}
\left
and \right
may be applied to the bracketsThe terms of a summation should be wrapped to avoid any ambiguity of when the summation ends. For example, consider the \sum_{i=0}^n x_i+y_i - z
(\(\sum_{i=0}^n x_i+y_i - z\)).
x_j+y_i
belong inside the summation, but the subtraction of z
does not, the x_j+y_i
should be wrapped using the suggested brackets:
\sum_{i=0}^n \{x_i+y_i\} - z
(\(\sum_{i=0}^n \{x_i+y_i\} - z\)).In the case of nested summations, the terms at the deepest level should be wrapped inside the supported bracket types. The nested \sum
command and its index definition do not have to be wrapped. For example:
\sum_{i=0}^n \sum_{j=0}^n \{X_i+y_i\} - z
(\(\sum_{i=0}^n \sum_{j=0}^n \{X_i+y_i\} - z\)).The \substack{}
command allows stacking of multiple lines in the subscript of a summation. This command can be used to specify the index space as a set relation, inequality, or equation. Lines should be separated by \\
. For example:
\sum_{\substack{i=0 \\ i \neq j}}^n
(\(\sum_{\substack{i=0 \\ i \neq j}}^n\))Use of the colon qualifier (:
) to specify a conditional is not currently supported inside a \substack{}
tag. For example, \sum_{\substack{i \in \{A : i \neq j\}}}
(\(\sum_{\substack{i \in \{A : i \neq j\}}}\)) will currently produce an error.
It is possible to "overload" a single summation with multiple indices. For example:
\sum_{i,j \in Q} x_{ij} \ge 0
(\(\sum_{i,j \in Q} x_{ij} \ge 0\)).Horizontal spacings are commonly used to separate a constraint or decision variable definition and their forall statement. For example:
Using Spacing Tags | Without Spacing | |
---|---|---|
x_i \ge 0 \quad \forall ~ i \in I |
x_i \ge 0 \forall i \in I |
|
$$x_i \ge 0 \quad \forall ~ i \in I$$ | $$x_i \ge 0 \forall i \in I$$ |
Currently, tex2solver supports the following horizontal space tags: \quad
, \qquad
, ~
, \enspace
, \hspace{}
, and \thinspace
.
The use of these tags is for purely cosmetic purposes. Spacing does not change the generated solver code.
Greek letters can be used as decision variables, parameters, or to modify the names of variables and parameters.
The following is a list of Greek letters in LaTeX and their conversion in the output solver code.
LaTeX | Python | LaTeX | Python | |||
---|---|---|---|---|---|---|
\(\alpha\) | \alpha | alpha | ||||
\(\beta\) | \beta | beta | ||||
\(\gamma\) | \gamma | gamma | \(\Gamma\) | \Gamma | Gamma | |
\(\delta\) | \delta | delta | \(\Delta\) | \Delta | Delta | |
\(\epsilon\) | \epsilon | epsilon | ||||
\(\varepsilon\) | \varepsilon | varepsilon | ||||
\(\zeta\) | \zeta | zeta | ||||
\(\eta\) | \eta | eta | ||||
\(\theta\) | \theta | theta | \(\Theta\) | \Theta | Theta | |
\(\vartheta\) | \vartheta | vartheta | ||||
\(\iota\) | \iota | iota | ||||
\(\kappa\) | \kappa | kappa | ||||
\(\lambda\) | \lambda | lmbda * | \(\Lambda\) | \Lambda | Lmbda * | |
\(\mu\) | \mu | mu | ||||
\(\nu\) | \nu | nu | ||||
\(\xi\) | \xi | xi | \(\Xi\) | \Xi | Xi | |
\(\pi\) | \pi | pi | \(\Pi\) | \Pi | Pi | |
\(\varpi\) | \varpi | varpi | ||||
\(\rho\) | \rho | rho | ||||
\(\varrho\) | \varrho | varrho | ||||
\(\sigma\) | \sigma | sigma | \(\Sigma\) | \Sigma | Sigma | |
\(\varsigma\) | \varsigma | varsigma | ||||
\(\tau\) | \tau | tau | ||||
\(\upsilon\) | \upsilon | upsilon | \(\Upsilon\) | \Upsilon | Upsilon | |
\(\phi\) | \phi | phi | \(\Phi\) | \Phi | Phi | |
\(\varphi\) | \varphi | varphi | ||||
\(\chi\) | \chi | chi | ||||
\(\psi\) | \psi | psi | \(\Psi\) | \Psi | Psi | |
\(\omega\) | \omega | omega | \(\Omega\) | \Omega | Omega |
* lambda
is a reserved keyword in Python. The LaTeX \lambda
tag is intentionally written in Python without the first "a" (as in lmbda
). For consistency, the upper case \Lambda
is similarly written in Python as Lmbda
.
Decorators can be used to modify the name of a variable or parameter.
The following is a list of decorators in LaTeX, applied to variablex
, and how they are converted to solver code.
LaTeX Decorator | Variable Name | |
---|---|---|
\(x'\) | x' | x_prime |
\(x''\) | x'' | x_dprime |
\(x'''\) | x''' | x_tprime |
\(\acute{x}\) | \acute{x} | x_acute |
\(\bar{x}\) | \bar{x} | x_bar |
\(\breve{x}\) | \breve{x} | x_breve |
\(\check{x}\) | \check{x} | x_check |
\(\dot{x}\) | \dot{x} | x_dot |
\(\ddot{x}\) | \ddot{x} | x_ddot |
\(\dddot{x}\) | \dddot{x} | x_dddot |
\(\grave{x}\) | \grave{x} | x_grave |
\(\hat{x}\) | \hat{x} | x_hat |
\(\widehat{x}\) | \widehat{x} | x_widehat |
\(\mathring{x}\) | \mathring{x} | x_mathring |
\(\overline{x}\) | \overline{x} | x_overline |
\(\underline{x}\) | \underline{x} | x_underline |
\(\overbrace{x}\) | \overbrace{x} | x_overbrace |
\(\underbrace{x}\) | \underbrace{x} | x_underbrace |
\(\tilde{x}\) | \tilde{x} | x_tilde |
\(\widetilde{x}\) | \widetilde{x} | x_widetilde |
\(\vec{x}\) | \vec{x} | x_vec |
Decorators may only be applied to single symbol arguments.
Allowed | Not Allowed | |||
---|---|---|---|---|
\(\grave{x}\) | \grave{x} | \(\grave{xy}\) | \grave{xy} | |
\(\tilde{\alpha}\) | \tilde{\alpha} | \(\tilde{\alpha\beta}\) | \tilde{\alpha\beta} | |
\(\vec{x}_i\) | \vec{x}_i | \(\vec{x_i}\) | \vec{x_i} |
PuLP provides several options for choosing a solver. By default, tex2solver assumes the use of the solver that is packaged with PuLP. However, one of the powerful features of PuLP is that it allows the user to choose from several different solvers. Details on available solvers may be found in the PuLP documentation at https://coin-or.github.io/pulp/technical/solvers.html.