Class: Legion::Extensions::Agentic::Attention::SignalDetection::Helpers::DetectionEngine
- Inherits:
-
Object
- Object
- Legion::Extensions::Agentic::Attention::SignalDetection::Helpers::DetectionEngine
- Defined in:
- lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb
Instance Method Summary collapse
- #adjust_bias(detector_id:, amount:) ⇒ Object
- #best_detectors(limit: 5) ⇒ Object
- #by_domain(domain:) ⇒ Object
- #compute_sensitivity(detector_id:) ⇒ Object
- #count ⇒ Object
- #create_detector(domain:) ⇒ Object
- #decay_all ⇒ Object
- #get(detector_id) ⇒ Object
-
#initialize ⇒ DetectionEngine
constructor
A new instance of DetectionEngine.
- #optimal_criterion(detector_id:, signal_probability: 0.5) ⇒ Object
- #record_trial(detector_id:, signal_present:, responded_present:) ⇒ Object
- #roc_point(detector_id:) ⇒ Object
- #to_h ⇒ Object
Constructor Details
#initialize ⇒ DetectionEngine
Returns a new instance of DetectionEngine.
10 11 12 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 10 def initialize @detectors = {} end |
Instance Method Details
#adjust_bias(detector_id:, amount:) ⇒ Object
43 44 45 46 47 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 43 def adjust_bias(detector_id:, amount:) detector = fetch!(detector_id) detector.adjust_criterion(amount: amount) { detector_id: detector_id, criterion: detector.criterion, bias_label: detector.bias_label } end |
#best_detectors(limit: 5) ⇒ Object
49 50 51 52 53 54 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 49 def best_detectors(limit: 5) @detectors.values .sort_by { |d| -d.sensitivity } .first(limit) .map(&:to_h) end |
#by_domain(domain:) ⇒ Object
56 57 58 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 56 def by_domain(domain:) @detectors.values.select { |d| d.domain == domain }.map(&:to_h) end |
#compute_sensitivity(detector_id:) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 29 def compute_sensitivity(detector_id:) detector = fetch!(detector_id) { detector_id: detector_id, d_prime: detector.compute_dprime, criterion: detector.compute_criterion, accuracy: detector.accuracy, hit_rate: detector.hit_rate, false_alarm_rate: detector.false_alarm_rate, sensitivity_label: detector.sensitivity_label, bias_label: detector.bias_label } end |
#count ⇒ Object
99 100 101 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 99 def count @detectors.size end |
#create_detector(domain:) ⇒ Object
14 15 16 17 18 19 20 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 14 def create_detector(domain:) raise ArgumentError, "max detectors reached (#{Constants::MAX_DETECTORS})" if @detectors.size >= Constants::MAX_DETECTORS detector = Detector.new(domain: domain) @detectors[detector.id] = detector detector end |
#decay_all ⇒ Object
84 85 86 87 88 89 90 91 92 93 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 84 def decay_all count = 0 @detectors.each_value do |detector| next if detector.trial_count.zero? detector.adjust_criterion(amount: Constants::DECAY_RATE * -detector.criterion.clamp(-1, 1)) count += 1 end count end |
#get(detector_id) ⇒ Object
95 96 97 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 95 def get(detector_id) @detectors[detector_id] end |
#optimal_criterion(detector_id:, signal_probability: 0.5) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 60 def optimal_criterion(detector_id:, signal_probability: 0.5) detector = fetch!(detector_id) # Optimal criterion for equal cost: c* = 0.5 * ln((1-p)/p) in likelihood ratio terms # In SDT criterion units: shift from neutral based on prior probability prior_ratio = (1.0 - signal_probability) / signal_probability.clamp(0.001, 0.999) optimal = 0.5 * Math.log(prior_ratio) { detector_id: detector_id, optimal_criterion: Constants.clamp_criterion(optimal), current_criterion: detector.criterion, signal_probability: signal_probability } end |
#record_trial(detector_id:, signal_present:, responded_present:) ⇒ Object
22 23 24 25 26 27 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 22 def record_trial(detector_id:, signal_present:, responded_present:) detector = fetch!(detector_id) outcome = classify_outcome(signal_present: signal_present, responded_present: responded_present) detector.record_trial(outcome: outcome) { detector_id: detector_id, outcome: outcome, trial_count: detector.trial_count } end |
#roc_point(detector_id:) ⇒ Object
74 75 76 77 78 79 80 81 82 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 74 def roc_point(detector_id:) detector = fetch!(detector_id) { detector_id: detector_id, hit_rate: detector.hit_rate, false_alarm_rate: detector.false_alarm_rate, d_prime: detector.sensitivity } end |
#to_h ⇒ Object
103 104 105 106 107 108 |
# File 'lib/legion/extensions/agentic/attention/signal_detection/helpers/detection_engine.rb', line 103 def to_h { detector_count: @detectors.size, detectors: @detectors.transform_values(&:to_h) } end |