rnel.betting
¶
Betting (e-value) reading of a neutrosophic triplet built from several sources (EXPERIMENTAL).
Reference: Leyva-Vázquez, M. Y. and Smarandache, F., "What does T = 0.7 mean? A betting reading of neutrosophic triplets built from several sources, with anytime error guarantees and its limits" (manuscript, 2026).
Setting. A proposition A is examined by sources that arrive one after another. For every source j there are two e-values: e_j+ against not-A and e_j- against A (non-negative, with expectation at most 1 under the hypothesis they bet against). Two bettors start with capital 1. Before every source each stakes a fixed fraction lam of its current capital, the first against not-A and the second against A:
K+ <- K+ * (1 - lam + lam * e+) K- <- K- * (1 - lam + lam * e-)
The triplet is read off the two capitals:
T = max(0, 1 - 1/K+) F = max(0, 1 - 1/K-)
conflict I_con = T * F (both bettors have won)
ignorance I_ign = (1 - T) * (1 - F) (neither has)
I = I_con + I_ign, so T + I + F = 1 + 2 T F
Guarantee (Ville's inequality). If not-A holds, P(T ever reaches 1 - alpha) <= alpha, however often the triplet is recomputed; symmetrically for F under A. 1 - T = min(1, 1/K+) is an anytime-valid p-value.
Verdicts at level alpha: "supported" (T >= 1 - alpha > F), "refuted" (F >= 1 - alpha > T), "conflict" (both), "insufficient" (neither). Record verdicts use the running maxima T* and F*.
Facts worth knowing before using it
- lam = 1 (pooling) never registers conflict: K+ * K- <= 1 when e+ * e- <= 1, so T and F cannot both be > 0.
- With lam < 1 the state depends on lam, on the effect size the e-values are built on, and on how the evidence is divided into sources. Fix them before seeing the data and report a grid.
- The verdicts are existential: "supported" rejects "no source is governed by A"; it does not say that A holds for every source.
- The guarantee presupposes valid e-values: unbiased, independent sources and a correct model.
Two families of e-values are provided
point_evalues two point hypotheses: e+ = likelihood ratio, e- = its inverse gaussian_evalues complementary one-sided hypotheses about a normal estimate (y, s) with a design effect delta: A is "theta > theta0" (or "< theta0"); conflict then means sign disagreement
and helpers that turn 2x2 tables or published hazard ratios into (y, s).
Refined truth (Section 10 of the manuscript, contributed by F. Smarandache), after the n-valued refined neutrosophic set (Smarandache 2013), with the sources read as possible worlds:
refined_triplet sextuple (T_abs, T_rel; I_con, I_ign; F_rel, F_abs). T_rel is the betting T ("true in at least one source"); T_abs = tau(min_j e_j+) is "true in every source", with P(false T_abs >= 1 - alpha) <= alpha (Proposition 9); T_abs > 0 forces F = 0 when e+ * e- <= 1 (Proposition 10). graded_truth sub-truths T_k betting against "every theta_j <= theta0 + eta_k" and their merge by the weighted MEAN of the capitals, which keeps the guarantee under any dependence (Proposition 11). Taking max_k T_k (a t-conorm) is valid only at level p * alpha.
Pure Python (standard library only). All capitals are kept on the log scale.
VERDICTS = ('insufficient', 'supported', 'refuted', 'conflict')
module-attribute
¶
DEFAULT_GRID = (0.1, 0.25, 0.5, 0.75, 1.0)
module-attribute
¶
REFINED_VERDICTS = ('insufficient', 'supported in some source', 'supported in every source', 'refuted in some source', 'refuted in every source', 'conflict')
module-attribute
¶
BettingState
dataclass
¶
Pair of betting capitals with a constant stake fraction lam, updated source by source.
st = BettingState(lam=0.5) st.update(math.log(1000), -math.log(1000)).update(-math.log(1000), math.log(1000)) # doctest: +ELLIPSIS BettingState(...) round(st.T, 3), round(st.F, 3), st.verdict() (0.996, 0.996, 'conflict')
Source code in src/rnel/betting.py
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | |
lam = 0.5
class-attribute
instance-attribute
¶
log_kp = 0.0
class-attribute
instance-attribute
¶
log_km = 0.0
class-attribute
instance-attribute
¶
log_kp_max = 0.0
class-attribute
instance-attribute
¶
log_km_max = 0.0
class-attribute
instance-attribute
¶
n = 0
class-attribute
instance-attribute
¶
path = field(default_factory=list, repr=False)
class-attribute
instance-attribute
¶
K_plus
property
¶
K_minus
property
¶
T
property
¶
F
property
¶
T_record
property
¶
F_record
property
¶
conflict
property
¶
ignorance
property
¶
I
property
¶
update(log_e_plus, log_e_minus)
¶
Add one source, given its two e-values on the log scale.
Source code in src/rnel/betting.py
237 238 239 240 241 242 243 244 | |
extend(log_e_plus, log_e_minus)
¶
Source code in src/rnel/betting.py
246 247 248 249 | |
triplet()
¶
(T, I, F).
Source code in src/rnel/betting.py
288 289 290 | |
masses()
¶
Belnap masses: true-only T(1-F), false-only (1-T)F, both (conflict), neither (ignorance).
Source code in src/rnel/betting.py
292 293 294 295 | |
p_values()
¶
Anytime-valid p-values (1 - T, 1 - F) = (min(1, 1/K+), min(1, 1/K-)).
Source code in src/rnel/betting.py
297 298 299 | |
verdict(alpha=0.05)
¶
Source code in src/rnel/betting.py
301 302 | |
record_verdict(alpha=0.05)
¶
Source code in src/rnel/betting.py
304 305 | |
first_crossing(alpha=0.05, side='T')
¶
1-based index of the first source after which T (or F) reached 1 - alpha; None if never.
Source code in src/rnel/betting.py
307 308 309 310 311 312 313 | |
MixtureState
dataclass
¶
Uniform (or weighted) mixture over stake fractions: K = sum_i w_i K_{lam_i}. It keeps the guarantee of
Ville's inequality, so the triplet, verdicts and p-values are read exactly as for BettingState.
Source code in src/rnel/betting.py
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | |
grid = DEFAULT_GRID
class-attribute
instance-attribute
¶
weights = None
class-attribute
instance-attribute
¶
states = field(default_factory=list, repr=False)
class-attribute
instance-attribute
¶
path = field(default_factory=list, repr=False)
class-attribute
instance-attribute
¶
log_kp_max = 0.0
class-attribute
instance-attribute
¶
log_km_max = 0.0
class-attribute
instance-attribute
¶
log_kp
property
¶
log_km
property
¶
n
property
¶
K_plus = BettingState.K_plus
class-attribute
instance-attribute
¶
K_minus = BettingState.K_minus
class-attribute
instance-attribute
¶
T = BettingState.T
class-attribute
instance-attribute
¶
F = BettingState.F
class-attribute
instance-attribute
¶
T_record = BettingState.T_record
class-attribute
instance-attribute
¶
F_record = BettingState.F_record
class-attribute
instance-attribute
¶
conflict = BettingState.conflict
class-attribute
instance-attribute
¶
ignorance = BettingState.ignorance
class-attribute
instance-attribute
¶
I = BettingState.I
class-attribute
instance-attribute
¶
triplet = BettingState.triplet
class-attribute
instance-attribute
¶
masses = BettingState.masses
class-attribute
instance-attribute
¶
p_values = BettingState.p_values
class-attribute
instance-attribute
¶
verdict = BettingState.verdict
class-attribute
instance-attribute
¶
record_verdict = BettingState.record_verdict
class-attribute
instance-attribute
¶
first_crossing = BettingState.first_crossing
class-attribute
instance-attribute
¶
update(log_e_plus, log_e_minus)
¶
Source code in src/rnel/betting.py
335 336 337 338 339 340 | |
extend(log_e_plus, log_e_minus)
¶
Source code in src/rnel/betting.py
342 343 344 345 | |
log_factor(log_e, lam)
¶
log(1 - lam + lam * e) for an e-value given on the log scale; stable for very large or small e.
Source code in src/rnel/betting.py
105 106 107 108 109 110 111 112 113 | |
tf_from_log_capital(log_k)
¶
T (or F) from a log capital: max(0, 1 - 1/K).
Source code in src/rnel/betting.py
116 117 118 119 120 | |
verdict(T, F, alpha=0.05)
¶
Level-alpha verdict: 'supported', 'refuted', 'conflict' or 'insufficient'.
Source code in src/rnel/betting.py
123 124 125 126 127 | |
point_evalues(log_lr)
¶
Two point hypotheses: log e+ = log LR(A : not-A), log e- = -log LR. Returns (log_e_plus, log_e_minus).
Source code in src/rnel/betting.py
134 135 136 137 | |
gaussian_evalues(y, s, delta, theta0=0.0, direction='greater')
¶
Complementary one-sided e-values for normal estimates y_j with standard errors s_j.
direction="greater": A is theta_j > theta0 for the sources it governs, not-A is theta_j <= theta0. direction="less": A is theta_j < theta0 (e.g. a log odds ratio below 0 meaning benefit). delta > 0 is the design effect: the distance from theta0 on which each bet is built. With b = +-(y - theta0),
log e+ = delta * b / s^2 - delta^2 / (2 s^2) (against not-A; valid for the composite null)
log e- = -delta * b / s^2 - delta^2 / (2 s^2) (against A)
Returns (log_e_plus, log_e_minus).
Source code in src/rnel/betting.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
log_odds_ratio(a, n1, c, n2, correction=0.5)
¶
(log OR, s.e.) of events a/n1 (treated) against c/n2 (control); correction is added to all four cells
of a table with a zero cell.
Source code in src/rnel/betting.py
176 177 178 179 180 | |
log_risk_ratio(a, n1, c, n2, correction=0.5)
¶
(log RR, s.e.) of events a/n1 against c/n2, with the same zero-cell rule as log_odds_ratio.
Source code in src/rnel/betting.py
183 184 185 186 187 | |
log_ratio_from_ci(estimate, lower, upper, level=0.95)
¶
(log ratio, s.e.) from a published ratio (HR, OR, RR) and its symmetric-on-log confidence interval.
Source code in src/rnel/betting.py
190 191 192 193 194 195 | |
betting_triplet(log_e_plus, log_e_minus, lam=0.5, alpha=0.05)
¶
One-call summary for a sequence of sources. lam is a stake fraction in [0, 1] or "mix" (uniform mixture
over 0.1, 0.25, 0.5, 0.75, 1). Returns T, I, F, the conflict and ignorance parts, both capitals, the verdict,
the record verdict, the first source at which T and F reached 1 - alpha, and the path of (T, F).
Source code in src/rnel/betting.py
380 381 382 383 384 385 386 387 388 389 390 391 | |
absolute_degree(log_e)
¶
Absolute degree tau(min_j e_j) = max(0, 1 - 1/min_j e_j) of a sequence of single-source log e-values: evidence that the hypothesis holds in EVERY source. It uses no stake, never increases as sources are added and is 0 for no sources. If (10) holds per source, a false value >= 1 - alpha has probability <= alpha (Prop. 9).
absolute_degree([math.log(30), math.log(8), math.log(0.5)]) 0.0 round(absolute_degree([math.log(25), math.log(30), math.log(40)]), 2) 0.96
Source code in src/rnel/betting.py
402 403 404 405 406 407 408 409 410 411 412 413 | |
refined_verdict(T_abs, T_rel, F_rel, F_abs, alpha=0.05)
¶
Refined Definition 3: 'supported in every source' when T_abs >= 1 - alpha; 'supported in some source' when T_rel >= 1 - alpha > T_abs and F_rel < 1 - alpha; symmetrically for 'refuted'; 'conflict' when T_rel and F_rel both reach 1 - alpha; otherwise 'insufficient'.
Source code in src/rnel/betting.py
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | |
refined_triplet(log_e_plus, log_e_minus, lam=0.5, alpha=0.05)
¶
Refined betting value (T_abs, T_rel; I_con, I_ign; F_rel, F_abs) of Definition 4, an n-valued refined neutrosophic value with p = r = s = 2. The gap between T_rel and T_abs is the number behind the warning that 'supported' means 'supported in at least one source'.
r = refined_triplet([math.log(30), math.log(8), math.log(0.5)], ... [-math.log(30), -math.log(8), -math.log(0.5)]) round(r["T_rel"], 3), r["T_abs"], r["verdict"] (0.981, 0.0, 'supported in some source')
Source code in src/rnel/betting.py
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 | |
merge_log_capitals(log_ks, weights=None)
¶
Log of the weighted arithmetic mean of capitals (Proposition 11). The mean of e-values is valid under arbitrary dependence (Vovk and Wang 2021) and essentially the only admissible symmetric merge (Wang 2025).
Source code in src/rnel/betting.py
455 456 457 458 459 460 461 462 463 464 | |
graded_truth(y, s, etas, delta, theta0=0.0, direction='greater', lam=0.5, weights=None, alpha=0.05)
¶
Graded sub-truths of Section 10.3 for normal estimates. T_k bets against 'every theta_j <= theta0 + eta_k' (direction 'greater'; 'every theta_j >= theta0 - eta_k' for 'less'), so it is a relative truth that grades the size of the effect, with thresholds 0 = eta_1 < ... fixed before the data. T_bar = tau(mean of the capitals) keeps Theorem 1 against not-A; simultaneous statements about all T_k need level alpha / p each.
Returns T_k, their log capitals, T_bar and whether each reaches 1 - alpha.
Source code in src/rnel/betting.py
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | |