← all posts

QUBO Solving ASIC

ASICDiscrete OptimizationGraph Optimization

What is QUBO?

QUBO stands for Quadrature Unconstrained Binary Optimization. It’s an unconstrained discrete optimization problem.

Graph of max-cut problem

The problem goes like this:

We can relate the QUBO problem to the Ising Hamiltonian for a Quantum system

Relationships:

Simulated Annealing

To summarize from the previous part:

We now have an evaluation function H(s)H(s) that inputs a proposed solution ss and outputs energy H(s)H(s). These are all the building blocks you need for meta-heuristic optimization.

Why Simulated Annealing?

So how does Simulated Annealing work?

This is the algorithm we’ll be using, the algorithm at the core of the computation.

Verilog Implementation

The starting implementation will be a random 5 x 5 Q matrix, representing an arbitrary QUBO problem. We can assume the Q matrix is diagonal and correctly encodes the QUBO weights and correlations. The entries in the matrix are whole integers that can be negative, positive, or zero, and can go up to the value 32.


LFSR Verilog Implementation

The “stochasticity” of this stochastic optimizer comes from a random number generator. Specifically, it uses a Fibonacci LFSR, an X-bit long register with a Y-bit long XOR operation that supplies the next bit value after shifting a register to the left.

From a starting seed (input of bits in the register), the LFSR can generate a cyclical random sequence of bits. Most importantly, it will never get stuck. For this implementation, it uses an 8-bit LFSR with a 4-bit input XOR. This can generate a random bit cycle of length 255, before repeating its values, meaning it will take 255 clock cycles before the output starts becoming deterministic. Thus, it is not a truly random number generator. The width of the LFSR can increase to exponentially increase the # of clock cycles, which can, in practice, make this a random number generator.

The output of the LFSR supplies both the spin update (spin flip operation) and the Metropolis test (probabilistic choice after checking if the energy is lower).


Let’s start with some instantiation.

Spin Update Verilog Implementation

Next we start doing spin updates.

Next we do temperature cooling.

Notice that we don’t compute a new xTQxx^TQx or a H(s)H(s) every time. We want to avoid computationally expensive operations wherever we can, and we can in this case by finding the relationship between the Ising Hamiltonian and the QUBO Argmin. That relationship turns out to be a few linear relationships that don’t even involve integer or matrix multiplication. That is huge!


Performance Benchmarks

Input: 5×55 \times 5 Q Matrix

Initial Solution Vector:

Results:

Stochastic Optimizer (Simulated Annealing)

Brute Force (Linear best search)

Optimized Solution Vector (both methods match):

On average, the optimizer reached the solution after 4410 ns. The total # of spin flips during the run was 186. The final solution was {1,0,1,0,1}. The brute force approach also reached the final solution {1,0,1,0,1}.

In this case, the brute force solution was 13.4x faster. This makes sense, the solution space is only an 8-bit integer. So you may be wondering why we’re taking so much extra effort when even a brute force search was faster.


Now let’s make some changes. We’ll change our scale to a QQ matrix of 15×1515 \times 15 (we’re just adapting the 5×55 \times 5 case to the new case, not changing any core computation), and compare the Simulated Annealing algorithm vs. the Brute Force approach.

Input: 15×1515 \times 15 Q matrix

Initial Solution Vector:

Results:

Stochastic Optimizer (Simulated Annealing)

Brute Force (Linear best search)

Optimized Solution Vector (both methods match):

On average, the optimizer reached the optimal solution after 4410 ns. The total # of spin flips during the run was 169. If you noticed, the convergence time was actually the same as the previous 5×55 \times 5 case. This is because I didn’t change the convergence runtime for the Simulated Annealing algorithm, meaning all the parameters were actually the same as the 5×55 \times 5 version (it ran for the same # of total steps). And look at that, it still converged.

In this case, the simulated annealing solution was 74.3x faster. The search space for the brute force method exponentially scales to a linearly scaling increase in size, Olog⁡(2n)O\log(2^n).

Keep in mind, this is before tuning and optimization. We could tune the initial solution vector to start at a more advantageous position to converge faster. We could tune the temperature cooling rate to the problem by perturbing and seeing which direction goes faster. We could also stack more compute modules in parallel.


Now for the final change. Let’s move to a 30×3030 \times 30 Q matrix. At this point and beyond, brute force solutions become impractical. An exhausting search would take 1.07 billion steps, which is a complete waste of computational resources. Now we have to evaluate in the dark.

Input: (I’m not pasting the whole matrix)

Initial Solution Vector:

Stochastic Optimizer (Simulated Annealing)

Optimized Solution Vector:

So how do we know if this is the optimal solution vector? Well, we don’t. But we can try to see if we can find a better one by running the algorithm for longer.

Let’s extend the length of the algorithm by double to see what we get:

Initial Solution Vector:

Stochastic Optimizer (Simulated Annealing)

Optimized Solution Vector:

I’ll save you the time that it takes to check if the solutions are the same. They are. So it looks like the initial convergence is actually optimal (comparing with a longer-running algorithm). So assuming that the solution is at the global minimum (or close), the convergence rate is extremely fast and scales slower than the matrix size increase.

In the future, I will do a schematic level review and layout for hardware. This is the part I’m most excited about.

You can find the repo here: QUBO Solver Verilog Implementation