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

Doc improvement - Extending and restructuring of the doc tutorials #431

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Build dirs.
build*
*build*

# Temp files.
*~
*.bak
.DS_Store
\.idea/

# .orig files from patch.
*.orig
Expand All @@ -24,4 +25,4 @@ doc/doxygen/xml/*
doc/doxygen/Doxyfile
doc/sphinx/conf.py

doc/sphinx/_build
doc/sphinx/_build
2 changes: 2 additions & 0 deletions doc/sphinx/docs/cpp/cpp_docs.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _cpp_api_documentation:

C++ API documentation
=====================

Expand Down
1 change: 1 addition & 0 deletions doc/sphinx/docs/cpp/problems/hock_schittkowsky_71.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.. _hock_schittkowsky:
Hock Schittkowsky No.71
=======================

Expand Down
60 changes: 56 additions & 4 deletions doc/sphinx/docs/cpp/tutorials/cpp_tut.rst
Original file line number Diff line number Diff line change
@@ -1,18 +1,70 @@
.. _tutorial:

Introduction
============
pagmo is a C++ scientific library to *perform parallel optimizations*.
pagmo is **not** a framework for forecasting, clustering, predictions etc.

Applicable optimization problems arise in most quantitative disciplines, such as:

- computer science (e.g. mapping and scheduling for hard-real-time systems, scheduling in networking)
- engineering (e.g. )
- finance (e.g. asset pricing, portfolio optimization)
- economics (e.g. utility maximization problem, expenditure minimization problem)
- operations research (e.g. Cutting stock problem, floorplanning, traveling salesman problem, staffing, job shop problem)
- physics (e.g. )


Some problems are applicable to several of these domains, for example the more general bin packing problem is
applicable to computer science (scheduling in real-time systems and networks) and operations research
(staffing, job shop problems).
The general aim in all these fields is to minimize or maximize a given function, i.e. we need to find the inputs to a
function that result in the best output of the function.

Ideally one always wants to find the optimal solution for a given problem. However, this is often not feasible as
the time required to solve optimization problems can grow exponentially with the size of the problem.
In order to tackle these challenges we use heuristics and metaheuristics that find approximate solutions.
Additionally, by using parallelism we can solve problems even faster or find better solutions.

This is where pagmo comes in. It provides you with among others a collection of solvers and a framework to
solve optimization problems in parallel. This way you can for example test a set of solvers on your specific problem.
An overview of solvers and other capabilities can be found :ref:`here <capabilities>`.

In this tutorial we explain the basics of pagmo and detail more advanced usecases.

C++ tutorial
============

.. toctree::
:maxdepth: 1

cpp_tut_preliminaries


First Problem
^^^^^^^^^^^^^

.. toctree::
:maxdepth: 1

cpp_tut_first_problem
cpp_tut_first_problem_solving
cpp_tut_first_problem_parallel
cpp_tut_next_steps


Basics
^^^^^^
Additional Problems
^^^^^^^^^^^^^^^^^^^

.. toctree::
:maxdepth: 2
:maxdepth: 1

cpp_tut_bin_packing

Advanced Topics
^^^^^^^^^^^^^^^

.. toctree::
:maxdepth: 1

evolving_a_population
cpp_tut_implement_optimizer
137 changes: 137 additions & 0 deletions doc/sphinx/docs/cpp/tutorials/cpp_tut_bin_packing.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
.. _cpp_tut_bin_packing:

Bin Packing
===========

In the original bin packing problem (*bpp*) one has to *pack* items of different volume/size into a finite number of containers or bins.
The aim is to minimze the number of containers that have to be used. This is a NP-hard problem.

Since then bin packing has been extended in many different ways: 2D bin packing, 3D bin packing, packing by weight or cost etc.
Problems similar to bin packing or application of bpp can be found in many different domains (computer science, logistic, job shop scheduling etc.).
Thus, it is still a very relevant problem with several new solvers being applied/tested/introduced every year
(Feng et al. "*An Enhanced Grasshopper Optimization Algorithm to the Bin Packing Problem*";
Abdel-Basset et al. "*An improved nature inspired meta-heuristic algorithm for 1-D bin packing problem*").

Here we consider a 1D version of bin packing, where we have a set of objects that need to be packed into a set of bins.
All bins have the same size and the aim is to minimize the number of bins used. The different items can be of different size.
An example of items are shown in the figure below. The total size of all items is 18.5.

.. image:: ../../images/bin_packing/bin_packing_items.png

These items have to fit into into six containers. Each container is of size 7, i.e. there is enough space for all items.
A solution minimizing the number of used bins could look like this:

.. image:: ../../images/bin_packing/bin_packing_solution.png

Other solutions using the same number of bins is also possible.
For a small example the solution is trivial and can easily be made by hand.
Lets see how we can solve this problem using pagmo, so that we can also solve non-trivial versions of this problem.

Problem Definition
------------------

For the bin packing problem we need to know 4 things.

- How many bins are there?
- How large are the bins?
- How many items are there?
- How large are the items?

The bounds and constraints are fairly straightforwards. All items have to be packed into one of the bins, i.e. between 0 and *max_bin_num - 1*.
The sum of the items in a bin cannot be larger than the size of the bins.

Just like in the :ref:`First Problem<cpp_tut_first_problem>` we have to implement 4 functions:

- ``fitness()``
- ``get_bounds()``
- ``get_nic()``
- ``get_nix()``

Lets start with the fitness function. As an input it receives a vector of possible item mappings, i.e. a possible solution.
For this solution it then computes the fitness, which in this case is the number of bins used.
The computed fitness value is then stored in a return vector.

After the fitness value we need to compute if the constraints are met, i.e. is there enough space left in the bins.
For this we loop over all bins and all items and compute the usage of each bin. For each bin we add an entry to the
return vector which represents the inequality. Each inequality number has to be smaller or equal to 0.

.. code-block:: c++

// Implementation of the objective function and all constraints
pagmo::vector_double fitness(const pagmo::vector_double &x_i) const {
// variables
double num_bins_used = 0; //how many bins are used
std::vector<int> bin_used(num_bins, 0);

// where x_i is the bin in which an item i is placed
// determine if a bin is used based on x_i
for (int i = 0; i < num_items; ++i) {
for (int j = 0; j < num_bins; ++j) {
if (x_i[i] == j){
bin_used[j] = 1;
}
}
}

// Objective function calculation; i.e. how many bins are used? We want to minimize this!
for(auto& y: bin_used){
num_bins_used += y;
}

// Make return vector and adding objective
pagmo::vector_double return_vector{num_bins_used};

// Adding inequalities to stick to the maximum size of the bin
for (int j = 0; j < num_bins; ++j) {
int temp_bin_occupation = 0;
for (int i = 0; i < num_items; ++i) {
if (x_i[i] == j){
temp_bin_occupation += items[i] ; // <= 0
}
}
return_vector.emplace_back(temp_bin_occupation - size_bins);
}
return return_vector;
}

Besides the fitness and the constraints we need to make sure that the bounds are also correct. We do not want that the
genetic algorithm starts packing items into a non existent bins. Therefore, the ``get_bounds()`` function returns the
lower and upper bound for each item. In our case the lower bound is 0 (i.e. Bin 1) and the upper bound is number of bins - 1.

.. code-block:: c++

// The lower and upper bounds are the bins in which an item can be placed.
std::pair<pagmo::vector_double, pagmo::vector_double> get_bounds() const {
std::vector<double> lower(num_items, 0);
std::vector<double> upper(num_items, num_bins-1);
return {lower, upper};
}

The ``get_nix()`` function returns the integer dimension of the problem, i.e. the size of the solution. In this case its given by the number of items.

.. code-block:: c++

// Integer dimension of the problem - i.e. into which bin each item is packed
pagmo::vector_double::size_type get_nix() const {
return pagmo::vector_double::size_type(num_items);
}

Lastly, we need the number of inequalities, which is equal to the number of bins, as we need one inequality per bin.

.. code-block:: c++

// Number of inequality constraints.
pagmo::vector_double::size_type get_nic() const {
return pagmo::vector_double::size_type(num_bins);
}

We can again solve this problem with :ref:gaco or :ref:ihs.
Combining the problem definition plus soliving it with gaco or ihs results in the following code.

.. literalinclude:: ../../../../../tutorials/problem_bin_packing.cpp
:caption: problem_bin_packing.cpp
:language: c++
:linenos:

Solving the problem with either ihs or gaco will result in a solution that occupies 3 bins, i.e. finding an optimal solution.

34 changes: 18 additions & 16 deletions doc/sphinx/docs/cpp/tutorials/cpp_tut_first_problem.rst
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
Writing your first optimisation problem
.. _cpp_tut_first_problem:

Writing your first optimization problem
=======================================

A fundamental requirement of any optimisation
library is the ability to represent an optimisation
A fundamental requirement of any optimization
library is the ability to represent an optimization
problem to be solved. In this section, our
goal is to show how this is done in pagmo.

A simple problem
----------------

We will be considering the minimisation of
the multidimensional objective function
We will be considering the minimization of
the multidimensional objective function (:ref:`Hock Schittkowsky No.71 <hock_schittkowsky>`)

.. math::

Expand All @@ -31,7 +33,7 @@ and to the constraints
25 - x_1 x_2 x_3 x_4 &\le 0.
\end{align}

In pagmo's taxonomy, this optimisation problem is
In pagmo's taxonomy, this optimization problem is

* *continuous* (because :math:`x_{1,2,3,4}` are real variables),
* *deterministic* (as neither the objectives nor the constraints depend
Expand All @@ -56,7 +58,7 @@ the constraints at a later stage.
The bare necessities
--------------------

In pagmo, an optimisation problem must provide
In pagmo, an optimization problem must provide
at the very least an objective function and
the box bounds. Let's see how this is done
for our simple example problem:
Expand All @@ -75,7 +77,7 @@ After the inclusion of the necessary header files, and a helpful
using namespace pagmo;

to reduce typing, we reach the definition
of our optimisation
of our optimization
problem via a class called ``problem_v0``. As explained
in the :ref:`section about type erasure <cpp_tut_type_erasure>`,
this class does not need to derive from any base class.
Expand All @@ -98,7 +100,7 @@ it is used to return not only the value of the objective function,
but also of the constraints (thus in some sense it computes the
overall "fitness"
of the input decision vector). In this specific case, however,
our optimisation problem does not have constraints yet,
our optimization problem does not have constraints yet,
and thus the ``fitness()`` implementation just returns
a vector of size 1 whose only element is the value
of the (single) objective function:
Expand Down Expand Up @@ -130,7 +132,7 @@ via the sizes of the returned lower/upper bounds vectors
Meet pagmo::problem
-------------------

After the definition of our optimisation problem, ``problem_v0``,
After the definition of our optimization problem, ``problem_v0``,
we encounter the ``main()`` function. In the ``main()``, the first
thing we do is to construct a :cpp:class:`pagmo::problem` from an
instance of ``problem_v0``:
Expand All @@ -140,12 +142,12 @@ instance of ``problem_v0``:
problem p{problem_v0{}};

:cpp:class:`pagmo::problem` is pagmo's
:ref:`type-erased <cpp_tut_type_erasure>` interface to optimisation
:ref:`type-erased <cpp_tut_type_erasure>` interface to optimization
problems. It is a generic container which can store internally
an instance of any class which "acts like" an optimisation problem,
an instance of any class which "acts like" an optimization problem,
that is, any class which provides (at least) the two member functions
described earlier (``fitness()`` and ``get_bounds()``). In the pagmo
jargon, we refer to classes which "act like" optimisation problems
jargon, we refer to classes which "act like" optimization problems
as *user-defined problems*, or UDPs.

In addition to storing a UDP (which, by itself, would not be
Expand Down Expand Up @@ -201,11 +203,11 @@ summary that may look like this:

Quite a mouthful! Do not worry about deciphering this
output right now, as we will examine the more intricate
aspects of the definition of an optimisation problem in due time.
aspects of the definition of an optimization problem in due time.

For now, let us just point out that, from our simple
UDP definition, pagmo was able to infer
on its own various properties of the optimisation problem
on its own various properties of the optimization problem
(e.g., the problem dimension, the number of objectives,
the absence of constraints, etc.). pagmo is able to do this
thanks to both introspection capabilities (based on template
Expand All @@ -229,7 +231,7 @@ Let us see the code:
:diff: ../../../../../tutorials/first_udp_ver0.cpp

In order to specify the type and number of constraints in our
optimisation problem, we have to implement the two member
optimization problem, we have to implement the two member
functions ``get_nec()``, which returns the number of equality
constraints, and ``get_nic()``, which returns the number of
inequality constraints:
Expand Down
Loading