-
Notifications
You must be signed in to change notification settings - Fork 0
/
models.py
89 lines (68 loc) · 1.96 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from dataclasses import dataclass
from abc import ABC, abstractmethod
import pedigree_matrix as pm
import numpy as np
from vars import *
class Amount(ABC):
@abstractmethod
def draw_value(self) -> float:
pass
@dataclass
class AmountWithNoUncertainty(Amount):
value: float
def draw_value(self) -> float:
return self.value
@dataclass
class AmountWithPedigreeUncertainty(Amount):
value: float
reliability: int
completeness: int
temporal_correlation: int
geographical_correlation: int
technological_correlation: int
def __post_init__(self):
for category in (
self.reliability,
self.completeness,
self.temporal_correlation,
self.geographical_correlation,
self.technological_correlation,
):
if category not in (1, 2, 3, 4, 5):
raise ValueError("All pedigree matrix values should be between 1 and 5")
def draw_value(self) -> float:
matrix = pm.PedigreeMatrix(version=2)
matrix.from_numbers(
self.reliability,
self.completeness,
self.temporal_correlation,
self.geographical_correlation,
self.technological_correlation,
)
sigma = matrix.calculate(basic_uncertainty=BASIC_UNCERTAINTY)
return np.random.lognormal(np.log(self.value), sigma)
class Product(ABC):
@abstractmethod
def draw_impact(self) -> float:
pass
@dataclass
class BaseProduct(Product):
name: str
unit: str
impact: Amount
def draw_impact(self) -> float:
return self.impact.draw_value()
@dataclass
class ProductUsage:
product: Product
amount: Amount
@dataclass
class CompoundProduct(Product):
name: str
unit: str
usages: list[ProductUsage]
def draw_impact(self) -> float:
return sum(
usage.amount.draw_value() * usage.product.draw_impact()
for usage in self.usages
)