refactored Sums into a class in sumfinder (much cleaner) and added method to output Sums to stdout
This commit is contained in:
		
							parent
							
								
									6bcdade804
								
							
						
					
					
						commit
						e1d71014d4
					
				
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -1,22 +1,22 @@ | |||
| #!/usr/bin/env python3 | ||||
| from pathlib import Path | ||||
| from sumfinder import load_sums, remove_invalid_sums | ||||
| from sumfinder import Sums | ||||
| from linuxmem import read_meminfo_stdout | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     sums = load_sums(Path('../expe001.5/alambix97-meminfo-sums.json')) | ||||
|     print(f'starting sums ({len(sums)} sums):') | ||||
|     print(sums) | ||||
|     sums = Sums.load(Path('../expe001.5/alambix97-meminfo-sums.json')) | ||||
|     print(f'starting sums ({sums.get_num_equations()} sums):') | ||||
|     sums.print() | ||||
| 
 | ||||
|     variables = read_meminfo_stdout(Path('../bug3897/alambix98/20240806-223916-meminfo.stdout')) | ||||
|     # variables = read_meminfo_stdout(Path('../bug3897/alambix97/20240805-191606-meminfo.stdout')) | ||||
|     (valid_sums, invalid_sums) = remove_invalid_sums(sums, variables) | ||||
|     print(f'invalid sums ({len(invalid_sums)} sums):') | ||||
|     print(invalid_sums) | ||||
|     (valid_sums, invalid_sums) = sums.validate_on_variables(variables) | ||||
|     print(f'invalid sums ({invalid_sums.get_num_equations()} sums):') | ||||
|     invalid_sums.print() | ||||
| 
 | ||||
|     print(f'valid sums ({len(valid_sums)} sums):') | ||||
|     print(valid_sums) | ||||
|     print(f'valid sums ({valid_sums.get_num_equations()} sums):') | ||||
|     valid_sums.print() | ||||
| 
 | ||||
| 
 | ||||
| main() | ||||
|  |  | |||
|  | @ -1,7 +1,5 @@ | |||
| from .sumfinder import Sums  # noqa | ||||
| from .sumfinder import SumExporter  # noqa | ||||
| from .sumfinder import load_sums  # noqa | ||||
| from .sumfinder import find_sums  # noqa | ||||
| from .sumfinder import sums_to_dot  # noqa | ||||
| from .sumfinder import find_and_graph_sums  # noqa | ||||
| from .sumfinder import remove_invalid_sums  # noqa | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ import subprocess | |||
| 
 | ||||
| VarName = str | ||||
| VarValue = int | ||||
| Sums = List[Dict[VarName, List[VarName]]] | ||||
| Sum = Dict[VarName, List[VarName]] | ||||
| 
 | ||||
| 
 | ||||
| class IntVariable(): | ||||
|  | @ -24,6 +24,66 @@ class IntVariable(): | |||
|         return f'{self.name}: {self.value}' | ||||
| 
 | ||||
| 
 | ||||
| class Sums(): | ||||
| 
 | ||||
|     variables: Set[IntVariable] | ||||
|     sums: List[Sum] | ||||
| 
 | ||||
|     def __init__(self) -> None: | ||||
|         self.variables = set() | ||||
|         self.sums = [] | ||||
| 
 | ||||
|     def get_num_variables(self): | ||||
|         return len(self.variables) | ||||
| 
 | ||||
|     def get_num_equations(self): | ||||
|         return len(self.sums) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def load(sums_file_path: Path) -> 'Sums': | ||||
|         sums = Sums() | ||||
|         with open(sums_file_path, 'rt', encoding='utf8') as sums_file: | ||||
|             root_dict = json.loads(sums_file.read()) | ||||
|         assert root_dict['format'] == 'sums-v001' | ||||
|         sums.sums = root_dict['sums'] | ||||
|         sums.variables = {IntVariable(var_id, var_value) for var_id, var_value in root_dict['variables'].items()} | ||||
|         return sums | ||||
| 
 | ||||
|     def save(self, sums_file_path: Path): | ||||
|         root_dict = {} | ||||
|         root_dict['format'] = 'sums-v001' | ||||
|         root_dict['variables'] = {var.name: var.value for var in self.variables} | ||||
|         root_dict['sums'] = self.sums | ||||
|         sums_file_path.write_text(json.dumps(root_dict)) | ||||
| 
 | ||||
|     def print(self): | ||||
|         equation_index = 0 | ||||
|         for s in self.sums: | ||||
|             print(f"{equation_index}: {s['total']} = {' + '.join([comp_id for comp_id in s['components']])}") | ||||
|             equation_index += 1 | ||||
| 
 | ||||
|     def validate_on_variables(self, variables: Dict[VarName, VarValue]) -> Tuple['Sums', 'Sums']: | ||||
|         """ | ||||
|         returns the tuple valid_sums, invalid_sums after checking each of the sum of input_sum againts the given variables | ||||
|         """ | ||||
|         valid_sums: Sums = Sums() | ||||
|         invalid_sums: Sums = Sums() | ||||
|         for _sum in self.sums: | ||||
|             # for total_var_id, components in input_sums.items(): | ||||
|             total_var_id = _sum['total'] | ||||
|             components = _sum['components'] | ||||
| 
 | ||||
|             computed_total_value = 0 | ||||
|             for component_var_id in components: | ||||
|                 computed_total_value += variables[component_var_id] | ||||
|             real_total_value = variables[total_var_id] | ||||
|             if computed_total_value == real_total_value: | ||||
|                 valid_sums.sums.append(_sum) | ||||
|             else: | ||||
|                 invalid_sums.sums.append(_sum) | ||||
|         return (valid_sums, invalid_sums) | ||||
| 
 | ||||
| 
 | ||||
| class ISumHandler(abc.ABC): | ||||
| 
 | ||||
|     @abc.abstractmethod | ||||
|  | @ -48,35 +108,23 @@ class SumExporter(ISumHandler): | |||
|     '''handler that exports the sums as a graphviz dot file | ||||
|     ''' | ||||
|     sum_file_path: Path | ||||
|     variables: Set[IntVariable] | ||||
|     sums: Sums | ||||
| 
 | ||||
|     def __init__(self, sum_file_path: Path): | ||||
|         self.sum_file_path = sum_file_path | ||||
|         self.variables = set() | ||||
|         self.sums = [] | ||||
|         self.sums = Sums() | ||||
| 
 | ||||
|     def on_sum_found(self, total: IntVariable, components: List[IntVariable]): | ||||
|         self.variables.add(total) | ||||
|         self.sums.variables.add(total) | ||||
|         for component in components: | ||||
|             self.variables.add(component) | ||||
|             self.sums.variables.add(component) | ||||
|         print(f"sum found: {total.name} = {' + '.join([comp.name for comp in components])}") | ||||
|         self.sums.append({'total': total.name, 'components': [comp.name for comp in components]}) | ||||
|         self.sums.sums.append({'total': total.name, 'components': [comp.name for comp in components]}) | ||||
| 
 | ||||
|     def on_end(self): | ||||
|         print(f'exporting sums to {self.sum_file_path}') | ||||
|         root_dict = {} | ||||
|         root_dict['format'] = 'sums-v001' | ||||
|         root_dict['variables'] = {var.name: var.value for var in self.variables} | ||||
|         root_dict['sums'] = self.sums | ||||
|         self.sum_file_path.write_text(json.dumps(root_dict)) | ||||
| 
 | ||||
| 
 | ||||
| def load_sums(sums_file_path: Path) -> Sums: | ||||
|     with open(sums_file_path, 'rt', encoding='utf8') as sums_file: | ||||
|         root_dict = json.loads(sums_file.read()) | ||||
|     assert root_dict['format'] == 'sums-v001' | ||||
|     return root_dict['sums'] | ||||
|         self.sums.save(self.sum_file_path) | ||||
| 
 | ||||
| 
 | ||||
| def explore(total: IntVariable, components: List[IntVariable], cur_sum: VarValue, cur_var_index: int, contrib_components: List[IntVariable], sum_handler: ISumHandler): | ||||
|  | @ -266,12 +314,8 @@ def sums_to_dot(sum_file_path: Path, dot_file_path: Path): | |||
|         "yellowgreen"] | ||||
| 
 | ||||
|     print(f'creating {dot_file_path} from {sum_file_path}') | ||||
|     with open(sum_file_path, 'rt', encoding='utf8') as sum_file: | ||||
|         root_dict = json.load(sum_file) | ||||
|     sums = Sums.load(sum_file_path) | ||||
|     # print(root_dict) | ||||
|     variables = {IntVariable(var_name, var_value) for var_name, var_value in root_dict['variables'].items()} | ||||
|     # print(variables) | ||||
|     sums = root_dict['sums'] | ||||
|     # print(sums) | ||||
|     with open(dot_file_path, 'wt+', encoding='utf8') as dot_file: | ||||
|         dot_file.write(f'digraph {to_dot_symbol(sum_file_path.stem)}\n') | ||||
|  | @ -279,10 +323,10 @@ def sums_to_dot(sum_file_path: Path, dot_file_path: Path): | |||
|         dot_file.write('layout = neato\n') | ||||
|         dot_file.write('overlap = false\n') | ||||
| 
 | ||||
|         for variable in variables: | ||||
|         for variable in sums.variables: | ||||
|             dot_file.write(f'{to_dot_symbol(variable.name)} [label="{variable.name}={variable.value}"];\n') | ||||
|         sum_index = 0 | ||||
|         for s in sums: | ||||
|         for s in sums.sums: | ||||
|             dot_file.write(f"{to_dot_symbol(s['total'])} -> {{{','.join([to_dot_symbol(comp) for comp in s['components']])}}} [color={svg_colors[sum_index % len(svg_colors)]}, label={sum_index}];\n") | ||||
|             sum_index += 1 | ||||
|         dot_file.write('}\n') | ||||
|  | @ -298,25 +342,3 @@ def find_and_graph_sums(variables: Dict[str, int], set_id: str): | |||
|     sums_to_dot(sums_file_path, dot_file_path) | ||||
|     print(f'creating {svg_file_path} from {dot_file_path}') | ||||
|     subprocess.run(f'dot -Tsvg {dot_file_path} > {svg_file_path}', shell=True, check=True) | ||||
| 
 | ||||
| 
 | ||||
| def remove_invalid_sums(input_sums: Sums, variables: Dict[VarName, VarValue]) -> Tuple[Sums, Sums]: | ||||
|     """ | ||||
|     returns the tuple valid_sums, invalid_sums after checking each of the sum of input_sum againts the given variables | ||||
|     """ | ||||
|     valid_sums: Sums = [] | ||||
|     invalid_sums: Sums = [] | ||||
|     for _sum in input_sums: | ||||
|         # for total_var_id, components in input_sums.items(): | ||||
|         total_var_id = _sum['total'] | ||||
|         components = _sum['components'] | ||||
| 
 | ||||
|         computed_total_value = 0 | ||||
|         for component_var_id in components: | ||||
|             computed_total_value += variables[component_var_id] | ||||
|         real_total_value = variables[total_var_id] | ||||
|         if computed_total_value == real_total_value: | ||||
|             valid_sums.append(_sum) | ||||
|         else: | ||||
|             invalid_sums.append(_sum) | ||||
|     return (valid_sums, invalid_sums) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue