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

Update solver_internals.rst #172

Merged
merged 1 commit into from
Nov 20, 2023
Merged
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
56 changes: 28 additions & 28 deletions docs/source/basis/solver_internals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ Solver internals and tips

.. include:: ../substitutions.sub

Kiwi is not a simple re-writing of Cassowary and because of that Kiwi does not
always perfectly reflects the original implementation. The following sections
points out those "discrepancies" and give some tips on how to work with
Kiwi.

Kiwi is not a mere rewriting of Cassowary, and due to this, it does not always
perfectly reflect the original implementation. The following sections point out
these discrepancies and provide tips on how to work effectively with Kiwi.


Inspecting the solver state
---------------------------

The state of the solver can be inspected by dumping a text representation of
its state either to stdout using the ``dump`` method of the solver, or to a
string using the ``dumps`` method. Typically at least a basic understanding of
string using the ``dumps`` method. Typically, at least a basic understanding of
the Cassowary algorithm is necessary to analyse the output.

A typical output is reproduced below:
Expand Down Expand Up @@ -59,7 +59,7 @@ A typical output is reproduced below:

In the dump, the letters have the following meaning:

- v: external variable, corresponds to the variable created by you the user
- v: external variable, corresponds to the variable created by you, the user
- s: slack symbol, used to represent inequalities
- e: error symbol, used to represent non-required constraints
- d: dummy variable, always zero, used to keep track of the impact of an
Expand All @@ -77,7 +77,7 @@ non-modified variable close to their original position. A typical example is
a rectangle whose one corner is being dragged in a drawing application.

Kiwi does not have stay constraints mostly because in the context of widget
placement the system is usually well constrained and stay constraints are hence
placement, the system is typically well constrained, rendering stay constraints
unnecessary.

If your application requires them, several workarounds can be considered:
Expand All @@ -92,18 +92,18 @@ stop making sense, while the second will require to update the suggested value.
Creating strengths and their internal representation
----------------------------------------------------

Kiwi provides three strengths in addition of the required strength by default:
"weak", "medium", "strong". Contrary to Cassowary, which uses lexicographic
Kiwi provides three strengths in addition to the required strength by default:
"weak", "medium", and "strong". Contrary to Cassowary, which uses lexicographic
ordering to ensure that strength are always respected, Kiwi strives for speed
and use simple floating point numbers.
and uses simple floating point numbers.

.. note::

Using simple floating point, means that is some rare corner case a large
number of weak constraints may overcome a medium constraint. However in
practice this rarely happens.
Using simple floating point, means that in some rare corner cases, a large
number of weak constraints may outweigh a medium constraint. However, in
practice, this rarely happens.

Kiwi allows to create custom strength in the following manner:
Kiwi allows to create custom strengths in the following manner:

.. tabs::

Expand All @@ -121,7 +121,7 @@ Kiwi allows to create custom strength in the following manner:

The first argument is multiplied by 1 000 000, the second argument by 1 000,
and the third by 1. No strength can be create larger than the required
strength. The default strengths in Kiwi corresponds to:
strength. The default strengths in Kiwi correspond to:

.. code:: python

Expand All @@ -130,14 +130,14 @@ strength. The default strengths in Kiwi corresponds to:
strong = strength.create(1, 0, 0)
required = strength.create(1000, 1000, 1000)

While Cassowary differentiate between strength and weight, those two concepts
are fused in Kiwi: when creating a strength one can apply a weight (the fourth
While Cassowary differentiates between strength and weight, those two concepts
are fused in Kiwi: when creating a strength, one can apply a weight (the fourth
argument) that will multiply it.

.. note::

Because strengths are implemented as floating point number, in order to be
effective strengths must be different enough from one another. The
Because strengths are implemented as floating point numbers, in order to be
effective, strengths must be different enough from one another. The
following is unlikely to produce any really useful result.

.. code:: python
Expand All @@ -151,13 +151,13 @@ Managing memory
---------------

When removing a constraint, Kiwi does not check whether or not the variables
used in the constraints are still in use in other constraints. This is mostly
because such checks could be quite expensive. However this means the map of
used in the constraint are still in use in other constraints. This is mostly
because such checks could be quite expensive. However, this means the map of
variables can grow over time.

To avoid this causing large memory leaks, it is recommended to reset the solver
state (using the method of the same name) and add back the constraints that
are still valid at this point.
To avoid this possibly causing large memory leaks, it is recommended to reset
the solver state (using the method of the same name) and to add back the
constraints, that are still valid at this point.


Representation of constraints
Expand All @@ -179,18 +179,18 @@ Map type
^^^^^^^^

Kiwi uses maps to represent the state of the solver and to manipulate it. As a
consequence the map type should be fast, with a particular emphasis on
consequence, the map type should be fast, with a particular emphasis on
iteration. The C++ standard library provides unordered_map and map that could
be used in kiwi, but none of those are very friendly to the CPU cache. For
this reason, Kiwi uses the AssocVector class implemented in Loki (slightly
updated to respect c++11 standards). The use of this class provides a 2x
speedups over std::map.
speedup over std::map.


Symbol representation
^^^^^^^^^^^^^^^^^^^^^

Symbol are used in Kiwi to represent the state of the solver. Since solving the
system requires a large number of manipulation of the symbols the operations
Symbols are used in Kiwi to represent the state of the solver. Since solving the
system requires a large number of manipulations of the symbols, the operations
have to compile down to an efficient representation. In Kiwi, symbols compile
down to long long meaning that a vector of them fits in a CPU cache line.