-
Notifications
You must be signed in to change notification settings - Fork 9
/
hierarchicalScorecard.py
58 lines (47 loc) · 2.09 KB
/
hierarchicalScorecard.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
# (c) 2021 - 2024 Open Risk (https://www.openriskmanagement.com)
#
# openRiskScore is licensed under the Apache 2.0 license a copy of which is included
# in the source distribution of openRiskScore. This is notwithstanding any licenses of
# third-party software included in this distribution. You may not use this file except in
# compliance with the License.
#
# Unless required by applicable law or agreed to in writing, software distributed under
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific language governing permissions and
# limitations under the License.
import networkx as nx
from networkx.readwrite import json_graph
class HierarchicalScorecard:
def __init__(self, structure):
self.structure = structure
self.G = json_graph.tree_graph(structure)
def score(self, data):
"""
The weight of each node is used to construct the weighted average partial score that is being aggregated to
the node parent (summing over all sibling nodes)
"""
leaf_nodes = [x for x in self.G.nodes() if self.G.out_degree(x) == 0]
path_scores = []
for x in leaf_nodes:
# construct path from root to leaf node of scorecard
path = nx.shortest_path(self.G, source='0', target=x)
scores = []
# get the partial score of the leaf node
i = len(path) - 1
weight = self.G.nodes[x]['weight'] # this weight should be unity
attribute = data[x]
partial_score = weight * attribute
i -= 1
scores.append(partial_score)
# iterate over path
while i >= 0:
node = path[i]
weight = self.G.nodes[node]['weight']
partial_score = weight * scores[0]
i -= 1
scores.insert(0, partial_score)
path_scores.append(scores)
total_score = 0
for scores in path_scores:
total_score += scores[0]
return round(total_score)