Source code for smart_choice.probabilistic_sensitivity

"""
Probabilistic Sensitivity Analysis
===============================================================================


"""
from typing import Any
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


from .decisiontree import DecisionTree


LINEFMTS = [
    "-k",
    "--k",
    ".-k",
    ":k",
    "-r",
    "--r",
    ".-r",
    ":r",
    "-g",
    "--g",
    ".-g",
    ":g",
]


[docs]class ProbabilisticSensitivity: """Display a probabilistic sensitivity plot for a chance node. :param tree: Decision tree to be analized. :param varname: Name of the variable. :param idx: Identification number of the node of the tree used to collect the results. The identifier of the root node is `0` . """ def __init__(self, decisiontree: DecisionTree, varname: str, idx: int = 0) -> Any: self._decisiontree = decisiontree.copy() self._varname = varname self._idx = idx # # Algorithm # type_ = self._decisiontree._data_nodes[varname]["type"] if type_ != "CHANCE": raise ValueError('Variable {} is {} != "CHANCE"'.format(varname, type_)) type_root = self._decisiontree._tree_nodes[self._idx].get("type") if type_root == "CHANCE": self.probabilistic_sensitivity_chance() if type_root == "DECISION": self.probabilistic_sensitivity_decision() def __repr__(self): return self.df_.__repr__() def _get_top_bottom_branches(self): ( self._top_branch, self._bottom_branch, ) = self._decisiontree._data_nodes.get_top_bottom_branches(self._varname) def _set_branch_probabilities_to_zero(self): for i_node, node in enumerate(self._decisiontree._tree_nodes): tag_name = node.get("tag_name") if tag_name == self._varname: self._decisiontree._tree_nodes[i_node]["tag_prob"] = 0 def _set_branch_probabilities(self, top_probability): for i_node, node in enumerate(self._decisiontree._tree_nodes): tag_name = node.get("tag_name") if tag_name == self._varname: tag_branch = node.get("tag_branch") if tag_branch == self._top_branch: self._decisiontree._tree_nodes[i_node]["tag_prob"] = ( 1 - top_probability ) if tag_branch == self._bottom_branch: self._decisiontree._tree_nodes[i_node]["tag_prob"] = top_probability
[docs] def probabilistic_sensitivity_chance(self) -> None: self._get_top_bottom_branches() self._set_branch_probabilities_to_zero() self.probabilities_ = np.linspace(start=0, stop=1, num=21).tolist() self.expected_values_ = [] for top_probability in self.probabilities_: self._set_branch_probabilities(top_probability) self._decisiontree.rollback() expval = self._decisiontree._tree_nodes[self._idx].get("EV") self.expected_values_.append(expval) self.df_ = pd.DataFrame( { "Probability": self.probabilities_, "Expected Value": self.expected_values_, } )
[docs] def probabilistic_sensitivity_decision(self) -> None: self._get_top_bottom_branches() self._set_branch_probabilities_to_zero() successors = self._decisiontree._tree_nodes[self._idx].get("successors") tag_branches = [ self._decisiontree._tree_nodes[successor].get("tag_branch") for successor in successors ] self.expected_values_ = {} for tag_branch in tag_branches: self.expected_values_[tag_branch] = [] self.probabilities_ = np.linspace(start=0, stop=1, num=21).tolist() for top_probability in self.probabilities_: self._set_branch_probabilities(top_probability) self._decisiontree.rollback() expvals = [ self._decisiontree._tree_nodes[successor].get("EV") for successor in successors ] for expval, tag_branch in zip(expvals, tag_branches): self.expected_values_[tag_branch].append(expval) self.df_ = pd.concat( [ pd.DataFrame( { "Branch": [str(tag_branch)] * len(self.probabilities_), "Probability": self.probabilities_, "Value": self.expected_values_[tag_branch], } ) for tag_branch in self.expected_values_.keys() ] )
[docs] def plot(self): """Plots the sensitivty to probability.""" if isinstance(self.expected_values_, dict): for fmt, tag_branch in zip(LINEFMTS, self.expected_values_.keys()): plt.gca().plot( self.probabilities_, self.expected_values_[tag_branch], fmt, label=tag_branch, ) else: plt.gca().plot(self.probabilities_, self.expected_values_, "-k") plt.gca().spines["bottom"].set_visible(False) plt.gca().spines["left"].set_visible(False) plt.gca().spines["right"].set_visible(False) plt.gca().spines["top"].set_visible(False) plt.gca().set_ylabel("Expected values") plt.gca().set_xlabel("Probability") plt.legend() plt.grid()