https://github.com/danylevych/precision-tree
Precision Tree Module for precision decision analysis, supporting custom nodes (Decision, Chance, and Payoff) with visualization and optimal path calculation.
https://github.com/danylevych/precision-tree
decsion-tree precision-tree pypl python python3
Last synced: 5 months ago
JSON representation
Precision Tree Module for precision decision analysis, supporting custom nodes (Decision, Chance, and Payoff) with visualization and optimal path calculation.
- Host: GitHub
- URL: https://github.com/danylevych/precision-tree
- Owner: danylevych
- License: mit
- Created: 2024-11-23T14:36:44.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-11-26T18:57:54.000Z (over 1 year ago)
- Last Synced: 2025-09-25T13:00:02.909Z (9 months ago)
- Topics: decsion-tree, precision-tree, pypl, python, python3
- Language: Python
- Homepage: https://pypi.org/project/precision-tree/
- Size: 9.77 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Guide
- [Start](#start)
- [Modules](#modules)
- [Nodes](#nodes)
- [Tree](#tree)
- [Usage](#usage)
---
## Start
This is a library to create decision trees and calculate the expected value of the best strategy.
To install the library, run the following command:
```bash
pip install precision-tree
```
---
## Modules
The library has two main modules: `nodes` and `tree`.
The `nodes` module contains the classes to create the nodes of the decision tree. The `tree` module contains the class to wrap the root node and calculate the expected value of the best strategy and visualize the tree.
### Nodes
The `nodes` module contains the following classes:
- `DecisionNode`: Represents a decision node.
- `ChanceNode`: Represents a chance node.
- `PayoffNode`: Represents a payoff node.
All of the classes are subclasses of the `Node` class.
#### DecisionNode
The `DecisionNode` class represents a decision node (in graph it looks like a squere).
The following table shows the attributes of the `DecisionNode` class:
| Attribute | Description |
| --- | --- |
| `name` | The name of the node. |
| `branches` | A list of branches. |
The following table shows the methods of the `DecisionNode` class:
| Method | Description |
| --- | --- |
| `add_branch(self, label, child)` | Adds a branch to the node. `label` is the name of the branch and `child` is the child node. |
| `calculate_value` | Calculates the expected value of the best strategy. |
#### ChanceNode
The `ChanceNode` class represents a chance node (in graph it looks like a circle).
The following table shows the attributes of the `ChanceNode` class:
| Attribute | Description |
| --- | --- |
| `name` | The name of the node. |
| `cost` | The cost of the node. |
| `years` | The number of years. |
| `branches` | A list of branches. |
The following table shows the methods of the `ChanceNode` class:
| Method | Description |
| --- | --- |
| `add_branch(self, label, child, probability)` | Adds a branch to the node. `label` is the name of the branch, `child` is the child node, and `probability` is the probability of the branch. |
| `calculate_value` | Calculates the expected value of the best strategy. |
#### PayoffNode
The `PayoffNode` class represents a payoff node (in graph it looks like a triangle).
The following table shows the attributes of the `PayoffNode` class:
| Attribute | Description |
| --- | --- |
| `name` | The name of the node. |
| `value` | The value of the node. |
| `branches` | A list of branches. |
The following table shows the methods of the `PayoffNode` class:
| Method | Description |
| --- | --- |
| `calculate_value` | Calculates the expected value of the best strategy. |
### Tree
The `tree` module contains the `TreeWrapper` class.
The following table shows the attributes of the `TreeWrapper` class:
| Attribute | Description |
| --- | --- |
| `root` | The root node of the tree. |
The following table shows the methods of the `TreeWrapper` class:
| Method | Description |
| --- | --- |
| `show(self, title: str, format: str):` | Shows the tree. `title` is the title of the tree and `format` is the format of the file `png`, `pdf` etc. |
| `get_optimal_path` | Returns the optimal path as a tuple, where the first element is the optimal nodes and second element is the optimal edges. |
| `calculate_value` | Calculates the expected value of the best strategy. |
---
## Usage
**Example**
```python
from precision_tree.nodes import DecisionNode, ChanceNode, PayoffNode
from precision_tree.tree import TreeWrapper
root = DecisionNode("Decision")
# Decision Node Without Analytics
without_analytics = DecisionNode("Without Analytics")
big_factory = ChanceNode("Big Factory 1", cost=0, years=1)
big_factory.add_branch(label="Favorable P(0.7)", child=PayoffNode("Favorable 1", 200), probability=0.7)
big_factory.add_branch(label="Unfavorable P(0.3)", child=PayoffNode("Unfavorable 1", -180), probability=0.3)
small_factory = ChanceNode("Small Factory 1", cost=0, years=1)
small_factory.add_branch(label="Favorable P(0.7)", child=PayoffNode("Favorable 2", 100), probability=0.7)
small_factory.add_branch(label="Unfavorable P(0.3)", child=PayoffNode("Unfavorable 2", -20), probability=0.3)
without_analytics.add_branch(label="Big Factory", child=big_factory)
without_analytics.add_branch(label="Small Factory", child=small_factory)
without_analytics.add_branch(label="Sell Patent", child=PayoffNode("Sell Patent 1", 10))
# Make Decision Node With Analytics
with_analytics = ChanceNode("With Analytics", cost=8, years=1)
# Positive Result
positive_result = DecisionNode("Positive Result")
big_factory_positive = ChanceNode("Big Factory 2", cost=0, years=1)
big_factory_positive.add_branch(label="Favorable", child=PayoffNode("Favorable 3", 200), probability=0.81)
big_factory_positive.add_branch(label="Unfavorable", child=PayoffNode("Unfavorable 3", -180), probability=0.19)
small_factory_positive = ChanceNode("Small Factory 2", cost=0, years=1)
small_factory_positive.add_branch(label="Favorable", child=PayoffNode("Favorable 4", 100), probability=0.81)
small_factory_positive.add_branch(label="Unfavorable", child=PayoffNode("Unfavorable 4", -20), probability=0.19)
positive_result.add_branch(label="Big Factory", child=big_factory_positive)
positive_result.add_branch(label="Small Factory", child=small_factory_positive)
positive_result.add_branch(label="Sell Patent", child=PayoffNode("Sell Patent 2", 10))
# Negative Result
negative_result = DecisionNode("Negative Result")
big_factory_negative = ChanceNode("Big Factory 3", cost=0, years=1)
big_factory_negative.add_branch(label="Favorable", child=PayoffNode("Favorable 5", 200), probability=0.28)
big_factory_negative.add_branch(label="Unfavorable", child=PayoffNode("Unfavorable 5", -180), probability=0.72)
small_factory_negative = ChanceNode("Small Factory 3", cost=0, years=1)
small_factory_negative.add_branch(label="Favorable", child=PayoffNode("Favorable 6", 100), probability=0.28)
small_factory_negative.add_branch(label="Unfavorable", child=PayoffNode("Unfavorable 6", -20), probability=0.72)
negative_result.add_branch(label="Big Factory", child=big_factory_negative)
negative_result.add_branch(label="Small Factory", child=small_factory_negative)
negative_result.add_branch(label="Sell Patent", child=PayoffNode("Sell Patent 3", 10))
with_analytics.add_branch(label="Positive Result", child=positive_result, probability=0.48)
with_analytics.add_branch(label="Negative Result", child=negative_result, probability=0.52)
# Add Branches to Root
root.add_branch(label="With Analytics", child=with_analytics)
root.add_branch(label="Without Analytics", child=without_analytics)
tree = TreeWrapper(root)
print(f"Expected Value of the best strategy: {tree.calculate_value():.2f}")
print(f"Optimal branch: {tree.get_optimal_path()[0]}")
```
**Output**
```bash
Expected Value of the best strategy: 86.00
Optimal branch: {'Unfavorable 1', 'Favorable 1', 'Big Factory 1', 'Without Analytics', 'Decision'}
```