goalseek¶
One-dimensional goal seek over a Grid: find the value of a variable cell that drives a formula cell to a target. See the Goal seek guide for the :goal command.
goalseek
¶
One-dimensional goal-seek over a Grid.
Find a value for a variable cell such that a formula cell evaluates to a given target value. Useful for spreadsheet what-if of the form "what input makes this output equal X?" -- the most common form of Solver use in Excel and the only one that doesn't need an LP.
Algorithm: bisection with an auto-bracket pre-step. Bisection is slow asymptotically but at spreadsheet scale a few dozen recalcs run in a few milliseconds; correctness, simplicity, and graceful failure on non-monotonic or noisy formulas are worth more than the iteration count. Brent's method would converge faster on smooth f but adds edge cases (oscillation, the mflag dance, slow-progress detection) that aren't justified here.
The variable cell must hold a value, not a formula (analogous to decision
cells in opt.py): goal-seek will overwrite it on success, and apply=False
restores it. The formula cell must contain a formula; it should depend on
the variable cell (otherwise f doesn't change with x and bracketing fails).
SeekResult
dataclass
¶
SeekResult(
converged: bool,
iterations: int,
var_value: float,
formula_value: float,
residual: float,
applied: bool,
)
GoalSeekError
¶
Bases: Exception
User-facing failure: bad cell selection, no sign change, non-converged.
seek
¶
seek(
grid: Grid,
formula_cell: CellKey,
target: float,
var_cell: CellKey,
*,
lo: float | None = None,
hi: float | None = None,
tol: float = 1e-09,
max_iter: int = 100,
apply: bool = True,
) -> SeekResult
Adjust var_cell so that formula_cell evaluates to target.
If both lo and hi are given they're used as the search bracket;
otherwise the algorithm auto-brackets outward from the variable cell's
current value.
On success (residual within tolerance) the variable cell is left holding
the solved value and the rest of the grid is recalculated to reflect it;
callers can roll back via undo (the TUI wrapper records a grid snapshot).
apply=False runs the search without leaving the grid mutated.
Source code in src/gridcalc/goalseek.py
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |