Class: DecisionAgent::Simulation::WhatIfAnalyzer
- Inherits:
-
Object
- Object
- DecisionAgent::Simulation::WhatIfAnalyzer
- Defined in:
- lib/decision_agent/simulation/what_if_analyzer.rb
Overview
Analyzer for what-if scenario simulation
Defined Under Namespace
Classes: GridConfig
Instance Attribute Summary collapse
-
#agent ⇒ Object
readonly
Returns the value of attribute agent.
-
#version_manager ⇒ Object
readonly
Returns the value of attribute version_manager.
Instance Method Summary collapse
-
#analyze(scenarios:, rule_version: nil, options: {}) ⇒ Hash
Analyze multiple scenarios.
- #analyze_field_variations(base_scenario, variations, base_decision_value, analysis_agent) ⇒ Object
- #build_field_result(value, decision, base_decision_value) ⇒ Object
- #build_field_sensitivity(field_results, values_size, base_decision_value) ⇒ Object
- #build_sensitivity_result(base_scenario, base_decision_value, base_confidence, sensitivity_results) ⇒ Object
-
#initialize(agent:, version_manager: nil) ⇒ WhatIfAnalyzer
constructor
A new instance of WhatIfAnalyzer.
-
#sensitivity_analysis(base_scenario:, variations:, rule_version: nil) ⇒ Hash
Perform sensitivity analysis to identify which inputs affect decisions most.
- #test_field_values(base_scenario, field, values, base_decision_value, analysis_agent) ⇒ Object
-
#visualize_decision_boundaries(base_scenario:, parameters:, rule_version: nil, options: {}) ⇒ Hash
Visualize decision boundaries for 1D or 2D parameter spaces.
Constructor Details
#initialize(agent:, version_manager: nil) ⇒ WhatIfAnalyzer
Returns a new instance of WhatIfAnalyzer.
11 12 13 14 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 11 def initialize(agent:, version_manager: nil) @agent = agent @version_manager = version_manager || Versioning::VersionManager.new end |
Instance Attribute Details
#agent ⇒ Object (readonly)
Returns the value of attribute agent.
9 10 11 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 9 def agent @agent end |
#version_manager ⇒ Object (readonly)
Returns the value of attribute version_manager.
9 10 11 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 9 def version_manager @version_manager end |
Instance Method Details
#analyze(scenarios:, rule_version: nil, options: {}) ⇒ Hash
Analyze multiple scenarios
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 24 def analyze(scenarios:, rule_version: nil, options: {}) = { parallel: true, thread_count: 4, sensitivity_analysis: false }.merge() analysis_agent = build_agent_from_version(rule_version) if rule_version analysis_agent ||= @agent results = execute_scenarios(scenarios, analysis_agent, ) report = { scenarios: results, total_scenarios: scenarios.size, decision_distribution: results.group_by { |r| r[:decision] }.transform_values(&:count), average_confidence: calculate_average_confidence(results) } report[:sensitivity] = perform_sensitivity_analysis(scenarios, analysis_agent) if [:sensitivity_analysis] report end |
#analyze_field_variations(base_scenario, variations, base_decision_value, analysis_agent) ⇒ Object
69 70 71 72 73 74 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 69 def analyze_field_variations(base_scenario, variations, base_decision_value, analysis_agent) variations.each_with_object({}) do |(field, values), results| field_results = test_field_values(base_scenario, field, values, base_decision_value, analysis_agent) results[field] = build_field_sensitivity(field_results, values.size, base_decision_value) end end |
#build_field_result(value, decision, base_decision_value) ⇒ Object
85 86 87 88 89 90 91 92 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 85 def build_field_result(value, decision, base_decision_value) { value: value, decision: decision.decision, confidence: decision.confidence, changed: decision.decision != base_decision_value } end |
#build_field_sensitivity(field_results, values_size, base_decision_value) ⇒ Object
94 95 96 97 98 99 100 101 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 94 def build_field_sensitivity(field_results, values_size, base_decision_value) changed_count = field_results.count { |r| r[:changed] } { impact: changed_count.to_f / values_size, results: field_results, base_decision: base_decision_value } end |
#build_sensitivity_result(base_scenario, base_decision_value, base_confidence, sensitivity_results) ⇒ Object
103 104 105 106 107 108 109 110 111 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 103 def build_sensitivity_result(base_scenario, base_decision_value, base_confidence, sensitivity_results) { base_scenario: base_scenario, base_decision: base_decision_value, base_confidence: base_confidence, field_sensitivity: sensitivity_results, most_sensitive_fields: sensitivity_results.sort_by { |_k, v| -v[:impact] }.to_h.keys } end |
#sensitivity_analysis(base_scenario:, variations:, rule_version: nil) ⇒ Hash
Perform sensitivity analysis to identify which inputs affect decisions most
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 53 def sensitivity_analysis(base_scenario:, variations:, rule_version: nil) analysis_agent = build_agent_from_version(rule_version) if rule_version analysis_agent ||= @agent base_decision = analysis_agent.decide(context: Context.new(base_scenario)) base_decision_value = base_decision.decision sensitivity_results = analyze_field_variations( base_scenario, variations, base_decision_value, analysis_agent ) build_sensitivity_result( base_scenario, base_decision_value, base_decision.confidence, sensitivity_results ) end |
#test_field_values(base_scenario, field, values, base_decision_value, analysis_agent) ⇒ Object
76 77 78 79 80 81 82 83 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 76 def test_field_values(base_scenario, field, values, base_decision_value, analysis_agent) values.map do |value| modified_scenario = base_scenario.dup set_nested_value(modified_scenario, field, value) decision = analysis_agent.decide(context: Context.new(modified_scenario)) build_field_result(value, decision, base_decision_value) end end |
#visualize_decision_boundaries(base_scenario:, parameters:, rule_version: nil, options: {}) ⇒ Hash
Visualize decision boundaries for 1D or 2D parameter spaces
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/decision_agent/simulation/what_if_analyzer.rb', line 121 def visualize_decision_boundaries(base_scenario:, parameters:, rule_version: nil, options: {}) = { output_format: "data", resolution: nil }.merge() analysis_agent = build_agent_from_version(rule_version) if rule_version analysis_agent ||= @agent # Validate parameters param_keys = parameters.keys raise ArgumentError, "Must specify 1 or 2 parameters for visualization" if param_keys.empty? || param_keys.size > 2 # Set default resolution resolution = [:resolution] || (param_keys.size == 1 ? 100 : 30) if param_keys.size == 1 visualize_1d_boundary(base_scenario, param_keys.first, parameters[param_keys.first], analysis_agent, ) else config = { base_scenario: base_scenario, param1_name: param_keys[0], param2_name: param_keys[1], param1_config: parameters[param_keys[0]], param2_config: parameters[param_keys[1]], analysis_agent: analysis_agent, resolution: resolution, output_options: } visualize_2d_boundary(config) end end |