Coverage for lapspython/stats.py: 100%

48 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-08-27 20:15 +0200

1"""Collect statistics for program translations.""" 

2 

3from typing import List 

4 

5import numpy as np 

6import uniplot 

7from scipy import stats 

8 

9from lapspython.types import CompactFrontier, CompactResult 

10 

11 

12class Statistics: 

13 """Collect statistics for translated frontiers and results.""" 

14 

15 stats: dict 

16 

17 def __init__(self, result: CompactResult = None): 

18 """Construct object and optionally summarized result. 

19 

20 :param result: Extracted and translated programs. 

21 :type result: CompactResult, optional 

22 """ 

23 self.stats = {} 

24 

25 if result is not None: 

26 self.summarize(result) 

27 

28 def __str__(self) -> str: 

29 """Convert summary to string.""" 

30 return '\n'.join([f'{k}:\t{v}' for k, v in self.stats.items()]) 

31 

32 def summarize(self, result: CompactResult) -> dict: 

33 """Compute descriptive statistics for given result. 

34 

35 :param result: Translated checkpoint. 

36 :type result: lapspython.types.CompactResult 

37 :returns: Descriptive statistics. 

38 :rtype: dict 

39 """ 

40 program_count = self.count_programs(result) 

41 self.stats.update({'programs': program_count}) 

42 translation_count = self.count_translations(result) 

43 self.stats.update({'translations': translation_count}) 

44 

45 percentages = self.percentages_result(result) 

46 n_obs, minmax, mean, var, skew, kurtosis = stats.describe(percentages) 

47 self.stats.update({'tasks (total)': n_obs}) 

48 self.stats.update({'tasks (solved)': np.count_nonzero(percentages)}) 

49 self.stats.update({'median\t(%)': np.median(percentages)}) 

50 self.stats.update({'min\t(%)': minmax[0]}) 

51 self.stats.update({'max\t(%)': minmax[1]}) 

52 self.stats.update({'mean\t(%)': mean}) 

53 self.stats.update({'std\t(%)': np.sqrt(var)}) 

54 

55 return self.stats 

56 

57 def plot_histogram(self, result: CompactResult) -> None: 

58 """Print histogram of percentages to terminal. 

59 

60 :param result: Translated checkpoint. 

61 :type result: CompactResult 

62 """ 

63 percentages = self.percentages_result(result) 

64 uniplot.histogram(percentages) 

65 

66 def count_programs(self, result: CompactResult) -> int: 

67 """Count totals number of programs across all tasks. 

68 

69 :param result: Translated checkpoint. 

70 :type result: lapspython.types.CompactResult 

71 rtype: int  

72 """ 

73 program_count: int = 0 

74 for frontier in result.hit_frontiers.values(): 

75 program_count += len(frontier.programs) 

76 return program_count 

77 

78 def count_translations(self, result: CompactResult) -> int: 

79 """Count total number of correct translations across all tasks. 

80 

81 :param result: Translated checkpoint. 

82 :type result: lapspython.types.CompactResult 

83 :rtype: int 

84 """ 

85 translation_count: int = 0 

86 for frontier in result.hit_frontiers.values(): 

87 translation_count += len(frontier.translations) 

88 return translation_count 

89 

90 def percentages_result(self, result: CompactResult) -> List[float]: 

91 """Return percentage of correctly translated programs per frontier. 

92 

93 :param result: Translated checkpoint. 

94 :type result: lapspython.types.CompactResult 

95 :rtype: List[float] 

96 """ 

97 percentages: list = [] 

98 for frontier in result.hit_frontiers.values(): 

99 percentages.append(self.percentage_frontier(frontier)) 

100 return percentages 

101 

102 def percentage_frontier(self, frontier: CompactFrontier) -> float: 

103 """Return percentage of correctly translated programs. 

104 

105 :param result: Translated frontier (task). 

106 :type result: lapspython.types.CompactFrontier 

107 :rtype: float 

108 """ 

109 return len(frontier.translations) / len(frontier.programs) * 100