Skip to content
Snippets Groups Projects
Commit 03581d0a authored by Mathias Berger's avatar Mathias Berger
Browse files

Added docs, temporary update to README (license).

parent a90c297e
No related branches found
No related tags found
No related merge requests found
Showing
with 1725 additions and 4 deletions
......@@ -22,4 +22,4 @@ speedtest.py
try_files/
examples/example1.json
src/gboml.egg-info/
src/gboml.egg-info/
\ No newline at end of file
......@@ -49,6 +49,4 @@ An early version of the GBOML framework was introduced in [a recent paper](https
## License
Copyright since 2020 Bardhyl Miftari, Mathias Berger, Hatim Djelassi, Damien Ernst, University of Liege
ADD LICENSE
Copyright since 2020 Bardhyl Miftari, Mathias Berger, Hatim Djelassi, Damien Ernst, University of Liege. All rights reserved.
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd
sphinx
sphinx-rtd-theme
docutils==0.16
About GBOML
-----------
The Graph-Based Optimization Modeling Language (GBOML) is a modeling language for mathematical programming designed and implemented at the University of Liège, Belgium. GBOML enables the easy implementation of a broad class of structured mixed-integer linear programs typically found in applications ranging from energy system planning to supply chain management. More precisely, the language is particularly well-suited for representing problems involving the optimization of discrete-time dynamical systems over a finite time horizon and possessing a block structure that can be encoded by a hierarchical hypergraph. The language combines elements of both algebraic and object-oriented modeling languages in order to facilitate problem encoding and model re-use, speed up model generation, expose problem structure to specialised solvers and simplify post-processing. The GBOML parser, which is implemented in Python, turns GBOML input files into hierarchical graph data structures representing optimization models. The associated tool provides both a command-line interface and a Python API to construct models, and directly interfaces with a variety of open source and commercial solvers, including structure-exploiting ones.
docs/source/abstract_problem.png

101 KiB

Abstract GBOML problem
======================
The modeling language is particularly well-suited for representing problems involving the optimization of discrete-time dynamical systems over a finite time horizon and exhibiting a natural block structure that may be encoded by a hierarchical hypergraph. A hypergraph abstraction is therefore employed to represent them. Nodes can therefore be viewed as hierarchical hypergraphs themselves representing optimization subproblems, while hyperedges express the relationships between nodes. A global discretized time horizon and associated set of time periods common to all nodes are also defined. Each node is equipped with a set of so-called *internal* and *external* (or *coupling*) variables. A set of constraints may be also defined for each node, along with a local objective function representing its contribution to a system-wide objective. Finally, for each hyperedge, constraints involving the coupling variables of the nodes to which it is incident are defined in order to express the relationships between nodes. In the following paragraphs, we formally define variables, constraints, objectives and formulate the abstract model that encapsulates the class of problems considered. For the sake of clarity, we do so for a model that can be represented by a hypergraph with a single *layer* (i.e., there is one level in the hierarchy).
Let :math:`\mathcal{G} = (\mathcal{N}, \mathcal{E})` be a (possibly directed) hypergraph encoding the block structure of the problem at hand, with node set :math:`\mathcal{N}` and hyperedge set :math:`\mathcal{E} \subseteq 2^\mathcal{N}` (i.e., each hyperedge corresponds to a subset of nodes), let :math:`T` be the time horizon considered and let :math:`\mathcal{T} = \{0, 1, \dots, T - 1\}` be the associated set of time periods. Let :math:`X^n \in \mathcal{X}^n` and :math:`Z^n \in \mathcal{Z}^n` denote the collection of internal and coupling variables defined at node :math:`n \in \mathcal{N}`. Note that variables may take values in discrete or continuous sets. In addition, for any hyperedge :math:`e \in \mathcal{E}`, let :math:`Z^e = \{Z^n | n \in e\}` denote the collection of coupling variables associated with each node to which this hyperedge is incident.
Let :math:`F^n` denote the function defining the local objective at node :math:`n \in \mathcal{N}`. In this paper, we consider scalar objectives of the form
.. math::
F^n(X^n, Z^n) = f_0^n(X^n, Z^n) + \sum_{t \in \mathcal{T}} f^n(X^n, Z^n, t),
where :math:`f_0^n` and :math:`f^n` are (scalar) affine functions of :math:`X^n` and :math:`Z^n`.
Both equality and inequality constraints may be defined at each node :math:`n \in \mathcal{N}`. More precisely, an arbitrary number of constraints that can each be expanded over a subset of time periods may be defined. Hence, we consider equality constraints of the form
.. math::
h_k^n(X^n, Z^n, t) = 0, \mbox{ } \forall t \in \mathcal{T}_k^n
with (scalar) affine functions :math:`h_k^n` and index sets :math:`\mathcal{T}_k^n \subseteq \mathcal{T}`, :math:`k = 1, \ldots, K^n`, as well as inequality constraints
.. math::
g_k^n(X^n, Z^n, t) \le 0, \mbox{ } \forall t \in \bar{\mathcal{T}}_k^n,
with (scalar) affine functions :math:`g_k^n` and index sets :math:`\bar{\mathcal{T}}_k^n \subseteq \mathcal{T}`, :math:`k = 1, \ldots, \bar{K}^n`.
Likewise, both equality and inequality constraints may be defined over any hyperedge :math:`e \in \mathcal{E}`. These constraints, however, can only involve the coupling variables of the nodes to which hyperedge :math:`e \in \mathcal{E}` is incident (i.e., nodes such that :math:`n \in e`). More precisely, let :math:`H^e` and :math:`G^e` be affine functions of :math:`Z^e` used to define the equality and inequality constraints associated with a given hyperedge :math:`e\in\mathcal{E}`.
Using this notation, the class of problems that can be represented in this framework reads
.. math::
\begin{array}{rl}
\min & \sum_{n \in \mathcal{N}} F^n(X^n, Z^n) \\
\hbox{s.t.} & h_k^n(X^n, Z^n, t) = 0, \mbox{ } \forall t \in \mathcal{T}_k^n, \hspace{2pt} k = 1, \ldots K^n, \hspace{2pt} \forall n \in \mathcal{N} \\
& g_k^n(X^n, Z^n, t) \le 0, \mbox{ } \forall t \in \bar{\mathcal{T}}_k^n, \hspace{2pt} k = 1, \ldots \bar{K}^n, \hspace{2pt} \forall n \in \mathcal{N} \\
& H^e(Z^e) = 0, \hspace{2pt} \forall e \in \mathcal{E} \\
& G^e(Z^e) \le 0, \hspace{2pt} \forall e \in \mathcal{E} \\
& X^n \in \mathcal{X}^n, Z^n \in \mathcal{Z}^n, \hspace{2pt} \forall n \in \mathcal{N}.
\end{array}
:numref:`abstract_problem` schematically illustrates the class of problems that can be modelled in this framework.
.. figure:: ./abstract_problem.png
:name: abstract_problem
:align: center
:alt: abstract GBOML problem
Schematic representation of the abstract GBOML problem.
Advanced Features
-----------------
Advanced features include hierarchical model definitions and imports.
These features are discussed in the following sections:
.. toctree::
:maxdepth: 4
./hierarchical_models.rst
./importing_components.rst
Block Definitions
-----------------
In order to implement an instance of the abstract GBOML problem, the model must be encoded in an input file written in the GBOML grammar.
This input file is structured into blocks, which are introduced by one of the following keywords, namely :math:`\texttt{#TIMEHORIZON}`, :math:`\texttt{#GLOBAL}`, :math:`\texttt{#NODE}`, and :math:`\texttt{#HYPEREDGE}`. The time horizon information is given in the :math:`\texttt{#TIMEHORIZON}` block, which must be the first one defined in the input file. Global parameters must be defined in the :math:`\texttt{#GLOBAL}` block, which must come in second position. Then, each node can be defined in a :math:`\texttt{#NODE}` block, while each hyperedge can be defined in a :math:`\texttt{#HYPEREDGE}` block. Note that the order in which :math:`\texttt{#NODE}` and :math:`\texttt{#HYPEREDGE}` blocks appear in the input file does not matter (i.e., hyperedge definitions may precede node definitions and vice-versa). Thus, an input file is typically structured as follows:
.. code-block:: c
#TIMEHORIZON
// time horizon definition
#GLOBAL
// global parameters
#NODE <identifier>
// first node definition
#NODE <identifier>
// second node definition
#HYPEREDGE <identifier>
// first hyperedge definition
// possibly further node blocks
#HYPEREDGE <identifier>
// second hyperedge definition
// possibly further hyperedge blocks
These different blocks are further discussed in this section:
.. toctree::
:maxdepth: 4
./time_horizon.rst
./global_parameters.rst
./nodes.rst
./hyperedges.rst
Citing GBOML
------------
An early version of the GBOML framework was introduced in `a recent paper <https://www.frontiersin.org/articles/10.3389/fenrg.2021.671279/full>`_. GBOML has also been submitted for review to the Journal of Open Source Software.
Command Line Interface
----------------------
The GBOML parser can be called from the command line by typing the following commands in a terminal window:
.. code-block:: bash
gboml <file> <options>
where :math:`\texttt{<file>}` is the name of the file to be considered and :math:`\texttt{<options>}` corresponds to one or several optional flags that can be activated.
The options are the following :
* *Print tokens*: the tokens output by the lexer can be printed with:
.. code-block:: bash
--lex
* *Print the syntax tree*: the syntax tree generated by the parser can be printed with:
.. code-block:: bash
--parser
* *Print the matrices*: the coefficient, right-hand side and objective matrices and vectors can be printed with:
.. code-block:: bash
--matrix
* *Linprog*: the linprog solver can be used with:
.. code-block:: bash
--linprog
The `linprog <https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.linprog.html>`_ solver for (continuous) linear programming comes with scipy and therefore does not require any installation or license. It is much less powerful than other solver options
and is therefore only recommended for testing purposes (e.g., make sure that GBOML was properly installed).
* *Gurobi*: Gurobi can be invoked with:
.. code-block:: bash
--gurobi
* *CPLEX*: CPLEX can be used with:
.. code-block:: bash
--cplex
* *Xpress*: Xpress can be used with:
.. code-block:: bash
--xpress
* *Cbc/Clp*: Cbc/Clp can be used with:
.. code-block:: bash
--clp
* *DSP Dantzig-Wolfe*: the DSP implementation (experimental) of the Dantzig-Wolfe algorithm can be invoked with:
.. code-block:: bash
--dsp_dw
* *DSP Extensive form*: the DSP Extensive Form (i.e., flattened model) algorithm can be used with:
.. code-block:: bash
--dsp_de
* *Solver option parameters*: solver parameters can be set via a ".opt" file with:
.. code-block:: bash
--opt opt_file
where :math:`\texttt{<opt_file>}` is the name of the file containing the solver parameters. If no parameters are provided, the default solver parameters are used.
* *CSV*: the solution can be printed to a CSV file on a row basis (e.g., one variable per row):
.. code-block:: bash
--csv
* *Transposed CSV*: the solution can be printed to a CSV file on a column basis (e.g., one variable per column):
.. code-block:: bash
--transposed_csv
* *JSON*: the solution can be printed to a JSON file with:
.. code-block:: bash
--json
* *Detailed JSON*: the solution provided by the solver along with auxiliary information (e.g., dual variables, slacks or basis ranges) can be printed to a JSON file with:
.. code-block:: bash
--detailed_json
* *Multi-processing*: the number of processes used for model generation can be controlled via:
.. code-block:: bash
--nb_processes <number>
where :math:`\texttt{<number>}` is an integer, whose default value is 1.
* *Output*: the name of the output file can be defined with:
.. code-block:: bash
--output <output_filename>
where :math:`\texttt{<output_filename>}` is the output filename without the extension (CSV or JSON). The default output name is the name of the GBOML file with the date and chosen extension.
Comments
========
Comments are initiated by a double forward slash :math:`\texttt{//}` and terminated by a line feed. The content that follows is ignored by the compiler.
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
#html_theme = 'alabaster'
numfig = True
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
#html_static_path = ['_static']
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'The Graph-Based Modeling Language'
copyright = '2021-2022, Bardhyl Miftari, Mathias Berger, Hatim Djelassi, Damien Ernst, University of Liege'
author = 'Bardhyl Miftari, Mathias Berger, Hatim Djelassi'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
napoleon_custom_sections = [('Returns', 'params_style')]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
#latex_documents = []
enable_pdf_build=False
enable_epub_build=False
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
#html_theme = 'alabaster'
numfig = True
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
#html_static_path = ['_static']
Examples
========
This section describes three examples. The first example deals with a microgrid system design problem and illustrates the basic features of GBOML.
The second example is more sophisticated and focuses on a remote carbon-neutral fuel supply chain planning problem.
Finally, the third example is based on a hypothetical problem and illustrates the Python API.
.. toctree::
:maxdepth: 3
./microgrid_example.rst
./remote_hub_example.rst
./python_api_example.rst
Expressions
===========
Algebraic expressions are used to construct the different components of a model, such as its constraints and objective. Expressions typically involve numbers and identifiers referring to parameters and variables, along with some of the operators introduced previously.
While numbers are always scalar, variables and parameters may be either scalars or vectors (of any length). Their entries are accessed via an index written in brackets :math:`\texttt{[}` and :math:`\texttt{]}`. For the sake of illustration, let :math:`\texttt{v}` be an identifier referring to a vector quantity of length :math:`\texttt{L}`. Then, the entries of :math:`\texttt{v}` are accessed via
.. math::
\texttt{v[0]}, \qquad \texttt{v[1]}, \qquad \texttt{v[2]}, \qquad \dots, \qquad \texttt{v[L-1]}.
Note that the first index is :math:`\texttt{0}` and not :math:`\texttt{1}`.
Let :math:`\texttt{x}` and :math:`\texttt{v}` be the identifiers of a scalar quantity and a vector quantity, respectively. Then, the following expressions are valid in GBOML:
.. math::
\texttt{x**2 - 6.5*x - 9}, \qquad \texttt{sum((i - 2.5)/3 for i in [0:10])}, \qquad \texttt{v[0] + v[mod(3,2)]}
Note that the above expressions contain whitespace characters, which are not required. Indeed, all kinds of whitespace characters (space, tabulation, line feed, form feed, and carriage return) are ignored by the GBOML compiler.
from .gboml_graph import GbomlGraph
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
Global Parameters
=================
The non-mandatory :math:`\texttt{#GLOBAL}` block contains the definitions of parameters that can be accessed anywhere in the model. This block is structured as follows:
.. code-block:: c
#GLOBAL
// global parameter definitions
A parameter definition maps an identifier to a fixed value, which may be either a scalar or a vector. The identifier must be unique within a given :math:`\texttt{#GLOBAL}` block and a value can be assigned to a parameter through one of the following three syntax rules:
.. code-block:: c
< identifier > = < expression >;
< identifier > = { < term > , < term > ,...};
< identifier > = import " < filename >";
First, a scalar parameter is defined according to the first rule. Therein, :math:`\texttt{<expression>}` may be a scalar expression that evaluates to any floating-point number. In particular, it may contain global parameters that have been defined previously. If the parameter definition is valid with respect to these rules, a parameter named :math:`\texttt{<identifier>}` will be created and assigned the value of :math:`\texttt{<expression>}`.
Second, a vector parameter can be defined directly by providing a comma-separated list of values according to the second rule. Therein, each :math:`\texttt{<term>}` may be a floating-point number, a previously-defined scalar parameter, or an entry of a previously-defined vector parameter. The resulting vector parameter can be indexed in order to retrieve its constituent entries.
Third, a vector parameter can be defined by providing an input file according to the third rule. Therein, :math:`\texttt{<filename>}` refers to an input file in one of several delimiter-separated formats. The supported delimiter characters are comma, semicolon, space, and line feed. In contrast to the direct way of defining a vector parameter, the input file may only contain floating-point values and may not refer to other parameters.
Given these syntax rules, the following is an example of a valid :math:`\texttt{#GLOBAL}` block:
.. code-block:: c
#GLOBAL
pi = 3.1416;
two_pi = 2* pi ;
data = import " data . csv ";
len_data = 23;
angles = {0 , data [2] , two_pi };
sum_data = sum ( data [ i ] for i in [0: len_data -1]) ;
Notably, the example makes use of the fact that previously-defined parameters can be employed to define new parameters. Furthermore, the parameters defined in this block can be accessed in any other block by referring to their identifier with the prefix :math:`\texttt{global}`. In other words, all global parameters are referred to as:
.. math::
\texttt{global.<parameter identifier>}
in the blocks that follow their definition.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment