Commit 52e3c1d1 authored by Your Name's avatar Your Name

Reinforced recovery algorithm

parent 8ed954c2
......@@ -2,6 +2,15 @@
All notable changes to this project will be documented in this file.
## [1.0.33] - 2026-05-21
### Fixed
- **Critical**: Fixed extraction algorithm structural bias causing the table to consistently lose. Two hardcoded constraints in `extract_balanced_safe` prevented the algorithm from steering away from expensive outcomes even when the redistribution balance was deeply negative: (1) the correction floor `0.35` meant an expensive outcome always retained ≥35% of its base weight regardless of balance; (2) `max_drift=0.4` set a `lower_bound` of `0.6 × base_weight`, keeping the most probable (and usually most expensive) result at ~30-35% selection probability even under maximum deficit. Together these made recovery mathematically too slow.
### Technical Details
- `extract_balanced_safe()`: both `max_drift` and the correction floor are now adaptive. A `balance_severity` scalar (0→1, proportional to deficit vs current stake) scales `max_drift` from `0.40``0.95` and the correction floor from `0.35``0.05` as the shortfall deepens. When the balance is neutral the function is mathematically identical to the previous version. Updated benchmark tests to reflect that `extract_balanced_safe` and `candidate_v4` are now distinct implementations.
- Updated user agent string from MbetterClient/1.0r32 to MbetterClient/1.0r33
## [10.0.22] - 2026-03-16
### Fixed
......
......@@ -14,7 +14,7 @@ from typing import List, Dict, Any
# Build configuration
BUILD_CONFIG = {
'app_name': 'MbetterClient',
'app_version': '1.0.32',
'app_version': '1.0.33',
'description': 'Cross-platform multimedia client application',
'author': 'MBetter Team',
'entry_point': 'main.py',
......
......@@ -217,7 +217,7 @@ Examples:
parser.add_argument(
'--version',
action='version',
version='MbetterClient 1.0.32'
version='MbetterClient 1.0.33'
)
# Timer options
......
......@@ -4,7 +4,7 @@ MbetterClient - Cross-platform multimedia client application
A multi-threaded application with video playback, web dashboard, and REST API integration.
"""
__version__ = "1.0.32"
__version__ = "1.0.33"
__author__ = "MBetter Project"
__email__ = "dev@mbetter.net"
__description__ = "Cross-platform multimedia client with video overlay and web dashboard"
......
......@@ -262,7 +262,7 @@ class ApiConfig:
# Request settings
verify_ssl: bool = True
user_agent: str = "MbetterClient/1.0r32"
user_agent: str = "MbetterClient/1.0r33"
max_response_size_mb: int = 100
# Additional API client settings
......@@ -403,7 +403,7 @@ class AppSettings:
timer: TimerConfig = field(default_factory=TimerConfig)
# Application settings
version: str = "1.0.32"
version: str = "1.0.33"
debug_mode: bool = False
dev_message: bool = False # Enable debug mode showing only message bus messages
debug_messages: bool = False # Show all messages passing through the message bus on screen
......
......@@ -71,9 +71,19 @@ def extract_balanced_safe(results, odds, current_balance, stake, payouts, house_
mean_payout = sum(payout_values) / len(payout_values)
span = max(max_achievable - min_achievable, 1.0)
# How severely negative is the balance relative to this stake?
# 0.0 = balanced, 1.0 = deficit >= 2× stake (strong steering needed)
balance_severity = min(max(-current_balance, 0.0) / max(stake * 2.0, 1.0), 1.0)
# Widen the drift window as deficit grows: 0.40 when balanced → 0.95 at full severity
effective_max_drift = max_drift + (0.95 - max_drift) * balance_severity
# Lower the correction floor as deficit grows: 0.35 when balanced → 0.05 at full severity
correction_floor = 0.35 * (1.0 - 0.857 * balance_severity)
ext_logger.info(
f"🔍 [EXTRACT_BALANCED] Step 3 - payout range=[{min_achievable:.2f}, {max_achievable:.2f}], "
f"base_target={expected_redistribution:.2f}, adjusted_target={target_payout:.2f}"
f"base_target={expected_redistribution:.2f}, adjusted_target={target_payout:.2f}, "
f"balance_severity={balance_severity:.3f}, effective_max_drift={effective_max_drift:.3f}, "
f"correction_floor={correction_floor:.4f}"
)
final_weights = []
......@@ -84,10 +94,10 @@ def extract_balanced_safe(results, odds, current_balance, stake, payouts, house_
payout_position = abs(payout - mean_payout) / span
centrality = 1.0 - payout_position
blended = (0.50 * closeness) + (0.35 * normalized_base_probs[i]) + (0.15 * centrality)
correction = 0.35 + (1.9 * blended)
correction = correction_floor + ((2.25 - correction_floor) * blended)
lower_bound = base_weight * (1 - max_drift)
upper_bound = base_weight * (1 + max_drift)
lower_bound = base_weight * (1 - effective_max_drift)
upper_bound = base_weight * (1 + effective_max_drift)
corrected = base_weight * correction
final_weight = max(min(corrected, upper_bound), lower_bound)
final_weights.append(final_weight)
......
......@@ -247,7 +247,7 @@ class WebDashboard(ThreadedComponent):
def inject_globals():
return {
'app_name': 'MbetterClient',
'app_version': '1.0.32',
'app_version': '1.0.33',
'current_time': time.time(),
}
......
......@@ -337,7 +337,8 @@ def test_extract_balanced_safe_benchmark_documents_target_error_vs_legacy():
assert metrics["current"] > 0
assert metrics["candidate_v4"] > 0
assert metrics["legacy"] > 0
assert abs(metrics["current"] - metrics["candidate_v4"]) < 1e-9
# current now uses adaptive max_drift/correction_floor; it may differ from candidate_v4
assert metrics["current"] <= metrics["candidate_v4"] * 1.10
def test_extract_balanced_candidate_v2_benchmark_documents_three_way_comparison():
......@@ -356,7 +357,7 @@ def test_extract_balanced_candidate_v2_benchmark_documents_three_way_comparison(
assert metrics["candidate_v2"] > 0
assert metrics["candidate_v3"] > 0
assert metrics["legacy"] > 0
assert abs(metrics["current"] - metrics["candidate_v4"]) < 1e-9
assert metrics["current"] <= metrics["candidate_v4"] * 1.10
def test_extract_balanced_controller_ordering_across_seeded_scenarios():
......@@ -392,7 +393,7 @@ def test_extract_balanced_controller_ordering_across_seeded_scenarios():
assert totals["candidate_v3"] > 0
assert totals["candidate_v4"] > 0
assert totals["legacy"] > 0
assert abs(totals["current"] - totals["candidate_v4"]) < 1e-9
assert totals["current"] <= totals["candidate_v4"] * 1.10
assert totals["current"] < totals["legacy"]
assert sum(wins.values()) == len(scenarios)
assert len(per_scenario) == len(scenarios)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment