This is the sixteenth part of the ILP series. For your convenience you can find other parts in the table of contents in Part 1 – Boolean algebra
Hi all. Today we are going to use ILP to solve a cube riddle. This will be a basic application of ILP approach because we are not going to define any meaningful cost function. All we want to get is any solution fulfilling provided constraints. Let’s go.
Table of Contents
Problem description
We have the following cube:


We have nine l-shape elements which we can use to build a bigger cube with a side of length three. Elements are identical, we can rotate them but we cannot change their shape.
This problem was posted as a question on 4programmers forum
For this problem we will utilize a so called zero-one linear programming. It is a special case of ILP with binary variables only. This approach is often used to solve decision problems for which we want to get any solution, disregarding the cost function.
Necessary variables
We start with defining necessary variables. We have nine elements, every element consists of three “pieces”. For each element we define a binary variables saying whether this element has piece in a specific cube position. So we end up with:
      
where  is a number of element (so it is from
 is a number of element (so it is from  to
 to  ) and
) and  are coordinates of the cube. So we have
 are coordinates of the cube. So we have  binary variables. Every variable is allowed to be zero or one. Zero means that the particular element has no piece in the specific coordinates.
 binary variables. Every variable is allowed to be zero or one. Zero means that the particular element has no piece in the specific coordinates.
Having these variables let’s start with adding constraints.
Three pieces for every element
We start with an obvious constraint. Every element should have exactly three pieces. This means the following:
      
We sum for indexes which make sense. For every  element we want the sum of variables for every coordinate for this element to be equal to three.
 element we want the sum of variables for every coordinate for this element to be equal to three.
Stop tearing elements
If we would solve the problem right now, we would end up with elements scattered throughout the cube. Elements would probably be tore apart, however, all of them would have exactly three pieces.
In order to avoid tearing element apart, we need to make sure that its pieces are next to each other. We say that two pieces are one next to another when they are neighbours in one of three possible directions (along  axis, along
 axis, along  axis, along
 axis, along  axis). We get the following constraint:
 axis). We get the following constraint:
      
This formula means that for every piece  and for every position
 and for every position  we check whether position
 we check whether position  and any of its neighbouring positions are occupied by pieces of one element. If it is so, these variables will be equal to
 and any of its neighbouring positions are occupied by pieces of one element. If it is so, these variables will be equal to  , so by multiplying them we will get
, so by multiplying them we will get  . Since we deal with binary variables only, we can use just a conjunction defined in part 1.
. Since we deal with binary variables only, we can use just a conjunction defined in part 1.
Bending elements
If we would solve the problem right now, elements would have exactly three pieces, and pieces would be next to each other. However, we might end up with a straightened element, e.g., element with all pieces along one axis.
In order to avoid this, we need to add the following constraints:
      
Let’s take the first one constraint. For every element  and for every position
 and for every position  on the bottom side of the cube we sum all elements along the
 on the bottom side of the cube we sum all elements along the  axis. So we sum take all positions for one vertical line, sum their variables and make sure that there are at most two pieces on that line. Next two constraints do the same for
 axis. So we sum take all positions for one vertical line, sum their variables and make sure that there are at most two pieces on that line. Next two constraints do the same for  axis and
 axis and  axis respectively.
 axis respectively.
Exactly one piece in one place
Once again, if we would solve the problem right now, we would end up with elements with correct shape (e.g., with three pieces and in l-shape), however, all this elements still might be in exactly the same place. In order to avoid that, we need to make sure that for every coordinate there is exactly one piece of exactly one element:
      
For every position we sum variables for all elements and we require that this sum is equal to exactly one. This means that exactly one variable will be true.
Summary
As we can see, this riddle can be solved really straightforward. We start with required variables and add constraints to make our elements look more realistic. Finally, we put elements in places and build the actual cube.
I checked this naive implementation using CPLEX and the solver was able to find the solution in less than 200 miliseconds. Not bad.
Next time we are going to solve similar problem, however, we will need to deal with elements of different shapes. Stay tuned.