83 lines
4.2 KiB
Go
83 lines
4.2 KiB
Go
package terminology
|
|
|
|
// contested.go: the PRE-CALL half of the word «contested» — the question asked of a candidate BEFORE any
|
|
// money moves, on nothing but what the drafts already produced.
|
|
//
|
|
// WHY THE WORD NEEDS A PREDICATE AT ALL. The mechanisms the owner asked for — a reviewer of another model
|
|
// family «only on contested clusters», a retry, a fallback (D39.254 п.2/п.6, backlog rows 435 and 438) —
|
|
// all route on «contested», and today that word has no denominator: nobody can say what share of a book's
|
|
// candidates it selects, so nobody can say what the routing would COST. A predicate with a measured
|
|
// population is the thing that has to exist first; the router is the pack after.
|
|
//
|
|
// ⛔ THE THRESHOLDS ARE INPUTS, NOT DEFAULTS, and there is no default value anywhere in this file. A
|
|
// number baked into Go would be a decision about a PAIR (how much do this language's drafts normally
|
|
// disagree) written into the engine every pair shares, and it would be a decision nobody measured. The
|
|
// caller passes them; today the only caller is the $0 probe that measures the population across a grid of
|
|
// them (cmd/tmbankprobe). When a paid consumer appears, its thresholds arrive as configuration carrying
|
|
// the measurement that chose them.
|
|
//
|
|
// ⚠ WHAT THIS PREDICATE CAN AND CANNOT SEE. It runs where buildBankCandidates runs — before the classifier
|
|
// — so the candidate's TYPE is still the miner's heuristic. It therefore answers «contested BY THE DRAFTS»
|
|
// and never «contested by type». The other half of the word lives after the answer comes back
|
|
// (pipeline.BankStopRow.Contest).
|
|
|
|
// ContestOpts are the pre-call predicate's inputs.
|
|
type ContestOpts struct {
|
|
// MinConventions is how many distinct DECISIONS the drafts must have made for the candidate to be in
|
|
// contention at all. Conventions, not Spread: two chunks writing «Море истинной ци» and «море истинной
|
|
// ци» made ONE decision written two ways, and counting that as a contest would send a normalization nit
|
|
// to a second model. Below 2 the arm is off — every candidate qualifies on this axis.
|
|
MinConventions int
|
|
// MaxLeaderShare is the dominance arm: the share of draft chunks behind the BEST-ranked convention,
|
|
// above which the contest is considered settled by the drafts themselves (0.75 = three quarters of the
|
|
// chunks already agree). Zero or negative disables the arm, and then MinConventions decides alone.
|
|
MaxLeaderShare float64
|
|
}
|
|
|
|
// Contest is what the predicate saw, not only what it decided: a bare bool cannot be argued with, and the
|
|
// numbers below are what a threshold is chosen against.
|
|
type Contest struct {
|
|
Contested bool
|
|
Conventions int
|
|
// LeaderShare is the best-ranked convention's share of the draft chunks, in [0,1]. It is 1 for a single
|
|
// convention, and 0 when the drafts proposed nothing at all — see Unsupported, which is the case that
|
|
// must not be read as «the drafts agreed».
|
|
LeaderShare float64
|
|
// Unsupported marks a candidate no draft rendered at all: the role is asked to render it with nothing
|
|
// to rank. It is NOT a contest — there is no disagreement — and it is carried separately because a
|
|
// router that treats it as agreement would send the least-evidenced rows to the cheapest path.
|
|
Unsupported bool
|
|
}
|
|
|
|
// Contest applies the pre-call predicate to a candidate.
|
|
func (c Candidate) Contest(o ContestOpts) Contest {
|
|
out := Contest{Conventions: c.Conventions()}
|
|
if len(c.Variants) == 0 {
|
|
out.Unsupported = true
|
|
return out // no drafts, no contest: nothing disagreed with anything
|
|
}
|
|
total, top := 0, 0
|
|
for _, v := range c.Variants {
|
|
total += v.Chunks
|
|
if v.Chunks > top {
|
|
top = v.Chunks
|
|
}
|
|
}
|
|
switch {
|
|
case total > 0:
|
|
out.LeaderShare = float64(top) / float64(total)
|
|
default:
|
|
// Renderings with no chunk count behind them (a channel that carries the rendering but not its
|
|
// support). Reported as 0 rather than as 1: «nothing is behind the leader» is what happened, and
|
|
// calling it dominance would silently settle every such contest.
|
|
out.LeaderShare = 0
|
|
}
|
|
if out.Conventions < o.MinConventions {
|
|
return out
|
|
}
|
|
if o.MaxLeaderShare > 0 && out.LeaderShare > o.MaxLeaderShare {
|
|
return out // the drafts already agree by a margin the caller called decisive
|
|
}
|
|
out.Contested = true
|
|
return out
|
|
}
|