kfupm / drilling-pad-optimisation
Publicuv add qiskit or uv add pennylane).
Baseline values printed by this template on first run, for you to check your environment:
small 117.4, medium 245.6, full 486.0 (total cost in million USD, values rounded).n_targets reservoir targets that must each be reached by one well, and n_sites candidate pad locations. A pad can serve a target if the horizontal distance is at most the rig reach R (1.7 km). Each pad has a construction cost (million USD), a maximum number of wells (capacity), and an exclusion flag for sites that cannot be built on. Drilling a well costs drill_rate million USD per kilometre of horizontal reach.
Total cost = sum of construction costs of open pads + sum of drilling costs of the target to pad assignments.x (one entry per candidate site, 1 = build the pad). The decoder below assigns each target to the cheapest open pad within reach that still has capacity, then computes the total cost. Targets that cannot be assigned are charged a fixed penalty. The same decoder is used to score every method, classical or quantum, so results stay comparable.x_i per candidate site:
where N(t) is the set of sites within reach of target t. The penalty term is the inclusion exclusion expansion of "target t is uncovered", truncated at second order: it is exactly zero when one or two pads cover the target, P when none does, and grows again beyond two. It is small (15 qubits on the small instance, which allows exact state vector simulation), but it still penalises heavy multiple coverage, which the real problem does not.
Encoding B, set cover with slack variables. For each target t, a one hot slack y_{t,m} (m = 1 .. |N(t)|) records how many pads cover it:
This is the standard set cover QUBO. It is correct (any cover has zero penalty) at the price of many more variables, which puts it out of reach of exact simulation but not of annealers or hybrid solvers.
Neither encoding sees capacity or drilling distance. The decoder of section 2 always computes the true cost afterwards, so any bitstring produced from these QUBOs is scored on the real objective. Adding a distance term, handling capacity, or finding a more compact correct encoding are expected contributions of the hackathon.exp(-i beta X) on every qubit. A coarse grid search over (gamma, beta) replaces the classical optimiser, which keeps the cell readable. The most probable bitstrings are then decoded with the shared evaluator.
This is a reference implementation, meant to be replaced by a proper SDK circuit (Qiskit, PennyLane, Cirq) with a real optimiser, larger depth, and, when access is granted, a hardware or emulator backend.