From a482ca92d283740938c620e876a62c680d6fc3e4 Mon Sep 17 00:00:00 2001 From: Samuel Pastva Date: Tue, 24 Sep 2024 11:27:06 +0200 Subject: [PATCH] Update to AEON.py 1.0. --- bundle.py | 42 +++++++++++++++++++++++------------------- k_count.py | 2 +- requirements.txt | 2 +- rules_to_bnet.py | 2 ++ sync.py | 41 +++++++++++++++++++---------------------- utils.py | 40 ++++++++++++++++++---------------------- 6 files changed, 64 insertions(+), 65 deletions(-) diff --git a/bundle.py b/bundle.py index 63af61f..2e6aeeb 100644 --- a/bundle.py +++ b/bundle.py @@ -60,10 +60,11 @@ user_count = input().lower() print(ENDC, end="") if user_count == "": - user_count = 32 - user_count = int(user_count) - if user_count > 0: - SAMPLE_COUNT = user_count + user_count_int = 32 + else: + user_count_int = int(user_count) + if user_count_int > 0: + SAMPLE_COUNT = user_count_int print(f"Selected {BOLD}{user_count}{ENDC} random samples.") break except: @@ -76,9 +77,10 @@ user_seed = input().lower() print(ENDC, end="") if user_seed == "": - user_seed = 0 - user_seed = int(user_seed) - SAMPLE_SEED = user_seed + user_seed_int = 0 + else: + user_seed_int = int(user_seed) + SAMPLE_SEED = user_seed_int print(f"Selected {BOLD}{user_seed}{ENDC} as the random seed.") break except: @@ -98,11 +100,11 @@ def check_filter(filter, model_dir): regulations = [] for var in model.variables(): name = model.get_variable_name(var) - if len(model.graph().regulators(var)) == 0: + if len(model.predecessors(var)) == 0: inputs.append(name) else: variables.append(name) - for reg in model.graph().regulators(var): + for reg in model.predecessors(var): reg_name = model.get_variable_name(reg) regulations.append((reg_name, name)) @@ -188,9 +190,9 @@ def check_filter(filter, model_dir): if INPUTS == "random": # For random sampling, we have to be a bit more clever... param_model = inputs_free(model) - stg = SymbolicAsyncGraph(param_model) - const_model = inputs_constant(stg.network(), "true") - all_colors = stg.unit_colors() + stg = AsynchronousGraph(param_model) + const_model = inputs_constant(model, True) + all_colors = stg.mk_unit_colors() if all_colors.is_singleton(): # This model does not have inputs, we can just output it. output_model(OUT_DIR, const_model, metadata['id'], FORMAT) @@ -204,7 +206,7 @@ def check_filter(filter, model_dir): input_symbolic_var = {} for var in param_model.implicit_parameters(): name = param_model.get_variable_name(var) - table = ctx.get_implicit_function_table(var) + table = ctx.get_function_table(var) assert len(table) == 1 symbolic_var = table[0][1] input_symbolic_var[name] = symbolic_var @@ -222,27 +224,29 @@ def check_filter(filter, model_dir): valuation_seed = rng.randrange(0, 2**30) valuation_sample = all_colors.to_bdd().valuation_random(valuation_seed) - valuation_bdd = bdd_vars.mk_valuation(valuation_sample) + valuation_bdd = bdd_vars.mk_conjunctive_clause(valuation_sample) # We have to project away the state variables from the valuation # and this seems to be the easiest way to do it. - valuation_set = stg.unit_colored_vertices().copy_with(valuation_bdd) + valuation_set = ColoredVertexSet(ctx, valuation_bdd) all_colors = all_colors.minus(valuation_set.colors()) suffix = "_" for (name, bdd_var) in input_symbolic_var.items(): if valuation_sample[bdd_var]: suffix += "1" - const_model.set_update_function(name, "true") + const_model.set_update_function(name, UpdateFunction.mk_const(const_model, True)) else: suffix += "0" - const_model.set_update_function(name, "false") + const_model.set_update_function(name, UpdateFunction.mk_const(const_model, False)) output_model(OUT_DIR, const_model, metadata['id'], FORMAT, suffix) print(" Done.") else: if INPUTS == "free": model = inputs_free(model) - if INPUTS == "true" or INPUTS == "false": - model = inputs_constant(model, INPUTS) + if INPUTS == "true": + model = inputs_constant(model, True) + if INPUTS == "false": + model = inputs_constant(model, False) if INPUTS == "identity": model = inputs_identity(model) diff --git a/k_count.py b/k_count.py index 0f5694f..d9f5cd4 100644 --- a/k_count.py +++ b/k_count.py @@ -13,7 +13,7 @@ bn = BooleanNetwork.from_file('./sbml-true/'+file) for var in bn.variables(): total_variables += 1 - regs = bn.regulators(var) + regs = bn.predecessors(var) total_regulations += len(regs) if len(regs) > 0: total_non_inputs += 1 diff --git a/requirements.txt b/requirements.txt index 4a0a425..5ca00fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -biodivine_aeon==0.2.0 \ No newline at end of file +biodivine_aeon>=1.0.0 \ No newline at end of file diff --git a/rules_to_bnet.py b/rules_to_bnet.py index b615db2..8b7b0b2 100644 --- a/rules_to_bnet.py +++ b/rules_to_bnet.py @@ -1,6 +1,8 @@ from pathlib import Path import sys +# Converts a "rules file" of an unspecified format into .bnet + input_file = Path(sys.argv[1]).read_text() input_file = input_file.replace("=", ",") input_file = input_file.replace(" AND ", " & ") diff --git a/sync.py b/sync.py index d3ded69..6a51de1 100644 --- a/sync.py +++ b/sync.py @@ -51,46 +51,43 @@ def check_metadata(id, name, metadata, bib): print(f"ERROR: Missing a `bbm-{int(id):03d}` key in the `citation.bib` file.") sys.exit(128) -def check_unused_variables(model): - graph = model.graph() - for var in graph.variables(): - name = graph.get_variable_name(var) - if len(graph.regulators(var)) == 0 and len(graph.targets(var)) == 0: +def check_unused_variables(model: BooleanNetwork): + for var in model.variables(): + name = model.get_variable_name(var) + if len(model.predecessors(var)) == 0 and len(model.successors(var)) == 0: print("ERROR: Variable", name, "is unused.") sys.exit(128) function = model.get_update_function(var) - if function is not None and function.as_variable() == var and len(graph.regulators(var)) <= 1: + if function is not None and function.as_var() == var and len(model.predecessors(var)) <= 1: print("ERROR: Variable", name, "is effectively an input.") sys.exit(128) -def erase_inputs(model): - graph = model.graph() - for var in graph.variables(): - if len(graph.regulators(var)) == 0: +def erase_inputs(model: BooleanNetwork): + for var in model.variables(): + if len(model.predecessors(var)) == 0: model.set_update_function(var, None) return model -def check_integrity(model): +def check_integrity(model: BooleanNetwork): # This will throw an error if the model is invalid. - async_graph = SymbolicAsyncGraph(model) + async_graph = AsynchronousGraph(model) + assert async_graph.network_variable_count() == model.variable_count() -def model_stats(model): - graph = model.graph() +def model_stats(model: BooleanNetwork): variables = 0 inputs = 0 - for var in graph.variables(): - if len(graph.regulators(var)) == 0: + for var in model.variables(): + if len(model.predecessors(var)) == 0: inputs += 1 else: variables += 1 - return (variables, inputs, len(graph.regulations())) + return (variables, inputs, len(model.regulations())) -def fix_variable_names(model): +def fix_variable_names(model: BooleanNetwork): # Ensures that every variable starts with v_, # otherwise bnet may have problems with invalid names. - graph = model.graph() - for var in graph.variables(): - name = graph.get_variable_name(var) + for var in model.variables(): + name = model.get_variable_name(var) model.set_variable_name(var, "v_"+name) return model @@ -159,7 +156,7 @@ def fix_variable_names(model): model = BooleanNetwork.from_bnet(source) if model == None: - print("ERROR: Missing source.sbml/.bnet/.aeon in", source_file) + print("ERROR: Missing source.sbml/.bnet/.aeon in", model_dir) sys.exit(128) # Static analysis (unused variables/regulations, etc.) diff --git a/utils.py b/utils.py index ca9b282..43eebf5 100644 --- a/utils.py +++ b/utils.py @@ -1,40 +1,36 @@ from pathlib import Path from biodivine_aeon import * +import copy # Note that the methods assume that the model is in the "canonical" format, # i.e. with all inputs as free. def inputs_free(model): - return model + return copy.copy(model) -def inputs_constant(model, constant): +def inputs_constant(model: BooleanNetwork, constant: bool): + model = copy.copy(model) for var in model.variables(): - if len(model.graph().regulators(var)) == 0: - model.set_update_function(var, constant) + if len(model.predecessors(var)) == 0: + model.set_update_function(var, UpdateFunction.mk_const(model, constant)) return model -def inputs_identity(model): +def inputs_identity(model: BooleanNetwork): # For identity, we have to also add self-regulations to inputs. - new_rg = model.graph() - for var in model.variables(): - if len(model.graph().regulators(var)) == 0: - new_rg.add_regulation({ - 'source': var, - 'target': var, - 'observable': True, - 'monotonicity': "activation" - }) - - new_model = BooleanNetwork(new_rg) - for var in model.variables(): - if len(model.graph().regulators(var)) == 0: - new_model.set_update_function(var, model.get_variable_name(var)) - else: - new_model.set_update_function(var, model.get_update_function(var)) + new_model = copy.copy(model) + for variable in new_model.variables(): + if len(new_model.predecessors(variable)) == 0: + reg: IdRegulation = { 'source': variable, + 'target': variable, + 'essential': True, + 'sign': '+' + } + new_model.ensure_regulation(reg) + new_model.set_update_function(variable, UpdateFunction.mk_var(new_model, variable)) return new_model -def output_model(dir, model, id, format, suffix = ""): +def output_model(dir: str, model: BooleanNetwork, id: int, format: str, suffix: str = ""): if format == "aeon": Path(f"{dir}/{id:03d}{suffix}.aeon").write_text(model.to_aeon()) if format == "bnet":