Skip to content

auto_math_lyapunov_stability_6

github-actions[bot] edited this page Jul 20, 2026 · 2 revisions

Snippet from Math-Lyapunov-Stability.md

from compitum.control import LyapunovController

# The real LyapunovController takes (kappa, r0, integral_gain) -- not
# initial_radius alone -- and update() always executes, returning
# (eta_cap, status) rather than an (radius, accept, metrics) gate tuple.
# This adapts the idea (accept the first task that doesn't destabilize the
# controller too much) using the real API: accept the first task whose
# resulting trust_radius stays above a floor, instead of a fictional
# lyapunov_gate() accept/reject call.


class TaskSequencer:
    """Lyapunov-based adaptive task difficulty manager."""

    def __init__(self):
        self.controller = LyapunovController(kappa=0.1, r0=1.0, integral_gain=0.005)
        self.student_load = 0.5  # Initial cognitive load

    def assess_load(self, task_complexity: float, student_state: dict) -> float:
        """Estimate cognitive load for proposed task."""
        base_load = task_complexity
        fatigue_factor = student_state.get("fatigue", 0)
        confidence_bonus = student_state.get("confidence", 0.5)
        return base_load * (1 + fatigue_factor) * (2 - confidence_bonus)

    def propose_task(self, task_pool: list, student_state: dict, min_trust_radius: float = 0.5) -> dict:
        """Select next task using the real controller's trust_radius as a stability gate."""
        current_load = self.student_load

        for task in sorted(task_pool, key=lambda t: t["complexity"]):
            proposed_load = self.assess_load(task["complexity"], student_state)
            d_star = max(proposed_load - current_load, 0.0)

            eta_cap, status = self.controller.update(d_star, grad_norm=1.0)

            if status["trust_radius"] >= min_trust_radius:
                self.student_load = proposed_load
                return {
                    "task": task,
                    "expected_load": proposed_load,
                    "status": status,
                }

        # If every task drops trust_radius below the floor, return a recovery task
        return {
            "task": {"name": "Review", "complexity": 0.1},
            "expected_load": 0.1,
            "status": {"trust_radius": self.controller.trust_radius},
        }


# Usage
sequencer = TaskSequencer()
tasks = [
    {"name": "Basic Algebra", "complexity": 0.3},
    {"name": "Word Problems", "complexity": 0.6},
    {"name": "Proof Writing", "complexity": 0.9},
]
student = {"fatigue": 0.2, "confidence": 0.7}

next_task = sequencer.propose_task(tasks, student)
print(f"Assigned: {next_task['task']['name']}")
print(f"Expected load: {next_task['expected_load']:.2f}")
print(f"Trust radius after: {next_task['status']['trust_radius']:.4f}")

Clone this wiki locally