I was looking to attempt a different method to solve a circle packing problem. More specifically, packing n circles in a rectangle with the goal to have the circles be as large as possible. There is a great post discussing this problem here http://yetanothermathprogrammingconsultant.blogspot.com/2018/05/knapsack-packing-difficult-miqcp.html, but I wanted to solve it using HiGHS and as an MILP.
With that said, this is the formulation I came up with. Is this right?
$$ \begin{alignat}{8} \text{max} & \sum_i R_i \\\\ \text{s.t.} \quad & R_i \le |rect_{length} - px_i| \quad \forall i \\\\ & R_i \le px_i \quad \forall i \\\\ & R_i \le |rect_{width} - py_i| \quad \forall i \\\\ & R_i \le py_i \quad \forall i \\\\ & D_{ij} \ge R_i + R_j - (1-y_i)M - (1-y_j)M \quad \forall i,j \\\\ & \sum_i y_i = n \\\\ &R_i \ge 0 \quad \forall i \\\\ & y_i \in \{0, 1\} \quad \forall i \end{alignat} $$
A few comments:
- I create a mesh grid of points. I recognize I lose some accuracy here, but the hope is the MILP solves quickly.
- $D_{ij}$ is a parameter that is calculated before the optimization, possible since Im using discrete points between $[(0, rect_{length}), (0, rect_{width})]$.
- Parameters used are: 11 grid points, $rect_{length} = rect_{width} = 10$, $M=10$, n=10
- I dont do all $i,j$ combinations, I only do $i<j$
- Final model size is 1414 rows, 163 cols, 5572 nonzeros
- Using HiGHS Im unable to close the gap (~36% after 300 seconds). Best solution found is 14.84.
Not sure if its helpful, but here is some code I used for building out the $px,py$ data.
import numpy as np
linear_grid_points = 11
xmax = 10
ymax = 10
x_grid = np.linspace(0, xmax, linear_grid_points)
y_grid = np.linspace(0, ymax, linear_grid_points)
xv, yv = np.meshgrid(x_grid, y_grid)
locs = np.vstack((xv.ravel(), yv.ravel())).T
dist = locs[:, :, None] - locs[:, :, None].T
dist = (dist * dist).sum(1)
dist = np.sqrt(dist)
circles_to_use = 10