Comparisons – Random IT Utensils https://blog.adamfurmanek.pl IT, operating systems, maths, and more. Sat, 02 Jan 2021 18:45:20 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.2 ILP Part 33 — Lexicographical comparisons https://blog.adamfurmanek.pl/2016/11/26/ilp-part-33/ https://blog.adamfurmanek.pl/2016/11/26/ilp-part-33/#comments Sat, 26 Nov 2016 09:00:02 +0000 https://blog.adamfurmanek.pl/?p=1890 Continue reading ILP Part 33 — Lexicographical comparisons]]>

This is the thirty third part of the ILP series. For your convenience you can find other parts in the table of contents in Part 1 – Boolean algebra

Hi. Today we are going to implement lexicographical comparisons using ILP. Let’s begin!

Introduction

Let’s assume that we want to solve the following:

    \begin{gather*} a_0, a_1, \ldots, a_n \in \mathbb{Z} \\ b_0, b_1, \ldots, b_n \in \mathbb{Z} \\ A = \{a_0, \ldots, a_n\}, B = \{b_0, \ldots, b_n\} \\ x = A \stackrel{?}{<} B\\ \end{gather*}

So we have two vectors of integer variables and we want to answer the question whether A is less than B. We define “less than” here in usual way, e.g., whether there exists 0 \le i \le n for which \forall_{j=0}^{j-1} a_j = b_j and a_i < b_i.

Naive implementation

We could implement this naively, e.g., perform all necessary comparisons and come up with the solution using conditions:

    \begin{gather*} x = (a_0 < b_0) \vee (a_0 = b_0 \wedge a_1 < b_1) \vee (a_0 = b_0 \wedge a_1 = b_1 \wedge a_2 < b_2) \vee \ldots \end{gather*}

This is slow and inefficient. For k elements in vector we have k clauses and each clause contains up to k conditions which sums up to O(n^2) conditions. We can do better.

Better implementation using hashing

We can perform faster comparison using hashes. First, let’s assume that we can operate on numbers up to 2^{30} and that for now n \le 29. We can do the following:

    \begin{gather*} y = (a_0 \stackrel{?}{>=} b_0 - a_0 \stackrel{?}{<=} b_0) \cdot 2^{n} + (a_1 \stackrel{?}{>=} b_1 - a_1 \stackrel{?}{<=} b_1) \cdot 2^{n-1} + (a_2 \stackrel{?}{>=} b_2 - a_2 \stackrel{?}{<=} b_2) \cdot 2^{n-2} + \ldots + (a_n \stackrel{?}{>=} b_n - a_n \stackrel{?}{<=} b_n) \cdot 2^{0} \\ x = y \stackrel{?}{<} 0 \end{gather*}

OK, some black magic. Let’s untangle it.

We compare each pair of vectors’ elements. For every pair we ask whether element from vector A is greater or equal than element in vector B and subtract flag whether it is less or equal. This results in extended binary solution (minus one or zero or one). Next, we multiply this binary flag by some constant power of two. We want to do it in a way which allows us to come out with final solution just by checking the sign of the sum.

Let’s see a simple example for the following data:

    \begin{gather*} A = \{ 5, 2, 4 \} \\ B = \{ 5, 4, 4 \} \\ y = (5 \stackrel{?}{>=} 5 - 5 \stackrel{?}{<=} 5)\cdot 2^{2} + (2 \stackrel{?}{>=} 4 - 2 \stackrel{?}{<=} 4)\cdot 2^{1} + \\ +(4 \stackrel{?}{>=} 4 - 4 \stackrel{?}{<=} 4)\cdot 2^{0} = (1-1) \cdot 4 + (0 - 1) \cdot 2 + (1 - 1) \cdot 1 = 0 - 2 + 0 = -2\\ x = y \stackrel{?}{<} 0 = 1 \end{gather*}

The idea here is: for every element we want to have positive positive term when element in vector A is greater than element in vector B, zero term when they are equal, and negative term when element in vector A is less than element in vector B. We achieve this by performing two comparisons: is greater or equal, and is less or equal. In the first case (element in A is greater than element in B), we get 1 - 0 = 1. In second case we get 1 - 1 = 0, in third case we get 0 - 1 = -1.

Next, we want to get just one number representing the whole vector comparison. Since we compare numbers from left to right (see the definition of lexicographical “less than”), we multiply numbers by consecutive powers of two starting from the greatest one so the preceding terms are not “neutralized” by the next ones. Takie this example:

    \begin{gather*} A = \{ 0, 1, 1, 1, 1 \} \\ B = \{ 1, 0, 0, 1, 1 \} \\ y = -16 + 8 + 4 + 2 + 1 = -1 \end{gather*}

Even though only first one element is lower and all the others are greater in vector A than in vector B, the total value is still negative, thanks to powers of two.

How do we perform other comparisons? It is pretty simple:

    \begin{gather*} A \stackrel{?}{>=} B = y \stackrel{?}{>=} 0 \\ A \stackrel{?}{>} B = y \stackrel{?}{>} 0 \\ A \stackrel{?}{<=} B = y \stackrel{?}{<=} 0 \\ A \stackrel{?}{<} B = y \stackrel{?}{<} 0 \\ A \stackrel{?}{=} B = y \stackrel{?}{=} 0 \\ A \stackrel{?}{\neq } B = y \stackrel{?}{\neq} 0 \end{gather*}

Longer vectors

We know how to compare vectors up to 30 elements but how to compare longer ones? Well, the trick is: let’s do the same again.

Imagine that we have vectors with hundreds of elements. We take first 30 elements and compare them lexicographically. We get one number which is negative, positive, or zero. The number represents relation of first 30 elements of A compared lexicographically with first 30 elements of B. We can now take next 30 elements and compare them in the same way. Moving forward we finally get the following vector:

    \begin{gather*} C = \{ c_0, c_1, \ldots, c_p \}, c_0, \ldots, c_p \in \mathbb{Z} \\ p = \left\lfloor \log _{30} n \right \rfloor \end{gather*}

This is another vector representing packages of 30 elements of A compared to B. We can now compare C with vector D = \{ 0, 0, 0, \ldots, 0 \} of the same length.

Why does it work? Well, if first 30 elements of A are lexicographically lower than 30 elements of B, c_0 will be negative so next comparison will still work well since c_0 < 0. If first 30 elements are equal, c_0 = 0 so next batch of 30 elements will have a chance to change the comparison result. If first elements are greater then c_0 > 0 which will determine the result.

We can recursively compare smaller and smaller vectors and finally end with just one number representing the solution. Finally, by comparing its sign we will be able to determine the final result.

Summary

As we can see, we are able to compare vectors much faster with hashing approach than by using naive one.

]]>
https://blog.adamfurmanek.pl/2016/11/26/ilp-part-33/feed/ 1
ILP Part 15 – Basic set operations https://blog.adamfurmanek.pl/2015/11/28/ilp-part-15/ https://blog.adamfurmanek.pl/2015/11/28/ilp-part-15/#comments Sat, 28 Nov 2015 09:00:22 +0000 https://blog.adamfurmanek.pl/?p=1458 Continue reading ILP Part 15 – Basic set operations]]>

This is the fifteenth part of the ILP series. For your convenience you can find other parts in the table of contents in Part 1 – Boolean algebra

Today we are going to use comparisons to implement few basic set operations. Let’s go.

In set, Not in set

We start with In set operation. For set x = \{x_1, x_2, \ldots, x_n \} and value v we want to ask whether v is in set x. This is very easy because all we need to do is compare v with all values from set and calculate the sum:

    \begin{gather*} \displaystyle\mathop{\forall}_{i=1}^{n} b_i = x_i \stackrel{?}{=} v \\ b = \sum_{i=1}^{n} b_i \stackrel{?}{\ge} 1 \end{gather*}

For every value we calculate variable b_i which is true when x_i is equal to v. Next, we sum all values and check whether the sum is positive. If it is true then b is true which means that v is in set x.
For operation Not in set we do almost the same. The only difference is in comparing the sum with 0.

Different values count

Very similar operation is a Different values count. For multiset (e.g., set with repetitions) x = \{x_1, x_2, \ldots, x_n \} we want to ask how many different values does it contain. The formula is as follows:

    \begin{gather*} \displaystyle\mathop{\forall}_{i=1}^{n} d_i = \displaystyle\mathop{\wedge} _{j=i+1}^{n} x_i \stackrel{?}{\neq} x_j \\ d = \sum_{i=1}^{n} d_i \end{gather*}

For every variable x_i we check whether all variables with indexes greater than i are different than x_i. Basically, we traverse multiset x in some arbitrary order and for i-th value we check whether all remaining values are different.

All different

We can use previous formula to make sure that all values in mulitset are different (so the multiset is in fact set). To achieve that we need to calculate different values count d and add constraint d = n where n is a number of variables in a multiset.

Summary

Today we implemented useful set operations. Next time we are going to utilize all ILP knowledge to solve real problem — we will be solving a simple cube riddle.

]]>
https://blog.adamfurmanek.pl/2015/11/28/ilp-part-15/feed/ 2
ILP Part 14 – Comparing real numbers https://blog.adamfurmanek.pl/2015/11/21/ilp-part-14/ https://blog.adamfurmanek.pl/2015/11/21/ilp-part-14/#comments Sat, 21 Nov 2015 09:00:10 +0000 https://blog.adamfurmanek.pl/?p=1448 Continue reading ILP Part 14 – Comparing real numbers]]>

This is the fourteenth part of the ILP series. For your convenience you can find other parts in the table of contents in Part 1 – Boolean algebra

We already know how to compare integer values and today we are going to extend this method to be able to compare real numbers.

Introduction

Comparing real numbers is a bit tricky. We need to remember that computers usually implement non-integer values using IEEE floating point representation. This means that they are not able to store any real number in a specified range but only some of them. What’s more, most popular format for interchanging ILP problems — MPS — allows to use only 12 digits for a value. This means that we cannot store numbers with arbitrary precision because we would not be able to solve our problems. By the way, did you know that decimal to floating-point conversion needs arbitrary precision? Working with real values is really difficult. We also need to remember that there is always a risk of having round-off error. There are solvers able to perform calculations using exact operations — for instance SCIP — but this increases the calculation cost. In fact we should work with integer numbers only to avoid problems.

Existing formula

To implement greater than we used the following formula:

    \[ 0 \le b - a + Kx \le K - 1 \]

Look at the right side of this inequality. We use “less or equal” operator because this is what ILP requires. We also subtract one from K because this is the scale of our numbers. Imagine now that we allow a and b to have non-integer values, e.g., a=0.1 and b=0. We get the following:

(1)   \begin{gather*} 0 \le b - a + Kx \le K - 1 \\ 0 \le 0 - 0.1 + Kx \le K-1 \\ 0 \le -0.1 + Kx \le K-1 \end{gather*}

Since -0.1 is a negative number, x should be true. However, in that case we get:

    \[ -0.1 + K = K-0.1 > K-1 \]

This means that our formula cannot be satisfied.

Solution 1

Once again we need to make an assumption about values of our variables. We already assumed that they cannot be greater than K and we silently assumed that the difference of two different values can be at least one. This doesn’t hold for real values so we need to verify our assumptions.
Let’s say that we want to perform exact calculations up to five digits after the decimal point. This means that the scale of our variables is equal to s = 10^{-5}. In order to compare values we need to modify formula in the following way:

    \[ 0 \le b - a + Kx \le K - s \]

Let’s now consider the situation a = 0.00001 and b=0. We get:

(2)   \begin{gather*} 0 \le b - a + Kx \le K - 0.00001 \\ 0 \le 0 - 0.00001 + Kx \le K-0.00001 \\ 0 \le -0.00001 + Kx \le K-0.00001 \end{gather*}

Now everything works because for x=1 we get -0.00001 + K = K-0.00001. All other comparisons goes exactly the same way.

Solution 2

We can solve the problem using another approach. Assuming that s=10^{-5} we can multiply every variable by 10^5 and perform all calculations using only formulas for integer values. When retrieving the final results we need to divide every variable by 10^5 and then we get the actual value. However, this approach is a bit more difficult because we need to remember which values were multiplied and which weren’t — we don’t want to multiply binary variables because our formulas are not adjusted for that situation.

Warning

Both formulas are very dangerous. They assume we’ll never try comparing numbers which are not equal and are closer than epsilon. Otherwise we break the model.

Let’s consider this example. Set s=0.25 meaning that our precision is one fourth. Now let’s compare a=0.1 and b=0. What we get is

(3)   \begin{gather*} 0 \le 0 - 0.1 + Kx \le K - 0.25 \end{gather*}

If x is zero then we get 0 \le -0.1 which is false. However, if x is one then we get K - 0.1 \le K - 0.25.
By adding comparison (which we would like to never affect the model) we effectively break the system and solver should indicate infeasibility.

Summary

We are now able to perform calculations using real values. As stated in summary, we should avoid this as much as possible because of rounding errors, efficiency problems, and MPS file precision. However, it is possible.

]]>
https://blog.adamfurmanek.pl/2015/11/21/ilp-part-14/feed/ 1
ILP Part 4 – Comparisons https://blog.adamfurmanek.pl/2015/09/12/ilp-part-4/ https://blog.adamfurmanek.pl/2015/09/12/ilp-part-4/#comments Sat, 12 Sep 2015 10:00:18 +0000 http://blog.adamfurmanek.pl/?p=371 Continue reading ILP Part 4 – Comparisons]]>

This is the fourth part of the ILP series. For your convenience you can find other parts in the table of contents in Part 1 – Boolean algebra

We have already seen how to define Boolean algebra. We also know how to multiply variables or calculate division, remainder, powers, and roots. Today we are going to compare variables.

Idea

Let’s assume that we have two integer variables: a and b. We want to know whether a is greater than b and we want to store this information in variable x. We do not want to enforce this constraint, we only want to know the result of the comparison.
As we will see in later parts of this series, such a knowledge will allow us to calculate more sophisticated mathematical functions, like maximum or absolute value. But today we need to start with basics.

Basics

First lets define variables:

    \begin{gather*} a, b \in \mathbb{Z} \\ \left|a\right|, \left|b\right| \le k \\ k = 2^n - 1, n \in \mathbb{N} \\ K = 2\cdot k + 1\\ x \in \{0, 1\} \end{gather*}

We have two integer variables, both of them not greater than arbitrary defined number named k. Since we will probably solve our models using computers, we assume that k is close to some power of two. We also define constant K, which we will use later. Finally, we define binary variable x, which will hold the result of the comparison.

Greater than comparison

Now we are going to implement greater than operator. We want to define the following:

    \[ x = a \stackrel{?}{>}b \]

which means that x is equal to one if and only if a is greater than b, otherwise x is equal to zero. We can achieve this using the following constraints:

    \[ 0 \le b - a + Kx \le K - 1 \]

When a is greater than b, then b - a is negative and x must be equal to one. Otherwise we would receive b - a + K\cdot0 < 0 which cannot happen because of the left inequality. However, when a is not greater than b, their difference b - a is non-negative and x has to be zero.
We use value K greather than 2\cdot k because for case when a = -k and b = k, their difference b-a = k - \left(-k\right) = 2k. In that case we obtain:

    \[ 0 \le 2k + Kx \le K-1 \]

Now imagine that K \le 2k. We get:

    \[ 2k + Kx \ge 2k + 2kx \ge 2k\left(1+x\right)\ge 2k \]

On the other hand, K-1 \le 2k-1, so inequality 2k + Kx \le K-1 has no solutions.

Other operators

We have define only one relational operator, but now we are able to use it to define others. That is:

    \begin{gather*} a \stackrel{?}{<} b \equiv b \stackrel{?}{>} a\\ a \stackrel{?}{\le}b \equiv \neg \left(a \stackrel{?}{>}b \right)\\ a \stackrel{?}{\ge}b \equiv \neg \left(a \stackrel{?}{<}b \right)\\ a \stackrel{?}{=}b \equiv \left(a \stackrel{?}{\le} b \right) \wedge \left( a \stackrel{?}{\ge} b \right)\\ a \stackrel{?}{\neq}b \equiv \neg \left(\left(a \stackrel{?}{\le} b \right) \wedge \left( a \stackrel{?}{\ge} b \right)\right) \end{gather*}

Summary

We defined relational operators and now we are able to compare variables. In the next part we will see how to utilize this knowledge to calculate absolute value, maximum, and minimum. These trivial functions are in fact really powerful and we will use them many times in other operators.

]]>
https://blog.adamfurmanek.pl/2015/09/12/ilp-part-4/feed/ 3