decision-tree-analyzer
Decision tree analysis skill with expected value, risk analysis, and utility theory.
What this skill does
# decision-tree-analyzer
You are **decision-tree-analyzer** - a specialized skill for decision tree analysis including expected value calculations, risk analysis, and utility theory applications.
## Overview
This skill enables AI-powered decision tree analysis including:
- Decision tree construction
- Expected Monetary Value (EMV) calculation
- Expected Value of Perfect Information (EVPI)
- Expected Value of Sample Information (EVSI)
- Risk profiles and sensitivity
- Utility function application
- Decision rollback analysis
- Multi-stage sequential decisions
## Capabilities
### 1. Decision Tree Construction
```python
import numpy as np
from dataclasses import dataclass
from typing import List, Dict, Optional
from enum import Enum
class NodeType(Enum):
DECISION = "decision"
CHANCE = "chance"
TERMINAL = "terminal"
@dataclass
class TreeNode:
node_id: str
node_type: NodeType
name: str
value: float = 0 # For terminal nodes
probability: float = 1.0 # For chance branches
children: List['TreeNode'] = None
parent: Optional['TreeNode'] = None
def __post_init__(self):
if self.children is None:
self.children = []
def build_decision_tree(structure: dict):
"""
Build decision tree from structure definition
structure: nested dict defining tree
{
'type': 'decision',
'name': 'Initial Decision',
'branches': [
{
'name': 'Option A',
'type': 'chance',
'branches': [
{'name': 'High', 'probability': 0.3, 'value': 100},
{'name': 'Low', 'probability': 0.7, 'value': 50}
]
}
]
}
"""
def build_node(data, parent=None, node_id='root'):
node_type = NodeType(data.get('type', 'terminal'))
node = TreeNode(
node_id=node_id,
node_type=node_type,
name=data.get('name', ''),
value=data.get('value', 0),
probability=data.get('probability', 1.0),
parent=parent
)
if 'branches' in data:
for i, branch in enumerate(data['branches']):
child = build_node(branch, node, f"{node_id}_{i}")
node.children.append(child)
return node
root = build_node(structure)
return root
```
### 2. Expected Monetary Value (EMV)
```python
def calculate_emv(node: TreeNode):
"""
Calculate Expected Monetary Value using rollback analysis
"""
results = {}
def rollback(n):
if n.node_type == NodeType.TERMINAL:
return n.value
if n.node_type == NodeType.CHANCE:
# EMV is weighted average of outcomes
emv = sum(child.probability * rollback(child) for child in n.children)
results[n.node_id] = {'name': n.name, 'emv': emv, 'type': 'chance'}
return emv
if n.node_type == NodeType.DECISION:
# Choose maximum EMV branch
child_values = [(child, rollback(child)) for child in n.children]
best_child, best_value = max(child_values, key=lambda x: x[1])
results[n.node_id] = {
'name': n.name,
'emv': best_value,
'type': 'decision',
'best_choice': best_child.name,
'all_choices': {c.name: v for c, v in child_values}
}
return best_value
final_emv = rollback(node)
return {
"emv": round(final_emv, 2),
"node_values": results,
"optimal_strategy": extract_optimal_strategy(results)
}
def extract_optimal_strategy(results):
"""Extract optimal decision path"""
strategy = []
for node_id, data in results.items():
if data['type'] == 'decision':
strategy.append({
'decision': data['name'],
'choice': data['best_choice'],
'emv': round(data['emv'], 2)
})
return strategy
```
### 3. Expected Value of Perfect Information (EVPI)
```python
def calculate_evpi(decision_node: TreeNode):
"""
Calculate Expected Value of Perfect Information
EVPI = EV with perfect information - EMV without information
"""
# First, get EMV without perfect information
emv_result = calculate_emv(decision_node)
emv_without = emv_result['emv']
# Calculate EV with perfect information
# For each state of nature, choose best decision
states = collect_chance_outcomes(decision_node)
ev_with_perfect = 0
perfect_decisions = {}
for state, prob in states.items():
# For this state, find best decision
best_value = float('-inf')
best_decision = None
for decision_branch in decision_node.children:
value = get_value_given_state(decision_branch, state)
if value > best_value:
best_value = value
best_decision = decision_branch.name
ev_with_perfect += prob * best_value
perfect_decisions[state] = {'decision': best_decision, 'value': best_value}
evpi = ev_with_perfect - emv_without
return {
"evpi": round(evpi, 2),
"ev_with_perfect_info": round(ev_with_perfect, 2),
"emv_without_info": round(emv_without, 2),
"perfect_decisions": perfect_decisions,
"interpretation": f"Worth up to ${round(evpi, 2)} for perfect information"
}
def collect_chance_outcomes(node, outcomes=None, current_prob=1.0):
"""Collect all chance outcomes and their probabilities"""
if outcomes is None:
outcomes = {}
if node.node_type == NodeType.TERMINAL:
return outcomes
if node.node_type == NodeType.CHANCE:
for child in node.children:
outcomes[child.name] = child.probability
collect_chance_outcomes(child, outcomes, current_prob * child.probability)
for child in node.children:
collect_chance_outcomes(child, outcomes, current_prob)
return outcomes
def get_value_given_state(node, state):
"""Get value of a branch given a specific state occurs"""
# Simplified - would need full tree traversal
for child in node.children:
if child.name == state:
return child.value if child.node_type == NodeType.TERMINAL else 0
result = get_value_given_state(child, state)
if result != 0:
return result
return 0
```
### 4. Risk Profile Analysis
```python
def create_risk_profile(decision_node: TreeNode, decision_choice: str = None):
"""
Create risk profile showing probability distribution of outcomes
"""
outcomes = []
def collect_outcomes(node, current_prob=1.0, path=None):
if path is None:
path = []
if node.node_type == NodeType.TERMINAL:
outcomes.append({
'value': node.value,
'probability': current_prob,
'path': ' -> '.join(path)
})
return
if node.node_type == NodeType.CHANCE:
for child in node.children:
collect_outcomes(child, current_prob * child.probability,
path + [child.name])
elif node.node_type == NodeType.DECISION:
if decision_choice:
for child in node.children:
if child.name == decision_choice:
collect_outcomes(child, current_prob, path + [child.name])
else:
# Use optimal decision
emv_result = calculate_emv(node)
best = emv_result['node_values'].get(node.node_id, {}).get('best_choice')
for child in node.children:
if child.name == best:
collect_outcomes(child, current_prob, path + [child.name])
collect_outcomes(decision_node)
# Aggregate by value
value_probs = {}
for outcome in outcomes:
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.