File size: 1,843 Bytes
cc6e5ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from __future__ import annotations

import numpy as np


INITIAL_DETECTION_LEVEL = 0.3
INITIAL_ENERGY = 1.0
INITIAL_FATIGUE = 0.0
VALUE_RANGE = (0.0, 1.0)
DETECTION_DECAY = 0.97
FATIGUE_GAIN_THRESHOLD = 0.7
FATIGUE_GAIN_MULTIPLIER = 0.5

B_CELL_TRANSITIONS = {
    "INCREASE_HIGH": {"detection_delta": 0.15, "energy_delta": -0.20, "fatigue_delta": 0.10},
    "INCREASE_LOW": {"detection_delta": 0.08, "energy_delta": -0.10, "fatigue_delta": 0.04},
    "MAINTAIN": {"detection_delta": 0.0, "energy_delta": -0.03, "fatigue_delta": 0.0},
    "REDUCE": {"detection_delta": -0.10, "energy_delta": 0.18, "fatigue_delta": -0.12},
}


def _clip_unit(value: float) -> float:
    return float(np.clip(value, *VALUE_RANGE))


class BCellAgent:
    def __init__(self) -> None:
        self.reset()

    def reset(self) -> None:
        self.detection_level = _clip_unit(INITIAL_DETECTION_LEVEL)
        self.energy = _clip_unit(INITIAL_ENERGY)
        self.fatigue = _clip_unit(INITIAL_FATIGUE)

    def step(self, action: str) -> None:
        transition = B_CELL_TRANSITIONS.get(action, B_CELL_TRANSITIONS["MAINTAIN"])
        detection_delta = float(transition["detection_delta"])

        if self.fatigue > FATIGUE_GAIN_THRESHOLD and detection_delta > 0.0:
            detection_delta *= FATIGUE_GAIN_MULTIPLIER

        self.detection_level = _clip_unit(self.detection_level * DETECTION_DECAY)
        self.detection_level = _clip_unit(self.detection_level + detection_delta)
        self.energy = _clip_unit(self.energy + float(transition["energy_delta"]))
        self.fatigue = _clip_unit(self.fatigue + float(transition["fatigue_delta"]))

    def get_state(self) -> dict:
        return {
            "detection_level": float(self.detection_level),
            "energy": float(self.energy),
            "fatigue": float(self.fatigue),
        }