Books · Solving Puzzles through Mathematical Programming
Chapter 11
Bug Byte
Jane Street’s Bug Byte is a weighted-graph labelling puzzle with an embedded word-search payoff. The setting is a connected graph on eighteen nodes and twenty-four edges; the goal is to assign to each edge a distinct integer weight from subject to sum-at-node and path-weight constraints, after which the shortest-weight path between two distinguished nodes spells out a secret word under the mapping , , , .
Two kinds of nodes carry constraints. The first kind (white with a green border, labelled with an integer ) asserts that the sum of all edges directly incident to the node equals . The second (solid green, labelled with one or more integers ) asserts that for each there exists a simple (non-self-intersecting) path starting from the node whose edge-weight sum equals . The puzzle also supplies four edge weights fixed in advance (), which removes those four values from the pool of twenty remaining unknowns.
The puzzle was distributed by Jane Street’s recruiting site in ; it illustrates the now-common genre of “graph puzzles” whose constraint structure is almost designed to be fed into CP-SAT. The unknowns number , the direct-sum constraints number , the path constraints involve seven starting nodes with a total of ten path-sum conditions, and the feasibility problem is decided in about milliseconds on a standard laptop.
The puzzle graph
The graph is displayed in Figure 11.1. The two stars (above and below) mark the endpoints between which the shortest path will be read. Nodes carrying a single number in green indicate a sum-at-node constraint; nodes in green with multiple numbers stacked indicate multiple path-sum conditions from that node.
The programming model
Variables
Let be the integer unknowns ranging over , all-different. Each edge of the graph is either labelled by a (twenty such edges) or by a fixed literal (four such edges: the weights , , , ).
Direct-sum constraints
For each labelled white-green-bordered node, equate the sum of incident edge weights to the prescribed total. In the classical Bug Byte instance there are ten such equalities, e.g. (One obtains the full list by reading off each labelled node’s neighbours and summing.)
Path-sum constraints
For each green node with labels , enumerate all simple paths starting from that node. Each must equal the edge-weight sum of some such path. Since there is no a priori bound on path length, the enumeration is finite only because simple paths in a graph of nodes have length at most ; typical Bug Byte instances have low-hundreds of simple paths per starting node, well within CP-SAT’s reach.
To encode “ equals some path’s sum” in CP-SAT, introduce a Boolean per candidate path , set via an pair, then require .
A solver in fifty lines
from ortools.sat.python import cp_model
import networkx as nx
def solve(edges, sum_nodes, path_nodes):
m = cp_model.CpModel()
w = [m.NewIntVar(1, 24, "") for _ in range(20)]
m.AddAllDifferent(w)
for v in (7, 12, 20, 24):
for i in range(20):
m.Add(w[i] != v)
def weight(lbl):
return lbl[1] if lbl[0] == "fix" else w[lbl[1]]
for refs, total in sum_nodes:
m.Add(sum(weight(r) for r in refs) == total)
G = nx.Graph()
for u, v, lbl in edges:
G.add_edge(u, v, lbl=lbl)
for start, target in path_nodes:
bools = []
for node in set(G.nodes) - {start}:
for p in nx.all_simple_paths(G, start, node):
exprs = [weight(G[a][b]["lbl"])
for a, b in zip(p, p[1:])]
b = m.NewBoolVar("")
m.Add(sum(exprs) == target).OnlyEnforceIf(b)
bools.append(b)
m.AddBoolOr(bools)
s = cp_model.CpSolver()
s.Solve(m)
return [s.Value(x) for x in w]
Reading the answer
With the edge weights filled in, the shortest weighted path from one star to the other is computed by any standard routine (Dijkstra’s algorithm, for instance). The path in Figure 11.1 has six edges with weights . Mapping onwards gives — appropriate for a puzzle distributed by a recruiting site that lives on the network.
Sources. Bug Byte was released by Jane Street as part of their public puzzle series in ; the original graph and its constraints appear on janestreet.com/bug-byte. The puzzle is a cleanly packaged exercise in graph labelling by constraint programming, and a gentle example of the pattern “enumerate simple paths, then disjunctive equality on sums” that recurs in Jane Street’s later Hall of Mirrors and Altered States puzzles. The ingredient that makes Bug Byte distinct among edge-weight puzzles is the path-sum disjunction — a constraint form that is awkward for straight mixed-integer programming but natural in CP-SAT with reified equality and Boolean disjunction.