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
|
#!/usr/bin/env python3
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from sumfinder import load_sums, remove_invalid_sums
|
from sumfinder import Sums
|
||||||
from linuxmem import read_meminfo_stdout
|
from linuxmem import read_meminfo_stdout
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
sums = load_sums(Path('../expe001.5/alambix97-meminfo-sums.json'))
|
sums = Sums.load(Path('../expe001.5/alambix97-meminfo-sums.json'))
|
||||||
print(f'starting sums ({len(sums)} sums):')
|
print(f'starting sums ({sums.get_num_equations()} sums):')
|
||||||
print(sums)
|
sums.print()
|
||||||
|
|
||||||
variables = read_meminfo_stdout(Path('../bug3897/alambix98/20240806-223916-meminfo.stdout'))
|
variables = read_meminfo_stdout(Path('../bug3897/alambix98/20240806-223916-meminfo.stdout'))
|
||||||
# variables = read_meminfo_stdout(Path('../bug3897/alambix97/20240805-191606-meminfo.stdout'))
|
# variables = read_meminfo_stdout(Path('../bug3897/alambix97/20240805-191606-meminfo.stdout'))
|
||||||
(valid_sums, invalid_sums) = remove_invalid_sums(sums, variables)
|
(valid_sums, invalid_sums) = sums.validate_on_variables(variables)
|
||||||
print(f'invalid sums ({len(invalid_sums)} sums):')
|
print(f'invalid sums ({invalid_sums.get_num_equations()} sums):')
|
||||||
print(invalid_sums)
|
invalid_sums.print()
|
||||||
|
|
||||||
print(f'valid sums ({len(valid_sums)} sums):')
|
print(f'valid sums ({valid_sums.get_num_equations()} sums):')
|
||||||
print(valid_sums)
|
valid_sums.print()
|
||||||
|
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from .sumfinder import Sums # noqa
|
from .sumfinder import Sums # noqa
|
||||||
from .sumfinder import SumExporter # noqa
|
from .sumfinder import SumExporter # noqa
|
||||||
from .sumfinder import load_sums # noqa
|
|
||||||
from .sumfinder import find_sums # noqa
|
from .sumfinder import find_sums # noqa
|
||||||
from .sumfinder import sums_to_dot # noqa
|
from .sumfinder import sums_to_dot # noqa
|
||||||
from .sumfinder import find_and_graph_sums # noqa
|
from .sumfinder import find_and_graph_sums # noqa
|
||||||
from .sumfinder import remove_invalid_sums # noqa
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import subprocess
|
||||||
|
|
||||||
VarName = str
|
VarName = str
|
||||||
VarValue = int
|
VarValue = int
|
||||||
Sums = List[Dict[VarName, List[VarName]]]
|
Sum = Dict[VarName, List[VarName]]
|
||||||
|
|
||||||
|
|
||||||
class IntVariable():
|
class IntVariable():
|
||||||
|
@ -24,6 +24,66 @@ class IntVariable():
|
||||||
return f'{self.name}: {self.value}'
|
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):
|
class ISumHandler(abc.ABC):
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
@ -48,35 +108,23 @@ class SumExporter(ISumHandler):
|
||||||
'''handler that exports the sums as a graphviz dot file
|
'''handler that exports the sums as a graphviz dot file
|
||||||
'''
|
'''
|
||||||
sum_file_path: Path
|
sum_file_path: Path
|
||||||
variables: Set[IntVariable]
|
|
||||||
sums: Sums
|
sums: Sums
|
||||||
|
|
||||||
def __init__(self, sum_file_path: Path):
|
def __init__(self, sum_file_path: Path):
|
||||||
self.sum_file_path = sum_file_path
|
self.sum_file_path = sum_file_path
|
||||||
self.variables = set()
|
self.variables = set()
|
||||||
self.sums = []
|
self.sums = Sums()
|
||||||
|
|
||||||
def on_sum_found(self, total: IntVariable, components: List[IntVariable]):
|
def on_sum_found(self, total: IntVariable, components: List[IntVariable]):
|
||||||
self.variables.add(total)
|
self.sums.variables.add(total)
|
||||||
for component in components:
|
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])}")
|
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):
|
def on_end(self):
|
||||||
print(f'exporting sums to {self.sum_file_path}')
|
print(f'exporting sums to {self.sum_file_path}')
|
||||||
root_dict = {}
|
self.sums.save(self.sum_file_path)
|
||||||
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']
|
|
||||||
|
|
||||||
|
|
||||||
def explore(total: IntVariable, components: List[IntVariable], cur_sum: VarValue, cur_var_index: int, contrib_components: List[IntVariable], sum_handler: ISumHandler):
|
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"]
|
"yellowgreen"]
|
||||||
|
|
||||||
print(f'creating {dot_file_path} from {sum_file_path}')
|
print(f'creating {dot_file_path} from {sum_file_path}')
|
||||||
with open(sum_file_path, 'rt', encoding='utf8') as sum_file:
|
sums = Sums.load(sum_file_path)
|
||||||
root_dict = json.load(sum_file)
|
|
||||||
# print(root_dict)
|
# 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)
|
# print(sums)
|
||||||
with open(dot_file_path, 'wt+', encoding='utf8') as dot_file:
|
with open(dot_file_path, 'wt+', encoding='utf8') as dot_file:
|
||||||
dot_file.write(f'digraph {to_dot_symbol(sum_file_path.stem)}\n')
|
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('layout = neato\n')
|
||||||
dot_file.write('overlap = false\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')
|
dot_file.write(f'{to_dot_symbol(variable.name)} [label="{variable.name}={variable.value}"];\n')
|
||||||
sum_index = 0
|
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")
|
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
|
sum_index += 1
|
||||||
dot_file.write('}\n')
|
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)
|
sums_to_dot(sums_file_path, dot_file_path)
|
||||||
print(f'creating {svg_file_path} from {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)
|
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