From 65e1ee67e2ae328fe364e0604d3f69e67264ee2b Mon Sep 17 00:00:00 2001 From: Daphne Odekerken Date: Sat, 23 Dec 2023 10:54:22 +0100 Subject: [PATCH] Flake8 --- .../canonical_constructions/aux_operators.py | 4 +- .../canonical_af/canonical_cf.py | 7 +- .../canonical_af/canonical_def.py | 12 +- .../canonical_af/canonical_st.py | 12 +- .../canonical_af/construct_af_adm.py | 11 +- .../canonical_af/construct_af_cf.py | 12 +- .../canonical_af/construct_af_grd.py | 9 +- .../canonical_af/construct_af_naive.py | 18 +- .../canonical_af/construct_af_stage.py | 14 +- .../canonical_af/construct_af_stb.py | 18 +- .../check_com_closed.py | 3 +- .../check_conf_sens.py | 3 +- .../check_dcl_tight.py | 3 +- .../check_downward_closed.py | 3 +- .../check_incomparable.py | 3 +- .../check_intersection_in.py | 3 +- .../check_non_empty.py | 1 - .../check_set_com_closed.py | 4 +- .../check_set_conf_sens.py | 4 +- .../canonical_constructions/check_tight.py | 5 +- .../canonical_constructions/check_unary.py | 1 - .../check_union_closed.py | 4 +- .../abstract_argumentation_framework.py | 42 +- .../classes/argument.py | 6 +- .../abstract_argumentation/classes/defeat.py | 9 +- .../explanation/defending.py | 33 +- .../explanation/not_defending.py | 91 ++-- .../explanation/reach_and_dist.py | 45 +- .../explanation/suff_nec.py | 85 ++-- ...tract_argumentation_framework_generator.py | 27 +- .../generators/barbasi_albert_generator.py | 50 ++- .../generators/enforce_prob_cycle.py | 9 +- .../generators/erdos_renyi_generator.py | 30 +- .../generators/watts_strogatz_generator.py | 49 ++- ...n_framework_from_aspartix_format_reader.py | 10 +- ...on_framework_from_iccma23_format_reader.py | 10 +- ...rgumentation_framework_from_json_reader.py | 6 +- ...mework_from_trivial_graph_format_reader.py | 7 +- ...ion_framework_to_aspartix_format_writer.py | 9 +- ...tion_framework_to_iccma23_format_writer.py | 20 +- .../argumentation_framework_to_json_writer.py | 13 +- ...ramework_to_trivial_graph_format_writer.py | 9 +- .../get_acceptable_with_respect_to.py | 43 +- .../semantics/get_admissible_sets.py | 87 ++-- .../semantics/get_complete_extensions.py | 108 ++--- .../semantics/get_conflict_free_extensions.py | 15 +- .../semantics/get_eager_extension.py | 163 ++++---- .../semantics/get_grounded_extension.py | 37 +- .../semantics/get_ideal_extension.py | 94 +++-- .../semantics/get_naive_extensions.py | 10 +- .../semantics/get_preferred_extensions.py | 92 ++-- .../semantics/get_semistable_extensions.py | 103 ++--- .../semantics/get_stable_extensions.py | 100 ++--- .../is_acceptable_with_respect_to.py | 41 +- .../semantics/is_admissible.py | 50 +-- .../semantics/is_complete.py | 47 +-- .../semantics/is_conflict_free.py | 35 +- .../semantics/is_grounded_extension.py | 43 +- .../semantics/is_preferred_extension.py | 54 +-- ...eral_grounded_justification_status_fast.py | 95 +++-- ...ral_grounded_justification_status_naive.py | 20 +- .../justification/connected_literal.py | 7 +- .../justification/literal_labels.py | 6 +- .../aspic/classes/argumentation_system.py | 39 +- .../aspic/classes/argumentation_theory.py | 272 ++++++++---- src/py_arg/aspic/classes/defeasible_rule.py | 7 +- .../aspic/classes/instantiated_argument.py | 84 ++-- src/py_arg/aspic/classes/literal.py | 15 +- .../argument_orderings/last_link_ordering.py | 32 +- .../weakest_link_ordering.py | 38 +- .../aspic/classes/orderings/ordering.py | 62 ++- .../classes/orderings/preference_preorder.py | 13 +- .../set_orderings/democratic_ordering.py | 25 +- .../set_orderings/elitist_ordering.py | 29 +- src/py_arg/aspic/classes/rule.py | 7 +- src/py_arg/aspic/classes/strict_rule.py | 6 +- .../structured_argumentation_framework.py | 10 +- .../layered_argumentation_system_generator.py | 171 +++++--- .../argumentation_theory_generator.py | 38 +- .../argumentation_system_from_json_reader.py | 40 +- .../argumentation_system_to_json_writer.py | 24 +- .../canonical_constructions/canonical_adm.py | 9 +- .../canonical_constructions/canonical_cf.py | 9 +- .../canonical_constructions/canonical_com.py | 22 +- .../canonical_constructions/canonical_st.py | 9 +- .../canonical_constructions/canonical_ucl.py | 12 +- .../construct_abaf_adm.py | 15 +- .../construct_abaf_cf.py | 16 +- .../construct_abaf_com.py | 18 +- .../construct_abaf_naive.py | 16 +- .../construct_abaf_prf.py | 16 +- .../construct_abaf_st.py | 13 +- .../classes/aba_framework.py | 78 ++-- .../classes/instantiated_argument.py | 3 +- .../classes/rule.py | 4 +- .../semantics/get_admissible_extensions.py | 13 +- .../semantics/get_complete_extensions.py | 10 +- .../semantics/get_conflict_free_extensions.py | 10 +- .../semantics/get_grounded_extensions.py | 10 +- .../semantics/get_naive_extensions.py | 13 +- .../semantics/get_preferred_extensions.py | 10 +- .../semantics/get_semi_stable_extensions.py | 26 +- .../semantics/get_stable_extensions.py | 10 +- .../experiment_compute_grounded_labelling.py | 40 +- ...t_generate_data_set_from_layered_argsys.py | 45 +- ...nt_generate_data_set_from_police_argsys.py | 24 +- ...enerate_incomplete_argumentation_theory.py | 62 +-- .../experiment_run_stability_algorithm.py | 44 +- src/py_arg/experiments/utils.py | 3 +- .../incomplete_argumentation_framework.py | 142 ++++--- .../algorithms/relevance/relevance_lister.py | 211 +++++++--- .../stability/satisfiability_labeler.py | 45 +- .../algorithms/stability/stability_label.py | 28 +- .../algorithms/stability/stability_labeler.py | 203 +++++---- .../algorithms/stability/stability_labels.py | 6 +- .../incomplete_argumentation_theory.py | 78 ++-- ...complete_argumentation_theory_generator.py | 66 ++- ...e_argumentation_theory_from_json_reader.py | 31 +- ...rgumentation_theory_from_lp_file_reader.py | 61 ++- ...e_argumentation_theory_from_xlsx_reader.py | 54 ++- ...ete_argumentation_theory_to_json_writer.py | 43 +- ..._argumentation_theory_to_lp_file_writer.py | 31 +- .../incomplete_aspic/import_export/writer.py | 10 +- src/py_arg/utils/closure.py | 3 +- src/py_arg/utils/fixpoint.py | 3 +- src/py_arg/utils/is_c_consistent.py | 6 +- src/py_arg_learning/abstract_exercise_set.py | 19 +- .../identify_grounded_extension.py | 38 +- .../list_complete_extensions.py | 60 ++- .../list_preferred_extensions.py | 66 ++- src/py_arg_tests/convert_resources.py | 6 +- src/py_arg_tests/modgil_prakken_aij_tests.py | 145 ++++--- .../test_aba_canonical_constructions.py | 129 +++--- src/py_arg_tests/test_aba_lasagne_example.py | 16 +- src/py_arg_tests/test_aba_semantics.py | 20 +- .../test_af_canonical_constructions.py | 52 ++- ..._canonical_constructions_with_generator.py | 40 +- .../test_af_complete_semantics.py | 6 +- src/py_arg_tests/test_af_from_apx.py | 6 +- src/py_arg_tests/test_af_from_scratch.py | 3 +- src/py_arg_tests/test_af_generator.py | 29 +- src/py_arg_tests/test_cf_naive_ext.py | 15 +- ...test_incomplete_argumentation_framework.py | 18 +- ...complete_argumentation_theory_generator.py | 67 ++- src/py_arg_tests/test_recompute_arguments.py | 6 +- src/py_arg_tests/test_stability.py | 152 ++++--- src/py_arg_tests/test_toast_api.py | 6 +- src/py_arg_visualisation/app.py | 55 ++- .../explanation_function_options.py | 13 +- .../get_af_explanations.py | 60 ++- .../get_at_explanations.py | 73 ++-- .../get_abaf_extensions.py | 30 +- .../get_accepted_arguments.py | 8 +- .../get_accepted_assumptions.py | 8 +- .../get_accepted_formulas.py | 11 +- .../extensions_functions/get_af_extensions.py | 35 +- .../get_aba_graph_data.py | 15 +- .../graph_data_functions/get_af_graph_data.py | 30 +- .../graph_data_functions/get_at_graph_data.py | 35 +- .../read_argumentation_framework_functions.py | 18 +- .../read_argumentation_theory_functions.py | 106 +++-- .../get_ordering_by_specification.py | 27 +- .../tweety_services_handler.py | 48 +-- .../pages/01_generate_abstract.py | 107 +++-- .../pages/02_generate_random_aspic.py | 7 +- .../pages/03_generate_layered_aspic.py | 161 ++++--- .../pages/04_generate_erdos_renyi.py | 123 ++++-- .../pages/05_generate_watts_strogatz.py | 152 ++++--- .../pages/06_generate_barabasi_albert.py | 142 ++++--- .../pages/21_visualise_abstract.py | 270 +++++++----- .../pages/22_visualise_aspic.py | 322 ++++++++------ .../pages/23_visualise_aba.py | 153 ++++--- .../24_visualise_tweety_services_test.py | 395 +++++++++++------- src/py_arg_visualisation/pages/30_learn.py | 31 +- .../pages/41_canonical_af.py | 54 ++- .../pages/42_canonical_abaf.py | 54 ++- src/py_arg_visualisation/pages/50_chat.py | 74 ++-- src/py_arg_visualisation/pages/90_pyarg.py | 20 +- 178 files changed, 4989 insertions(+), 3004 deletions(-) diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/aux_operators.py b/src/py_arg/abstract_argumentation/canonical_constructions/aux_operators.py index 26fc2c9..aa79988 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/aux_operators.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/aux_operators.py @@ -31,7 +31,8 @@ def pairs(extension_set: Set) -> Set[FrozenSet]: @staticmethod def powerset(iterable) -> Set[FrozenSet]: s = list(iterable) - list_of_tuples = set(itertools.chain.from_iterable(itertools.combinations(s, r) for r in range(len(s) + 1))) + list_of_tuples = set(itertools.chain.from_iterable( + itertools.combinations(s, r) for r in range(len(s) + 1))) out = set() for el in list_of_tuples: @@ -110,4 +111,3 @@ def reduce(extension_set: Set) -> Set[FrozenSet]: for ext in extension_set: out.add(ext.difference(intersection)) return out - diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_cf.py b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_cf.py index c4b8e09..85dc400 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_cf.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_cf.py @@ -1,8 +1,9 @@ - from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.defeat import Defeat diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_def.py b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_def.py index a2f353e..65cc472 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_def.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_def.py @@ -1,7 +1,9 @@ from typing import Set, FrozenSet -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_cf as canonical_cf -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions.canonical_af \ + .canonical_cf as canonical_cf +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat @@ -16,7 +18,8 @@ def defence_formula(extension_set: Set, arg: Argument) -> Set[FrozenSet]: @staticmethod -def disjunctive_defence_formula(extension_set: Set, arg: Argument) -> Set[FrozenSet]: +def disjunctive_defence_formula(extension_set: Set, arg: Argument) -> \ + Set[FrozenSet]: cnf = defence_formula(extension_set, arg) dnf = set({frozenset()}) for conjunct in cnf: @@ -59,4 +62,5 @@ def apply(extension_set: Set) -> AbstractArgumentationFramework: for c in disj: atts_def.append(Defeat(c, new_arg)) - return AbstractArgumentationFramework('', arguments=args_def, defeats=atts_def) + return AbstractArgumentationFramework('', arguments=args_def, + defeats=atts_def) diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_st.py b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_st.py index bcaa389..8e38c44 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_st.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/canonical_st.py @@ -1,9 +1,12 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_cf as canonical_cf -import py_arg.abstract_argumentation.semantics.get_stable_extensions as get_stable_extensions -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions.canonical_af\ + .canonical_cf as canonical_cf +import py_arg.abstract_argumentation.semantics.get_stable_extensions as \ + get_stable_extensions +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat @@ -22,4 +25,5 @@ def apply(extension_set: Set) -> AbstractArgumentationFramework: for arg in set(canon_cf.arguments).difference(el): defeats.add(Defeat(arg, new_arg)) - return AbstractArgumentationFramework('', arguments=list(arguments), defeats=list(defeats)) + return AbstractArgumentationFramework('', arguments=list(arguments), + defeats=list(defeats)) diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_adm.py b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_adm.py index e47221b..4309d28 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_adm.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_adm.py @@ -1,9 +1,12 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_def as canonical_def -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -import py_arg.abstract_argumentation.canonical_constructions.check_conf_sens as check_conf_sens +import py_arg.abstract_argumentation.canonical_constructions.canonical_af\ + .canonical_def as canonical_def +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions.check_conf_sens \ + as check_conf_sens @staticmethod @@ -11,5 +14,3 @@ def apply(extension_set: Set) -> AbstractArgumentationFramework: if check_conf_sens.apply(extension_set) and frozenset() in extension_set: return canonical_def.apply(extension_set) return AbstractArgumentationFramework('', arguments=[], defeats=[]) - - diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_cf.py b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_cf.py index bc239b3..83859b5 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_cf.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_cf.py @@ -1,14 +1,18 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_cf as canonical_cf -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -import py_arg.abstract_argumentation.canonical_constructions.check_downward_closed as check_downward_closed +import py_arg.abstract_argumentation.canonical_constructions.canonical_af\ + .canonical_cf as canonical_cf +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions\ + .check_downward_closed as check_downward_closed from py_arg.abstract_argumentation.canonical_constructions import check_tight @staticmethod def apply(extension_set: Set) -> AbstractArgumentationFramework: - if check_downward_closed.apply(extension_set) and check_tight.apply(extension_set): + if check_downward_closed.apply(extension_set) and check_tight.apply( + extension_set): return canonical_cf.apply(extension_set) return AbstractArgumentationFramework('', arguments=[], defeats=[]) diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_grd.py b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_grd.py index f4dc314..b52ab4e 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_grd.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_grd.py @@ -1,12 +1,15 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework @staticmethod def apply(extension_set: Set) -> AbstractArgumentationFramework: if len(extension_set) == 1: - return AbstractArgumentationFramework('', arguments=list(aux.big_a(extension_set)), defeats=[]) + return AbstractArgumentationFramework('', arguments=list(aux.big_a( + extension_set)), defeats=[]) return AbstractArgumentationFramework('', arguments=[], defeats=[]) diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_naive.py b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_naive.py index 8f02205..f226b5d 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_naive.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_naive.py @@ -1,17 +1,23 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_cf as canonical_cf -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -import py_arg.abstract_argumentation.canonical_constructions.check_dcl_tight as check_dcl_tight -import py_arg.abstract_argumentation.canonical_constructions.check_incomparable as check_incomparable -import py_arg.abstract_argumentation.canonical_constructions.check_non_empty as check_non_empty +import py_arg.abstract_argumentation.canonical_constructions.canonical_af\ + .canonical_cf as canonical_cf +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions.check_dcl_tight \ + as check_dcl_tight +import py_arg.abstract_argumentation.canonical_constructions\ + .check_incomparable as check_incomparable +import py_arg.abstract_argumentation.canonical_constructions.check_non_empty \ + as check_non_empty from py_arg.abstract_argumentation.canonical_constructions import aux_operators @staticmethod def apply(extension_set: Set) -> AbstractArgumentationFramework: - if check_incomparable.apply(extension_set) and check_dcl_tight.apply(aux_operators.dcl(extension_set)) \ + if check_incomparable.apply(extension_set) and check_dcl_tight.apply( + aux_operators.dcl(extension_set)) \ and check_non_empty.apply(extension_set): return canonical_cf.apply(extension_set) return AbstractArgumentationFramework('', arguments=[], defeats=[]) diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_stage.py b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_stage.py index 0e61592..ccffb01 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_stage.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_stage.py @@ -1,16 +1,18 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_st as canonical_st -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -import py_arg.abstract_argumentation.canonical_constructions.check_incomparable as check_incomparable +import py_arg.abstract_argumentation.canonical_constructions.canonical_af\ + .canonical_st as canonical_st +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions\ + .check_incomparable as check_incomparable from py_arg.abstract_argumentation.canonical_constructions import check_tight @staticmethod def apply(extension_set: Set) -> AbstractArgumentationFramework: - if check_incomparable.apply(extension_set) and check_tight.apply(extension_set) and len(extension_set) != 0: + if check_incomparable.apply(extension_set) and check_tight.apply( + extension_set) and len(extension_set) != 0: return canonical_st.apply(extension_set) return AbstractArgumentationFramework('', arguments=[], defeats=[]) - - diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_stb.py b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_stb.py index 788f653..89e7217 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_stb.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/canonical_af/construct_af_stb.py @@ -1,10 +1,14 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_st as canonical_st -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -import py_arg.abstract_argumentation.canonical_constructions.check_incomparable as check_incomparable -import py_arg.abstract_argumentation.canonical_constructions.check_non_empty as check_non_empty +import py_arg.abstract_argumentation.canonical_constructions.canonical_af\ + .canonical_st as canonical_st +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions\ + .check_incomparable as check_incomparable +import py_arg.abstract_argumentation.canonical_constructions.check_non_empty \ + as check_non_empty from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat from py_arg.abstract_argumentation.canonical_constructions import check_tight @@ -14,7 +18,9 @@ def apply(extension_set: Set) -> AbstractArgumentationFramework: if not check_non_empty.apply(extension_set): x = Argument('x') - return AbstractArgumentationFramework('', arguments=[x], defeats=[Defeat(x, x)]) - if check_incomparable.apply(extension_set) and check_tight.apply(extension_set): + return AbstractArgumentationFramework('', arguments=[x], + defeats=[Defeat(x, x)]) + if check_incomparable.apply(extension_set) and check_tight.apply( + extension_set): return canonical_st.apply(extension_set) return AbstractArgumentationFramework('', arguments=[], defeats=[]) diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_com_closed.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_com_closed.py index 2812a66..ba26f90 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_com_closed.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_com_closed.py @@ -1,6 +1,7 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_conf_sens.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_conf_sens.py index b03c0f7..4eb2ac2 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_conf_sens.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_conf_sens.py @@ -1,7 +1,8 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_dcl_tight.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_dcl_tight.py index 553f044..c774479 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_dcl_tight.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_dcl_tight.py @@ -2,7 +2,8 @@ from typing import Set from py_arg.abstract_argumentation.canonical_constructions import check_tight -from py_arg.abstract_argumentation.canonical_constructions import aux_operators as aux +from py_arg.abstract_argumentation.canonical_constructions import \ + aux_operators as aux @staticmethod diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_downward_closed.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_downward_closed.py index 5199d16..dec853e 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_downward_closed.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_downward_closed.py @@ -1,7 +1,8 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_incomparable.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_incomparable.py index 1c5b82e..9f9ac5e 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_incomparable.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_incomparable.py @@ -1,7 +1,8 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_intersection_in.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_intersection_in.py index f7a177a..7cbeaeb 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_intersection_in.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_intersection_in.py @@ -1,7 +1,8 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_non_empty.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_non_empty.py index 4ba0e1a..1a5dcdd 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_non_empty.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_non_empty.py @@ -1,4 +1,3 @@ - from typing import Set diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_set_com_closed.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_set_com_closed.py index ae30f88..cf44e8c 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_set_com_closed.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_set_com_closed.py @@ -1,7 +1,7 @@ - from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as\ + aux @staticmethod diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_set_conf_sens.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_set_conf_sens.py index c501922..53ebf7e 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_set_conf_sens.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_set_conf_sens.py @@ -1,7 +1,7 @@ - from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_tight.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_tight.py index 7dd0fbb..29eb063 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_tight.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_tight.py @@ -1,6 +1,7 @@ - from typing import Set -from py_arg.abstract_argumentation.canonical_constructions import aux_operators as aux +from py_arg.abstract_argumentation.canonical_constructions import \ + aux_operators as aux + @staticmethod def apply(extension_set: Set) -> bool: diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_unary.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_unary.py index bf2b2ff..8dd4d6f 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_unary.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_unary.py @@ -1,4 +1,3 @@ - from typing import Set diff --git a/src/py_arg/abstract_argumentation/canonical_constructions/check_union_closed.py b/src/py_arg/abstract_argumentation/canonical_constructions/check_union_closed.py index b046745..b847836 100644 --- a/src/py_arg/abstract_argumentation/canonical_constructions/check_union_closed.py +++ b/src/py_arg/abstract_argumentation/canonical_constructions/check_union_closed.py @@ -1,7 +1,7 @@ - from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod diff --git a/src/py_arg/abstract_argumentation/classes/abstract_argumentation_framework.py b/src/py_arg/abstract_argumentation/classes/abstract_argumentation_framework.py index c4b5091..1439de5 100644 --- a/src/py_arg/abstract_argumentation/classes/abstract_argumentation_framework.py +++ b/src/py_arg/abstract_argumentation/classes/abstract_argumentation_framework.py @@ -13,7 +13,8 @@ def __init__(self, name: str = '', if arguments is None: self._arguments = {} else: - self._arguments = {argument.name: argument for argument in arguments} + self._arguments = {argument.name: argument + for argument in arguments} if defeats is None: self._defeats = [] @@ -25,8 +26,10 @@ def __init__(self, name: str = '', defeat.to_argument.add_ingoing_defeat(defeat.from_argument) def __repr__(self): - return '( [' + ', '.join(argument.name for argument in self.arguments) + \ - '], [' + ', '.join(defeat.__repr__() for defeat in self.defeats) + '] )' + return '( [' + ', '.join(argument.name + for argument in self.arguments) + \ + '], [' + ', '.join(defeat.__repr__() + for defeat in self.defeats) + '] )' def __eq__(self, other): return isinstance(other, AbstractArgumentationFramework) and \ @@ -34,11 +37,13 @@ def __eq__(self, other): self.arguments == other.arguments and \ self.defeats == other.defeats - def get_incoming_defeat_arguments(self, argument: Argument) -> List[Argument]: + def get_incoming_defeat_arguments(self, argument: Argument) -> List[ + Argument]: """ Get a list of arguments that defeat this argument. - :param argument: Argument for which we want to know the incoming defeating arguments. + :param argument: Argument for which we want to know the incoming + defeating arguments. :return: List of arguments that defeat this argument. >>> a = Argument('a') @@ -51,13 +56,16 @@ def get_incoming_defeat_arguments(self, argument: Argument) -> List[Argument]: >>> a in af.get_incoming_defeat_arguments(b) True """ - return [defeat.from_argument for defeat in self._defeats if defeat.to_argument == argument] + return [defeat.from_argument + for defeat in self._defeats if defeat.to_argument == argument] - def get_outgoing_defeat_arguments(self, argument: Argument) -> List[Argument]: + def get_outgoing_defeat_arguments(self, argument: Argument) -> List[ + Argument]: """ Get a list of arguments that are defeated by this argument. - :param argument: The argument for which we want to know the arguments it defeats. + :param argument: The argument for which we want to know the arguments + it defeats. :return: List of arguments that are defeated by this argument. >>> a = Argument('a') @@ -70,14 +78,16 @@ def get_outgoing_defeat_arguments(self, argument: Argument) -> List[Argument]: >>> b in af.get_outgoing_defeat_arguments(a) True """ - return [defeat.to_argument for defeat in self._defeats if defeat.from_argument == argument] + return [defeat.to_argument for defeat in self._defeats + if defeat.from_argument == argument] def is_defeated(self, argument: Argument) -> bool: """ Check if this argument is defeated by any argument. :param argument: Argument for which we want to know if it is defeated. - :return: Boolean indicating if this argument is defeated by any argument. + :return: Boolean indicating if the argument is defeated by + any argument. >>> a = Argument('a') >>> b = Argument('b') @@ -96,10 +106,12 @@ def is_defeated(self, argument: Argument) -> bool: def is_in_arguments(self, argument_name: str) -> bool: """ - Check if an argument with this name is part of the argumentation framework's arguments. + Check if an argument with this name is part of the argumentation + framework's arguments. :param argument_name: The name of the argument we try to find. - :return: Boolean indicating if there is an argument with this name in the argumentation framework. + :return: Boolean indicating if there is an argument with this name in + the argumentation framework. >>> a = Argument('a') >>> b = Argument('b') @@ -115,7 +127,8 @@ def is_in_arguments(self, argument_name: str) -> bool: def get_argument(self, argument_name: str) -> Argument: """ - Get the argument with this name (if it exists, otherwise raise ValueError). + Get the argument with this name (if it exists, otherwise raise + ValueError). :param argument_name: The name of the argument we try to find. :return: The argument with the specified name. @@ -131,7 +144,8 @@ def get_argument(self, argument_name: str) -> Argument: ValueError: There is no argument named b. """ if not self.is_in_arguments(argument_name): - raise ValueError('There is no argument named ' + argument_name + '.') + raise ValueError('There is no argument named ' + argument_name + + '.') return self._arguments[argument_name] @property diff --git a/src/py_arg/abstract_argumentation/classes/argument.py b/src/py_arg/abstract_argumentation/classes/argument.py index 79233d0..718e058 100644 --- a/src/py_arg/abstract_argumentation/classes/argument.py +++ b/src/py_arg/abstract_argumentation/classes/argument.py @@ -24,7 +24,8 @@ def __hash__(self): def add_ingoing_defeat(self, other: 'Argument'): """ - Add ingoing defeat from the other argument. NOTE: does not add an outgoing defeat from other to this argument! + Add ingoing defeat from the other argument. NOTE: does not add an + outgoing defeat from other to this argument! :param other: The argument defeating this argument. """ @@ -32,7 +33,8 @@ def add_ingoing_defeat(self, other: 'Argument'): def add_outgoing_defeat(self, other: 'Argument'): """ - Add outgoing defeat to the other argument. NOTE: does not add an ingoing defeat to the other argument! + Add outgoing defeat to the other argument. NOTE: does not add an + ingoing defeat to the other argument! :param other: The argument defeated by this argument. """ diff --git a/src/py_arg/abstract_argumentation/classes/defeat.py b/src/py_arg/abstract_argumentation/classes/defeat.py index 1fa41b6..658ae52 100644 --- a/src/py_arg/abstract_argumentation/classes/defeat.py +++ b/src/py_arg/abstract_argumentation/classes/defeat.py @@ -10,14 +10,17 @@ def __str__(self): return str(self.from_argument) + ' defeats ' + str(self.to_argument) def __lt__(self, other): - return self.from_argument < other.from_argument or self.from_argument == other.from_argument and \ + return self.from_argument < other.from_argument or \ + self.from_argument == other.from_argument and \ self.to_argument < other.to_argument def __repr__(self): - return '(' + str(self.from_argument) + ', ' + str(self.to_argument) + ')' + return '(' + str(self.from_argument) + ', ' + \ + str(self.to_argument) + ')' def __eq__(self, other): - return self.from_argument == other.from_argument and self.to_argument == other.to_argument + return self.from_argument == other.from_argument and \ + self.to_argument == other.to_argument def __hash__(self): return hash(str(self)) diff --git a/src/py_arg/abstract_argumentation/explanation/defending.py b/src/py_arg/abstract_argumentation/explanation/defending.py index 92aee00..4275083 100644 --- a/src/py_arg/abstract_argumentation/explanation/defending.py +++ b/src/py_arg/abstract_argumentation/explanation/defending.py @@ -1,18 +1,24 @@ -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.explanation.reach_and_dist import get_reach -def get_defending(argumentation_framework: AbstractArgumentationFramework, argument: Argument, extensions): +def get_defending(argumentation_framework: AbstractArgumentationFramework, + argument: Argument, extensions): """ - Obtain for each extension with the argument te set of arguments that (in)directly defend the argument. + Obtain for each extension with the argument te set of arguments that + (in)directly defend the argument. In papers: Defending. - :param argumentation_framework: the argumentation framework the explanation should be about + :param argumentation_framework: the argumentation framework the explanation + should be about :param argument: the argument that is accepted - :param extensions: the extensions (sets of accepted arguments) of the argumentation framework. - :return: a list of sets of arguments, each representing one or more extensions, containing the arguments from the + :param extensions: the extensions (sets of accepted arguments) of the + argumentation framework. + :return: a list of sets of arguments, each representing one or more + extensions, containing the arguments from the extension that (in)directly defend the argument. """ reach, distance = get_reach(argumentation_framework, argument) @@ -35,16 +41,21 @@ def get_defending(argumentation_framework: AbstractArgumentationFramework, argum return defending_sets -def get_dir_defending(argumentation_framework: AbstractArgumentationFramework, argument: Argument, extensions): +def get_dir_defending(argumentation_framework: AbstractArgumentationFramework, + argument: Argument, extensions): """ - Obtain for each extension with the argument te set of arguments that directly defend the argument. + Obtain for each extension with the argument te set of arguments that + directly defend the argument. In papers: DirDefending. - :param argumentation_framework: the argumentation framework the explanation should be about + :param argumentation_framework: the argumentation framework the explanation + should be about :param argument: the argument that is accepted - :param extensions: the extensions (sets of accepted arguments) of the argumentation framework. - :return: a list of sets of arguments, each representing one or more extensions, containing the arguments from the + :param extensions: the extensions (sets of accepted arguments) of the + argumentation framework. + :return: a list of sets of arguments, each representing one or more + extensions, containing the arguments from the extension that directly defend the argument. """ reach, distance = get_reach(argumentation_framework, argument) diff --git a/src/py_arg/abstract_argumentation/explanation/not_defending.py b/src/py_arg/abstract_argumentation/explanation/not_defending.py index 1828cee..a5df162 100644 --- a/src/py_arg/abstract_argumentation/explanation/not_defending.py +++ b/src/py_arg/abstract_argumentation/explanation/not_defending.py @@ -1,18 +1,24 @@ -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.explanation.reach_and_dist import get_reach -def get_not_defending(argumentation_framework: AbstractArgumentationFramework, argument: Argument, extensions): +def get_not_defending(argumentation_framework: AbstractArgumentationFramework, + argument: Argument, extensions): """ - Obtain for each extension without the argument the set of arguments that attack the argument and to which the + Obtain for each extension without the argument the set of arguments that + attack the argument and to which the extension provides no defense. - In papers: NoDefAgainst. - - :param argumentation_framework: the argumentation framework the explanation should be about + In papers: NoDefAgainst. + + :param argumentation_framework: the argumentation framework the explanation + should be about :param argument: the argument that is not accepted - :param extensions: the extensions (sets of accepted arguments) of the argumentation framework. - :return: a list of sets of arguments, each representing one or more extensions, containing the arguments that + :param extensions: the extensions (sets of accepted arguments) of the + argumentation framework. + :return: a list of sets of arguments, each representing one or more + extensions, containing the arguments that attack the argument and to which the extension provides to defense. """ reach, distance = get_reach(argumentation_framework, argument) @@ -30,14 +36,16 @@ def get_not_defending(argumentation_framework: AbstractArgumentationFramework, a not_def_ext = set() if argument not in extension: for defeater in attackers: - reach_def, distance_def = get_reach(argumentation_framework, defeater) + reach_def, distance_def = get_reach(argumentation_framework, + defeater) defenders = set() for pot_defender in reach_def: dist_pot_def = distance_def[str(pot_defender)] for dist in dist_pot_def: if dist % 2: defenders.add(pot_defender) - no_def_against = [nodefense for nodefense in defenders if nodefense not in extension] + no_def_against = [nodefense for nodefense in defenders + if nodefense not in extension] if no_def_against == list(defenders): not_def_ext.add(defeater) if not_def_ext not in not_defending_sets: @@ -46,26 +54,36 @@ def get_not_defending(argumentation_framework: AbstractArgumentationFramework, a return not_defending_sets -def get_no_dir_defending(argumentation_framework: AbstractArgumentationFramework, argument: Argument, extensions): +def get_no_dir_defending( + argumentation_framework: AbstractArgumentationFramework, + argument: Argument, extensions): """ - Obtain for each extension without the argument the set of arguments that directly attack the argument and to which + Obtain for each extension without the argument the set of arguments that + directly attack the argument and to which the extension provides no direct defense. - In papers: NoDirDefense. - - :param argumentation_framework: the argumentation framework the explanation should be about + In papers: NoDirDefense. + + :param argumentation_framework: the argumentation framework the explanation + should be about :param argument: the argument that is not accepted - :param extensions: the extensions (sets of accepted arguments) of the argumentation framework. - :return: a list of sets of arguments, each representing one or more extensions, containing the arguments that - directly attack the argument and to which the extension provides to direct defense. + :param extensions: the extensions (sets of accepted arguments) of the + argumentation framework. + :return: a list of sets of arguments, each representing one or more + extensions, containing the arguments that + directly attack the argument and to which the extension provides to + direct defense. """ not_dir_def_sets = [] for extension in extensions: - attackers = argumentation_framework.get_incoming_defeat_arguments(argument) not_def_ext = set() if argument not in extension: - for attacker in argumentation_framework.get_incoming_defeat_arguments(argument): - if [dirdf for dirdf in argumentation_framework.get_incoming_defeat_arguments(attacker) - if dirdf in extension] == []: + for attacker in argumentation_framework. \ + get_incoming_defeat_arguments(argument): + if not [dirdf + for dirdf in + argumentation_framework.get_incoming_defeat_arguments( + attacker) + if dirdf in extension]: not_def_ext.add(attacker) if not_def_ext not in not_dir_def_sets: not_dir_def_sets.append(not_def_ext) @@ -73,25 +91,34 @@ def get_no_dir_defending(argumentation_framework: AbstractArgumentationFramework return not_dir_def_sets -def get_no_self_defense(argumentation_framework: AbstractArgumentationFramework, argument: Argument, extensions): +def get_no_self_defense( + argumentation_framework: AbstractArgumentationFramework, + argument: Argument, extensions): """ - Obtain for each set obtained with get_not_defending the arguments that are not attacked by the argument. - In papers: NoSelfDefense. - - :param argumentation_framework: the argumentation framework the explanation should be about + Obtain for each set obtained with get_not_defending the arguments that are + not attacked by the argument. + In papers: NoSelfDefense. + + :param argumentation_framework: the argumentation framework the explanation + should be about :param argument: the argument that is not accepted - :param extensions: the extensions (sets of accepted arguments) of the argumentation framework. - :return: a list of sets of arguments, each representing one or more extensions, containing the arguments that attack - the argument, to which the extension provides to defense and which the argument itself does not (in)directly + :param extensions: the extensions (sets of accepted arguments) of the + argumentation framework. + :return: a list of sets of arguments, each representing one or more + extensions, containing the arguments that attack + the argument, to which the extension provides to defense and which the + argument itself does not (in)directly attack either. """ - not_defending = get_not_defending(argumentation_framework, argument, extensions) + not_defending = get_not_defending(argumentation_framework, argument, + extensions) not_dir_defending_sets = [] for not_def_ext in not_defending: not_ddef_ext = set() for attacker in not_def_ext: - reach_att, distance_att = get_reach(argumentation_framework, attacker) + reach_att, distance_att = get_reach(argumentation_framework, + attacker) defenders = set() for pot_defender in reach_att: dist_pot_def = distance_att[str(pot_defender)] diff --git a/src/py_arg/abstract_argumentation/explanation/reach_and_dist.py b/src/py_arg/abstract_argumentation/explanation/reach_and_dist.py index 49f68cc..f47c43e 100644 --- a/src/py_arg/abstract_argumentation/explanation/reach_and_dist.py +++ b/src/py_arg/abstract_argumentation/explanation/reach_and_dist.py @@ -1,15 +1,21 @@ -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -def get_reach(argumentation_framework: AbstractArgumentationFramework, argument: Argument): +def get_reach(argumentation_framework: AbstractArgumentationFramework, + argument: Argument): """ - Obtain the arguments in the framework from which the argument can be reach via the attack relation and the distance + Obtain the arguments in the framework from which the argument can be reach + via the attack relation and the distance between those arguments. - :param argumentation_framework: The argumentation framework used to determine reach and distance. - :param argument: The argument for which the reach and distance need to be calculated. - :return: A set of arguments from which the argument can be reached and a dictionary with for each argument in the + :param argumentation_framework: The argumentation framework used to + determine reach and distance. + :param argument: The argument for which the reach and distance need to be + calculated. + :return: A set of arguments from which the argument can be reached and a + dictionary with for each argument in the framework the distance (possibly several) to the given argument. """ initial_reach = {argument} @@ -17,34 +23,43 @@ def get_reach(argumentation_framework: AbstractArgumentationFramework, argument: for arg in argumentation_framework.arguments: distance[str(arg)] = set() distance[str(argument)] = {0} - return recursive_reach(argumentation_framework, initial_reach, argument, argument, 0, [], distance) + return recursive_reach(argumentation_framework, initial_reach, argument, + argument, 0, [], distance) -def recursive_reach(argumentation_framework, reach, argument, new_argument, dist, visited, distance): +def recursive_reach(argumentation_framework, reach, argument, new_argument, + dist, visited, distance): """ - Obtain the arguments in the framework from which the argument can be reach via the attack relation and the + Obtain the arguments in the framework from which the argument can be reach + via the attack relation and the distance between those arguments. - :param argumentation_framework: The argumentation framework used to determine reach and distance. + :param argumentation_framework: The argumentation framework used to + determine reach and distance. :param reach: A set of arguments from which the argument is reachable. - :param argument: The argument for which the reach and distance need to be calculated. - :param new_argument: An argument from argumentation_framework from which the argument is reachable. + :param argument: The argument for which the reach and distance need to be + calculated. + :param new_argument: An argument from argumentation_framework from which + the argument is reachable. :param dist: the depth of the current search step. :param visited: a list of defeats that has been used by the algorithm. :param distance: the dictionary with the distances. - :return: A set of arguments from which the argument can be reached and a dictionary with for each argument in the + :return: A set of arguments from which the argument can be reached and a + dictionary with for each argument in the framework the distance (possibly several) to the given argument. """ visited_start = visited.copy() for pot_argument in argumentation_framework.arguments: - if pot_argument in argumentation_framework.get_incoming_defeat_arguments(new_argument) \ + if pot_argument in argumentation_framework.\ + get_incoming_defeat_arguments(new_argument) \ and [str(pot_argument), str(new_argument)] not in visited: pot_dist = distance[str(pot_argument)] pot_dist.add(dist + 1) distance[str(pot_argument)] = pot_dist reach.add(pot_argument) visited.append([str(pot_argument), str(new_argument)]) - recursive_reach(argumentation_framework, reach, argument, pot_argument, dist + 1, visited, distance) + recursive_reach(argumentation_framework, reach, argument, + pot_argument, dist + 1, visited, distance) visited = visited_start return reach, distance diff --git a/src/py_arg/abstract_argumentation/explanation/suff_nec.py b/src/py_arg/abstract_argumentation/explanation/suff_nec.py index a9146e7..4835d27 100644 --- a/src/py_arg/abstract_argumentation/explanation/suff_nec.py +++ b/src/py_arg/abstract_argumentation/explanation/suff_nec.py @@ -1,55 +1,79 @@ -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.explanation.reach_and_dist import get_reach -from py_arg.abstract_argumentation.semantics.get_admissible_sets import get_admissible_sets +from py_arg.abstract_argumentation.semantics.get_admissible_sets import \ + get_admissible_sets -def get_sufficient_or_necessary(argumentation_framework: AbstractArgumentationFramework, argument: Argument, - explanation_function: str, explanation_type: str): +def get_sufficient_or_necessary( + argumentation_framework: AbstractArgumentationFramework, + argument: Argument, + explanation_function: str, + explanation_type: str): """ - Obtain the necessary or (minimal) sufficient explanations for the given argument. + Obtain the necessary or (minimal) sufficient explanations for the given + argument. - :param argumentation_framework: The argumentation framework the explanation should be about. + :param argumentation_framework: The argumentation framework the explanation + should be about. :param argument: The argument that is accepted. - :param explanation_function: The explanation function, to determine the content of the explanation. - :param explanation_type: The explanation type, to determine acceptance/non-acceptance explanation. - :return: a list of sets of arguments, each representing a sufficient set of arguments for the acceptance of the - given argument, or the necessary arguments. + :param explanation_function: The explanation function, to determine the + content of the explanation. + :param explanation_type: The explanation type, to determine acceptance/ + non-acceptance explanation. + :return: a list of sets of arguments, each representing a sufficient set of + arguments for the acceptance of the given argument, or the necessary + arguments. """ if explanation_type == 'Acceptance': if explanation_function == 'Suff': - return get_sufficient_arguments_for_acceptance(argumentation_framework, argument) + return get_sufficient_arguments_for_acceptance( + argumentation_framework, argument) elif explanation_function == 'MinSuff': # TODO: Check what happens here, could be done more efficiently. - sufficient_sets = get_sufficient_arguments_for_acceptance(argumentation_framework, argument) + sufficient_sets = get_sufficient_arguments_for_acceptance( + argumentation_framework, argument) current_minimal_sufficient_explanations = [] for sufficient_set in sufficient_sets: minsuff_suff = [] - for potential_minimal_sufficient_explanation in current_minimal_sufficient_explanations: - if potential_minimal_sufficient_explanation.issubset(sufficient_set): - minsuff_suff.append(potential_minimal_sufficient_explanation) - if sufficient_set.issubset(potential_minimal_sufficient_explanation): - current_minimal_sufficient_explanations.remove(potential_minimal_sufficient_explanation) - current_minimal_sufficient_explanations.append(sufficient_set) - if minsuff_suff == [] and sufficient_set not in current_minimal_sufficient_explanations: - current_minimal_sufficient_explanations.append(sufficient_set) + for potential_minimal_sufficient_explanation in \ + current_minimal_sufficient_explanations: + if potential_minimal_sufficient_explanation.issubset( + sufficient_set): + minsuff_suff.append( + potential_minimal_sufficient_explanation) + if sufficient_set.issubset( + potential_minimal_sufficient_explanation): + current_minimal_sufficient_explanations.remove( + potential_minimal_sufficient_explanation) + current_minimal_sufficient_explanations.append( + sufficient_set) + if minsuff_suff == [] and sufficient_set not in \ + current_minimal_sufficient_explanations: + current_minimal_sufficient_explanations.append( + sufficient_set) return current_minimal_sufficient_explanations elif explanation_function == 'Nec': - return get_necessary_arguments_for_acceptance(argumentation_framework, argument) + return get_necessary_arguments_for_acceptance( + argumentation_framework, argument) raise NotImplementedError -def get_sufficient_arguments_for_acceptance(arg_framework: AbstractArgumentationFramework, argument: Argument): +def get_sufficient_arguments_for_acceptance( + arg_framework: AbstractArgumentationFramework, argument: Argument): """ - Obtain the sets with sufficient arguments for the acceptance of the given argument. + Obtain the sets with sufficient arguments for the acceptance of the given + argument. - :param arg_framework: The argumentation framework the explanation should be about. + :param arg_framework: The argumentation framework the explanation should + be about. :param argument: The argument that is accepted. - :return: a list of sets of arguments, each representing a sufficient set of arguments for the acceptance of the - given argument. + :return: a list of sets of arguments, each representing a sufficient set of + arguments for the acceptance of the given argument. """ sufficient_sets = [] reach, dist = get_reach(arg_framework, argument) @@ -66,13 +90,16 @@ def get_sufficient_arguments_for_acceptance(arg_framework: AbstractArgumentation return sufficient_sets -def get_necessary_arguments_for_acceptance(arg_framework: AbstractArgumentationFramework, argument: Argument): +def get_necessary_arguments_for_acceptance( + arg_framework: AbstractArgumentationFramework, argument: Argument): """ Obtain the necessary arguments for the acceptance of the given argument. - :param arg_framework: The argumentation framework the explanation should be about. + :param arg_framework: The argumentation framework the explanation should be + about. :param argument: The argument that is accepted. - :return: a list of arguments, necessary for the acceptance of the given argument. + :return: a list of arguments, necessary for the acceptance of the given + argument. """ reach, dist = get_reach(arg_framework, argument) admissible_sets = get_admissible_sets(arg_framework) diff --git a/src/py_arg/abstract_argumentation/generators/abstract_argumentation_framework_generator.py b/src/py_arg/abstract_argumentation/generators/abstract_argumentation_framework_generator.py index 59e7d79..ac5d586 100644 --- a/src/py_arg/abstract_argumentation/generators/abstract_argumentation_framework_generator.py +++ b/src/py_arg/abstract_argumentation/generators/abstract_argumentation_framework_generator.py @@ -2,7 +2,8 @@ from datetime import datetime from typing import Optional -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat @@ -10,31 +11,38 @@ class AbstractArgumentationFrameworkGenerator: - def __init__(self, nr_of_arguments: int, nr_of_defeats: int, allow_self_defeats: bool = True): + def __init__(self, nr_of_arguments: int, nr_of_defeats: int, + allow_self_defeats: bool = True): """ - Construct a generator for making random AbstractArgumentationFramework objects. + Construct a generator for making random AbstractArgumentationFramework + objects. :param nr_of_arguments: The desired number of arguments. :param nr_of_defeats: The desired number of defeats. - :param allow_self_defeats: Boolean indicating whether to allow self-defeats. + :param allow_self_defeats: Boolean indicating whether to allow + self-defeats. """ self.nr_of_arguments = nr_of_arguments self.nr_of_defeats = nr_of_defeats self.allow_self_defeats = allow_self_defeats if self.allow_self_defeats: - if self.nr_of_defeats > self.nr_of_arguments * self.nr_of_arguments: + if self.nr_of_defeats >\ + self.nr_of_arguments * self.nr_of_arguments: raise ValueError('The number of defeats cannot be so high.') else: - if self.nr_of_defeats > self.nr_of_arguments * (self.nr_of_arguments - 1): + if self.nr_of_defeats > self.nr_of_arguments * \ + (self.nr_of_arguments - 1): raise ValueError('The number of defeats cannot be so high.') if self.nr_of_arguments <= 26: self.argument_names = ALPHABET[:self.nr_of_arguments] else: - self.argument_names = ['A' + str(i) for i in range(self.nr_of_arguments)] + self.argument_names = ['A' + str(i) + for i in range(self.nr_of_arguments)] - def generate(self, name: Optional[str] = None) -> AbstractArgumentationFramework: + def generate(self, name: Optional[str] = None) -> \ + AbstractArgumentationFramework: """ Generate a new AbstractArgumentationFramework. @@ -60,7 +68,8 @@ def generate(self, name: Optional[str] = None) -> AbstractArgumentationFramework """ # If no name is specified, a name containing a timestamp is generated. if not name: - name = 'AF_Generated' + datetime.now().strftime('%d/%m/%Y,%H:%M:%S') + name = 'AF_Generated' + \ + datetime.now().strftime('%d/%m/%Y,%H:%M:%S') # Construct arguments and randomly generate defeats. arguments = [Argument(arg_name) for arg_name in self.argument_names] diff --git a/src/py_arg/abstract_argumentation/generators/barbasi_albert_generator.py b/src/py_arg/abstract_argumentation/generators/barbasi_albert_generator.py index c7de953..90ec894 100644 --- a/src/py_arg/abstract_argumentation/generators/barbasi_albert_generator.py +++ b/src/py_arg/abstract_argumentation/generators/barbasi_albert_generator.py @@ -3,16 +3,21 @@ import networkx as nx -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import ALPHABET -from py_arg.abstract_argumentation.generators.generate_directed_graph import generate_directed_graph -from py_arg.abstract_argumentation.generators.enforce_prob_cycle import enforce_prob_cycle +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import ALPHABET +from py_arg.abstract_argumentation.generators.generate_directed_graph import \ + generate_directed_graph +from py_arg.abstract_argumentation.generators.enforce_prob_cycle import \ + enforce_prob_cycle class BarabasiAlbert: - def __init__(self, nr_of_arguments: int, nr_attach_node_to: int, prob_cycle: float, seed: int = None): + def __init__(self, nr_of_arguments: int, nr_attach_node_to: int, + prob_cycle: float, seed: int = None): self.nr_of_arguments = nr_of_arguments self.prob_cycle = prob_cycle self.nr_attach_node_to = nr_attach_node_to @@ -20,18 +25,23 @@ def __init__(self, nr_of_arguments: int, nr_attach_node_to: int, prob_cycle: flo self.last_generated_nx_graph = None if not (0 <= self.prob_cycle <= 1.0): - raise ValueError('The Probability of argument being in a cycle must lie in the interval [0,1]') + raise ValueError('The Probability of argument being in a cycle ' + 'must lie in the interval [0,1]') - if not self.nr_attach_node_to >= 1 and self.nr_attach_node_to < self.nr_of_arguments: + if not self.nr_attach_node_to >= 1 and \ + self.nr_attach_node_to < self.nr_of_arguments: raise ValueError( - 'Barabási–Albert network must have nr_attach_node_to >= 1 and nr_attach_node_to < nr_of_arguments') + 'Barabási–Albert network must have nr_attach_node_to >= 1 and ' + 'nr_attach_node_to < nr_of_arguments') if self.nr_of_arguments <= 26: self.argument_names = ALPHABET[:self.nr_of_arguments] else: - self.argument_names = ['A' + str(i) for i in range(self.nr_of_arguments)] + self.argument_names = ['A' + str(i) + for i in range(self.nr_of_arguments)] - def generate(self, name: Optional[str] = None) -> AbstractArgumentationFramework: + def generate(self, name: Optional[str] = None) -> \ + AbstractArgumentationFramework: """ Generate a Watts-Strogatz small-world graph. @@ -40,26 +50,32 @@ def generate(self, name: Optional[str] = None) -> AbstractArgumentationFramework """ # If no name is specified, a name containing a timestamp is generated. if not name: - name = 'AF_BA_Generated' + datetime.now().strftime('%d/%m/%Y,%H:%M:%S') + name = 'AF_BA_Generated' + \ + datetime.now().strftime('%d/%m/%Y,%H:%M:%S') - barabasi_albert_graph = nx.barabasi_albert_graph(n=self.nr_of_arguments, m=self.nr_attach_node_to, - seed=self.seed) + barabasi_albert_graph = nx.barabasi_albert_graph( + n=self.nr_of_arguments, m=self.nr_attach_node_to, + seed=self.seed) directed_edges = [] # Choose edge direction at random - directed_barabasi_albert_graph = generate_directed_graph(barabasi_albert_graph, directed_edges) + directed_barabasi_albert_graph = generate_directed_graph( + barabasi_albert_graph, directed_edges) self.last_generated_nx_graph = directed_barabasi_albert_graph edge_list = list(directed_barabasi_albert_graph.edges()) # - enforce_prob_cycle(self.nr_of_arguments, self.prob_cycle, directed_barabasi_albert_graph, edge_list) + enforce_prob_cycle(self.nr_of_arguments, self.prob_cycle, + directed_barabasi_albert_graph, edge_list) # Construct arguments arguments = [Argument(arg_name) for arg_name in self.argument_names] # Map node ids from networkx graph to arguments - node_id_to_argument_map = dict(zip(sorted(directed_barabasi_albert_graph.nodes), arguments)) + node_id_to_argument_map = dict(zip(sorted( + directed_barabasi_albert_graph.nodes), arguments)) - defeats = [Defeat(node_id_to_argument_map[defeat[0]], node_id_to_argument_map[defeat[1]]) for defeat in + defeats = [Defeat(node_id_to_argument_map[defeat[0]], + node_id_to_argument_map[defeat[1]]) for defeat in barabasi_albert_graph.edges] return AbstractArgumentationFramework(name, arguments, defeats) diff --git a/src/py_arg/abstract_argumentation/generators/enforce_prob_cycle.py b/src/py_arg/abstract_argumentation/generators/enforce_prob_cycle.py index 98e0201..482b291 100644 --- a/src/py_arg/abstract_argumentation/generators/enforce_prob_cycle.py +++ b/src/py_arg/abstract_argumentation/generators/enforce_prob_cycle.py @@ -3,9 +3,10 @@ import networkx as nx -def enforce_prob_cycle(nr_of_arguments,prob_cycle, graph, edge_list): - while nx.number_strongly_connected_components(graph) >= nr_of_arguments * (1.00 - prob_cycle): +def enforce_prob_cycle(nr_of_arguments, prob_cycle, graph, edge_list): + while nx.number_strongly_connected_components(graph) >= nr_of_arguments * \ + (1.00 - prob_cycle): edge = random.choice(edge_list) - if (edge[1],edge[0]) in graph.edges: + if (edge[1], edge[0]) in graph.edges: continue - graph.add_edge(edge[1],edge[0]) + graph.add_edge(edge[1], edge[0]) diff --git a/src/py_arg/abstract_argumentation/generators/erdos_renyi_generator.py b/src/py_arg/abstract_argumentation/generators/erdos_renyi_generator.py index 26fa0ce..f559df1 100644 --- a/src/py_arg/abstract_argumentation/generators/erdos_renyi_generator.py +++ b/src/py_arg/abstract_argumentation/generators/erdos_renyi_generator.py @@ -3,14 +3,17 @@ import networkx as nx -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import ALPHABET +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import ALPHABET class ErdosRenyiGenerator: - def __init__(self, nr_of_arguments: int, prob_edge: float, is_directed: bool = True, seed: int = None): + def __init__(self, nr_of_arguments: int, prob_edge: float, + is_directed: bool = True, seed: int = None): self.nr_of_arguments = nr_of_arguments self.prob_edge = prob_edge self.is_directed = is_directed @@ -18,14 +21,17 @@ def __init__(self, nr_of_arguments: int, prob_edge: float, is_directed: bool = T self.last_generated_nx_graph = None if not (0 < self.prob_edge <= 1.0): - raise ValueError('The probability for an edge must lie in the interval ]0,1]') + raise ValueError( + 'The probability for an edge must lie in the interval ]0,1]') if self.nr_of_arguments <= 26: self.argument_names = ALPHABET[:self.nr_of_arguments] else: - self.argument_names = ['A' + str(i) for i in range(self.nr_of_arguments)] + self.argument_names = ['A' + str(i) for i in + range(self.nr_of_arguments)] - def generate(self, name: Optional[str] = None) -> AbstractArgumentationFramework: + def generate(self, + name: Optional[str] = None) -> AbstractArgumentationFramework: """ Generate a new random graph Erdős-Rényi graph. @@ -34,17 +40,21 @@ def generate(self, name: Optional[str] = None) -> AbstractArgumentationFramework """ # If no name is specified, a name containing a timestamp is generated. if not name: - name = 'AF_ER_Generated' + datetime.now().strftime('%d/%m/%Y,%H:%M:%S') + name = 'AF_ER_Generated' + datetime.now().strftime( + '%d/%m/%Y,%H:%M:%S') - erdos_reny_graph = nx.erdos_renyi_graph(self.nr_of_arguments, self.prob_edge, seed=self.seed, + erdos_reny_graph = nx.erdos_renyi_graph(self.nr_of_arguments, + self.prob_edge, seed=self.seed, directed=self.is_directed) self.last_generated_nx_graph = erdos_reny_graph # Construct arguments arguments = [Argument(arg_name) for arg_name in self.argument_names] # Map node ids from networkx graph to arguments - node_id_to_argument_map = dict(zip(sorted(erdos_reny_graph.nodes), arguments)) + node_id_to_argument_map = dict( + zip(sorted(erdos_reny_graph.nodes), arguments)) - defeats = [Defeat(node_id_to_argument_map[defeat[0]], node_id_to_argument_map[defeat[1]]) for defeat in + defeats = [Defeat(node_id_to_argument_map[defeat[0]], + node_id_to_argument_map[defeat[1]]) for defeat in erdos_reny_graph.edges] return AbstractArgumentationFramework(name, arguments, defeats) diff --git a/src/py_arg/abstract_argumentation/generators/watts_strogatz_generator.py b/src/py_arg/abstract_argumentation/generators/watts_strogatz_generator.py index 1b8816a..cd9db89 100644 --- a/src/py_arg/abstract_argumentation/generators/watts_strogatz_generator.py +++ b/src/py_arg/abstract_argumentation/generators/watts_strogatz_generator.py @@ -3,16 +3,21 @@ import networkx as nx -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import ALPHABET -from py_arg.abstract_argumentation.generators.generate_directed_graph import generate_directed_graph -from py_arg.abstract_argumentation.generators.enforce_prob_cycle import enforce_prob_cycle +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import ALPHABET +from py_arg.abstract_argumentation.generators.enforce_prob_cycle import \ + enforce_prob_cycle +from py_arg.abstract_argumentation.generators.generate_directed_graph import \ + generate_directed_graph class WattsStrogatz: - def __init__(self, nr_of_arguments: int, prob_edge_rewiring: float, prob_cycle: float, nr_join_neighbours: int, + def __init__(self, nr_of_arguments: int, prob_edge_rewiring: float, + prob_cycle: float, nr_join_neighbours: int, seed: int = None): self.nr_of_arguments = nr_of_arguments self.prob_edge_rewiring = prob_edge_rewiring @@ -22,16 +27,22 @@ def __init__(self, nr_of_arguments: int, prob_edge_rewiring: float, prob_cycle: self.last_generated_nx_graph = None if not (0 <= self.prob_edge_rewiring <= 1.0): - raise ValueError('The probability for rewiring an edge must lie in the interval [0,1]') + raise ValueError( + 'The probability for rewiring an edge must lie in the interval' + ' [0,1]') if not (0 <= self.prob_cycle <= 1.0): - raise ValueError('The Probability of argument being in a cycle must lie in the interval [0,1]') + raise ValueError( + 'The Probability of argument being in a cycle must lie in the ' + 'interval [0,1]') if self.nr_of_arguments <= 26: self.argument_names = ALPHABET[:self.nr_of_arguments] else: - self.argument_names = ['A' + str(i) for i in range(self.nr_of_arguments)] + self.argument_names = ['A' + str(i) for i in + range(self.nr_of_arguments)] - def generate(self, name: Optional[str] = None) -> AbstractArgumentationFramework: + def generate(self, + name: Optional[str] = None) -> AbstractArgumentationFramework: """ Generate a Watts-Strogatz small-world graph. @@ -40,26 +51,32 @@ def generate(self, name: Optional[str] = None) -> AbstractArgumentationFramework """ # If no name is specified, a name containing a timestamp is generated. if not name: - name = 'AF_WS_Generated' + datetime.now().strftime('%d/%m/%Y,%H:%M:%S') + name = 'AF_WS_Generated' + datetime.now().strftime( + '%d/%m/%Y,%H:%M:%S') - watts_strogatz_graph = nx.watts_strogatz_graph(n=self.nr_of_arguments, k=self.nr_join_neighbours, - p=self.prob_edge_rewiring, seed=self.seed) + watts_strogatz_graph = nx.watts_strogatz_graph( + n=self.nr_of_arguments, k=self.nr_join_neighbours, + p=self.prob_edge_rewiring, seed=self.seed) directed_edges = [] # Choose edge direction at random - directed_watts_strogatz_graph = generate_directed_graph(watts_strogatz_graph, directed_edges) + directed_watts_strogatz_graph = generate_directed_graph( + watts_strogatz_graph, directed_edges) self.last_generated_nx_graph = directed_watts_strogatz_graph edge_list = list(directed_watts_strogatz_graph.edges()) # - enforce_prob_cycle(self.nr_of_arguments, self.prob_cycle, directed_watts_strogatz_graph, edge_list) + enforce_prob_cycle(self.nr_of_arguments, self.prob_cycle, + directed_watts_strogatz_graph, edge_list) # Construct arguments arguments = [Argument(arg_name) for arg_name in self.argument_names] # Map node ids from networkx graph to arguments - node_id_to_argument_map = dict(zip(sorted(directed_watts_strogatz_graph.nodes), arguments)) + node_id_to_argument_map = dict( + zip(sorted(directed_watts_strogatz_graph.nodes), arguments)) - defeats = [Defeat(node_id_to_argument_map[defeat[0]], node_id_to_argument_map[defeat[1]]) for defeat in + defeats = [Defeat(node_id_to_argument_map[defeat[0]], + node_id_to_argument_map[defeat[1]]) for defeat in watts_strogatz_graph.edges] return AbstractArgumentationFramework(name, arguments, defeats) diff --git a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_aspartix_format_reader.py b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_aspartix_format_reader.py index 316397c..db43649 100644 --- a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_aspartix_format_reader.py +++ b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_aspartix_format_reader.py @@ -2,21 +2,25 @@ import parse -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat class ArgumentationFrameworkFromASPARTIXFormatReader: @staticmethod - def from_apx(apx_str: str, argumentation_framework_name: Optional[str] = None) -> AbstractArgumentationFramework: + def from_apx(apx_str: str, + argumentation_framework_name: Optional[str] = None) -> \ + AbstractArgumentationFramework: if argumentation_framework_name: name = argumentation_framework_name else: name = '' argument_strs = [r[0] for r in parse.findall('arg({}).', apx_str)] - defeat_strs = [(r[0], r[1]) for r in parse.findall('att({},{}).', apx_str)] + defeat_strs = [(r[0], r[1]) for r in parse.findall('att({},{}).', + apx_str)] arguments = [Argument(arg_str) for arg_str in argument_strs] defeats = [Defeat(Argument(defeat_str[0]), Argument(defeat_str[1])) diff --git a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_iccma23_format_reader.py b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_iccma23_format_reader.py index 05f432e..c63c41f 100644 --- a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_iccma23_format_reader.py +++ b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_iccma23_format_reader.py @@ -1,13 +1,16 @@ from typing import Optional -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat class ArgumentationFrameworkFromICCMA23FormatReader: @staticmethod - def from_iccma23(iccma_23_str: str, argumentation_framework_name: Optional[str] = None) -> AbstractArgumentationFramework: + def from_iccma23(iccma_23_str: str, + argumentation_framework_name: Optional[str] = None) -> \ + AbstractArgumentationFramework: if argumentation_framework_name: name = argumentation_framework_name else: @@ -15,7 +18,8 @@ def from_iccma23(iccma_23_str: str, argumentation_framework_name: Optional[str] lines = iccma_23_str.split('\n') nr_argument_lines = int(lines[0].split(' ')[2]) - arguments = [Argument('A' + str(index)) for index in range(1, nr_argument_lines + 1)] + arguments = [Argument('A' + str(index)) + for index in range(1, nr_argument_lines + 1)] defeats = [] for line in lines[1:]: if line: diff --git a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_json_reader.py b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_json_reader.py index 03927cb..5a87984 100644 --- a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_json_reader.py +++ b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_json_reader.py @@ -2,7 +2,8 @@ from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework class ArgumentationFrameworkFromJsonReader: @@ -15,7 +16,8 @@ def from_json(json_object) -> AbstractArgumentationFramework: name = json_object['name'] else: name = '' - arguments = [Argument(argument_name) for argument_name in json_object['arguments']] + arguments = [Argument(argument_name) + for argument_name in json_object['arguments']] defeats = [Defeat(Argument(from_argument), Argument(to_argument)) for from_argument, to_argument in json_object['defeats']] return AbstractArgumentationFramework(name, arguments, defeats) diff --git a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_trivial_graph_format_reader.py b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_trivial_graph_format_reader.py index 845c1ef..2ec01e0 100644 --- a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_trivial_graph_format_reader.py +++ b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_from_trivial_graph_format_reader.py @@ -1,13 +1,16 @@ from typing import Optional -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat class ArgumentationFrameworkFromTrivialGraphFormatReader: @staticmethod - def from_tgf(tgf_str: str, argumentation_framework_name: Optional[str] = None) -> AbstractArgumentationFramework: + def from_tgf(tgf_str: str, + argumentation_framework_name: Optional[str] = None) -> \ + AbstractArgumentationFramework: if argumentation_framework_name: name = argumentation_framework_name else: diff --git a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_aspartix_format_writer.py b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_aspartix_format_writer.py index 1e538d5..fba8b3a 100644 --- a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_aspartix_format_writer.py +++ b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_aspartix_format_writer.py @@ -1,14 +1,17 @@ from io import StringIO -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework class ArgumentationFrameworkToASPARTIXFormatWriter: @staticmethod - def write_to_str(argumentation_framework: AbstractArgumentationFramework) -> str: + def write_to_str( + argumentation_framework: AbstractArgumentationFramework) -> str: sentence = StringIO() for argument in argumentation_framework.arguments: sentence.write('arg(' + argument.name + ').\n') for defeat in argumentation_framework.defeats: - sentence.write('att(' + defeat.from_argument.name + ',' + defeat.to_argument.name + ').\n') + sentence.write('att(' + defeat.from_argument.name + ',' + + defeat.to_argument.name + ').\n') return sentence.getvalue() diff --git a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_iccma23_format_writer.py b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_iccma23_format_writer.py index 0296ee4..ff05b85 100644 --- a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_iccma23_format_writer.py +++ b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_iccma23_format_writer.py @@ -1,17 +1,25 @@ from io import StringIO -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework class ArgumentationFrameworkToICCMA23FormatWriter: @staticmethod - def write_to_str(argumentation_framework: AbstractArgumentationFramework) -> str: + def write_to_str( + argumentation_framework: AbstractArgumentationFramework) -> str: arg_name_to_index_dict = \ - {name: str(index + 1) for index, name in enumerate([arg.name for arg in argumentation_framework.arguments])} + {name: str(index + 1) + for index, name in + enumerate([arg.name + for arg in argumentation_framework.arguments])} sentence = StringIO() - sentence.write('p af ' + str(len(argumentation_framework.arguments)) + '\n') + sentence.write('p af ' + str(len(argumentation_framework.arguments)) + + '\n') for defeat in argumentation_framework.defeats: - sentence.write(arg_name_to_index_dict[defeat.from_argument.name] + ' ' + - arg_name_to_index_dict[defeat.to_argument.name] + '\n') + sentence.write(arg_name_to_index_dict[defeat.from_argument.name] + + ' ' + + arg_name_to_index_dict[defeat.to_argument.name] + + '\n') return sentence.getvalue() diff --git a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_json_writer.py b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_json_writer.py index ab2fb5f..5403877 100644 --- a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_json_writer.py +++ b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_json_writer.py @@ -1,6 +1,7 @@ import json -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.incomplete_aspic.import_export.writer import Writer @@ -11,11 +12,15 @@ def __init__(self): @staticmethod def to_dict(argumentation_framework: AbstractArgumentationFramework): return {'name': argumentation_framework.name, - 'arguments': [str(argument) for argument in argumentation_framework.arguments], - 'defeats': [(str(defeat.from_argument), str(defeat.to_argument)) + 'arguments': + [str(argument) + for argument in argumentation_framework.arguments], + 'defeats': [(str(defeat.from_argument), + str(defeat.to_argument)) for defeat in argumentation_framework.defeats]} - def write(self, argumentation_framework: AbstractArgumentationFramework, file_name: str): + def write(self, argumentation_framework: AbstractArgumentationFramework, + file_name: str): write_path = self.data_folder / file_name result = self.to_dict(argumentation_framework) with open(write_path, 'w') as write_file: diff --git a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_trivial_graph_format_writer.py b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_trivial_graph_format_writer.py index b5ed6df..c92a1d6 100644 --- a/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_trivial_graph_format_writer.py +++ b/src/py_arg/abstract_argumentation/import_export/argumentation_framework_to_trivial_graph_format_writer.py @@ -1,15 +1,18 @@ from io import StringIO -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework class ArgumentationFrameworkToTrivialGraphFormatWriter: @staticmethod - def write_to_str(argumentation_framework: AbstractArgumentationFramework) -> str: + def write_to_str( + argumentation_framework: AbstractArgumentationFramework) -> str: sentence = StringIO() for argument in argumentation_framework.arguments: sentence.write(argument.name + '\n') sentence.write('#\n') for defeat in argumentation_framework.defeats: - sentence.write(defeat.from_argument.name + ' ' + defeat.to_argument.name + '\n') + sentence.write(defeat.from_argument.name + ' ' + + defeat.to_argument.name + '\n') return sentence.getvalue() diff --git a/src/py_arg/abstract_argumentation/semantics/get_acceptable_with_respect_to.py b/src/py_arg/abstract_argumentation/semantics/get_acceptable_with_respect_to.py index 4a4bef4..a01fa81 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_acceptable_with_respect_to.py +++ b/src/py_arg/abstract_argumentation/semantics/get_acceptable_with_respect_to.py @@ -1,40 +1,29 @@ from typing import Set, Iterable -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.semantics.is_acceptable_with_respect_to import is_acceptable_with_respect_to +from py_arg.abstract_argumentation.semantics.is_acceptable_with_respect_to \ + import is_acceptable_with_respect_to -def get_acceptable_with_respect_to(argument_set: Iterable[Argument], - argumentation_framework: AbstractArgumentationFramework) -> Set[Argument]: +def get_acceptable_with_respect_to( + argument_set: Iterable[Argument], + argumentation_framework: AbstractArgumentationFramework) -> \ + Set[Argument]: """ - Get the set of argument that is acceptable with respect to this set of arguments. + Get the set of argument that is acceptable with respect to this set of + arguments. - :param argument_set: The set of arguments for which we want to find the acceptable arguments. + :param argument_set: The set of arguments for which we want to find the + acceptable arguments. :param argumentation_framework: Abstract argumentation framework. - :return: The set of arguments that are acceptable w.r.t. this set of arguments. - - >>> a = Argument('a') - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [a, b, c, d] - >>> defeats = [Defeat(b, a), Defeat(c, b), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> acc_set = get_acceptable_with_respect_to(set(), af) - >>> d in acc_set - True - >>> a in acc_set or b in acc_set or c in acc_set - False - >>> acc_set = get_acceptable_with_respect_to({d}, af) - >>> d in acc_set - True - >>> b in acc_set - True + :return: The set of arguments that are acceptable w.r.t. this set of + arguments. """ return {argument for argument in argumentation_framework.arguments - if is_acceptable_with_respect_to(argument, argument_set, argumentation_framework)} + if is_acceptable_with_respect_to(argument, argument_set, + argumentation_framework)} if __name__ == "__main__": diff --git a/src/py_arg/abstract_argumentation/semantics/get_admissible_sets.py b/src/py_arg/abstract_argumentation/semantics/get_admissible_sets.py index bedb5d5..2948c11 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_admissible_sets.py +++ b/src/py_arg/abstract_argumentation/semantics/get_admissible_sets.py @@ -1,86 +1,93 @@ from enum import Enum from typing import Set, Dict, FrozenSet -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. "Algorithms for decision problems in argument -# systems under preferred semantics." Artificial Intelligence 207 (2014): 23-51. +# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. +# "Algorithms for decision problems in argument +# systems under preferred semantics." Artificial Intelligence 207 (2014): +# 23-51. class AdmissibleLabel(Enum): IN = 1 # Arguments *might* be in an admissible set OUT = 2 # Argument is defeated by an IN argument - BLANK = 3 # Default label for all arguments, indicating that the argument is still unprocessed. + # Default label for all arguments, indicating that the argument is still + # unprocessed. + BLANK = 3 MUST_OUT = 4 # Argument defeats IN argument - UNDEC = 5 # Argument may not be included in an admissible set because not defended by any IN argument. + # Argument may not be included in an admissible set because not defended + # by any IN argument. + UNDEC = 5 -def get_admissible_sets(argumentation_framework: AbstractArgumentationFramework) -> Set[FrozenSet[Argument]]: +def get_admissible_sets( + argumentation_framework: AbstractArgumentationFramework) -> \ + Set[FrozenSet[Argument]]: """ Get the admissible sets of an argumentation framework. - :param argumentation_framework: The argumentation framework for which we need the admissible sets. + :param argumentation_framework: The argumentation framework for which we + need the admissible sets. :return: admissible sets of the argumentation framework. - - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [b, c, d] - >>> defeats = [Defeat(b, c), Defeat(c, d), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> ads = get_admissible_sets(af) - >>> len(ads) - 4 - >>> frozenset({b, d}) in ads - True - >>> frozenset({c}) in ads - False """ initial_labelling = {argument: AdmissibleLabel.BLANK for argument in argumentation_framework.arguments} - return _recursively_get_admissible_sets(argumentation_framework, initial_labelling, set()) + return _recursively_get_admissible_sets(argumentation_framework, + initial_labelling, set()) -def _recursively_get_admissible_sets(argumentation_framework: AbstractArgumentationFramework, - labelling: Dict[Argument, AdmissibleLabel], - admissible_sets: Set[FrozenSet[Argument]]) -> Set[FrozenSet[Argument]]: - if all(labelling[argument] != AdmissibleLabel.BLANK for argument in argumentation_framework.arguments): +def _recursively_get_admissible_sets( + argumentation_framework: AbstractArgumentationFramework, + labelling: Dict[Argument, AdmissibleLabel], + admissible_sets: Set[FrozenSet[Argument]]) -> Set[FrozenSet[Argument]]: + if all(labelling[argument] != AdmissibleLabel.BLANK for argument in + argumentation_framework.arguments): if all(labelling[argument] != AdmissibleLabel.MUST_OUT for argument in argumentation_framework.arguments): - candidate_admissible_set = frozenset(sorted({argument for argument in argumentation_framework.arguments - if labelling[argument] == AdmissibleLabel.IN})) + candidate_admissible_set = frozenset(sorted( + {argument for argument in argumentation_framework.arguments + if labelling[argument] == AdmissibleLabel.IN})) admissible_sets.add(candidate_admissible_set) else: - blank_argument = [argument for argument in argumentation_framework.arguments - if labelling[argument] == AdmissibleLabel.BLANK][0] - alternative_labelling = _in_trans(labelling, blank_argument, argumentation_framework) - admissible_sets = _recursively_get_admissible_sets(argumentation_framework, alternative_labelling, - admissible_sets) + blank_argument = \ + [argument for argument in argumentation_framework.arguments + if labelling[argument] == AdmissibleLabel.BLANK][0] + alternative_labelling = _in_trans(labelling, blank_argument, + argumentation_framework) + admissible_sets = _recursively_get_admissible_sets( + argumentation_framework, alternative_labelling, + admissible_sets) alternative_labelling = _undec_trans(labelling, blank_argument) - admissible_sets = _recursively_get_admissible_sets(argumentation_framework, alternative_labelling, - admissible_sets) + admissible_sets = _recursively_get_admissible_sets( + argumentation_framework, alternative_labelling, + admissible_sets) return admissible_sets def _in_trans(labelling: Dict[Argument, AdmissibleLabel], argument: Argument, - argumentation_framework: AbstractArgumentationFramework) -> Dict[Argument, AdmissibleLabel]: + argumentation_framework: AbstractArgumentationFramework) -> \ + Dict[Argument, AdmissibleLabel]: new_labelling = labelling.copy() new_labelling[argument] = AdmissibleLabel.IN - for defeater in argumentation_framework.get_outgoing_defeat_arguments(argument): + for defeater in argumentation_framework.get_outgoing_defeat_arguments( + argument): if defeater == argument: break else: new_labelling[defeater] = AdmissibleLabel.OUT - for defeated in argumentation_framework.get_incoming_defeat_arguments(argument): + for defeated in argumentation_framework.get_incoming_defeat_arguments( + argument): if new_labelling[defeated] != AdmissibleLabel.OUT: new_labelling[defeated] = AdmissibleLabel.MUST_OUT return new_labelling -def _undec_trans(labelling: Dict[Argument, AdmissibleLabel], argument: Argument) -> \ +def _undec_trans(labelling: Dict[Argument, AdmissibleLabel], + argument: Argument) -> \ Dict[Argument, AdmissibleLabel]: new_labelling = labelling.copy() new_labelling[argument] = AdmissibleLabel.UNDEC diff --git a/src/py_arg/abstract_argumentation/semantics/get_complete_extensions.py b/src/py_arg/abstract_argumentation/semantics/get_complete_extensions.py index 08d1596..bf5d08f 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_complete_extensions.py +++ b/src/py_arg/abstract_argumentation/semantics/get_complete_extensions.py @@ -1,97 +1,111 @@ from enum import Enum from typing import Set, Dict, FrozenSet -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. "Algorithms for decision problems in argument -# systems under preferred semantics." Artificial Intelligence 207 (2014): 23-51. +# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. +# "Algorithms for decision problems in argument +# systems under preferred semantics." Artificial Intelligence 207 (2014): +# 23-51. class CompleteExtensionLabel(Enum): IN = 1 # Arguments *might* be in a complete extension OUT = 2 # Argument is defeated by an IN argument - BLANK = 3 # Default label for all arguments, indicating that the argument is still unprocessed. + BLANK = 3 # Default label for all arguments, indicating that the argument + # is still unprocessed. MUST_OUT = 4 # Argument defeats IN argument - UNDEC = 5 # Argument may not be included in a complete extension because not defended by any IN argument. + UNDEC = 5 # Argument may not be included in a complete extension because + # not defended by any IN argument. -def get_complete_extensions(argumentation_framework: AbstractArgumentationFramework) -> Set[FrozenSet[Argument]]: +def get_complete_extensions( + argumentation_framework: AbstractArgumentationFramework) -> \ + Set[FrozenSet[Argument]]: """ Get the complete extensions of an argumentation framework. - :param argumentation_framework: The argumentation framework for which we need the complete extensions. + :param argumentation_framework: The argumentation framework for which we + need the complete extensions. :return: complete extensions of the argumentation framework. - - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [b, c, d] - >>> defeats = [Defeat(b, c), Defeat(c, d), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> ces = get_complete_extensions(af) - >>> len(ces) - 1 - >>> frozenset({b, d}) in ces - True - >>> frozenset({b}) in ces - False """ initial_labelling = {argument: CompleteExtensionLabel.BLANK for argument in argumentation_framework.arguments} - return _recursively_get_complete_extensions(argumentation_framework, initial_labelling, set()) + return _recursively_get_complete_extensions(argumentation_framework, + initial_labelling, set()) -def _recursively_get_complete_extensions(argumentation_framework: AbstractArgumentationFramework, - labelling: Dict[Argument, CompleteExtensionLabel], - complete_extensions: Set[FrozenSet[Argument]]) -> Set[FrozenSet[Argument]]: - if all(labelling[argument] != CompleteExtensionLabel.BLANK for argument in argumentation_framework.arguments): +def _recursively_get_complete_extensions( + argumentation_framework: AbstractArgumentationFramework, + labelling: Dict[Argument, CompleteExtensionLabel], + complete_extensions: Set[FrozenSet[Argument]]) -> \ + Set[FrozenSet[Argument]]: + if all(labelling[argument] != CompleteExtensionLabel.BLANK for argument in + argumentation_framework.arguments): if all(labelling[argument] != CompleteExtensionLabel.MUST_OUT for argument in argumentation_framework.arguments): - candidate_complete_extension = frozenset(sorted({argument for argument in argumentation_framework.arguments - if labelling[argument] == CompleteExtensionLabel.IN})) + candidate_complete_extension = frozenset(sorted( + {argument for argument in argumentation_framework.arguments + if labelling[argument] == CompleteExtensionLabel.IN})) - candidate_complete_undec = {argument for argument in argumentation_framework.arguments - if labelling[argument] == CompleteExtensionLabel.UNDEC} + candidate_complete_undec = \ + {argument for argument in argumentation_framework.arguments + if labelling[argument] == CompleteExtensionLabel.UNDEC} legally_undec = set() for argument in candidate_complete_undec: - if all(labelling[defeater] != CompleteExtensionLabel.IN for defeater in - argumentation_framework.get_incoming_defeat_arguments(argument)) and \ - not all(labelling[defeater_out] == CompleteExtensionLabel.OUT for defeater_out in - argumentation_framework.get_incoming_defeat_arguments(argument)): + if all(labelling[defeater] != CompleteExtensionLabel.IN for + defeater in + argumentation_framework.get_incoming_defeat_arguments( + argument)) and \ + not all(labelling[ + defeater_out] == CompleteExtensionLabel.OUT + for defeater_out in + argumentation_framework. + get_incoming_defeat_arguments( + argument)): legally_undec.add(argument) if legally_undec == candidate_complete_undec: complete_extensions.add(candidate_complete_extension) else: - blank_argument = [argument for argument in argumentation_framework.arguments - if labelling[argument] == CompleteExtensionLabel.BLANK][0] - alternative_labelling = _in_trans(labelling, blank_argument, argumentation_framework) - complete_extensions = _recursively_get_complete_extensions(argumentation_framework, alternative_labelling, - complete_extensions) + blank_argument = \ + [argument for argument in argumentation_framework.arguments + if labelling[argument] == CompleteExtensionLabel.BLANK][0] + alternative_labelling = _in_trans(labelling, blank_argument, + argumentation_framework) + complete_extensions = _recursively_get_complete_extensions( + argumentation_framework, alternative_labelling, + complete_extensions) alternative_labelling = _undec_trans(labelling, blank_argument) - complete_extensions = _recursively_get_complete_extensions(argumentation_framework, alternative_labelling, - complete_extensions) + complete_extensions = _recursively_get_complete_extensions( + argumentation_framework, alternative_labelling, + complete_extensions) return complete_extensions -def _in_trans(labelling: Dict[Argument, CompleteExtensionLabel], argument: Argument, - argumentation_framework: AbstractArgumentationFramework) -> Dict[Argument, CompleteExtensionLabel]: +def _in_trans(labelling: Dict[Argument, CompleteExtensionLabel], + argument: Argument, + argumentation_framework: AbstractArgumentationFramework) -> \ + Dict[Argument, CompleteExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = CompleteExtensionLabel.IN - for defeater in argumentation_framework.get_outgoing_defeat_arguments(argument): + for defeater in argumentation_framework.get_outgoing_defeat_arguments( + argument): if defeater == argument: break else: new_labelling[defeater] = CompleteExtensionLabel.OUT - for defeated in argumentation_framework.get_incoming_defeat_arguments(argument): + for defeated in argumentation_framework.get_incoming_defeat_arguments( + argument): if new_labelling[defeated] != CompleteExtensionLabel.OUT: new_labelling[defeated] = CompleteExtensionLabel.MUST_OUT return new_labelling -def _undec_trans(labelling: Dict[Argument, CompleteExtensionLabel], argument: Argument) -> \ +def _undec_trans(labelling: Dict[Argument, CompleteExtensionLabel], + argument: Argument) -> \ Dict[Argument, CompleteExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = CompleteExtensionLabel.UNDEC diff --git a/src/py_arg/abstract_argumentation/semantics/get_conflict_free_extensions.py b/src/py_arg/abstract_argumentation/semantics/get_conflict_free_extensions.py index 604184b..1323dfb 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_conflict_free_extensions.py +++ b/src/py_arg/abstract_argumentation/semantics/get_conflict_free_extensions.py @@ -1,14 +1,18 @@ from typing import Set -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -def apply(argumentation_framework: AbstractArgumentationFramework) -> Set[frozenset[Argument]]: - return recursively_get_cf(set(), set(argumentation_framework.arguments), argumentation_framework) +def apply(argumentation_framework: AbstractArgumentationFramework) -> \ + Set[frozenset[Argument]]: + return recursively_get_cf(set(), set(argumentation_framework.arguments), + argumentation_framework) def recursively_get_cf(in_: Set[Argument], todo: Set[Argument], - af: AbstractArgumentationFramework) -> Set[frozenset[Argument]]: + af: AbstractArgumentationFramework) -> \ + Set[frozenset[Argument]]: if len(todo) == 0: return set() @@ -20,7 +24,8 @@ def recursively_get_cf(in_: Set[Argument], todo: Set[Argument], rec_todo.remove(arg) rm = set() for a in rec_todo: - if a < arg or a in arg.get_outgoing_defeat_arguments or a in arg.get_ingoing_defeat_arguments: + if a < arg or a in arg.get_outgoing_defeat_arguments or \ + a in arg.get_ingoing_defeat_arguments: rm.add(a) rec_todo.difference_update(rm) out.add(frozenset(in_.union({arg}))) diff --git a/src/py_arg/abstract_argumentation/semantics/get_eager_extension.py b/src/py_arg/abstract_argumentation/semantics/get_eager_extension.py index be7b86a..d416fe2 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_eager_extension.py +++ b/src/py_arg/abstract_argumentation/semantics/get_eager_extension.py @@ -1,79 +1,81 @@ from enum import Enum from typing import Set, Dict, FrozenSet, List, Union, Any -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. "Algorithms for decision problems in argument -# systems under preferred semantics." Artificial Intelligence 207 (2014): 23-51. -# Adjustment based on Modgil, Sanjay and Martin Caminada. "Proof Theories and Algorithms for Abstract Argumentation -# Frameworks." In Iyad Rahwan and Guillermo R. Simari, editors, Argumentation in Artificial Intelligence, pages 105–132 +# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. +# "Algorithms for decision problems in argument +# systems under preferred semantics." Artificial Intelligence 207 (2014): +# 23-51. +# Adjustment based on Modgil, Sanjay and Martin Caminada. "Proof Theories and +# Algorithms for Abstract Argumentation +# Frameworks." In Iyad Rahwan and Guillermo R. Simari, editors, Argumentation +# in Artificial Intelligence, pages 105–132 class EagerExtensionLabel(Enum): IN = 1 # Arguments *might* be in the eager extension OUT = 2 # Argument is defeated by an IN argument - BLANK = 3 # Default label for all arguments, indicating that the argument is still unprocessed. + BLANK = 3 # Default label for all arguments, indicating that the argument + # is still unprocessed. MUST_OUT = 4 # Argument defeats IN argument - UNDEC = 5 # Argument may not be included in the eager extension because not defended by any IN argument. + UNDEC = 5 # Argument may not be included in the eager extension because + # not defended by any IN argument. -def get_eager_extension(argumentation_framework: AbstractArgumentationFramework) -> List[ - Set[Union[Any]]]: +def get_eager_extension( + argumentation_framework: AbstractArgumentationFramework) -> \ + List[Set[Union[Any]]]: """ Get the eager extension of an argumentation framework. - :param argumentation_framework: The argumentation framework for which we need the eager extension. + :param argumentation_framework: The argumentation framework for which we + need the eager extension. :return: eager extension of the argumentation framework. - - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [b, c, d] - >>> defeats = [Defeat(b, c), Defeat(c, d), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> ees = get_eager_extension(af) - >>> len(ees) - 1 - >>> frozenset({b, d}) in ees - True - >>> frozenset({b}) in ees - False """ initial_labelling = {argument: EagerExtensionLabel.BLANK for argument in argumentation_framework.arguments} - admissible_labellings = _recursively_get_admissible_labellings(argumentation_framework, initial_labelling, []) + admissible_labellings = _recursively_get_admissible_labellings( + argumentation_framework, initial_labelling, []) frozen_admissible_sets = set() for labelling in admissible_labellings: - frozen_admissible_sets.add(frozenset(sorted({argument for argument in argumentation_framework.arguments - if labelling[argument] == EagerExtensionLabel.IN}))) - admissible_sets = [set(frozen_admissible_set) for frozen_admissible_set in frozen_admissible_sets] + frozen_admissible_sets.add(frozenset(sorted( + {argument for argument in argumentation_framework.arguments + if labelling[argument] == EagerExtensionLabel.IN}))) + admissible_sets = [set(frozen_admissible_set) + for frozen_admissible_set in frozen_admissible_sets] calculated_eager_undec = [] ss_labellings = [] for ss_labelling in admissible_labellings: - calculated_eager_undec.append([frozenset(sorted({argument for argument in argumentation_framework.arguments - if ss_labelling[argument] == EagerExtensionLabel.UNDEC})), + calculated_eager_undec.append([frozenset(sorted( + {argument for argument in argumentation_framework.arguments + if ss_labelling[argument] == EagerExtensionLabel.UNDEC})), ss_labelling]) for ss_labelling in admissible_labellings: - candidate_eager_undec = frozenset(sorted({argument for argument in argumentation_framework.arguments - if ss_labelling[argument] == EagerExtensionLabel.UNDEC})) + candidate_eager_undec = frozenset(sorted({ + argument for argument in argumentation_framework.arguments + if ss_labelling[argument] == EagerExtensionLabel.UNDEC})) if not any(candidate_eager_undec > eager_undec[0] for eager_undec in calculated_eager_undec): ss_labellings.append(ss_labelling) if any(candidate_eager_undec < eager_undec[0] for eager_undec in calculated_eager_undec): for eager_undec in calculated_eager_undec: - if candidate_eager_undec < eager_undec[0] and eager_undec[1] in ss_labellings: + if candidate_eager_undec < eager_undec[0] and \ + eager_undec[1] in ss_labellings: ss_labellings.remove(eager_undec[1]) semistable_extensions = [] for labelling in ss_labellings: - semistable_extensions.append({argument for argument in argumentation_framework.arguments if - labelling[argument] == EagerExtensionLabel.IN}) + semistable_extensions.append({ + argument for argument in argumentation_framework.arguments + if labelling[argument] == EagerExtensionLabel.IN}) intersect_semistable = set.intersection(*semistable_extensions) - admissible_subsets = [admissible_set for admissible_set in admissible_sets if - intersect_semistable.issuperset(admissible_set) == True] + admissible_subsets = [admissible_set + for admissible_set in admissible_sets if + intersect_semistable.issuperset(admissible_set)] max_admissible_subsets = [] for candidate_eager_extension in admissible_subsets: if not any(candidate_eager_extension < admissible_set @@ -82,39 +84,38 @@ def get_eager_extension(argumentation_framework: AbstractArgumentationFramework) return max_admissible_subsets -def _recursively_get_admissible_labellings(argumentation_framework: AbstractArgumentationFramework, - labelling: Dict[Argument, EagerExtensionLabel], - admissible_labellings: List[Dict[Argument, EagerExtensionLabel]]) -> List[ - Dict[Argument, EagerExtensionLabel]]: - if all(labelling[argument] != EagerExtensionLabel.BLANK for argument in argumentation_framework.arguments): +def _recursively_get_admissible_labellings( + argumentation_framework: AbstractArgumentationFramework, + labelling: Dict[Argument, EagerExtensionLabel], + admissible_labellings: List[Dict[Argument, EagerExtensionLabel]]) -> \ + List[Dict[Argument, EagerExtensionLabel]]: + if all(labelling[argument] != EagerExtensionLabel.BLANK + for argument in argumentation_framework.arguments): if all(labelling[argument] != EagerExtensionLabel.MUST_OUT for argument in argumentation_framework.arguments): admissible_labellings.append(labelling) - else: - blank_argument = [argument for argument in argumentation_framework.arguments - if labelling[argument] == EagerExtensionLabel.BLANK][0] - alternative_labelling = _in_trans(labelling, blank_argument, argumentation_framework) - admissible_sets = _recursively_get_admissible_labellings(argumentation_framework, alternative_labelling, - admissible_labellings) - alternative_labelling = _undec_trans(labelling, blank_argument) - admissible_sets = _recursively_get_admissible_labellings(argumentation_framework, alternative_labelling, - admissible_labellings) return admissible_labellings -def _recursively_get_eager_extension(argumentation_framework: AbstractArgumentationFramework, - labelling: Dict[Argument, EagerExtensionLabel], - labellings) -> Set[FrozenSet[Argument]]: - if all(labelling[argument] != EagerExtensionLabel.BLANK for argument in argumentation_framework.arguments): +def _recursively_get_eager_extension( + argumentation_framework: AbstractArgumentationFramework, + labelling: Dict[Argument, EagerExtensionLabel], + labellings) -> Set[FrozenSet[Argument]]: + if all(labelling[argument] != EagerExtensionLabel.BLANK + for argument in argumentation_framework.arguments): if all(labelling[argument] != EagerExtensionLabel.MUST_OUT for argument in argumentation_framework.arguments): - candidate_eager_undec = frozenset(sorted({argument for argument in argumentation_framework.arguments - if labelling[argument] == EagerExtensionLabel.UNDEC})) + candidate_eager_undec = frozenset(sorted({ + argument for argument in argumentation_framework.arguments + if labelling[argument] == EagerExtensionLabel.UNDEC})) calculated_eager_undec = [] for ss_labelling in labellings: calculated_eager_undec.append( - [frozenset(sorted({argument for argument in argumentation_framework.arguments - if ss_labelling[argument] == EagerExtensionLabel.UNDEC})), + [frozenset(sorted({ + argument + for argument in argumentation_framework.arguments + if ss_labelling[argument] == + EagerExtensionLabel.UNDEC})), ss_labelling]) if not any(candidate_eager_undec > eager_undec[0] for eager_undec in calculated_eager_undec): @@ -125,45 +126,47 @@ def _recursively_get_eager_extension(argumentation_framework: AbstractArgumentat if candidate_eager_undec < eager_undec[0]: labellings.remove(eager_undec[1]) else: - blank_argument = [argument for argument in argumentation_framework.arguments - if labelling[argument] == EagerExtensionLabel.BLANK][0] - alternative_labelling = _in_trans(labelling, blank_argument, argumentation_framework) - eager_extensions = _recursively_get_eager_extension(argumentation_framework, alternative_labelling, - labellings) + blank_argument = \ + [argument for argument in argumentation_framework.arguments + if labelling[argument] == EagerExtensionLabel.BLANK][0] + alternative_labelling = _in_trans(labelling, blank_argument, + argumentation_framework) + eager_extensions = _recursively_get_eager_extension( + argumentation_framework, alternative_labelling, labellings) alternative_labelling = _undec_trans(labelling, blank_argument) - eager_extensions = _recursively_get_eager_extension(argumentation_framework, alternative_labelling, - labellings) + eager_extensions = _recursively_get_eager_extension( + argumentation_framework, alternative_labelling, labellings) eager_extensions = set() for labelling in labellings: - eager_extensions.add(frozenset(sorted({argument for argument in argumentation_framework.arguments if - labelling[argument] == EagerExtensionLabel.IN}))) + eager_extensions.add(frozenset(sorted({ + argument for argument in argumentation_framework.arguments + if labelling[argument] == EagerExtensionLabel.IN}))) return eager_extensions -def _in_trans(labelling: Dict[Argument, EagerExtensionLabel], argument: Argument, - argumentation_framework: AbstractArgumentationFramework) -> Dict[Argument, EagerExtensionLabel]: +def _in_trans(labelling: Dict[Argument, EagerExtensionLabel], + argument: Argument, + argumentation_framework: AbstractArgumentationFramework) -> \ + Dict[Argument, EagerExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = EagerExtensionLabel.IN - for defeater in argumentation_framework.get_outgoing_defeat_arguments(argument): + for defeater in argumentation_framework.get_outgoing_defeat_arguments( + argument): if defeater == argument: break else: new_labelling[defeater] = EagerExtensionLabel.OUT - for defeated in argumentation_framework.get_incoming_defeat_arguments(argument): + for defeated in argumentation_framework.get_incoming_defeat_arguments( + argument): if new_labelling[defeated] != EagerExtensionLabel.OUT: new_labelling[defeated] = EagerExtensionLabel.MUST_OUT return new_labelling -def _undec_trans(labelling: Dict[Argument, EagerExtensionLabel], argument: Argument) -> \ +def _undec_trans(labelling: Dict[Argument, EagerExtensionLabel], + argument: Argument) -> \ Dict[Argument, EagerExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = EagerExtensionLabel.UNDEC return new_labelling - - -if __name__ == "__main__": - import doctest - - doctest.testmod() diff --git a/src/py_arg/abstract_argumentation/semantics/get_grounded_extension.py b/src/py_arg/abstract_argumentation/semantics/get_grounded_extension.py index 200f2d0..57da797 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_grounded_extension.py +++ b/src/py_arg/abstract_argumentation/semantics/get_grounded_extension.py @@ -1,36 +1,19 @@ from typing import Set -from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.semantics.get_acceptable_with_respect_to import get_acceptable_with_respect_to -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.semantics.get_acceptable_with_respect_to \ + import get_acceptable_with_respect_to +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.utils.fixpoint import get_least_fixed_point -def get_grounded_extension(argumentation_framework: AbstractArgumentationFramework) -> Set[Argument]: - """ - - :param argumentation_framework: - :return: - - >>> a = Argument('a') - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [a, b, c, d] - >>> defeats = [Defeat(b, a), Defeat(c, b), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> ge = get_grounded_extension(af) - >>> a in ge - False - >>> b in ge - True - >>> c in ge - False - >>> d in ge - True - """ - return get_least_fixed_point(lambda x: get_acceptable_with_respect_to(x, argumentation_framework), set()) +def get_grounded_extension( + argumentation_framework: AbstractArgumentationFramework) -> \ + Set[Argument]: + return get_least_fixed_point( + lambda x: get_acceptable_with_respect_to(x, argumentation_framework), + set()) if __name__ == "__main__": diff --git a/src/py_arg/abstract_argumentation/semantics/get_ideal_extension.py b/src/py_arg/abstract_argumentation/semantics/get_ideal_extension.py index 803c59b..2fcade2 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_ideal_extension.py +++ b/src/py_arg/abstract_argumentation/semantics/get_ideal_extension.py @@ -1,56 +1,50 @@ from enum import Enum from typing import Set, Dict, FrozenSet, List, Any -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. "Algorithms for decision problems in argument -# systems under preferred semantics." Artificial Intelligence 207 (2014): 23-51. +# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. "Algorithms +# for decision problems in argument systems +# under preferred semantics." Artificial Intelligence 207 (2014): 23-51. class IdealExtensionLabel(Enum): IN = 1 # Arguments *might* be in a preferred extension OUT = 2 # Argument is defeated by an IN argument - BLANK = 3 # Default label for all arguments, indicating that the argument is still unprocessed. + BLANK = 3 # Default label for all arguments, indicating that the argument + # is still unprocessed. MUST_OUT = 4 # Argument defeats IN argument - UNDEC = 5 # Argument may not be included in a preferred extension because not defended by any IN argument. + UNDEC = 5 # Argument may not be included in a preferred extension because + # not defended by any IN argument. -def get_ideal_extension(argumentation_framework: AbstractArgumentationFramework) -> List[Set[Any]]: +def get_ideal_extension( + argumentation_framework: AbstractArgumentationFramework) -> \ + List[Set[Any]]: """ Get the ideal extension of an argumentation framework. - :param argumentation_framework: The argumentation framework for which we need the ideal extension. + :param argumentation_framework: The argumentation framework for which we + need the ideal extension. :return: ideal extension of the argumentation framework. - - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [b, c, d] - >>> defeats = [Defeat(b, c), Defeat(c, d), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> idl = get_ideal_extension(af) - >>> len(idl) - 1 - >>> frozenset({b, d}) in idl - True - >>> frozenset({b}) in idl - False """ initial_labelling = {argument: IdealExtensionLabel.BLANK for argument in argumentation_framework.arguments} - frozen_admissible_sets = _recursively_get_admissible_sets(argumentation_framework, initial_labelling, set()) - admissible_sets = [set(frozen_admissible_set) for frozen_admissible_set in frozen_admissible_sets] + frozen_admissible_sets = _recursively_get_admissible_sets( + argumentation_framework, initial_labelling, set()) + admissible_sets = [set(frozen_admissible_set) + for frozen_admissible_set in frozen_admissible_sets] preferred_extensions = [] for candidate_preferred_extension in admissible_sets: if not any(candidate_preferred_extension < admissible_set for admissible_set in admissible_sets): preferred_extensions.append(candidate_preferred_extension) intersect_preferred = set.intersection(*preferred_extensions) - admissible_subsets = [admissible_set for admissible_set in admissible_sets if - intersect_preferred.issuperset(admissible_set) == True] + admissible_subsets = [admissible_set for admissible_set in admissible_sets + if intersect_preferred.issuperset(admissible_set)] max_admissible_subsets = [] for candidate_ideal_extension in admissible_subsets: if not any(candidate_ideal_extension < admissible_set @@ -59,44 +53,56 @@ def get_ideal_extension(argumentation_framework: AbstractArgumentationFramework) return max_admissible_subsets -def _recursively_get_admissible_sets(argumentation_framework: AbstractArgumentationFramework, - labelling: Dict[Argument, IdealExtensionLabel], - admissible_sets: Set[FrozenSet[Argument]]) -> Set[FrozenSet[Argument]]: - if all(labelling[argument] != IdealExtensionLabel.BLANK for argument in argumentation_framework.arguments): +def _recursively_get_admissible_sets( + argumentation_framework: AbstractArgumentationFramework, + labelling: Dict[Argument, IdealExtensionLabel], + admissible_sets: Set[FrozenSet[Argument]]) -> Set[FrozenSet[Argument]]: + if all(labelling[argument] != IdealExtensionLabel.BLANK + for argument in argumentation_framework.arguments): if all(labelling[argument] != IdealExtensionLabel.MUST_OUT for argument in argumentation_framework.arguments): - candidate_admissible_set = frozenset(sorted({argument for argument in argumentation_framework.arguments - if labelling[argument] == IdealExtensionLabel.IN})) + candidate_admissible_set = frozenset(sorted({ + argument for argument in argumentation_framework.arguments + if labelling[argument] == IdealExtensionLabel.IN})) admissible_sets.add(candidate_admissible_set) else: - blank_argument = [argument for argument in argumentation_framework.arguments - if labelling[argument] == IdealExtensionLabel.BLANK][0] - alternative_labelling = _in_trans(labelling, blank_argument, argumentation_framework) - admissible_sets = _recursively_get_admissible_sets(argumentation_framework, alternative_labelling, - admissible_sets) + blank_argument = \ + [argument for argument in argumentation_framework.arguments + if labelling[argument] == IdealExtensionLabel.BLANK][0] + alternative_labelling = _in_trans(labelling, blank_argument, + argumentation_framework) + admissible_sets = _recursively_get_admissible_sets( + argumentation_framework, alternative_labelling, + admissible_sets) alternative_labelling = _undec_trans(labelling, blank_argument) - admissible_sets = _recursively_get_admissible_sets(argumentation_framework, alternative_labelling, - admissible_sets) + admissible_sets = _recursively_get_admissible_sets( + argumentation_framework, alternative_labelling, + admissible_sets) return admissible_sets -def _in_trans(labelling: Dict[Argument, IdealExtensionLabel], argument: Argument, - argumentation_framework: AbstractArgumentationFramework) -> Dict[Argument, IdealExtensionLabel]: +def _in_trans(labelling: Dict[Argument, IdealExtensionLabel], + argument: Argument, + argumentation_framework: AbstractArgumentationFramework) -> \ + Dict[Argument, IdealExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = IdealExtensionLabel.IN - for defeater in argumentation_framework.get_outgoing_defeat_arguments(argument): + for defeater in argumentation_framework.get_outgoing_defeat_arguments( + argument): if defeater == argument: break else: new_labelling[defeater] = IdealExtensionLabel.OUT - for defeated in argumentation_framework.get_incoming_defeat_arguments(argument): + for defeated in argumentation_framework.get_incoming_defeat_arguments( + argument): if new_labelling[defeated] != IdealExtensionLabel.OUT: new_labelling[defeated] = IdealExtensionLabel.MUST_OUT return new_labelling -def _undec_trans(labelling: Dict[Argument, IdealExtensionLabel], argument: Argument) -> \ +def _undec_trans(labelling: Dict[Argument, IdealExtensionLabel], + argument: Argument) -> \ Dict[Argument, IdealExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = IdealExtensionLabel.UNDEC diff --git a/src/py_arg/abstract_argumentation/semantics/get_naive_extensions.py b/src/py_arg/abstract_argumentation/semantics/get_naive_extensions.py index dafab7a..36b13dd 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_naive_extensions.py +++ b/src/py_arg/abstract_argumentation/semantics/get_naive_extensions.py @@ -1,10 +1,13 @@ from typing import Set -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -import py_arg.abstract_argumentation.semantics.get_conflict_free_extensions as get_conflict_free_extensions +import py_arg.abstract_argumentation.semantics.get_conflict_free_extensions \ + as get_conflict_free_extensions -def apply(argumentation_framework: AbstractArgumentationFramework) -> Set[frozenset[Argument]]: +def apply(argumentation_framework: AbstractArgumentationFramework) -> \ + Set[frozenset[Argument]]: cf_ext = get_conflict_free_extensions.apply(argumentation_framework) rm = set() for ext1 in cf_ext: @@ -12,4 +15,3 @@ def apply(argumentation_framework: AbstractArgumentationFramework) -> Set[frozen if ext1.issubset(ext2) and not ext2.issubset(ext1): rm.add(ext1) return cf_ext.difference(rm) - diff --git a/src/py_arg/abstract_argumentation/semantics/get_preferred_extensions.py b/src/py_arg/abstract_argumentation/semantics/get_preferred_extensions.py index c66f2ce..3fddff6 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_preferred_extensions.py +++ b/src/py_arg/abstract_argumentation/semantics/get_preferred_extensions.py @@ -1,87 +1,95 @@ from enum import Enum from typing import Set, Dict, FrozenSet -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. "Algorithms for decision problems in argument -# systems under preferred semantics." Artificial Intelligence 207 (2014): 23-51. +# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. +# "Algorithms for decision problems in argument +# systems under preferred semantics." Artificial Intelligence 207 (2014): +# 23-51. class PreferredExtensionLabel(Enum): IN = 1 # Arguments *might* be in a preferred extension OUT = 2 # Argument is defeated by an IN argument - BLANK = 3 # Default label for all arguments, indicating that the argument is still unprocessed. + BLANK = 3 # Default label for all arguments, indicating + # that the argument is still unprocessed. MUST_OUT = 4 # Argument defeats IN argument - UNDEC = 5 # Argument may not be included in a preferred extension because not defended by any IN argument. + UNDEC = 5 # Argument may not be included in a preferred + # extension because not defended by any IN argument. -def get_preferred_extensions(argumentation_framework: AbstractArgumentationFramework) -> Set[FrozenSet[Argument]]: +def get_preferred_extensions( + argumentation_framework: AbstractArgumentationFramework) -> \ + Set[FrozenSet[Argument]]: """ Get the preferred extensions of an argumentation framework. - :param argumentation_framework: The argumentation framework for which we need the preferred extensions. + :param argumentation_framework: The argumentation framework for + which we need the preferred extensions. :return: Preferred extension of the argumentation framework. - - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [b, c, d] - >>> defeats = [Defeat(b, c), Defeat(c, d), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> pes = get_preferred_extensions(af) - >>> len(pes) - 1 - >>> frozenset({b, d}) in pes - True - >>> frozenset({b}) in pes - False """ initial_labelling = {argument: PreferredExtensionLabel.BLANK for argument in argumentation_framework.arguments} - return _recursively_get_preferred_extensions(argumentation_framework, initial_labelling, set()) + return _recursively_get_preferred_extensions(argumentation_framework, + initial_labelling, set()) -def _recursively_get_preferred_extensions(argumentation_framework: AbstractArgumentationFramework, - labelling: Dict[Argument, PreferredExtensionLabel], - preferred_extensions: Set[FrozenSet[Argument]]) -> Set[FrozenSet[Argument]]: - if all(labelling[argument] != PreferredExtensionLabel.BLANK for argument in argumentation_framework.arguments): +def _recursively_get_preferred_extensions( + argumentation_framework: AbstractArgumentationFramework, + labelling: Dict[Argument, PreferredExtensionLabel], + preferred_extensions: Set[FrozenSet[Argument]]) -> \ + Set[FrozenSet[Argument]]: + if all(labelling[argument] != PreferredExtensionLabel.BLANK + for argument in argumentation_framework.arguments): if all(labelling[argument] != PreferredExtensionLabel.MUST_OUT for argument in argumentation_framework.arguments): - candidate_preferred_extension = frozenset(sorted({argument for argument in argumentation_framework.arguments - if labelling[argument] == PreferredExtensionLabel.IN})) + candidate_preferred_extension = frozenset(sorted({ + argument for argument in argumentation_framework.arguments + if labelling[argument] == PreferredExtensionLabel.IN})) if not any(candidate_preferred_extension < preferred_extension for preferred_extension in preferred_extensions): preferred_extensions.add(candidate_preferred_extension) else: - blank_argument = [argument for argument in argumentation_framework.arguments - if labelling[argument] == PreferredExtensionLabel.BLANK][0] - alternative_labelling = _in_trans(labelling, blank_argument, argumentation_framework) - preferred_extensions = _recursively_get_preferred_extensions(argumentation_framework, alternative_labelling, - preferred_extensions) + blank_argument = \ + [argument for argument in argumentation_framework.arguments + if labelling[argument] == PreferredExtensionLabel.BLANK][0] + alternative_labelling = _in_trans(labelling, blank_argument, + argumentation_framework) + preferred_extensions = _recursively_get_preferred_extensions( + argumentation_framework, alternative_labelling, + preferred_extensions) alternative_labelling = _undec_trans(labelling, blank_argument) - preferred_extensions = _recursively_get_preferred_extensions(argumentation_framework, alternative_labelling, - preferred_extensions) + preferred_extensions = _recursively_get_preferred_extensions( + argumentation_framework, alternative_labelling, + preferred_extensions) return preferred_extensions -def _in_trans(labelling: Dict[Argument, PreferredExtensionLabel], argument: Argument, - argumentation_framework: AbstractArgumentationFramework) -> Dict[Argument, PreferredExtensionLabel]: +def _in_trans(labelling: Dict[Argument, PreferredExtensionLabel], + argument: Argument, + argumentation_framework: AbstractArgumentationFramework) -> \ + Dict[Argument, PreferredExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = PreferredExtensionLabel.IN - for defeater in argumentation_framework.get_outgoing_defeat_arguments(argument): - if defeater == argument: break + for defeater in argumentation_framework.get_outgoing_defeat_arguments( + argument): + if defeater == argument: + break else: new_labelling[defeater] = PreferredExtensionLabel.OUT - for defeated in argumentation_framework.get_incoming_defeat_arguments(argument): + for defeated in argumentation_framework.get_incoming_defeat_arguments( + argument): if new_labelling[defeated] != PreferredExtensionLabel.OUT: new_labelling[defeated] = PreferredExtensionLabel.MUST_OUT return new_labelling -def _undec_trans(labelling: Dict[Argument, PreferredExtensionLabel], argument: Argument) -> \ +def _undec_trans(labelling: Dict[Argument, PreferredExtensionLabel], + argument: Argument) -> \ Dict[Argument, PreferredExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = PreferredExtensionLabel.UNDEC diff --git a/src/py_arg/abstract_argumentation/semantics/get_semistable_extensions.py b/src/py_arg/abstract_argumentation/semantics/get_semistable_extensions.py index b30c516..942096f 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_semistable_extensions.py +++ b/src/py_arg/abstract_argumentation/semantics/get_semistable_extensions.py @@ -1,64 +1,65 @@ from enum import Enum from typing import Set, Dict, FrozenSet -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. "Algorithms for decision problems in argument -# systems under preferred semantics." Artificial Intelligence 207 (2014): 23-51. -# Adjustment based on Modgil, Sanjay and Martin Caminada. "Proof Theories and Algorithms for Abstract Argumentation -# Frameworks." In Iyad Rahwan and Guillermo R. Simari, editors, Argumentation in Artificial Intelligence, pages 105–132 +# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. +# "Algorithms for decision problems in argument systems +# under preferred semantics." Artificial Intelligence 207 (2014): 23-51. +# Adjustment based on Modgil, Sanjay and Martin Caminada. "Proof Theories and +# Algorithms for Abstract Argumentation +# Frameworks." In Iyad Rahwan and Guillermo R. Simari, editors, Argumentation +# in Artificial Intelligence, pages 105–132 class SemiStableExtensionLabel(Enum): IN = 1 # Arguments *might* be in a semi-stable extension OUT = 2 # Argument is defeated by an IN argument - BLANK = 3 # Default label for all arguments, indicating that the argument is still unprocessed. + BLANK = 3 # Default label for all arguments, indicating that the argument + # is still unprocessed. MUST_OUT = 4 # Argument defeats IN argument - UNDEC = 5 # Argument may not be included in a semi-stable extension because not defended by any IN argument. + UNDEC = 5 # Argument may not be included in a semi-stable extension + # because not defended by any IN argument. -def get_semistable_extensions(argumentation_framework: AbstractArgumentationFramework) -> Set[FrozenSet[Argument]]: +def get_semistable_extensions( + argumentation_framework: AbstractArgumentationFramework) -> \ + Set[FrozenSet[Argument]]: """ Get the semi-stable extensions of an argumentation framework. - :param argumentation_framework: The argumentation framework for which we need the semi-stable extensions. + :param argumentation_framework: The argumentation framework for which we + need the semi-stable extensions. :return: semi-stable extension of the argumentation framework. - - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [b, c, d] - >>> defeats = [Defeat(b, c), Defeat(c, d), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> sses = get_semistable_extensions(af) - >>> len(sses) - 1 - >>> frozenset({b, d}) in sses - True - >>> frozenset({b}) in sses - False """ initial_labelling = {argument: SemiStableExtensionLabel.BLANK for argument in argumentation_framework.arguments} - return _recursively_get_semistable_extensions(argumentation_framework, initial_labelling, []) + return _recursively_get_semistable_extensions(argumentation_framework, + initial_labelling, []) -def _recursively_get_semistable_extensions(argumentation_framework: AbstractArgumentationFramework, - labelling: Dict[Argument, SemiStableExtensionLabel], - labellings) -> Set[FrozenSet[Argument]]: - if all(labelling[argument] != SemiStableExtensionLabel.BLANK for argument in argumentation_framework.arguments): +def _recursively_get_semistable_extensions( + argumentation_framework: AbstractArgumentationFramework, + labelling: Dict[Argument, SemiStableExtensionLabel], + labellings) -> Set[FrozenSet[Argument]]: + if all(labelling[argument] != SemiStableExtensionLabel.BLANK + for argument in argumentation_framework.arguments): if all(labelling[argument] != SemiStableExtensionLabel.MUST_OUT for argument in argumentation_framework.arguments): - candidate_semistable_undec = frozenset(sorted({argument for argument in argumentation_framework.arguments - if labelling[argument] == SemiStableExtensionLabel.UNDEC})) + candidate_semistable_undec = frozenset(sorted({ + argument for argument in argumentation_framework.arguments + if labelling[argument] == SemiStableExtensionLabel.UNDEC})) calculated_semistable_undec = [] for ss_labelling in labellings: calculated_semistable_undec.append( - [frozenset(sorted({argument for argument in argumentation_framework.arguments - if ss_labelling[argument] == SemiStableExtensionLabel.UNDEC})), + [frozenset(sorted({ + argument + for argument in argumentation_framework.arguments + if ss_labelling[argument] == + SemiStableExtensionLabel.UNDEC})), ss_labelling]) if not any(candidate_semistable_undec > semistable_undec[0] for semistable_undec in calculated_semistable_undec): @@ -69,38 +70,46 @@ def _recursively_get_semistable_extensions(argumentation_framework: AbstractArgu if candidate_semistable_undec < semistable_undec[0]: labellings.remove(semistable_undec[1]) else: - blank_argument = [argument for argument in argumentation_framework.arguments - if labelling[argument] == SemiStableExtensionLabel.BLANK][0] - alternative_labelling = _in_trans(labelling, blank_argument, argumentation_framework) - semistable_extensions = _recursively_get_semistable_extensions(argumentation_framework, alternative_labelling, - labellings) + blank_argument = \ + [argument for argument in argumentation_framework.arguments + if labelling[argument] == SemiStableExtensionLabel.BLANK][0] + alternative_labelling = _in_trans(labelling, blank_argument, + argumentation_framework) + semistable_extensions = _recursively_get_semistable_extensions( + argumentation_framework, alternative_labelling, labellings) alternative_labelling = _undec_trans(labelling, blank_argument) - semistable_extensions = _recursively_get_semistable_extensions(argumentation_framework, alternative_labelling, - labellings) + semistable_extensions = _recursively_get_semistable_extensions( + argumentation_framework, alternative_labelling, labellings) semistable_extensions = set() for labelling in labellings: - semistable_extensions.add(frozenset(sorted({argument for argument in argumentation_framework.arguments if - labelling[argument] == SemiStableExtensionLabel.IN}))) + semistable_extensions.add(frozenset(sorted({ + argument for argument in argumentation_framework.arguments + if labelling[argument] == SemiStableExtensionLabel.IN}))) return semistable_extensions -def _in_trans(labelling: Dict[Argument, SemiStableExtensionLabel], argument: Argument, - argumentation_framework: AbstractArgumentationFramework) -> Dict[Argument, SemiStableExtensionLabel]: +def _in_trans(labelling: Dict[Argument, SemiStableExtensionLabel], + argument: Argument, + argumentation_framework: AbstractArgumentationFramework) -> \ + Dict[Argument, SemiStableExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = SemiStableExtensionLabel.IN - for defeater in argumentation_framework.get_outgoing_defeat_arguments(argument): + for defeater in argumentation_framework.get_outgoing_defeat_arguments( + argument): if defeater == argument: break else: new_labelling[defeater] = SemiStableExtensionLabel.OUT - for defeated in argumentation_framework.get_incoming_defeat_arguments(argument): + for defeated in argumentation_framework.get_incoming_defeat_arguments( + argument): if new_labelling[defeated] != SemiStableExtensionLabel.OUT: new_labelling[defeated] = SemiStableExtensionLabel.MUST_OUT return new_labelling -def _undec_trans(labelling: Dict[Argument, SemiStableExtensionLabel], argument: Argument) -> \ +def _undec_trans(labelling: Dict[Argument, SemiStableExtensionLabel], + argument: Argument) -> \ Dict[Argument, SemiStableExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = SemiStableExtensionLabel.UNDEC diff --git a/src/py_arg/abstract_argumentation/semantics/get_stable_extensions.py b/src/py_arg/abstract_argumentation/semantics/get_stable_extensions.py index 2395f44..cb54187 100644 --- a/src/py_arg/abstract_argumentation/semantics/get_stable_extensions.py +++ b/src/py_arg/abstract_argumentation/semantics/get_stable_extensions.py @@ -1,88 +1,94 @@ from enum import Enum from typing import Set, Dict, FrozenSet -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. "Algorithms for decision problems in argument -# systems under preferred semantics." Artificial Intelligence 207 (2014): 23-51. -# Adjustment based on Modgil, Sanjay and Martin Caminada. "Proof Theories and Algorithms for Abstract Argumentation -# Frameworks." In Iyad Rahwan and Guillermo R. Simari, editors, Argumentation in Artificial Intelligence, pages 105–132 +# Algorithm 1 from Nofal, Samer, Katie Atkinson, and Paul E. Dunne. "Algorithms +# for decision problems in argument systems +# under preferred semantics." Artificial Intelligence 207 (2014): 23-51. +# Adjustment based on Modgil, Sanjay and Martin Caminada. "Proof Theories and +# Algorithms for Abstract Argumentation +# Frameworks." In Iyad Rahwan and Guillermo R. Simari, editors, Argumentation +# in Artificial Intelligence, pages 105–132 class StableExtensionLabel(Enum): IN = 1 # Arguments *might* be in a stable extension OUT = 2 # Argument is defeated by an IN argument - BLANK = 3 # Default label for all arguments, indicating that the argument is still unprocessed. + BLANK = 3 # Default label for all arguments, indicating that the argument + # is still unprocessed. MUST_OUT = 4 # Argument defeats IN argument - UNDEC = 5 # Argument may not be included in a stable extension because not defended by any IN argument. + UNDEC = 5 # Argument may not be included in a stable extension because not + # defended by any IN argument. -def get_stable_extensions(argumentation_framework: AbstractArgumentationFramework) -> Set[FrozenSet[Argument]]: +def get_stable_extensions( + argumentation_framework: AbstractArgumentationFramework) -> \ + Set[FrozenSet[Argument]]: """ Get the stable extensions of an argumentation framework. - :param argumentation_framework: The argumentation framework for which we need the stable extensions. + :param argumentation_framework: The argumentation framework for which we + need the stable extensions. :return: stable extension of the argumentation framework. - - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [b, c, d] - >>> defeats = [Defeat(b, c), Defeat(c, d), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> ses = get_stable_extensions(af) - >>> len(ses) - 1 - >>> frozenset({b, d}) in ses - True - >>> frozenset({b}) in ses - False """ initial_labelling = {argument: StableExtensionLabel.BLANK for argument in argumentation_framework.arguments} - return _recursively_get_stable_extensions(argumentation_framework, initial_labelling, set()) - - -def _recursively_get_stable_extensions(argumentation_framework: AbstractArgumentationFramework, - labelling: Dict[Argument, StableExtensionLabel], - stable_extensions: Set[FrozenSet[Argument]]) -> Set[FrozenSet[Argument]]: - if all(labelling[argument] != StableExtensionLabel.BLANK for argument in argumentation_framework.arguments): - if all(labelling[argument] != StableExtensionLabel.MUST_OUT and labelling[ - argument] != StableExtensionLabel.UNDEC + return _recursively_get_stable_extensions(argumentation_framework, + initial_labelling, set()) + + +def _recursively_get_stable_extensions( + argumentation_framework: AbstractArgumentationFramework, + labelling: Dict[Argument, StableExtensionLabel], + stable_extensions: Set[FrozenSet[Argument]]) -> \ + Set[FrozenSet[Argument]]: + if all(labelling[argument] != StableExtensionLabel.BLANK + for argument in argumentation_framework.arguments): + if all(labelling[argument] != StableExtensionLabel.MUST_OUT and + labelling[argument] != StableExtensionLabel.UNDEC for argument in argumentation_framework.arguments): - stable_extensions.add(frozenset(sorted({argument for argument in argumentation_framework.arguments - if labelling[argument] == StableExtensionLabel.IN}))) + stable_extensions.add(frozenset(sorted({ + argument for argument in argumentation_framework.arguments + if labelling[argument] == StableExtensionLabel.IN}))) else: - blank_argument = [argument for argument in argumentation_framework.arguments - if labelling[argument] == StableExtensionLabel.BLANK][0] - alternative_labelling = _in_trans(labelling, blank_argument, argumentation_framework) - stable_extensions = _recursively_get_stable_extensions(argumentation_framework, alternative_labelling, - stable_extensions) + blank_argument = \ + [argument for argument in argumentation_framework.arguments + if labelling[argument] == StableExtensionLabel.BLANK][0] + alternative_labelling = _in_trans( + labelling, blank_argument, argumentation_framework) + stable_extensions = _recursively_get_stable_extensions( + argumentation_framework, alternative_labelling, stable_extensions) alternative_labelling = _undec_trans(labelling, blank_argument) - stable_extensions = _recursively_get_stable_extensions(argumentation_framework, alternative_labelling, - stable_extensions) + stable_extensions = _recursively_get_stable_extensions( + argumentation_framework, alternative_labelling, stable_extensions) return stable_extensions -def _in_trans(labelling: Dict[Argument, StableExtensionLabel], argument: Argument, - argumentation_framework: AbstractArgumentationFramework) -> Dict[Argument, StableExtensionLabel]: +def _in_trans(labelling: Dict[Argument, StableExtensionLabel], + argument: Argument, + argumentation_framework: AbstractArgumentationFramework) -> \ + Dict[Argument, StableExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = StableExtensionLabel.IN - for defeater in argumentation_framework.get_outgoing_defeat_arguments(argument): + for defeater in argumentation_framework.get_outgoing_defeat_arguments( + argument): if defeater == argument: break else: new_labelling[defeater] = StableExtensionLabel.OUT - for defeated in argumentation_framework.get_incoming_defeat_arguments(argument): + for defeated in argumentation_framework.get_incoming_defeat_arguments( + argument): if new_labelling[defeated] != StableExtensionLabel.OUT: new_labelling[defeated] = StableExtensionLabel.MUST_OUT return new_labelling -def _undec_trans(labelling: Dict[Argument, StableExtensionLabel], argument: Argument) -> \ +def _undec_trans(labelling: Dict[Argument, StableExtensionLabel], + argument: Argument) -> \ Dict[Argument, StableExtensionLabel]: new_labelling = labelling.copy() new_labelling[argument] = StableExtensionLabel.UNDEC diff --git a/src/py_arg/abstract_argumentation/semantics/is_acceptable_with_respect_to.py b/src/py_arg/abstract_argumentation/semantics/is_acceptable_with_respect_to.py index fba9df8..8d954d9 100644 --- a/src/py_arg/abstract_argumentation/semantics/is_acceptable_with_respect_to.py +++ b/src/py_arg/abstract_argumentation/semantics/is_acceptable_with_respect_to.py @@ -1,34 +1,27 @@ from typing import Iterable -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -def is_acceptable_with_respect_to(argument: Argument, argument_set: Iterable[Argument], - argumentation_framework: AbstractArgumentationFramework) -> bool: +def is_acceptable_with_respect_to( + argument: Argument, argument_set: Iterable[Argument], + argumentation_framework: AbstractArgumentationFramework) -> bool: """ - Verify that the argument is acceptable with respect to the argument set in the abstract argumentation framework. + Verify that the argument is acceptable with respect to the argument set in + the abstract argumentation framework. :param argument: Argument for which we want to know if it is acceptable. - :param argument_set: Argument set for which we want to know if the argument is acceptable w.r.t. this set. - :param argumentation_framework: Argumentation framework in which the arguments occur. + :param argument_set: Argument set for which we want to know if the argument + is acceptable w.r.t. this set. + :param argumentation_framework: Argumentation framework in which the + arguments occur. :return: Is the argument acceptable w.r.t. the argument set? - - >>> a = Argument('a') - >>> b = Argument('b') - >>> c = Argument('c') - >>> d = Argument('d') - >>> arguments = [a, b, c, d] - >>> defeats = [Defeat(b, a), Defeat(c, b), Defeat(d, c)] - >>> af = AbstractArgumentationFramework('af', arguments, defeats) - >>> is_acceptable_with_respect_to(a, [a], af) - False - >>> is_acceptable_with_respect_to(b, [b], af) - False - >>> is_acceptable_with_respect_to(b, [b, d], af) - True """ - return all(any([attacker_attacker in argument_set - for attacker_attacker in argumentation_framework.get_incoming_defeat_arguments(attacker)]) - for attacker in argumentation_framework.get_incoming_defeat_arguments(argument)) + return all(any([ + attacker_attacker in argument_set + for attacker_attacker in argumentation_framework. + get_incoming_defeat_arguments(attacker)]) + for attacker in argumentation_framework. + get_incoming_defeat_arguments(argument)) diff --git a/src/py_arg/abstract_argumentation/semantics/is_admissible.py b/src/py_arg/abstract_argumentation/semantics/is_admissible.py index abdf908..4e87a01 100644 --- a/src/py_arg/abstract_argumentation/semantics/is_admissible.py +++ b/src/py_arg/abstract_argumentation/semantics/is_admissible.py @@ -1,44 +1,36 @@ from typing import Iterable -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.semantics.is_acceptable_with_respect_to import is_acceptable_with_respect_to -from py_arg.abstract_argumentation.semantics.is_conflict_free import is_conflict_free +from py_arg.abstract_argumentation.semantics.is_acceptable_with_respect_to \ + import is_acceptable_with_respect_to +from py_arg.abstract_argumentation.semantics.is_conflict_free import \ + is_conflict_free -def is_admissible(argument_set: Iterable[Argument], argumentation_framework: AbstractArgumentationFramework) -> bool: +def is_admissible( + argument_set: Iterable[Argument], + argumentation_framework: AbstractArgumentationFramework) -> bool: """ - Check if the argument set if it is admissible in the corresponding argumentation framework. - :param argument_set: Set of arguments for which we want to know if it is admissible. - :param argumentation_framework: Argumentation framework specifying defeats between arguments. + Check if the argument set if it is admissible in the corresponding + argumentation framework. + :param argument_set: Set of arguments for which we want to know if it is + admissible. + :param argumentation_framework: Argumentation framework specifying defeats + between arguments. :return: Is this argument set admissible? - - >>> arguments = {s: Argument(s) for s in 'ABCD'} - >>> defeats = [Defeat(arguments[s[0]], arguments[s[1]]) for s in ['AB', 'BA', 'AC', 'BC', 'CD']] - >>> af = AbstractArgumentationFramework('Test', list(arguments.values()), defeats) - >>> is_admissible([arguments['C']], af) - False - >>> is_admissible([arguments['A']], af) - True - >>> is_admissible([arguments['B']], af) - True - >>> is_admissible([arguments['A'], arguments['B']], af) - False - >>> is_admissible([arguments['D']], af) - False - >>> is_admissible([arguments['A'], arguments['D']], af) - True - >>> is_admissible([arguments['B'], arguments['D']], af) - True """ - if any(argument not in argumentation_framework.arguments for argument in argument_set): - raise ValueError('Not all arguments in the argument set are in the argumentation framework.') + if any(argument not in argumentation_framework.arguments + for argument in argument_set): + raise ValueError('Not all arguments in the argument set are in the ' + 'argumentation framework.') if not is_conflict_free(argument_set, argumentation_framework): return False - if any(not is_acceptable_with_respect_to(argument, argument_set, argumentation_framework) + if any(not is_acceptable_with_respect_to(argument, argument_set, + argumentation_framework) for argument in argument_set): return False diff --git a/src/py_arg/abstract_argumentation/semantics/is_complete.py b/src/py_arg/abstract_argumentation/semantics/is_complete.py index 9305b30..e63332b 100644 --- a/src/py_arg/abstract_argumentation/semantics/is_complete.py +++ b/src/py_arg/abstract_argumentation/semantics/is_complete.py @@ -1,45 +1,36 @@ from typing import List -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.semantics.get_acceptable_with_respect_to import get_acceptable_with_respect_to +from py_arg.abstract_argumentation.semantics.get_acceptable_with_respect_to \ + import get_acceptable_with_respect_to from py_arg.abstract_argumentation.semantics.is_admissible import is_admissible -def is_complete(argument_set: List[Argument], argumentation_framework: AbstractArgumentationFramework) -> bool: +def is_complete( + argument_set: List[Argument], + argumentation_framework: AbstractArgumentationFramework) -> bool: """ - Check if the argument set if it is admissible in the corresponding argumentation framework. - :param argument_set: Set of arguments for which we want to know if it is admissible. - :param argumentation_framework: Argumentation framework specifying defeats between arguments. + Check if the argument set if it is admissible in the corresponding + argumentation framework. + :param argument_set: Set of arguments for which we want to know if it is + admissible. + :param argumentation_framework: Argumentation framework specifying defeats + between arguments. :return: Is this argument set admissible? - - >>> arguments = {s: Argument(s) for s in 'ABCD'} - >>> defeats = [Defeat(arguments[s[0]], arguments[s[1]]) for s in ['AB', 'BA', 'AC', 'BC', 'CD']] - >>> af = AbstractArgumentationFramework('Test', list(arguments.values()), defeats) - >>> is_complete([arguments['C']], af) - False - >>> is_complete([arguments['A']], af) - False - >>> is_complete([arguments['B']], af) - False - >>> is_complete([arguments['A'], arguments['B']], af) - False - >>> is_complete([arguments['D']], af) - False - >>> is_complete([arguments['A'], arguments['D']], af) - True - >>> is_complete([arguments['B'], arguments['D']], af) - True """ - if any(argument not in argumentation_framework.arguments for argument in argument_set): - raise ValueError('Not all arguments in the argument set are in the argumentation framework.') + if any(argument not in argumentation_framework.arguments + for argument in argument_set): + raise ValueError('Not all arguments in the argument set are in the ' + 'argumentation framework.') if not is_admissible(argument_set, argumentation_framework): return False if any(acceptable_argument not in argument_set - for acceptable_argument in get_acceptable_with_respect_to(argument_set, argumentation_framework)): + for acceptable_argument in get_acceptable_with_respect_to( + argument_set, argumentation_framework)): return False return True diff --git a/src/py_arg/abstract_argumentation/semantics/is_conflict_free.py b/src/py_arg/abstract_argumentation/semantics/is_conflict_free.py index 87bade5..bb377ce 100644 --- a/src/py_arg/abstract_argumentation/semantics/is_conflict_free.py +++ b/src/py_arg/abstract_argumentation/semantics/is_conflict_free.py @@ -1,30 +1,29 @@ import itertools from typing import Iterable -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -def is_conflict_free(argument_set: Iterable[Argument], argumentation_framework: AbstractArgumentationFramework) -> bool: +def is_conflict_free( + argument_set: Iterable[Argument], + argumentation_framework: AbstractArgumentationFramework) -> bool: """ - Check if the argument set if it is conflict free in the corresponding argumentation framework. - :param argument_set: Set of arguments for which we want to know if it is conflict-free. - :param argumentation_framework: Argumentation framework specifying defeats between arguments. + Check if the argument set if it is conflict free in the corresponding + argumentation framework. + :param argument_set: Set of arguments for which we want to know if it is + conflict-free. + :param argumentation_framework: Argumentation framework specifying defeats + between arguments. :return: Is this argument set conflict free? - - >>> arguments = {s: Argument(s) for s in 'ABC'} - >>> defeats = [Defeat(arguments[s[0]], arguments[s[1]]) for s in ['AB', 'CC']] - >>> af = AbstractArgumentationFramework('Test', list(arguments.values()), defeats) - >>> is_conflict_free([arguments['C']], af) - False - >>> is_conflict_free([arguments['A']], af) - True - >>> is_conflict_free([arguments['A'], arguments['B']], af) - False """ - if any(argument not in argumentation_framework.arguments for argument in argument_set): - raise ValueError('Not all arguments in the argument set are in the argumentation framework.') + if any(argument not in argumentation_framework.arguments + for argument in argument_set): + raise ValueError('Not all arguments in the argument set are in the ' + 'argumentation framework.') return not any(Defeat(arg_a, arg_b) in argumentation_framework.defeats - for arg_a, arg_b in itertools.product(argument_set, argument_set)) + for arg_a, arg_b in itertools.product(argument_set, + argument_set)) diff --git a/src/py_arg/abstract_argumentation/semantics/is_grounded_extension.py b/src/py_arg/abstract_argumentation/semantics/is_grounded_extension.py index a34c980..28f757d 100644 --- a/src/py_arg/abstract_argumentation/semantics/is_grounded_extension.py +++ b/src/py_arg/abstract_argumentation/semantics/is_grounded_extension.py @@ -1,33 +1,30 @@ from typing import List -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.semantics.get_grounded_extension import get_grounded_extension +from py_arg.abstract_argumentation.semantics.get_grounded_extension \ + import get_grounded_extension -def is_grounded_extension(argument_set: List[Argument], argumentation_framework: AbstractArgumentationFramework) -> bool: +def is_grounded_extension( + argument_set: List[Argument], + argumentation_framework: AbstractArgumentationFramework) -> bool: """ - Check if the argument set if it is the grounded extension in the corresponding argumentation framework. - :param argument_set: Set of arguments for which we want to know if it is the grounded extension. - :param argumentation_framework: Argumentation framework specifying defeats between arguments. - :return: Is this argument set the grounded exension? - - >>> arguments = {s: Argument(s) for s in 'ABCD'} - >>> defeats = [Defeat(arguments[s[0]], arguments[s[1]]) for s in ['AB', 'CC', 'BD']] - >>> af = AbstractArgumentationFramework('Test', list(arguments.values()), defeats) - >>> is_grounded_extension([arguments['A']], af) - False - >>> is_grounded_extension([arguments['D']], af) - False - >>> is_grounded_extension([arguments['A'], arguments['D']], af) - True - >>> is_grounded_extension([arguments['D'], arguments['A']], af) - True + Check if the argument set if it is the grounded extension in the + corresponding argumentation framework. + :param argument_set: Set of arguments for which we want to know if it is + the grounded extension. + :param argumentation_framework: Argumentation framework specifying defeats + between arguments. + :return: Is this argument set the grounded extension? """ - if any(argument not in argumentation_framework.arguments for argument in argument_set): - raise ValueError('Not all arguments in the argument set are in the argumentation framework.') + if any(argument not in argumentation_framework.arguments + for argument in argument_set): + raise ValueError('Not all arguments in the argument set are in the ' + 'argumentation framework.') - sorted_grounded_extension = sorted(get_grounded_extension(argumentation_framework)) + sorted_grounded_extension = sorted(get_grounded_extension( + argumentation_framework)) sorted_set = sorted(argument_set) return sorted_grounded_extension == sorted_set diff --git a/src/py_arg/abstract_argumentation/semantics/is_preferred_extension.py b/src/py_arg/abstract_argumentation/semantics/is_preferred_extension.py index 5144a86..bd4e46c 100644 --- a/src/py_arg/abstract_argumentation/semantics/is_preferred_extension.py +++ b/src/py_arg/abstract_argumentation/semantics/is_preferred_extension.py @@ -1,49 +1,41 @@ import itertools from typing import List -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.classes.defeat import Defeat from py_arg.abstract_argumentation.semantics.is_admissible import is_admissible -def is_preferred_extension(argument_set: List[Argument], argumentation_framework: AbstractArgumentationFramework) \ +def is_preferred_extension( + argument_set: List[Argument], + argumentation_framework: AbstractArgumentationFramework) \ -> bool: """ - Check if the argument set if it is a preferred extension in the corresponding argumentation framework. - :param argument_set: Set of arguments for which we want to know if it is a preferred extension. - :param argumentation_framework: Argumentation framework specifying defeats between arguments. - :return: Is this argument set a preferred exension? - - >>> arguments = {s: Argument(s) for s in 'ABCDEF'} - >>> defeats = [Defeat(arguments[s[0]], arguments[s[1]]) for s in ['AB', 'CC', 'BD', 'EF', 'FE']] - >>> af = AbstractArgumentationFramework('Test', list(arguments.values()), defeats) - >>> is_preferred_extension([arguments['A'], arguments['D']], af) - False - >>> is_preferred_extension([arguments['D'], arguments['A']], af) - False - >>> is_preferred_extension([arguments['E']], af) - False - >>> is_preferred_extension([arguments['A'], arguments['D'], arguments['E']], af) - True - >>> is_preferred_extension([arguments['D'], arguments['A'], arguments['E']], af) - True - >>> is_preferred_extension([arguments['A'], arguments['D'], arguments['F']], af) - True - >>> is_preferred_extension([arguments['D'], arguments['A'], arguments['F']], af) - True + Check if the argument set if it is a preferred extension in the + corresponding argumentation framework. + :param argument_set: Set of arguments for which we want to know if it is a + preferred extension. + :param argumentation_framework: Argumentation framework specifying defeats + between arguments. + :return: Is this argument set a preferred extension? """ - if any(argument not in argumentation_framework.arguments for argument in argument_set): - raise ValueError('Not all arguments in the argument set are in the argumentation framework.') + if any(argument not in argumentation_framework.arguments + for argument in argument_set): + raise ValueError('Not all arguments in the argument set are in the ' + 'argumentation framework.') if not is_admissible(argument_set, argumentation_framework): return False # Iterator for generating all sets of arguments - arguments_not_in_argument_set = [arg for arg in argumentation_framework.arguments if arg not in argument_set] - all_combinations_of_arguments_not_in_argument_set = itertools.chain.from_iterable( - itertools.combinations(arguments_not_in_argument_set, n) - for n in range(1, len(arguments_not_in_argument_set) + 1)) + arguments_not_in_argument_set = \ + [arg for arg in argumentation_framework.arguments + if arg not in argument_set] + all_combinations_of_arguments_not_in_argument_set = \ + itertools.chain.from_iterable( + itertools.combinations(arguments_not_in_argument_set, n) + for n in range(1, len(arguments_not_in_argument_set) + 1)) if any(is_admissible(argument_set + list(subset), argumentation_framework) for subset in all_combinations_of_arguments_not_in_argument_set): return False diff --git a/src/py_arg/aspic/algorithms/justification/compute_all_literal_grounded_justification_status_fast.py b/src/py_arg/aspic/algorithms/justification/compute_all_literal_grounded_justification_status_fast.py index a7cf60b..937eab0 100644 --- a/src/py_arg/aspic/algorithms/justification/compute_all_literal_grounded_justification_status_fast.py +++ b/src/py_arg/aspic/algorithms/justification/compute_all_literal_grounded_justification_status_fast.py @@ -1,21 +1,26 @@ from typing import Optional -from py_arg.aspic.algorithms.justification.connected_literal import connect_parents_and_children +from py_arg.aspic.algorithms.justification.connected_literal import \ + connect_parents_and_children +from py_arg.aspic.algorithms.justification.enum_justification_label import \ + EnumJustificationLabel +from py_arg.aspic.algorithms.justification.literal_labels import LiteralLabels from py_arg.aspic.classes.argumentation_theory import ArgumentationTheory from py_arg.aspic.classes.orderings.ordering import Ordering -from py_arg.aspic.algorithms.justification.enum_justification_label import EnumJustificationLabel -from py_arg.aspic.algorithms.justification.literal_labels import LiteralLabels -def compute_all_literal_grounded_justification_status_fast(argumentation_theory: ArgumentationTheory, - ordering: Optional[Ordering] = None) -> LiteralLabels: +def compute_all_literal_grounded_justification_status_fast( + argumentation_theory: ArgumentationTheory, + ordering: Optional[Ordering] = None) -> LiteralLabels: # Connect parents and children connect_parents_and_children(argumentation_theory) # Phase 1: UNSATISFIABLE / BLOCKED labelling result = {literal: EnumJustificationLabel.UNSATISFIABLE - for literal in argumentation_theory.argumentation_system.language.values()} - todo_literals = argumentation_theory.knowledge_base_axioms + argumentation_theory.knowledge_base_ordinary_premises + for literal in argumentation_theory.argumentation_system. + language.values()} + todo_literals = argumentation_theory.knowledge_base_axioms + \ + argumentation_theory.knowledge_base_ordinary_premises todo_rules = set() for literal in todo_literals: result[literal] = EnumJustificationLabel.BLOCKED @@ -25,23 +30,37 @@ def compute_all_literal_grounded_justification_status_fast(argumentation_theory: todo_rule = todo_rules.pop() literal = todo_rule.consequent if result[literal] == EnumJustificationLabel.UNSATISFIABLE: - if all(result[antecedent] == EnumJustificationLabel.BLOCKED for antecedent in todo_rule.antecedents): + if all(result[antecedent] == EnumJustificationLabel.BLOCKED + for antecedent in todo_rule.antecedents): result[literal] = EnumJustificationLabel.BLOCKED for rule in literal.parents: todo_rules.add(rule) # Phase 2: DEFENDED / OUT labelling # Start with all literals for which there is an undefeated argument - todo_literals = [literal for literal in argumentation_theory.argumentation_system.language.values() - if literal in argumentation_theory.knowledge_base_axioms or - (literal in argumentation_theory.knowledge_base_ordinary_premises and - all(contrary_literal not in argumentation_theory.knowledge_base_ordinary_premises - or ordering.ordinary_premise_is_strictly_weaker_than(contrary_literal, literal) - for contrary_literal in literal.contraries_and_contradictories)) or - (result[literal] != EnumJustificationLabel.UNSATISFIABLE and - all(result[contrary_literal] == EnumJustificationLabel.UNSATISFIABLE - for contrary_literal in literal.contraries_and_contradictories)) - ] + todo_literals = \ + [literal for literal in + argumentation_theory.argumentation_system.language.values() + if literal in argumentation_theory.knowledge_base_axioms or + ( + literal in argumentation_theory. + knowledge_base_ordinary_premises and + all( + contrary_literal not in argumentation_theory. + knowledge_base_ordinary_premises + or ordering. + ordinary_premise_is_strictly_weaker_than( + contrary_literal, literal) + for contrary_literal in + literal.contraries_and_contradictories)) or + (result[ + literal] != EnumJustificationLabel.UNSATISFIABLE and + all(result[ + contrary_literal] == + EnumJustificationLabel.UNSATISFIABLE + for contrary_literal in + literal.contraries_and_contradictories)) + ] todo_rules = set() for literal in todo_literals: result[literal] = EnumJustificationLabel.DEFENDED @@ -57,29 +76,43 @@ def compute_all_literal_grounded_justification_status_fast(argumentation_theory: old_conclusion_label = result[todo_rule.consequent] if old_conclusion_label == EnumJustificationLabel.BLOCKED: # Maybe this literal will change label - if all(result[antecedent] == EnumJustificationLabel.DEFENDED for antecedent in todo_rule.antecedents): - # There is an argument based on this rule such that all subarguments are in the grounded extension. + if all(result[antecedent] == EnumJustificationLabel.DEFENDED for + antecedent in todo_rule.antecedents): + # There is an argument based on this rule such that all + # subarguments are in the grounded extension. # Is the argument attacked on its conclusion? - if todo_rule in argumentation_theory.argumentation_system.strict_rules or \ - all(contrary_literal not in argumentation_theory.knowledge_base_axioms and - contrary_literal not in argumentation_theory.knowledge_base_ordinary_premises and - all(any(result[contrary_antecedent] in [EnumJustificationLabel.UNSATISFIABLE, - EnumJustificationLabel.OUT] - for contrary_antecedent in contrary_rule.antecedents) + if todo_rule in argumentation_theory.argumentation_system.\ + strict_rules or \ + all( + contrary_literal not in argumentation_theory. + knowledge_base_axioms and + contrary_literal not in argumentation_theory. + knowledge_base_ordinary_premises and + all(any(result[contrary_antecedent] in [ + EnumJustificationLabel.UNSATISFIABLE, + EnumJustificationLabel.OUT] + for contrary_antecedent in + contrary_rule.antecedents) for contrary_rule in contrary_literal.children) - for contrary_literal in todo_rule.consequent.contraries_and_contradictories): - result[todo_rule.consequent] = EnumJustificationLabel.DEFENDED + for contrary_literal in + todo_rule.consequent. + contraries_and_contradictories): + result[ + todo_rule.consequent] = EnumJustificationLabel.DEFENDED for parent_rule in todo_rule.consequent.parents: todo_rules.add(parent_rule) - for contrary_literal in todo_rule.consequent.contraries_and_contradictories: + for contrary_literal in todo_rule.consequent.\ + contraries_and_contradictories: result[contrary_literal] = EnumJustificationLabel.OUT for contrary_parent_rule in contrary_literal.parents: todo_rules.add(contrary_parent_rule) - elif any(result[antecedent] == EnumJustificationLabel.OUT for antecedent in todo_rule.antecedents): + elif any(result[antecedent] == EnumJustificationLabel.OUT for + antecedent in todo_rule.antecedents): result[todo_rule.consequent] = EnumJustificationLabel.OUT for parent_rule in todo_rule.consequent.parents: todo_rules.add(parent_rule) - for contrary_literal in todo_rule.consequent.contraries_and_contradictories: + for contrary_literal in \ + todo_rule.consequent.contraries_and_contradictories: for contrary_parent_rule in contrary_literal.parents: todo_rules.add(contrary_parent_rule) diff --git a/src/py_arg/aspic/algorithms/justification/compute_all_literal_grounded_justification_status_naive.py b/src/py_arg/aspic/algorithms/justification/compute_all_literal_grounded_justification_status_naive.py index 4135d10..01a67d4 100644 --- a/src/py_arg/aspic/algorithms/justification/compute_all_literal_grounded_justification_status_naive.py +++ b/src/py_arg/aspic/algorithms/justification/compute_all_literal_grounded_justification_status_naive.py @@ -2,21 +2,27 @@ from py_arg.aspic.classes.argumentation_theory import ArgumentationTheory from py_arg.aspic.classes.orderings.ordering import Ordering -from py_arg.aspic.algorithms.justification.enum_justification_label import EnumJustificationLabel +from py_arg.aspic.algorithms.justification.enum_justification_label import \ + EnumJustificationLabel from py_arg.aspic.algorithms.justification.literal_labels import LiteralLabels -from py_arg.abstract_argumentation.semantics.get_grounded_extension import get_grounded_extension +from py_arg.abstract_argumentation.semantics.get_grounded_extension import \ + get_grounded_extension -def compute_all_literal_grounded_justification_status_naive(argumentation_theory: ArgumentationTheory, - ordering: Optional[Ordering] = None) -> LiteralLabels: +def compute_all_literal_grounded_justification_status_naive( + argumentation_theory: ArgumentationTheory, + ordering: Optional[Ordering] = None) -> LiteralLabels: result = {literal: EnumJustificationLabel.UNSATISFIABLE - for literal in argumentation_theory.argumentation_system.language.values()} - arg_framework = argumentation_theory.create_abstract_argumentation_framework('af', ordering) + for literal in argumentation_theory.argumentation_system. + language.values()} + arg_framework = argumentation_theory.\ + create_abstract_argumentation_framework('af', ordering) for argument in arg_framework.arguments: result[argument.conclusion] = EnumJustificationLabel.BLOCKED grounded_extension = get_grounded_extension(arg_framework) for grounded_argument in grounded_extension: result[grounded_argument.conclusion] = EnumJustificationLabel.DEFENDED - for attacked_argument in grounded_argument.get_outgoing_defeat_arguments: + for attacked_argument in \ + grounded_argument.get_outgoing_defeat_arguments: result[attacked_argument.conclusion] = EnumJustificationLabel.OUT return LiteralLabels(result) diff --git a/src/py_arg/aspic/algorithms/justification/connected_literal.py b/src/py_arg/aspic/algorithms/justification/connected_literal.py index 98ae4ee..dc8755f 100644 --- a/src/py_arg/aspic/algorithms/justification/connected_literal.py +++ b/src/py_arg/aspic/algorithms/justification/connected_literal.py @@ -2,7 +2,8 @@ from py_arg.aspic.classes.argumentation_theory import ArgumentationTheory from py_arg.aspic.classes.literal import Literal -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory class ConnectedLiteral(Literal): @@ -21,7 +22,9 @@ def __hash__(self): return self.s1_hash -def connect_parents_and_children(argumentation_theory: Union[ArgumentationTheory, IncompleteArgumentationTheory]): +def connect_parents_and_children( + argumentation_theory: Union[ + ArgumentationTheory, IncompleteArgumentationTheory]): for literal in argumentation_theory.argumentation_system.language.values(): literal.__class__ = ConnectedLiteral literal.init_connected_literal() diff --git a/src/py_arg/aspic/algorithms/justification/literal_labels.py b/src/py_arg/aspic/algorithms/justification/literal_labels.py index 22baec6..abd46a9 100644 --- a/src/py_arg/aspic/algorithms/justification/literal_labels.py +++ b/src/py_arg/aspic/algorithms/justification/literal_labels.py @@ -1,11 +1,13 @@ from typing import Dict -from py_arg.aspic.algorithms.justification.enum_justification_label import EnumJustificationLabel +from py_arg.aspic.algorithms.justification.enum_justification_label import \ + EnumJustificationLabel from py_arg.aspic.classes.literal import Literal class LiteralLabels: - def __init__(self, literal_labeling: Dict[Literal, EnumJustificationLabel]): + def __init__(self, + literal_labeling: Dict[Literal, EnumJustificationLabel]): self.literal_labeling = literal_labeling def __getitem__(self, item): diff --git a/src/py_arg/aspic/classes/argumentation_system.py b/src/py_arg/aspic/classes/argumentation_system.py index 4be1da9..62f4ca9 100644 --- a/src/py_arg/aspic/classes/argumentation_system.py +++ b/src/py_arg/aspic/classes/argumentation_system.py @@ -1,7 +1,8 @@ from typing import Dict, List, Optional, Set from py_arg.aspic.classes.defeasible_rule import DefeasibleRule -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder from py_arg.aspic.classes.rule import Rule from py_arg.aspic.classes.strict_rule import StrictRule from py_arg.aspic.classes.literal import Literal @@ -13,32 +14,42 @@ def __init__(self, contraries_and_contradictories: Dict[str, Set[Literal]], strict_rules: List[StrictRule], defeasible_rules: List[DefeasibleRule], - defeasible_rule_preferences: Optional[PreferencePreorder] = None, + defeasible_rule_preferences: + Optional[PreferencePreorder] = None, add_defeasible_rule_literals: bool = True): # Language self.language = language # Contradiction function - for literal_str, literal_contraries in contraries_and_contradictories.items(): - self.language[literal_str].contraries_and_contradictories = literal_contraries + for literal_str, literal_contraries in \ + contraries_and_contradictories.items(): + self.language[literal_str].contraries_and_contradictories = \ + literal_contraries # Rules self.defeasible_rules = defeasible_rules self.strict_rules = strict_rules if add_defeasible_rule_literals: for defeasible_rule in defeasible_rules: - defeasible_rule_literal = Literal.from_defeasible_rule(defeasible_rule) - defeasible_rule_literal_negation = Literal.from_defeasible_rule_negation(defeasible_rule) - defeasible_rule_literal.contraries_and_contradictories = {defeasible_rule_literal_negation} - defeasible_rule_literal_negation.contraries_and_contradictories = {defeasible_rule_literal} - self.language[str(defeasible_rule_literal)] = defeasible_rule_literal - self.language[str(defeasible_rule_literal_negation)] = defeasible_rule_literal_negation + defeasible_rule_literal = \ + Literal.from_defeasible_rule(defeasible_rule) + defeasible_rule_literal_negation = \ + Literal.from_defeasible_rule_negation(defeasible_rule) + defeasible_rule_literal.contraries_and_contradictories = \ + {defeasible_rule_literal_negation} + defeasible_rule_literal_negation.\ + contraries_and_contradictories = {defeasible_rule_literal} + self.language[str(defeasible_rule_literal)] = \ + defeasible_rule_literal + self.language[str(defeasible_rule_literal_negation)] = \ + defeasible_rule_literal_negation # Rule preferences if defeasible_rule_preferences: self.rule_preferences = defeasible_rule_preferences else: - reflexive_order = [(rule_a, rule_a) for rule_a in self.defeasible_rules] + reflexive_order = [(rule_a, rule_a) + for rule_a in self.defeasible_rules] self.rule_preferences = PreferencePreorder(reflexive_order) @property @@ -50,8 +61,10 @@ def get_literal(self, defeasible_rule: DefeasibleRule) -> Literal: return self.language[defeasible_rule.id_str] def __eq__(self, other): - return isinstance(other, ArgumentationSystem) and self.language == other.language and \ - all(literal.contraries_and_contradictories == other.language[lit_str].contraries_and_contradictories + return isinstance(other, ArgumentationSystem) and \ + self.language == other.language and \ + all(literal.contraries_and_contradictories == + other.language[lit_str].contraries_and_contradictories for lit_str, literal in self.language.items()) and \ self.defeasible_rules == other.defeasible_rules and \ self.strict_rules == other.strict_rules and \ diff --git a/src/py_arg/aspic/classes/argumentation_theory.py b/src/py_arg/aspic/classes/argumentation_theory.py index a9c7b04..414b09e 100644 --- a/src/py_arg/aspic/classes/argumentation_theory.py +++ b/src/py_arg/aspic/classes/argumentation_theory.py @@ -1,38 +1,46 @@ import itertools from typing import List, Dict, Optional, Set, Tuple -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.defeat import Defeat from py_arg.aspic.classes.defeasible_rule import DefeasibleRule from py_arg.aspic.classes.literal import Literal -from py_arg.aspic.classes.orderings.argument_orderings.last_link_ordering import LastLinkElitistOrdering +from py_arg.aspic.classes.orderings.argument_orderings.last_link_ordering \ + import LastLinkElitistOrdering from py_arg.aspic.classes.orderings.ordering import Ordering from py_arg.aspic.classes.instantiated_argument import InstantiatedArgument from py_arg.aspic.classes.argumentation_system import ArgumentationSystem -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder -from py_arg.aspic.classes.structured_argumentation_framework import StructuredArgumentationFramework +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder +from py_arg.aspic.classes.structured_argumentation_framework import \ + StructuredArgumentationFramework class ArgumentationTheory: """ - An ArgumentationTheory consists of an ArgumentationSystem and a knowledge base. + An ArgumentationTheory consists of an ArgumentationSystem and a knowledge + base. Arguments can be inferred on the basis of an ArgumentationTheory. """ def __init__(self, argumentation_system: ArgumentationSystem, knowledge_base_axioms: List[Literal], knowledge_base_ordinary_premises: List[Literal], - ordinary_premise_preferences: Optional[PreferencePreorder] = None): + ordinary_premise_preferences: + Optional[PreferencePreorder] = None): self._argumentation_system = argumentation_system self._knowledge_base_axioms = knowledge_base_axioms - self._knowledge_base_ordinary_premises = knowledge_base_ordinary_premises + self._knowledge_base_ordinary_premises = \ + knowledge_base_ordinary_premises # Rule preferences if ordinary_premise_preferences: self.ordinary_premise_preferences = ordinary_premise_preferences else: self.ordinary_premise_preferences = \ - PreferencePreorder.create_reflexive_preorder(self._knowledge_base_ordinary_premises) + PreferencePreorder.create_reflexive_preorder( + self._knowledge_base_ordinary_premises) self._recompute_arguments() @@ -47,7 +55,8 @@ def argumentation_system(self, argumentation_system_input): @property def knowledge_base(self): - return self._knowledge_base_axioms + self._knowledge_base_ordinary_premises + return self._knowledge_base_axioms + \ + self._knowledge_base_ordinary_premises @property def knowledge_base_axioms(self): @@ -67,20 +76,26 @@ def knowledge_base_ordinary_premises(self): return self._knowledge_base_ordinary_premises @knowledge_base_ordinary_premises.setter - def knowledge_base_ordinary_premises(self, knowledge_base_ordinary_premises_input): - self._knowledge_base_ordinary_premises = knowledge_base_ordinary_premises_input + def knowledge_base_ordinary_premises( + self, knowledge_base_ordinary_premises_input): + self._knowledge_base_ordinary_premises = \ + knowledge_base_ordinary_premises_input self._recompute_arguments() - def add_to_knowledge_base_ordinary_premises(self, new_knowledge_base_ordinary_premise: Literal): - self._knowledge_base_ordinary_premises.append(new_knowledge_base_ordinary_premise) + def add_to_knowledge_base_ordinary_premises( + self, new_knowledge_base_ordinary_premise: Literal): + self._knowledge_base_ordinary_premises.append( + new_knowledge_base_ordinary_premise) self._recompute_arguments() @property def arguments(self) -> Dict[Literal, Set[InstantiatedArgument]]: """ - Get a dictionary of all arguments in this argumentation theory, indexed by their conclusion literal. + Get a dictionary of all arguments in this argumentation theory, + indexed by their conclusion literal. - :return: A dictionary of all arguments, indexed by their conclusion literal. + :return: A dictionary of all arguments, indexed by their conclusion + literal. """ return self._arguments @@ -88,42 +103,66 @@ def _recompute_arguments(self): """ Recompute the set of arguments inferred from this argumentation theory. - This step is necessary after every change in the argumentation system or knowledge base (note that this is done + This step is necessary after every change in the argumentation system + or knowledge base (note that this is done automatically by the corresponding setters). """ - arguments_per_conclusion = {literal: set() for literal in self._argumentation_system.language.values()} + arguments_per_conclusion = { + literal: set() + for literal in self._argumentation_system.language.values()} for knowledge_item in self._knowledge_base_axioms: - arguments_per_conclusion[knowledge_item].add(InstantiatedArgument.axiom_based(knowledge_item)) + arguments_per_conclusion[knowledge_item].add( + InstantiatedArgument.axiom_based(knowledge_item)) for knowledge_item in self._knowledge_base_ordinary_premises: - arguments_per_conclusion[knowledge_item].add(InstantiatedArgument.ordinary_premise_based(knowledge_item)) + arguments_per_conclusion[knowledge_item].add( + InstantiatedArgument.ordinary_premise_based(knowledge_item)) change = True while change: change = False for defeasible_rule in self._argumentation_system.defeasible_rules: - possible_antecedents = [[argument_for_antecedent - for argument_for_antecedent in arguments_per_conclusion[antecedent] - if defeasible_rule.consequent not in argument_for_antecedent.sub_conclusions] - for antecedent in defeasible_rule.antecedents] + possible_antecedents = \ + [[argument_for_antecedent + for argument_for_antecedent in + arguments_per_conclusion[antecedent] + if defeasible_rule.consequent not in + argument_for_antecedent.sub_conclusions] + for antecedent in defeasible_rule.antecedents] if all(possible_antecedents): - for direct_sub_argument_tuple in itertools.product(*possible_antecedents): + for direct_sub_argument_tuple in \ + itertools.product(*possible_antecedents): new_instantiated_argument = \ - InstantiatedArgument.defeasible_rule_based(defeasible_rule, set(direct_sub_argument_tuple)) - if new_instantiated_argument not in arguments_per_conclusion[defeasible_rule.consequent]: - arguments_per_conclusion[defeasible_rule.consequent].add(new_instantiated_argument) + InstantiatedArgument.defeasible_rule_based( + defeasible_rule, + set(direct_sub_argument_tuple)) + if new_instantiated_argument not in \ + arguments_per_conclusion[ + defeasible_rule.consequent]: + arguments_per_conclusion[ + defeasible_rule.consequent].add( + new_instantiated_argument) change = True for strict_rule in self._argumentation_system.strict_rules: - possible_antecedents = [[argument_for_antecedent - for argument_for_antecedent in arguments_per_conclusion[antecedent] - if strict_rule.consequent not in argument_for_antecedent.sub_conclusions] - for antecedent in strict_rule.antecedents] + possible_antecedents = \ + [[argument_for_antecedent + for argument_for_antecedent + in arguments_per_conclusion[antecedent] + if strict_rule.consequent not in + argument_for_antecedent.sub_conclusions] + for antecedent in strict_rule.antecedents] if all(possible_antecedents): - for direct_sub_argument_tuple in itertools.product(*possible_antecedents): + for direct_sub_argument_tuple in itertools.product( + *possible_antecedents): new_instantiated_argument = \ - InstantiatedArgument.strict_rule_based(strict_rule, set(direct_sub_argument_tuple)) - if new_instantiated_argument not in arguments_per_conclusion[strict_rule.consequent]: - arguments_per_conclusion[strict_rule.consequent].add(new_instantiated_argument) + InstantiatedArgument.strict_rule_based( + strict_rule, set(direct_sub_argument_tuple)) + if new_instantiated_argument not in \ + arguments_per_conclusion[ + strict_rule.consequent]: + arguments_per_conclusion[ + strict_rule.consequent].add( + new_instantiated_argument) change = True self._arguments = arguments_per_conclusion @@ -133,10 +172,12 @@ def all_arguments(self) -> List[InstantiatedArgument]: """ Get a list of all arguments inferred from this argumentation theory. """ - return [argument for arguments_for_literal in self.arguments.values() for argument in arguments_for_literal] + return [argument for arguments_for_literal in self.arguments.values() + for argument in arguments_for_literal] @property - def all_attacks(self) -> List[Tuple[InstantiatedArgument, InstantiatedArgument]]: + def all_attacks(self) -> \ + List[Tuple[InstantiatedArgument, InstantiatedArgument]]: """ Get a list of all attacks (note: not defeats!) """ @@ -146,21 +187,25 @@ def all_attacks(self) -> List[Tuple[InstantiatedArgument, InstantiatedArgument]] if self.attacks(argument_a, argument_b)] @staticmethod - def rebuts_on_conclusion(argument_a: InstantiatedArgument, argument_b: InstantiatedArgument) -> bool: + def rebuts_on_conclusion(argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument) -> bool: """ Check if argument_a rebuts argument_b on its conclusion. :param argument_a: The supposedly attacking argument. :param argument_b: The supposedly attacked argument. - :return: Boolean indicating whether argument_a rebuts argument_b on its conclusion. + :return: Boolean indicating whether argument_a rebuts argument_b on + its conclusion. """ if argument_b.is_observation_based: return False if not isinstance(argument_b.top_rule, DefeasibleRule): return False - return argument_a.conclusion.is_contrary_or_contradictory_of(argument_b.conclusion) + return argument_a.conclusion.is_contrary_or_contradictory_of( + argument_b.conclusion) - def rebuts(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument) -> bool: + def rebuts(self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument) -> bool: """ Check if argument_a rebuts argument_b. @@ -171,28 +216,35 @@ def rebuts(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgum return any([self.rebuts_on_conclusion(argument_a, sub_argument_b) for sub_argument_b in argument_b.sub_arguments]) - def rebuts_and_is_not_weaker(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument, + def rebuts_and_is_not_weaker(self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument, ordering: Ordering) -> bool: """ - Check if argument_a rebuts argument_b and is not weaker according to the given ordering. + Check if argument_a rebuts argument_b and is not weaker according to + the given ordering. :param argument_a: The supposedly attacking argument. :param argument_b: The supposedly attacked argument. :param ordering: The ordering used to identify argument strength. - :return: Boolean indicating whether argument_a rebuts argument_b and is stronger. + :return: Boolean indicating whether argument_a rebuts argument_b and + is stronger. """ return any([self.rebuts_on_conclusion(argument_a, sub_argument_b) and - not ordering.argument_is_strictly_weaker_than(argument_a, sub_argument_b) + not ordering.argument_is_strictly_weaker_than( + argument_a, sub_argument_b) for sub_argument_b in argument_b.sub_arguments]) @staticmethod - def contrary_rebuts_on_conclusion(argument_a: InstantiatedArgument, argument_b: InstantiatedArgument) -> bool: + def contrary_rebuts_on_conclusion( + argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument) -> bool: """ Check if argument_a contrary-rebuts argument_b on its conclusion. :param argument_a: The supposedly attacking argument. :param argument_b: The supposedly attacked argument. - :return: Boolean indicating whether argument_a contrary-rebuts argument_b on its conclusion. + :return: Boolean indicating whether argument_a contrary-rebuts + argument_b on its conclusion. """ if argument_b.is_observation_based: return False @@ -200,33 +252,42 @@ def contrary_rebuts_on_conclusion(argument_a: InstantiatedArgument, argument_b: return False return argument_a.conclusion.is_contrary_of(argument_b.conclusion) - def contrary_rebuts(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument) -> bool: + def contrary_rebuts(self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument) -> bool: """ Check if argument_a contrary-rebuts argument_b. :param argument_a: The supposedly attacking argument. :param argument_b: The supposedly attacked argument. - :return: Boolean indicating whether argument_a contrary-rebuts argument_b. + :return: Boolean indicating whether argument_a contrary-rebuts + argument_b. """ - return any([self.contrary_rebuts_on_conclusion(argument_a, sub_argument_b) + return any([self.contrary_rebuts_on_conclusion(argument_a, + sub_argument_b) for sub_argument_b in argument_b.sub_arguments]) - def undercuts_on_top_rule(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument) -> bool: + def undercuts_on_top_rule( + self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument) -> bool: """ Check if argument_a undercuts argument_b on its top rule. :param argument_a: The supposedly attacking argument. :param argument_b: The supposedly attacked argument. - :return: Boolean indicating whether argument_a undercuts argument_b on its top rule. + :return: Boolean indicating whether argument_a undercuts argument_b on + its top rule. """ if argument_b.is_observation_based: return False if not isinstance(argument_b.top_rule, DefeasibleRule): return False - argument_b_top_rule_literal = self._argumentation_system.get_literal(argument_b.top_rule) - return argument_a.conclusion.is_contrary_or_contradictory_of(argument_b_top_rule_literal) + argument_b_top_rule_literal = self._argumentation_system.get_literal( + argument_b.top_rule) + return argument_a.conclusion.is_contrary_or_contradictory_of( + argument_b_top_rule_literal) - def undercuts(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument) -> bool: + def undercuts(self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument) -> bool: """ Check if argument_a undercuts argument_b. @@ -238,7 +299,8 @@ def undercuts(self, argument_a: InstantiatedArgument, argument_b: InstantiatedAr for sub_argument_b in argument_b.sub_arguments]) @staticmethod - def undermines(argument_a: InstantiatedArgument, argument_b: InstantiatedArgument) -> bool: + def undermines(argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument) -> bool: """ Check if argument_a undermines argument_b. @@ -246,38 +308,50 @@ def undermines(argument_a: InstantiatedArgument, argument_b: InstantiatedArgumen :param argument_b: The supposedly attacked argument. :return: Boolean indicating whether argument_a undermines argument_b. """ - return any([argument_a.conclusion.is_contrary_or_contradictory_of(ordinary_premise_b) + return any([argument_a.conclusion.is_contrary_or_contradictory_of( + ordinary_premise_b) for ordinary_premise_b in argument_b.ordinary_premises]) @staticmethod - def undermines_and_is_not_weaker(argument_a: InstantiatedArgument, argument_b: InstantiatedArgument, + def undermines_and_is_not_weaker(argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument, ordering: Ordering) -> bool: """ - Check if argument_a undermines argument_b and is not weaker according to the specifies ordering. + Check if argument_a undermines argument_b and is not weaker according + to the specifies ordering. :param argument_a: The supposedly attacking argument. :param argument_b: The supposedly attacked argument. - :param ordering: The ordering used to decide if argument_a is weaker than argument_b. - :return: Boolean indicating whether argument_a undermines argument_b and is not weaker. - """ - return any([argument_a.conclusion.is_contrary_or_contradictory_of(sub_argument_b.conclusion) and - not ordering.argument_is_strictly_weaker_than(argument_a, sub_argument_b) + :param ordering: The ordering used to decide if argument_a is weaker + than argument_b. + :return: Boolean indicating whether argument_a undermines argument_b + and is not weaker. + """ + return any([argument_a.conclusion.is_contrary_or_contradictory_of( + sub_argument_b.conclusion) and + not ordering.argument_is_strictly_weaker_than( + argument_a, sub_argument_b) for sub_argument_b in argument_b.sub_arguments - if sub_argument_b.is_observation_based and sub_argument_b.is_plausible]) + if sub_argument_b.is_observation_based and + sub_argument_b.is_plausible]) @staticmethod - def contrary_undermines(argument_a: InstantiatedArgument, argument_b: InstantiatedArgument) -> bool: + def contrary_undermines( + argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument) -> bool: """ Check if argument_a contrary-undermines argument_b. :param argument_a: The supposedly attacking argument. :param argument_b: The supposedly attacked argument. - :return: Boolean indicating whether argument_a contrary-undermines argument_b. + :return: Boolean indicating whether argument_a + contrary-undermines argument_b. """ return any([argument_a.conclusion.is_contrary_of(ordinary_premise_b) for ordinary_premise_b in argument_b.ordinary_premises]) - def attacks(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument): + def attacks(self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument): """ Check if argument_a attacks argument_b. @@ -285,16 +359,19 @@ def attacks(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgu :param argument_b: The supposedly attacked argument. :return: Boolean indicating whether argument_a attacks argument_b. """ - return self.rebuts(argument_a, argument_b) or self.undercuts(argument_a, argument_b) or \ + return self.rebuts(argument_a, argument_b) or \ + self.undercuts(argument_a, argument_b) or \ self.undermines(argument_a, argument_b) - def defeats(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument, ordering: Ordering) -> bool: + def defeats(self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument, ordering: Ordering) -> bool: """ Check if argument_a defeats argument_b, given the specified ordering. :param argument_a: The supposedly attacking argument. :param argument_b: The supposedly attacked argument. - :param ordering: The ordering used to decide if argument_a is weaker than argument_b. + :param ordering: The ordering used to decide if argument_a is weaker + than argument_b. :return: Boolean indicating whether argument_a defeats argument_b. """ # Preference-independent attacks @@ -314,9 +391,11 @@ def defeats(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgu def recompute_all_defeats(self, ordering: Ordering) -> List[Defeat]: """ - Recompute all defeats between all arguments, given the specified ordering. + Recompute all defeats between all arguments, given the specified + ordering. - :param ordering: The ordering used to decide if the attacking argument is weaker than the attacking argument. + :param ordering: The ordering used to decide if the attacking argument + is weaker than the attacking argument. :return: List of all defeats. """ if ordering is None: @@ -330,41 +409,52 @@ def recompute_all_defeats(self, ordering: Ordering) -> List[Defeat]: for argument_b in self.all_arguments if self.defeats(argument_a, argument_b, ordering)] - def create_abstract_argumentation_framework(self, name: str, ordering: Optional[Ordering] = None): + def create_abstract_argumentation_framework( + self, name: str, ordering: Optional[Ordering] = None): """ - Create an abstract argumentation framework based on this argumentation theory. Note: if no ordering is given, + Create an abstract argumentation framework based on this argumentation + theory. Note: if no ordering is given, last link elitist ordering is chosen as default ordering. :param name: The name of the argumentation framework. - :param ordering: Ordering that influences which attacks are defeats. Note: default is last link elitist. - :return: Abstract argumentation framework based on this argumentation theory. + :param ordering: Ordering that influences which attacks are defeats. + Note: default is last link elitist. + :return: Abstract argumentation framework based on this argumentation + theory. """ if ordering is None: - ordering = LastLinkElitistOrdering(self.argumentation_system.rule_preferences, - self.ordinary_premise_preferences) - return AbstractArgumentationFramework(name, self.all_arguments, self.recompute_all_defeats(ordering)) + ordering = LastLinkElitistOrdering( + self.argumentation_system.rule_preferences, + self.ordinary_premise_preferences) + return AbstractArgumentationFramework( + name, self.all_arguments, self.recompute_all_defeats(ordering)) - def create_structured_argumentation_framework(self, name: str, ordering: Optional[Ordering] = None): + def create_structured_argumentation_framework( + self, name: str, ordering: Optional[Ordering] = None): """ - Create a structured argumentation framework based on this argumentation theory. Note: if no ordering is given, + Create a structured argumentation framework based on this + argumentation theory. Note: if no ordering is given, last link elitist ordering is chosen as default ordering. :param name: The name of the argumentation framework. - :param ordering: Ordering that influences the argument preferences. Note: default is last link elitist. - :return: Structured argumentation framework based on this argumentation theory. + :param ordering: Ordering that influences the argument preferences. + Note: default is last link elitist. + :return: Structured argumentation framework based on this argumentation + theory. """ if ordering is None: - ordering = LastLinkElitistOrdering(self.argumentation_system.rule_preferences, - self.ordinary_premise_preferences) - return StructuredArgumentationFramework(name, self.all_arguments, self.all_attacks, - [(arg_a, arg_b) - for arg_a in self.all_arguments for arg_b in self.all_arguments - if ordering.argument_is_weaker_or_equal_than(arg_a, arg_b)]) + ordering = LastLinkElitistOrdering( + self.argumentation_system.rule_preferences, + self.ordinary_premise_preferences) + return StructuredArgumentationFramework( + name, self.all_arguments, self.all_attacks, + [(arg_a, arg_b) + for arg_a in self.all_arguments for arg_b in self.all_arguments + if ordering.argument_is_weaker_or_equal_than(arg_a, arg_b)]) if __name__ == "__main__": import doctest - doctest.testmod() diff --git a/src/py_arg/aspic/classes/defeasible_rule.py b/src/py_arg/aspic/classes/defeasible_rule.py index 423206a..873a463 100644 --- a/src/py_arg/aspic/classes/defeasible_rule.py +++ b/src/py_arg/aspic/classes/defeasible_rule.py @@ -5,11 +5,14 @@ class DefeasibleRule(Rule): - def __init__(self, rule_id: str, antecedents: Set[Literal], consequent: Literal): + def __init__(self, rule_id: str, antecedents: Set[Literal], + consequent: Literal): super().__init__(rule_id, antecedents, consequent) def __repr__(self): - return ','.join([str(antecedent) for antecedent in self.antecedents]) + '=>' + str(self.consequent) + return ','.join([str(antecedent) + for antecedent in self.antecedents]) + '=>' + \ + str(self.consequent) @property def id_str(self) -> str: diff --git a/src/py_arg/aspic/classes/instantiated_argument.py b/src/py_arg/aspic/classes/instantiated_argument.py index 0b13d21..639a97b 100644 --- a/src/py_arg/aspic/classes/instantiated_argument.py +++ b/src/py_arg/aspic/classes/instantiated_argument.py @@ -26,49 +26,81 @@ def __init__(self, name: str, self.defeasible_rules = defeasible_rules self.strict_rules = strict_rules self.top_rule = top_rule - self.sub_conclusions = {sub_conclusion for dir_sub in self.direct_sub_arguments - for sub_conclusion in dir_sub.sub_conclusions} + self.sub_conclusions = { + sub_conclusion for dir_sub in self.direct_sub_arguments + for sub_conclusion in dir_sub.sub_conclusions} self.sub_conclusions.add(self.conclusion) - self.short_name = self.name.replace(' (axiom)', '').replace(' (ordinary premise)', '') + self.short_name = self.name.replace(' (axiom)', '').replace( + ' (ordinary premise)', '') @classmethod def axiom_based(cls, conclusion: Literal): - return cls(str(conclusion) + ' (axiom)', {conclusion}, set(), conclusion, set(), set(), set(), None) + return cls(str(conclusion) + ' (axiom)', {conclusion}, set(), + conclusion, set(), set(), set(), None) @classmethod def ordinary_premise_based(cls, conclusion: Literal): - return cls(str(conclusion) + ' (ordinary premise)', set(), {conclusion}, conclusion, set(), set(), set(), None) + return cls(str(conclusion) + ' (ordinary premise)', set(), + {conclusion}, conclusion, set(), set(), set(), None) @classmethod - def strict_rule_based(cls, strict_rule: StrictRule, direct_sub_arguments: Set['InstantiatedArgument']): - direct_sub_argument_conclusions = sorted([sub_argument.conclusion for sub_argument in direct_sub_arguments]) + def strict_rule_based(cls, strict_rule: StrictRule, + direct_sub_arguments: Set['InstantiatedArgument']): + direct_sub_argument_conclusions = sorted([ + sub_argument.conclusion + for sub_argument in direct_sub_arguments]) if direct_sub_argument_conclusions != sorted(strict_rule.antecedents): - raise ValueError('Strict rule does not match with direct subarguments.') + raise ValueError( + 'Strict rule does not match with direct subarguments.') - name = '[' + ','.join(sorted(sub.name for sub in direct_sub_arguments)) \ + name = '[' + ','.join(sorted(sub.name + for sub in direct_sub_arguments)) \ + '->' + str(strict_rule.consequent) + ']' - axiom_premises = set().union(*[sub_argument.axiom_premises for sub_argument in direct_sub_arguments]) - ordinary_premises = set().union(*[sub_argument.ordinary_premises for sub_argument in direct_sub_arguments]) + axiom_premises = set().union(*[ + sub_argument.axiom_premises + for sub_argument in direct_sub_arguments]) + ordinary_premises = set().union(*[ + sub_argument.ordinary_premises + for sub_argument in direct_sub_arguments]) conclusion = strict_rule.consequent - def_rules = set().union(*[sub_argument.defeasible_rules for sub_argument in direct_sub_arguments]) - strict_rules = {strict_rule}.union(*[sub_argument.strict_rules for sub_argument in direct_sub_arguments]) - return cls(name, axiom_premises, ordinary_premises, conclusion, direct_sub_arguments, def_rules, + def_rules = set().union(*[ + sub_argument.defeasible_rules + for sub_argument in direct_sub_arguments]) + strict_rules = {strict_rule}.union(*[ + sub_argument.strict_rules + for sub_argument in direct_sub_arguments]) + return cls(name, axiom_premises, ordinary_premises, conclusion, + direct_sub_arguments, def_rules, strict_rules, strict_rule) @classmethod - def defeasible_rule_based(cls, defeasible_rule: DefeasibleRule, direct_sub_arguments: Set['InstantiatedArgument']): - direct_sub_argument_conclusions = sorted([sub_argument.conclusion for sub_argument in direct_sub_arguments]) - if direct_sub_argument_conclusions != sorted(defeasible_rule.antecedents): + def defeasible_rule_based( + cls, defeasible_rule: DefeasibleRule, + direct_sub_arguments: Set['InstantiatedArgument']): + direct_sub_argument_conclusions = sorted([ + sub_argument.conclusion for sub_argument in direct_sub_arguments]) + if direct_sub_argument_conclusions != sorted( + defeasible_rule.antecedents): raise ValueError('Strict rule does not match direct subarguments.') - name = '[' + ','.join([sub.name for sub in direct_sub_arguments]) + '=>' + \ + name = '[' + ','.join([sub.name + for sub in direct_sub_arguments]) + '=>' + \ str(defeasible_rule.consequent) + ']' - axiom_premises = set().union(*[sub_argument.axiom_premises for sub_argument in direct_sub_arguments]) - ordinary_premises = set().union(*[sub_argument.ordinary_premises for sub_argument in direct_sub_arguments]) + axiom_premises = set().union(*[ + sub_argument.axiom_premises + for sub_argument in direct_sub_arguments]) + ordinary_premises = set().union(*[ + sub_argument.ordinary_premises + for sub_argument in direct_sub_arguments]) conclusion = defeasible_rule.consequent - def_rules = {defeasible_rule}.union(*[sub_argument.defeasible_rules for sub_argument in direct_sub_arguments]) - strict_rules = set().union(*[sub_argument.strict_rules for sub_argument in direct_sub_arguments]) - return cls(name, axiom_premises, ordinary_premises, conclusion, direct_sub_arguments, def_rules, + def_rules = {defeasible_rule}.union(*[ + sub_argument.defeasible_rules + for sub_argument in direct_sub_arguments]) + strict_rules = set().union(*[ + sub_argument.strict_rules + for sub_argument in direct_sub_arguments]) + return cls(name, axiom_premises, ordinary_premises, conclusion, + direct_sub_arguments, def_rules, strict_rules, defeasible_rule) @property @@ -85,7 +117,8 @@ def is_rule_based(self): @property def sub_arguments(self) -> Set['InstantiatedArgument']: - return {self}.union(*[sub_argument.sub_arguments for sub_argument in self.direct_sub_arguments]) + return {self}.union(*[sub_argument.sub_arguments + for sub_argument in self.direct_sub_arguments]) @property def last_defeasible_rules(self) -> Set[DefeasibleRule]: @@ -93,7 +126,8 @@ def last_defeasible_rules(self) -> Set[DefeasibleRule]: return set() if self.is_rule_based and isinstance(self.top_rule, DefeasibleRule): return {self.top_rule} - return set().union(*[dir_sub.last_defeasible_rules for dir_sub in self.direct_sub_arguments]) + return set().union(*[dir_sub.last_defeasible_rules + for dir_sub in self.direct_sub_arguments]) @property def is_strict(self) -> bool: diff --git a/src/py_arg/aspic/classes/literal.py b/src/py_arg/aspic/classes/literal.py index 8c07e1b..f4df613 100644 --- a/src/py_arg/aspic/classes/literal.py +++ b/src/py_arg/aspic/classes/literal.py @@ -39,19 +39,23 @@ def is_positive(self): def is_contrary_or_contradictory_of(self, other) -> bool: """ - Boolean indicating if this Literal is a contrary or contradictory of some other Literal. + Boolean indicating if this Literal is a contrary or contradictory + of some other Literal. - :param other: Some other Literal that might be contrary or contradictory. + :param other: Some other Literal that might be contrary or + contradictory. """ return self in other.contraries_and_contradictories def is_contradictory_of(self, other) -> bool: """ - Boolean indicating if this Literal is a contradictory of some other Literal. + Boolean indicating if this Literal is a contradictory of some other + Literal. :param other: Some other Literal that might be contradictory. """ - return self.is_contrary_or_contradictory_of(other) and other.is_contrary_or_contradictory_of(self) + return self.is_contrary_or_contradictory_of(other) and \ + other.is_contrary_or_contradictory_of(self) def is_contrary_of(self, other) -> bool: """ @@ -59,7 +63,8 @@ def is_contrary_of(self, other) -> bool: :param other: Some other Literal that might be contrary. """ - return self.is_contrary_or_contradictory_of(other) and not other.is_contrary_or_contradictory_of(self) + return self.is_contrary_or_contradictory_of(other) and \ + not other.is_contrary_or_contradictory_of(self) def __hash__(self): return self.s1_hash diff --git a/src/py_arg/aspic/classes/orderings/argument_orderings/last_link_ordering.py b/src/py_arg/aspic/classes/orderings/argument_orderings/last_link_ordering.py index 3bece48..d997da9 100644 --- a/src/py_arg/aspic/classes/orderings/argument_orderings/last_link_ordering.py +++ b/src/py_arg/aspic/classes/orderings/argument_orderings/last_link_ordering.py @@ -1,6 +1,9 @@ -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder -from py_arg.aspic.classes.orderings.set_orderings.democratic_ordering import DemocraticOrdering -from py_arg.aspic.classes.orderings.set_orderings.elitist_ordering import ElitistOrdering +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder +from py_arg.aspic.classes.orderings.set_orderings.democratic_ordering import \ + DemocraticOrdering +from py_arg.aspic.classes.orderings.set_orderings.elitist_ordering import \ + ElitistOrdering from py_arg.aspic.classes.orderings.ordering import Ordering from py_arg.aspic.classes.instantiated_argument import InstantiatedArgument @@ -8,26 +11,33 @@ class LastLinkOrdering(Ordering): def __init__(self, defeasible_rule_preferences: PreferencePreorder, ordinary_premise_preferences: PreferencePreorder): - super().__init__(defeasible_rule_preferences, ordinary_premise_preferences) + super().__init__(defeasible_rule_preferences, + ordinary_premise_preferences) - def argument_is_strictly_weaker_than(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument): + def argument_is_strictly_weaker_than(self, + argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument): ldr_a = argument_a.last_defeasible_rules ldr_b = argument_b.last_defeasible_rules if self.rule_set_is_strictly_weaker_than(ldr_a, ldr_b): return True - if len(ldr_a) == 0 and len(ldr_b) == 0 and self.ordinary_premise_set_is_strictly_weaker_than( + if len(ldr_a) == 0 and len(ldr_b) == 0 and \ + self.ordinary_premise_set_is_strictly_weaker_than( argument_a.ordinary_premises, argument_b.ordinary_premises): return True return False - def argument_is_weaker_or_equal_than(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument): + def argument_is_weaker_or_equal_than( + self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument): if self.argument_is_strictly_weaker_than(argument_a, argument_b): return True if len(argument_b.last_defeasible_rules) == 0: if argument_a.ordinary_premises == argument_b.ordinary_premises: return True else: - if argument_a.last_defeasible_rules == argument_b.last_defeasible_rules: + if argument_a.last_defeasible_rules == \ + argument_b.last_defeasible_rules: return True return False @@ -35,10 +45,12 @@ def argument_is_weaker_or_equal_than(self, argument_a: InstantiatedArgument, arg class LastLinkDemocraticOrdering(DemocraticOrdering, LastLinkOrdering): def __init__(self, defeasible_rule_preferences: PreferencePreorder, ordinary_premise_preferences: PreferencePreorder): - super().__init__(defeasible_rule_preferences, ordinary_premise_preferences) + super().__init__(defeasible_rule_preferences, + ordinary_premise_preferences) class LastLinkElitistOrdering(ElitistOrdering, LastLinkOrdering): def __init__(self, defeasible_rule_preferences: PreferencePreorder, ordinary_premise_preferences: PreferencePreorder): - super().__init__(defeasible_rule_preferences, ordinary_premise_preferences) + super().__init__(defeasible_rule_preferences, + ordinary_premise_preferences) diff --git a/src/py_arg/aspic/classes/orderings/argument_orderings/weakest_link_ordering.py b/src/py_arg/aspic/classes/orderings/argument_orderings/weakest_link_ordering.py index b363756..2607a4f 100644 --- a/src/py_arg/aspic/classes/orderings/argument_orderings/weakest_link_ordering.py +++ b/src/py_arg/aspic/classes/orderings/argument_orderings/weakest_link_ordering.py @@ -1,6 +1,9 @@ -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder -from py_arg.aspic.classes.orderings.set_orderings.democratic_ordering import DemocraticOrdering -from py_arg.aspic.classes.orderings.set_orderings.elitist_ordering import ElitistOrdering +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder +from py_arg.aspic.classes.orderings.set_orderings.democratic_ordering import \ + DemocraticOrdering +from py_arg.aspic.classes.orderings.set_orderings.elitist_ordering import \ + ElitistOrdering from py_arg.aspic.classes.orderings.ordering import Ordering from py_arg.aspic.classes.instantiated_argument import InstantiatedArgument @@ -8,20 +11,27 @@ class WeakestLinkOrdering(Ordering): def __init__(self, defeasible_rule_preferences: PreferencePreorder, ordinary_premise_preferences: PreferencePreorder): - super().__init__(defeasible_rule_preferences, ordinary_premise_preferences) + super().__init__(defeasible_rule_preferences, + ordinary_premise_preferences) - def argument_is_strictly_weaker_than(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument): + def argument_is_strictly_weaker_than( + self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument): if argument_a.is_strict and argument_b.is_strict: - return self.ordinary_premise_set_is_strictly_weaker_than(argument_a.ordinary_premises, - argument_b.ordinary_premises) + return self.ordinary_premise_set_is_strictly_weaker_than( + argument_a.ordinary_premises, argument_b.ordinary_premises) elif argument_a.is_firm and argument_b.is_firm: - return self.rule_set_is_strictly_weaker_than(argument_a.defeasible_rules, argument_b.defeasible_rules) + return self.rule_set_is_strictly_weaker_than( + argument_a.defeasible_rules, argument_b.defeasible_rules) else: return self.ordinary_premise_set_is_strictly_weaker_than( - argument_a.ordinary_premises, argument_b.ordinary_premises) and \ - self.rule_set_is_strictly_weaker_than(argument_a.defeasible_rules, argument_b.defeasible_rules) + argument_a.ordinary_premises, argument_b.ordinary_premises) \ + and self.rule_set_is_strictly_weaker_than( + argument_a.defeasible_rules, argument_b.defeasible_rules) - def argument_is_weaker_or_equal_than(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument): + def argument_is_weaker_or_equal_than( + self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument): if self.argument_is_strictly_weaker_than(argument_a, argument_b): return True if argument_a.defeasible_rules == argument_b.defeasible_rules and \ @@ -33,10 +43,12 @@ def argument_is_weaker_or_equal_than(self, argument_a: InstantiatedArgument, arg class WeakestLinkDemocraticOrdering(DemocraticOrdering, WeakestLinkOrdering): def __init__(self, defeasible_rule_preferences: PreferencePreorder, ordinary_premise_preferences: PreferencePreorder): - super().__init__(defeasible_rule_preferences, ordinary_premise_preferences) + super().__init__(defeasible_rule_preferences, + ordinary_premise_preferences) class WeakestLinkElitistOrdering(ElitistOrdering, WeakestLinkOrdering): def __init__(self, defeasible_rule_preferences: PreferencePreorder, ordinary_premise_preferences: PreferencePreorder): - super().__init__(defeasible_rule_preferences, ordinary_premise_preferences) + super().__init__(defeasible_rule_preferences, + ordinary_premise_preferences) diff --git a/src/py_arg/aspic/classes/orderings/ordering.py b/src/py_arg/aspic/classes/orderings/ordering.py index 0d474c6..ba1592c 100644 --- a/src/py_arg/aspic/classes/orderings/ordering.py +++ b/src/py_arg/aspic/classes/orderings/ordering.py @@ -3,7 +3,8 @@ from py_arg.aspic.classes.defeasible_rule import DefeasibleRule from py_arg.aspic.classes.literal import Literal from py_arg.aspic.classes.instantiated_argument import InstantiatedArgument -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder class Ordering: @@ -12,34 +13,51 @@ def __init__(self, defeasible_rule_preferences: PreferencePreorder, self.defeasible_rule_preferences = defeasible_rule_preferences self.ordinary_premise_preferences = ordinary_premise_preferences - def rule_is_strictly_weaker_than(self, rule_a: DefeasibleRule, rule_b: DefeasibleRule) -> bool: - return self.defeasible_rule_preferences.is_strictly_weaker_than(rule_a, rule_b) + def rule_is_strictly_weaker_than(self, rule_a: DefeasibleRule, + rule_b: DefeasibleRule) -> bool: + return self.defeasible_rule_preferences.is_strictly_weaker_than( + rule_a, rule_b) - def rule_is_weaker_or_equal_than(self, rule_a: DefeasibleRule, rule_b: DefeasibleRule) -> bool: + def rule_is_weaker_or_equal_than(self, rule_a: DefeasibleRule, + rule_b: DefeasibleRule) -> bool: return self.defeasible_rule_preferences.is_weaker_than(rule_a, rule_b) - def ordinary_premise_is_strictly_weaker_than(self, ordinary_premise_a: Literal, - ordinary_premise_b: Literal) -> bool: - return self.ordinary_premise_preferences.is_strictly_weaker_than(ordinary_premise_a, ordinary_premise_b) - - def ordinary_premise_is_weaker_or_equal_than(self, ordinary_premise_a: Literal, - ordinary_premise_b: Literal) -> bool: - return self.ordinary_premise_preferences.is_weaker_than(ordinary_premise_a, ordinary_premise_b) - - def rule_set_is_strictly_weaker_than(self, rule_set_a: Set[DefeasibleRule], rule_set_b: Set[DefeasibleRule]): + def ordinary_premise_is_strictly_weaker_than( + self, ordinary_premise_a: Literal, + ordinary_premise_b: Literal) -> bool: + return self.ordinary_premise_preferences.is_strictly_weaker_than( + ordinary_premise_a, ordinary_premise_b) + + def ordinary_premise_is_weaker_or_equal_than( + self, ordinary_premise_a: Literal, + ordinary_premise_b: Literal) -> bool: + return self.ordinary_premise_preferences.is_weaker_than( + ordinary_premise_a, ordinary_premise_b) + + def rule_set_is_strictly_weaker_than( + self, rule_set_a: Set[DefeasibleRule], + rule_set_b: Set[DefeasibleRule]): pass - def ordinary_premise_set_is_strictly_weaker_than(self, ordinary_premise_set_a: Set[Literal], - ordinary_premise_set_b: Set[Literal]): + def ordinary_premise_set_is_strictly_weaker_than( + self, ordinary_premise_set_a: Set[Literal], + ordinary_premise_set_b: Set[Literal]): pass - def rule_set_is_weaker_or_equal_than(self, rule_set_a: Set[DefeasibleRule], rule_set_b: Set[DefeasibleRule]): - return self.rule_set_is_strictly_weaker_than(rule_set_a, rule_set_b) or rule_set_a == rule_set_b - - def ordinary_premise_set_is_weaker_or_equal_than(self, ordinary_premise_set_a: Set[Literal], - ordinary_premise_set_b: Set[Literal]): - return self.ordinary_premise_set_is_strictly_weaker_than(ordinary_premise_set_a, ordinary_premise_set_b) or \ + def rule_set_is_weaker_or_equal_than(self, + rule_set_a: Set[DefeasibleRule], + rule_set_b: Set[DefeasibleRule]): + return self.rule_set_is_strictly_weaker_than( + rule_set_a, rule_set_b) or rule_set_a == rule_set_b + + def ordinary_premise_set_is_weaker_or_equal_than( + self, ordinary_premise_set_a: Set[Literal], + ordinary_premise_set_b: Set[Literal]): + return self.ordinary_premise_set_is_strictly_weaker_than( + ordinary_premise_set_a, ordinary_premise_set_b) or \ ordinary_premise_set_a == ordinary_premise_set_b - def argument_is_strictly_weaker_than(self, argument_a: InstantiatedArgument, argument_b: InstantiatedArgument): + def argument_is_strictly_weaker_than( + self, argument_a: InstantiatedArgument, + argument_b: InstantiatedArgument): pass diff --git a/src/py_arg/aspic/classes/orderings/preference_preorder.py b/src/py_arg/aspic/classes/orderings/preference_preorder.py index f7941d6..fe25496 100644 --- a/src/py_arg/aspic/classes/orderings/preference_preorder.py +++ b/src/py_arg/aspic/classes/orderings/preference_preorder.py @@ -2,7 +2,9 @@ class PreferencePreorder: - def __init__(self, preference_tuples: Optional[List[Tuple[Hashable, Hashable]]] = None): + def __init__( + self, preference_tuples: + Optional[List[Tuple[Hashable, Hashable]]] = None): if preference_tuples: self.preference_tuples = preference_tuples else: @@ -12,15 +14,18 @@ def is_weaker_than(self, object_a, object_b): return (object_a, object_b) in self.preference_tuples def is_strictly_weaker_than(self, object_a, object_b): - return self.is_weaker_than(object_a, object_b) and not self.is_weaker_than(object_b, object_a) + return self.is_weaker_than(object_a, object_b) and not \ + self.is_weaker_than(object_b, object_a) def __eq__(self, other): - return set(sorted(self.preference_tuples)) == set(sorted(other.preference_tuples)) + return set(sorted(self.preference_tuples)) == set( + sorted(other.preference_tuples)) def append(self, item: Tuple[Hashable, Hashable]): self.preference_tuples.append(item) @classmethod def create_reflexive_preorder(cls, items_to_be_ordered: List[Hashable]): - preference_tuples = [(item_to_be_ordered, item_to_be_ordered) for item_to_be_ordered in items_to_be_ordered] + preference_tuples = [(item_to_be_ordered, item_to_be_ordered) + for item_to_be_ordered in items_to_be_ordered] return cls(preference_tuples) diff --git a/src/py_arg/aspic/classes/orderings/set_orderings/democratic_ordering.py b/src/py_arg/aspic/classes/orderings/set_orderings/democratic_ordering.py index 786eda2..9c4b32f 100644 --- a/src/py_arg/aspic/classes/orderings/set_orderings/democratic_ordering.py +++ b/src/py_arg/aspic/classes/orderings/set_orderings/democratic_ordering.py @@ -3,29 +3,36 @@ from py_arg.aspic.classes.defeasible_rule import DefeasibleRule from py_arg.aspic.classes.literal import Literal from py_arg.aspic.classes.orderings.ordering import Ordering -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder class DemocraticOrdering(Ordering): def __init__(self, defeasible_rule_preferences: PreferencePreorder, ordinary_premise_preferences: PreferencePreorder): - super().__init__(defeasible_rule_preferences, ordinary_premise_preferences) + super().__init__(defeasible_rule_preferences, + ordinary_premise_preferences) - def rule_set_is_strictly_weaker_than(self, rule_set_a: Set[DefeasibleRule], rule_set_b: Set[DefeasibleRule]): + def rule_set_is_strictly_weaker_than( + self, rule_set_a: Set[DefeasibleRule], + rule_set_b: Set[DefeasibleRule]): if not rule_set_a: return False if not rule_set_b: return True - return all([any([self.rule_is_strictly_weaker_than(rule_from_a, rule_from_b) + return all([any([self.rule_is_strictly_weaker_than( + rule_from_a, rule_from_b) for rule_from_b in rule_set_b]) for rule_from_a in rule_set_a]) - def ordinary_premise_set_is_strictly_weaker_than(self, ordinary_premise_set_a: Set[Literal], - ordinary_premise_set_b: Set[Literal]): + def ordinary_premise_set_is_strictly_weaker_than( + self, ordinary_premise_set_a: Set[Literal], + ordinary_premise_set_b: Set[Literal]): if not ordinary_premise_set_a: return False if not ordinary_premise_set_b: return True - return all([any([self.ordinary_premise_is_strictly_weaker_than(ordinary_premise_from_a, ordinary_premise_from_b) - for ordinary_premise_from_b in ordinary_premise_set_b]) - for ordinary_premise_from_a in ordinary_premise_set_a]) + return all([any([self.ordinary_premise_is_strictly_weaker_than( + ordinary_premise_from_a, ordinary_premise_from_b) + for ordinary_premise_from_b in ordinary_premise_set_b]) + for ordinary_premise_from_a in ordinary_premise_set_a]) diff --git a/src/py_arg/aspic/classes/orderings/set_orderings/elitist_ordering.py b/src/py_arg/aspic/classes/orderings/set_orderings/elitist_ordering.py index fcc6f3c..fb2219b 100644 --- a/src/py_arg/aspic/classes/orderings/set_orderings/elitist_ordering.py +++ b/src/py_arg/aspic/classes/orderings/set_orderings/elitist_ordering.py @@ -3,29 +3,36 @@ from py_arg.aspic.classes.defeasible_rule import DefeasibleRule from py_arg.aspic.classes.literal import Literal from py_arg.aspic.classes.orderings.ordering import Ordering -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder class ElitistOrdering(Ordering): def __init__(self, defeasible_rule_preferences: PreferencePreorder, ordinary_premise_preferences: PreferencePreorder): - super().__init__(defeasible_rule_preferences, ordinary_premise_preferences) + super().__init__(defeasible_rule_preferences, + ordinary_premise_preferences) - def rule_set_is_strictly_weaker_than(self, rule_set_a: Set[DefeasibleRule], rule_set_b: Set[DefeasibleRule]): + def rule_set_is_strictly_weaker_than( + self, rule_set_a: Set[DefeasibleRule], + rule_set_b: Set[DefeasibleRule]): if not rule_set_a: return False if not rule_set_b: return True - return any([all([self.rule_is_strictly_weaker_than(rule_from_a, rule_from_b) - for rule_from_b in rule_set_b]) - for rule_from_a in rule_set_a]) + return any([all([self.rule_is_strictly_weaker_than( + rule_from_a, rule_from_b) + for rule_from_b in rule_set_b]) + for rule_from_a in rule_set_a]) - def ordinary_premise_set_is_strictly_weaker_than(self, ordinary_premise_set_a: Set[Literal], - ordinary_premise_set_b: Set[Literal]): + def ordinary_premise_set_is_strictly_weaker_than( + self, ordinary_premise_set_a: Set[Literal], + ordinary_premise_set_b: Set[Literal]): if not ordinary_premise_set_a: return False if not ordinary_premise_set_b: return True - return any([all([self.ordinary_premise_is_strictly_weaker_than(ordinary_premise_from_a, ordinary_premise_from_b) - for ordinary_premise_from_b in ordinary_premise_set_b]) - for ordinary_premise_from_a in ordinary_premise_set_a]) + return any([all([self.ordinary_premise_is_strictly_weaker_than( + ordinary_premise_from_a, ordinary_premise_from_b) + for ordinary_premise_from_b in ordinary_premise_set_b]) + for ordinary_premise_from_a in ordinary_premise_set_a]) diff --git a/src/py_arg/aspic/classes/rule.py b/src/py_arg/aspic/classes/rule.py index 386552f..77eace8 100644 --- a/src/py_arg/aspic/classes/rule.py +++ b/src/py_arg/aspic/classes/rule.py @@ -7,11 +7,14 @@ class Rule: """ A Rule has a list of antecedents and a single consequent. """ - def __init__(self, rule_id: str, antecedents: Set[Literal], consequent: Literal): + def __init__(self, rule_id: str, antecedents: Set[Literal], + consequent: Literal): self.id = str(rule_id) self.antecedents = sorted(antecedents) self.consequent = consequent - self.rule_str = ','.join([str(antecedent) for antecedent in self.antecedents]) + '=>' + str(self.consequent) + self.rule_str = ','.join([str(antecedent) + for antecedent in self.antecedents]) + \ + '=>' + str(self.consequent) self.rule_hash = hash(self.rule_str) def is_rule_for(self, literal: Literal) -> bool: diff --git a/src/py_arg/aspic/classes/strict_rule.py b/src/py_arg/aspic/classes/strict_rule.py index 41b6d15..743f90c 100644 --- a/src/py_arg/aspic/classes/strict_rule.py +++ b/src/py_arg/aspic/classes/strict_rule.py @@ -5,11 +5,13 @@ class StrictRule(Rule): - def __init__(self, rule_id: str, antecedents: Set[Literal], consequent: Literal): + def __init__(self, rule_id: str, antecedents: Set[Literal], + consequent: Literal): super().__init__(rule_id, antecedents, consequent) def __repr__(self): - return ','.join([str(antecedent) for antecedent in self.antecedents]) + '->' + str(self.consequent) + return ','.join([str(antecedent) for antecedent in self.antecedents])\ + + '->' + str(self.consequent) def __str__(self): return self.__repr__() diff --git a/src/py_arg/aspic/classes/structured_argumentation_framework.py b/src/py_arg/aspic/classes/structured_argumentation_framework.py index 67f2882..daa33c2 100644 --- a/src/py_arg/aspic/classes/structured_argumentation_framework.py +++ b/src/py_arg/aspic/classes/structured_argumentation_framework.py @@ -7,13 +7,15 @@ class StructuredArgumentationFramework: def __init__(self, name: str = '', arguments: Optional[List[Argument]] = None, attacks: Optional[List[Tuple[Argument, Argument]]] = None, - argument_preference_relation: Optional[List[Tuple[Argument, Argument]]] = None): + argument_preference_relation: + Optional[List[Tuple[Argument, Argument]]] = None): self.name = name if arguments is None: self._arguments = {} else: - self._arguments = {argument.name: argument for argument in arguments} + self._arguments = {argument.name: argument + for argument in arguments} if attacks is None: self.attacks = [] @@ -21,6 +23,8 @@ def __init__(self, name: str = '', self.attacks = attacks if argument_preference_relation is None: - self.argument_preference_relation = [(argument, argument) for argument in self._arguments.values()] + self.argument_preference_relation = [ + (argument, argument) + for argument in self._arguments.values()] else: self.argument_preference_relation = argument_preference_relation diff --git a/src/py_arg/aspic/generators/argumentation_system_generators/layered_argumentation_system_generator.py b/src/py_arg/aspic/generators/argumentation_system_generators/layered_argumentation_system_generator.py index 176ac1d..6147193 100644 --- a/src/py_arg/aspic/generators/argumentation_system_generators/layered_argumentation_system_generator.py +++ b/src/py_arg/aspic/generators/argumentation_system_generators/layered_argumentation_system_generator.py @@ -5,7 +5,8 @@ from py_arg.aspic.classes.argumentation_system import ArgumentationSystem from py_arg.aspic.classes.defeasible_rule import DefeasibleRule from py_arg.aspic.classes.literal import Literal -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder from py_arg.aspic.classes.strict_rule import StrictRule @@ -15,63 +16,84 @@ def __init__(self, nr_of_literals: int, nr_of_rules: int, literal_layer_distribution: Dict[int, int], strict_rule_ratio: float): """ - Construct a generator for making random Argumentation Systems with a layered structure + Construct a generator for making random Argumentation Systems with a + layered structure :param nr_of_literals: The desired number of literals. :param nr_of_rules: The desired number of rules. - :param rule_antecedent_distribution: Number of rules (value) with specific number of antecedents (key) - :param literal_layer_distribution: Number of literals (value) in a specific layer (key) + :param rule_antecedent_distribution: Number of rules (value) with + specific number of antecedents (key) + :param literal_layer_distribution: Number of literals (value) in a + specific layer (key) :param strict_rule_ratio: Ratio of strict rules given all rules. """ if nr_of_literals % 2 != 0: - raise ValueError('Language size should be even, since each literal should have a negated version.') + raise ValueError('Language size should be even, since each ' + 'literal should have a negated version.') self.nr_of_literals = nr_of_literals - required_rules = sum([value for key, value in literal_layer_distribution.items() if key != 0]) + required_rules = sum([ + value for key, value in literal_layer_distribution.items() + if key != 0]) if nr_of_rules < required_rules: - raise ValueError('You need more rules to enable this literal layer distribution.') + raise ValueError('You need more rules to enable this literal ' + 'layer distribution.') self.nr_of_rules = nr_of_rules possible_layers = sorted(literal_layer_distribution.keys()) if 0 not in possible_layers: raise ValueError('There should at least be a literal of layer 0.') - if any([x + 1 != y for x, y in zip(possible_layers[:-1], possible_layers[1:])]): - raise ValueError('Each layer between the minimum and maximum should have a value.') + if any([x + 1 != y for x, y in zip(possible_layers[:-1], + possible_layers[1:])]): + raise ValueError('Each layer between the minimum and maximum ' + 'should have a value.') if sum(literal_layer_distribution.values()) != nr_of_literals: - raise ValueError('The sum of the literal layer distribution should equal the language size.') + raise ValueError('The sum of the literal layer distribution ' + 'should equal the language size.') self.literal_layer_distribution = literal_layer_distribution if sum(rule_antecedent_distribution.values()) != nr_of_rules: - raise ValueError('The sum of the rule antecedent distribution should equal the rule size.') + raise ValueError('The sum of the rule antecedent distribution ' + 'should equal the rule size.') self.rule_antecedent_distribution = rule_antecedent_distribution - if any([nr_antecedents > nr_of_literals / 2 for nr_antecedents in self.rule_antecedent_distribution.keys()]): - raise ValueError('Rules cannot have more antecedents than half of the language size.') + if any([nr_antecedents > nr_of_literals / 2 + for nr_antecedents in + self.rule_antecedent_distribution.keys()]): + raise ValueError('Rules cannot have more antecedents than half' + ' of the language size.') if strict_rule_ratio < 0 or strict_rule_ratio > 1: - raise ValueError('Strict rule ratio should be between zero and one.') + raise ValueError('Strict rule ratio should be between zero and ' + 'one.') self.strict_rule_ratio = strict_rule_ratio - def generate(self, return_layered_language: bool = False, add_rule_preferences=True): + def generate(self, return_layered_language: bool = False, + add_rule_preferences=True): max_remaining_tries = 25 while max_remaining_tries > 0: try: max_remaining_tries -= 1 - layered_language, contraries = self._generate_language_and_contradictories_initial() - strict_rules, defeasible_rules, def_rule_preferences = self._generate_rules(layered_language, - add_rule_preferences, - contraries) - language = {str(literal): literal for literals in layered_language.values() for literal in literals} - - argumentation_system = ArgumentationSystem(language, contraries, strict_rules, defeasible_rules, - add_defeasible_rule_literals=False, - defeasible_rule_preferences=def_rule_preferences) + layered_language, contraries = \ + self._generate_language_and_contradictories_initial() + strict_rules, defeasible_rules, def_rule_preferences = \ + self._generate_rules(layered_language, + add_rule_preferences, contraries) + language = {str(literal): literal + for literals in layered_language.values() + for literal in literals} + + argumentation_system = ArgumentationSystem( + language, contraries, strict_rules, defeasible_rules, + add_defeasible_rule_literals=False, + defeasible_rule_preferences=def_rule_preferences) if return_layered_language: return argumentation_system, layered_language return argumentation_system except ValueError: pass - raise ValueError('Could not generate an ArgumentationSystem with these properties.') + raise ValueError('Could not generate an ArgumentationSystem with ' + 'these properties.') def _generate_language_and_contradictories_initial(self) -> \ Tuple[Dict[int, List[Literal]], Dict[str, Set[Literal]]]: @@ -86,9 +108,11 @@ def _generate_language_and_contradictories_initial(self) -> \ literal_str_negative = '-l' + str(pos_literal_index) # Get layer and update layers for future random layer choices - new_literal_positive_layer = random.choices(list(layers.keys()), list(layers.values()), k=1)[0] + new_literal_positive_layer = random.choices( + list(layers.keys()), list(layers.values()), k=1)[0] layers[new_literal_positive_layer] -= 1 - new_literal_negative_layer = random.choices(list(layers.keys()), list(layers.values()), k=1)[0] + new_literal_negative_layer = random.choices( + list(layers.keys()), list(layers.values()), k=1)[0] layers[new_literal_negative_layer] -= 1 # Generate a Literal: positive version @@ -101,12 +125,15 @@ def _generate_language_and_contradictories_initial(self) -> \ contradictories[literal_str_negative] = {new_literal_positive} # Add to layered language dict - layered_language[new_literal_positive_layer].append(new_literal_positive) - layered_language[new_literal_negative_layer].append(new_literal_negative) + layered_language[new_literal_positive_layer].append( + new_literal_positive) + layered_language[new_literal_negative_layer].append( + new_literal_negative) return layered_language, contradictories - def _generate_rules(self, layered_language: Dict[int, List[Literal]], add_rule_preferences: bool, + def _generate_rules(self, layered_language: Dict[int, List[Literal]], + add_rule_preferences: bool, contradictories: Dict[str, Set[Literal]]) -> \ Tuple[List[StrictRule], List[DefeasibleRule], PreferencePreorder]: # Keep track of remaining antecedent options @@ -116,18 +143,24 @@ def _generate_rules(self, layered_language: Dict[int, List[Literal]], add_rule_p defeasible_rules = [] # Start with the necessary rules - necessary_consequents = [(literal, layer) for layer, literals in layered_language.items() - for literal in literals - if layer > 0] + necessary_consequents = [ + (literal, layer) + for layer, literals in layered_language.items() + for literal in literals + if layer > 0] for consequent, consequent_layer in necessary_consequents: antecedents = [] if not layered_language[consequent_layer - 1]: - raise ValueError('Could not add a rule with the required number of literals') - highest_antecedent = random.choice(layered_language[consequent_layer - 1]) + raise ValueError( + 'Could not add a rule with the required number of ' + 'literals') + highest_antecedent = random.choice( + layered_language[consequent_layer - 1]) antecedents.append(highest_antecedent) - nr_of_antecedents = random.choices(list(r_a_d.keys()), list(r_a_d.values()), k=1)[0] + nr_of_antecedents = random.choices( + list(r_a_d.keys()), list(r_a_d.values()), k=1)[0] r_a_d[nr_of_antecedents] -= 1 while len(antecedents) < nr_of_antecedents: @@ -135,35 +168,45 @@ def _generate_rules(self, layered_language: Dict[int, List[Literal]], add_rule_p for other_layer, other_literals in layered_language.items(): if other_layer < consequent_layer: for other_literal in other_literals: - if other_literal not in antecedents and other_literal != consequent and \ - all([contrary not in antecedents and contrary != consequent - for contrary in contradictories[str(other_literal)]]): + if other_literal not in antecedents and \ + other_literal != consequent and \ + all([contrary not in antecedents and + contrary != consequent + for contrary in contradictories[ + str(other_literal)]]): antecedent_candidates.append(other_literal) if not antecedent_candidates: - raise ValueError('Could not add a rule with the required number of literals') + raise ValueError('Could not add a rule with the required ' + 'number of literals') new_antecedent = random.choice(antecedent_candidates) antecedents.append(new_antecedent) # Decide if this rule will be strict or defeasible - rule_will_be_strict = random.choices([True, False], - weights=[self.strict_rule_ratio, 1 - self.strict_rule_ratio])[0] + rule_will_be_strict = random.choices( + [True, False], + weights=[ + self.strict_rule_ratio, 1 - self.strict_rule_ratio])[0] if rule_will_be_strict: - new_rule = StrictRule('r' + str(len(strict_rules)), set(antecedents), consequent) + new_rule = StrictRule('r' + str(len(strict_rules)), + set(antecedents), consequent) strict_rules.append(new_rule) else: - new_rule = DefeasibleRule('d' + str(len(defeasible_rules)), set(antecedents), consequent) + new_rule = DefeasibleRule('d' + str(len(defeasible_rules)), + set(antecedents), consequent) defeasible_rules.append(new_rule) # Add additional rules while len(strict_rules) + len(defeasible_rules) < self.nr_of_rules: if not necessary_consequents: - raise ValueError('It is not possible to generate the required number of rules.') + raise ValueError('It is not possible to generate the required ' + 'number of rules.') consequent, consequent_layer = random.choice(necessary_consequents) # Find antecedents - nr_of_antecedents = random.choices(list(r_a_d.keys()), list(r_a_d.values()), k=1)[0] + nr_of_antecedents = random.choices(list(r_a_d.keys()), + list(r_a_d.values()), k=1)[0] r_a_d[nr_of_antecedents] -= 1 antecedents = [] @@ -172,35 +215,47 @@ def _generate_rules(self, layered_language: Dict[int, List[Literal]], add_rule_p for other_layer, other_literals in layered_language.items(): if other_layer < consequent_layer: for other_literal in other_literals: - if other_literal not in antecedents and other_literal != consequent and \ - all([contrary not in antecedents and contrary != consequent - for contrary in contradictories[str(other_literal)]]): + if other_literal not in antecedents and \ + other_literal != consequent and \ + all([contrary not in antecedents and + contrary != consequent + for contrary in contradictories[ + str(other_literal)]]): antecedent_candidates.append(other_literal) if not antecedent_candidates: - raise ValueError('Could not add a rule with the required number of literals') + raise ValueError('Could not add a rule with the required ' + 'number of literals') new_antecedent = random.choice(antecedent_candidates) antecedents.append(new_antecedent) # Decide if this rule will be strict or defeasible - rule_will_be_strict = random.choices([True, False], - weights=[self.strict_rule_ratio, 1 - self.strict_rule_ratio])[0] + rule_will_be_strict = random.choices( + [True, False], + weights=[ + self.strict_rule_ratio, 1 - self.strict_rule_ratio])[0] if rule_will_be_strict: - new_rule = StrictRule('r' + str(len(strict_rules)), set(antecedents), consequent) + new_rule = StrictRule('r' + str(len(strict_rules)), + set(antecedents), consequent) strict_rules.append(new_rule) else: - new_rule = DefeasibleRule('d' + str(len(defeasible_rules)), set(antecedents), consequent) + new_rule = DefeasibleRule('d' + str(len(defeasible_rules)), + set(antecedents), consequent) defeasible_rules.append(new_rule) if add_rule_preferences: rule_preferences = PreferencePreorder() shuffled_defeasible_rules = defeasible_rules.copy() random.shuffle(shuffled_defeasible_rules) - contradicting_rules = {(rule_a, rule_b) - for rule_a, rule_b in itertools.combinations(shuffled_defeasible_rules, 2) - if rule_a.consequent in contradictories[str(rule_b.consequent)]} - leq_rules = random.sample(list(contradicting_rules), int(len(contradicting_rules) / 2)) + contradicting_rules = { + (rule_a, rule_b) + for rule_a, rule_b in itertools.combinations( + shuffled_defeasible_rules, 2) + if rule_a.consequent in contradictories[ + str(rule_b.consequent)]} + leq_rules = random.sample(list(contradicting_rules), + int(len(contradicting_rules) / 2)) for geq_tuple in leq_rules: rule_preferences.append(geq_tuple) else: diff --git a/src/py_arg/aspic/generators/argumentation_theory_generators/argumentation_theory_generator.py b/src/py_arg/aspic/generators/argumentation_theory_generators/argumentation_theory_generator.py index 429c41d..75700d8 100644 --- a/src/py_arg/aspic/generators/argumentation_theory_generators/argumentation_theory_generator.py +++ b/src/py_arg/aspic/generators/argumentation_theory_generators/argumentation_theory_generator.py @@ -5,44 +5,56 @@ class ArgumentationTheoryGenerator: - def __init__(self, argumentation_system: ArgumentationSystem, knowledge_literal_ratio: float, + def __init__(self, argumentation_system: ArgumentationSystem, + knowledge_literal_ratio: float, axiom_knowledge_ratio: float): self.argumentation_system = argumentation_system if knowledge_literal_ratio > 0.5: - raise ValueError('At most half of the literals can be in the knowledge base.') + raise ValueError('At most half of the literals can be in the ' + 'knowledge base.') if knowledge_literal_ratio < 0: - raise ValueError('The knowledge literal ratio should be at least one.') + raise ValueError('The knowledge literal ratio should be at least ' + 'one.') self.knowledge_literal_ratio = knowledge_literal_ratio if axiom_knowledge_ratio < 0 or axiom_knowledge_ratio > 1: - raise ValueError('The axiom knowledge ratio should be between zero and one.') + raise ValueError('The axiom knowledge ratio should be between ' + 'zero and one.') self.axiom_knowledge_ratio = axiom_knowledge_ratio def generate(self) -> ArgumentationTheory: - normal_literals = [literal for literal_str, literal in self.argumentation_system.language.items() - if 'd' not in literal_str] + normal_literals = [ + literal + for literal_str, literal in + self.argumentation_system.language.items() + if 'd' not in literal_str] nr_of_literals = len(normal_literals) - knowledge_base_size = int(self.knowledge_literal_ratio * nr_of_literals) + knowledge_base_size = \ + int(self.knowledge_literal_ratio * nr_of_literals) knowledge_base_candidates = normal_literals knowledge_base = [] for _ in range(knowledge_base_size): if not knowledge_base_candidates: - raise ValueError('Could not construct such a large knowledge base given the contradictories.') + raise ValueError('Could not construct such a large knowledge ' + 'base given the contradictories.') new_knowledge = random.choice(knowledge_base_candidates) knowledge_base.append(new_knowledge) knowledge_base_candidates.remove(new_knowledge) - for new_knowledge_contrary in new_knowledge.contraries_and_contradictories: + for new_knowledge_contrary in \ + new_knowledge.contraries_and_contradictories: knowledge_base_candidates.remove(new_knowledge_contrary) axiom_size = int(knowledge_base_size * self.axiom_knowledge_ratio) axiom_indices = random.sample(range(knowledge_base_size), axiom_size) axioms = [knowledge_base[i] for i in axiom_indices] - ordinary_premises = [knowledge_base[i] for i in range(knowledge_base_size) + ordinary_premises = [knowledge_base[i] + for i in range(knowledge_base_size) if i not in axiom_indices] - return ArgumentationTheory(argumentation_system=self.argumentation_system, - knowledge_base_axioms=axioms, - knowledge_base_ordinary_premises=ordinary_premises) + return ArgumentationTheory( + argumentation_system=self.argumentation_system, + knowledge_base_axioms=axioms, + knowledge_base_ordinary_premises=ordinary_premises) diff --git a/src/py_arg/aspic/import_export/argumentation_system_from_json_reader.py b/src/py_arg/aspic/import_export/argumentation_system_from_json_reader.py index 3acdd40..cff361d 100644 --- a/src/py_arg/aspic/import_export/argumentation_system_from_json_reader.py +++ b/src/py_arg/aspic/import_export/argumentation_system_from_json_reader.py @@ -3,7 +3,8 @@ from py_arg.aspic.classes.argumentation_system import ArgumentationSystem from py_arg.aspic.classes.defeasible_rule import DefeasibleRule from py_arg.aspic.classes.literal import Literal -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder from py_arg.aspic.classes.strict_rule import StrictRule @@ -13,35 +14,46 @@ def __init__(self): @staticmethod def from_json(json_object) -> ArgumentationSystem: - language = {literal_str: Literal(literal_str) for literal_str in json_object['language']} - contraries = {literal_str: {language[con_lit] for con_lit in con_lit_list} - for literal_str, con_lit_list in json_object['contraries'].items()} + language = {literal_str: Literal(literal_str) + for literal_str in json_object['language']} + contraries = {literal_str: {language[con_lit] + for con_lit in con_lit_list} + for literal_str, con_lit_list + in json_object['contraries'].items()} defeasible_rules = [] for defeasible_rule_str in json_object['defeasible_rules']: - antecedents_str, consequent_str = defeasible_rule_str[1].split('=>', 1) + antecedents_str, consequent_str = defeasible_rule_str[1].split( + '=>', 1) antecedent_str_list = antecedents_str.split(',') - defeasible_rule = DefeasibleRule(defeasible_rule_str[0], - {language[antecedent_str] for antecedent_str in antecedent_str_list}, - language[consequent_str]) + defeasible_rule = DefeasibleRule( + defeasible_rule_str[0], + {language[antecedent_str] + for antecedent_str in antecedent_str_list}, + language[consequent_str]) defeasible_rules.append(defeasible_rule) - def_rules_lookup = {defeasible_rule.id: defeasible_rule for defeasible_rule in defeasible_rules} + def_rules_lookup = {defeasible_rule.id: defeasible_rule + for defeasible_rule in defeasible_rules} strict_rules = [] for strict_rule_str in json_object['strict_rules']: antecedents_str, consequent_str = strict_rule_str[1].split('->', 1) antecedent_str_list = antecedents_str.split(',') - strict_rule = StrictRule(strict_rule_str[0], - {language[antecedent_str] for antecedent_str in antecedent_str_list}, + strict_rule = StrictRule(strict_rule_str[0], { + language[antecedent_str] + for antecedent_str in antecedent_str_list}, language[consequent_str]) strict_rules.append(strict_rule) rule_preferences = PreferencePreorder() for rule_preference in json_object['rule_preferences']: - rule_preferences.append((def_rules_lookup[rule_preference[0]], def_rules_lookup[rule_preference[1]])) + rule_preferences.append((def_rules_lookup[rule_preference[0]], + def_rules_lookup[rule_preference[1]])) - return ArgumentationSystem(language, contraries, strict_rules, defeasible_rules, rule_preferences, - add_defeasible_rule_literals=False) + return ArgumentationSystem( + language, contraries, strict_rules, defeasible_rules, + rule_preferences, + add_defeasible_rule_literals=False) def read_from_json(self, file_path: str) -> ArgumentationSystem: with open(file_path, 'r') as reader: diff --git a/src/py_arg/aspic/import_export/argumentation_system_to_json_writer.py b/src/py_arg/aspic/import_export/argumentation_system_to_json_writer.py index 2ce52ac..981850d 100644 --- a/src/py_arg/aspic/import_export/argumentation_system_to_json_writer.py +++ b/src/py_arg/aspic/import_export/argumentation_system_to_json_writer.py @@ -11,15 +11,21 @@ def __init__(self): @staticmethod def to_dict(argumentation_system: ArgumentationSystem): return {'language': list(argumentation_system.language.keys()), - 'contraries': {lit_str: [str(con_lit) for con_lit in lit.contraries_and_contradictories] - for lit_str, lit in argumentation_system.language.items()}, - 'defeasible_rules': [(defeasible_rule.id, str(defeasible_rule)) - for defeasible_rule in argumentation_system.defeasible_rules], - 'strict_rules': [(strict_rule.id, str(strict_rule)) - for strict_rule in argumentation_system.strict_rules], - 'rule_preferences': [(rule_preference_tuple[0].id, rule_preference_tuple[1].id) - for rule_preference_tuple in - argumentation_system.rule_preferences.preference_tuples] + 'contraries': {lit_str: [ + str(con_lit) + for con_lit in lit.contraries_and_contradictories] + for lit_str, lit in argumentation_system.language.items()}, + 'defeasible_rules': [ + (defeasible_rule.id, str(defeasible_rule)) + for defeasible_rule in + argumentation_system.defeasible_rules], + 'strict_rules': [ + (strict_rule.id, str(strict_rule)) + for strict_rule in argumentation_system.strict_rules], + 'rule_preferences': [ + (rule_preference_tuple[0].id, rule_preference_tuple[1].id) + for rule_preference_tuple in + argumentation_system.rule_preferences.preference_tuples] } def write(self, argumentation_system: ArgumentationSystem, file_name: str): diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_adm.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_adm.py index 146fab5..33a89cb 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_adm.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_adm.py @@ -1,8 +1,10 @@ from typing import Set -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -from py_arg.assumption_based_argumentation.canonical_constructions import canonical_ucl, canonical_cf +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +from py_arg.assumption_based_argumentation.canonical_constructions import \ + canonical_ucl, canonical_cf @staticmethod @@ -15,4 +17,5 @@ def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: contraries = abaf_cf.contraries contraries.update(abaf_ucl.contraries) - return AssumptionBasedArgumentationFramework(assumptions, rules, language, contraries) + return AssumptionBasedArgumentationFramework(assumptions, rules, language, + contraries) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_cf.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_cf.py index d583053..1ae6d2c 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_cf.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_cf.py @@ -1,9 +1,11 @@ from typing import Set -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework from py_arg.assumption_based_argumentation.classes.rule import Rule -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod @@ -22,4 +24,5 @@ def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: if ext.union({a}) not in aux.dcl(extension_set): rules.add(Rule('', ext, contraries[a])) - return AssumptionBasedArgumentationFramework(assumptions, rules, language, contraries) + return AssumptionBasedArgumentationFramework(assumptions, rules, language, + contraries) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_com.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_com.py index c3ce62f..6a2e5b9 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_com.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_com.py @@ -1,15 +1,19 @@ from typing import Set -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework from py_arg.assumption_based_argumentation.classes.rule import Rule -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux -import py_arg.assumption_based_argumentation.canonical_constructions.canonical_adm as canonical_adm +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux +import py_arg.assumption_based_argumentation.canonical_constructions.\ + canonical_adm as canonical_adm @staticmethod def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: - extension_set_star = aux.dcl(aux.reduce(extension_set)).intersection(aux.ucl(aux.reduce(extension_set))) + extension_set_star = aux.dcl(aux.reduce(extension_set)).intersection( + aux.ucl(aux.reduce(extension_set))) assumptions = set(aux.big_a(extension_set)) abaf_adm_star = canonical_adm.apply(extension_set_star) @@ -23,10 +27,12 @@ def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: contraries[a] = a_c rules = abaf_adm_star.rules - for ext_a, ext_b in aux.tuples(aux.reduce(extension_set).difference(frozenset())): - for a in aux.unique_big_c(frozenset(set(ext_a).union(set(ext_b))), aux.reduce(extension_set)): + for ext_a, ext_b in aux.tuples(aux.reduce(extension_set).difference( + frozenset())): + for a in aux.unique_big_c(frozenset(set(ext_a).union(set(ext_b))), + aux.reduce(extension_set)): x_a_c = 'χ_' + a + '_c' rules.add(Rule('', set(ext_a).union(set(ext_b)), x_a_c)) - return AssumptionBasedArgumentationFramework(assumptions, rules, language, contraries) - + return AssumptionBasedArgumentationFramework(assumptions, rules, language, + contraries) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_st.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_st.py index 4bd76ca..f53e39c 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_st.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_st.py @@ -1,9 +1,11 @@ from typing import Set -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework from py_arg.assumption_based_argumentation.classes.rule import Rule -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod @@ -21,4 +23,5 @@ def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: for a in assumptions.difference(ext): rules.add(Rule('', ext, contraries[a])) - return AssumptionBasedArgumentationFramework(assumptions, rules, language, contraries) + return AssumptionBasedArgumentationFramework(assumptions, rules, language, + contraries) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_ucl.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_ucl.py index 1a57757..84d6693 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_ucl.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/canonical_ucl.py @@ -1,9 +1,11 @@ from typing import Set -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework from py_arg.assumption_based_argumentation.classes.rule import Rule -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux @staticmethod @@ -34,6 +36,8 @@ def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: for ext in extension_set: for a in ext: - rules.add(Rule('', ext, contraries[corresponding_self_attackers[a]])) + rules.add(Rule('', ext, + contraries[corresponding_self_attackers[a]])) - return AssumptionBasedArgumentationFramework(assumptions, rules, language, contraries) + return AssumptionBasedArgumentationFramework(assumptions, rules, language, + contraries) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_adm.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_adm.py index 0ca859a..e046fec 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_adm.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_adm.py @@ -1,14 +1,19 @@ from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.check_set_conf_sens as check_set_conf_sens -import py_arg.abstract_argumentation.canonical_constructions.check_contains_empty as check_contains_empty -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -from py_arg.assumption_based_argumentation.canonical_constructions import canonical_adm +import py_arg.abstract_argumentation.canonical_constructions.\ + check_set_conf_sens as check_set_conf_sens +import py_arg.abstract_argumentation.canonical_constructions.\ + check_contains_empty as check_contains_empty +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +from py_arg.assumption_based_argumentation.canonical_constructions import \ + canonical_adm @staticmethod def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: - if check_set_conf_sens.apply(extension_set) and check_contains_empty.apply(extension_set): + if check_set_conf_sens.apply(extension_set) and \ + check_contains_empty.apply(extension_set): return canonical_adm.apply(extension_set) return AssumptionBasedArgumentationFramework(set(), set(), set(), {}) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_cf.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_cf.py index a6c3f60..9602fcf 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_cf.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_cf.py @@ -1,16 +1,20 @@ from typing import Set -from py_arg.abstract_argumentation.canonical_constructions import check_downward_closed -from py_arg.assumption_based_argumentation.canonical_constructions import canonical_cf - -import py_arg.abstract_argumentation.canonical_constructions.check_non_empty as check_non_empty -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework +from py_arg.abstract_argumentation.canonical_constructions import \ + check_downward_closed +from py_arg.assumption_based_argumentation.canonical_constructions import \ + canonical_cf +import py_arg.abstract_argumentation.canonical_constructions.check_non_empty \ + as check_non_empty +from py_arg.assumption_based_argumentation.classes.aba_framework \ + import AssumptionBasedArgumentationFramework @staticmethod def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: - if check_non_empty.apply(extension_set) and check_downward_closed.apply(extension_set): + if check_non_empty.apply(extension_set) and check_downward_closed.apply( + extension_set): return canonical_cf.apply(extension_set) return AssumptionBasedArgumentationFramework(set(), set(), set(), {}) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_com.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_com.py index 3513300..aac54d9 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_com.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_com.py @@ -1,16 +1,22 @@ from typing import Set -import py_arg.assumption_based_argumentation.canonical_constructions.canonical_com as canonical_com -import py_arg.abstract_argumentation.canonical_constructions.check_set_com_closed as check_set_com_closed -import py_arg.abstract_argumentation.canonical_constructions.check_intersection_in as check_intersection_in -import py_arg.abstract_argumentation.canonical_constructions.check_non_empty as check_non_empty +import py_arg.assumption_based_argumentation.canonical_constructions.\ + canonical_com as canonical_com +import py_arg.abstract_argumentation.canonical_constructions.\ + check_set_com_closed as check_set_com_closed +import py_arg.abstract_argumentation.canonical_constructions.\ + check_intersection_in as check_intersection_in +import py_arg.abstract_argumentation.canonical_constructions.\ + check_non_empty as check_non_empty -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework @staticmethod def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: - if check_set_com_closed.apply(extension_set) and check_intersection_in.apply(extension_set) and \ + if check_set_com_closed.apply(extension_set) and \ + check_intersection_in.apply(extension_set) and \ check_non_empty.apply(extension_set): return canonical_com.apply(extension_set) return AssumptionBasedArgumentationFramework(set(), set(), set(), {}) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_naive.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_naive.py index 10efc22..0fb7190 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_naive.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_naive.py @@ -1,14 +1,18 @@ - from typing import Set -import py_arg.abstract_argumentation.canonical_constructions.check_incomparable as check_incomparable -import py_arg.abstract_argumentation.canonical_constructions.check_non_empty as check_non_empty -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -from py_arg.assumption_based_argumentation.canonical_constructions import canonical_st +import py_arg.abstract_argumentation.canonical_constructions.\ + check_incomparable as check_incomparable +import py_arg.abstract_argumentation.canonical_constructions.check_non_empty \ + as check_non_empty +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +from py_arg.assumption_based_argumentation.canonical_constructions import \ + canonical_st @staticmethod def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: - if check_non_empty.apply(extension_set) and check_incomparable.apply(extension_set): + if check_non_empty.apply(extension_set) and check_incomparable.apply( + extension_set): return canonical_st.apply(extension_set) return AssumptionBasedArgumentationFramework(set(), set(), set(), {}) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_prf.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_prf.py index 5f0bcad..e9be6b6 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_prf.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_prf.py @@ -1,14 +1,18 @@ - from typing import Set -import py_arg.assumption_based_argumentation.canonical_constructions.canonical_st as canonical_st -import py_arg.abstract_argumentation.canonical_constructions.check_incomparable as check_incomparable -import py_arg.abstract_argumentation.canonical_constructions.check_non_empty as check_non_empty -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework +import py_arg.assumption_based_argumentation.canonical_constructions.\ + canonical_st as canonical_st +import py_arg.abstract_argumentation.canonical_constructions.\ + check_incomparable as check_incomparable +import py_arg.abstract_argumentation.canonical_constructions.\ + check_non_empty as check_non_empty +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework @staticmethod def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: - if check_incomparable.apply(extension_set) and check_non_empty.apply(extension_set): + if check_incomparable.apply(extension_set) and check_non_empty.apply( + extension_set): return canonical_st.apply(extension_set) return AssumptionBasedArgumentationFramework(set(), set(), set(), {}) diff --git a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_st.py b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_st.py index 3e159e5..6aa2059 100644 --- a/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_st.py +++ b/src/py_arg/assumption_based_argumentation/canonical_constructions/construct_abaf_st.py @@ -1,16 +1,19 @@ - from typing import Set -import py_arg.assumption_based_argumentation.canonical_constructions.canonical_st as canonical_st -import py_arg.abstract_argumentation.canonical_constructions.check_incomparable as check_incomparable -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework +import py_arg.assumption_based_argumentation.canonical_constructions.\ + canonical_st as canonical_st +import py_arg.abstract_argumentation.canonical_constructions.\ + check_incomparable as check_incomparable +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework from py_arg.assumption_based_argumentation.classes.rule import Rule @staticmethod def apply(extension_set: Set) -> AssumptionBasedArgumentationFramework: if len(extension_set) == 0: - return AssumptionBasedArgumentationFramework({'x'}, {Rule('', {'x'}, 'x_c')}, {'x', 'x_c'}, {'x': 'x_c'}) + return AssumptionBasedArgumentationFramework( + {'x'}, {Rule('', {'x'}, 'x_c')}, {'x', 'x_c'}, {'x': 'x_c'}) if check_incomparable.apply(extension_set): return canonical_st.apply(extension_set) return AssumptionBasedArgumentationFramework(set(), set(), set(), {}) diff --git a/src/py_arg/assumption_based_argumentation/classes/aba_framework.py b/src/py_arg/assumption_based_argumentation/classes/aba_framework.py index cc480c2..a9e858c 100644 --- a/src/py_arg/assumption_based_argumentation/classes/aba_framework.py +++ b/src/py_arg/assumption_based_argumentation/classes/aba_framework.py @@ -1,9 +1,10 @@ from typing import Dict, Set -from py_arg.assumption_based_argumentation.classes.instantiated_argument import InstantiatedArgument +from py_arg.assumption_based_argumentation.classes.instantiated_argument \ + import InstantiatedArgument from py_arg.assumption_based_argumentation.classes.rule import Rule -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import \ - AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.defeat import Defeat @@ -22,34 +23,43 @@ def __init__(self, self.language = language - # Verify that every item in the body or head of the rule is in the language. + # Verify that every item in the body or head of the rule is in the + # language. for rule in rules: - if any(rule_part not in self.language for rule_part in rule.get_signature()): - raise ValueError('Some part of the rule ' + str(rule) + ' is not in the language.') + if any(rule_part not in self.language + for rule_part in rule.get_signature()): + raise ValueError('Some part of the rule ' + str(rule) + + ' is not in the language.') self.contraries = contraries # Verify that each assumption has a contrary. - if any(assumption not in self.contraries.keys() for assumption in self.assumptions): + if any(assumption not in self.contraries.keys() + for assumption in self.assumptions): raise ValueError('Some assumption does not have a contrary.') # Verify that each contrary element is in the language. - if any(assumption not in self.assumptions or contrary not in self.language + if any(assumption not in self.assumptions or + contrary not in self.language for assumption, contrary in self.contraries.items()): - raise ValueError('Some contrary pair does not consist of an assumption and an atom.') + raise ValueError('Some contrary pair does not consist of an ' + 'assumption and an atom.') - # Verify that the framework is flat (assumptions cannot be in the rule head). + # Verify that the framework is flat (assumptions cannot be in the + # rule head). self.is_flat = True for rule in rules: if rule.head in assumptions: self.is_flat = False - raise ValueError('This ABA framework is not flat. At this point, we only support flat ABA.') + raise ValueError('This ABA framework is not flat. At this ' + 'point, we only support flat ABA.') def __eq__(self, other): return self.assumptions == other.assumptions and \ self.rules == other.rules and \ self.language == other.language and \ - all(literal.contraries_and_contradictories == other.language[lit_str].contraries_and_contradictories + all(literal.contraries_and_contradictories == other.language[ + lit_str].contraries_and_contradictories for lit_str, literal in self.language) def generate_af(self) -> AbstractArgumentationFramework: @@ -63,21 +73,23 @@ def generate_af(self) -> AbstractArgumentationFramework: arguments.add(InstantiatedArgument('', {assumption}, assumption)) contrary = self.contraries[assumption] - contrary_premises_set = self.recursively_construct_argument(self.rules, contrary, {contrary}) + contrary_premises_set = self.recursively_construct_argument( + self.rules, contrary, {contrary}) for contrary_premise in contrary_premises_set: - arguments.add(InstantiatedArgument('', set(contrary_premise), contrary)) + arguments.add(InstantiatedArgument('', set(contrary_premise), + contrary)) for arg1 in arguments: for premise in arg1.premise: for arg2 in arguments: - # if arg1 != arg2 and self.contraries[premise] == arg2.conclusion: if self.contraries[premise] == arg2.conclusion: arg1.add_ingoing_defeat(arg2) arg2.add_outgoing_defeat(arg1) defeats.add(Defeat(arg2, arg1)) - return AbstractArgumentationFramework('', arguments=list(arguments), defeats=list(defeats)) + return AbstractArgumentationFramework('', arguments=list(arguments), + defeats=list(defeats)) def generate_af_full(self) -> AbstractArgumentationFramework: arguments = set() @@ -91,27 +103,32 @@ def generate_af_full(self) -> AbstractArgumentationFramework: for atom in self.language.difference(self.assumptions): - atom_premises_set = self.recursively_construct_argument(self.rules, atom, {atom}) + atom_premises_set = self.recursively_construct_argument( + self.rules, atom, {atom}) for atom_premise in atom_premises_set: - arguments.add(InstantiatedArgument('', set(atom_premise), atom)) + arguments.add(InstantiatedArgument( + '', set(atom_premise), atom)) for arg1 in arguments: for premise in arg1.premise: for arg2 in arguments: - # if arg1 != arg2 and self.contraries[premise] == arg2.conclusion: if self.contraries[premise] == arg2.conclusion: arg1.add_ingoing_defeat(arg2) arg2.add_outgoing_defeat(arg1) defeats.add(Defeat(arg2, arg1)) - return AbstractArgumentationFramework('', arguments=list(arguments), defeats=list(defeats)) + return AbstractArgumentationFramework('', arguments=list(arguments), + defeats=list(defeats)) # I am basically reimplementing Prolog? # A premise of an argument is a minimal set of assumptions implying an atom - # Premises of an atom are determined recursively, going through all rules implying the atom - # Dealing with all the combinations makes the code a bit convoluted, but basically it is only backtracking - def recursively_construct_argument(self, rules: Set[Rule], target: str, visited: Set[str]): + # Premises of an atom are determined recursively, going through all rules + # implying the atom + # Dealing with all the combinations makes the code a bit convoluted, but + # basically it is only backtracking + def recursively_construct_argument(self, rules: Set[Rule], target: str, + visited: Set[str]): premises_set = set() relevant_rules = set() rest_rules = set() @@ -133,16 +150,17 @@ def recursively_construct_argument(self, rules: Set[Rule], target: str, visited: rule_premises = {frozenset(asm)} for atom in rule.body: if atom not in self.assumptions: - rule_premises = self.merge(rule_premises, - self.recursively_construct_argument(rest_rules, - atom, - visited.copy().union({atom}))) + rule_premises = self.merge( + rule_premises, + self.recursively_construct_argument( + rest_rules, atom, visited.copy().union({atom}))) premises_set = premises_set.union(rule_premises) return premises_set # crossproductlike merge - def merge(self, premise_set_set1: Set[frozenset], premise_set_set2: Set[frozenset]): + def merge(self, premise_set_set1: Set[frozenset], + premise_set_set2: Set[frozenset]): if len(premise_set_set1) == 0: return premise_set_set2 out = set() @@ -155,6 +173,8 @@ def reduce(self): rm = set() for rule1 in self.rules: for rule2 in self.rules: - if rule1.head == rule2.head and rule1.body.issubset(rule2.body) and not rule2.body.issubset(rule1.body): + if rule1.head == rule2.head and \ + rule1.body.issubset(rule2.body) and \ + not rule2.body.issubset(rule1.body): rm.add(rule2) self.rules = self.rules.difference(rm) diff --git a/src/py_arg/assumption_based_argumentation/classes/instantiated_argument.py b/src/py_arg/assumption_based_argumentation/classes/instantiated_argument.py index b8afc01..851e519 100644 --- a/src/py_arg/assumption_based_argumentation/classes/instantiated_argument.py +++ b/src/py_arg/assumption_based_argumentation/classes/instantiated_argument.py @@ -5,7 +5,8 @@ class InstantiatedArgument(Argument): def __init__(self, argument_id: str, premise: Set[str], conclusion: str): - super().__init__(', '.join([str(atom) for atom in sorted(premise)]) + ' ⊢ ' + str(conclusion)) + super().__init__(', '.join([str(atom) for atom in sorted(premise)]) + + ' ⊢ ' + str(conclusion)) self.id = str(argument_id) self.premise = premise self.conclusion = conclusion diff --git a/src/py_arg/assumption_based_argumentation/classes/rule.py b/src/py_arg/assumption_based_argumentation/classes/rule.py index 89a9891..7fdf946 100644 --- a/src/py_arg/assumption_based_argumentation/classes/rule.py +++ b/src/py_arg/assumption_based_argumentation/classes/rule.py @@ -9,7 +9,9 @@ def __init__(self, rule_id: str, body: Set[str], head: str): self.id = str(rule_id) self.body = body self.head = head - self.rule_str = str(self.head) + '<-' + ','.join([str(atom) for atom in sorted(self.body)]) + self.rule_str = \ + str(self.head) + '<-' + \ + ','.join([str(atom) for atom in sorted(self.body)]) self.rule_hash = hash(self.rule_str) def get_signature(self) -> Set[str]: diff --git a/src/py_arg/assumption_based_argumentation/semantics/get_admissible_extensions.py b/src/py_arg/assumption_based_argumentation/semantics/get_admissible_extensions.py index e42671c..ec723ea 100644 --- a/src/py_arg/assumption_based_argumentation/semantics/get_admissible_extensions.py +++ b/src/py_arg/assumption_based_argumentation/semantics/get_admissible_extensions.py @@ -1,11 +1,16 @@ from typing import Set, FrozenSet -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -import py_arg.abstract_argumentation.semantics.is_admissible as is_admissible_af -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +import py_arg.abstract_argumentation.semantics.is_admissible as \ + is_admissible_af +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux -def get_admissible_extensions(aba_framework: AssumptionBasedArgumentationFramework) -> Set[FrozenSet[str]]: +def get_admissible_extensions( + aba_framework: AssumptionBasedArgumentationFramework) -> \ + Set[FrozenSet[str]]: af = aba_framework.generate_af() aba_framework_extensions = set() diff --git a/src/py_arg/assumption_based_argumentation/semantics/get_complete_extensions.py b/src/py_arg/assumption_based_argumentation/semantics/get_complete_extensions.py index 0d8dfb0..caf41a6 100644 --- a/src/py_arg/assumption_based_argumentation/semantics/get_complete_extensions.py +++ b/src/py_arg/assumption_based_argumentation/semantics/get_complete_extensions.py @@ -1,10 +1,14 @@ from typing import Set, FrozenSet -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -import py_arg.abstract_argumentation.semantics.get_complete_extensions as get_complete_extensions_af +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +import py_arg.abstract_argumentation.semantics.get_complete_extensions as \ + get_complete_extensions_af -def get_complete_extensions(aba_framework: AssumptionBasedArgumentationFramework) -> Set[FrozenSet[str]]: +def get_complete_extensions( + aba_framework: AssumptionBasedArgumentationFramework) -> \ + Set[FrozenSet[str]]: af = aba_framework.generate_af() af_extensions = get_complete_extensions_af.get_complete_extensions(af) aba_framework_extensions = set() diff --git a/src/py_arg/assumption_based_argumentation/semantics/get_conflict_free_extensions.py b/src/py_arg/assumption_based_argumentation/semantics/get_conflict_free_extensions.py index 0c4e383..ae17d4f 100644 --- a/src/py_arg/assumption_based_argumentation/semantics/get_conflict_free_extensions.py +++ b/src/py_arg/assumption_based_argumentation/semantics/get_conflict_free_extensions.py @@ -1,10 +1,14 @@ from typing import Set, FrozenSet -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +import py_arg.abstract_argumentation.canonical_constructions.aux_operators as \ + aux -def get_conflict_free_extensions(aba_framework: AssumptionBasedArgumentationFramework) -> Set[FrozenSet[str]]: +def get_conflict_free_extensions( + aba_framework: AssumptionBasedArgumentationFramework) -> \ + Set[FrozenSet[str]]: aba_framework_extensions = set() af = aba_framework.generate_af() for ext in aux.powerset(aba_framework.assumptions): diff --git a/src/py_arg/assumption_based_argumentation/semantics/get_grounded_extensions.py b/src/py_arg/assumption_based_argumentation/semantics/get_grounded_extensions.py index f82a2bd..b36a413 100644 --- a/src/py_arg/assumption_based_argumentation/semantics/get_grounded_extensions.py +++ b/src/py_arg/assumption_based_argumentation/semantics/get_grounded_extensions.py @@ -1,10 +1,14 @@ from typing import Set, FrozenSet -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -import py_arg.abstract_argumentation.semantics.get_grounded_extension as get_grounded_extensions_af +from py_arg.assumption_based_argumentation.classes.aba_framework \ + import AssumptionBasedArgumentationFramework +import py_arg.abstract_argumentation.semantics.get_grounded_extension \ + as get_grounded_extensions_af -def get_preferred_extensions(aba_framework: AssumptionBasedArgumentationFramework) -> Set[FrozenSet[str]]: +def get_preferred_extensions( + aba_framework: AssumptionBasedArgumentationFramework) -> \ + Set[FrozenSet[str]]: af = aba_framework.generate_af() af_extension = get_grounded_extensions_af.get_grounded_extension(af) aba_framework_extensions = set() diff --git a/src/py_arg/assumption_based_argumentation/semantics/get_naive_extensions.py b/src/py_arg/assumption_based_argumentation/semantics/get_naive_extensions.py index 96578ac..307d4d4 100644 --- a/src/py_arg/assumption_based_argumentation/semantics/get_naive_extensions.py +++ b/src/py_arg/assumption_based_argumentation/semantics/get_naive_extensions.py @@ -1,11 +1,16 @@ from typing import Set, FrozenSet -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -import py_arg.assumption_based_argumentation.semantics.get_conflict_free_extensions as get_conflict_free_extensions +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +import py_arg.assumption_based_argumentation.semantics.\ + get_conflict_free_extensions as get_conflict_free_extensions -def get_naive_extensions(aba_framework: AssumptionBasedArgumentationFramework) -> Set[FrozenSet[str]]: - cf_ext = get_conflict_free_extensions.get_conflict_free_extensions(aba_framework) +def get_naive_extensions( + aba_framework: AssumptionBasedArgumentationFramework) -> \ + Set[FrozenSet[str]]: + cf_ext = get_conflict_free_extensions.get_conflict_free_extensions( + aba_framework) rm = set() for ext1 in cf_ext: for ext2 in cf_ext: diff --git a/src/py_arg/assumption_based_argumentation/semantics/get_preferred_extensions.py b/src/py_arg/assumption_based_argumentation/semantics/get_preferred_extensions.py index c12256d..3d61df9 100644 --- a/src/py_arg/assumption_based_argumentation/semantics/get_preferred_extensions.py +++ b/src/py_arg/assumption_based_argumentation/semantics/get_preferred_extensions.py @@ -1,10 +1,14 @@ from typing import Set, FrozenSet -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -import py_arg.abstract_argumentation.semantics.get_preferred_extensions as get_preferred_extensions_af +from py_arg.assumption_based_argumentation.classes.aba_framework \ + import AssumptionBasedArgumentationFramework +import py_arg.abstract_argumentation.semantics.get_preferred_extensions as \ + get_preferred_extensions_af -def get_preferred_extensions(aba_framework: AssumptionBasedArgumentationFramework) -> Set[FrozenSet[str]]: +def get_preferred_extensions( + aba_framework: AssumptionBasedArgumentationFramework) -> \ + Set[FrozenSet[str]]: af = aba_framework.generate_af() af_extensions = get_preferred_extensions_af.get_preferred_extensions(af) abaf_extensions = set() diff --git a/src/py_arg/assumption_based_argumentation/semantics/get_semi_stable_extensions.py b/src/py_arg/assumption_based_argumentation/semantics/get_semi_stable_extensions.py index b87e3f9..8530f22 100644 --- a/src/py_arg/assumption_based_argumentation/semantics/get_semi_stable_extensions.py +++ b/src/py_arg/assumption_based_argumentation/semantics/get_semi_stable_extensions.py @@ -1,22 +1,32 @@ from typing import Set, FrozenSet -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -import py_arg.assumption_based_argumentation.semantics.get_complete_extensions as get_complete_extensions +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +import py_arg.assumption_based_argumentation.semantics.\ + get_complete_extensions as get_complete_extensions -# We thank Anh Kiet Nguyen for pointing out that semi-stable assumption extensions +# We thank Anh Kiet Nguyen for pointing out that semi-stable assumption +# extensions # cannot in general be attained from the instantiated af. -# cf. 'ON THE DIFFERENCE BETWEEN ASSUMPTION-BASED ARGUMENTATION AND ABSTRACT ARGUMENTATION' -def get_semi_stable_extensions(aba_framework: AssumptionBasedArgumentationFramework) -> Set[FrozenSet[str]]: +# cf. 'ON THE DIFFERENCE BETWEEN ASSUMPTION-BASED ARGUMENTATION AND ABSTRACT +# ARGUMENTATION' +def get_semi_stable_extensions( + aba_framework: AssumptionBasedArgumentationFramework) -> \ + Set[FrozenSet[str]]: af = aba_framework.generate_af() com_ext = get_complete_extensions.get_complete_extensions(aba_framework) extension_reach = {} for ext in com_ext: extension_reach[ext] = set(ext.copy()) for arg in af.arguments: - if arg.premise.issubset(ext) and arg.conclusion not in aba_framework.assumptions: - conclusion_index = list(aba_framework.contraries.values()).index(arg.conclusion) - extension_reach[ext].add(list(aba_framework.contraries.keys())[conclusion_index]) + if arg.premise.issubset(ext) and \ + arg.conclusion not in aba_framework.assumptions: + conclusion_index = \ + list(aba_framework.contraries.values()).index( + arg.conclusion) + extension_reach[ext].add(list( + aba_framework.contraries.keys())[conclusion_index]) ss_ext = set() for ext1 in com_ext: is_semi_stable = True diff --git a/src/py_arg/assumption_based_argumentation/semantics/get_stable_extensions.py b/src/py_arg/assumption_based_argumentation/semantics/get_stable_extensions.py index ee2e02c..d0ffbc5 100644 --- a/src/py_arg/assumption_based_argumentation/semantics/get_stable_extensions.py +++ b/src/py_arg/assumption_based_argumentation/semantics/get_stable_extensions.py @@ -1,10 +1,14 @@ from typing import Set, FrozenSet -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -import py_arg.abstract_argumentation.semantics.get_stable_extensions as get_stable_extensions_af +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +import py_arg.abstract_argumentation.semantics.get_stable_extensions as \ + get_stable_extensions_af -def get_stable_extensions(aba_framework: AssumptionBasedArgumentationFramework) -> Set[FrozenSet[str]]: +def get_stable_extensions( + aba_framework: AssumptionBasedArgumentationFramework) -> \ + Set[FrozenSet[str]]: af = aba_framework.generate_af() af_extensions = get_stable_extensions_af.get_stable_extensions(af) aba_framework_extensions = set() diff --git a/src/py_arg/experiments/experiment_compute_grounded_labelling.py b/src/py_arg/experiments/experiment_compute_grounded_labelling.py index 104cdb1..9626177 100644 --- a/src/py_arg/experiments/experiment_compute_grounded_labelling.py +++ b/src/py_arg/experiments/experiment_compute_grounded_labelling.py @@ -1,46 +1,58 @@ import time -from py_arg.aspic.algorithms.justification.compute_all_literal_grounded_justification_status_fast import \ +from py_arg.aspic.algorithms.justification.\ + compute_all_literal_grounded_justification_status_fast import \ compute_all_literal_grounded_justification_status_fast -from py_arg.aspic.algorithms.justification.compute_all_literal_grounded_justification_status_naive import \ +from py_arg.aspic.algorithms.justification.\ + compute_all_literal_grounded_justification_status_naive import \ compute_all_literal_grounded_justification_status_naive -from py_arg.aspic.generators.argumentation_system_generators import \ +from py_arg.aspic.algorithms.justification.literal_labels import \ + LiteralLabels +from py_arg.aspic.generators.argumentation_system_generators.\ + layered_argumentation_system_generator import \ LayeredArgumentationSystemGenerator -from py_arg.aspic.generators.argumentation_theory_generators import \ +from py_arg.aspic.generators.argumentation_theory_generators.\ + argumentation_theory_generator import \ ArgumentationTheoryGenerator -from py_arg.aspic.algorithms.justification.literal_labels import LiteralLabels def instantiate_argumentation_theory_generator(): nr_of_literals = 8 nr_of_rules = 5 layered_argumentation_system_generator = \ - LayeredArgumentationSystemGenerator(nr_of_literals, nr_of_rules, - rule_antecedent_distribution={1: 2, 2: 1, 3: 1, 4: 1}, - literal_layer_distribution={0: 3, 1: 2, 2: 1, 3: 1, 4: 1}, - strict_rule_ratio=0.4) + LayeredArgumentationSystemGenerator( + nr_of_literals, nr_of_rules, + rule_antecedent_distribution={1: 2, 2: 1, 3: 1, 4: 1}, + literal_layer_distribution={0: 3, 1: 2, 2: 1, 3: 1, 4: 1}, + strict_rule_ratio=0.4) arg_sys = layered_argumentation_system_generator.generate() knowledge_literal_ratio = 0.3 axiom_knowledge_ratio = 0.5 - return ArgumentationTheoryGenerator(arg_sys, knowledge_literal_ratio=knowledge_literal_ratio, - axiom_knowledge_ratio=axiom_knowledge_ratio) + return ArgumentationTheoryGenerator( + arg_sys, knowledge_literal_ratio=knowledge_literal_ratio, + axiom_knowledge_ratio=axiom_knowledge_ratio) -def execute_grounded_labelling_experiment(argumentation_theory_generator: ArgumentationTheoryGenerator): +def execute_grounded_labelling_experiment( + argumentation_theory_generator: ArgumentationTheoryGenerator): for iteration in range(100): arg_theory = argumentation_theory_generator.generate() grounded_labelling_naive = grounded_labelling_fast = LiteralLabels({}) for i in range(1): start_time = time.time() - grounded_labelling_naive = compute_all_literal_grounded_justification_status_naive(arg_theory) + grounded_labelling_naive = \ + compute_all_literal_grounded_justification_status_naive( + arg_theory) end_time = time.time() grounded_labelling_naive_time = end_time - start_time print(f'Runtime naive: {grounded_labelling_naive_time}') for i in range(10): start_time = time.time() - grounded_labelling_fast = compute_all_literal_grounded_justification_status_fast(arg_theory) + grounded_labelling_fast = \ + compute_all_literal_grounded_justification_status_fast( + arg_theory) end_time = time.time() grounded_labelling_fast_time = end_time - start_time print(f'Runtime fast: {grounded_labelling_fast_time}') diff --git a/src/py_arg/experiments/experiment_generate_data_set_from_layered_argsys.py b/src/py_arg/experiments/experiment_generate_data_set_from_layered_argsys.py index 0a8182a..6a4f3f6 100644 --- a/src/py_arg/experiments/experiment_generate_data_set_from_layered_argsys.py +++ b/src/py_arg/experiments/experiment_generate_data_set_from_layered_argsys.py @@ -1,12 +1,16 @@ -from py_arg.aspic.generators.argumentation_system_generators import \ +from py_arg.aspic.generators.argumentation_system_generators.\ + layered_argumentation_system_generator import \ LayeredArgumentationSystemGenerator -from py_arg.incomplete_aspic.generators.incomplete_argumentation_theory_generator import \ +from py_arg.incomplete_aspic.generators.\ + incomplete_argumentation_theory_generator import \ IncompleteArgumentationTheoryGenerator -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_to_lp_file_writer import \ +from py_arg.incomplete_aspic.import_export.\ + incomplete_argumentation_theory_to_lp_file_writer import \ IncompleteArgumentationTheoryToLPFileWriter -def instantiate_incomplete_argumentation_theory_generator(nr_of_literals, nr_of_rules): +def instantiate_incomplete_argumentation_theory_generator( + nr_of_literals, nr_of_rules): rule_antecedent_distribution = {1: int(nr_of_rules / 3), 2: int(nr_of_rules / 3), 3: int(nr_of_rules / 9), @@ -22,19 +26,25 @@ def instantiate_incomplete_argumentation_theory_generator(nr_of_literals, nr_of_ literal_layer_distribution[4] = literals_left layered_argumentation_system_generator = \ - LayeredArgumentationSystemGenerator(nr_of_literals=nr_of_literals, - nr_of_rules=nr_of_rules, - rule_antecedent_distribution=rule_antecedent_distribution, - literal_layer_distribution=literal_layer_distribution, - strict_rule_ratio=0) + LayeredArgumentationSystemGenerator( + nr_of_literals=nr_of_literals, + nr_of_rules=nr_of_rules, + rule_antecedent_distribution=rule_antecedent_distribution, + literal_layer_distribution=literal_layer_distribution, + strict_rule_ratio=0) # Generate the argumentation system, and keep the "layers" of literals. - arg_sys, layered_language = layered_argumentation_system_generator.generate(return_layered_language=True, - add_rule_preferences=True) + arg_sys, layered_language = \ + layered_argumentation_system_generator.generate( + return_layered_language=True, add_rule_preferences=True) - # Generate an incomplete argumentation theory, where only literals on the first layer can be queryable. - positive_queryable_candidates = {arg_sys.language[str(literal).replace('-', '')] for literal in layered_language[0]} - topics = list({str(literal) for literal in layered_language[3] + layered_language[4]}) + # Generate an incomplete argumentation theory, where only literals on the + # first layer can be queryable. + positive_queryable_candidates = { + arg_sys.language[str(literal).replace('-', '')] + for literal in layered_language[0]} + topics = list({str(literal) + for literal in layered_language[3] + layered_language[4]}) return IncompleteArgumentationTheoryGenerator( argumentation_system=arg_sys, positive_queryable_candidates=list(positive_queryable_candidates), @@ -51,10 +61,13 @@ def instantiate_incomplete_argumentation_theory_generator(nr_of_literals, nr_of_ for rule_literal_ratio in rule_literal_ratios: rule_size = int(rule_literal_ratio * literal_size) for arg_sys_nr in range(25): - generator, topic_literals = instantiate_incomplete_argumentation_theory_generator(literal_size, rule_size) + generator, topic_literals = \ + instantiate_incomplete_argumentation_theory_generator( + literal_size, rule_size) for iat_nr in range(25): iat = generator.generate() IncompleteArgumentationTheoryToLPFileWriter().write( incomplete_argumentation_theory=iat, - file_name=f'DS2_{str(literal_size)}L{str(rule_size)}R_AS{str(arg_sys_nr)}_IAT{str(iat_nr)}.pl', + file_name=f'DS2_{str(literal_size)}L{str(rule_size)}' + f'R_AS{str(arg_sys_nr)}_IAT{str(iat_nr)}.pl', topic_literals=topic_literals) diff --git a/src/py_arg/experiments/experiment_generate_data_set_from_police_argsys.py b/src/py_arg/experiments/experiment_generate_data_set_from_police_argsys.py index fc8d292..5066a1f 100644 --- a/src/py_arg/experiments/experiment_generate_data_set_from_police_argsys.py +++ b/src/py_arg/experiments/experiment_generate_data_set_from_police_argsys.py @@ -1,15 +1,18 @@ import random from py_arg.experiments.utils import path_to_resources -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_from_xlsx_reader import \ +from py_arg.incomplete_aspic.import_export.\ + incomplete_argumentation_theory_from_xlsx_reader import \ IncompleteArgumentationTheoryFromXLSXFileReader # Load argumentation system and queryables for the fraud system. -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_to_lp_file_writer import \ +from py_arg.incomplete_aspic.import_export.\ + incomplete_argumentation_theory_to_lp_file_writer import \ IncompleteArgumentationTheoryToLPFileWriter asr = IncompleteArgumentationTheoryFromXLSXFileReader() -iat = asr.read_from_xlsx_file(path_to_resources() / 'Police_Intake_System_Anon.xlsx') +iat = asr.read_from_xlsx_file(path_to_resources() / + 'Police_Intake_System_Anon.xlsx') topic_literals = [ 'FraudArticle326', @@ -24,7 +27,7 @@ # Export IAT with empty knowledge base IncompleteArgumentationTheoryToLPFileWriter().write( incomplete_argumentation_theory=iat, - file_name=f'0Knr0.pl', + file_name='0Knr0.pl', topic_literals=topic_literals) # Generate knowledge bases in various sizes @@ -34,12 +37,15 @@ knowledge_candidates = iat.queryables.copy() extra_knowledge_required = knowledge_base_size while extra_knowledge_required > 0: - knowledge_base_candidates = [q for q in iat.queryables - if all([not k.is_contrary_or_contradictory_of(q) and k != q - for k in knowledge_base])] + knowledge_base_candidates = [ + q for q in iat.queryables + if all([not k.is_contrary_or_contradictory_of(q) and k != q + for k in knowledge_base])] if not knowledge_base_candidates: - raise ValueError(f'Could not make knowledge base of size {str(knowledge_base)} for ' - f'argumentation system.') + raise ValueError( + f'Could not make knowledge base of ' + f'size {str(knowledge_base)} for ' + f'argumentation system.') new_knowledge_base_item = random.choice(knowledge_base_candidates) knowledge_base.append(new_knowledge_base_item) extra_knowledge_required -= 1 diff --git a/src/py_arg/experiments/experiment_generate_incomplete_argumentation_theory.py b/src/py_arg/experiments/experiment_generate_incomplete_argumentation_theory.py index 700ebdd..c3648af 100644 --- a/src/py_arg/experiments/experiment_generate_incomplete_argumentation_theory.py +++ b/src/py_arg/experiments/experiment_generate_incomplete_argumentation_theory.py @@ -1,36 +1,45 @@ -from py_arg.aspic.generators.argumentation_system_generators import \ +from py_arg.aspic.generators.argumentation_system_generators.\ + layered_argumentation_system_generator import \ LayeredArgumentationSystemGenerator -from py_arg.incomplete_aspic.generators.incomplete_argumentation_theory_generator import \ +from py_arg.incomplete_aspic.generators.\ + incomplete_argumentation_theory_generator import \ IncompleteArgumentationTheoryGenerator -def instantiate_incomplete_argumentation_theory_generator(nr_of_literals, nr_of_rules): - rule_antecedent_distribution = {1: int(nr_of_rules / 3), - 2: int(nr_of_rules / 3), - 3: int(nr_of_rules / 9), - 4: int(nr_of_rules / 9)} - rules_left = nr_of_rules - sum(rule_antecedent_distribution.values()) +def instantiate_incomplete_argumentation_theory_generator( + nr_literals, nr_rules): + rule_antecedent_distribution = {1: int(nr_rules / 3), + 2: int(nr_rules / 3), + 3: int(nr_rules / 9), + 4: int(nr_rules / 9)} + rules_left = nr_rules - sum(rule_antecedent_distribution.values()) rule_antecedent_distribution[5] = rules_left - literal_layer_distribution = {0: 2 * nr_of_literals / 3, - 1: nr_of_literals / 10, - 2: nr_of_literals / 10, - 3: nr_of_literals / 10} - literals_left = nr_of_literals - sum(literal_layer_distribution.values()) + literal_layer_distribution = {0: 2 * nr_literals / 3, + 1: nr_literals / 10, + 2: nr_literals / 10, + 3: nr_literals / 10} + literals_left = nr_literals - sum(literal_layer_distribution.values()) literal_layer_distribution[4] = literals_left layered_argumentation_system_generator = \ - LayeredArgumentationSystemGenerator(nr_of_literals=nr_of_literals, - nr_of_rules=nr_of_rules, - rule_antecedent_distribution=rule_antecedent_distribution, - literal_layer_distribution=literal_layer_distribution, - strict_rule_ratio=0) + LayeredArgumentationSystemGenerator( + nr_of_literals=nr_literals, + nr_of_rules=nr_rules, + rule_antecedent_distribution=rule_antecedent_distribution, + literal_layer_distribution=literal_layer_distribution, + strict_rule_ratio=0) # Generate the argumentation system, and keep the "layers" of literals. - arg_sys, layered_language = layered_argumentation_system_generator.generate(return_layered_language=True) - - # Generate an incomplete argumentation theory, where only literals on the first layer can be queryable. - positive_queryable_candidates = {arg_sys.language[str(literal).replace('-', '')] for literal in layered_language[0]} + arg_sys, layered_language = \ + layered_argumentation_system_generator.generate( + return_layered_language=True) + + # Generate an incomplete argumentation theory, where only literals on the + # first layer can be queryable. + positive_queryable_candidates = { + arg_sys.language[str(literal).replace('-', '')] + for literal in layered_language[0]} return IncompleteArgumentationTheoryGenerator( argumentation_system=arg_sys, positive_queryable_candidates=list(positive_queryable_candidates), @@ -41,8 +50,11 @@ def instantiate_incomplete_argumentation_theory_generator(nr_of_literals, nr_of_ if __name__ == "__main__": - for nr_of_literals in [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150]: - for nr_of_rules in [nr_of_literals / 2, nr_of_literals, 3 * nr_of_literals / 2]: - generator = instantiate_incomplete_argumentation_theory_generator(nr_of_literals, nr_of_rules) + for nr_of_literals in [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, + 130, 140, 150]: + for nr_of_rules in [nr_of_literals / 2, nr_of_literals, + 3 * nr_of_literals / 2]: + generator = instantiate_incomplete_argumentation_theory_generator( + nr_of_literals, nr_of_rules) for instance in range(50): iaf = generator.generate() diff --git a/src/py_arg/experiments/experiment_run_stability_algorithm.py b/src/py_arg/experiments/experiment_run_stability_algorithm.py index be8bc36..a70a991 100644 --- a/src/py_arg/experiments/experiment_run_stability_algorithm.py +++ b/src/py_arg/experiments/experiment_run_stability_algorithm.py @@ -2,19 +2,24 @@ import pathlib from typing import Tuple -from py_arg.incomplete_aspic.algorithms.stability import StabilityLabeler -from py_arg.incomplete_aspic.algorithms.stability.stability_labels import StabilityLabels +from py_arg.incomplete_aspic.algorithms.stability.stability_labeler import \ + StabilityLabeler +from py_arg.incomplete_aspic.algorithms.stability.stability_labels import \ + StabilityLabels from py_arg.aspic.classes.argumentation_system import ArgumentationSystem -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_from_lp_file_reader import \ +from py_arg.incomplete_aspic.import_export.\ + incomplete_argumentation_theory_from_lp_file_reader import \ IncompleteArgumentationTheoryFromLPFileReader import datetime -def _run_stability_approximation_algorithm(lp_file_name: str) -> Tuple[StabilityLabels, ArgumentationSystem]: +def _run_stability_approximation_algorithm(lp_file_name: str) -> \ + Tuple[StabilityLabels, ArgumentationSystem]: start_time = datetime.datetime.now() iat_lp_reader = IncompleteArgumentationTheoryFromLPFileReader() - iat = iat_lp_reader.read_from_lp_file(str(pathlib.Path('generated_data') / lp_file_name)) + iat = iat_lp_reader.read_from_lp_file( + str(pathlib.Path('generated_data') / lp_file_name)) stability_labeler = StabilityLabeler() algorithm_start_time = datetime.datetime.now() result = stability_labeler.label(iat), iat.argumentation_system @@ -23,20 +28,25 @@ def _run_stability_approximation_algorithm(lp_file_name: str) -> Tuple[Stability def get_literal_is_stable(lp_file_name: str, literal_str: str): - stability_labels, arg_sys = _run_stability_approximation_algorithm(lp_file_name) - if stability_labels.literal_labeling[arg_sys.language[literal_str]].is_stable: + stability_labels, arg_sys = _run_stability_approximation_algorithm( + lp_file_name) + if stability_labels.literal_labeling[arg_sys.language[ + literal_str]].is_stable: print('YES') else: print('NO') def get_literal_stability(lp_file_name: str, literal_str: str): - stability_labels, arg_sys = _run_stability_approximation_algorithm(lp_file_name) - print(stability_labels.literal_labeling[arg_sys.language[literal_str]].stability_str) + stability_labels, arg_sys = _run_stability_approximation_algorithm( + lp_file_name) + print(stability_labels.literal_labeling[arg_sys.language[ + literal_str]].stability_str) def get_all_literals_is_stable(lp_file_name: str): - stability_labels, arg_sys = _run_stability_approximation_algorithm(lp_file_name) + stability_labels, arg_sys = _run_stability_approximation_algorithm( + lp_file_name) for literal in arg_sys.language.values(): if stability_labels.literal_labeling[literal].is_stable: print(literal.s1 + ' ' + 'YES') @@ -45,9 +55,11 @@ def get_all_literals_is_stable(lp_file_name: str): def get_all_literals_stability(lp_file_name: str): - (stability_labels, arg_sys), (st, st2, et) = _run_stability_approximation_algorithm(lp_file_name) + (stability_labels, arg_sys), (st, st2, et) = \ + _run_stability_approximation_algorithm(lp_file_name) for literal in arg_sys.language.values(): - print(literal.s1 + ' ' + stability_labels.literal_labeling[literal].stability_str) + print(literal.s1 + ' ' + stability_labels.literal_labeling[ + literal].stability_str) return st, st2, et @@ -57,7 +69,9 @@ def get_all_literals_stability(lp_file_name: str): filename = entry.name st, st2, et = get_all_literals_stability(filename) with open('results.csv', 'a') as writer: - print(filename + ' ' + str((et - st).total_seconds() * 1000) + ' ' + - str((et - st2).total_seconds() * 1000)) - writer.write(filename + ';' + str((et - st).total_seconds() * 1000) + ';' + + print(filename + ' ' + + str((et - st).total_seconds() * 1000) + ' ' + + str((et - st2).total_seconds() * 1000)) + writer.write(filename + ';' + + str((et - st).total_seconds() * 1000) + ';' + str((et - st2).total_seconds() * 1000) + '\n') diff --git a/src/py_arg/experiments/utils.py b/src/py_arg/experiments/utils.py index 30f6556..65ae301 100644 --- a/src/py_arg/experiments/utils.py +++ b/src/py_arg/experiments/utils.py @@ -2,4 +2,5 @@ def path_to_resources(): - return pathlib.Path(__file__).parent.parent.parent / 'py_arg_tests' / 'resources' + return pathlib.Path(__file__).parent.parent.parent / \ + 'py_arg_tests' / 'resources' diff --git a/src/py_arg/incomplete_argumentation_frameworks/classes/incomplete_argumentation_framework.py b/src/py_arg/incomplete_argumentation_frameworks/classes/incomplete_argumentation_framework.py index b79a7a8..c95e3c4 100644 --- a/src/py_arg/incomplete_argumentation_frameworks/classes/incomplete_argumentation_framework.py +++ b/src/py_arg/incomplete_argumentation_frameworks/classes/incomplete_argumentation_framework.py @@ -1,15 +1,18 @@ import itertools from typing import Optional, List, Dict -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat class IncompleteArgumentationFramework: """ - An incomplete argumentation framework (IAF) is an extension to abstract argumentation frameworks - in which the sets of arguments and defeats are each split in two disjoint parts: a certain part + An incomplete argumentation framework (IAF) is an extension to abstract + argumentation frameworks + in which the sets of arguments and defeats are each split in two disjoint + parts: a certain part and an uncertain part. """ def __init__(self, name: str = '', @@ -22,14 +25,18 @@ def __init__(self, name: str = '', if arguments is None: self._arguments = {} else: - self._arguments = {argument.name: argument for argument in arguments} + self._arguments = {argument.name: argument + for argument in arguments} if uncertain_arguments is None: self._uncertain_arguments = {} else: - if any(uncertain_argument in arguments for uncertain_argument in uncertain_arguments): - raise ValueError('Argument cannot be both certain and uncertain.') - self._uncertain_arguments = {argument.name: argument for argument in uncertain_arguments} + if any(uncertain_argument in arguments + for uncertain_argument in uncertain_arguments): + raise ValueError('Argument cannot be both certain and ' + 'uncertain.') + self._uncertain_arguments = {argument.name: argument + for argument in uncertain_arguments} if defeats is None: self._defeats = [] @@ -43,13 +50,16 @@ def __init__(self, name: str = '', for defeat in self._defeats + self._uncertain_defeats: if defeat.from_argument.name in self._arguments.keys(): - defeat_from_argument = self._arguments[defeat.from_argument.name] + defeat_from_argument = self._arguments[ + defeat.from_argument.name] else: - defeat_from_argument = self._uncertain_arguments[defeat.from_argument.name] + defeat_from_argument = self._uncertain_arguments[ + defeat.from_argument.name] if defeat.to_argument.name in self._arguments.keys(): defeat_to_argument = self._arguments[defeat.to_argument.name] else: - defeat_to_argument = self._uncertain_arguments[defeat.to_argument.name] + defeat_to_argument = self._uncertain_arguments[ + defeat.to_argument.name] defeat_from_argument.add_outgoing_defeat(defeat.to_argument) defeat_to_argument.add_ingoing_defeat(defeat.from_argument) @@ -61,10 +71,18 @@ def __eq__(self, other): self.uncertain_defeats == other.uncertain_defeats def __repr__(self): - return '( [' + ', '.join(argument_key for argument_key in self.arguments.keys()) + \ - '], [' + ', '.join(argument_key for argument_key in self.uncertain_arguments.keys()) + \ - '], [' + ', '.join(defeat.__repr__() for defeat in self.defeats) + \ - '], [' + ', '.join(defeat.__repr__() for defeat in self.uncertain_defeats) + '] )' + return '( [' + ', '.join( + argument_key + for argument_key in self.arguments.keys()) + \ + '], [' + ', '.join( + argument_key + for argument_key in self.uncertain_arguments.keys()) + \ + '], [' + ', '.join( + defeat.__repr__() + for defeat in self.defeats) + \ + '], [' + ', '.join( + defeat.__repr__() + for defeat in self.uncertain_defeats) + '] )' @property def arguments(self) -> Dict[str, Argument]: @@ -97,27 +115,34 @@ def uncertain_defeats(self) -> List[Defeat]: @property def certain_projection(self) -> AbstractArgumentationFramework: """ - The certain projection consists of all certain arguments and all certain defeats between two + The certain projection consists of all certain arguments and all + certain defeats between two certain arguments. """ arguments = list(self._arguments.values()) - return AbstractArgumentationFramework(arguments=arguments, - defeats=[defeat for defeat in self._defeats - if defeat.from_argument in arguments and - defeat.to_argument in arguments]) + return AbstractArgumentationFramework( + arguments=arguments, + defeats=[defeat for defeat in self._defeats + if defeat.from_argument in arguments and + defeat.to_argument in arguments]) def get_all_completions(self) -> List[AbstractArgumentationFramework]: """ - The set of completions consists of all abstract AFs that can be obtained by resolving the + The set of completions consists of all abstract AFs that can be + obtained by resolving the uncertainties of the IAF. """ def powerset(s): - return itertools.chain.from_iterable(itertools.combinations(s, r) for r in range(len(s) + 1)) + return itertools.chain.from_iterable(itertools.combinations(s, r) + for r in range(len(s) + 1)) - remaining_uncertain_argument_options = powerset(self.uncertain_arguments.values()) + remaining_uncertain_argument_options = powerset( + self.uncertain_arguments.values()) remaining_uncertain_defeat_options = powerset(self.uncertain_defeats) - combined_options = itertools.product(remaining_uncertain_argument_options, remaining_uncertain_defeat_options) + combined_options = itertools.product( + remaining_uncertain_argument_options, + remaining_uncertain_defeat_options) result = [] arguments = list(self.arguments.values()) @@ -127,21 +152,25 @@ def powerset(s): completion = AbstractArgumentationFramework( arguments=all_arguments, defeats=[defeat for defeat in all_defeats - if defeat.to_argument in all_arguments and defeat.from_argument in all_arguments] + if defeat.to_argument in all_arguments and + defeat.from_argument in all_arguments] ) if completion not in result: result.append(completion) return result - def get_all_partial_completions(self) -> List['IncompleteArgumentationFramework']: + def get_all_partial_completions(self) -> \ + List['IncompleteArgumentationFramework']: """ - The set of partial completions consists of all IAFs that can be obtained by resolving some of the + The set of partial completions consists of all IAFs that can be + obtained by resolving some of the uncertainties of the IAF, as well as the original IAF itself. """ def powerset(s): - return itertools.chain.from_iterable(itertools.combinations(s, r) for r in range(len(s) + 1)) + return itertools.chain.from_iterable(itertools.combinations(s, r) + for r in range(len(s) + 1)) # Remember the old values. old_certain_arguments = list(self.arguments.values()) @@ -150,41 +179,60 @@ def powerset(s): old_uncertain_defeats = self.uncertain_defeats # Construct all possible combinations of uncertain elements. - remaining_uncertain_argument_options = powerset(old_uncertain_arguments) + remaining_uncertain_argument_options = \ + powerset(old_uncertain_arguments) remaining_uncertain_defeat_options = powerset(old_uncertain_defeats) - combined_options = itertools.product(remaining_uncertain_argument_options, remaining_uncertain_defeat_options) + combined_options = itertools.product( + remaining_uncertain_argument_options, + remaining_uncertain_defeat_options) result = [] for uncertain_arguments, uncertain_defeats in combined_options: - # This is a particular guess for the uncertain elements that will remain (as either certain or uncertain + # This is a particular guess for the uncertain elements that + # will remain (as either certain or uncertain # arguments) in the partial completion. - # Now construct all possible combinations of these remaining elements. + # Now construct all possible combinations of these remaining + # elements. new_certain_argument_options = powerset(uncertain_arguments) new_certain_defeat_options = powerset(uncertain_defeats) - new_combined_options = itertools.product(new_certain_argument_options, new_certain_defeat_options) + new_combined_options = itertools.product( + new_certain_argument_options, new_certain_defeat_options) - for new_certain_arguments, new_certain_defeats in new_combined_options: - # This is a particular guess for the elements that will become the new certain elements in the partial + for new_certain_arguments, new_certain_defeats in \ + new_combined_options: + # This is a particular guess for the elements that will become + # the new certain elements in the partial # completion. - all_new_certain_arguments = sorted(old_certain_arguments + list(new_certain_arguments)) - all_new_certain_defeats = sorted(old_certain_defeats + list(new_certain_defeats)) - new_uncertain_arguments = sorted([arg for arg in uncertain_arguments - if arg not in new_certain_arguments]) - new_uncertain_defeats = sorted([defeat for defeat in uncertain_defeats - if defeat not in new_certain_defeats]) - - all_new_certain_or_uncertain_arguments = all_new_certain_arguments + new_uncertain_arguments + all_new_certain_arguments = \ + sorted(old_certain_arguments + list(new_certain_arguments)) + all_new_certain_defeats = \ + sorted(old_certain_defeats + list(new_certain_defeats)) + new_uncertain_arguments = \ + sorted([arg for arg in uncertain_arguments + if arg not in new_certain_arguments]) + new_uncertain_defeats = \ + sorted([defeat for defeat in uncertain_defeats + if defeat not in new_certain_defeats]) + + all_new_certain_or_uncertain_arguments = \ + all_new_certain_arguments + new_uncertain_arguments partial_completion = IncompleteArgumentationFramework( arguments=all_new_certain_arguments, uncertain_arguments=new_uncertain_arguments, defeats=[defeat for defeat in all_new_certain_defeats - if defeat.to_argument in all_new_certain_or_uncertain_arguments and - defeat.from_argument in all_new_certain_or_uncertain_arguments], - uncertain_defeats=[defeat for defeat in new_uncertain_defeats - if defeat.to_argument in all_new_certain_or_uncertain_arguments and - defeat.from_argument in all_new_certain_or_uncertain_arguments] + if defeat.to_argument in + all_new_certain_or_uncertain_arguments and + defeat.from_argument in + all_new_certain_or_uncertain_arguments], + uncertain_defeats=[ + defeat + for defeat in new_uncertain_defeats + if defeat.to_argument in + all_new_certain_or_uncertain_arguments and + defeat.from_argument in + all_new_certain_or_uncertain_arguments] ) if partial_completion not in result: result.append(partial_completion) diff --git a/src/py_arg/incomplete_aspic/algorithms/relevance/relevance_lister.py b/src/py_arg/incomplete_aspic/algorithms/relevance/relevance_lister.py index c0e6997..28fa3b0 100644 --- a/src/py_arg/incomplete_aspic/algorithms/relevance/relevance_lister.py +++ b/src/py_arg/incomplete_aspic/algorithms/relevance/relevance_lister.py @@ -1,7 +1,9 @@ -from py_arg.incomplete_aspic.algorithms.stability.stability_labels import StabilityLabels from py_arg.aspic.classes.literal import Literal from py_arg.aspic.classes.rule import Rule -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.incomplete_aspic.algorithms.stability.stability_labels import \ + StabilityLabels +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory class FourBoolRelevanceLister: @@ -18,8 +20,13 @@ def __init__(self): self.four_bool_labels = None self.relevance_visited = None - def update(self, incomplete_argumentation_theory: IncompleteArgumentationTheory, four_bool_labels: StabilityLabels): - literals = incomplete_argumentation_theory.argumentation_system.language.values() + def update( + self, + incomplete_argumentation_theory: IncompleteArgumentationTheory, + four_bool_labels: StabilityLabels): + literals = \ + incomplete_argumentation_theory.\ + argumentation_system.language.values() rules = incomplete_argumentation_theory.argumentation_system.rules self.u_relevant_literal = {literal: set() for literal in literals} @@ -33,21 +40,28 @@ def update(self, incomplete_argumentation_theory: IncompleteArgumentationTheory, self.four_bool_labels = four_bool_labels - # Start by collecting relevant observables of leaves (or-nodes for which there is no rule) and observables + # Start by collecting relevant observables of leaves (or-nodes for + # which there is no rule) and observables nodes_to_update_relevancy_round = \ [literal for literal in literals - if not literal.children or incomplete_argumentation_theory.is_queryable(literal)] + if not literal.children or + incomplete_argumentation_theory.is_queryable(literal)] while nodes_to_update_relevancy_round: # Update literals new_rules_to_update_relevancy = set() for literal in nodes_to_update_relevancy_round: - old_relevancy = self._get_current_relevancy_for_literal(literal) - self._update_relevant_literals_for_literal(incomplete_argumentation_theory, - literal, incomplete_argumentation_theory.knowledge_base) - new_relevancy = self._get_current_relevancy_for_literal(literal) + old_relevancy = self._get_current_relevancy_for_literal( + literal) + self._update_relevant_literals_for_literal( + incomplete_argumentation_theory, + literal, incomplete_argumentation_theory.knowledge_base) + new_relevancy = self._get_current_relevancy_for_literal( + literal) if old_relevancy != new_relevancy: - new_rules_to_update_relevancy = new_rules_to_update_relevancy | set(literal.parents) + new_rules_to_update_relevancy = \ + new_rules_to_update_relevancy | \ + set(literal.parents) nodes_to_update_relevancy_round = new_rules_to_update_relevancy # Update rules @@ -57,20 +71,24 @@ def update(self, incomplete_argumentation_theory: IncompleteArgumentationTheory, self._update_relevant_literals_for_rule(rule) new_relevancy = self._get_current_relevancy_for_rule(rule) if old_relevancy != new_relevancy: - new_literals_to_update_relevancy = new_literals_to_update_relevancy | set( - [rule.consequent] + list(rule.consequent.contraries_and_contradictories)) + new_literals_to_update_relevancy = \ + new_literals_to_update_relevancy | \ + set([rule.consequent] + list( + rule.consequent.contraries_and_contradictories)) nodes_to_update_relevancy_round = new_literals_to_update_relevancy for literal in literals: - self.relevance_list[literal] = self._get_current_relevancy_for_literal(literal) + self.relevance_list[ + literal] = self._get_current_relevancy_for_literal(literal) def _get_current_relevancy_for_literal(self, literal: Literal): - return self.u_relevant_literal[literal] | self.d_relevant_literal[literal] | \ - self.o_relevant_literal[literal] | self.b_relevant_literal[literal] + return self.u_relevant_literal[literal] | self.d_relevant_literal[ + literal] | \ + self.o_relevant_literal[literal] | self.b_relevant_literal[literal] def _get_current_relevancy_for_rule(self, rule: Rule): return self.u_relevant_rule[rule] | self.d_relevant_rule[rule] | \ - self.o_relevant_rule[rule] | self.b_relevant_rule[rule] + self.o_relevant_rule[rule] | self.b_relevant_rule[rule] def _lit_label(self, literal: Literal): return self.four_bool_labels.literal_labeling[literal] @@ -78,12 +96,18 @@ def _lit_label(self, literal: Literal): def _rule_label(self, rule: Rule): return self.four_bool_labels.rule_labeling[rule] - def _update_relevant_literals_for_literal(self, incomplete_argumentation_theory: IncompleteArgumentationTheory, - literal: Literal, knowledge_base): - self._update_relevant_literals_u_literal(incomplete_argumentation_theory, knowledge_base, literal) - self._update_relevant_literals_d_literal(incomplete_argumentation_theory, knowledge_base, literal) - self._update_relevant_literals_o_literal(incomplete_argumentation_theory, knowledge_base, literal) - self._update_relevant_literals_b_literal(incomplete_argumentation_theory, literal) + def _update_relevant_literals_for_literal( + self, + incomplete_argumentation_theory: IncompleteArgumentationTheory, + literal: Literal, knowledge_base): + self._update_relevant_literals_u_literal( + incomplete_argumentation_theory, knowledge_base, literal) + self._update_relevant_literals_d_literal( + incomplete_argumentation_theory, knowledge_base, literal) + self._update_relevant_literals_o_literal( + incomplete_argumentation_theory, knowledge_base, literal) + self._update_relevant_literals_b_literal( + incomplete_argumentation_theory, literal) def _update_relevant_literals_for_rule(self, rule: Rule): self._update_relevant_literals_u_rule(rule) @@ -91,13 +115,17 @@ def _update_relevant_literals_for_rule(self, rule: Rule): self._update_relevant_literals_o_rule(rule) self._update_relevant_literals_b_rule(rule) - def _update_relevant_literals_u_literal(self, incomplete_argumentation_theory, knowledge_base, literal): + def _update_relevant_literals_u_literal(self, + incomplete_argumentation_theory, + knowledge_base, literal): u_relevant = set() if self._lit_label(literal).unsatisfiable: if incomplete_argumentation_theory.is_queryable(literal): - if literal not in knowledge_base and all([contrary not in knowledge_base - for contrary in literal.contraries_and_contradictories]): + if literal not in knowledge_base and all( + [contrary not in knowledge_base + for contrary in + literal.contraries_and_contradictories]): u_relevant.add(literal) for rule in literal.children: @@ -106,39 +134,53 @@ def _update_relevant_literals_u_literal(self, incomplete_argumentation_theory, k self.u_relevant_literal[literal] = u_relevant - def _update_relevant_literals_d_literal(self, incomplete_argumentation_theory, knowledge_base, literal): + def _update_relevant_literals_d_literal(self, + incomplete_argumentation_theory, + knowledge_base, literal): d_relevant = set() if self._lit_label(literal).defended: if incomplete_argumentation_theory.is_queryable(literal): if literal not in knowledge_base and \ - all([contrary not in knowledge_base for contrary in literal.contraries_and_contradictories]): + all([contrary not in knowledge_base for contrary in + literal.contraries_and_contradictories]): for contrary in literal.contraries_and_contradictories: - if all([contrary_contrary not in knowledge_base for contrary_contrary in contrary.contraries_and_contradictories]): + if all([contrary_contrary not in knowledge_base for + contrary_contrary in + contrary.contraries_and_contradictories]): d_relevant.add(contrary) else: - if all([self._rule_label(rule).unsatisfiable or self._rule_label(rule).out + if all([self._rule_label( + rule).unsatisfiable or self._rule_label(rule).out or self._rule_label(rule).blocked for rule in literal.children]): for rule in literal.children: if self._rule_label(rule).defended: - d_relevant = d_relevant | self.d_relevant_rule[rule] + d_relevant = d_relevant | self.d_relevant_rule[ + rule] for contrary in literal.contraries_and_contradictories: for contrary_rule in contrary.children: - if self._rule_label(contrary_rule).defended or self._rule_label(contrary_rule).blocked: + if self._rule_label( + contrary_rule).defended or self._rule_label( + contrary_rule).blocked: if self._rule_label(contrary_rule).unsatisfiable: - d_relevant = d_relevant | self.u_relevant_rule[contrary_rule] + d_relevant = d_relevant | self.u_relevant_rule[ + contrary_rule] if self._rule_label(contrary_rule).out: - d_relevant = d_relevant | self.o_relevant_rule[contrary_rule] + d_relevant = d_relevant | self.o_relevant_rule[ + contrary_rule] self.d_relevant_literal[literal] = d_relevant - def _update_relevant_literals_o_literal(self, incomplete_argumentation_theory, knowledge_base, literal): + def _update_relevant_literals_o_literal(self, + incomplete_argumentation_theory, + knowledge_base, literal): o_relevant = set() if self._lit_label(literal).out: - if all([self._rule_label(rule).unsatisfiable for rule in literal.children]): + if all([self._rule_label(rule).unsatisfiable for rule in + literal.children]): for rule in literal.children: if self._rule_label(rule).defended: o_relevant = o_relevant | self.d_relevant_rule[rule] @@ -148,64 +190,88 @@ def _update_relevant_literals_o_literal(self, incomplete_argumentation_theory, k o_relevant = o_relevant | self.b_relevant_rule[rule] if incomplete_argumentation_theory.is_queryable(literal): - if literal not in knowledge_base and all([contrary not in knowledge_base - for contrary in literal.contraries_and_contradictories]): + if literal not in knowledge_base and all( + [contrary not in knowledge_base + for contrary in + literal.contraries_and_contradictories]): o_relevant.add(literal) else: - if all([self._rule_label(rule).unsatisfiable or self._rule_label(rule).defended + if all([self._rule_label( + rule).unsatisfiable or self._rule_label(rule).defended or self._rule_label(rule).blocked for rule in literal.children]): for rule in literal.children: o_relevant = o_relevant | self.o_relevant_rule[rule] for rule in literal.children: - if self._rule_label(rule).defended or self._rule_label(rule).blocked: + if self._rule_label(rule).defended or self._rule_label( + rule).blocked: if self._rule_label(rule).unsatisfiable: - o_relevant = o_relevant | self.u_relevant_rule[rule] + o_relevant = o_relevant | self.u_relevant_rule[ + rule] if self._rule_label(rule).out: - o_relevant = o_relevant | self.o_relevant_rule[rule] + o_relevant = o_relevant | self.o_relevant_rule[ + rule] self.o_relevant_literal[literal] = o_relevant - def _update_relevant_literals_b_literal(self, incomplete_argumentation_theory, literal): + def _update_relevant_literals_b_literal(self, + incomplete_argumentation_theory, + literal): b_relevant = set() - if self._lit_label(literal).blocked and not incomplete_argumentation_theory.is_queryable(literal): - if all([self._rule_label(rule).unsatisfiable or self._rule_label(rule).out for rule in literal.children]): + if self._lit_label( + literal).blocked and \ + not incomplete_argumentation_theory.is_queryable( + literal): + if all([self._rule_label(rule).unsatisfiable or self._rule_label( + rule).out for rule in literal.children]): for rule in literal.children: if self._rule_label(rule).defended: b_relevant = b_relevant | self.d_relevant_rule[rule] if self._rule_label(rule).blocked: b_relevant = b_relevant | self.b_relevant_rule[rule] - if all([self._rule_label(contrary_rule).unsatisfiable or self._rule_label(contrary_rule).out - for contrary in literal.contraries_and_contradictories for contrary_rule in contrary.children]): - if all([self._rule_label(rule).unsatisfiable or self._rule_label(rule).defended + if all([self._rule_label( + contrary_rule).unsatisfiable or self._rule_label( + contrary_rule).out + for contrary in literal.contraries_and_contradictories for + contrary_rule in contrary.children]): + if all([self._rule_label( + rule).unsatisfiable or self._rule_label(rule).defended or self._rule_label(rule).out for rule in literal.children]): for rule in literal.children: if self._rule_label(rule).blocked: - b_relevant = b_relevant | self.b_relevant_rule[rule] + b_relevant = b_relevant | self.b_relevant_rule[ + rule] for contrary in literal.contraries_and_contradictories: for contrary_rule in contrary.children: if self._rule_label(contrary_rule).defended: - b_relevant = b_relevant | self.d_relevant_rule[contrary_rule] + b_relevant = b_relevant | self.d_relevant_rule[ + contrary_rule] if self._rule_label(contrary_rule).blocked: - b_relevant = b_relevant | self.b_relevant_rule[contrary_rule] + b_relevant = b_relevant | self.b_relevant_rule[ + contrary_rule] for rule in literal.children: if self._rule_label(rule).defended: if self._rule_label(rule).unsatisfiable: - b_relevant = b_relevant | self.u_relevant_rule[rule] + b_relevant = b_relevant | self.u_relevant_rule[ + rule] if self._rule_label(rule).out: - b_relevant = b_relevant | self.o_relevant_rule[rule] + b_relevant = b_relevant | self.o_relevant_rule[ + rule] if self._rule_label(rule).blocked: - b_relevant = b_relevant | self.b_relevant_rule[rule] + b_relevant = b_relevant | self.b_relevant_rule[ + rule] for contrary in literal.contraries_and_contradictories: for contrary_rule in contrary.children: if self._rule_label(contrary_rule).defended: - b_relevant = b_relevant | self.d_relevant_rule[contrary_rule] + b_relevant = b_relevant | self.d_relevant_rule[ + contrary_rule] if self._rule_label(contrary_rule).blocked: - b_relevant = b_relevant | self.b_relevant_rule[contrary_rule] + b_relevant = b_relevant | self.b_relevant_rule[ + contrary_rule] self.b_relevant_literal[literal] = b_relevant @@ -213,7 +279,8 @@ def _update_relevant_literals_u_rule(self, rule): u_relevant = set() if self._rule_label(rule).unsatisfiable and \ - all([self._lit_label(literal).defended or self._lit_label(literal).out + all([self._lit_label(literal).defended or self._lit_label( + literal).out or self._lit_label(literal).blocked for literal in rule.antecedents]): for literal in rule.antecedents: @@ -236,21 +303,26 @@ def _update_relevant_literals_o_rule(self, rule): o_relevant = set() if self._rule_label(rule).out: - if all([self._lit_label(literal).unsatisfiable or self._lit_label(literal).defended + if all([self._lit_label(literal).unsatisfiable or self._lit_label( + literal).defended or self._lit_label(literal).blocked for literal in rule.antecedents]): for literal in rule.antecedents: if self._lit_label(literal).out: - o_relevant = o_relevant | self.o_relevant_literal[literal] + o_relevant = o_relevant | self.o_relevant_literal[ + literal] for literal in rule.antecedents: if self._lit_label(literal).unsatisfiable: if self._lit_label(literal).defended: - o_relevant = o_relevant | self.d_relevant_literal[literal] + o_relevant = o_relevant | self.d_relevant_literal[ + literal] if self._lit_label(literal).out: - o_relevant = o_relevant | self.o_relevant_literal[literal] + o_relevant = o_relevant | self.o_relevant_literal[ + literal] if self._lit_label(literal).blocked: - o_relevant = o_relevant | self.b_relevant_literal[literal] + o_relevant = o_relevant | self.b_relevant_literal[ + literal] self.o_relevant_rule[rule] = o_relevant @@ -258,18 +330,23 @@ def _update_relevant_literals_b_rule(self, rule): b_relevant = set() if self._rule_label(rule).blocked: - if all([self._lit_label(literal).unsatisfiable or self._lit_label(literal).defended or + if all([self._lit_label(literal).unsatisfiable or self._lit_label( + literal).defended or self._lit_label(literal).blocked for literal in rule.antecedents]): for literal in rule.antecedents: if self._lit_label(literal).blocked: - b_relevant = b_relevant | self.b_relevant_literal[literal] + b_relevant = b_relevant | self.b_relevant_literal[ + literal] for literal in rule.antecedents: - if self._lit_label(literal).unsatisfiable or self._lit_label(literal).out: + if self._lit_label(literal).unsatisfiable or self._lit_label( + literal).out: if self._lit_label(literal).defended: - b_relevant = b_relevant | self.d_relevant_literal[literal] + b_relevant = b_relevant | self.d_relevant_literal[ + literal] if self._lit_label(literal).blocked: - b_relevant = b_relevant | self.b_relevant_literal[literal] + b_relevant = b_relevant | self.b_relevant_literal[ + literal] self.b_relevant_rule[rule] = b_relevant diff --git a/src/py_arg/incomplete_aspic/algorithms/stability/satisfiability_labeler.py b/src/py_arg/incomplete_aspic/algorithms/stability/satisfiability_labeler.py index cf55228..f10f751 100644 --- a/src/py_arg/incomplete_aspic/algorithms/stability/satisfiability_labeler.py +++ b/src/py_arg/incomplete_aspic/algorithms/stability/satisfiability_labeler.py @@ -1,6 +1,9 @@ -from py_arg.incomplete_aspic.algorithms.stability.stability_label import StabilityLabel -from py_arg.incomplete_aspic.algorithms.stability.stability_labels import StabilityLabels -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.incomplete_aspic.algorithms.stability.stability_label import \ + StabilityLabel +from py_arg.incomplete_aspic.algorithms.stability.stability_labels import \ + StabilityLabels +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory class SatisfiabilityLabeler: @@ -11,30 +14,44 @@ def __init__(self): def _preprocess_visit(rule, labels): if labels.rule_labeling[rule].defended: return False - if all([labels.literal_labeling[literal].defended for literal in rule.antecedents]): + if all([labels.literal_labeling[literal].defended for literal in + rule.antecedents]): labels.rule_labeling[rule] = StabilityLabel(True, True, True, True) - labels.literal_labeling[rule.consequent] = StabilityLabel(True, True, True, True) + labels.literal_labeling[rule.consequent] = StabilityLabel( + True, True, True, True) return True return False - def label(self, incomplete_argumentation_theory: IncompleteArgumentationTheory) -> StabilityLabels: + def label( + self, + incomplete_argumentation_theory: IncompleteArgumentationTheory) \ + -> StabilityLabels: labels = StabilityLabels(dict(), dict()) - for literal in incomplete_argumentation_theory.argumentation_system.language.values(): + for literal in incomplete_argumentation_theory.argumentation_system.\ + language.values(): if incomplete_argumentation_theory.is_queryable(literal) and \ - all([contrary not in incomplete_argumentation_theory.knowledge_base - for contrary in literal.contraries_and_contradictories]): - labels.literal_labeling[literal] = StabilityLabel(True, True, True, True) + all([ + contrary not in + incomplete_argumentation_theory.knowledge_base + for contrary in + literal.contraries_and_contradictories]): + labels.literal_labeling[literal] = StabilityLabel( + True, True, True, True) else: - labels.literal_labeling[literal] = StabilityLabel(True, False, False, False) + labels.literal_labeling[literal] = StabilityLabel( + True, False, False, False) for rule in incomplete_argumentation_theory.argumentation_system.rules: - labels.rule_labeling[rule] = StabilityLabel(True, False, False, False) + labels.rule_labeling[rule] = StabilityLabel( + True, False, False, False) label_added = True while label_added: label_added = False - for rule in incomplete_argumentation_theory.argumentation_system.rules: - label_added = self._preprocess_visit(rule, labels) or label_added + for rule in incomplete_argumentation_theory.argumentation_system.\ + rules: + label_added = \ + self._preprocess_visit(rule, labels) or label_added return labels diff --git a/src/py_arg/incomplete_aspic/algorithms/stability/stability_label.py b/src/py_arg/incomplete_aspic/algorithms/stability/stability_label.py index 2e4535f..ab95506 100644 --- a/src/py_arg/incomplete_aspic/algorithms/stability/stability_label.py +++ b/src/py_arg/incomplete_aspic/algorithms/stability/stability_label.py @@ -4,15 +4,17 @@ class StabilityLabel: - def __init__(self, unsatisfiable: bool, defended: bool, out: bool, blocked: bool): + def __init__(self, unsatisfiable: bool, defended: bool, out: bool, + blocked: bool): self.unsatisfiable = unsatisfiable self.defended = defended self.out = out self.blocked = blocked def __str__(self): - s1 = '(U:{0}, D:{1}, O:{2}, B:{3})'.format(str(self.unsatisfiable), str(self.defended), str(self.out), - str(self.blocked)) + s1 = '(U:{0}, D:{1}, O:{2}, B:{3})'.format( + str(self.unsatisfiable), str(self.defended), str(self.out), + str(self.blocked)) return s1 @property @@ -31,11 +33,13 @@ def __repr__(self): return self.__str__() def __eq__(self, other): - return self.unsatisfiable == other.unsatisfiable and self.defended == other.defended and \ - self.out == other.out and self.blocked == other.blocked + return self.unsatisfiable == other.unsatisfiable and \ + self.defended == other.defended and \ + self.out == other.out and self.blocked == other.blocked def __copy__(self): - return StabilityLabel(self.unsatisfiable, self.defended, self.out, self.blocked) + return StabilityLabel(self.unsatisfiable, self.defended, + self.out, self.blocked) def __add__(self, other: 'StabilityLabel'): unsatisfiable = self.unsatisfiable or other.unsatisfiable @@ -46,7 +50,8 @@ def __add__(self, other: 'StabilityLabel'): @property def is_stable(self): - return sum([self.unsatisfiable, self.defended, self.out, self.blocked]) == 1 + return sum([self.unsatisfiable, self.defended, self.out, + self.blocked]) == 1 @property def is_stable_defended(self): @@ -55,8 +60,10 @@ def is_stable_defended(self): @property def is_contested_stable(self): """ - Contested is an alternative stability status, using either the defended justification status or combining - the justification statuses that are not defended. So if some literal is contested-stable, then it is either + Contested is an alternative stability status, using either the defended + justification status or combining + the justification statuses that are not defended. So if some literal is + contested-stable, then it is either defended in each future AT or it is not defended in any future AT. """ if self.defended and (self.unsatisfiable or self.out or self.blocked): @@ -65,6 +72,7 @@ def is_contested_stable(self): @classmethod def from_str(cls, label_str: str): - parse_result_str_list = parse('(U:{0}, D:{1}, O:{2}, B:{3})', label_str).fixed + parse_result_str_list = parse( + '(U:{0}, D:{1}, O:{2}, B:{3})', label_str).fixed parse_result_bool_list = [strtobool(s) for s in parse_result_str_list] return StabilityLabel(*parse_result_bool_list) diff --git a/src/py_arg/incomplete_aspic/algorithms/stability/stability_labeler.py b/src/py_arg/incomplete_aspic/algorithms/stability/stability_labeler.py index 6fc9303..bcccc55 100644 --- a/src/py_arg/incomplete_aspic/algorithms/stability/stability_labeler.py +++ b/src/py_arg/incomplete_aspic/algorithms/stability/stability_labeler.py @@ -1,40 +1,44 @@ -from py_arg.aspic.algorithms.justification.connected_literal import connect_parents_and_children -from py_arg.incomplete_aspic.algorithms.stability.satisfiability_labeler import SatisfiabilityLabeler -from py_arg.incomplete_aspic.algorithms.stability.stability_labels import StabilityLabels -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.aspic.algorithms.justification.connected_literal import \ + connect_parents_and_children +from py_arg.incomplete_aspic.algorithms.stability.satisfiability_labeler \ + import SatisfiabilityLabeler +from py_arg.incomplete_aspic.algorithms.stability.stability_labels import \ + StabilityLabels +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory class StabilityLabeler: def __init__(self): pass - def label(self, incomplete_argumentation_theory: IncompleteArgumentationTheory) -> StabilityLabels: - # Preprocessing: take the initial labeling from the SatisfiabilityLabeler + def label( + self, + incomplete_argumentation_theory: IncompleteArgumentationTheory) \ + -> StabilityLabels: + # Preprocessing: take the initial labeling from the + # SatisfiabilityLabeler labels = SatisfiabilityLabeler().label(incomplete_argumentation_theory) - rules_visited = {rule: False for rule in incomplete_argumentation_theory.argumentation_system.rules} + rules_visited = { + rule: False + for rule in incomplete_argumentation_theory. + argumentation_system.rules} # Connect literals, so we can ask for their children and parents connect_parents_and_children(incomplete_argumentation_theory) - # TODO remove again: compute argument height - # literal_height = {lit_str: 0 - # for lit_str in set(incomplete_argumentation_theory.argumentation_system.language.keys())} - # change = True - # while change: - # change = False - # for rule in incomplete_argumentation_theory.argumentation_system.defeasible_rules: - # max_antecedent_height = max(literal_height[lit_str.s1] for lit_str in rule.antecedents) - # if max_antecedent_height + 1 > literal_height[rule.consequent.s1]: - # literal_height[rule.consequent.s1] = max_antecedent_height + 1 - # change = True - - # Start by coloring leaves (literals for which there is no rule) and observables - leaves_and_observables = [literal - for literal in incomplete_argumentation_theory.argumentation_system.language.values() - if not literal.children or incomplete_argumentation_theory.is_queryable(literal)] + # Start by coloring leaves (literals for which there is no rule) and + # observables + leaves_and_observables = [ + literal + for literal in incomplete_argumentation_theory. + argumentation_system.language.values() + if not literal.children or + incomplete_argumentation_theory.is_queryable(literal)] rules_to_reconsider = set() for literal in leaves_and_observables: - self.color_literal(incomplete_argumentation_theory, literal, labels) + self.color_literal( + incomplete_argumentation_theory, literal, labels) rules_to_reconsider = rules_to_reconsider | set(literal.parents) # Color rules and (contraries of) their conclusions @@ -46,17 +50,28 @@ def label(self, incomplete_argumentation_theory: IncompleteArgumentationTheory) self.color_rule(rule, labels) - # If this was the first time the rule was considered or if its label changed, it may influence others. - if not rules_visited[rule] or labels.rule_labeling[rule] != old_rule_label: - old_literal_label = labels.literal_labeling[rule.consequent].__copy__() - self.color_literal(incomplete_argumentation_theory, rule.consequent, labels) - if labels.literal_labeling[rule.consequent] != old_literal_label: - rules_to_reconsider = rules_to_reconsider | set(rule.consequent.parents) - for contrary_literal in rule.consequent.contraries_and_contradictories: - old_contrary_literal_label = labels.literal_labeling[contrary_literal].__copy__() - self.color_literal(incomplete_argumentation_theory, contrary_literal, labels) - if labels.literal_labeling[contrary_literal] != old_contrary_literal_label: - rules_to_reconsider = rules_to_reconsider | set(contrary_literal.parents) + # If this was the first time the rule was considered or if its + # label changed, it may influence others. + if not rules_visited[rule] or \ + labels.rule_labeling[rule] != old_rule_label: + old_literal_label = \ + labels.literal_labeling[rule.consequent].__copy__() + self.color_literal(incomplete_argumentation_theory, + rule.consequent, labels) + if labels.literal_labeling[rule.consequent] != \ + old_literal_label: + rules_to_reconsider = rules_to_reconsider | \ + set(rule.consequent.parents) + for contrary_literal in \ + rule.consequent.contraries_and_contradictories: + old_contrary_literal_label = \ + labels.literal_labeling[contrary_literal].__copy__() + self.color_literal(incomplete_argumentation_theory, + contrary_literal, labels) + if labels.literal_labeling[contrary_literal] != \ + old_contrary_literal_label: + rules_to_reconsider = rules_to_reconsider | \ + set(contrary_literal.parents) rules_visited[rule] = True return labels @@ -64,31 +79,41 @@ def label(self, incomplete_argumentation_theory: IncompleteArgumentationTheory) @staticmethod def color_literal(incomplete_argumentation_theory, literal, labels): """ - Color the Literal, that is: check, based on observations/rules for this literal/rules for its contraries, if + Color the Literal, that is: check, based on observations/rules for + this literal/rules for its contraries, if this Literal can still become unsatisfiable/defended/out/blocked. """ if incomplete_argumentation_theory.is_queryable(literal) and \ literal in incomplete_argumentation_theory.knowledge_base: # L-U-a: The literal is observed, so it cannot be unsatisfiable. labels.literal_labeling[literal].unsatisfiable = False - elif any([not labels.rule_labeling[rule].unsatisfiable for rule in literal.children]): - # L-U-b: There is a rule-based argument for the literal, so it cannot be unsatisfiable. + elif any([not labels.rule_labeling[rule].unsatisfiable + for rule in literal.children]): + # L-U-b: There is a rule-based argument for the literal, + # so it cannot be unsatisfiable. labels.literal_labeling[literal].unsatisfiable = False if incomplete_argumentation_theory.is_queryable(literal): - if any([contrary_literal in incomplete_argumentation_theory.knowledge_base - for contrary_literal in literal.contraries_and_contradictories]): - # L-D-a: A contrary of the literal is observed, so the literal cannot be in the grounded extension. + if any([contrary_literal in + incomplete_argumentation_theory.knowledge_base + for contrary_literal in + literal.contraries_and_contradictories]): + # L-D-a: A contrary of the literal is observed, so the + # literal cannot be in the grounded extension. labels.literal_labeling[literal].defended = False else: - if all([not labels.rule_labeling[rule].defended for rule in literal.children]): - # L-D-b: The literal is not observable and there is no defended rule, so the literal cannot be defended. + if all([not labels.rule_labeling[rule].defended + for rule in literal.children]): + # L-D-b: The literal is not observable and there is no + # defended rule, so the literal cannot be defended. labels.literal_labeling[literal].defended = False elif any([not labels.rule_labeling[contrary_rule].unsatisfiable and not labels.rule_labeling[contrary_rule].out - for contrary_literal in literal.contraries_and_contradictories + for contrary_literal in + literal.contraries_and_contradictories for contrary_rule in contrary_literal.children]): - # L-D-c: The literal is not observable and there is a defended or blocked rule for a contrary, so the + # L-D-c: The literal is not observable and there is a + # defended or blocked rule for a contrary, so the # literal cannot be defended. labels.literal_labeling[literal].defended = False @@ -96,71 +121,99 @@ def color_literal(incomplete_argumentation_theory, literal, labels): if literal in incomplete_argumentation_theory.knowledge_base: # L-O-a: Observed literals cannot be out. labels.literal_labeling[literal].out = False - elif all([any([contrary_contrary_literal in incomplete_argumentation_theory.knowledge_base - for contrary_contrary_literal in contrary_literal.contraries_and_contradictories]) - for contrary_literal in literal.contraries_and_contradictories]): - if all([not labels.rule_labeling[rule].out for rule in literal.children]): + elif all([any([contrary_contrary_literal in + incomplete_argumentation_theory.knowledge_base + for contrary_contrary_literal in + contrary_literal.contraries_and_contradictories]) + for contrary_literal in + literal.contraries_and_contradictories]): + if all([not labels.rule_labeling[rule].out + for rule in literal.children]): # L-O-b labels.literal_labeling[literal].out = False - elif any([not labels.rule_labeling[rule].unsatisfiable and not labels.rule_labeling[rule].out + elif any([not labels.rule_labeling[rule].unsatisfiable and + not labels.rule_labeling[rule].out for rule in literal.children]): # L-O-c labels.literal_labeling[literal].out = False else: - if all([not labels.rule_labeling[rule].out for rule in literal.children]): + if all([not labels.rule_labeling[rule].out + for rule in literal.children]): # L-O-d labels.literal_labeling[literal].out = False - elif any([not labels.rule_labeling[rule].unsatisfiable and not labels.rule_labeling[rule].out + elif any([not labels.rule_labeling[rule].unsatisfiable and + not labels.rule_labeling[rule].out for rule in literal.children]): # L-O-e labels.literal_labeling[literal].out = False - if all([not labels.rule_labeling[rule].defended and not labels.rule_labeling[rule].out and - not labels.rule_labeling[rule].blocked for rule in literal.children]): - # L-O-f: There is no rule-based argument for the literal, so the literal cannot be out. + if all([not labels.rule_labeling[rule].defended and + not labels.rule_labeling[rule].out and + not labels.rule_labeling[rule].blocked + for rule in literal.children]): + # L-O-f: There is no rule-based argument for the literal, + # so the literal cannot be out. labels.literal_labeling[literal].out = False if incomplete_argumentation_theory.is_queryable(literal): - # L-B-a: Observable literals cannot be blocked (only defended or unsatisfiable). + # L-B-a: Observable literals cannot be blocked (only + # defended or unsatisfiable). labels.literal_labeling[literal].blocked = False elif all([not labels.rule_labeling[rule].defended and - not labels.rule_labeling[rule].blocked for rule in literal.children]): - # L-B-b: There is no defended or blocked rule-based argument for the literal, so it cannot be blocked. + not labels.rule_labeling[rule].blocked + for rule in literal.children]): + # L-B-b: There is no defended or blocked rule-based argument for + # the literal, so it cannot be blocked. labels.literal_labeling[literal].blocked = False elif all([not labels.rule_labeling[contrary_rule].blocked and not labels.rule_labeling[contrary_rule].defended - for contrary_literal in literal.contraries_and_contradictories + for contrary_literal in + literal.contraries_and_contradictories for contrary_rule in contrary_literal.children]): - if all([not labels.rule_labeling[rule].blocked for rule in literal.children]): - # L-B-c: There is no rule-based counterargument that is strong enough. + if all([not labels.rule_labeling[rule].blocked + for rule in literal.children]): + # L-B-c: There is no rule-based counterargument that is + # strong enough. labels.literal_labeling[literal].blocked = False - elif any([not labels.rule_labeling[rule].unsatisfiable and not labels.rule_labeling[rule].out and + elif any([not labels.rule_labeling[rule].unsatisfiable and + not labels.rule_labeling[rule].out and not labels.rule_labeling[rule].blocked for rule in literal.children]): - # L-B-d: There is a rule-based argument in the grounded extension. + # L-B-d: There is a rule-based argument in the + # grounded extension. labels.literal_labeling[literal].blocked = False @staticmethod def color_rule(rule, labels): """ - Color the Rule, that is: check, based on is children, if this Rule can still become - unsatisfiable/defended/out/blocked. + Color the Rule, that is: check, based on is children, if this Rule can + still become unsatisfiable/defended/out/blocked. """ - if all([not labels.literal_labeling[literal].unsatisfiable for literal in rule.antecedents]): - # R-U-a: None of the antecedents can become unsatisfiable, so the rule cannot be unsatisfiable. + if all([not labels.literal_labeling[literal].unsatisfiable + for literal in rule.antecedents]): + # R-U-a: None of the antecedents can become unsatisfiable, + # so the rule cannot be unsatisfiable. labels.rule_labeling[rule].unsatisfiable = False - if any([not labels.literal_labeling[literal].defended for literal in rule.antecedents]): - # R-D-a: At least one of the antecedents cannot become defended, so the rule cannot be defended. + if any([not labels.literal_labeling[literal].defended + for literal in rule.antecedents]): + # R-D-a: At least one of the antecedents cannot become defended, + # so the rule cannot be defended. labels.rule_labeling[rule].defended = False - if all([not labels.literal_labeling[literal].out for literal in rule.antecedents]): - # R-O-a: None of the antecedents can become out, so the rule cannot be out. + if all([not labels.literal_labeling[literal].out + for literal in rule.antecedents]): + # R-O-a: None of the antecedents can become out, so the rule + # cannot be out. labels.rule_labeling[rule].out = False - if all([not labels.literal_labeling[literal].blocked for literal in rule.antecedents]): - # R-B-a: None of the antecedents can become blocked, so the rule cannot be blocked. + if all([not labels.literal_labeling[literal].blocked + for literal in rule.antecedents]): + # R-B-a: None of the antecedents can become blocked, so the + # rule cannot be blocked. labels.rule_labeling[rule].blocked = False if any([not labels.literal_labeling[literal].blocked and - not labels.literal_labeling[literal].defended for literal in rule.antecedents]): - # R-B-b: At least one of the antecedents cannot become defended or blocked, so the rule cannot be blocked. + not labels.literal_labeling[literal].defended + for literal in rule.antecedents]): + # R-B-b: At least one of the antecedents cannot become defended + # or blocked, so the rule cannot be blocked. labels.rule_labeling[rule].blocked = False diff --git a/src/py_arg/incomplete_aspic/algorithms/stability/stability_labels.py b/src/py_arg/incomplete_aspic/algorithms/stability/stability_labels.py index 32a7ab6..8c501a1 100644 --- a/src/py_arg/incomplete_aspic/algorithms/stability/stability_labels.py +++ b/src/py_arg/incomplete_aspic/algorithms/stability/stability_labels.py @@ -1,11 +1,13 @@ from typing import Dict -from py_arg.incomplete_aspic.algorithms.stability.stability_label import StabilityLabel +from py_arg.incomplete_aspic.algorithms.stability.stability_label import \ + StabilityLabel from py_arg.aspic.classes.literal import Literal from py_arg.aspic.classes.rule import Rule class StabilityLabels: - def __init__(self, literal_labeling: Dict[Literal, StabilityLabel], rule_labeling: Dict[Rule, StabilityLabel]): + def __init__(self, literal_labeling: Dict[Literal, StabilityLabel], + rule_labeling: Dict[Rule, StabilityLabel]): self.literal_labeling = literal_labeling self.rule_labeling = rule_labeling diff --git a/src/py_arg/incomplete_aspic/classes/incomplete_argumentation_theory.py b/src/py_arg/incomplete_aspic/classes/incomplete_argumentation_theory.py index 2333fc0..6e703f4 100644 --- a/src/py_arg/incomplete_aspic/classes/incomplete_argumentation_theory.py +++ b/src/py_arg/incomplete_aspic/classes/incomplete_argumentation_theory.py @@ -4,26 +4,34 @@ from py_arg.aspic.classes.argumentation_system import ArgumentationSystem from py_arg.aspic.classes.argumentation_theory import ArgumentationTheory from py_arg.aspic.classes.literal import Literal -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder class IncompleteArgumentationTheory: """ - An IncompleteArgumentationTheory consists of an ArgumentationSystem, a knowledge base and a set of queryables. - By adding queryables, or their negations, to the knowledge base, future ArgumentationTheories can be obtained. + An IncompleteArgumentationTheory consists of an ArgumentationSystem, a + knowledge base and a set of queryables. + By adding queryables, or their negations, to the knowledge base, future + ArgumentationTheories can be obtained. """ - def __init__(self, argumentation_system: ArgumentationSystem, - queryables: List[Literal], - knowledge_base_axioms: List[Literal], - knowledge_base_ordinary_premises: List[Literal], - ordinary_premise_preferences: Optional[PreferencePreorder] = None): + def __init__( + self, argumentation_system: ArgumentationSystem, + queryables: List[Literal], + knowledge_base_axioms: List[Literal], + knowledge_base_ordinary_premises: List[Literal], + ordinary_premise_preferences: Optional[PreferencePreorder] = + None): self._argumentation_system = argumentation_system self._queryables = sorted(queryables) self._knowledge_base_axioms = sorted(knowledge_base_axioms) - self._knowledge_base_ordinary_premises = sorted(knowledge_base_ordinary_premises) + self._knowledge_base_ordinary_premises = sorted( + knowledge_base_ordinary_premises) - self._is_queryable_dict = {lit_str: False for lit_str in self.argumentation_system.language.keys()} + self._is_queryable_dict = { + lit_str: False + for lit_str in self.argumentation_system.language.keys()} for queryable in self._queryables: self._is_queryable_dict[queryable.s1] = True @@ -32,7 +40,8 @@ def __init__(self, argumentation_system: ArgumentationSystem, self.ordinary_premise_preferences = ordinary_premise_preferences else: self.ordinary_premise_preferences = \ - PreferencePreorder.create_reflexive_preorder(self._knowledge_base_ordinary_premises) + PreferencePreorder.create_reflexive_preorder( + self._knowledge_base_ordinary_premises) @property def argumentation_system(self): @@ -57,11 +66,13 @@ def is_queryable(self, literal: Union[Literal, str]): @property def positive_queryables(self): - return [queryable for queryable in self._queryables if queryable.is_positive] + return [queryable for queryable in self._queryables + if queryable.is_positive] @property def knowledge_base(self): - return self._knowledge_base_axioms + self._knowledge_base_ordinary_premises + return self._knowledge_base_axioms + \ + self._knowledge_base_ordinary_premises @property def knowledge_base_axioms(self): @@ -79,17 +90,23 @@ def knowledge_base_ordinary_premises(self): return self._knowledge_base_ordinary_premises @knowledge_base_ordinary_premises.setter - def knowledge_base_ordinary_premises(self, knowledge_base_ordinary_premises_input): - self._knowledge_base_ordinary_premises = knowledge_base_ordinary_premises_input + def knowledge_base_ordinary_premises( + self, knowledge_base_ordinary_premises_input): + self._knowledge_base_ordinary_premises = \ + knowledge_base_ordinary_premises_input - def add_to_knowledge_base_ordinary_premises(self, new_knowledge_base_ordinary_premise: Literal): - self._knowledge_base_ordinary_premises.append(new_knowledge_base_ordinary_premise) + def add_to_knowledge_base_ordinary_premises( + self, new_knowledge_base_ordinary_premise: Literal): + self._knowledge_base_ordinary_premises.append( + new_knowledge_base_ordinary_premise) def get_all_axiom_completions(self): # -1: Negation of this queryable is an axiom in the knowledge base. - # 0: This queryable remains unknown in that neither this queryable, nor its negation is an axiom. + # 0: This queryable remains unknown in that neither this queryable, + # nor its negation is an axiom. # 1: This queryable is an axiom in the knowledge base. - queryable_value_list = ([(queryable_str, possible_value) for possible_value in [-1, 0, 1]] + queryable_value_list = ([(queryable_str, possible_value) + for possible_value in [-1, 0, 1]] for queryable_str in self.positive_queryables) queryable_value_combinations = itertools.product(*queryable_value_list) @@ -97,22 +114,29 @@ def get_knowledge_base(queryable_value_combination_tuples): knowledge_base = [] for queryable, value in queryable_value_combination_tuples: if value == -1: - knowledge_base.append(self.argumentation_system.language['-' + str(queryable)]) + knowledge_base.append( + self.argumentation_system.language[ + '-' + str(queryable)]) elif value == 1: knowledge_base.append(queryable) return knowledge_base - result = (ArgumentationTheory(self.argumentation_system, get_knowledge_base(queryable_value_combination), - [], None) - for queryable_value_combination in queryable_value_combinations) + result = (ArgumentationTheory( + self.argumentation_system, + get_knowledge_base(queryable_value_combination), + [], None) + for queryable_value_combination in queryable_value_combinations) return result def __eq__(self, other): return isinstance(other, IncompleteArgumentationTheory) and \ - self.argumentation_system == other.argumentation_system and self.queryables == other.queryables and \ - self.knowledge_base_axioms == other.knowledge_base_axioms and \ - self.knowledge_base_ordinary_premises == other.knowledge_base_ordinary_premises and \ - self.ordinary_premise_preferences == other.ordinary_premise_preferences + self.argumentation_system == other.argumentation_system and \ + self.queryables == other.queryables and \ + self.knowledge_base_axioms == other.knowledge_base_axioms and \ + self.knowledge_base_ordinary_premises == other.\ + knowledge_base_ordinary_premises and \ + self.ordinary_premise_preferences == other.\ + ordinary_premise_preferences if __name__ == "__main__": diff --git a/src/py_arg/incomplete_aspic/generators/incomplete_argumentation_theory_generator.py b/src/py_arg/incomplete_aspic/generators/incomplete_argumentation_theory_generator.py index adfb0c0..73895a4 100644 --- a/src/py_arg/incomplete_aspic/generators/incomplete_argumentation_theory_generator.py +++ b/src/py_arg/incomplete_aspic/generators/incomplete_argumentation_theory_generator.py @@ -3,7 +3,8 @@ from py_arg.aspic.classes.argumentation_system import ArgumentationSystem from py_arg.aspic.classes.literal import Literal -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory class IncompleteArgumentationTheoryGenerator: @@ -15,56 +16,75 @@ def __init__(self, argumentation_system: ArgumentationSystem, """ Initialise the IncompleteArgumentationTheoryGenerator. - Note: we assume that the contradiction function in the argumentation system only consists of negations. + Note: we assume that the contradiction function in the argumentation + system only consists of negations. - :param argumentation_system: The argumentation system based on which this IncompleteArgumentationTheory will be. - :param positive_queryable_candidates: Literals that are positive and may be queryable. - :param queryable_literal_ratio: Number of queryables compared to number of literals. - :param knowledge_queryable_ratio: Number of knowledge base items compared to number of positive queryables. - :param axiom_knowledge_ratio: Number of axioms compared to number of knowledge base items. + :param argumentation_system: The argumentation system based on which + this IncompleteArgumentationTheory will be. + :param positive_queryable_candidates: Literals that are positive and + may be queryable. + :param queryable_literal_ratio: Number of queryables compared to number + of literals. + :param knowledge_queryable_ratio: Number of knowledge base items + compared to number of positive queryables. + :param axiom_knowledge_ratio: Number of axioms compared to number of + knowledge base items. """ self.argumentation_system = argumentation_system if queryable_literal_ratio < 0 or queryable_literal_ratio > 1: - raise ValueError('The queryable literal ratio should be between zero and one.') + raise ValueError('The queryable literal ratio should be between ' + 'zero and one.') self.queryable_literal_ratio = queryable_literal_ratio if knowledge_queryable_ratio < 0 or knowledge_queryable_ratio > 1: - raise ValueError('The knowledge queryable ratio should be between zero and one.') + raise ValueError('The knowledge queryable ratio should be between ' + 'zero and one.') self.knowledge_queryable_ratio = knowledge_queryable_ratio if axiom_knowledge_ratio < 0 or axiom_knowledge_ratio > 1: - raise ValueError('The axiom knowledge ratio should be between zero and one.') + raise ValueError('The axiom knowledge ratio should be between ' + 'zero and one.') self.axiom_knowledge_ratio = axiom_knowledge_ratio # Find the positive literals in the ArgumentationSystem. - normal_literals = [literal for literal_str, literal in self.argumentation_system.language.items() - if 'd' not in literal_str] - self.positive_literals = [literal for literal in normal_literals if literal.is_positive] + normal_literals = [ + literal + for literal_str, literal in + self.argumentation_system.language.items() + if 'd' not in literal_str] + self.positive_literals = [ + literal for literal in normal_literals if literal.is_positive] if positive_queryable_candidates: self.positive_queryable_candidates = positive_queryable_candidates else: self.positive_queryable_candidates = self.positive_literals - self.nr_of_positive_queryables = int(queryable_literal_ratio * len(self.positive_literals)) - knowledge_base_size = int(self.nr_of_positive_queryables * self.knowledge_queryable_ratio) + self.nr_of_positive_queryables = int(queryable_literal_ratio * len( + self.positive_literals)) + knowledge_base_size = int( + self.nr_of_positive_queryables * self.knowledge_queryable_ratio) self.axiom_size = int(knowledge_base_size * self.axiom_knowledge_ratio) self.ordinary_premise_size = knowledge_base_size - self.axiom_size def generate(self) -> IncompleteArgumentationTheory: # Sample the queryables from the set of literals. - positive_queryables = random.sample(self.positive_queryable_candidates, self.nr_of_positive_queryables) - negative_queryables = [self.argumentation_system.language['-' + str(pos_q)] - for pos_q in positive_queryables] + positive_queryables = random.sample( + self.positive_queryable_candidates, self.nr_of_positive_queryables) + negative_queryables = [ + self.argumentation_system.language['-' + str(pos_q)] + for pos_q in positive_queryables] queryables = positive_queryables + negative_queryables - # Sample the axioms from the set of queryables, making sure that the axioms are consistent. + # Sample the axioms from the set of queryables, making sure that the + # axioms are consistent. axioms = [] axiom_candidates = queryables.copy() for _ in range(self.axiom_size - 1): if not axiom_candidates: - raise ValueError('Could not construct such a large knowledge base given the contradictories.') + raise ValueError('Could not construct such a large knowledge ' + 'base given the contradictories.') new_axiom = random.choice(axiom_candidates) axioms.append(new_axiom) axiom_candidates.remove(new_axiom) @@ -72,8 +92,10 @@ def generate(self) -> IncompleteArgumentationTheory: axiom_candidates.remove(new_axiom_contrary) # Finally, sample the ordinary premises. - ordinary_premise_candidates = [queryable for queryable in queryables if queryable not in axioms] - ordinary_premises = random.sample(ordinary_premise_candidates, self.ordinary_premise_size) + ordinary_premise_candidates = [queryable for queryable in queryables + if queryable not in axioms] + ordinary_premises = random.sample(ordinary_premise_candidates, + self.ordinary_premise_size) return IncompleteArgumentationTheory( argumentation_system=self.argumentation_system, diff --git a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_json_reader.py b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_json_reader.py index 3fa5e7d..9a0aabb 100644 --- a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_json_reader.py +++ b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_json_reader.py @@ -1,8 +1,11 @@ import json -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder -from py_arg.aspic.import_export.argumentation_system_from_json_reader import ArgumentationSystemFromJsonReader -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder +from py_arg.aspic.import_export.argumentation_system_from_json_reader import \ + ArgumentationSystemFromJsonReader +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory class IncompleteArgumentationTheoryFromJsonReader: @@ -11,17 +14,23 @@ def __init__(self): @staticmethod def from_json(json_object) -> IncompleteArgumentationTheory: - argumentation_system = ArgumentationSystemFromJsonReader().from_json(json_object['argumentation_system']) - queryables = [argumentation_system.language[queryable_str] for queryable_str in json_object['queryables']] - knowledge_base_axioms = [argumentation_system.language[axiom_str] for axiom_str in json_object['axioms']] - knowledge_base_ordinary_premises = [argumentation_system.language[prem_str] - for prem_str in json_object['ordinary_premises']] + argumentation_system = ArgumentationSystemFromJsonReader().from_json( + json_object['argumentation_system']) + queryables = [argumentation_system.language[queryable_str] + for queryable_str in json_object['queryables']] + knowledge_base_axioms = [argumentation_system.language[axiom_str] + for axiom_str in json_object['axioms']] + knowledge_base_ordinary_premises = [ + argumentation_system.language[prem_str] + for prem_str in json_object['ordinary_premises']] ordinary_premise_preferences = PreferencePreorder( - [(argumentation_system.language[lit_a], argumentation_system.language[lit_b]) + [(argumentation_system.language[lit_a], + argumentation_system.language[lit_b]) for lit_a, lit_b in json_object['ordinary_premise_preferences']]) - return IncompleteArgumentationTheory(argumentation_system, queryables, knowledge_base_axioms, - knowledge_base_ordinary_premises, ordinary_premise_preferences) + return IncompleteArgumentationTheory( + argumentation_system, queryables, knowledge_base_axioms, + knowledge_base_ordinary_premises, ordinary_premise_preferences) def read_from_json(self, file_path: str) -> IncompleteArgumentationTheory: with open(file_path, 'r') as reader: diff --git a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_lp_file_reader.py b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_lp_file_reader.py index babb30b..d040a6c 100644 --- a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_lp_file_reader.py +++ b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_lp_file_reader.py @@ -1,8 +1,10 @@ from py_arg.aspic.classes.argumentation_system import ArgumentationSystem from py_arg.aspic.classes.defeasible_rule import DefeasibleRule from py_arg.aspic.classes.literal import Literal -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory class IncompleteArgumentationTheoryFromLPFileReader: @@ -21,17 +23,22 @@ def read_from_lp_file(file_path: str) -> IncompleteArgumentationTheory: reader = open(file_path, 'r') for line in reader: if line.startswith('queryable'): - positive_queryable_strs.append(line.split('(', 1)[1].split(')', 1)[0]) + positive_queryable_strs.append(line.split( + '(', 1)[1].split(')', 1)[0]) if line.startswith('axiom'): axiom_strs.append(line.split('(', 1)[1].split(')', 1)[0]) if line.startswith('body'): - defeasible_rule_bodies.append((line.split('(', 1)[1].split(')', 1)[0]).split(', ', 1)) + defeasible_rule_bodies.append((line.split( + '(', 1)[1].split(')', 1)[0]).split(', ', 1)) if line.startswith('head'): - defeasible_rule_heads.append((line.split('(', 1)[1].split(')', 1)[0]).split(', ', 1)) + defeasible_rule_heads.append((line.split( + '(', 1)[1].split(')', 1)[0]).split(', ', 1)) if line.startswith('neg'): - contradiction_pairs.append((line.split('(', 1)[1].split(')', 1)[0]).split(', ', 1)) + contradiction_pairs.append((line.split( + '(', 1)[1].split(')', 1)[0]).split(', ', 1)) if line.startswith('preferred'): - preferred_pairs.append((line.split('(', 1)[1].split(')', 1)[0]).split(', ', 1)) + preferred_pairs.append((line.split( + '(', 1)[1].split(')', 1)[0]).split(', ', 1)) reader.close() all_positive_literals = set(positive_queryable_strs) @@ -43,7 +50,8 @@ def read_from_lp_file(file_path: str) -> IncompleteArgumentationTheory: all_positive_literals.add(defeasible_rule_body[1].replace('-', '')) for contradiction_pair in contradiction_pairs: all_positive_literals.add(contradiction_pair[0]) - all_negative_literals = {'-' + pos_literal for pos_literal in all_positive_literals} + all_negative_literals = {'-' + pos_literal + for pos_literal in all_positive_literals} all_literals = all_positive_literals | all_negative_literals language = {lit_str: Literal(lit_str) for lit_str in all_literals} @@ -54,29 +62,40 @@ def read_from_lp_file(file_path: str) -> IncompleteArgumentationTheory: defeasible_rules = [] for rule_nr, rule_head in defeasible_rule_heads: - rule_antecedents = [rule_body_literal - for rule_body_nr, rule_body_literal in defeasible_rule_bodies - if rule_body_nr == rule_nr] - defeasible_rule = DefeasibleRule(rule_nr, {language[ant_str] for ant_str in rule_antecedents}, - language[rule_head]) + rule_antecedents = [ + rule_body_literal + for rule_body_nr, rule_body_literal in defeasible_rule_bodies + if rule_body_nr == rule_nr] + defeasible_rule = DefeasibleRule( + rule_nr, {language[ant_str] for ant_str in rule_antecedents}, + language[rule_head]) defeasible_rules.append(defeasible_rule) - def_rules_lookup = {defeasible_rule.id: defeasible_rule for defeasible_rule in defeasible_rules} + def_rules_lookup = {defeasible_rule.id: defeasible_rule + for defeasible_rule in defeasible_rules} preference_preorder = PreferencePreorder( [(def_rules_lookup[rule_a], def_rules_lookup[rule_b]) for rule_a, rule_b in preferred_pairs]) argumentation_system = ArgumentationSystem( - language=language, contraries_and_contradictories=contraries_and_contradictories, + language=language, + contraries_and_contradictories=contraries_and_contradictories, strict_rules=[], defeasible_rules=defeasible_rules, - defeasible_rule_preferences=preference_preorder, add_defeasible_rule_literals=False) + defeasible_rule_preferences=preference_preorder, + add_defeasible_rule_literals=False) - negative_queryable_strs = ['-' + queryable for queryable in positive_queryable_strs] - queryables = [language[queryable] for queryable in positive_queryable_strs + negative_queryable_strs] - knowledge_base_axioms = [language[axiom_str] for axiom_str in axiom_strs] + negative_queryable_strs = [ + '-' + queryable for queryable in positive_queryable_strs] + queryables = [ + language[queryable] + for queryable in positive_queryable_strs + negative_queryable_strs] + knowledge_base_axioms = [ + language[axiom_str] for axiom_str in axiom_strs] return IncompleteArgumentationTheory( - argumentation_system=argumentation_system, queryables=queryables, - knowledge_base_axioms=knowledge_base_axioms, knowledge_base_ordinary_premises=[], + argumentation_system=argumentation_system, + queryables=queryables, + knowledge_base_axioms=knowledge_base_axioms, + knowledge_base_ordinary_premises=[], ordinary_premise_preferences=None ) diff --git a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_xlsx_reader.py b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_xlsx_reader.py index 6035382..8dae2ef 100644 --- a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_xlsx_reader.py +++ b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_from_xlsx_reader.py @@ -7,7 +7,8 @@ from py_arg.aspic.classes.argumentation_system import ArgumentationSystem from py_arg.aspic.classes.defeasible_rule import DefeasibleRule from py_arg.aspic.classes.literal import Literal -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory class IncompleteArgumentationTheoryFromXLSXFileReader: @@ -15,21 +16,24 @@ def __init__(self): pass @staticmethod - def read_from_xlsx_file(file_path: Union[Path, str]) -> IncompleteArgumentationTheory: + def read_from_xlsx_file(file_path: Union[Path, str]) -> \ + IncompleteArgumentationTheory: wb_sheet_names = load_workbook(file_path, read_only=True).sheetnames _literal_df = pd.read_excel(file_path, sheet_name='Literals') _rule_df = pd.read_excel(file_path, sheet_name='Rules') - _query_df = pd.read_excel(file_path, sheet_name='Queries', index_col='Query') + # _query_df = pd.read_excel(file_path, sheet_name='Queries', + # index_col='Query') if 'Contraries' in wb_sheet_names: _contrary_df = pd.read_excel(file_path, sheet_name='Contraries') else: _contrary_df = None - if 'RulePreferences' in wb_sheet_names: - _rule_preference_df = pd.read_excel(file_path, sheet_name='RulePreferences') - else: - _rule_preference_df = None + # if 'RulePreferences' in wb_sheet_names: + # _rule_preference_df = pd.read_excel(file_path, + # sheet_name='RulePreferences') + # else: + # _rule_preference_df = None try: language = dict() @@ -51,18 +55,23 @@ def read_from_xlsx_file(file_path: Union[Path, str]) -> IncompleteArgumentationT if _contrary_df is not None: for index, row in _contrary_df.iterrows(): literal_str = row['Literal'].replace('~', '-') - contraries_str = [cont.strip().replace('~', '-') for cont in row['Contraries'].split(',')] + contraries_str = [cont.strip().replace('~', '-') + for cont in row['Contraries'].split(',')] for contrary_str in contraries_str: - contraries_and_contradictories[literal_str].add(language[contrary_str]) + contraries_and_contradictories[literal_str].add( + language[contrary_str]) # Add rules rules = [] for index, row in _rule_df.iterrows(): - ants_str = [ant.strip().replace('~', '-') for ant in row['Antecedents'].split(',')] + ants_str = [ant.strip().replace('~', '-') + for ant in row['Antecedents'].split(',')] cons_str = row['Consequent'].strip().replace('~', '-') - if any([ant not in language for ant in ants_str]) or cons_str not in language: + if any([ant not in language + for ant in ants_str]) or cons_str not in language: raise KeyError( - 'Not each literal in ' + str(ants_str) + ' or ' + cons_str + ' was in logical language.') + 'Not each literal in ' + str(ants_str) + ' or ' + + cons_str + ' was in logical language.') ants = {language[literal_str] for literal_str in ants_str} cons = language[cons_str] @@ -73,13 +82,16 @@ def read_from_xlsx_file(file_path: Union[Path, str]) -> IncompleteArgumentationT rules.append(DefeasibleRule(rule_id, ants, cons)) - argumentation_system = ArgumentationSystem(language=language, - contraries_and_contradictories=contraries_and_contradictories, - strict_rules=[], defeasible_rules=rules, - add_defeasible_rule_literals=False) - return IncompleteArgumentationTheory(argumentation_system=argumentation_system, - queryables=queryables, - knowledge_base_axioms=[], - knowledge_base_ordinary_premises=[]) + argumentation_system = ArgumentationSystem( + language=language, + contraries_and_contradictories=contraries_and_contradictories, + strict_rules=[], defeasible_rules=rules, + add_defeasible_rule_literals=False) + return IncompleteArgumentationTheory( + argumentation_system=argumentation_system, + queryables=queryables, + knowledge_base_axioms=[], + knowledge_base_ordinary_premises=[]) except Exception as exception: - raise ImportError('Could not load Argumentation System.' + str(type(exception))) + raise ImportError('Could not load Argumentation System.' + + str(type(exception))) diff --git a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_to_json_writer.py b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_to_json_writer.py index c9d7917..eeab56b 100644 --- a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_to_json_writer.py +++ b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_to_json_writer.py @@ -1,7 +1,9 @@ import json -from py_arg.aspic.import_export.argumentation_system_to_json_writer import ArgumentationSystemToJSONWriter -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.aspic.import_export.argumentation_system_to_json_writer import \ + ArgumentationSystemToJSONWriter +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory from py_arg.incomplete_aspic.import_export.writer import Writer @@ -10,20 +12,33 @@ def __init__(self): super().__init__() @staticmethod - def to_dict(incomplete_argumentation_theory: IncompleteArgumentationTheory): - return {'argumentation_system': ArgumentationSystemToJSONWriter().to_dict( - incomplete_argumentation_theory.argumentation_system), - 'axioms': [str(literal) for literal in incomplete_argumentation_theory.knowledge_base_axioms], - 'ordinary_premises': - [str(literal) for literal in incomplete_argumentation_theory.knowledge_base_ordinary_premises], - 'ordinary_premise_preferences': - [(str(premise_preference_tuple[0]), str(premise_preference_tuple[1])) - for premise_preference_tuple in - incomplete_argumentation_theory.ordinary_premise_preferences.preference_tuples], - 'queryables': [str(literal) for literal in incomplete_argumentation_theory.queryables] + def to_dict( + incomplete_argumentation_theory: IncompleteArgumentationTheory): + return { + 'argumentation_system': ArgumentationSystemToJSONWriter().to_dict( + incomplete_argumentation_theory.argumentation_system), + 'axioms': [str(literal) + for literal in + incomplete_argumentation_theory.knowledge_base_axioms], + 'ordinary_premises': + [str(literal) + for literal in incomplete_argumentation_theory. + knowledge_base_ordinary_premises], + 'ordinary_premise_preferences': + [(str(premise_preference_tuple[0]), + str(premise_preference_tuple[1])) + for premise_preference_tuple in + incomplete_argumentation_theory.ordinary_premise_preferences. + preference_tuples], + 'queryables': + [str(literal) + for literal in incomplete_argumentation_theory.queryables] } - def write(self, incomplete_argumentation_theory: IncompleteArgumentationTheory, file_name: str): + def write( + self, + incomplete_argumentation_theory: IncompleteArgumentationTheory, + file_name: str): write_path = self.data_folder / file_name result = self.to_dict(incomplete_argumentation_theory) with open(write_path, 'w') as write_file: diff --git a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_to_lp_file_writer.py b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_to_lp_file_writer.py index 9fd6069..7a37b0d 100644 --- a/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_to_lp_file_writer.py +++ b/src/py_arg/incomplete_aspic/import_export/incomplete_argumentation_theory_to_lp_file_writer.py @@ -1,6 +1,7 @@ from typing import Optional, List -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory from py_arg.incomplete_aspic.import_export.writer import Writer @@ -8,11 +9,15 @@ class IncompleteArgumentationTheoryToLPFileWriter(Writer): def __init__(self): super().__init__() - def write(self, incomplete_argumentation_theory: IncompleteArgumentationTheory, file_name: str, - topic_literals: Optional[List[str]] = None): + def write( + self, + incomplete_argumentation_theory: IncompleteArgumentationTheory, + file_name: str, + topic_literals: Optional[List[str]] = None): write_path = self.data_folder / file_name with open(write_path, 'w') as write_file: - for queryable in incomplete_argumentation_theory.positive_queryables: + for queryable in \ + incomplete_argumentation_theory.positive_queryables: write_file.write(f'queryable({queryable.s1.lower()}).\n') write_file.write('\n') @@ -20,20 +25,26 @@ def write(self, incomplete_argumentation_theory: IncompleteArgumentationTheory, write_file.write(f'axiom({axiom.s1.lower()}).\n') write_file.write('\n') - for literal in incomplete_argumentation_theory.argumentation_system.language.values(): + for literal in incomplete_argumentation_theory.\ + argumentation_system.language.values(): if literal.s1[0] != '-': for contrary in literal.contraries_and_contradictories: - write_file.write(f'neg({literal.s1.lower()}, {contrary.s1.lower()}).\n') + write_file.write(f'neg({literal.s1.lower()}, ' + f'{contrary.s1.lower()}).\n') write_file.write('\n') - for rule in incomplete_argumentation_theory.argumentation_system.defeasible_rules: + for rule in incomplete_argumentation_theory.\ + argumentation_system.defeasible_rules: id_rule = rule.id for antecedent in rule.antecedents: - write_file.write(f'body({str(id_rule)}, {antecedent.s1.lower()}).\n') - write_file.write(f'head({str(id_rule)}, {rule.consequent.s1.lower()}).\n') + write_file.write(f'body({str(id_rule)}, ' + f'{antecedent.s1.lower()}).\n') + write_file.write(f'head({str(id_rule)}, ' + f'{rule.consequent.s1.lower()}).\n') write_file.write('\n') - for (r1, r2) in incomplete_argumentation_theory.argumentation_system.rule_preferences.preference_tuples: + for (r1, r2) in incomplete_argumentation_theory.\ + argumentation_system.rule_preferences.preference_tuples: write_file.write(f'preferred({r1.id}, {r2.id}).\n') write_file.write('\n') diff --git a/src/py_arg/incomplete_aspic/import_export/writer.py b/src/py_arg/incomplete_aspic/import_export/writer.py index 949f0db..57eb43f 100644 --- a/src/py_arg/incomplete_aspic/import_export/writer.py +++ b/src/py_arg/incomplete_aspic/import_export/writer.py @@ -1,13 +1,17 @@ import pathlib -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory class Writer: def __init__(self): - self.data_folder = pathlib.Path(__file__).parent.parent.parent / 'experiments' / 'generated_data' + self.data_folder = pathlib.Path(__file__).parent.parent.parent \ + / 'experiments' / 'generated_data' if not self.data_folder.is_dir(): self.data_folder.mkdir() - def write(self, incomplete_argumentation_theory: IncompleteArgumentationTheory, write_path): + def write(self, + incomplete_argumentation_theory: IncompleteArgumentationTheory, + write_path): pass diff --git a/src/py_arg/utils/closure.py b/src/py_arg/utils/closure.py index 25d62d0..eea3154 100644 --- a/src/py_arg/utils/closure.py +++ b/src/py_arg/utils/closure.py @@ -12,7 +12,8 @@ def get_closure(literals: Set[Literal], strict_rules: Set[StrictRule]): interesting_strict_rules = {strict_rule for strict_rule in strict_rules if strict_rule.consequent not in closure} for strict_rule in interesting_strict_rules: - if all([antecedent in closure for antecedent in strict_rule.antecedents]): + if all([antecedent in closure + for antecedent in strict_rule.antecedents]): closure.add(strict_rule.consequent) change = True return closure diff --git a/src/py_arg/utils/fixpoint.py b/src/py_arg/utils/fixpoint.py index c9ee6a7..5b68593 100644 --- a/src/py_arg/utils/fixpoint.py +++ b/src/py_arg/utils/fixpoint.py @@ -5,7 +5,8 @@ def get_least_fixed_point(function: Callable[[T], T], function_input: T) -> T: """ - Get the least fixed point of a given function, by applying this function until the result did not change any more. + Get the least fixed point of a given function, by applying this function + until the result did not change any more. :param function: The function that should be applied iteratively. :param function_input: Initial input. diff --git a/src/py_arg/utils/is_c_consistent.py b/src/py_arg/utils/is_c_consistent.py index cb3d5a4..5fa6645 100644 --- a/src/py_arg/utils/is_c_consistent.py +++ b/src/py_arg/utils/is_c_consistent.py @@ -5,6 +5,8 @@ from py_arg.utils.closure import get_closure -def is_c_consistent(literals: Set[Literal], strict_rules: Set[StrictRule]) -> bool: +def is_c_consistent( + literals: Set[Literal], strict_rules: Set[StrictRule]) -> bool: closure = get_closure(literals, strict_rules) - return any(literal_a in literal_b.contraries_and_contradictories for literal_a in closure for literal_b in closure) + return any(literal_a in literal_b.contraries_and_contradictories + for literal_a in closure for literal_b in closure) diff --git a/src/py_arg_learning/abstract_exercise_set.py b/src/py_arg_learning/abstract_exercise_set.py index c9bc4f5..7e1fe9a 100644 --- a/src/py_arg_learning/abstract_exercise_set.py +++ b/src/py_arg_learning/abstract_exercise_set.py @@ -4,19 +4,25 @@ import dash_bootstrap_components as dbc import visdcc -from py_arg_visualisation.functions.graph_data_functions.get_af_graph_data import get_argumentation_framework_graph_data +from py_arg_visualisation.functions.graph_data_functions.get_af_graph_data \ + import get_argumentation_framework_graph_data class AbstractExerciseSet(ABC): @staticmethod def argumentation_framework_to_exercise_instance(argumentation_framework): - return ', '.join(argument.name for argument in argumentation_framework.arguments) + ';' + \ - ', '.join('(' + defeat.from_argument.name + ', ' + defeat.to_argument.name + ')' + return ', '.join( + argument.name + for argument in argumentation_framework.arguments) + ';' + \ + ', '.join('(' + defeat.from_argument.name + ', ' + + defeat.to_argument.name + ')' for defeat in argumentation_framework.defeats) @staticmethod - def argumentation_framework_to_graph_data(argumentation_framework, color_blind_mode): - return get_argumentation_framework_graph_data(argumentation_framework, None, color_blind_mode) + def argumentation_framework_to_graph_data(argumentation_framework, + color_blind_mode): + return get_argumentation_framework_graph_data( + argumentation_framework, None, color_blind_mode) @abstractmethod def get_explanation_html(self): @@ -42,5 +48,6 @@ def render_exercise_instance(self, challenge_instance, graph_data): ]) @abstractmethod - def get_feedback(self, solution_by_user: str, pre_generated_solutions: List[str]): + def get_feedback(self, solution_by_user: str, + pre_generated_solutions: List[str]): pass diff --git a/src/py_arg_learning/identify_grounded_extension.py b/src/py_arg_learning/identify_grounded_extension.py index 4b47ee4..e2bc5c6 100644 --- a/src/py_arg_learning/identify_grounded_extension.py +++ b/src/py_arg_learning/identify_grounded_extension.py @@ -1,7 +1,9 @@ from typing import List -from py_arg.abstract_argumentation.semantics.get_grounded_extension import get_grounded_extension -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import \ +from py_arg.abstract_argumentation.semantics.get_grounded_extension import \ + get_grounded_extension +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import \ AbstractArgumentationFrameworkGenerator from py_arg_learning.abstract_exercise_set import AbstractExerciseSet @@ -9,33 +11,44 @@ class IdentifyGroundedExtension(AbstractExerciseSet): def get_explanation_html(self): # TODO better explanation - return "The grounded extension is the minimal complete extension w.r.t. set inclusion." + return "The grounded extension is the minimal complete extension " \ + "w.r.t. set inclusion." def generate_exercise_and_solutions(self, color_blind_mode: bool): - argumentation_framework_generator = AbstractArgumentationFrameworkGenerator(5, 4, True) + argumentation_framework_generator = \ + AbstractArgumentationFrameworkGenerator(5, 4, True) af = argumentation_framework_generator.generate() - exercise_instance = self.argumentation_framework_to_exercise_instance(af) - graph_data = self.argumentation_framework_to_graph_data(af, color_blind_mode) + exercise_instance = \ + self.argumentation_framework_to_exercise_instance(af) + graph_data = self.argumentation_framework_to_graph_data( + af, color_blind_mode) grounded_extension = sorted(get_grounded_extension(af)) - grounded_extension_argument_names = [argument.name for argument in grounded_extension] + grounded_extension_argument_names = [ + argument.name + for argument in grounded_extension] solution = ','.join(grounded_extension_argument_names) return exercise_instance, graph_data, [solution] def render_exercise_instance_text(self, exercise_instance): exercise_instance_parts = exercise_instance.split(';') - exercise_text = 'Consider an abstract argumentation framework AF = (A, R) with A = {{{a}}} and R = {{{r}}}. ' \ - 'Which arguments belong to the grounded extension (divide by commas)?'.format( + exercise_text = 'Consider an abstract argumentation framework AF = ' \ + '(A, R) with A = {{{a}}} and R = {{{r}}}. ' \ + 'Which arguments belong to the grounded extension ' \ + '(divide by commas)?'.format( a=exercise_instance_parts[0], r=exercise_instance_parts[1]) return exercise_text - def get_feedback(self, solution_by_user: str, pre_generated_solutions: List[str]): + def get_feedback(self, solution_by_user: str, + pre_generated_solutions: List[str]): def preprocess(input_str: str) -> List[str]: for c in '{}[]': input_str = input_str.replace(c, '') - output_unsorted = [solution_part.strip() for solution_part in input_str.upper().split(',')] + output_unsorted = [ + solution_part.strip() + for solution_part in input_str.upper().split(',')] return sorted(output_unsorted) solution_learner = preprocess(solution_by_user) @@ -43,4 +56,5 @@ def preprocess(input_str: str) -> List[str]: if solution_learner == ground_truth: return 'Correct!' else: - return 'This is not correct. The right answer was ' + pre_generated_solutions[0] + '.' + return 'This is not correct. The right answer was ' + \ + pre_generated_solutions[0] + '.' diff --git a/src/py_arg_learning/list_complete_extensions.py b/src/py_arg_learning/list_complete_extensions.py index 20e5bf9..fee7d8c 100644 --- a/src/py_arg_learning/list_complete_extensions.py +++ b/src/py_arg_learning/list_complete_extensions.py @@ -1,21 +1,27 @@ from typing import List -from py_arg.abstract_argumentation.semantics.get_complete_extensions import get_complete_extensions -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import \ +from py_arg.abstract_argumentation.semantics.get_complete_extensions import \ + get_complete_extensions +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import \ AbstractArgumentationFrameworkGenerator from py_arg_learning.abstract_exercise_set import AbstractExerciseSet class ListCompleteExtensions(AbstractExerciseSet): def get_explanation_html(self): - return "A complete extension is a set of arguments that contains exactly those arguments that it defends." + return "A complete extension is a set of arguments that contains " \ + "exactly those arguments that it defends." def generate_exercise_and_solutions(self, color_blind_mode: bool): - argumentation_framework_generator = AbstractArgumentationFrameworkGenerator(4, 5, False) + argumentation_framework_generator = \ + AbstractArgumentationFrameworkGenerator(4, 5, False) af = argumentation_framework_generator.generate() - exercise_instance = self.argumentation_framework_to_exercise_instance(af) - graph_data = self.argumentation_framework_to_graph_data(af, color_blind_mode) + exercise_instance = self.argumentation_framework_to_exercise_instance( + af) + graph_data = self.argumentation_framework_to_graph_data( + af, color_blind_mode) complete_extensions = get_complete_extensions(af) complete_extensions_str_list = \ @@ -27,33 +33,47 @@ def generate_exercise_and_solutions(self, color_blind_mode: bool): def render_exercise_instance_text(self, exercise_instance): exercise_instance_parts = exercise_instance.split(';') - exercise_text = 'Consider an abstract argumentation framework AF = (A, R) with A = {{{a}}} and R = {{{r}}}. ' \ - 'List all complete extensions. Use a new line for each set, and ' \ - 'represent a set with arguments X, Y and Z as {{X, Y, Z}}.'.format( + exercise_text = 'Consider an abstract argumentation framework ' \ + 'AF = (A, R) with A = {{{a}}} and R = {{{r}}}. ' \ + 'List all complete extensions. Use a new line for ' \ + 'each set, and ' \ + 'represent a set with arguments X, Y and Z as ' \ + '{{X, Y, Z}}.'.format( a=exercise_instance_parts[0], r=exercise_instance_parts[1]) return exercise_text - def get_feedback(self, solution_by_user: str, pre_generated_solutions: List[str]): + def get_feedback(self, solution_by_user: str, + pre_generated_solutions: List[str]): solutions_learner = solution_by_user.upper() def preprocess(input_str: str) -> List[str]: for c in '{}[]': input_str = input_str.replace(c, '') - output_unsorted = [solution_part.strip() for solution_part in input_str.upper().split(',')] + output_unsorted = \ + [solution_part.strip() + for solution_part in input_str.upper().split(',')] return sorted(output_unsorted) - solutions_learner_parts = [preprocess(part) for part in solutions_learner.split('\n')] - ground_truth_parts = [preprocess(part) for part in pre_generated_solutions] + solutions_learner_parts = [preprocess(part) + for part in solutions_learner.split('\n')] + ground_truth_parts = [preprocess(part) + for part in pre_generated_solutions] - overlapping_parts = [part for part in solutions_learner_parts if part in ground_truth_parts] - missing_parts = [part for part in ground_truth_parts if part not in solutions_learner_parts] + overlapping_parts = [part for part in solutions_learner_parts + if part in ground_truth_parts] + missing_parts = [part for part in ground_truth_parts + if part not in solutions_learner_parts] - if len(solutions_learner_parts) == len(ground_truth_parts) and not missing_parts: + if len(solutions_learner_parts) == len(ground_truth_parts) and \ + not missing_parts: return 'Great! You found all complete extensions.' if len(overlapping_parts) < len(solutions_learner_parts): not_complete = ['{' + ', '.join(part) + '}' - for part in solutions_learner_parts if part not in ground_truth_parts] - return 'The following parts of your answer were not complete extensions:\n' + '\n'.join(not_complete) - return 'You missed the following complete extensions:\n' + '\n'.join(['{' + ', '.join(missing) + '}' - for missing in missing_parts]) + for part in solutions_learner_parts + if part not in ground_truth_parts] + return 'The following parts of your answer were ' \ + 'not complete extensions:\n' + '\n'.join(not_complete) + return 'You missed the following complete extensions:\n' + \ + '\n'.join(['{' + ', '.join(missing) + '}' + for missing in missing_parts]) diff --git a/src/py_arg_learning/list_preferred_extensions.py b/src/py_arg_learning/list_preferred_extensions.py index d43dd65..1077e87 100644 --- a/src/py_arg_learning/list_preferred_extensions.py +++ b/src/py_arg_learning/list_preferred_extensions.py @@ -1,21 +1,27 @@ from typing import List -from py_arg.abstract_argumentation.semantics.get_preferred_extensions import get_preferred_extensions -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import \ +from py_arg.abstract_argumentation.semantics.get_preferred_extensions \ + import get_preferred_extensions +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import \ AbstractArgumentationFrameworkGenerator from py_arg_learning.abstract_exercise_set import AbstractExerciseSet class ListPreferredExtensions(AbstractExerciseSet): def get_explanation_html(self): - return "A preferred extension is a maximal complete extensions (w.r.t. set inclusion)." + return "A preferred extension is a maximal complete extensions " \ + "(w.r.t. set inclusion)." def generate_exercise_and_solutions(self, color_blind_mode: bool): - argumentation_framework_generator = AbstractArgumentationFrameworkGenerator(4, 5, False) + argumentation_framework_generator = \ + AbstractArgumentationFrameworkGenerator(4, 5, False) af = argumentation_framework_generator.generate() - exercise_instance = self.argumentation_framework_to_exercise_instance(af) - graph_data = self.argumentation_framework_to_graph_data(af, color_blind_mode) + exercise_instance = \ + self.argumentation_framework_to_exercise_instance(af) + graph_data = self.argumentation_framework_to_graph_data( + af, color_blind_mode) preferred_extensions = get_preferred_extensions(af) preferred_extensions_str_list = \ @@ -27,33 +33,49 @@ def generate_exercise_and_solutions(self, color_blind_mode: bool): def render_exercise_instance_text(self, exercise_instance): exercise_instance_parts = exercise_instance.split(';') - exercise_text = 'Consider an abstract argumentation framework AF = (A, R) with A = {{{a}}} and R = {{{r}}}. ' \ - 'List all preferred extensions. Use a new line for each set, and ' \ - 'represent a set with arguments X, Y and Z as {{X, Y, Z}}.'.format( - a=exercise_instance_parts[0], - r=exercise_instance_parts[1]) + exercise_text = 'Consider an abstract argumentation framework ' \ + 'AF = (A, R) with A = {{{a}}} and R = {{{r}}}. ' \ + 'List all preferred extensions. Use a new line ' \ + 'for each set, and ' \ + 'represent a set with arguments X, Y and Z as ' \ + '{{X, Y, Z}}.'.format( + a=exercise_instance_parts[0], + r=exercise_instance_parts[1]) return exercise_text - def get_feedback(self, solution_by_user: str, pre_generated_solutions: List[str]): + def get_feedback(self, solution_by_user: str, + pre_generated_solutions: List[str]): solutions_learner = solution_by_user.upper() def preprocess(input_str: str) -> List[str]: for c in '{}[]': input_str = input_str.replace(c, '') - output_unsorted = [solution_part.strip() for solution_part in input_str.upper().split(',')] + output_unsorted = [ + solution_part.strip() + for solution_part in input_str.upper().split(',')] return sorted(output_unsorted) - solutions_learner_parts = [preprocess(part) for part in solutions_learner.split('\n')] - ground_truth_parts = [preprocess(part) for part in pre_generated_solutions] + solutions_learner_parts = [ + preprocess(part) for part in solutions_learner.split('\n')] + ground_truth_parts = [ + preprocess(part) for part in pre_generated_solutions] - overlapping_parts = [part for part in solutions_learner_parts if part in ground_truth_parts] - missing_parts = [part for part in ground_truth_parts if part not in solutions_learner_parts] + overlapping_parts = [ + part for part in solutions_learner_parts + if part in ground_truth_parts] + missing_parts = [ + part for part in ground_truth_parts + if part not in solutions_learner_parts] - if len(solutions_learner_parts) == len(ground_truth_parts) and not missing_parts: + if len(solutions_learner_parts) == len(ground_truth_parts) and \ + not missing_parts: return 'Great! You found all preferred extensions.' if len(overlapping_parts) < len(solutions_learner_parts): not_preferred = ['{' + ', '.join(part) + '}' - for part in solutions_learner_parts if part not in ground_truth_parts] - return 'The following parts of your answer were not preferred extensions:\n' + '\n'.join(not_preferred) - return 'You missed the following preferred extensions:\n' + '\n'.join(['{' + ', '.join(missing) + '}' - for missing in missing_parts]) + for part in solutions_learner_parts + if part not in ground_truth_parts] + return 'The following parts of your answer were not preferred ' \ + 'extensions:\n' + '\n'.join(not_preferred) + return 'You missed the following preferred extensions:\n' + \ + '\n'.join(['{' + ', '.join(missing) + '}' + for missing in missing_parts]) diff --git a/src/py_arg_tests/convert_resources.py b/src/py_arg_tests/convert_resources.py index 507b173..1a77138 100644 --- a/src/py_arg_tests/convert_resources.py +++ b/src/py_arg_tests/convert_resources.py @@ -1,7 +1,9 @@ import pathlib -from py_arg.aspic.import_export.argumentation_system_to_json_writer import ArgumentationSystemToJSONWriter -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_from_xlsx_reader import \ +from py_arg.aspic.import_export.argumentation_system_to_json_writer \ + import ArgumentationSystemToJSONWriter +from py_arg.incomplete_aspic.import_export.\ + incomplete_argumentation_theory_from_xlsx_reader import \ IncompleteArgumentationTheoryFromXLSXFileReader diff --git a/src/py_arg_tests/modgil_prakken_aij_tests.py b/src/py_arg_tests/modgil_prakken_aij_tests.py index 161d597..f948c13 100644 --- a/src/py_arg_tests/modgil_prakken_aij_tests.py +++ b/src/py_arg_tests/modgil_prakken_aij_tests.py @@ -3,17 +3,20 @@ from py_arg.aspic.classes.argumentation_system import ArgumentationSystem from py_arg.aspic.classes.argumentation_theory import ArgumentationTheory from py_arg.aspic.classes.defeasible_rule import DefeasibleRule -from py_arg.aspic.classes.orderings.argument_orderings.last_link_ordering import LastLinkElitistOrdering, \ - LastLinkDemocraticOrdering +from py_arg.aspic.classes.orderings.argument_orderings.last_link_ordering \ + import LastLinkElitistOrdering, LastLinkDemocraticOrdering from py_arg.aspic.classes.literal import Literal -from py_arg.aspic.classes.orderings.set_orderings.elitist_ordering import ElitistOrdering +from py_arg.aspic.classes.orderings.set_orderings.elitist_ordering import \ + ElitistOrdering from py_arg.aspic.classes.strict_rule import StrictRule -from py_arg.aspic.classes.orderings.argument_orderings.weakest_link_ordering import WeakestLinkElitistOrdering, \ - WeakestLinkDemocraticOrdering +from py_arg.aspic.classes.orderings.argument_orderings.weakest_link_ordering \ + import WeakestLinkElitistOrdering, WeakestLinkDemocraticOrdering from py_arg.aspic.classes.instantiated_argument import InstantiatedArgument -def get_argumentation_theory(include_d: bool = False, include_e: bool = False) -> ArgumentationTheory: +def get_argumentation_theory( + include_d: bool = False, include_e: bool = False) -> \ + ArgumentationTheory: literal_str_list = ['a', 'p', 'q', 'r', 's', 't'] if include_d: @@ -25,14 +28,18 @@ def get_argumentation_theory(include_d: bool = False, include_e: bool = False) - language = {literal_str: Literal(literal_str) for literal_str in literal_str_list} - contraries_and_contradictories = {literal_str: [] for literal_str in language.keys()} + contraries_and_contradictories = {literal_str: [] + for literal_str in language.keys()} for literal_str in language.keys(): if literal_str[0] in ('~', '-'): - contraries_and_contradictories[literal_str].append(language[literal_str[1:]]) + contraries_and_contradictories[literal_str].append( + language[literal_str[1:]]) else: - contraries_and_contradictories[literal_str].append(language['-' + literal_str]) + contraries_and_contradictories[literal_str].append( + language['-' + literal_str]) - strict_rules = [StrictRule('s1', {language['t'], language['q']}, language['-p'])] + strict_rules = [StrictRule('s1', {language['t'], language['q']}, + language['-p'])] d1 = DefeasibleRule('d1', {language['~s']}, language['t']) d2 = DefeasibleRule('d2', {language['r']}, language['q']) @@ -40,23 +47,30 @@ def get_argumentation_theory(include_d: bool = False, include_e: bool = False) - defeasible_rules = [d1, d2, d3] if include_d: - defeasible_rules.append(DefeasibleRule('d4', {language['~d']}, language['s'])) + defeasible_rules.append( + DefeasibleRule('d4', {language['~d']}, language['s'])) for defeasible_rule in defeasible_rules: defeasible_rule_literal = Literal.from_defeasible_rule(defeasible_rule) - defeasible_rule_literal_negation = Literal.from_defeasible_rule_negation(defeasible_rule) + defeasible_rule_literal_negation = \ + Literal.from_defeasible_rule_negation(defeasible_rule) language[str(defeasible_rule_literal)] = defeasible_rule_literal - language[str(defeasible_rule_literal_negation)] = defeasible_rule_literal_negation - contraries_and_contradictories[str(defeasible_rule_literal)] = [defeasible_rule_literal_negation] - contraries_and_contradictories[str(defeasible_rule_literal_negation)] = [defeasible_rule_literal] + language[str(defeasible_rule_literal_negation)] = \ + defeasible_rule_literal_negation + contraries_and_contradictories[str(defeasible_rule_literal)] = \ + [defeasible_rule_literal_negation] + contraries_and_contradictories[ + str(defeasible_rule_literal_negation)] = [defeasible_rule_literal] if include_e: strict_rules.append(StrictRule('s2', {language['r']}, language['-d3'])) - arg_sys = ArgumentationSystem(language, contraries_and_contradictories, strict_rules, defeasible_rules) + arg_sys = ArgumentationSystem(language, contraries_and_contradictories, + strict_rules, defeasible_rules) axioms = [] - ordinary_premises = [language[literal_str] for literal_str in ['a', 'r', '-r', '~s']] + ordinary_premises = [language[literal_str] + for literal_str in ['a', 'r', '-r', '~s']] if include_d: ordinary_premises.append(language['~d']) @@ -67,7 +81,8 @@ def get_argumentation_theory(include_d: bool = False, include_e: bool = False) - class TestModgilPrakkenAIJ(unittest.TestCase): """ - This class tests the running example from: S.J. Modgil & H. Prakken, A general account of argumentation with + This class tests the running example from: S.J. Modgil & H. Prakken, + A general account of argumentation with preferences. Artificial Intelligence 195 (2013): 361-397. """ def test_contradiction_function(self): @@ -105,9 +120,11 @@ def test_arguments(self): language = arg_theory.argumentation_system.language args_per_literal = arg_theory.arguments all_args = set().union(*args_per_literal.values()) - arg_a_prime = InstantiatedArgument.ordinary_premise_based(language['a']) + arg_a_prime = InstantiatedArgument.ordinary_premise_based( + language['a']) arg_a = InstantiatedArgument.defeasible_rule_based( - DefeasibleRule('d3', {language['a']}, language['p']), {arg_a_prime}) + DefeasibleRule( + 'd3', {language['a']}, language['p']), {arg_a_prime}) arg_b1 = InstantiatedArgument.ordinary_premise_based(language['~s']) arg_b1_prime = InstantiatedArgument.defeasible_rule_based( DefeasibleRule('d1', {language['~s']}, language['t']), {arg_b1}) @@ -115,21 +132,27 @@ def test_arguments(self): arg_b2_prime = InstantiatedArgument.defeasible_rule_based( DefeasibleRule('d2', {language['r']}, language['q']), {arg_b2}) arg_b = InstantiatedArgument.strict_rule_based( - StrictRule('s1', {language['t'], language['q']}, language['-p']), {arg_b2_prime, arg_b1_prime}) + StrictRule('s1', {language['t'], language['q']}, language['-p']), + {arg_b2_prime, arg_b1_prime}) arg_c = InstantiatedArgument.ordinary_premise_based(language['-r']) self.assertListEqual(sorted(all_args), - sorted([arg_a_prime, arg_a, arg_b1, arg_b1_prime, arg_b2, arg_b2_prime, arg_b, arg_c])) + sorted([arg_a_prime, arg_a, arg_b1, arg_b1_prime, + arg_b2, arg_b2_prime, arg_b, arg_c])) self.assertSetEqual(arg_b.premises, {language['~s'], language['r']}) self.assertEqual(arg_b.conclusion, language['-p']) # Note: incorrect in paper! - self.assertSetEqual(arg_b.sub_arguments, {arg_b1, arg_b2, arg_b1_prime, arg_b2_prime, arg_b}) - self.assertEqual(arg_b.top_rule, StrictRule('s1', {language['t'], language['q']}, language['-p'])) + self.assertSetEqual(arg_b.sub_arguments, {arg_b1, arg_b2, arg_b1_prime, + arg_b2_prime, arg_b}) + self.assertEqual(arg_b.top_rule, + StrictRule('s1', {language['t'], language['q']}, + language['-p'])) self.assertSetEqual(arg_b.defeasible_rules, { DefeasibleRule('d1', {language['~s']}, language['t']), DefeasibleRule('d2', {language['r']}, language['q']) }) - self.assertSetEqual(arg_b.strict_rules, {StrictRule('s1', {language['t'], language['q']}, language['-p'])}) + self.assertSetEqual(arg_b.strict_rules, {StrictRule( + 's1', {language['t'], language['q']}, language['-p'])}) # Test attacks self.assertTrue(arg_theory.rebuts(arg_b, arg_a)) @@ -142,14 +165,15 @@ def test_arguments(self): arg_theory = get_argumentation_theory(include_d=True) language = arg_theory.argumentation_system.language arg_d1 = InstantiatedArgument.ordinary_premise_based(language['~d']) - arg_d2 = InstantiatedArgument.defeasible_rule_based(DefeasibleRule('d4', {language['~d']}, language['s']), - {arg_d1}) + arg_d2 = InstantiatedArgument.defeasible_rule_based(DefeasibleRule( + 'd4', {language['~d']}, language['s']), {arg_d1}) self.assertTrue(arg_theory.contrary_undermines(arg_d2, arg_b)) self.assertTrue(arg_theory.contrary_undermines(arg_d2, arg_b1)) self.assertTrue(arg_theory.contrary_undermines(arg_d2, arg_b1_prime)) arg_theory = get_argumentation_theory(include_d=True, include_e=True) - arg_e = InstantiatedArgument.strict_rule_based(arg_theory.argumentation_system.strict_rules[1], {arg_b2}) + arg_e = InstantiatedArgument.strict_rule_based( + arg_theory.argumentation_system.strict_rules[1], {arg_b2}) self.assertTrue(arg_theory.undercuts(arg_e, arg_a)) # Test defeats @@ -158,36 +182,52 @@ def test_arguments(self): d3 = DefeasibleRule('d3', {language['a']}, language['p']) arg_theory.argumentation_system.rule_preferences.append((d2, d3)) - arg_theory.ordinary_premise_preferences.append((language['-r'], language['r'])) - arg_theory.ordinary_premise_preferences.append((language['~s'], language['-r'])) + arg_theory.ordinary_premise_preferences.append( + (language['-r'], language['r'])) + arg_theory.ordinary_premise_preferences.append( + (language['~s'], language['-r'])) - self.assertSetEqual(arg_a.defeasible_rules, arg_a.last_defeasible_rules, {d3}) + self.assertSetEqual(arg_a.defeasible_rules, + arg_a.last_defeasible_rules, {d3}) self.assertSetEqual(arg_a.ordinary_premises, {language['a']}) - self.assertSetEqual(arg_a_prime.defeasible_rules, arg_a_prime.last_defeasible_rules, set()) + self.assertSetEqual(arg_a_prime.defeasible_rules, + arg_a_prime.last_defeasible_rules, set()) self.assertSetEqual(arg_a_prime.ordinary_premises, {language['a']}) - self.assertSetEqual(arg_b.defeasible_rules, arg_b.last_defeasible_rules, {d1, d2}) - self.assertSetEqual(arg_b.ordinary_premises, {language['~s'], language['r']}) - self.assertSetEqual(arg_b2.defeasible_rules, arg_b2.last_defeasible_rules, set()) + self.assertSetEqual(arg_b.defeasible_rules, + arg_b.last_defeasible_rules, {d1, d2}) + self.assertSetEqual(arg_b.ordinary_premises, + {language['~s'], language['r']}) + self.assertSetEqual(arg_b2.defeasible_rules, + arg_b2.last_defeasible_rules, set()) self.assertSetEqual(arg_b2.ordinary_premises, {language['r']}) - self.assertSetEqual(arg_c.defeasible_rules, arg_c.last_defeasible_rules, set()) + self.assertSetEqual(arg_c.defeasible_rules, + arg_c.last_defeasible_rules, set()) self.assertSetEqual(arg_c.premises, {language['-r']}) - eli = ElitistOrdering(arg_theory.argumentation_system.rule_preferences, arg_theory.ordinary_premise_preferences) - self.assertTrue(eli.rule_set_is_strictly_weaker_than(arg_b.last_defeasible_rules, arg_a.last_defeasible_rules)) - ell = LastLinkElitistOrdering(arg_theory.argumentation_system.rule_preferences, - arg_theory.ordinary_premise_preferences) + eli = ElitistOrdering( + arg_theory.argumentation_system.rule_preferences, + arg_theory.ordinary_premise_preferences) + self.assertTrue(eli.rule_set_is_strictly_weaker_than( + arg_b.last_defeasible_rules, arg_a.last_defeasible_rules)) + ell = LastLinkElitistOrdering( + arg_theory.argumentation_system.rule_preferences, + arg_theory.ordinary_premise_preferences) self.assertTrue(ell.argument_is_strictly_weaker_than(arg_b, arg_a)) - self.assertTrue(eli.rule_set_is_strictly_weaker_than(arg_b.defeasible_rules, arg_a.defeasible_rules)) - self.assertFalse(eli.ordinary_premise_set_is_strictly_weaker_than(arg_b.ordinary_premises, - arg_a.ordinary_premises)) - ewl = WeakestLinkElitistOrdering(arg_theory.argumentation_system.rule_preferences, - arg_theory.ordinary_premise_preferences) + self.assertTrue(eli.rule_set_is_strictly_weaker_than( + arg_b.defeasible_rules, arg_a.defeasible_rules)) + self.assertFalse(eli.ordinary_premise_set_is_strictly_weaker_than( + arg_b.ordinary_premises, arg_a.ordinary_premises)) + ewl = WeakestLinkElitistOrdering( + arg_theory.argumentation_system.rule_preferences, + arg_theory.ordinary_premise_preferences) self.assertFalse(ewl.argument_is_strictly_weaker_than(arg_b, arg_a)) - dll = LastLinkDemocraticOrdering(arg_theory.argumentation_system.rule_preferences, - arg_theory.ordinary_premise_preferences) + dll = LastLinkDemocraticOrdering( + arg_theory.argumentation_system.rule_preferences, + arg_theory.ordinary_premise_preferences) self.assertFalse(dll.argument_is_strictly_weaker_than(arg_b, arg_a)) - dwl = WeakestLinkDemocraticOrdering(arg_theory.argumentation_system.rule_preferences, - arg_theory.ordinary_premise_preferences) + dwl = WeakestLinkDemocraticOrdering( + arg_theory.argumentation_system.rule_preferences, + arg_theory.ordinary_premise_preferences) self.assertFalse(dwl.argument_is_strictly_weaker_than(arg_b, arg_a)) self.assertTrue(ell.argument_is_strictly_weaker_than(arg_c, arg_b2)) self.assertTrue(ewl.argument_is_strictly_weaker_than(arg_c, arg_b2)) @@ -200,9 +240,10 @@ def test_arguments(self): self.assertTrue(arg_theory.defeats(arg_b2, arg_c, ell)) arg_d1 = InstantiatedArgument.ordinary_premise_based(language['~d']) - arg_d2 = InstantiatedArgument.defeasible_rule_based(DefeasibleRule('d4', {language['~d']}, language['s']), - {arg_d1}) - arg_e = InstantiatedArgument.strict_rule_based(arg_theory.argumentation_system.strict_rules[1], {arg_b2}) + arg_d2 = InstantiatedArgument.defeasible_rule_based( + DefeasibleRule('d4', {language['~d']}, language['s']), {arg_d1}) + arg_e = InstantiatedArgument.strict_rule_based( + arg_theory.argumentation_system.strict_rules[1], {arg_b2}) self.assertTrue(arg_theory.defeats(arg_d2, arg_b1_prime, ell)) self.assertTrue(arg_theory.defeats(arg_d2, arg_b, ell)) diff --git a/src/py_arg_tests/test_aba_canonical_constructions.py b/src/py_arg_tests/test_aba_canonical_constructions.py index 00d4d56..c914218 100644 --- a/src/py_arg_tests/test_aba_canonical_constructions.py +++ b/src/py_arg_tests/test_aba_canonical_constructions.py @@ -1,26 +1,37 @@ import unittest -import py_arg.assumption_based_argumentation.canonical_constructions.canonical_st as canonical_st -import py_arg.assumption_based_argumentation.canonical_constructions.construct_abaf_cf as construct_abaf_cf -import py_arg.assumption_based_argumentation.canonical_constructions.construct_abaf_com as construct_abaf_com -from py_arg.assumption_based_argumentation.canonical_constructions import construct_abaf_adm -import py_arg.abstract_argumentation.canonical_constructions.check_intersection_in as check_intersection_in -import py_arg.abstract_argumentation.canonical_constructions.check_union_closed as check_union_closed -import py_arg.abstract_argumentation.canonical_constructions.check_set_com_closed as check_set_com_closed -import py_arg.abstract_argumentation.canonical_constructions.check_downward_closed as check_downward_closed -import py_arg.abstract_argumentation.canonical_constructions.aux_operators as aux - -from py_arg.assumption_based_argumentation.semantics import get_complete_extensions as get_complete_extensions -from py_arg.assumption_based_argumentation.semantics import get_conflict_free_extensions as get_conflict_free_extensions, \ - get_stable_extensions as get_stable_extensions, get_admissible_extensions as get_admissible_extensions - -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -from py_arg.assumption_based_argumentation.classes.instantiated_argument import InstantiatedArgument -from py_arg.assumption_based_argumentation.classes.rule import Rule - +import py_arg.abstract_argumentation.canonical_constructions. \ + aux_operators as aux +import py_arg.abstract_argumentation.canonical_constructions. \ + check_contains_empty as check_contains_empty +import py_arg.abstract_argumentation.canonical_constructions. \ + check_downward_closed as check_downward_closed +import py_arg.abstract_argumentation.canonical_constructions. \ + check_intersection_in as check_intersection_in +import py_arg.abstract_argumentation.canonical_constructions. \ + check_set_com_closed as check_set_com_closed +import py_arg.abstract_argumentation.canonical_constructions. \ + check_union_closed as check_union_closed +import py_arg.assumption_based_argumentation.canonical_constructions. \ + canonical_st as canonical_st +import py_arg.assumption_based_argumentation.canonical_constructions. \ + construct_abaf_cf as construct_abaf_cf +import py_arg.assumption_based_argumentation.canonical_constructions. \ + construct_abaf_com as construct_abaf_com from py_arg.abstract_argumentation.classes.defeat import Defeat - -import py_arg.abstract_argumentation.canonical_constructions.check_contains_empty as check_contains_empty +from py_arg.assumption_based_argumentation.canonical_constructions \ + import construct_abaf_adm +from py_arg.assumption_based_argumentation.classes.aba_framework \ + import AssumptionBasedArgumentationFramework +from py_arg.assumption_based_argumentation.classes.instantiated_argument \ + import InstantiatedArgument +from py_arg.assumption_based_argumentation.classes.rule import Rule +from py_arg.assumption_based_argumentation.semantics import \ + get_complete_extensions as get_complete_extensions +from py_arg.assumption_based_argumentation.semantics import \ + get_conflict_free_extensions as get_conflict_free_extensions, \ + get_stable_extensions as get_stable_extensions, get_admissible_extensions \ + as get_admissible_extensions class TestCanonicalConstructions(unittest.TestCase): @@ -50,7 +61,8 @@ def test_instantiation(self): r_5 = Rule('', set(), q) rules = {r_1, r_2, r_3, r_4, r_5} - aba = AssumptionBasedArgumentationFramework(assumptions, rules, atoms, contraries) + aba = AssumptionBasedArgumentationFramework(assumptions, rules, atoms, + contraries) af = aba.generate_af() a_to_a = InstantiatedArgument('', {a}, a) @@ -139,53 +151,42 @@ def test_canonical_stb(self): a_c = 'a_c' b_c = 'b_c' c_c = 'c_c' - x_a = 'x_a' - x_b = 'x_b' - x_c = 'x_c' - x_a_c = 'x_a_c' - x_b_c = 'x_b_c' - x_c_c = 'x_c_c' - set_empty = frozenset({}) set_a = frozenset({a}) set_b = frozenset({b}) set_c = frozenset({c}) set_ab = frozenset({a, b}) set_ac = frozenset({a, c}) set_bc = frozenset({b, c}) - set_abc = frozenset({a, b, c}) es1 = {set_ab, set_ac, set_bc} canonical_aba1 = canonical_st.apply(es1) self.assertEqual(canonical_aba1.assumptions, {a, b, c}) self.assertEqual(canonical_aba1.language, {a, b, c, a_c, b_c, c_c}) - self.assertEqual(canonical_aba1.rules, {Rule('', {a, b}, c_c), Rule('', {a, c}, b_c), Rule('', {b, c}, a_c)}) + self.assertEqual( + canonical_aba1.rules, + {Rule('', {a, b}, c_c), Rule('', {a, c}, b_c), + Rule('', {b, c}, a_c)}) self.assertEqual(canonical_aba1.contraries, {a: a_c, b: b_c, c: c_c}) - self.assertEqual(get_stable_extensions.get_stable_extensions(canonical_aba1), es1) + self.assertEqual( + get_stable_extensions.get_stable_extensions(canonical_aba1), es1) es2 = {set_a, set_b, set_c} canonical_aba2 = canonical_st.apply(es2) self.assertEqual(canonical_aba2.assumptions, {a, b, c}) self.assertEqual(canonical_aba2.language, {a, b, c, a_c, b_c, c_c}) - self.assertEqual(canonical_aba2.rules, {Rule('', {a}, b_c), Rule('', {a}, c_c), - Rule('', {b}, a_c), Rule('', {b}, c_c), - Rule('', {c}, a_c), Rule('', {c}, b_c)}) + self.assertEqual(canonical_aba2.rules, { + Rule('', {a}, b_c), Rule('', {a}, c_c), + Rule('', {b}, a_c), Rule('', {b}, c_c), + Rule('', {c}, a_c), Rule('', {c}, b_c)}) self.assertEqual(canonical_aba2.contraries, {a: a_c, b: b_c, c: c_c}) - self.assertEqual(get_stable_extensions.get_stable_extensions(canonical_aba2), es2) + self.assertEqual( + get_stable_extensions.get_stable_extensions(canonical_aba2), es2) def test_canonical_cf(self): a = 'a' b = 'b' c = 'c' - a_c = 'a_c' - b_c = 'b_c' - c_c = 'c_c' - x_a = 'x_a' - x_b = 'x_b' - x_c = 'x_c' - x_a_c = 'x_a_c' - x_b_c = 'x_b_c' - x_c_c = 'x_c_c' set_empty = frozenset({}) set_a = frozenset({a}) @@ -194,7 +195,6 @@ def test_canonical_cf(self): set_ab = frozenset({a, b}) set_ac = frozenset({a, c}) set_bc = frozenset({b, c}) - set_abc = frozenset({a, b, c}) es1 = {set_empty, set_a, set_b, set_c, set_ab} aba = construct_abaf_cf.apply(es1) @@ -210,19 +210,8 @@ def test_canonical_adm(self): a = 'a' b = 'b' c = 'c' - a_c = 'a_c' - b_c = 'b_c' - c_c = 'c_c' - x_a = 'x_a' - x_b = 'x_b' - x_c = 'x_c' - x_a_c = 'x_a_c' - x_b_c = 'x_b_c' - x_c_c = 'x_c_c' set_empty = frozenset({}) - set_a = frozenset({a}) - set_b = frozenset({b}) set_c = frozenset({c}) set_ab = frozenset({a, b}) set_ac = frozenset({a, c}) @@ -232,14 +221,16 @@ def test_canonical_adm(self): es1 = {set_empty, set_c, set_ab, set_abc} canonical_aba1 = construct_abaf_adm.apply(es1) canonical_aba1.reduce() - es_n = get_admissible_extensions.get_admissible_extensions(canonical_aba1) + es_n = get_admissible_extensions.get_admissible_extensions( + canonical_aba1) self.assertEqual(es1, es_n) es2 = {set_empty, set_ab, set_ac, set_bc} canonical_aba2 = construct_abaf_adm.apply(es2) canonical_aba2.reduce() - es_n = get_admissible_extensions.get_admissible_extensions(canonical_aba2) + es_n = get_admissible_extensions.get_admissible_extensions( + canonical_aba2) self.assertEqual(es2, es_n) @@ -248,35 +239,13 @@ def test_canonical_com(self): b = 'b' c = 'c' d = 'd' - a_c = 'a_c' - b_c = 'b_c' - c_c = 'c_c' - d_c = 'd_c' - x_a = 'x_a' - x_b = 'x_b' - x_c = 'x_c' - x_d = 'x_d' - x_a_c = 'x_a_c' - x_b_c = 'x_b_c' - x_c_c = 'x_c_c' - x_d_c = 'x_d_c' set_empty = frozenset({}) - set_a = frozenset({a}) - set_b = frozenset({b}) set_c = frozenset({c}) set_d = frozenset({d}) set_ab = frozenset({a, b}) - set_ac = frozenset({a, c}) - set_ad = frozenset({a, d}) - set_bc = frozenset({b, c}) - set_bd = frozenset({b, d}) set_cd = frozenset({c, d}) set_abc = frozenset({a, b, c}) - set_abd = frozenset({a, b, d}) - set_acd = frozenset({a, c, d}) - set_bcd = frozenset({b, c, d}) - set_abcd = frozenset({a, b, c, d}) es1 = {set_empty, set_c, set_d, set_cd, set_ab, set_abc} diff --git a/src/py_arg_tests/test_aba_lasagne_example.py b/src/py_arg_tests/test_aba_lasagne_example.py index 9c8fb14..be98e80 100644 --- a/src/py_arg_tests/test_aba_lasagne_example.py +++ b/src/py_arg_tests/test_aba_lasagne_example.py @@ -1,8 +1,10 @@ import unittest +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework from py_arg.assumption_based_argumentation.classes.rule import Rule -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -from py_arg.assumption_based_argumentation.semantics import get_preferred_extensions +from py_arg.assumption_based_argumentation.semantics import \ + get_preferred_extensions class TestABALasagneExample(unittest.TestCase): @@ -23,7 +25,11 @@ def test_aba_lasagne_example(self): 'no_fork': 'fork', 'dirty_hands': 'clean_hands'} - aba_framework = AssumptionBasedArgumentationFramework(assumptions, rules, language, contraries) + aba_framework = AssumptionBasedArgumentationFramework(assumptions, + rules, language, + contraries) # Get preferred extensions - extensions = get_preferred_extensions.get_preferred_extensions(aba_framework) - self.assertSetEqual(extensions, {frozenset({'dirty_hands', 'no_fork'})}) \ No newline at end of file + extensions = get_preferred_extensions.get_preferred_extensions( + aba_framework) + self.assertSetEqual(extensions, + {frozenset({'dirty_hands', 'no_fork'})}) diff --git a/src/py_arg_tests/test_aba_semantics.py b/src/py_arg_tests/test_aba_semantics.py index a1e5e4d..ed5414e 100644 --- a/src/py_arg_tests/test_aba_semantics.py +++ b/src/py_arg_tests/test_aba_semantics.py @@ -1,7 +1,7 @@ import unittest -import py_arg.assumption_based_argumentation.canonical_constructions.canonical_st as canonical_st - +import py_arg.assumption_based_argumentation.canonical_constructions.\ + canonical_st as canonical_st from py_arg.assumption_based_argumentation.classes.rule import Rule @@ -14,27 +14,17 @@ def test_canonical_stb(self): a_c = 'a_c' b_c = 'b_c' c_c = 'c_c' - x_a = 'x_a' - x_b = 'x_b' - x_c = 'x_c' - x_a_c = 'x_a_c' - x_b_c = 'x_b_c' - x_c_c = 'x_c_c' - set_empty = frozenset({}) - set_a = frozenset({a}) - set_b = frozenset({b}) - set_c = frozenset({c}) set_ab = frozenset({a, b}) set_ac = frozenset({a, c}) set_bc = frozenset({b, c}) - set_abc = frozenset({a, b, c}) es1 = {set_ab, set_ac, set_bc} canonical_aba1 = canonical_st.apply(es1) self.assertEqual(canonical_aba1.assumptions, {a, b, c}) self.assertEqual(canonical_aba1.language, {a, b, c, a_c, b_c, c_c}) - self.assertEqual(canonical_aba1.rules, {Rule('', {a, b}, c_c), Rule('', {a, c}, b_c), Rule('', {b, c}, a_c)}) + self.assertEqual(canonical_aba1.rules, + {Rule('', {a, b}, c_c), Rule('', {a, c}, b_c), + Rule('', {b, c}, a_c)}) self.assertEqual(canonical_aba1.contraries, {a: a_c, b: b_c, c: c_c}) - diff --git a/src/py_arg_tests/test_af_canonical_constructions.py b/src/py_arg_tests/test_af_canonical_constructions.py index 28e975e..956b826 100644 --- a/src/py_arg_tests/test_af_canonical_constructions.py +++ b/src/py_arg_tests/test_af_canonical_constructions.py @@ -1,19 +1,29 @@ import unittest -import py_arg.abstract_argumentation.semantics.get_stable_extensions as get_stable_extensions -import py_arg.abstract_argumentation.canonical_constructions.check_com_closed as check_com_closed -import py_arg.abstract_argumentation.canonical_constructions.check_set_com_closed as check_set_com_closed -import py_arg.abstract_argumentation.canonical_constructions.check_conf_sens as check_conf_sens -import py_arg.abstract_argumentation.canonical_constructions.check_set_conf_sens as check_set_conf_sens - -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_cf as canonical_cf -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_st as canonical_st -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_def as canonical_def - -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +import py_arg.abstract_argumentation.semantics.get_stable_extensions as \ + get_stable_extensions +import py_arg.abstract_argumentation.canonical_constructions.check_com_closed \ + as check_com_closed +import py_arg.abstract_argumentation.canonical_constructions.\ + check_set_com_closed as check_set_com_closed +import py_arg.abstract_argumentation.canonical_constructions.\ + check_conf_sens as check_conf_sens +import py_arg.abstract_argumentation.canonical_constructions.\ + check_set_conf_sens as check_set_conf_sens + +import py_arg.abstract_argumentation.canonical_constructions.\ + canonical_af.canonical_cf as canonical_cf +import py_arg.abstract_argumentation.canonical_constructions.\ + canonical_af.canonical_st as canonical_st +import py_arg.abstract_argumentation.canonical_constructions.\ + canonical_af.canonical_def as canonical_def + +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.canonical_constructions import aux_operators, check_incomparable, check_tight +from py_arg.abstract_argumentation.canonical_constructions import \ + aux_operators, check_incomparable, check_tight class TestCanonicalConstructions(unittest.TestCase): @@ -65,10 +75,12 @@ def test_construct_af(self): def2 = Defeat(a, c) def3 = Defeat(b, c) - af = AbstractArgumentationFramework('', arguments=[a, b, c], defeats=[def1, def2, def3]) + af = AbstractArgumentationFramework('', arguments=[a, b, c], + defeats=[def1, def2, def3]) print(af.arguments) for defeat in af.defeats: - print(defeat.from_argument.name + ' attacks ' + defeat.to_argument.name) + print(defeat.from_argument.name + ' attacks ' + + defeat.to_argument.name) def test_cf_construction(self): a = Argument('a') @@ -86,7 +98,8 @@ def test_cf_construction(self): af_cf = canonical_cf.apply(es) print(af_cf.arguments) for defeat in af_cf.defeats: - print(defeat.from_argument.name + ' attacks ' + defeat.to_argument.name) + print(defeat.from_argument.name + ' attacks ' + + defeat.to_argument.name) def test_sem_stb(self): a = Argument('a') @@ -96,7 +109,8 @@ def test_sem_stb(self): def2 = Defeat(b, a) def3 = Defeat(b, c) - af = AbstractArgumentationFramework('', arguments=[a, b, c], defeats=[def1, def2, def3]) + af = AbstractArgumentationFramework('', arguments=[a, b, c], + defeats=[def1, def2, def3]) stable_ext = get_stable_extensions.get_stable_extensions(af) @@ -118,7 +132,8 @@ def test_st_construction(self): af = canonical_st.apply(es) print(af.arguments) for defeats in af.defeats: - print(defeats.from_argument.name + ' attacks ' + defeats.to_argument.name) + print(defeats.from_argument.name + ' attacks ' + + defeats.to_argument.name) def test_defence_formula(self): a = Argument('a') @@ -155,4 +170,5 @@ def test_canonical_def(self): print(af.arguments) for defeat in af.defeats: - print(defeat.from_argument.name + ' attacks ' + defeat.to_argument.name) + print(defeat.from_argument.name + ' attacks ' + + defeat.to_argument.name) diff --git a/src/py_arg_tests/test_af_canonical_constructions_with_generator.py b/src/py_arg_tests/test_af_canonical_constructions_with_generator.py index 440737b..fa5de66 100644 --- a/src/py_arg_tests/test_af_canonical_constructions_with_generator.py +++ b/src/py_arg_tests/test_af_canonical_constructions_with_generator.py @@ -1,22 +1,29 @@ import unittest -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.canonical_cf as canonical_cf - -from py_arg.abstract_argumentation.canonical_constructions import check_incomparable, check_conf_sens, check_tight -from py_arg.abstract_argumentation.canonical_constructions.canonical_af import construct_af_adm, construct_af_grd -from py_arg.abstract_argumentation.canonical_constructions.canonical_af import construct_af_stb -from py_arg.abstract_argumentation.semantics import get_grounded_extension, get_stable_extensions, get_admissible_sets -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator \ +import py_arg.abstract_argumentation.canonical_constructions.canonical_af. \ + canonical_cf as canonical_cf +from py_arg.abstract_argumentation.canonical_constructions \ + import check_incomparable, check_conf_sens, check_tight +from py_arg.abstract_argumentation.canonical_constructions.canonical_af \ + import construct_af_adm, construct_af_grd +from py_arg.abstract_argumentation.canonical_constructions.canonical_af \ + import construct_af_stb +from py_arg.abstract_argumentation.generators. \ + abstract_argumentation_framework_generator \ import AbstractArgumentationFrameworkGenerator +from py_arg.abstract_argumentation.semantics import get_grounded_extension, \ + get_stable_extensions, get_admissible_sets class TestCanonicalConstructions(unittest.TestCase): def test_grd_construction(self): af = AbstractArgumentationFrameworkGenerator(9, 8).generate() - es_original = {frozenset(get_grounded_extension.get_grounded_extension(af))} + es_original = { + frozenset(get_grounded_extension.get_grounded_extension(af))} af_cf = canonical_cf.apply(es_original) - es_new = {frozenset(get_grounded_extension.get_grounded_extension(af_cf))} + es_new = { + frozenset(get_grounded_extension.get_grounded_extension(af_cf))} self.assertEqual(es_original, es_new) self.assertEqual(len(es_new), 1) @@ -27,14 +34,17 @@ def test_adm_construction(self): af_adm = construct_af_adm.apply(es_original) es_new = get_admissible_sets.get_admissible_sets(af_adm) - self.assertTrue(check_conf_sens.apply(es_original) and frozenset() in es_original) + self.assertTrue( + check_conf_sens.apply(es_original) and frozenset() in es_original) self.assertEqual(es_original, es_new) - def test_grd_construction(self): + def test_grd_construction_small(self): af = AbstractArgumentationFrameworkGenerator(5, 5).generate() - es_original = {frozenset(get_grounded_extension.get_grounded_extension(af))} + es_original = { + frozenset(get_grounded_extension.get_grounded_extension(af))} af_grd = construct_af_grd.apply(es_original) - es_new = {frozenset(get_grounded_extension.get_grounded_extension(af_grd))} + es_new = { + frozenset(get_grounded_extension.get_grounded_extension(af_grd))} self.assertEqual(es_original, es_new) @@ -44,5 +54,7 @@ def test_stb_construction(self): af_stb = construct_af_stb.apply(es_original) es_new = get_stable_extensions.get_stable_extensions(af_stb) - self.assertTrue(check_incomparable.apply(es_original) and check_tight.apply(es_original)) + self.assertTrue( + check_incomparable.apply(es_original) and check_tight.apply( + es_original)) self.assertEqual(es_original, es_new) diff --git a/src/py_arg_tests/test_af_complete_semantics.py b/src/py_arg_tests/test_af_complete_semantics.py index 7ddc652..77e46e5 100644 --- a/src/py_arg_tests/test_af_complete_semantics.py +++ b/src/py_arg_tests/test_af_complete_semantics.py @@ -1,9 +1,11 @@ import unittest -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.semantics.get_complete_extensions import get_complete_extensions +from py_arg.abstract_argumentation.semantics.get_complete_extensions import \ + get_complete_extensions class TestAFCompleteSemantics(unittest.TestCase): diff --git a/src/py_arg_tests/test_af_from_apx.py b/src/py_arg_tests/test_af_from_apx.py index 5d77b68..ddc94dc 100644 --- a/src/py_arg_tests/test_af_from_apx.py +++ b/src/py_arg_tests/test_af_from_apx.py @@ -1,6 +1,7 @@ import unittest -from py_arg.abstract_argumentation.import_export.argumentation_framework_from_aspartix_format_reader import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_from_aspartix_format_reader import \ ArgumentationFrameworkFromASPARTIXFormatReader @@ -12,6 +13,7 @@ def test_af_from_apx(self): 'att(A, B).\n' \ 'att(B, C).\n' \ 'att(B, A).\n' - af = ArgumentationFrameworkFromASPARTIXFormatReader.from_apx(test_file_str) + af = ArgumentationFrameworkFromASPARTIXFormatReader.from_apx( + test_file_str) self.assertEqual(len(af.arguments), 3) self.assertEqual(len(af.defeats), 3) diff --git a/src/py_arg_tests/test_af_from_scratch.py b/src/py_arg_tests/test_af_from_scratch.py index 7d96ba9..cbc90f5 100644 --- a/src/py_arg_tests/test_af_from_scratch.py +++ b/src/py_arg_tests/test_af_from_scratch.py @@ -1,6 +1,7 @@ import unittest -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat diff --git a/src/py_arg_tests/test_af_generator.py b/src/py_arg_tests/test_af_generator.py index 0c91e96..98e168c 100644 --- a/src/py_arg_tests/test_af_generator.py +++ b/src/py_arg_tests/test_af_generator.py @@ -1,11 +1,15 @@ import unittest import networkx as nx -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import \ +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import \ AbstractArgumentationFrameworkGenerator -from py_arg.abstract_argumentation.generators.barbasi_albert_generator import BarabasiAlbert -from py_arg.abstract_argumentation.generators.watts_strogatz_generator import WattsStrogatz -from py_arg.abstract_argumentation.generators.erdos_renyi_generator import ErdosRenyiGenerator +from py_arg.abstract_argumentation.generators.barbasi_albert_generator \ + import BarabasiAlbert +from py_arg.abstract_argumentation.generators.watts_strogatz_generator \ + import WattsStrogatz +from py_arg.abstract_argumentation.generators.erdos_renyi_generator \ + import ErdosRenyiGenerator class TestAFGenerator(unittest.TestCase): @@ -16,7 +20,8 @@ def test_af_generator(self): self.assertEqual(len(af.defeats), 3) def test_erdos_renyi_generator(self): - generator = ErdosRenyiGenerator(nr_of_arguments=10, prob_edge=0.5, is_directed=True, seed=42) + generator = ErdosRenyiGenerator( + nr_of_arguments=10, prob_edge=0.5, is_directed=True, seed=42) af = generator.generate() print(generator.last_generated_nx_graph) self.assertEqual(len(af.arguments), 10) @@ -24,16 +29,20 @@ def test_erdos_renyi_generator(self): # self.assertEqual(nx.is_directed(generator.last_generated_nx_graph),True) def test_wats_strogatz_generator(self): - generator = WattsStrogatz(nr_of_arguments=10, nr_join_neighbours=5, prob_edge_rewiring=0.5, seed=42, - prob_cycle=0.8) + generator = WattsStrogatz( + nr_of_arguments=10, nr_join_neighbours=5, prob_edge_rewiring=0.5, + seed=42, prob_cycle=0.8) af = generator.generate() self.assertEqual(len(af.arguments), 10) self.assertEqual(len(af.defeats), 20) - self.assertEqual(nx.is_directed(generator.last_generated_nx_graph), True) + self.assertEqual(nx.is_directed(generator.last_generated_nx_graph), + True) def test_wats_barabasi_albert_generator(self): - generator = BarabasiAlbert(nr_of_arguments=10, nr_attach_node_to=5, seed=42, prob_cycle=0.8) + generator = BarabasiAlbert( + nr_of_arguments=10, nr_attach_node_to=5, seed=42, prob_cycle=0.8) af = generator.generate() self.assertEqual(len(af.arguments), 10) self.assertEqual(len(af.defeats), 25) - self.assertEqual(nx.is_directed(generator.last_generated_nx_graph), True) + self.assertEqual(nx.is_directed(generator.last_generated_nx_graph), + True) diff --git a/src/py_arg_tests/test_cf_naive_ext.py b/src/py_arg_tests/test_cf_naive_ext.py index 8d99e86..dc8e230 100644 --- a/src/py_arg_tests/test_cf_naive_ext.py +++ b/src/py_arg_tests/test_cf_naive_ext.py @@ -1,11 +1,16 @@ import unittest -import py_arg.abstract_argumentation.semantics.get_conflict_free_extensions as get_conflict_free_extensions +import py_arg.abstract_argumentation.semantics.get_conflict_free_extensions \ + as get_conflict_free_extensions -import py_arg.abstract_argumentation.canonical_constructions.canonical_af.construct_af_cf as construct_af_cf -from py_arg.abstract_argumentation.canonical_constructions import check_tight -from py_arg.abstract_argumentation.canonical_constructions import check_downward_closed -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import \ +import py_arg.abstract_argumentation.canonical_constructions.canonical_af.\ + construct_af_cf as construct_af_cf +from py_arg.abstract_argumentation.canonical_constructions \ + import check_tight +from py_arg.abstract_argumentation.canonical_constructions \ + import check_downward_closed +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import \ AbstractArgumentationFrameworkGenerator diff --git a/src/py_arg_tests/test_incomplete_argumentation_framework.py b/src/py_arg_tests/test_incomplete_argumentation_framework.py index 938f066..9ae1037 100644 --- a/src/py_arg_tests/test_incomplete_argumentation_framework.py +++ b/src/py_arg_tests/test_incomplete_argumentation_framework.py @@ -1,9 +1,11 @@ import unittest -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.incomplete_argumentation_frameworks.classes.incomplete_argumentation_framework import IncompleteArgumentationFramework +from py_arg.incomplete_argumentation_frameworks.classes.\ + incomplete_argumentation_framework import IncompleteArgumentationFramework a = Argument('a') @@ -96,8 +98,8 @@ def test_ac_example_9(self): self.assertIn(iaf1, all_partial_completions) cert_iaf1 = iaf1.certain_projection - self.assertEqual(cert_iaf1, AbstractArgumentationFramework(arguments=[a, b, c, d, e], - defeats=[ab, bc, cb, dc, de, ed])) + self.assertEqual(cert_iaf1, AbstractArgumentationFramework( + arguments=[a, b, c, d, e], defeats=[ab, bc, cb, dc, de, ed])) iaf2 = IncompleteArgumentationFramework( arguments=[b, c, e], @@ -108,8 +110,8 @@ def test_ac_example_9(self): self.assertIn(iaf2, all_partial_completions) cert_iaf2 = iaf2.certain_projection - self.assertEqual(cert_iaf2, AbstractArgumentationFramework(arguments=[b, c, e], - defeats=[bc])) + self.assertEqual(cert_iaf2, AbstractArgumentationFramework( + arguments=[b, c, e], defeats=[bc])) iaf3 = IncompleteArgumentationFramework( arguments=[a, b, c, e], @@ -119,5 +121,5 @@ def test_ac_example_9(self): ) self.assertIn(iaf3, all_partial_completions) cert_iaf3 = iaf3.certain_projection - self.assertEqual(cert_iaf3, AbstractArgumentationFramework(arguments=[a, b, c, e], - defeats=[ab, bc])) + self.assertEqual(cert_iaf3, AbstractArgumentationFramework( + arguments=[a, b, c, e], defeats=[ab, bc])) diff --git a/src/py_arg_tests/test_incomplete_argumentation_theory_generator.py b/src/py_arg_tests/test_incomplete_argumentation_theory_generator.py index d908a43..30ffc6a 100644 --- a/src/py_arg_tests/test_incomplete_argumentation_theory_generator.py +++ b/src/py_arg_tests/test_incomplete_argumentation_theory_generator.py @@ -1,19 +1,27 @@ import pathlib import unittest -from py_arg.aspic.generators.argumentation_system_generators.layered_argumentation_system_generator import \ +from py_arg.aspic.generators.argumentation_system_generators.\ + layered_argumentation_system_generator import \ LayeredArgumentationSystemGenerator -from py_arg.incomplete_aspic.generators.incomplete_argumentation_theory_generator import \ +from py_arg.incomplete_aspic.generators.\ + incomplete_argumentation_theory_generator import \ IncompleteArgumentationTheoryGenerator -from py_arg.aspic.import_export.argumentation_system_from_json_reader import ArgumentationSystemFromJsonReader -from py_arg.aspic.import_export.argumentation_system_to_json_writer import ArgumentationSystemToJSONWriter -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_from_json_reader import \ +from py_arg.aspic.import_export.argumentation_system_from_json_reader \ + import ArgumentationSystemFromJsonReader +from py_arg.aspic.import_export.argumentation_system_to_json_writer \ + import ArgumentationSystemToJSONWriter +from py_arg.incomplete_aspic.import_export.\ + incomplete_argumentation_theory_from_json_reader import \ IncompleteArgumentationTheoryFromJsonReader -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_from_lp_file_reader import \ +from py_arg.incomplete_aspic.import_export.\ + incomplete_argumentation_theory_from_lp_file_reader import \ IncompleteArgumentationTheoryFromLPFileReader -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_to_json_writer import \ +from py_arg.incomplete_aspic.import_export.\ + incomplete_argumentation_theory_to_json_writer import \ IncompleteArgumentationTheoryToJSONWriter -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_to_lp_file_writer import \ +from py_arg.incomplete_aspic.import_export.\ + incomplete_argumentation_theory_to_lp_file_writer import \ IncompleteArgumentationTheoryToLPFileWriter @@ -35,17 +43,22 @@ def instantiate_incomplete_argumentation_theory_generator(): literal_layer_distribution[4] = literals_left layered_argumentation_system_generator = \ - LayeredArgumentationSystemGenerator(nr_of_literals=nr_of_literals, - nr_of_rules=nr_of_rules, - rule_antecedent_distribution=rule_antecedent_distribution, - literal_layer_distribution=literal_layer_distribution, - strict_rule_ratio=0) + LayeredArgumentationSystemGenerator( + nr_of_literals=nr_of_literals, nr_of_rules=nr_of_rules, + rule_antecedent_distribution=rule_antecedent_distribution, + literal_layer_distribution=literal_layer_distribution, + strict_rule_ratio=0) # Generate the argumentation system, and keep the "layers" of literals. - arg_sys, layered_language = layered_argumentation_system_generator.generate(return_layered_language=True) + arg_sys, layered_language = \ + layered_argumentation_system_generator.generate( + return_layered_language=True) - # Generate an incomplete argumentation theory, where only literals on the first layer can be queryable. - positive_queryable_candidates = {arg_sys.language[str(literal).replace('-', '')] for literal in layered_language[0]} + # Generate an incomplete argumentation theory, where only literals on the + # first layer can be queryable. + positive_queryable_candidates = \ + {arg_sys.language[str(literal).replace('-', '')] + for literal in layered_language[0]} return IncompleteArgumentationTheoryGenerator( argumentation_system=arg_sys, positive_queryable_candidates=list(positive_queryable_candidates), @@ -56,13 +69,17 @@ def instantiate_incomplete_argumentation_theory_generator(): class TestGenerator(unittest.TestCase): - def test_generator_returns_consistent_knowledge_base_without_duplicates(self): + def test_generator_returns_consistent_knowledge_base_without_duplicates( + self): for _ in range(10): - iat_generator = instantiate_incomplete_argumentation_theory_generator() + iat_generator = \ + instantiate_incomplete_argumentation_theory_generator() iat = iat_generator.generate() axioms = iat.knowledge_base_axioms self.assertTrue(len(axioms) == len(set(axioms))) - self.assertFalse(any(ax1 in ax2.contraries_and_contradictories for ax1 in axioms for ax2 in axioms)) + self.assertFalse(any( + ax1 in ax2.contraries_and_contradictories + for ax1 in axioms for ax2 in axioms)) def test_generator_readers_and_writers(self): iat_generator = instantiate_incomplete_argumentation_theory_generator() @@ -71,16 +88,20 @@ def test_generator_readers_and_writers(self): iat_writer.write(iat, 'generated_iat.lp') iat_lp_reader = IncompleteArgumentationTheoryFromLPFileReader() - data_folder = pathlib.Path(__file__).parent.parent / 'py_arg' / 'experiments' / 'generated_data' - read_iat_lp = iat_lp_reader.read_from_lp_file(str(data_folder / 'generated_iat.lp')) + data_folder = pathlib.Path(__file__).parent.parent / \ + 'py_arg' / 'experiments' / 'generated_data' + read_iat_lp = iat_lp_reader.read_from_lp_file( + str(data_folder / 'generated_iat.lp')) iat_json_writer = IncompleteArgumentationTheoryToJSONWriter() iat_json_writer.write(iat, 'generated_iat.json') as_writer = ArgumentationSystemToJSONWriter() as_writer.write(iat.argumentation_system, 'generated_as.json') as_reader = ArgumentationSystemFromJsonReader() - read_as = as_reader.read_from_json(str(data_folder / 'generated_as.json')) + read_as = as_reader.read_from_json( + str(data_folder / 'generated_as.json')) iat_reader = IncompleteArgumentationTheoryFromJsonReader() - read_iat = iat_reader.read_from_json(str(data_folder / 'generated_iat.json')) + read_iat = iat_reader.read_from_json( + str(data_folder / 'generated_iat.json')) self.assertEqual(read_as, iat.argumentation_system) self.assertEqual(read_iat, iat) self.assertEqual(read_iat_lp, iat) diff --git a/src/py_arg_tests/test_recompute_arguments.py b/src/py_arg_tests/test_recompute_arguments.py index ffb161a..08bf60d 100644 --- a/src/py_arg_tests/test_recompute_arguments.py +++ b/src/py_arg_tests/test_recompute_arguments.py @@ -7,10 +7,12 @@ class TestRecomputeArguments(unittest.TestCase): def test_nr_arguments_update(self): arg_theory = get_argumentation_theory() self.assertEqual(len(arg_theory.all_arguments), 8) - old_ordinary_premises = arg_theory.knowledge_base_ordinary_premises.copy() + old_ordinary_premises = \ + arg_theory.knowledge_base_ordinary_premises.copy() # Add -a to the ordinary premises. - arg_theory.add_to_knowledge_base_ordinary_premises(arg_theory.argumentation_system.language['-a']) + arg_theory.add_to_knowledge_base_ordinary_premises( + arg_theory.argumentation_system.language['-a']) self.assertEqual(len(arg_theory.all_arguments), 9) # Go back to the old situation. diff --git a/src/py_arg_tests/test_stability.py b/src/py_arg_tests/test_stability.py index 3e8fdcb..6e7dee5 100644 --- a/src/py_arg_tests/test_stability.py +++ b/src/py_arg_tests/test_stability.py @@ -2,10 +2,10 @@ import unittest from typing import List -from py_arg.incomplete_aspic.algorithms.stability.stability_labeler import StabilityLabeler -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_from_lp_file_reader import \ - IncompleteArgumentationTheoryFromLPFileReader -from py_arg.incomplete_aspic.import_export.incomplete_argumentation_theory_from_xlsx_reader import \ +from py_arg.incomplete_aspic.algorithms.stability.stability_labeler import \ + StabilityLabeler +from py_arg.incomplete_aspic.import_export. \ + incomplete_argumentation_theory_from_xlsx_reader import \ IncompleteArgumentationTheoryFromXLSXFileReader @@ -14,187 +14,225 @@ def path_to_resources(filename: str): class TestStability(unittest.TestCase): - def test_single_axiom(self): - asr = IncompleteArgumentationTheoryFromLPFileReader() - iat = asr.read_from_lp_file(str(pathlib.Path.cwd() / 'resources' / 'single_axiom.lp')) - stability_labeler = StabilityLabeler() - stability_labels = stability_labeler.label(iat) - i = 0 - - def test_fraud_real_test(self): - asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('Police_Intake_System_Anon')) - stability_labeler = StabilityLabeler() - stability_labels = stability_labeler.label(iat) - i = 0 def test_fraud_mini_test(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('03_2019_FQAS_Paper_Example')) + iat = asr.read_from_xlsx_file( + path_to_resources('03_2019_FQAS_Paper_Example')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = \ + [iat.argumentation_system.language[lit_str] + for lit_str in str_list] update_knowledge_base(['wrong_product']) stability_labels = stability_labeler.label(iat) - self.assertFalse(stability_labels.literal_labeling[language['fraud']].is_stable) - self.assertTrue(stability_labels.literal_labeling[language['fraud']].is_contested_stable) + self.assertFalse(stability_labels.literal_labeling[ + language['fraud']].is_stable) + self.assertTrue(stability_labels.literal_labeling[ + language['fraud']].is_contested_stable) update_knowledge_base(['wrong_product', 'counter_party_delivered']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['fraud']].is_stable) + self.assertTrue(stability_labels.literal_labeling[ + language['fraud']].is_stable) update_knowledge_base(['counter_party_delivered']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['fraud']].is_contested_stable) + self.assertTrue(stability_labels.literal_labeling[ + language['fraud']].is_contested_stable) def test_inconsistent_premise_test(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter01_inconsistent_premises')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter01_inconsistent_premises')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() stability_labels = stability_labeler.label(iat) - self.assertFalse(stability_labels.literal_labeling[language['t']].is_stable) + self.assertFalse(stability_labels.literal_labeling[ + language['t']].is_stable) def test_support_cycle(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter02_support_cycle')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter02_support_cycle')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue(stability_labels.literal_labeling[ + language['t']].is_stable) def test_attack_cycle(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter03_attack_cycle')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter03_attack_cycle')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o1', 'o2']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue( + stability_labels.literal_labeling[language['t']].is_stable) def test_ou_irrelevant_d_lit_c(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter04_OU_irrelevant_in_D_lit_c')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter04_OU_irrelevant_in_D_lit_c')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o1', 'o2']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue( + stability_labels.literal_labeling[language['t']].is_stable) def test_bou_irrelevant_b_lit_b(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter05_BOU_irrelevant_in_B_lit_b')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter05_BOU_irrelevant_in_B_lit_b')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o1', 'o2', 'o5']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue( + stability_labels.literal_labeling[language['t']].is_stable) def test_db_irrelevant_b_lit_a(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter06_DB_irrelevant_in_B_lit_a')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter06_DB_irrelevant_in_B_lit_a')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o1']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue( + stability_labels.literal_labeling[language['t']].is_stable) def test_dbo_irrelevant_o_lit_a(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter07_DBO_irrelevant_in_O_lit_a')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter07_DBO_irrelevant_in_O_lit_a')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o1', '-t']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue( + stability_labels.literal_labeling[language['t']].is_stable) def test_uo_irrelevant_o_lit_b(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter08_UO_irrelevant_in_O_lit_b')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter08_UO_irrelevant_in_O_lit_b')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o1', 'o2', 'o3']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue( + stability_labels.literal_labeling[language['t']].is_stable) def test_dbo_irrelevant_o_rule(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter09_DBO_irrelevant_in_O_rule')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter09_DBO_irrelevant_in_O_rule')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o3', 'o4', 'o5']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue( + stability_labels.literal_labeling[language['t']].is_stable) def test_db_irrelevant_b_rule(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter10_DB_irrelevant_in_B_rule')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter10_DB_irrelevant_in_B_rule')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o2', 'o3', 'o4']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue( + stability_labels.literal_labeling[language['t']].is_stable) def test_support_cycle_attacker(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter11_support_cycle_attacker')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter11_support_cycle_attacker')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o']) stability_labels = stability_labeler.label(iat) - self.assertTrue(stability_labels.literal_labeling[language['t']].is_stable) + self.assertTrue( + stability_labels.literal_labeling[language['t']].is_stable) def test_support_cycle_attacker_q(self): asr = IncompleteArgumentationTheoryFromXLSXFileReader() - iat = asr.read_from_xlsx_file(path_to_resources('counter12_support_cycle_attacker_q')) + iat = asr.read_from_xlsx_file( + path_to_resources('counter12_support_cycle_attacker_q')) language = iat.argumentation_system.language stability_labeler = StabilityLabeler() def update_knowledge_base(str_list: List[str]): - iat.knowledge_base_axioms = [iat.argumentation_system.language[lit_str] for lit_str in str_list] + iat.knowledge_base_axioms = [ + iat.argumentation_system.language[lit_str] for lit_str in + str_list] update_knowledge_base(['o']) stability_labels = stability_labeler.label(iat) - self.assertFalse(stability_labels.literal_labeling[language['t']].is_stable) + self.assertFalse( + stability_labels.literal_labeling[language['t']].is_stable) if __name__ == '__main__': diff --git a/src/py_arg_tests/test_toast_api.py b/src/py_arg_tests/test_toast_api.py index 5c9ddef..36e173e 100644 --- a/src/py_arg_tests/test_toast_api.py +++ b/src/py_arg_tests/test_toast_api.py @@ -18,7 +18,9 @@ def test_toast_api(self): 'axioms': [] } json_str = json.dumps(input_dict) - response = requests.post('http://toast.arg-tech.org/api/evaluate', json_str) + response = requests.post('http://toast.arg-tech.org/api/evaluate', + json_str) result = response.json() self.assertEqual(len(result['arguments']), 4) - self.assertListEqual(result['acceptableConclusions']['0'], ['p', 'q', 't']) + self.assertListEqual(result['acceptableConclusions']['0'], + ['p', 'q', 't']) diff --git a/src/py_arg_visualisation/app.py b/src/py_arg_visualisation/app.py index 8a89199..06f8d11 100644 --- a/src/py_arg_visualisation/app.py +++ b/src/py_arg_visualisation/app.py @@ -1,25 +1,31 @@ -from dash import Dash, html -import dash_bootstrap_components as dbc import dash +import dash_bootstrap_components as dbc import dash_daq as daq - +from dash import Dash, html # Create a Dash app using an external stylesheet. -app = Dash(__name__, use_pages=True, suppress_callback_exceptions=True, external_stylesheets=[dbc.themes.YETI]) +app = Dash(__name__, use_pages=True, suppress_callback_exceptions=True, + external_stylesheets=[dbc.themes.YETI]) # Navigation bar. navbar = dbc.NavbarSimple( children=[ dbc.DropdownMenu( children=[ - dbc.DropdownMenuItem('Random Abstract AF', href='01-generate-abstract', className='fw-bold text-white'), - dbc.DropdownMenuItem('Random Erdos-Renyi AF', href='04-generate-erdos-renyi', + dbc.DropdownMenuItem('Random Abstract AF', + href='01-generate-abstract', + className='fw-bold text-white'), + dbc.DropdownMenuItem('Random Erdos-Renyi AF', + href='04-generate-erdos-renyi', className='fw-bold text-white'), - dbc.DropdownMenuItem('Random Watts-Strogatz AF', href='05-generate-watts-strogatz', + dbc.DropdownMenuItem('Random Watts-Strogatz AF', + href='05-generate-watts-strogatz', className='fw-bold text-white'), - dbc.DropdownMenuItem('Random Barabasi-Albert AF', href='06-generate-barabasi-albert', + dbc.DropdownMenuItem('Random Barabasi-Albert AF', + href='06-generate-barabasi-albert', className='fw-bold text-white'), - dbc.DropdownMenuItem('Layered ASPIC+ AS', href='03-generate-layered-aspic', + dbc.DropdownMenuItem('Layered ASPIC+ AS', + href='03-generate-layered-aspic', className='fw-bold text-white'), ], nav=True, @@ -30,10 +36,15 @@ ), dbc.DropdownMenu( children=[ - dbc.DropdownMenuItem('Abstract', href='21-visualise-abstract', className='fw-bold text-white'), - dbc.DropdownMenuItem('Tweety API Test', href='24-visualise-tweety-services-test', className='fw-bold text-white'), - dbc.DropdownMenuItem('ASPIC+', href='22-visualise-aspic', className='fw-bold text-white'), - dbc.DropdownMenuItem('ABA', href='23-visualise-aba', className='fw-bold text-white'), + dbc.DropdownMenuItem('Abstract', href='21-visualise-abstract', + className='fw-bold text-white'), + dbc.DropdownMenuItem('Tweety API Test', + href='24-visualise-tweety-services-test', + className='fw-bold text-white'), + dbc.DropdownMenuItem('ASPIC+', href='22-visualise-aspic', + className='fw-bold text-white'), + dbc.DropdownMenuItem('ABA', href='23-visualise-aba', + className='fw-bold text-white'), ], nav=True, in_navbar=True, @@ -42,7 +53,8 @@ ), dbc.DropdownMenu( children=[ - dbc.DropdownMenuItem('Practice', href='30-learn', className='fw-bold text-white'), + dbc.DropdownMenuItem('Practice', href='30-learn', + className='fw-bold text-white'), ], nav=True, in_navbar=True, @@ -51,9 +63,11 @@ ), dbc.DropdownMenu( children=[ - dbc.DropdownMenuItem('Canonical Construction AF', href='41-canonical-af', + dbc.DropdownMenuItem('Canonical Construction AF', + href='41-canonical-af', className='fw-bold text-white'), - dbc.DropdownMenuItem('Canonical Construction ABAF', href='42-canonical-abaf', + dbc.DropdownMenuItem('Canonical Construction ABAF', + href='42-canonical-abaf', className='fw-bold text-white') ], nav=True, @@ -63,7 +77,8 @@ ), dbc.DropdownMenu( children=[ - dbc.DropdownMenuItem('Chat', href='50-chat', className='fw-bold text-white'), + dbc.DropdownMenuItem('Chat', href='50-chat', + className='fw-bold text-white'), ], nav=True, in_navbar=True, @@ -79,8 +94,10 @@ color='primary', className='fw-bold', dark=True ) -# Specification of the layout, consisting of a navigation bar and the page container. -app.layout = html.Div([navbar, dbc.Col(html.Div([dash.page_container]), width={'size': 10, 'offset': 1})]) +# Specification of the layout, consisting of a navigation bar and the page +# container. +app.layout = html.Div([navbar, dbc.Col(html.Div([dash.page_container]), + width={'size': 10, 'offset': 1})]) # Running the app. if __name__ == '__main__': diff --git a/src/py_arg_visualisation/functions/explanations_functions/explanation_function_options.py b/src/py_arg_visualisation/functions/explanations_functions/explanation_function_options.py index b7a2db0..b3dcfd3 100644 --- a/src/py_arg_visualisation/functions/explanations_functions/explanation_function_options.py +++ b/src/py_arg_visualisation/functions/explanations_functions/explanation_function_options.py @@ -4,13 +4,18 @@ {'label': 'Defending', 'value': 'Defending'}, {'label': 'Directly defending', 'value': 'DirDefending'}, {'label': 'Sufficient for acceptance', 'value': 'Suff'}, - {'label': 'Minimally sufficient for acceptance', 'value': 'MinSuff'}, + {'label': 'Minimally sufficient for acceptance', + 'value': 'MinSuff'}, {'label': 'Necessary for acceptance', 'value': 'Nec'} ], 'NonAcceptance': [ - {'label': 'Defeated by and not defended against', 'value': 'NoDefAgainst'}, - {'label': 'Defeated by and not directly defended against', 'value': 'NoDirDefense'}, - {'label': 'Defeated by and not defended against by the argument itself', 'value': 'NoSelfDefense'} + {'label': 'Defeated by and not defended against', + 'value': 'NoDefAgainst'}, + {'label': 'Defeated by and not directly defended against', + 'value': 'NoDirDefense'}, + {'label': 'Defeated by and not defended against by the argument ' + 'itself', + 'value': 'NoSelfDefense'} ] } diff --git a/src/py_arg_visualisation/functions/explanations_functions/get_af_explanations.py b/src/py_arg_visualisation/functions/explanations_functions/get_af_explanations.py index 94ddcf3..cff288e 100644 --- a/src/py_arg_visualisation/functions/explanations_functions/get_af_explanations.py +++ b/src/py_arg_visualisation/functions/explanations_functions/get_af_explanations.py @@ -1,41 +1,61 @@ from typing import List, Set -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -from py_arg.abstract_argumentation.explanation.defending import get_defending, get_dir_defending -from py_arg.abstract_argumentation.explanation.not_defending import get_not_defending, get_no_dir_defending, get_no_self_defense -from py_arg.abstract_argumentation.explanation.suff_nec import get_sufficient_or_necessary +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework +from py_arg.abstract_argumentation.explanation.defending \ + import get_defending, get_dir_defending +from py_arg.abstract_argumentation.explanation.not_defending \ + import get_not_defending, get_no_dir_defending, get_no_self_defense +from py_arg.abstract_argumentation.explanation.suff_nec \ + import get_sufficient_or_necessary -def get_argumentation_framework_explanations(arg_framework: AbstractArgumentationFramework, extensions: List[Set], - accepted_arguments: Set, explanation_function: str, explanation_type: str): +def get_argumentation_framework_explanations( + arg_framework: AbstractArgumentationFramework, extensions: List[Set], + accepted_arguments: Set, explanation_function: str, + explanation_type: str): """ - Calculate, for each argument, the explanations, given the function, type and strategy. + Calculate, for each argument, the explanations, given the function, type + and strategy. - :param arg_framework: The argumentation framework the explanation has to be calculated from. - :param extensions: The sets of accepted arguments in arg_framework, based on semantics. - :param accepted_arguments: The arguments that are considered accepted given the extensions and strategy. - :param explanation_function: The explanation function, to determine the content of the explanation. - :param explanation_type: The explanation type, to determine acceptance/non-acceptance explanation. - :return: A dictionary with for each (non-)accepted argument its explanation, given the parameters. + :param arg_framework: The argumentation framework the explanation has to be + calculated from. + :param extensions: The sets of accepted arguments in arg_framework, based + on semantics. + :param accepted_arguments: The arguments that are considered accepted given + the extensions and strategy. + :param explanation_function: The explanation function, to determine the + content of the explanation. + :param explanation_type: The explanation type, to determine + acceptance/non-acceptance explanation. + :return: A dictionary with for each (non-)accepted argument its + explanation, given the parameters. """ explanation = {} if explanation_type == 'Acceptance': for arg in accepted_arguments: if explanation_function == 'Defending': - explanation[str(arg)] = get_defending(arg_framework, arg, extensions) + explanation[str(arg)] = get_defending(arg_framework, arg, + extensions) elif explanation_function == 'DirDefending': - explanation[str(arg)] = get_dir_defending(arg_framework, arg, extensions) + explanation[str(arg)] = get_dir_defending(arg_framework, arg, + extensions) else: - explanation[str(arg)] = get_sufficient_or_necessary(arg_framework, arg, explanation_function, explanation_type) + explanation[str(arg)] = get_sufficient_or_necessary( + arg_framework, arg, explanation_function, explanation_type) return explanation elif explanation_type == 'NonAcceptance': - not_accepted_arguments = [arg for arg in arg_framework.arguments if arg not in accepted_arguments] + not_accepted_arguments = [arg for arg in arg_framework.arguments + if arg not in accepted_arguments] for arg in not_accepted_arguments: if explanation_function == 'NoDefAgainst': - explanation[str(arg)] = get_not_defending(arg_framework, arg, extensions) + explanation[str(arg)] = get_not_defending( + arg_framework, arg, extensions) elif explanation_function == 'NoDirDefense': - explanation[str(arg)] = get_no_dir_defending(arg_framework, arg, extensions) + explanation[str(arg)] = get_no_dir_defending( + arg_framework, arg, extensions) elif explanation_function == 'NoSelfDefense': - explanation[str(arg)] = get_no_self_defense(arg_framework, arg, extensions) + explanation[str(arg)] = get_no_self_defense( + arg_framework, arg, extensions) return explanation diff --git a/src/py_arg_visualisation/functions/explanations_functions/get_at_explanations.py b/src/py_arg_visualisation/functions/explanations_functions/get_at_explanations.py index ddfcc43..09fbc39 100644 --- a/src/py_arg_visualisation/functions/explanations_functions/get_at_explanations.py +++ b/src/py_arg_visualisation/functions/explanations_functions/get_at_explanations.py @@ -1,25 +1,41 @@ -from py_arg.abstract_argumentation.explanation.defending import get_defending, get_dir_defending -from py_arg.abstract_argumentation.explanation.not_defending import get_not_defending, get_no_dir_defending, get_no_self_defense -from py_arg.abstract_argumentation.explanation.suff_nec import get_sufficient_or_necessary +from py_arg.abstract_argumentation.explanation.defending \ + import get_defending, get_dir_defending +from py_arg.abstract_argumentation.explanation.not_defending \ + import get_not_defending, get_no_dir_defending, get_no_self_defense +from py_arg.abstract_argumentation.explanation.suff_nec \ + import get_sufficient_or_necessary -def get_str_explanations(argumentation_theory, semantics, ordering_specification, extensions, accepted_formulas, +def get_str_explanations(argumentation_theory, semantics, + ordering_specification, extensions, accepted_formulas, function, expl_type, strategy, form): """ - Calculate, for each formula, the explanations, given the function, type, strategy and form. + Calculate, for each formula, the explanations, given the function, type, + strategy and form. - :param argumentation_theory: the argumentation theory the explanation has to be calculated from. + :param argumentation_theory: the argumentation theory the explanation has + to be calculated from. :param semantics: The semantics used to determine (non-)acceptance. - :param ordering_specification: The chosen ordering, combining both last/weakest link and democratic/elitist. - :param extensions: The sets of accepted arguments in arg_framework, based on semantics. - :param accepted_formulas: The formulas that are considered accepted given the extensions and strategy. - :param function: The explanation function, to determine the content of the explanation. - :param expl_type: The explanation type, to determine acceptance/non-acceptance explanation. - :param strategy: The strategy of the explanation, whether credulous or skeptical reasoning. - :param form: The form of the explanation, for example, explanations in terms of arguments, rules or premises. - :return: A dictionary with for each (non-)accepted argument its explanation, given the parameters. + :param ordering_specification: The chosen ordering, combining both + last/weakest link and democratic/elitist. + :param extensions: The sets of accepted arguments in arg_framework, + based on semantics. + :param accepted_formulas: The formulas that are considered accepted + given the extensions and strategy. + :param function: The explanation function, to determine the content + of the explanation. + :param expl_type: The explanation type, to determine + acceptance/non-acceptance explanation. + :param strategy: The strategy of the explanation, whether credulous + or skeptical reasoning. + :param form: The form of the explanation, for example, explanations + in terms of arguments, rules or premises. + :return: A dictionary with for each (non-)accepted argument its + explanation, given the parameters. """ - argumentation_framework = argumentation_theory.create_abstract_argumentation_framework('af', ordering_specification) + argumentation_framework = \ + argumentation_theory.create_abstract_argumentation_framework( + 'af', ordering_specification) abstract_explanation = {} if expl_type == 'Acceptance': for formula in accepted_formulas: @@ -28,11 +44,14 @@ def get_str_explanations(argumentation_theory, semantics, ordering_specification suff_expl = [] for arg in form_arg: if function == 'Defending': - arg_expl.extend(get_defending(argumentation_framework, arg, extensions)) + arg_expl.extend(get_defending(argumentation_framework, + arg, extensions)) elif function == 'DirDefending': - arg_expl.extend(get_dir_defending(argumentation_framework, arg, extensions)) + arg_expl.extend(get_dir_defending(argumentation_framework, + arg, extensions)) else: - suff_expl.extend(get_sufficient_or_necessary(argumentation_framework, arg, 'Suff', expl_type)) + suff_expl.extend(get_sufficient_or_necessary( + argumentation_framework, arg, 'Suff', expl_type)) if suff_expl != []: if function == 'Suff': arg_expl.extend(suff_expl) @@ -45,14 +64,16 @@ def get_str_explanations(argumentation_theory, semantics, ordering_specification for sets in suff_expl: set_expl = [] for arg in sets: - if form == 'Prem' and arg.premises not in form_expl: + if form == 'Prem' and \ + arg.premises not in form_expl: set_expl.append(arg.premises) elif form == 'Rule': defrules = arg.defeasible_rules rules = defrules.union(arg.strict_rules) if rules not in form_expl: set_expl.append(rules) - elif form == 'SubArg' and arg.sub_arguments not in form_expl: + elif form == 'SubArg' \ + and arg.sub_arguments not in form_expl: set_expl.append(arg.sub_arguments) elif form == 'SubArgConclusions': subargconc = set() @@ -102,11 +123,14 @@ def get_str_explanations(argumentation_theory, semantics, ordering_specification arg_expl = [] for arg in form_arg: if function == 'NoDefAgainst': - arg_expl.extend(get_not_defending(argumentation_framework, arg, extensions)) + arg_expl.extend(get_not_defending( + argumentation_framework, arg, extensions)) elif function == 'NoDirDefense': - arg_expl.extend(get_no_dir_defending(argumentation_framework, arg, extensions)) + arg_expl.extend(get_no_dir_defending( + argumentation_framework, arg, extensions)) elif function == 'NoSelfDefense': - arg_expl.extend(get_no_self_defense(argumentation_framework, arg, extensions)) + arg_expl.extend(get_no_self_defense( + argumentation_framework, arg, extensions)) abstract_explanation[str(formula)] = arg_expl if form == 'Arg': @@ -128,7 +152,8 @@ def get_str_explanations(argumentation_theory, semantics, ordering_specification # if arg.top_rule != None: # if arg.top_rule not in form_expl: # form_expl.append(arg.top_rule) - elif form == 'SubArg' and arg.sub_arguments not in form_expl: + elif form == 'SubArg' and \ + arg.sub_arguments not in form_expl: form_expl.append(arg.sub_arguments) elif form == 'SubArgConclusions': subargconc = set() diff --git a/src/py_arg_visualisation/functions/extensions_functions/get_abaf_extensions.py b/src/py_arg_visualisation/functions/extensions_functions/get_abaf_extensions.py index 904a0ef..c00ac76 100644 --- a/src/py_arg_visualisation/functions/extensions_functions/get_abaf_extensions.py +++ b/src/py_arg_visualisation/functions/extensions_functions/get_abaf_extensions.py @@ -1,15 +1,25 @@ -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -import py_arg.assumption_based_argumentation.semantics.get_stable_extensions as get_stable_extensions -import py_arg.assumption_based_argumentation.semantics.get_complete_extensions as get_complete_extensions -import py_arg.assumption_based_argumentation.semantics.get_conflict_free_extensions as get_conflict_free_extensions -import py_arg.assumption_based_argumentation.semantics.get_admissible_extensions as get_admissible_extensions -import py_arg.assumption_based_argumentation.semantics.get_preferred_extensions as get_preferred_extensions -import py_arg.assumption_based_argumentation.semantics.get_semi_stable_extensions as get_semi_stable_extensions -import py_arg.assumption_based_argumentation.semantics.get_grounded_extensions as get_ground_extensions -import py_arg.assumption_based_argumentation.semantics.get_naive_extensions as get_naive_extensions +from py_arg.assumption_based_argumentation.classes.aba_framework import \ + AssumptionBasedArgumentationFramework +import py_arg.assumption_based_argumentation.semantics.get_stable_extensions \ + as get_stable_extensions +import py_arg.assumption_based_argumentation.\ + semantics.get_complete_extensions as get_complete_extensions +import py_arg.assumption_based_argumentation.semantics.\ + get_conflict_free_extensions as get_conflict_free_extensions +import py_arg.assumption_based_argumentation.semantics.\ + get_admissible_extensions as get_admissible_extensions +import py_arg.assumption_based_argumentation.semantics.\ + get_preferred_extensions as get_preferred_extensions +import py_arg.assumption_based_argumentation.semantics.\ + get_semi_stable_extensions as get_semi_stable_extensions +import py_arg.assumption_based_argumentation.semantics.\ + get_grounded_extensions as get_ground_extensions +import py_arg.assumption_based_argumentation.semantics.\ + get_naive_extensions as get_naive_extensions -def apply(abaf: AssumptionBasedArgumentationFramework, semantics_specification: str): +def apply(abaf: AssumptionBasedArgumentationFramework, + semantics_specification: str): if semantics_specification == 'Stable': return get_stable_extensions.get_stable_extensions(abaf) if semantics_specification == 'Preferred': diff --git a/src/py_arg_visualisation/functions/extensions_functions/get_accepted_arguments.py b/src/py_arg_visualisation/functions/extensions_functions/get_accepted_arguments.py index b74fa09..385fbb2 100644 --- a/src/py_arg_visualisation/functions/extensions_functions/get_accepted_arguments.py +++ b/src/py_arg_visualisation/functions/extensions_functions/get_accepted_arguments.py @@ -1,9 +1,11 @@ def get_accepted_arguments(extensions, strategy_specification: str): """ - Calculate the set of accepted arguments from a set of extensions (sets of arguments) and evaluation strategy + Calculate the set of accepted arguments from a set of extensions + (sets of arguments) and evaluation strategy - :param extensions: The extensions (sets of collectively accepted arguments). - :param strategy_specification: The evaluation strategy (e.g., skeptical or credulous). + :param extensions: The extensions (sets of collectively accepted arguments) + :param strategy_specification: The evaluation strategy (e.g., skeptical or + credulous). """ if strategy_specification == 'Skeptical': return set.intersection(*extensions) diff --git a/src/py_arg_visualisation/functions/extensions_functions/get_accepted_assumptions.py b/src/py_arg_visualisation/functions/extensions_functions/get_accepted_assumptions.py index 1f47e20..4830bfc 100644 --- a/src/py_arg_visualisation/functions/extensions_functions/get_accepted_assumptions.py +++ b/src/py_arg_visualisation/functions/extensions_functions/get_accepted_assumptions.py @@ -1,9 +1,11 @@ def apply(extensions, strategy_specification: str): """ - Calculate the set of accepted formulas from a set of extensions (sets of arguments) and evaluation strategy + Calculate the set of accepted formulas from a set of extensions + (sets of arguments) and evaluation strategy - :param extensions: The extensions (sets of collectively accepted arguments). - :param strategy_specification: The evaluation strategy (e.g., skeptical or credulous). + :param extensions: The extensions (sets of collectively accepted arguments) + :param strategy_specification: The evaluation strategy (e.g., skeptical or + credulous). """ if strategy_specification == 'Skeptical': return frozenset().intersection(*extensions) diff --git a/src/py_arg_visualisation/functions/extensions_functions/get_accepted_formulas.py b/src/py_arg_visualisation/functions/extensions_functions/get_accepted_formulas.py index 7d05163..cae5242 100644 --- a/src/py_arg_visualisation/functions/extensions_functions/get_accepted_formulas.py +++ b/src/py_arg_visualisation/functions/extensions_functions/get_accepted_formulas.py @@ -1,9 +1,11 @@ def get_accepted_formulas(extensions, strategy_specification: str): """ - Calculate the set of accepted formulas from a set of extensions (sets of arguments) and evaluation strategy + Calculate the set of accepted formulas from a set of extensions + (sets of arguments) and evaluation strategy - :param extensions: The extensions (sets of collectively accepted arguments). - :param strategy_specification: The evaluation strategy (e.g., skeptical or credulous). + :param extensions: The extensions (sets of collectively accepted arguments) + :param strategy_specification: The evaluation strategy (e.g., skeptical or + credulous). """ if strategy_specification == 'Skeptical': accepted_arguments = set.intersection(*extensions) @@ -12,5 +14,6 @@ def get_accepted_formulas(extensions, strategy_specification: str): accepted_arguments = set.union(*extensions) return set(arg.conclusion for arg in accepted_arguments) elif strategy_specification == 'WeaklySkeptical': - extension_formulas = [{arg.conclusion for arg in extension} for extension in extensions] + extension_formulas = [{arg.conclusion for arg in extension} + for extension in extensions] return set.intersection(*extension_formulas) diff --git a/src/py_arg_visualisation/functions/extensions_functions/get_af_extensions.py b/src/py_arg_visualisation/functions/extensions_functions/get_af_extensions.py index 3bfa4d6..393209f 100644 --- a/src/py_arg_visualisation/functions/extensions_functions/get_af_extensions.py +++ b/src/py_arg_visualisation/functions/extensions_functions/get_af_extensions.py @@ -1,18 +1,29 @@ -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -from py_arg.abstract_argumentation.semantics.get_admissible_sets import get_admissible_sets -from py_arg.abstract_argumentation.semantics import get_complete_extensions -from py_arg.abstract_argumentation.semantics.get_eager_extension import get_eager_extension -from py_arg.abstract_argumentation.semantics.get_grounded_extension import get_grounded_extension -from py_arg.abstract_argumentation.semantics.get_ideal_extension import get_ideal_extension -from py_arg.abstract_argumentation.semantics import get_preferred_extensions -from py_arg.abstract_argumentation.semantics.get_semistable_extensions import get_semistable_extensions -from py_arg.abstract_argumentation.semantics.get_stable_extensions import get_stable_extensions +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework +from py_arg.abstract_argumentation.semantics.get_admissible_sets \ + import get_admissible_sets +from py_arg.abstract_argumentation.semantics.get_complete_extensions import \ + get_complete_extensions +from py_arg.abstract_argumentation.semantics.get_eager_extension \ + import get_eager_extension +from py_arg.abstract_argumentation.semantics.get_grounded_extension \ + import get_grounded_extension +from py_arg.abstract_argumentation.semantics.get_ideal_extension \ + import get_ideal_extension +from py_arg.abstract_argumentation.semantics.get_preferred_extensions import \ + get_preferred_extensions +from py_arg.abstract_argumentation.semantics.get_semistable_extensions \ + import get_semistable_extensions +from py_arg.abstract_argumentation.semantics.get_stable_extensions \ + import get_stable_extensions -def get_argumentation_framework_extensions(argumentation_framework: AbstractArgumentationFramework, - semantics_specification: str): +def get_argumentation_framework_extensions( + argumentation_framework: AbstractArgumentationFramework, + semantics_specification: str): """ - Calculate the set of extensions from the given abstract argumentation framework and chosen semantics + Calculate the set of extensions from the given abstract argumentation + framework and chosen semantics :param argumentation_framework: The abstract argumentation framework. :param semantics_specification: The chosen semantics. diff --git a/src/py_arg_visualisation/functions/graph_data_functions/get_aba_graph_data.py b/src/py_arg_visualisation/functions/graph_data_functions/get_aba_graph_data.py index 7c5fbc7..0f671bc 100644 --- a/src/py_arg_visualisation/functions/graph_data_functions/get_aba_graph_data.py +++ b/src/py_arg_visualisation/functions/graph_data_functions/get_aba_graph_data.py @@ -1,10 +1,13 @@ from typing import List, Dict -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -from py_arg_visualisation.functions.graph_data_functions.get_color import get_color +from py_arg.assumption_based_argumentation.classes.aba_framework \ + import AssumptionBasedArgumentationFramework +from py_arg_visualisation.functions.graph_data_functions.get_color \ + import get_color -def apply(abaf: AssumptionBasedArgumentationFramework, selected_arguments: Dict[str, List[str]], +def apply(abaf: AssumptionBasedArgumentationFramework, + selected_arguments: Dict[str, List[str]], color_blind_mode: bool): if selected_arguments and 'blue' in selected_arguments: blue = selected_arguments['blue'] @@ -38,7 +41,8 @@ def apply(abaf: AssumptionBasedArgumentationFramework, selected_arguments: Dict[ color = get_color('red', color_blind_mode) else: color = get_color('gray', color_blind_mode) - data_nodes.append({'id': readable_id, 'label': argument.name, 'color': color}) + data_nodes.append({'id': readable_id, 'label': argument.name, + 'color': color}) data_edges = [] for defeat in abaf.generate_af_full().defeats: @@ -46,7 +50,8 @@ def apply(abaf: AssumptionBasedArgumentationFramework, selected_arguments: Dict[ argument_b_id = argument_long_str_to_id[defeat.to_argument.name] data_edges.append({'id': str(argument_a_id) + '-' + str(argument_b_id), - 'from': argument_a_id, 'to': argument_b_id, 'arrows': 'to'}) + 'from': argument_a_id, 'to': argument_b_id, + 'arrows': 'to'}) data = {'nodes': data_nodes, 'edges': data_edges} return data diff --git a/src/py_arg_visualisation/functions/graph_data_functions/get_af_graph_data.py b/src/py_arg_visualisation/functions/graph_data_functions/get_af_graph_data.py index 07fe9e3..59f2f72 100644 --- a/src/py_arg_visualisation/functions/graph_data_functions/get_af_graph_data.py +++ b/src/py_arg_visualisation/functions/graph_data_functions/get_af_graph_data.py @@ -1,16 +1,21 @@ from typing import List, Optional, Dict -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -from py_arg_visualisation.functions.graph_data_functions.get_color import get_color +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework +from py_arg_visualisation.functions.graph_data_functions.get_color \ + import get_color -def get_argumentation_framework_graph_data(arg_framework: AbstractArgumentationFramework, - selected_arguments: Optional[Dict[str, List[str]]], - color_blind_mode: bool): +def get_argumentation_framework_graph_data( + arg_framework: AbstractArgumentationFramework, + selected_arguments: Optional[Dict[str, List[str]]], + color_blind_mode: bool): """ - Calculate the data needed for the graphical representation of the argumentation framework + Calculate the data needed for the graphical representation of the + argumentation framework - :param arg_framework: The abstract argumentation framework that needs to be visualized. + :param arg_framework: The abstract argumentation framework that needs to be + visualized. :param selected_arguments: The arguments to be marked in a specific color. :param color_blind_mode: Is the color-blind mode on? """ @@ -53,10 +58,13 @@ def get_argumentation_framework_graph_data(arg_framework: AbstractArgumentationF 'color': get_color('gray', color_blind_mode)} for argument in arg_framework.arguments if argument.name in other_arguments] - data_nodes = data_nodes_blue + data_nodes_red + data_nodes_yellow + data_nodes_green + data_nodes_unselected + data_nodes = data_nodes_blue + data_nodes_red + data_nodes_yellow + \ + data_nodes_green + data_nodes_unselected - data_edges = [{'id': str(defeat.from_argument) + '-' + str(defeat.to_argument), - 'from': str(defeat.from_argument), 'to': str(defeat.to_argument), 'arrows': 'to'} - for defeat in arg_framework.defeats] + data_edges = [{ + 'id': str(defeat.from_argument) + '-' + str(defeat.to_argument), + 'from': str(defeat.from_argument), + 'to': str(defeat.to_argument), 'arrows': 'to'} + for defeat in arg_framework.defeats] data = {'nodes': data_nodes, 'edges': data_edges} return data diff --git a/src/py_arg_visualisation/functions/graph_data_functions/get_at_graph_data.py b/src/py_arg_visualisation/functions/graph_data_functions/get_at_graph_data.py index ecd8289..c3ffde0 100644 --- a/src/py_arg_visualisation/functions/graph_data_functions/get_at_graph_data.py +++ b/src/py_arg_visualisation/functions/graph_data_functions/get_at_graph_data.py @@ -1,20 +1,26 @@ from typing import List, Dict from py_arg.aspic.classes.argumentation_theory import ArgumentationTheory -from py_arg_visualisation.functions.graph_data_functions.get_color import get_color -from py_arg_visualisation.functions.ordering_functions.get_ordering_by_specification \ - import get_ordering_by_specification +from py_arg_visualisation.functions.graph_data_functions.get_color \ + import get_color +from py_arg_visualisation.functions.ordering_functions.\ + get_ordering_by_specification import get_ordering_by_specification -def get_argumentation_theory_graph_data(argumentation_theory: ArgumentationTheory, ordering_specification: str, - selected_arguments: Dict[str, List[str]], - color_blind_mode: bool): +def get_argumentation_theory_graph_data( + argumentation_theory: ArgumentationTheory, ordering_specification: str, + selected_arguments: Dict[str, List[str]], + color_blind_mode: bool): """ - Calculate the data needed for the graphical representation of the argumentation theory and ordering + Calculate the data needed for the graphical representation of the + argumentation theory and ordering - :param argumentation_theory: The argumentation_theory that needs to be visualized. - :param ordering_specification: The chosen ordering, combining both last/weakest link and democratic/elitist. - :param selected_arguments: Arguments to be marked with a different color (e.g. because they are in some extension) + :param argumentation_theory: The argumentation_theory that needs to be + visualized. + :param ordering_specification: The chosen ordering, combining both + last/weakest link and democratic/elitist. + :param selected_arguments: Arguments to be marked with a different + color (e.g. because they are in some extension) :param color_blind_mode: Is the color-blind mode on? """ if selected_arguments and 'blue' in selected_arguments: @@ -49,16 +55,19 @@ def get_argumentation_theory_graph_data(argumentation_theory: ArgumentationTheor color = get_color('red', color_blind_mode) else: color = get_color('gray', color_blind_mode) - data_nodes.append({'id': readable_id, 'label': argument.short_name, 'color': color}) + data_nodes.append({'id': readable_id, 'label': argument.short_name, + 'color': color}) - ordering = get_ordering_by_specification(argumentation_theory, ordering_specification) + ordering = get_ordering_by_specification(argumentation_theory, + ordering_specification) data_edges = [] for defeat in argumentation_theory.recompute_all_defeats(ordering): argument_a_id = argument_long_str_to_id[defeat.from_argument.name] argument_b_id = argument_long_str_to_id[defeat.to_argument.name] data_edges.append({'id': str(argument_a_id) + '-' + str(argument_b_id), - 'from': argument_a_id, 'to': argument_b_id, 'arrows': 'to'}) + 'from': argument_a_id, 'to': argument_b_id, + 'arrows': 'to'}) data = {'nodes': data_nodes, 'edges': data_edges} return data diff --git a/src/py_arg_visualisation/functions/import_functions/read_argumentation_framework_functions.py b/src/py_arg_visualisation/functions/import_functions/read_argumentation_framework_functions.py index 579f8a6..682a3c1 100644 --- a/src/py_arg_visualisation/functions/import_functions/read_argumentation_framework_functions.py +++ b/src/py_arg_visualisation/functions/import_functions/read_argumentation_framework_functions.py @@ -1,26 +1,32 @@ -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat def read_argumentation_framework(arguments_str: str, attacks_str: str): """ - Calculate the abstract argumentation framework from the given arguments and attacks between them. + Calculate the abstract argumentation framework from the given arguments and + attacks between them. :param arguments_str: The provided arguments. :param attacks_str: The provided attacks. """ - arg_list = [Argument(arg) for arg in arguments_str.replace(',', '').split()] + arg_list = [Argument(arg) + for arg in arguments_str.replace(',', '').split()] defeat_list = [] for attack in attacks_str.splitlines(): - att_list = attack.replace(' ', '').replace(')', '').replace('(', '').split(',') + att_list = attack.replace(' ', '').replace(')', '').replace('(', '').\ + split(',') if len(att_list) == 2 and att_list[0] != '' and att_list[1] != '': from_argument = Argument(att_list[0]) to_argument = Argument(att_list[1]) if from_argument not in arg_list or to_argument not in arg_list: - raise ValueError('Not a valid defeat, since one of the arguments does not exist.') - defeat_list.append(Defeat(Argument(att_list[0]), Argument(att_list[1]))) + raise ValueError('Not a valid defeat, since one of the ' + 'arguments does not exist.') + defeat_list.append(Defeat(Argument(att_list[0]), + Argument(att_list[1]))) arg_framework = AbstractArgumentationFramework('AF', arg_list, defeat_list) return arg_framework diff --git a/src/py_arg_visualisation/functions/import_functions/read_argumentation_theory_functions.py b/src/py_arg_visualisation/functions/import_functions/read_argumentation_theory_functions.py index 9c0bfc4..37aee02 100644 --- a/src/py_arg_visualisation/functions/import_functions/read_argumentation_theory_functions.py +++ b/src/py_arg_visualisation/functions/import_functions/read_argumentation_theory_functions.py @@ -4,42 +4,54 @@ from py_arg.aspic.classes.argumentation_theory import ArgumentationTheory from py_arg.aspic.classes.defeasible_rule import DefeasibleRule from py_arg.aspic.classes.literal import Literal -from py_arg.aspic.classes.orderings.preference_preorder import PreferencePreorder +from py_arg.aspic.classes.orderings.preference_preorder import \ + PreferencePreorder from py_arg.aspic.classes.strict_rule import StrictRule -def _read_axioms_and_ordinary_premises(axioms_or_ordinary_premises_str) -> List[str]: - return [literal_str.strip() for literal_str in axioms_or_ordinary_premises_str.split()] +def _read_axioms_and_ordinary_premises(axioms_or_ordinary_premises_str) -> \ + List[str]: + return [literal_str.strip() + for literal_str in axioms_or_ordinary_premises_str.split()] def _read_strict_rules(strict_rules_str) -> List[Tuple[str, Set[str], str]]: - def read_strict_rule(rule_id, strict_rule_str) -> Tuple[str, Set[str], str]: + def read_strict_rule(rule_id, strict_rule_str) -> \ + Tuple[str, Set[str], str]: if '->' not in strict_rule_str: - raise ValueError('Each strict rule should contain -> at least once.') + raise ValueError( + 'Each strict rule should contain -> at least once.') before_rule, after_rule = strict_rule_str.split('->', 1) - antecedents = set(antecedent_str.strip() for antecedent_str in before_rule.split(',')) + antecedents = set(antecedent_str.strip() + for antecedent_str in before_rule.split(',')) if '->' in after_rule: raise ValueError('Each strict rule should contain -> only once.') consequent = after_rule.strip() return rule_id, antecedents, consequent return [read_strict_rule(str(rule_id), strict_rule_str) - for rule_id, strict_rule_str in enumerate(strict_rules_str.splitlines())] + for rule_id, strict_rule_str in enumerate( + strict_rules_str.splitlines())] -def _read_defeasible_rules(defeasible_rules_str: str) -> List[Tuple[str, Set[str], str]]: - def read_defeasible_rule(named_defeasible_rule_str: str) -> Tuple[str, Set[str], str]: +def _read_defeasible_rules(defeasible_rules_str: str) -> \ + List[Tuple[str, Set[str], str]]: + def read_defeasible_rule(named_defeasible_rule_str: str) -> \ + Tuple[str, Set[str], str]: if ':' not in named_defeasible_rule_str: raise ValueError('The rule should have a rule name, preceding :.') name, defeasible_rule_str = named_defeasible_rule_str.split(':', 1) if '=>' not in defeasible_rule_str: - raise ValueError('Each defeasible rule should contain => at least once.') + raise ValueError( + 'Each defeasible rule should contain => at least once.') before_rule, after_rule = defeasible_rule_str.split('=>', 1) - antecedents = set(antecedent_str.strip() for antecedent_str in before_rule.split(',')) + antecedents = set(antecedent_str.strip() + for antecedent_str in before_rule.split(',')) if '=>' in after_rule: - raise ValueError('Each defeasible rule should contain => only once.') + raise ValueError( + 'Each defeasible rule should contain => only once.') consequent = after_rule.strip() return name, antecedents, consequent @@ -59,31 +71,41 @@ def read_preference_rule(preference_str: str) -> Tuple: else: more, less = preference_str.split('>', 1) return less.strip(), more.strip() - return [read_preference_rule(preference_str_rule) for preference_str_rule in preferences_str.splitlines()] + return [read_preference_rule(preference_str_rule) + for preference_str_rule in preferences_str.splitlines()] def read_argumentation_theory(axioms_str: str, ordinary_premises_str: str, strict_rules_str: str, defeasible_rules_str: str, - premise_preferences_str: str, defeasible_rule_preference_str: str): + premise_preferences_str: str, + defeasible_rule_preference_str: str): """ - Calculate the argumentation theory from the axioms, ordinary premises, strict and defeasible rules, premise and + Calculate the argumentation theory from the axioms, ordinary premises, + strict and defeasible rules, premise and rule preference and the given ordering :param axioms_str: The provided axioms (premises that cannot be attacked). - :param ordinary_premises_str: The ordinary premises (premises that can be questioned). - :param strict_rules_str: The provided strict rules (rules that cannot be attacked). - :param defeasible_rules_str: The defeasible rules (rules that can be questioned). + :param ordinary_premises_str: The ordinary premises (premises that can be + questioned). + :param strict_rules_str: The provided strict rules (rules that cannot be + attacked). + :param defeasible_rules_str: The defeasible rules (rules that can be + questioned). :param premise_preferences_str: The preferences over the ordinary premises. - :param defeasible_rule_preference_str: The preferences over the defeasible rules. + :param defeasible_rule_preference_str: The preferences over the defeasible + rules. """ - # Read axioms, ordinary premises, defeasible rules and strict rules (first in a str format) from the strs + # Read axioms, ordinary premises, defeasible rules and strict rules + # (first in a str format) from the strs axioms = _read_axioms_and_ordinary_premises(axioms_str) - ordinary_premises = _read_axioms_and_ordinary_premises(ordinary_premises_str) + ordinary_premises = _read_axioms_and_ordinary_premises( + ordinary_premises_str) defeasible_rules = _read_defeasible_rules(defeasible_rules_str) strict_rules = _read_strict_rules(strict_rules_str) - # Derive the language: first obtain "absolute" literal strs from axioms and rules + # Derive the language: first obtain "absolute" literal strs from axioms and + # rules def get_absolute(non_absolute_literal_str: str) -> str: return non_absolute_literal_str.replace('~', '').replace('-', '') absolute_literal_strs = set() @@ -114,34 +136,46 @@ def get_absolute(non_absolute_literal_str: str) -> str: contraries_and_contradictories[l_naf.s1] = {l_pos} contraries_and_contradictories[l_neg.s1] = {l_pos} - # Read axioms, ordinary premises, defeasible rules and strict rules, now in the proper format + # Read axioms, ordinary premises, defeasible rules and strict rules, now in + # the proper format axioms = [language[axiom_str] for axiom_str in axioms] - ordinary_premises = [language[ordinary_premise_str] for ordinary_premise_str in ordinary_premises] - defeasible_rules = [DefeasibleRule(rule_id, {language[antecedent] for antecedent in antecedents}, - language[consequent]) - for rule_id, antecedents, consequent in defeasible_rules] - strict_rules = [StrictRule(rule_id, {language[antecedent] for antecedent in antecedents}, language[consequent]) + ordinary_premises = [language[ordinary_premise_str] + for ordinary_premise_str in ordinary_premises] + defeasible_rules = \ + [DefeasibleRule(rule_id, {language[antecedent] + for antecedent in antecedents}, + language[consequent]) + for rule_id, antecedents, consequent in defeasible_rules] + strict_rules = [StrictRule(rule_id, {language[antecedent] + for antecedent in antecedents}, + language[consequent]) for rule_id, antecedents, consequent in strict_rules] # Read the ordinary premise preferences - ordinary_premise_preference_strs = _read_preferences(premise_preferences_str) - ordinary_premise_preferences = PreferencePreorder.create_reflexive_preorder(ordinary_premises) + ordinary_premise_preference_strs = \ + _read_preferences(premise_preferences_str) + ordinary_premise_preferences = \ + PreferencePreorder.create_reflexive_preorder(ordinary_premises) for less, more in ordinary_premise_preference_strs: less_literal = language[less] more_literal = language[more] ordinary_premise_preferences.append((less_literal, more_literal)) # Read the defeasible rule preferences - defeasible_rule_preference_strs = _read_preferences(defeasible_rule_preference_str) - defeasible_rule_preferences = PreferencePreorder.create_reflexive_preorder(defeasible_rules) + defeasible_rule_preference_strs = \ + _read_preferences(defeasible_rule_preference_str) + defeasible_rule_preferences = \ + PreferencePreorder.create_reflexive_preorder(defeasible_rules) defeasible_rule_dict = {rule.id: rule for rule in defeasible_rules} for less, more in defeasible_rule_preference_strs: less_rule = defeasible_rule_dict[less] more_rule = defeasible_rule_dict[more] defeasible_rule_preferences.append((less_rule, more_rule)) - argumentation_system = ArgumentationSystem(language, contraries_and_contradictories, strict_rules, - defeasible_rules, defeasible_rule_preferences) - argumentation_theory = ArgumentationTheory(argumentation_system, axioms, ordinary_premises, - ordinary_premise_preferences) + argumentation_system = ArgumentationSystem( + language, contraries_and_contradictories, strict_rules, + defeasible_rules, defeasible_rule_preferences) + argumentation_theory = ArgumentationTheory( + argumentation_system, axioms, ordinary_premises, + ordinary_premise_preferences) return argumentation_theory diff --git a/src/py_arg_visualisation/functions/ordering_functions/get_ordering_by_specification.py b/src/py_arg_visualisation/functions/ordering_functions/get_ordering_by_specification.py index bef4fe9..dace185 100644 --- a/src/py_arg_visualisation/functions/ordering_functions/get_ordering_by_specification.py +++ b/src/py_arg_visualisation/functions/ordering_functions/get_ordering_by_specification.py @@ -1,21 +1,32 @@ from py_arg.aspic.classes.argumentation_theory import ArgumentationTheory -from py_arg.aspic.classes.orderings.argument_orderings.last_link_ordering import LastLinkDemocraticOrdering, \ +from py_arg.aspic.classes.orderings.argument_orderings.last_link_ordering \ + import LastLinkDemocraticOrdering, \ LastLinkElitistOrdering -from py_arg.aspic.classes.orderings.argument_orderings.weakest_link_ordering import WeakestLinkDemocraticOrdering, \ +from py_arg.aspic.classes.orderings.argument_orderings.weakest_link_ordering \ + import WeakestLinkDemocraticOrdering, \ WeakestLinkElitistOrdering -def get_ordering_by_specification(argumentation_theory: ArgumentationTheory, ordering_specification: str): - def_rule_preferences = argumentation_theory.argumentation_system.rule_preferences +def get_ordering_by_specification(argumentation_theory: ArgumentationTheory, + ordering_specification: str): + def_rule_preferences = \ + argumentation_theory.argumentation_system.rule_preferences premise_preferences = argumentation_theory.ordinary_premise_preferences if ordering_specification == 'democratic_last_link': - ordering = LastLinkDemocraticOrdering(def_rule_preferences, premise_preferences) + ordering = \ + LastLinkDemocraticOrdering(def_rule_preferences, + premise_preferences) elif ordering_specification == 'elitist_last_link': - ordering = LastLinkElitistOrdering(def_rule_preferences, premise_preferences) + ordering = \ + LastLinkElitistOrdering(def_rule_preferences, premise_preferences) elif ordering_specification == 'democratic_weakest_link': - ordering = WeakestLinkDemocraticOrdering(def_rule_preferences, premise_preferences) + ordering = \ + WeakestLinkDemocraticOrdering(def_rule_preferences, + premise_preferences) elif ordering_specification == 'elitist_weakest_link': - ordering = WeakestLinkElitistOrdering(def_rule_preferences, premise_preferences) + ordering = \ + WeakestLinkElitistOrdering(def_rule_preferences, + premise_preferences) else: raise NotImplementedError return ordering diff --git a/src/py_arg_visualisation/functions/tweety_services_functions/tweety_services_handler.py b/src/py_arg_visualisation/functions/tweety_services_functions/tweety_services_handler.py index f0c5dde..d6fa6c7 100644 --- a/src/py_arg_visualisation/functions/tweety_services_functions/tweety_services_handler.py +++ b/src/py_arg_visualisation/functions/tweety_services_functions/tweety_services_handler.py @@ -1,14 +1,12 @@ - +import os from dataclasses import dataclass, field -from yamldataclassconfig.config import YamlDataClassConfig -from yamldataclassconfig import create_file_path_field from pathlib import Path -import os + +import requests from dataclasses_json import DataClassJsonMixin from marshmallow import fields -from datetime import datetime -from typing import Optional,List -import requests +from yamldataclassconfig import create_file_path_field +from yamldataclassconfig.config import YamlDataClassConfig @dataclass @@ -32,38 +30,42 @@ class PayloadConfig(DataClassJsonMixin): 'mm_field': fields.String}}) - @dataclass class TweetyServiceConfig(YamlDataClassConfig): - base_url: str = None - payload: PayloadConfig = field( + base_url: str = None + payload: PayloadConfig = field( default=None, metadata={'dataclasses_json': {'mm_field': PayloadConfig}}) - FILE_PATH: Path = create_file_path_field(os.path.join(Path(__file__).parent, 'tweety_api_configs.yaml')) + FILE_PATH: Path = create_file_path_field( + os.path.join(Path(__file__).parent, 'tweety_api_configs.yaml')) + def get_models(config: TweetyServiceConfig): config.payload.cmd = 'get_models' # TODO: check if config is valid - url = os.path.join(config.base_url,'dung') - return send_post(config.payload,url) + url = os.path.join(config.base_url, 'dung') + return send_post(config.payload, url) -def send_post(payload: PayloadConfig,url: str): - response = requests.post(url, json=payload.__dict__) - # Check the response status code +def send_post(payload: PayloadConfig, url: str): + response = requests.post(url, json=payload.__dict__) + # Check the response status code if response.status_code == 200: print(f"Request successful. Response: {response.json()}") - return response.json(), response.status_code # Print the response JSON + # Print the response JSON + return response.json(), response.status_code else: print(f"Request failed with status code {response.status_code}:") - return response.text, response.status_code # Print the error response text + # Print the error response text + return response.text, response.status_code def get_services_info(config: TweetyServiceConfig): - info_url = os.path.join(config.base_url,'info') + info_url = os.path.join(config.base_url, 'info') config.payload.cmd = 'info' return send_post(config.payload, info_url) + def get_supported_semantics(config): return get_services_info(config)[0]['semantics'] @@ -71,15 +73,11 @@ def get_supported_semantics(config): def get_supported_semantics_mapping(): pass -if __name__ == '__main__': +if __name__ == '__main__': config = TweetyServiceConfig() config.load() print(config) - - + semantics = get_supported_semantics(config) print(semantics) - - - diff --git a/src/py_arg_visualisation/pages/01_generate_abstract.py b/src/py_arg_visualisation/pages/01_generate_abstract.py index 081e902..661e011 100644 --- a/src/py_arg_visualisation/pages/01_generate_abstract.py +++ b/src/py_arg_visualisation/pages/01_generate_abstract.py @@ -5,35 +5,46 @@ from dash import html, callback, Input, Output, State, MATCH, dcc import dash_bootstrap_components as dbc -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import \ +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import \ AbstractArgumentationFrameworkGenerator -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_aspartix_format_writer import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_to_aspartix_format_writer import \ ArgumentationFrameworkToASPARTIXFormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_iccma23_format_writer import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_to_iccma23_format_writer import \ ArgumentationFrameworkToICCMA23FormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_json_writer import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_to_json_writer import \ ArgumentationFrameworkToJSONWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_trivial_graph_format_writer import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_to_trivial_graph_format_writer import \ ArgumentationFrameworkToTrivialGraphFormatWriter -dash.register_page(__name__, name='GenerateAbstract', title='Generate Abstract AF') +dash.register_page(__name__, name='GenerateAbstract', + title='Generate Abstract AF') left_column = dbc.Col([ html.H2('Input'), html.Br(), dbc.Row([dbc.Col(html.B('Number of arguments')), - dbc.Col(dbc.Input(type='number', min=0, max=50, step=1, value=8, - id='01-generate-abstract-nr-arguments-input'))]), + dbc.Col(dbc.Input( + type='number', min=0, max=50, step=1, value=8, + id='01-generate-abstract-nr-arguments-input'))]), dbc.Row([dbc.Col(html.B('Number of defeats')), - dbc.Col(dbc.Input(type='number', min=0, max=50, step=1, value=8, - id='01-generate-abstract-nr-defeats-input'))]), + dbc.Col(dbc.Input( + type='number', min=0, max=50, step=1, value=8, + id='01-generate-abstract-nr-defeats-input'))]), dbc.Row([dbc.Col(html.B('Allow self-defeats')), dbc.Col(dbc.Select( - options=[{'label': answer, 'value': answer} for answer in ['Yes', 'No']], - value='Yes', id='01-generate-abstract-allow-self-defeats-input')) + options=[{'label': answer, 'value': answer} + for answer in ['Yes', 'No']], + value='Yes', + id='01-generate-abstract-allow-self-defeats-input')) ]), html.Br(), dbc.Row([dbc.Button('Generate', id='01-generate-abstract-button', @@ -54,7 +65,8 @@ State('01-generate-abstract-nr-defeats-input', 'value'), State('01-generate-abstract-allow-self-defeats-input', 'value')) def generate_abstract_argumentation_framework( - nr_clicks: int, nr_arguments: str, nr_defeats: str, allow_self_defeats: str): + nr_clicks: int, nr_arguments: str, nr_defeats: str, + allow_self_defeats: str): if not nr_clicks: return 'Press the button to generate an argumentation framework.' @@ -85,27 +97,40 @@ def generate_abstract_argumentation_framework( [html.H2('Output'), dbc.Row([ dbc.Col([html.B('Arguments'), dbc.Textarea( - value='\n'.join(str(arg) for arg in argumentation_framework.arguments), + value='\n'.join(str(arg) + for arg in argumentation_framework.arguments), style={'height': '300px'}, - id={'type': '01-generate-abstract-arguments-text', 'index': nr_clicks})]), + id={'type': '01-generate-abstract-arguments-text', + 'index': nr_clicks})]), dbc.Col([html.B('Defeats'), dbc.Textarea( - value='\n'.join((f'({str(defeat.from_argument)},{str(defeat.to_argument)})' - for defeat in argumentation_framework.defeats)), + value='\n'.join( + (f'({str(defeat.from_argument)},' + f'{str(defeat.to_argument)})' + for defeat in argumentation_framework.defeats)), style={'height': '300px'}, - id={'type': '01-generate-abstract-defeats-text', 'index': nr_clicks})]) + id={'type': '01-generate-abstract-defeats-text', + 'index': nr_clicks})]) ]), html.Br(), dbc.Row([ dbc.InputGroup([ dbc.InputGroupText('Filename'), - dbc.Input(value='generated_af', id={'type': '01-generate-abstract-filename', 'index': nr_clicks}), + dbc.Input(value='generated_af', + id={'type': '01-generate-abstract-filename', + 'index': nr_clicks}), dbc.InputGroupText('.'), dbc.Select(options=[{'label': extension, 'value': extension} - for extension in ['JSON', 'TGF', 'APX', 'ICCMA23']], - value='JSON', id={'type': '01-generate-abstract-extension', 'index': nr_clicks}), - dbc.Button('Download', id={'type': '01-generate-abstract-download-button', 'index': nr_clicks}), + for extension in ['JSON', 'TGF', 'APX', + 'ICCMA23']], + value='JSON', + id={'type': '01-generate-abstract-extension', + 'index': nr_clicks}), + dbc.Button('Download', + id={'type': '01-generate-abstract-download-button', + 'index': nr_clicks}), ]), - dcc.Download(id={'type': '01-generate-abstract-downloader', 'index': nr_clicks}) + dcc.Download(id={'type': '01-generate-abstract-downloader', + 'index': nr_clicks}) ]) ] @@ -126,35 +151,47 @@ def read_defeats(defeat_text: str) -> List[Defeat]: @callback( - Output({'type': '01-generate-abstract-downloader', 'index': MATCH}, 'data'), - Input({'type': '01-generate-abstract-download-button', 'index': MATCH}, 'n_clicks'), - State({'type': '01-generate-abstract-arguments-text', 'index': MATCH}, 'value'), - State({'type': '01-generate-abstract-defeats-text', 'index': MATCH}, 'value'), + Output({'type': '01-generate-abstract-downloader', 'index': MATCH}, + 'data'), + Input({'type': '01-generate-abstract-download-button', 'index': MATCH}, + 'n_clicks'), + State({'type': '01-generate-abstract-arguments-text', 'index': MATCH}, + 'value'), + State({'type': '01-generate-abstract-defeats-text', 'index': MATCH}, + 'value'), State({'type': '01-generate-abstract-filename', 'index': MATCH}, 'value'), State({'type': '01-generate-abstract-extension', 'index': MATCH}, 'value'), prevent_initial_call=True, ) def download_generated_abstract_argumentation_framework( - _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, extension: str): + _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, + extension: str): argumentation_framework = AbstractArgumentationFramework( name='generated', - arguments=[Argument(arg_str.strip()) for arg_str in arguments_text.split('\n')], + arguments=[Argument(arg_str.strip()) + for arg_str in arguments_text.split('\n')], defeats=read_defeats(defeats_text) ) if extension == 'JSON': - argumentation_framework_json = ArgumentationFrameworkToJSONWriter().to_dict(argumentation_framework) + argumentation_framework_json = \ + ArgumentationFrameworkToJSONWriter().to_dict( + argumentation_framework) argumentation_framework_str = json.dumps(argumentation_framework_json) elif extension == 'TGF': argumentation_framework_str = \ - ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str( + argumentation_framework) elif extension == 'APX': argumentation_framework_str = \ - ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str( + argumentation_framework) elif extension == 'ICCMA23': argumentation_framework_str = \ - ArgumentationFrameworkToICCMA23FormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToICCMA23FormatWriter.write_to_str( + argumentation_framework) else: raise NotImplementedError - return {'content': argumentation_framework_str, 'filename': filename + '.' + extension} + return {'content': argumentation_framework_str, + 'filename': filename + '.' + extension} diff --git a/src/py_arg_visualisation/pages/02_generate_random_aspic.py b/src/py_arg_visualisation/pages/02_generate_random_aspic.py index 86f0a02..2252d3d 100644 --- a/src/py_arg_visualisation/pages/02_generate_random_aspic.py +++ b/src/py_arg_visualisation/pages/02_generate_random_aspic.py @@ -1,9 +1,8 @@ import dash -from dash import html, dcc, callback, Input, Output -import dash_bootstrap_components as dbc +from dash import html - -dash.register_page(__name__, name='GenerateRandomAspic', title='Generate Random ASPIC+ AT') +dash.register_page(__name__, name='GenerateRandomAspic', + title='Generate Random ASPIC+ AT') layout = html.Div( children=[ diff --git a/src/py_arg_visualisation/pages/03_generate_layered_aspic.py b/src/py_arg_visualisation/pages/03_generate_layered_aspic.py index 88f020c..4296b71 100644 --- a/src/py_arg_visualisation/pages/03_generate_layered_aspic.py +++ b/src/py_arg_visualisation/pages/03_generate_layered_aspic.py @@ -1,51 +1,76 @@ import json import dash -from dash import html, dcc, callback, Input, Output, State, MATCH import dash_bootstrap_components as dbc +from dash import html, dcc, callback, Input, Output, State, MATCH -from py_arg.aspic.generators.argumentation_system_generators.layered_argumentation_system_generator import \ +from py_arg.aspic.generators.argumentation_system_generators. \ + layered_argumentation_system_generator import \ LayeredArgumentationSystemGenerator -from py_arg.aspic.import_export.argumentation_system_to_json_writer import ArgumentationSystemToJSONWriter +from py_arg.aspic.import_export.argumentation_system_to_json_writer import \ + ArgumentationSystemToJSONWriter -dash.register_page(__name__, name='GenerateLayeredAspic', title='Generate Layered ASPIC+ AS') +dash.register_page(__name__, name='GenerateLayeredAspic', + title='Generate Layered ASPIC+ AS') left_column = dbc.Col([ html.H2('Input'), html.Br(), dbc.Row([dbc.Col(html.B('Number of literals')), - dbc.Col([dbc.Input(type='number', min=0, max=500, step=2, value=6, - id='03-generate-layered-aspic-nr-literals-input'), - dbc.Tooltip('The desired number of literals in the argumentation system. ' - 'Note that this number should be even.', - target='03-generate-layered-aspic-nr-literals-input')])]), - dbc.Row([dbc.Col(html.B('Number of rules')), - dbc.Col([dbc.Input(type='number', min=0, max=500, step=1, value=3, - id='03-generate-layered-aspic-nr-rules-input'), - dbc.Tooltip('The desired number of rules (strict or defeasible).', - target='03-generate-layered-aspic-nr-rules-input')])]), - dbc.Row([dbc.Col(html.B('Rule antecedent distribution')), - dbc.Col([dbc.Input(id='03-generate-layered-aspic-rule-antecedent-distribution-input', - value='2: 1, 1: 2'), - dbc.Tooltip('Number of rules with a specific number of antecedents. ' - 'These should be put in the format ' - '[nr_ants_1]: [nr_rules_1], [nr_ants_2]: [nr_rules_2], ...', - target='03-generate-layered-aspic-rule-antecedent-distribution-input')])]), + dbc.Col([dbc.Input( + type='number', min=0, max=500, step=2, value=6, + id='03-generate-layered-aspic-nr-literals-input'), + dbc.Tooltip( + 'The desired number of literals in the argumentation ' + 'system. Note that this number should be even.', + target='03-generate-layered-aspic-nr-literals-input' + )])]), + dbc.Row([ + dbc.Col(html.B('Number of rules')), + dbc.Col([dbc.Input(type='number', min=0, max=500, step=1, value=3, + id='03-generate-layered-aspic-nr-rules-input'), + dbc.Tooltip( + 'The desired number of rules (strict or defeasible).', + target='03-generate-layered-aspic-nr-rules-input')])]), + dbc.Row([ + dbc.Col(html.B('Rule antecedent distribution')), + dbc.Col([dbc.Input( + id='03-generate-layered-aspic-rule-antecedent-distribution-input', + value='2: 1, 1: 2'), + dbc.Tooltip( + 'Number of rules with a specific number of ' + 'antecedents. ' + 'These should be put in the format ' + '[nr_ants_1]: [nr_rules_1], ' + '[nr_ants_2]: [nr_rules_2], ...', + target='03-generate-layered-aspic-rule-antecedent-' + 'distribution-input')])]), dbc.Row([dbc.Col(html.B('Literal layer distribution')), - dbc.Col([dbc.Input(id='03-generate-layered-aspic-literal-layer-distribution-input', - value='0: 3, 1: 2, 2: 1'), - dbc.Tooltip('Number of literals on a specific "layer" (which is something ' - 'like the height in the support graph). ' - 'These should be put in the format ' - '[layer_nr_1]: [nr_literals_1], [layer_nr_2]: [nr_literals_2], ...', - target='03-generate-layered-aspic-literal-layer-distribution-input' - )])]), + dbc.Col([dbc.Input( + id='03-generate-layered-aspic-literal-layer-' + 'distribution-input', + value='0: 3, 1: 2, 2: 1'), + dbc.Tooltip( + 'Number of literals on a specific "layer" ' + '(which is something ' + 'like the height in the support graph). ' + 'These should be put in the format ' + '[layer_nr_1]: [nr_literals_1], ' + '[layer_nr_2]: [nr_literals_2], ...', + target='03-generate-layered-aspic-literal-layer-' + 'distribution-input' + )])]), dbc.Row([dbc.Col(html.B('Strict rule ratio')), dbc.Col([dbc.Input(type='number', min=0, max=1, value=0, - id='03-generate-layered-aspic-strict-rule-ratio-input'), - dbc.Tooltip('Ration of strict rules over all rules, e.g. if this number is 0.8, ' - 'then around 80% of the generated rules are expected to be strict.', - target='03-generate-layered-aspic-strict-rule-ratio-input')])]), + id='03-generate-layered-aspic-strict-rule-' + 'ratio-input'), + dbc.Tooltip( + 'Ration of strict rules over all rules, e.g. ' + 'if this number is 0.8, ' + 'then around 80% of the generated rules are ' + 'expected to be strict.', + target='03-generate-layered-aspic-strict-rule-' + 'ratio-input')])]), html.Br(), dbc.Row([dbc.Button('Generate', id='03-generate-layered-aspic-button', className='w-50 mx-auto')]) @@ -56,7 +81,8 @@ layout = html.Div([ html.H1('Generate Random Layered ASPIC+ Argumentation System'), html.P('This generator assumes that negation is used for contradiction. ' - 'In addition, it does not generate any preference ordering between defeasible rules.'), + 'In addition, it does not generate any preference ordering ' + 'between defeasible rules.'), html.Div(layout_generate_layered_aspic) ]) @@ -65,8 +91,10 @@ Input('03-generate-layered-aspic-button', 'n_clicks'), State('03-generate-layered-aspic-nr-literals-input', 'value'), State('03-generate-layered-aspic-nr-rules-input', 'value'), - State('03-generate-layered-aspic-rule-antecedent-distribution-input', 'value'), - State('03-generate-layered-aspic-literal-layer-distribution-input', 'value'), + State('03-generate-layered-aspic-rule-antecedent-distribution-input', + 'value'), + State('03-generate-layered-aspic-literal-layer-distribution-input', + 'value'), State('03-generate-layered-aspic-strict-rule-ratio-input', 'value')) def generate_layered_aspic_argumentation_system( nr_clicks: int, nr_literals: str, nr_rules: str, @@ -126,36 +154,42 @@ def generate_layered_aspic_argumentation_system( strict_rule_ratio=strict_rule_ratio_float ) argumentation_system = generator.generate() - argumentation_system_json = json.dumps(ArgumentationSystemToJSONWriter().to_dict(argumentation_system)) + argumentation_system_json = json.dumps( + ArgumentationSystemToJSONWriter().to_dict(argumentation_system)) output_children = \ [html.H2('Output'), dbc.Row([ - dbc.Col([html.B('Literals'), dbc.Textarea( - value='\n'.join(sorted(argumentation_system.language.keys())), - style={'height': '300px'})]), - dbc.Col([html.B('Rules'), dbc.Textarea( - value='\n'.join((str(rule) for rule in argumentation_system.rules)), - style={'height': '300px'})]) + dbc.Col([html.B('Literals'), dbc.Textarea( + value='\n'.join(sorted(argumentation_system.language.keys())), + style={'height': '300px'})]), + dbc.Col([html.B('Rules'), dbc.Textarea( + value='\n'.join( + (str(rule) for rule in argumentation_system.rules)), + style={'height': '300px'})]) ]), dcc.Store(data=argumentation_system_json, - id={'type': '03-generate-layered-aspic-download-content', 'index': nr_clicks}), + id={'type': '03-generate-layered-aspic-download-content', + 'index': nr_clicks}), html.Br(), - # dbc.Row([dbc.Button('Download', - # id={'type': '03-generate-layered-aspic-download-button', 'index': nr_clicks}, - # className='w-50 mx-auto')]), - # dcc.Download(id={'type': '03-generate-layered-aspic-downloader', 'index': nr_clicks}), dbc.Row([ dbc.InputGroup([ dbc.InputGroupText('Filename'), - dbc.Input(value='generated_as', id={'type': '03-generate-layered-aspic-filename', 'index': nr_clicks}), + dbc.Input(value='generated_as', + id={'type': '03-generate-layered-aspic-filename', + 'index': nr_clicks}), dbc.InputGroupText('.'), dbc.Select(options=[{'label': extension, 'value': extension} for extension in ['JSON']], - value='JSON', id={'type': '03-generate-layered-aspic-extension', 'index': nr_clicks}), - dbc.Button('Download', id={'type': '03-generate-layered-aspic-download-button', 'index': nr_clicks}), + value='JSON', + id={'type': '03-generate-layered-aspic-extension', + 'index': nr_clicks}), + dbc.Button('Download', id={ + 'type': '03-generate-layered-aspic-download-button', + 'index': nr_clicks}), ]), - dcc.Download(id={'type': '03-generate-layered-aspic-downloader', 'index': nr_clicks}) + dcc.Download(id={'type': '03-generate-layered-aspic-downloader', + 'index': nr_clicks}) ]) ] @@ -163,15 +197,24 @@ def generate_layered_aspic_argumentation_system( @callback( - Output({'type': '03-generate-layered-aspic-downloader', 'index': MATCH}, 'data'), - Input({'type': '03-generate-layered-aspic-download-button', 'index': MATCH}, 'n_clicks'), - State({'type': '03-generate-layered-aspic-download-content', 'index': MATCH}, 'data'), - State({'type': '03-generate-layered-aspic-filename', 'index': MATCH}, 'value'), - State({'type': '03-generate-layered-aspic-extension', 'index': MATCH}, 'value'), + Output({'type': '03-generate-layered-aspic-downloader', 'index': MATCH}, + 'data'), + Input({'type': '03-generate-layered-aspic-download-button', + 'index': MATCH}, + 'n_clicks'), + State( + {'type': '03-generate-layered-aspic-download-content', 'index': MATCH}, + 'data'), + State({'type': '03-generate-layered-aspic-filename', 'index': MATCH}, + 'value'), + State({'type': '03-generate-layered-aspic-extension', 'index': MATCH}, + 'value'), prevent_initial_call=True, ) def download_generated_argumentation_system( - _nr_clicks: int, argumentation_system_data, filename: str, extension: str): + _nr_clicks: int, argumentation_system_data, filename: str, + extension: str): if extension == 'JSON': - return {'content': argumentation_system_data, 'filename': filename + '.' + extension} + return {'content': argumentation_system_data, + 'filename': filename + '.' + extension} return NotImplementedError diff --git a/src/py_arg_visualisation/pages/04_generate_erdos_renyi.py b/src/py_arg_visualisation/pages/04_generate_erdos_renyi.py index 92e8d6f..73a4fdf 100644 --- a/src/py_arg_visualisation/pages/04_generate_erdos_renyi.py +++ b/src/py_arg_visualisation/pages/04_generate_erdos_renyi.py @@ -2,45 +2,57 @@ from typing import List import dash -from dash import html, callback, Input, Output, State, MATCH, dcc import dash_bootstrap_components as dbc +from dash import html, callback, Input, Output, State, MATCH, dcc -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.generators.erdos_renyi_generator import ErdosRenyiGenerator -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_aspartix_format_writer import \ +from py_arg.abstract_argumentation.generators.erdos_renyi_generator import \ + ErdosRenyiGenerator +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_aspartix_format_writer import \ ArgumentationFrameworkToASPARTIXFormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_iccma23_format_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_iccma23_format_writer import \ ArgumentationFrameworkToICCMA23FormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_json_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_json_writer import \ ArgumentationFrameworkToJSONWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_trivial_graph_format_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_trivial_graph_format_writer import \ ArgumentationFrameworkToTrivialGraphFormatWriter -dash.register_page(__name__, name='GenerateErdosRenyi', title='Generate Erdős-Rényi AF') +dash.register_page(__name__, name='GenerateErdosRenyi', + title='Generate Erdős-Rényi AF') left_column = dbc.Col([ html.H2('Input'), html.Br(), dbc.Row([dbc.Col(html.B('Number of arguments')), - dbc.Col(dbc.Input(type='number', min=0, max=50, step=1, value=8, - id='04-generate-abstract-nr-arguments-input'))]), + dbc.Col(dbc.Input( + type='number', min=0, max=50, step=1, value=8, + id='04-generate-abstract-nr-arguments-input'))]), dbc.Row([dbc.Col(html.B('Use Seed')), dbc.Col(dbc.Select( - options=[{'label': answer, 'value': answer} for answer in ['Yes', 'No']], + options=[{'label': answer, 'value': answer} for answer in + ['Yes', 'No']], value='No', id='04-generate-abstract-use-seed-input'))]), dbc.Row([dbc.Col(html.B('Seed')), dbc.Col(dbc.Input(type='number', min=0, max=128, step=1, value=42, id='04-generate-abstract-seed-input'))]), dbc.Row([dbc.Col(html.B('Directed')), dbc.Col(dbc.Select( - options=[{'label': answer, 'value': answer} for answer in ['Yes', 'No']], + options=[{'label': answer, 'value': answer} for answer in + ['Yes', 'No']], value='Yes', id='04-generate-abstract-is-directed-input'))]), dbc.Row([dbc.Col(html.B('Probability of defeat')), - dbc.Col(dcc.Slider( min=0.1, max=1, step=0.1, value=0.5,marks=None, - tooltip={"placement": "bottom", "always_visible": True}, - id='04-generate-abstract-prob-defeats-input'))]), + dbc.Col(dcc.Slider( + min=0.1, max=1, step=0.1, value=0.5, marks=None, + tooltip={"placement": "bottom", + "always_visible": True}, + id='04-generate-abstract-prob-defeats-input'))]), html.Br(), dbc.Row([dbc.Button('Generate', id='04-generate-abstract-button', className='w-50 mx-auto')]) @@ -62,7 +74,8 @@ State('04-generate-abstract-seed-input', 'value'), State('04-generate-abstract-use-seed-input', 'value')) def generate_abstract_argumentation_framework( - nr_clicks: int, nr_arguments: str, prob_defeats: str, is_directed: str, seed: str,use_seed: str): + nr_clicks: int, nr_arguments: str, prob_defeats: str, is_directed: str, + seed: str, use_seed: str): if not nr_clicks: return 'Press the button to generate an argumentation framework.' @@ -72,17 +85,13 @@ def generate_abstract_argumentation_framework( return 'The number of arguments is not an integer.' if nr_arguments_int < 1: return 'The number of arguments should be at least one.' - + try: seed_int = int(seed) except TypeError: return 'The seed value is not an integer.' - prob_defeats_float = float(prob_defeats) - - - is_directed_bool = is_directed == 'Yes' if use_seed == 'No': @@ -93,34 +102,50 @@ def generate_abstract_argumentation_framework( # nr_of_defeats=nr_defeats_int, # allow_self_defeats=allow_self_defeats_bool # ) - generator = ErdosRenyiGenerator(nr_of_arguments=nr_arguments_int,prob_edge=prob_defeats_float,is_directed=is_directed_bool,seed=seed_int) + generator = ErdosRenyiGenerator( + nr_of_arguments=nr_arguments_int, + prob_edge=prob_defeats_float, + is_directed=is_directed_bool, seed=seed_int) argumentation_framework = generator.generate() output_children = \ [html.H2('Output'), dbc.Row([ dbc.Col([html.B('Arguments'), dbc.Textarea( - value='\n'.join(str(arg) for arg in argumentation_framework.arguments), + value='\n'.join( + str(arg) for arg in argumentation_framework.arguments), style={'height': '300px'}, - id={'type': '04-generate-abstract-arguments-text', 'index': nr_clicks})]), + id={'type': '04-generate-abstract-arguments-text', + 'index': nr_clicks})]), dbc.Col([html.B('Defeats'), dbc.Textarea( - value='\n'.join((f'({str(defeat.from_argument)},{str(defeat.to_argument)})' - for defeat in argumentation_framework.defeats)), + value='\n'.join( + (f'({str(defeat.from_argument)},' + f'{str(defeat.to_argument)})' + for defeat in argumentation_framework.defeats)), style={'height': '300px'}, - id={'type': '04-generate-abstract-defeats-text', 'index': nr_clicks})]) + id={'type': '04-generate-abstract-defeats-text', + 'index': nr_clicks})]) ]), html.Br(), dbc.Row([ dbc.InputGroup([ dbc.InputGroupText('Filename'), - dbc.Input(value='generated_er_af', id={'type': '04-generate-abstract-filename', 'index': nr_clicks}), + dbc.Input(value='generated_er_af', + id={'type': '04-generate-abstract-filename', + 'index': nr_clicks}), dbc.InputGroupText('.'), dbc.Select(options=[{'label': extension, 'value': extension} - for extension in ['JSON', 'TGF', 'APX', 'ICCMA23']], - value='JSON', id={'type': '04-generate-abstract-extension', 'index': nr_clicks}), - dbc.Button('Download', id={'type': '04-generate-abstract-download-button', 'index': nr_clicks}), + for extension in + ['JSON', 'TGF', 'APX', 'ICCMA23']], + value='JSON', + id={'type': '04-generate-abstract-extension', + 'index': nr_clicks}), + dbc.Button('Download', + id={'type': '04-generate-abstract-download-button', + 'index': nr_clicks}), ]), - dcc.Download(id={'type': '04-generate-abstract-downloader', 'index': nr_clicks}) + dcc.Download(id={'type': '04-generate-abstract-downloader', + 'index': nr_clicks}) ]) ] @@ -141,35 +166,47 @@ def read_defeats(defeat_text: str) -> List[Defeat]: @callback( - Output({'type': '04-generate-abstract-downloader', 'index': MATCH}, 'data'), - Input({'type': '04-generate-abstract-download-button', 'index': MATCH}, 'n_clicks'), - State({'type': '04-generate-abstract-arguments-text', 'index': MATCH}, 'value'), - State({'type': '04-generate-abstract-defeats-text', 'index': MATCH}, 'value'), + Output({'type': '04-generate-abstract-downloader', 'index': MATCH}, + 'data'), + Input({'type': '04-generate-abstract-download-button', 'index': MATCH}, + 'n_clicks'), + State({'type': '04-generate-abstract-arguments-text', 'index': MATCH}, + 'value'), + State({'type': '04-generate-abstract-defeats-text', 'index': MATCH}, + 'value'), State({'type': '04-generate-abstract-filename', 'index': MATCH}, 'value'), State({'type': '04-generate-abstract-extension', 'index': MATCH}, 'value'), prevent_initial_call=True, ) def download_generated_abstract_argumentation_framework( - _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, extension: str): + _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, + extension: str): argumentation_framework = AbstractArgumentationFramework( name='generated', - arguments=[Argument(arg_str.strip()) for arg_str in arguments_text.split('\n')], + arguments=[Argument(arg_str.strip()) for arg_str in + arguments_text.split('\n')], defeats=read_defeats(defeats_text) ) if extension == 'JSON': - argumentation_framework_json = ArgumentationFrameworkToJSONWriter().to_dict(argumentation_framework) + argumentation_framework_json = \ + ArgumentationFrameworkToJSONWriter().to_dict( + argumentation_framework) argumentation_framework_str = json.dumps(argumentation_framework_json) elif extension == 'TGF': argumentation_framework_str = \ - ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str( + argumentation_framework) elif extension == 'APX': argumentation_framework_str = \ - ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str( + argumentation_framework) elif extension == 'ICCMA23': argumentation_framework_str = \ - ArgumentationFrameworkToICCMA23FormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToICCMA23FormatWriter.write_to_str( + argumentation_framework) else: raise NotImplementedError - return {'content': argumentation_framework_str, 'filename': filename + '.' + extension} + return {'content': argumentation_framework_str, + 'filename': filename + '.' + extension} diff --git a/src/py_arg_visualisation/pages/05_generate_watts_strogatz.py b/src/py_arg_visualisation/pages/05_generate_watts_strogatz.py index 3bf6f26..0f46b77 100644 --- a/src/py_arg_visualisation/pages/05_generate_watts_strogatz.py +++ b/src/py_arg_visualisation/pages/05_generate_watts_strogatz.py @@ -2,48 +2,64 @@ from typing import List import dash -from dash import html, callback, Input, Output, State, MATCH, dcc import dash_bootstrap_components as dbc +from dash import html, callback, Input, Output, State, MATCH, dcc -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.generators.watts_strogatz_generator import WattsStrogatz -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_aspartix_format_writer import \ +from py_arg.abstract_argumentation.generators.watts_strogatz_generator \ + import WattsStrogatz +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_aspartix_format_writer import \ ArgumentationFrameworkToASPARTIXFormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_iccma23_format_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_iccma23_format_writer import \ ArgumentationFrameworkToICCMA23FormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_json_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_json_writer import \ ArgumentationFrameworkToJSONWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_trivial_graph_format_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_trivial_graph_format_writer import \ ArgumentationFrameworkToTrivialGraphFormatWriter -dash.register_page(__name__, name='GenerateWattsStrogatz', title='Generate Watts-Strogatz AF') -# self, nr_of_arguments: int, prob_edge_rewiring: float,prob_cycle: float, nr_join_neighbours: int, seed: int = None) +dash.register_page(__name__, name='GenerateWattsStrogatz', + title='Generate Watts-Strogatz AF') + left_column = dbc.Col([ html.H2('Input'), html.Br(), dbc.Row([dbc.Col(html.B('Number of arguments')), - dbc.Col(dbc.Input(type='number', min=0, max=50, step=1, value=8, - id='05-generate-watts-strogatz-nr-arguments-input'))]), + dbc.Col(dbc.Input( + type='number', min=0, max=50, step=1, value=8, + id='05-generate-watts-strogatz-nr-arguments-input'))]), dbc.Row([dbc.Col(html.B('Number of neighbours to join')), - dbc.Col(dbc.Input(type='number', min=0, max=50, step=1, value=8, - id='05-generate-watts-strogatz-nr-join-neighbours-input'))]), + dbc.Col(dbc.Input( + type='number', min=0, max=50, step=1, value=8, + id='05-generate-watts-strogatz-nr-join-neighbours-input'))]), dbc.Row([dbc.Col(html.B('Use Seed')), dbc.Col(dbc.Select( - options=[{'label': answer, 'value': answer} for answer in ['Yes', 'No']], - value='No', id='05-generate-watts-strogatz-use-seed-input'))]), + options=[{'label': answer, 'value': answer} for answer in + ['Yes', 'No']], + value='No', + id='05-generate-watts-strogatz-use-seed-input'))]), dbc.Row([dbc.Col(html.B('Seed')), dbc.Col(dbc.Input(type='number', min=0, max=128, step=1, value=42, id='05-generate-watts-strogatz-seed-input'))]), dbc.Row([dbc.Col(html.B('Probability of defeat rewiring')), - dbc.Col(dcc.Slider( min=0.1, max=1, step=0.1, value=0.5,marks=None, - tooltip={"placement": "bottom", "always_visible": True}, - id='05-generate-watts-strogatz-prob-defeat-rewiring-input'))]), + dbc.Col(dcc.Slider( + min=0.1, max=1, step=0.1, value=0.5, marks=None, + tooltip={"placement": "bottom", + "always_visible": True}, + id='05-generate-watts-strogatz-prob-defeat-rewiring-input')) + ]), dbc.Row([dbc.Col(html.B('Probability of argument in cycle')), - dbc.Col(dcc.Slider( min=0.1, max=1, step=0.1, value=0.5,marks=None, - tooltip={"placement": "bottom", "always_visible": True}, - id='05-generate-watts-strogatz-prob-cycle-input'))]), + dbc.Col(dcc.Slider( + min=0.1, max=1, step=0.1, value=0.5, marks=None, + tooltip={"placement": "bottom", + "always_visible": True}, + id='05-generate-watts-strogatz-prob-cycle-input'))]), html.Br(), dbc.Row([dbc.Button('Generate', id='05-generate-watts-strogatz-button', className='w-50 mx-auto')]) @@ -60,13 +76,16 @@ @callback(Output('05-generate-watts-strogatz-output', 'children'), Input('05-generate-watts-strogatz-button', 'n_clicks'), State('05-generate-watts-strogatz-nr-arguments-input', 'value'), - State('05-generate-watts-strogatz-nr-join-neighbours-input', 'value'), + State('05-generate-watts-strogatz-nr-join-neighbours-input', + 'value'), State('05-generate-watts-strogatz-seed-input', 'value'), State('05-generate-watts-strogatz-use-seed-input', 'value'), - State('05-generate-watts-strogatz-prob-defeat-rewiring-input', 'value'), + State('05-generate-watts-strogatz-prob-defeat-rewiring-input', + 'value'), State('05-generate-watts-strogatz-prob-cycle-input', 'value')) def generate_abstract_argumentation_framework( - nr_clicks: int, nr_arguments: str,nr_join_neighbours: str, seed: str,use_seed: str, prob_rewiring: str, prob_cycle: str): + nr_clicks: int, nr_arguments: str, nr_join_neighbours: str, seed: str, + use_seed: str, prob_rewiring: str, prob_cycle: str): if not nr_clicks: return 'Press the button to generate an argumentation framework.' @@ -76,51 +95,63 @@ def generate_abstract_argumentation_framework( return 'The number of arguments is not an integer.' if nr_arguments_int < 1: return 'The number of arguments should be at least one.' - + try: seed_int = int(seed) except TypeError: return 'The seed value is not an integer.' - prob_rewiring_float = float(prob_rewiring) prob_cycle_float = float(prob_cycle) nr_join_neighbours_int = int(nr_join_neighbours) - - - if use_seed == 'No': seed_int = None - generator = WattsStrogatz(nr_of_arguments=nr_arguments_int,nr_join_neighbours=nr_join_neighbours_int,prob_edge_rewiring=prob_rewiring_float,prob_cycle=prob_cycle_float,seed=seed_int) + generator = WattsStrogatz(nr_of_arguments=nr_arguments_int, + nr_join_neighbours=nr_join_neighbours_int, + prob_edge_rewiring=prob_rewiring_float, + prob_cycle=prob_cycle_float, seed=seed_int) argumentation_framework = generator.generate() output_children = \ [html.H2('Output'), dbc.Row([ dbc.Col([html.B('Arguments'), dbc.Textarea( - value='\n'.join(str(arg) for arg in argumentation_framework.arguments), + value='\n'.join( + str(arg) for arg in argumentation_framework.arguments), style={'height': '300px'}, - id={'type': '05-generate-watts-strogatz-arguments-text', 'index': nr_clicks})]), + id={'type': '05-generate-watts-strogatz-arguments-text', + 'index': nr_clicks})]), dbc.Col([html.B('Defeats'), dbc.Textarea( - value='\n'.join((f'({str(defeat.from_argument)},{str(defeat.to_argument)})' - for defeat in argumentation_framework.defeats)), + value='\n'.join( + (f'({str(defeat.from_argument)},' + f'{str(defeat.to_argument)})' + for defeat in argumentation_framework.defeats)), style={'height': '300px'}, - id={'type': '05-generate-watts-strogatz-defeats-text', 'index': nr_clicks})]) + id={'type': '05-generate-watts-strogatz-defeats-text', + 'index': nr_clicks})]) ]), html.Br(), dbc.Row([ dbc.InputGroup([ dbc.InputGroupText('Filename'), - dbc.Input(value='generated_ws_af', id={'type': '05-generate-watts-strogatz-filename', 'index': nr_clicks}), + dbc.Input(value='generated_ws_af', + id={'type': '05-generate-watts-strogatz-filename', + 'index': nr_clicks}), dbc.InputGroupText('.'), dbc.Select(options=[{'label': extension, 'value': extension} - for extension in ['JSON', 'TGF', 'APX', 'ICCMA23']], - value='JSON', id={'type': '05-generate-watts-strogatz-extension', 'index': nr_clicks}), - dbc.Button('Download', id={'type': '05-generate-watts-strogatz-download-button', 'index': nr_clicks}), + for extension in + ['JSON', 'TGF', 'APX', 'ICCMA23']], + value='JSON', + id={'type': '05-generate-watts-strogatz-extension', + 'index': nr_clicks}), + dbc.Button('Download', id={ + 'type': '05-generate-watts-strogatz-download-button', + 'index': nr_clicks}), ]), - dcc.Download(id={'type': '05-generate-watts-strogatz-downloader', 'index': nr_clicks}) + dcc.Download(id={'type': '05-generate-watts-strogatz-downloader', + 'index': nr_clicks}) ]) ] @@ -141,35 +172,50 @@ def read_defeats(defeat_text: str) -> List[Defeat]: @callback( - Output({'type': '05-generate-watts-strogatz-downloader', 'index': MATCH}, 'data'), - Input({'type': '05-generate-watts-strogatz-download-button', 'index': MATCH}, 'n_clicks'), - State({'type': '05-generate-watts-strogatz-arguments-text', 'index': MATCH}, 'value'), - State({'type': '05-generate-watts-strogatz-defeats-text', 'index': MATCH}, 'value'), - State({'type': '05-generate-watts-strogatz-filename', 'index': MATCH}, 'value'), - State({'type': '05-generate-watts-strogatz-extension', 'index': MATCH}, 'value'), + Output({'type': '05-generate-watts-strogatz-downloader', 'index': MATCH}, + 'data'), + Input( + {'type': '05-generate-watts-strogatz-download-button', 'index': MATCH}, + 'n_clicks'), + State({'type': '05-generate-watts-strogatz-arguments-text', + 'index': MATCH}, 'value'), + State({'type': '05-generate-watts-strogatz-defeats-text', 'index': MATCH}, + 'value'), + State({'type': '05-generate-watts-strogatz-filename', 'index': MATCH}, + 'value'), + State({'type': '05-generate-watts-strogatz-extension', 'index': MATCH}, + 'value'), prevent_initial_call=True, ) def download_generated_abstract_argumentation_framework( - _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, extension: str): + _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, + extension: str): argumentation_framework = AbstractArgumentationFramework( name='generated', - arguments=[Argument(arg_str.strip()) for arg_str in arguments_text.split('\n')], + arguments=[Argument(arg_str.strip()) for arg_str in + arguments_text.split('\n')], defeats=read_defeats(defeats_text) ) if extension == 'JSON': - argumentation_framework_json = ArgumentationFrameworkToJSONWriter().to_dict(argumentation_framework) + argumentation_framework_json = \ + ArgumentationFrameworkToJSONWriter().to_dict( + argumentation_framework) argumentation_framework_str = json.dumps(argumentation_framework_json) elif extension == 'TGF': argumentation_framework_str = \ - ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str( + argumentation_framework) elif extension == 'APX': argumentation_framework_str = \ - ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str( + argumentation_framework) elif extension == 'ICCMA23': argumentation_framework_str = \ - ArgumentationFrameworkToICCMA23FormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToICCMA23FormatWriter.write_to_str( + argumentation_framework) else: raise NotImplementedError - return {'content': argumentation_framework_str, 'filename': filename + '.' + extension} + return {'content': argumentation_framework_str, + 'filename': filename + '.' + extension} diff --git a/src/py_arg_visualisation/pages/06_generate_barabasi_albert.py b/src/py_arg_visualisation/pages/06_generate_barabasi_albert.py index 91f1dea..a4fd470 100644 --- a/src/py_arg_visualisation/pages/06_generate_barabasi_albert.py +++ b/src/py_arg_visualisation/pages/06_generate_barabasi_albert.py @@ -2,44 +2,56 @@ from typing import List import dash -from dash import html, callback, Input, Output, State, MATCH, dcc import dash_bootstrap_components as dbc +from dash import html, callback, Input, Output, State, MATCH, dcc -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework from py_arg.abstract_argumentation.classes.argument import Argument from py_arg.abstract_argumentation.classes.defeat import Defeat -from py_arg.abstract_argumentation.generators.barbasi_albert_generator import BarabasiAlbert -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_aspartix_format_writer import \ +from py_arg.abstract_argumentation.generators.barbasi_albert_generator \ + import BarabasiAlbert +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_aspartix_format_writer import \ ArgumentationFrameworkToASPARTIXFormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_iccma23_format_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_iccma23_format_writer import \ ArgumentationFrameworkToICCMA23FormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_json_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_json_writer import \ ArgumentationFrameworkToJSONWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_trivial_graph_format_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_trivial_graph_format_writer import \ ArgumentationFrameworkToTrivialGraphFormatWriter -dash.register_page(__name__, name='GenerateBarabasiAlbert', title='Generate Barabasi-Albert AF') -# self, nr_of_arguments: int, prob_edge_rewiring: float,prob_cycle: float, nr_join_neighbours: int, seed: int = None) +dash.register_page(__name__, name='GenerateBarabasiAlbert', + title='Generate Barabasi-Albert AF') + left_column = dbc.Col([ html.H2('Input'), html.Br(), dbc.Row([dbc.Col(html.B('Number of arguments')), - dbc.Col(dbc.Input(type='number', min=0, max=50, step=1, value=8, - id='06-generate-barbasi-albert-nr-arguments-input'))]), + dbc.Col(dbc.Input( + type='number', min=0, max=50, step=1, value=8, + id='06-generate-barbasi-albert-nr-arguments-input'))]), dbc.Row([dbc.Col(html.B('Attach new argument to')), - dbc.Col(dbc.Input(type='number', min=0, max=50, step=1, value=8, - id='06-generate-barbasi-albert-nr-join-neighbours-input'))]), + dbc.Col(dbc.Input( + type='number', min=0, max=50, step=1, value=8, + id='06-generate-barbasi-albert-nr-join-neighbours-input'))]), dbc.Row([dbc.Col(html.B('Use Seed')), dbc.Col(dbc.Select( - options=[{'label': answer, 'value': answer} for answer in ['Yes', 'No']], - value='No', id='06-generate-barbasi-albert-use-seed-input'))]), + options=[{'label': answer, 'value': answer} + for answer in ['Yes', 'No']], + value='No', + id='06-generate-barbasi-albert-use-seed-input'))]), dbc.Row([dbc.Col(html.B('Seed')), dbc.Col(dbc.Input(type='number', min=0, max=128, step=1, value=42, id='06-generate-barbasi-albert-seed-input'))]), dbc.Row([dbc.Col(html.B('Probability of argument in cycle')), - dbc.Col(dcc.Slider( min=0.1, max=1, step=0.1, value=0.5,marks=None, - tooltip={"placement": "bottom", "always_visible": True}, - id='06-generate-barbasi-albert-prob-cycle-input'))]), + dbc.Col(dcc.Slider( + min=0.1, max=1, step=0.1, value=0.5, marks=None, + tooltip={"placement": "bottom", "always_visible": True}, + id='06-generate-barbasi-albert-prob-cycle-input'))]), html.Br(), dbc.Row([dbc.Button('Generate', id='06-generate-barbasi-albert-button', className='w-50 mx-auto')]) @@ -48,7 +60,8 @@ layout_generate_abstract = dbc.Row([left_column, right_column]) layout = html.Div([ - html.H1('Generate Random Barabasi-Albert Abstract Argumentation Framework'), + html.H1('Generate Random Barabasi-Albert ' + 'Abstract Argumentation Framework'), html.Div(layout_generate_abstract) ]) @@ -56,12 +69,14 @@ @callback(Output('06-generate-barbasi-albert-output', 'children'), Input('06-generate-barbasi-albert-button', 'n_clicks'), State('06-generate-barbasi-albert-nr-arguments-input', 'value'), - State('06-generate-barbasi-albert-nr-join-neighbours-input', 'value'), + State('06-generate-barbasi-albert-nr-join-neighbours-input', + 'value'), State('06-generate-barbasi-albert-seed-input', 'value'), State('06-generate-barbasi-albert-use-seed-input', 'value'), State('06-generate-barbasi-albert-prob-cycle-input', 'value')) def generate_abstract_argumentation_framework( - nr_clicks: int, nr_arguments: str,nr_join_neighbours: str, seed: str,use_seed: str, prob_cycle: str): + nr_clicks: int, nr_arguments: str, nr_join_neighbours: str, seed: str, + use_seed: str, prob_cycle: str): if not nr_clicks: return 'Press the button to generate an argumentation framework.' @@ -71,50 +86,61 @@ def generate_abstract_argumentation_framework( return 'The number of arguments is not an integer.' if nr_arguments_int < 1: return 'The number of arguments should be at least one.' - + try: seed_int = int(seed) except TypeError: return 'The seed value is not an integer.' - prob_cycle_float = float(prob_cycle) nr_join_neighbours_int = int(nr_join_neighbours) - - - if use_seed == 'No': seed_int = None - generator = BarabasiAlbert(nr_of_arguments=nr_arguments_int,nr_attach_node_to=nr_join_neighbours_int,prob_cycle=prob_cycle_float,seed=seed_int) + generator = BarabasiAlbert(nr_of_arguments=nr_arguments_int, + nr_attach_node_to=nr_join_neighbours_int, + prob_cycle=prob_cycle_float, seed=seed_int) argumentation_framework = generator.generate() output_children = \ [html.H2('Output'), dbc.Row([ dbc.Col([html.B('Arguments'), dbc.Textarea( - value='\n'.join(str(arg) for arg in argumentation_framework.arguments), + value='\n'.join( + str(arg) for arg in argumentation_framework.arguments), style={'height': '300px'}, - id={'type': '06-generate-barbasi-albert-arguments-text', 'index': nr_clicks})]), + id={'type': '06-generate-barbasi-albert-arguments-text', + 'index': nr_clicks})]), dbc.Col([html.B('Defeats'), dbc.Textarea( - value='\n'.join((f'({str(defeat.from_argument)},{str(defeat.to_argument)})' - for defeat in argumentation_framework.defeats)), + value='\n'.join( + (f'({str(defeat.from_argument)},' + f'{str(defeat.to_argument)})' + for defeat in argumentation_framework.defeats)), style={'height': '300px'}, - id={'type': '06-generate-barbasi-albert-defeats-text', 'index': nr_clicks})]) + id={'type': '06-generate-barbasi-albert-defeats-text', + 'index': nr_clicks})]) ]), html.Br(), dbc.Row([ dbc.InputGroup([ dbc.InputGroupText('Filename'), - dbc.Input(value='generated_ba_af', id={'type': '06-generate-barbasi-albert-filename', 'index': nr_clicks}), + dbc.Input(value='generated_ba_af', + id={'type': '06-generate-barbasi-albert-filename', + 'index': nr_clicks}), dbc.InputGroupText('.'), dbc.Select(options=[{'label': extension, 'value': extension} - for extension in ['JSON', 'TGF', 'APX', 'ICCMA23']], - value='JSON', id={'type': '06-generate-barbasi-albert-extension', 'index': nr_clicks}), - dbc.Button('Download', id={'type': '06-generate-barbasi-albert-download-button', 'index': nr_clicks}), + for extension in + ['JSON', 'TGF', 'APX', 'ICCMA23']], + value='JSON', + id={'type': '06-generate-barbasi-albert-extension', + 'index': nr_clicks}), + dbc.Button('Download', id={ + 'type': '06-generate-barbasi-albert-download-button', + 'index': nr_clicks}), ]), - dcc.Download(id={'type': '06-generate-barbasi-albert-downloader', 'index': nr_clicks}) + dcc.Download(id={'type': '06-generate-barbasi-albert-downloader', + 'index': nr_clicks}) ]) ] @@ -135,35 +161,51 @@ def read_defeats(defeat_text: str) -> List[Defeat]: @callback( - Output({'type': '06-generate-barbasi-albert-downloader', 'index': MATCH}, 'data'), - Input({'type': '06-generate-barbasi-albert-download-button', 'index': MATCH}, 'n_clicks'), - State({'type': '06-generate-barbasi-albert-arguments-text', 'index': MATCH}, 'value'), - State({'type': '06-generate-barbasi-albert-defeats-text', 'index': MATCH}, 'value'), - State({'type': '06-generate-barbasi-albert-filename', 'index': MATCH}, 'value'), - State({'type': '06-generate-barbasi-albert-extension', 'index': MATCH}, 'value'), + Output({'type': '06-generate-barbasi-albert-downloader', 'index': MATCH}, + 'data'), + Input( + {'type': '06-generate-barbasi-albert-download-button', 'index': MATCH}, + 'n_clicks'), + State({'type': '06-generate-barbasi-albert-arguments-text', + 'index': MATCH}, + 'value'), + State({'type': '06-generate-barbasi-albert-defeats-text', 'index': MATCH}, + 'value'), + State({'type': '06-generate-barbasi-albert-filename', 'index': MATCH}, + 'value'), + State({'type': '06-generate-barbasi-albert-extension', 'index': MATCH}, + 'value'), prevent_initial_call=True, ) def download_generated_abstract_argumentation_framework( - _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, extension: str): + _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, + extension: str): argumentation_framework = AbstractArgumentationFramework( name='generated', - arguments=[Argument(arg_str.strip()) for arg_str in arguments_text.split('\n')], + arguments=[Argument(arg_str.strip()) for arg_str in + arguments_text.split('\n')], defeats=read_defeats(defeats_text) ) if extension == 'JSON': - argumentation_framework_json = ArgumentationFrameworkToJSONWriter().to_dict(argumentation_framework) + argumentation_framework_json = \ + ArgumentationFrameworkToJSONWriter().to_dict( + argumentation_framework) argumentation_framework_str = json.dumps(argumentation_framework_json) elif extension == 'TGF': argumentation_framework_str = \ - ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str( + argumentation_framework) elif extension == 'APX': argumentation_framework_str = \ - ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str( + argumentation_framework) elif extension == 'ICCMA23': argumentation_framework_str = \ - ArgumentationFrameworkToICCMA23FormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToICCMA23FormatWriter.write_to_str( + argumentation_framework) else: raise NotImplementedError - return {'content': argumentation_framework_str, 'filename': filename + '.' + extension} + return {'content': argumentation_framework_str, + 'filename': filename + '.' + extension} diff --git a/src/py_arg_visualisation/pages/21_visualise_abstract.py b/src/py_arg_visualisation/pages/21_visualise_abstract.py index d6d1573..7c4eafa 100644 --- a/src/py_arg_visualisation/pages/21_visualise_abstract.py +++ b/src/py_arg_visualisation/pages/21_visualise_abstract.py @@ -8,33 +8,49 @@ from dash.exceptions import PreventUpdate import dash_bootstrap_components as dbc -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import \ +from py_arg.abstract_argumentation.classes.abstract_argumentation_framework \ + import AbstractArgumentationFramework +from py_arg.abstract_argumentation.generators.\ + abstract_argumentation_framework_generator import \ AbstractArgumentationFrameworkGenerator -from py_arg.abstract_argumentation.import_export.argumentation_framework_from_aspartix_format_reader import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_from_aspartix_format_reader import \ ArgumentationFrameworkFromASPARTIXFormatReader -from py_arg.abstract_argumentation.import_export.argumentation_framework_from_iccma23_format_reader import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_from_iccma23_format_reader import \ ArgumentationFrameworkFromICCMA23FormatReader -from py_arg.abstract_argumentation.import_export.argumentation_framework_from_json_reader import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_from_json_reader import \ ArgumentationFrameworkFromJsonReader -from py_arg.abstract_argumentation.import_export.argumentation_framework_from_trivial_graph_format_reader import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_from_trivial_graph_format_reader import \ ArgumentationFrameworkFromTrivialGraphFormatReader -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_aspartix_format_writer import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_to_aspartix_format_writer import \ ArgumentationFrameworkToASPARTIXFormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_iccma23_format_writer import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_to_iccma23_format_writer import \ ArgumentationFrameworkToICCMA23FormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_json_writer import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_to_json_writer import \ ArgumentationFrameworkToJSONWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_trivial_graph_format_writer import \ +from py_arg.abstract_argumentation.import_export.\ + argumentation_framework_to_trivial_graph_format_writer import \ ArgumentationFrameworkToTrivialGraphFormatWriter -from py_arg_visualisation.functions.explanations_functions.explanation_function_options import \ +from py_arg_visualisation.functions.explanations_functions.\ + explanation_function_options import \ EXPLANATION_FUNCTION_OPTIONS -from py_arg_visualisation.functions.explanations_functions.get_af_explanations import \ +from py_arg_visualisation.functions.explanations_functions.\ + get_af_explanations import \ get_argumentation_framework_explanations -from py_arg_visualisation.functions.extensions_functions.get_accepted_arguments import get_accepted_arguments -from py_arg_visualisation.functions.extensions_functions.get_af_extensions import get_argumentation_framework_extensions -from py_arg_visualisation.functions.graph_data_functions.get_af_graph_data import get_argumentation_framework_graph_data -from py_arg_visualisation.functions.import_functions.read_argumentation_framework_functions import \ +from py_arg_visualisation.functions.extensions_functions.\ + get_accepted_arguments import get_accepted_arguments +from py_arg_visualisation.functions.extensions_functions.\ + get_af_extensions import get_argumentation_framework_extensions +from py_arg_visualisation.functions.graph_data_functions.\ + get_af_graph_data import get_argumentation_framework_graph_data +from py_arg_visualisation.functions.import_functions.\ + read_argumentation_framework_functions import \ read_argumentation_framework dash.register_page(__name__, name='Visualise AF', title='Visualise AF') @@ -46,22 +62,30 @@ def get_abstract_setting_specification_div(): return html.Div(children=[ dcc.Store(id='selected-argument-store-abstract'), dbc.Col([ - dbc.Row([dbc.Col(dbc.Button('Generate random', id='generate-random-af-button', n_clicks=0, - className='w-100')), - dbc.Col(dcc.Upload(dbc.Button('Open existing AF', className='w-100'), id='upload-af')) + dbc.Row([dbc.Col(dbc.Button( + 'Generate random', + id='generate-random-af-button', n_clicks=0, + className='w-100')), + dbc.Col(dcc.Upload(dbc.Button( + 'Open existing AF', className='w-100'), + id='upload-af')) ], className='mt-2'), dbc.Row([ dbc.Col([ html.B('Arguments'), - dbc.Textarea(id='abstract-arguments', - placeholder='Add one argument per line. For example:\n A\n B\n C', - value='', style={'height': '300px'}) + dbc.Textarea( + id='abstract-arguments', + placeholder='Add one argument per line. ' + 'For example:\n A\n B\n C', + value='', style={'height': '300px'}) ]), dbc.Col([ html.B('Attacks'), - dbc.Textarea(id='abstract-attacks', - placeholder='Add one attack per line. For example: \n (A,B) \n (A,C) \n (C,B)', - value='', style={'height': '300px'}), + dbc.Textarea( + id='abstract-attacks', + placeholder='Add one attack per line. ' + 'For example: \n (A,B) \n (A,C) \n (C,B)', + value='', style={'height': '300px'}), ]) ], className='mt-2'), dbc.Row([ @@ -69,9 +93,11 @@ def get_abstract_setting_specification_div(): dbc.InputGroupText('Filename'), dbc.Input(value='edited_af', id='21-af-filename'), dbc.InputGroupText('.'), - dbc.Select(options=[{'label': extension, 'value': extension} - for extension in ['JSON', 'TGF', 'APX', 'ICCMA23']], - value='JSON', id='21-af-extension'), + dbc.Select( + options=[{'label': extension, 'value': extension} + for extension in ['JSON', 'TGF', 'APX', + 'ICCMA23']], + value='JSON', id='21-af-extension'), dbc.Button('Download', id='21-af-download-button'), ], className='mt-2'), dcc.Download(id='21-af-download') @@ -114,9 +140,11 @@ def get_abstract_explanation_div(): return html.Div([ dbc.Row([ dbc.Col(html.B('Type')), - dbc.Col(dbc.Select(options=[{'label': 'Acceptance', 'value': 'Acceptance'}, - {'label': 'Non-Acceptance', 'value': 'NonAcceptance'}], - value='Acceptance', id='abstract-explanation-type'))]), + dbc.Col(dbc.Select( + options=[{'label': 'Acceptance', 'value': 'Acceptance'}, + {'label': 'Non-Acceptance', + 'value': 'NonAcceptance'}], + value='Acceptance', id='abstract-explanation-type'))]), dbc.Row([ dbc.Col(html.B('Explanation function')), dbc.Col(dbc.Select(id='abstract-explanation-function')) @@ -127,19 +155,24 @@ def get_abstract_explanation_div(): left_column = dbc.Col( dbc.Accordion([ - dbc.AccordionItem(get_abstract_setting_specification_div(), title='Abstract Argumentation Framework'), - dbc.AccordionItem(get_abstract_evaluation_div(), title='Evaluation', item_id='Evaluation'), - dbc.AccordionItem(get_abstract_explanation_div(), title='Explanation', item_id='Explanation') + dbc.AccordionItem(get_abstract_setting_specification_div(), + title='Abstract Argumentation Framework'), + dbc.AccordionItem(get_abstract_evaluation_div(), + title='Evaluation', item_id='Evaluation'), + dbc.AccordionItem(get_abstract_explanation_div(), + title='Explanation', item_id='Explanation') ], id='abstract-evaluation-accordion') ) right_column = dbc.Col([ dbc.Row([ - dbc.Card(visdcc.Network(data={'nodes': [], 'edges': []}, id='abstract-argumentation-graph', + dbc.Card(visdcc.Network(data={'nodes': [], 'edges': []}, + id='abstract-argumentation-graph', options={'height': '500px'}), body=True), ]) ]) layout_abstract = dbc.Row([left_column, right_column]) -layout = html.Div([html.H1('Visualisation of abstract argumentation frameworks'), layout_abstract]) +layout = html.Div([html.H1( + 'Visualisation of abstract argumentation frameworks'), layout_abstract]) @callback( @@ -149,14 +182,19 @@ def get_abstract_explanation_div(): Input('upload-af', 'contents'), State('upload-af', 'filename') ) -def generate_abstract_argumentation_framework(_nr_of_clicks_random: int, af_content: str, af_filename: str): +def generate_abstract_argumentation_framework( + _nr_of_clicks_random: int, af_content: str, af_filename: str): """ - Generate a random AF after clicking the button and put the result in the text box. + Generate a random AF after clicking the button and put the result in the + text box. """ if dash.callback_context.triggered_id == 'generate-random-af-button': - random_af = AbstractArgumentationFrameworkGenerator(8, 8, True).generate() - abstract_arguments_value = '\n'.join((str(arg) for arg in random_af.arguments)) - abstract_attacks_value = '\n'.join((f'({str(defeat.from_argument)},{str(defeat.to_argument)})' + random_af = \ + AbstractArgumentationFrameworkGenerator(8, 8, True).generate() + abstract_arguments_value = '\n'.join((str(arg) + for arg in random_af.arguments)) + abstract_attacks_value = '\n'.join((f'({str(defeat.from_argument)},' + f'{str(defeat.to_argument)})' for defeat in random_af.defeats)) return abstract_arguments_value, abstract_attacks_value elif dash.callback_context.triggered_id == 'upload-af': @@ -165,18 +203,25 @@ def generate_abstract_argumentation_framework(_nr_of_clicks_random: int, af_cont name = af_filename.split('.')[0] if af_filename.upper().endswith('.JSON'): - opened_af = ArgumentationFrameworkFromJsonReader().from_json(json.loads(decoded)) + opened_af = ArgumentationFrameworkFromJsonReader().from_json( + json.loads(decoded)) elif af_filename.upper().endswith('.TGF'): - opened_af = ArgumentationFrameworkFromTrivialGraphFormatReader.from_tgf(decoded.decode(), name) + opened_af = ArgumentationFrameworkFromTrivialGraphFormatReader.\ + from_tgf(decoded.decode(), name) elif af_filename.upper().endswith('.APX'): - opened_af = ArgumentationFrameworkFromASPARTIXFormatReader.from_apx(decoded.decode(), name) + opened_af = ArgumentationFrameworkFromASPARTIXFormatReader.\ + from_apx(decoded.decode(), name) elif af_filename.upper().endswith('.ICCMA23'): - opened_af = ArgumentationFrameworkFromICCMA23FormatReader.from_iccma23(decoded.decode(), name) + opened_af = ArgumentationFrameworkFromICCMA23FormatReader.\ + from_iccma23(decoded.decode(), name) else: - raise NotImplementedError('This file format is currently not supported.') + raise NotImplementedError('This file format is currently not ' + 'supported.') - abstract_arguments_value = '\n'.join((str(arg) for arg in opened_af.arguments)) - abstract_attacks_value = '\n'.join((f'({str(defeat.from_argument)},{str(defeat.to_argument)})' + abstract_arguments_value = '\n'.join((str(arg) + for arg in opened_af.arguments)) + abstract_attacks_value = '\n'.join((f'({str(defeat.from_argument)},' + f'{str(defeat.to_argument)})' for defeat in opened_af.defeats)) return abstract_arguments_value, abstract_attacks_value return '', '' @@ -190,9 +235,9 @@ def generate_abstract_argumentation_framework(_nr_of_clicks_random: int, af_cont State('color-blind-mode', 'on'), prevent_initial_call=True ) -def create_abstract_argumentation_framework(arguments: str, attacks: str, - selected_arguments: Dict[str, List[str]], - color_blind_mode: bool): +def create_abstract_argumentation_framework( + arguments: str, attacks: str, selected_arguments: Dict[str, List[str]], + color_blind_mode: bool): """ Send the AF data to the graph for plotting. """ @@ -201,10 +246,12 @@ def create_abstract_argumentation_framework(arguments: str, attacks: str, except ValueError: arg_framework = AbstractArgumentationFramework() - if dash.callback_context.triggered_id != 'selected-argument-store-abstract': + if dash.callback_context.triggered_id != \ + 'selected-argument-store-abstract': selected_arguments = None - data = get_argumentation_framework_graph_data(arg_framework, selected_arguments, color_blind_mode) + data = get_argumentation_framework_graph_data( + arg_framework, selected_arguments, color_blind_mode) return data @@ -218,25 +265,33 @@ def create_abstract_argumentation_framework(arguments: str, attacks: str, prevent_initial_call=True, ) def download_generated_abstract_argumentation_framework( - _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, extension: str): - argumentation_framework = read_argumentation_framework(arguments_text, defeats_text) + _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, + extension: str): + argumentation_framework = read_argumentation_framework(arguments_text, + defeats_text) if extension == 'JSON': - argumentation_framework_json = ArgumentationFrameworkToJSONWriter().to_dict(argumentation_framework) + argumentation_framework_json = \ + ArgumentationFrameworkToJSONWriter().to_dict( + argumentation_framework) argumentation_framework_str = json.dumps(argumentation_framework_json) elif extension == 'TGF': argumentation_framework_str = \ - ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str( + argumentation_framework) elif extension == 'APX': argumentation_framework_str = \ - ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str( + argumentation_framework) elif extension == 'ICCMA23': argumentation_framework_str = \ - ArgumentationFrameworkToICCMA23FormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToICCMA23FormatWriter.write_to_str( + argumentation_framework) else: raise NotImplementedError - return {'content': argumentation_framework_str, 'filename': filename + '.' + extension} + return {'content': argumentation_framework_str, + 'filename': filename + '.' + extension} @callback( @@ -258,36 +313,53 @@ def evaluate_abstract_argumentation_framework(arguments: str, attacks: str, arg_framework = read_argumentation_framework(arguments, attacks) # Compute the extensions and put them in a list of sets. - frozen_extensions = get_argumentation_framework_extensions(arg_framework, semantics) - extensions = [set(frozen_extension) for frozen_extension in frozen_extensions] + frozen_extensions = get_argumentation_framework_extensions(arg_framework, + semantics) + extensions = [set(frozen_extension) + for frozen_extension in frozen_extensions] # Make a button for each extension. extension_buttons = [] for extension in sorted(extensions): out_arguments = {attacked for attacked in arg_framework.arguments - if any(argument in arg_framework.get_incoming_defeat_arguments(attacked) + if any(argument in arg_framework. + get_incoming_defeat_arguments(attacked) for argument in extension)} undecided_arguments = {argument for argument in arg_framework.arguments - if argument not in extension and argument not in out_arguments} - extension_readable_str = '{' + ', '.join(argument.name for argument in sorted(extension)) + '}' - extension_in_str = '+'.join(argument.name for argument in sorted(extension)) - extension_out_str = '+'.join(argument.name for argument in sorted(out_arguments)) - extension_undecided_str = '+'.join(argument.name for argument in sorted(undecided_arguments)) - extension_long_str = '|'.join([extension_in_str, extension_undecided_str, extension_out_str]) - extension_buttons.append(dbc.Button([extension_readable_str], color='secondary', - id={'type': 'extension-button-abstract', 'index': extension_long_str})) + if argument not in extension and + argument not in out_arguments} + extension_readable_str = \ + '{' + ', '.join(argument.name + for argument in sorted(extension)) + '}' + extension_in_str = \ + '+'.join(argument.name for argument in sorted(extension)) + extension_out_str = \ + '+'.join(argument.name for argument in sorted(out_arguments)) + extension_undecided_str = \ + '+'.join(argument.name for argument in sorted(undecided_arguments)) + extension_long_str = \ + '|'.join([extension_in_str, extension_undecided_str, + extension_out_str]) + extension_buttons.append( + dbc.Button([extension_readable_str], color='secondary', + id={'type': 'extension-button-abstract', + 'index': extension_long_str})) # Based on the extensions, get the acceptance status of arguments. accepted_arguments = get_accepted_arguments(extensions, strategy) # Make a button for each accepted argument. - accepted_argument_buttons = [dbc.Button(argument.name, color='secondary', id={'type': 'argument-button-abstract', - 'index': argument.name}) - for argument in sorted(accepted_arguments)] + accepted_argument_buttons = [ + dbc.Button(argument.name, color='secondary', + id={'type': 'argument-button-abstract', + 'index': argument.name}) + for argument in sorted(accepted_arguments)] return html.Div([html.B('The extension(s):'), html.Div(extension_buttons), - html.B('The accepted argument(s):'), html.Div(accepted_argument_buttons), - html.P('Click on the extension/argument buttons to display the corresponding argument(s) ' + html.B('The accepted argument(s):'), + html.Div(accepted_argument_buttons), + html.P('Click on the extension/argument buttons to ' + 'display the corresponding argument(s) ' 'in the graph.')]) @@ -297,17 +369,22 @@ def evaluate_abstract_argumentation_framework(arguments: str, attacks: str, Input({'type': 'argument-button-abstract', 'index': ALL}, 'n_clicks'), State('selected-argument-store-abstract', 'data'), ) -def mark_extension_or_argument_in_graph(_nr_of_clicks_extension_values, _nr_of_clicks_argument_values, +def mark_extension_or_argument_in_graph(_nr_of_clicks_extension_values, + _nr_of_clicks_argument_values, old_selected_data: List[str]): - button_clicked_id = dash.callback_context.triggered[0]['prop_id'].split('.')[0] + button_clicked_id = \ + dash.callback_context.triggered[0]['prop_id'].split('.')[0] if button_clicked_id == '': return old_selected_data button_clicked_id_content = json.loads(button_clicked_id) button_clicked_id_type = button_clicked_id_content['type'] button_clicked_id_index = button_clicked_id_content['index'] if button_clicked_id_type == 'extension-button-abstract': - in_part, undecided_part, out_part = button_clicked_id_index.split('|', 3) - return {'green': in_part.split('+'), 'yellow': undecided_part.split('+'), 'red': out_part.split('+')} + in_part, undecided_part, out_part = \ + button_clicked_id_index.split('|', 3) + return {'green': in_part.split('+'), + 'yellow': undecided_part.split('+'), + 'red': out_part.split('+')} elif button_clicked_id_type == 'argument-button-abstract': return {'blue': [button_clicked_id_index]} return [] @@ -319,7 +396,8 @@ def mark_extension_or_argument_in_graph(_nr_of_clicks_extension_values, _nr_of_c [Input('abstract-explanation-type', 'value')] ) def setting_choice(choice: str): - return EXPLANATION_FUNCTION_OPTIONS[choice], EXPLANATION_FUNCTION_OPTIONS[choice][0]['value'] + return EXPLANATION_FUNCTION_OPTIONS[choice], \ + EXPLANATION_FUNCTION_OPTIONS[choice][0]['value'] @callback( @@ -333,25 +411,31 @@ def setting_choice(choice: str): State('abstract-evaluation-strategy', 'value'), prevent_initial_call=True ) -def derive_explanations_abstract_argumentation_framework(active_item, - arguments: str, attacks: str, - semantics: str, explanation_function: str, - explanation_type: str, explanation_strategy: str): +def derive_explanations_abstract_argumentation_framework( + active_item, arguments: str, attacks: str, semantics: str, + explanation_function: str, explanation_type: str, + explanation_strategy: str): if active_item != 'Explanation': raise PreventUpdate # Compute the explanations based on the input. arg_framework = read_argumentation_framework(arguments, attacks) - frozen_extensions = get_argumentation_framework_extensions(arg_framework, semantics) - extensions = [set(frozen_extension) for frozen_extension in frozen_extensions] - accepted_arguments = get_accepted_arguments(extensions, explanation_strategy) - explanations = get_argumentation_framework_explanations(arg_framework, extensions, accepted_arguments, - explanation_function, explanation_type) + frozen_extensions = get_argumentation_framework_extensions(arg_framework, + semantics) + extensions = [set(frozen_extension) + for frozen_extension in frozen_extensions] + accepted_arguments = get_accepted_arguments( + extensions, explanation_strategy) + explanations = get_argumentation_framework_explanations( + arg_framework, extensions, accepted_arguments, + explanation_function, explanation_type) # Print the explanations for each of the arguments. return html.Div([html.Div(html.B('Explanation(s) by argument:'))] + [html.Div([ html.B(explanation_key), - html.Ul([html.Li(str(explanation_value).replace('set()', '{}')) - for explanation_value in explanation_values])]) - for explanation_key, explanation_values in explanations.items()]) + html.Ul([html.Li(str(explanation_value).replace( + 'set()', '{}')) + for explanation_value in explanation_values])]) + for explanation_key, explanation_values in + explanations.items()]) diff --git a/src/py_arg_visualisation/pages/22_visualise_aspic.py b/src/py_arg_visualisation/pages/22_visualise_aspic.py index 1a1999c..ccbe924 100644 --- a/src/py_arg_visualisation/pages/22_visualise_aspic.py +++ b/src/py_arg_visualisation/pages/22_visualise_aspic.py @@ -10,35 +10,50 @@ from py_arg.aspic.classes.argumentation_system import ArgumentationSystem from py_arg.aspic.classes.argumentation_theory import ArgumentationTheory from py_arg.aspic.classes.instantiated_argument import InstantiatedArgument -from py_arg.aspic.generators.argumentation_system_generators.layered_argumentation_system_generator import \ +from py_arg.aspic.generators.argumentation_system_generators. \ + layered_argumentation_system_generator import \ LayeredArgumentationSystemGenerator -from py_arg.aspic.generators.argumentation_theory_generators.argumentation_theory_generator import \ +from py_arg.aspic.generators.argumentation_theory_generators. \ + argumentation_theory_generator import \ ArgumentationTheoryGenerator -from py_arg_visualisation.functions.explanations_functions.explanation_function_options import \ +from py_arg_visualisation.functions.explanations_functions. \ + explanation_function_options import \ EXPLANATION_FUNCTION_OPTIONS -from py_arg_visualisation.functions.explanations_functions.get_at_explanations import get_str_explanations -from py_arg_visualisation.functions.extensions_functions.get_accepted_formulas import get_accepted_formulas -from py_arg_visualisation.functions.extensions_functions.get_af_extensions import get_argumentation_framework_extensions -from py_arg_visualisation.functions.graph_data_functions.get_at_graph_data import get_argumentation_theory_graph_data -from py_arg_visualisation.functions.import_functions.read_argumentation_theory_functions import \ +from py_arg_visualisation.functions.explanations_functions. \ + get_at_explanations import get_str_explanations +from py_arg_visualisation.functions.extensions_functions. \ + get_accepted_formulas import get_accepted_formulas +from py_arg_visualisation.functions.extensions_functions. \ + get_af_extensions import get_argumentation_framework_extensions +from py_arg_visualisation.functions.graph_data_functions. \ + get_at_graph_data import get_argumentation_theory_graph_data +from py_arg_visualisation.functions.import_functions. \ + read_argumentation_theory_functions import \ read_argumentation_theory -from py_arg_visualisation.functions.ordering_functions.get_ordering_by_specification import \ +from py_arg_visualisation.functions.ordering_functions. \ + get_ordering_by_specification import \ get_ordering_by_specification -dash.register_page(__name__, name='Visualise ASPIC+ AT', title='Visualise ASPIC+ AT') +dash.register_page(__name__, name='Visualise ASPIC+ AT', + title='Visualise ASPIC+ AT') -def get_aspic_layout(aspic_setting, structured_evaluation, structured_explanation): +def get_aspic_layout(aspic_setting, structured_evaluation, + structured_explanation): left_column = dbc.Col( dbc.Accordion([ - dbc.AccordionItem(aspic_setting, title='ASPIC+ Argumentation Theory'), - dbc.AccordionItem(structured_evaluation, title='Evaluation', item_id='Evaluation'), - dbc.AccordionItem(structured_explanation, title='Explanation', item_id='Explanation') + dbc.AccordionItem(aspic_setting, + title='ASPIC+ Argumentation Theory'), + dbc.AccordionItem(structured_evaluation, + title='Evaluation', item_id='Evaluation'), + dbc.AccordionItem(structured_explanation, + title='Explanation', item_id='Explanation') ], id='structured-evaluation-accordion') ) right_column = dbc.Col([ dbc.Row([ - dbc.Card(visdcc.Network(data={'nodes': [], 'edges': []}, id='structured-argumentation-graph', + dbc.Card(visdcc.Network(data={'nodes': [], 'edges': []}, + id='structured-argumentation-graph', options={'height': '500px'}), body=True), ]) ]) @@ -49,23 +64,31 @@ def get_aspic_setting_specification_div(): return html.Div(children=[ dcc.Store(id='selected-argument-store-structured'), dbc.Col([ - dbc.Row(dbc.Button('Generate random', id='generate-random-arg-theory-button', n_clicks=0)), + dbc.Row(dbc.Button('Generate random', + id='generate-random-arg-theory-button', + n_clicks=0)), dbc.Row([ dbc.Col([html.B('Axioms')]), dbc.Col([html.B('Ordinary premises')]), dbc.Col([html.B('Ordinary premise preferences')]), ]), dbc.Row([ - dbc.Col([dbc.Textarea(id='aspic-axioms', - placeholder='Add one axiom per line. For example:\n p \n -q \n ~r', - value='', style={'height': '200px'})]), - dbc.Col([dbc.Textarea(id='aspic-ordinary-premises', - placeholder='Add one ordinary premise per line. For example:\n p \n -q \n ~r', - value='', style={'height': '200px'}), ]), - dbc.Col([dbc.Textarea(id='ordinary-prem-preferences', - placeholder='Add one preference between two premises per line. ' - 'For example:\n p < -q \n -q > ~r', - value='', style={'height': '200px'}), ]), + dbc.Col([dbc.Textarea( + id='aspic-axioms', + placeholder='Add one axiom per line. ' + 'For example:\n p \n -q \n ~r', + value='', style={'height': '200px'})]), + dbc.Col([dbc.Textarea( + id='aspic-ordinary-premises', + placeholder='Add one ordinary premise per line. ' + 'For example:\n p \n -q \n ~r', + value='', style={'height': '200px'}), ]), + dbc.Col([dbc.Textarea( + id='ordinary-prem-preferences', + placeholder='Add one preference between two premises per ' + 'line. ' + 'For example:\n p < -q \n -q > ~r', + value='', style={'height': '200px'}), ]), ]), dbc.Row([ dbc.Col([html.B('Strict rules')]), @@ -73,17 +96,23 @@ def get_aspic_setting_specification_div(): dbc.Col([html.B('Defeasible rule preferences')]), ]), dbc.Row([ - dbc.Col([dbc.Textarea(id='aspic-strict-rules', - placeholder='Add one strict rule per line. For example:\n p->q \n -q -> -r', - value='', style={'height': '200px'})]), - dbc.Col([dbc.Textarea(id='aspic-defeasible-rules', - placeholder='Add one defeasible rule per line, including the rule name. ' - 'For example:\n d1: p=>q \n d2: -q => -r', - value='', style={'height': '200px'}), ]), - dbc.Col([dbc.Textarea(id='defeasible-rule-preferences', - placeholder='Add one preference between two rules per line. ' - 'For example:\n d1 < d2', - value='', style={'height': '200px'}), ]), + dbc.Col([dbc.Textarea( + id='aspic-strict-rules', + placeholder='Add one strict rule per line. ' + 'For example:\n p->q \n -q -> -r', + value='', style={'height': '200px'})]), + dbc.Col([dbc.Textarea( + id='aspic-defeasible-rules', + placeholder='Add one defeasible rule per line, ' + 'including the rule name. ' + 'For example:\n d1: p=>q \n d2: -q => -r', + value='', style={'height': '200px'}), ]), + dbc.Col([dbc.Textarea( + id='defeasible-rule-preferences', + placeholder='Add one preference between two rules per ' + 'line. ' + 'For example:\n d1 < d2', + value='', style={'height': '200px'}), ]), ]), dbc.Row([html.B('Ordering')]), dbc.Row([ @@ -126,7 +155,8 @@ def get_structured_evaluation_specification_div(): dbc.Col(dbc.Select( options=[ {'label': 'Credulous', 'value': 'Credulous'}, - {'label': 'Weakly Skeptical', 'value': 'WeaklySkeptical'}, + {'label': 'Weakly Skeptical', + 'value': 'WeaklySkeptical'}, {'label': 'Skeptical', 'value': 'Skeptical'} ], value='Credulous', id='structured-evaluation-strategy')), @@ -140,9 +170,12 @@ def get_structured_explanation_specification_div(): return html.Div([ dbc.Row([ dbc.Col(html.B('Type')), - dbc.Col(dbc.Select(options=[{'label': 'Acceptance', 'value': 'Acceptance'}, - {'label': 'Non-Acceptance', 'value': 'NonAcceptance'}], - value='Acceptance', id='structured-explanation-type'))]), + dbc.Col(dbc.Select(options=[{'label': 'Acceptance', + 'value': 'Acceptance'}, + {'label': 'Non-Acceptance', + 'value': 'NonAcceptance'}], + value='Acceptance', + id='structured-explanation-type'))]), dbc.Row([ dbc.Col(html.B('Explanation function')), dbc.Col(dbc.Select(id='structured-explanation-function')) @@ -152,7 +185,8 @@ def get_structured_explanation_specification_div(): dbc.Col(dbc.Select(options=[{'label': 'Argument', 'value': 'Arg'}, {'label': 'Premises', 'value': 'Prem'}, {'label': 'Rules', 'value': 'Rule'}, - {'label': 'Sub-arguments', 'value': 'SubArg'}], + {'label': 'Sub-arguments', + 'value': 'SubArg'}], value='Arg', id='structured-explanation-form')) ]), dbc.Row(id='structured-explanation') @@ -162,7 +196,8 @@ def get_structured_explanation_specification_div(): layout = html.Div( children=[ html.H1('Visualisation of ASPIC+ argumentation theories'), - get_aspic_layout(get_aspic_setting_specification_div(), get_structured_evaluation_specification_div(), + get_aspic_layout(get_aspic_setting_specification_div(), + get_structured_evaluation_specification_div(), get_structured_explanation_specification_div()) ] ) @@ -174,7 +209,8 @@ def get_structured_explanation_specification_div(): [Input('structured-explanation-type', 'value')] ) def setting_choice(choice: str): - return EXPLANATION_FUNCTION_OPTIONS[choice], EXPLANATION_FUNCTION_OPTIONS[choice][0]['value'] + return EXPLANATION_FUNCTION_OPTIONS[choice], \ + EXPLANATION_FUNCTION_OPTIONS[choice][0]['value'] @callback( @@ -195,25 +231,36 @@ def generate_random_argumentation_theory(nr_of_clicks: int): strict_rule_ratio=0.3 ) argumentation_system = argumentation_system_generator.generate() - argumentation_theory_generator = ArgumentationTheoryGenerator(argumentation_system, - knowledge_literal_ratio=0.4, - axiom_knowledge_ratio=0.5) + argumentation_theory_generator = ArgumentationTheoryGenerator( + argumentation_system, knowledge_literal_ratio=0.4, + axiom_knowledge_ratio=0.5) argumentation_theory = argumentation_theory_generator.generate() - aspic_axioms_value = '\n'.join(str(axiom) for axiom in argumentation_theory.knowledge_base_axioms) - aspic_ordinary_premises_value = '\n'.join(str(premise) - for premise in argumentation_theory.knowledge_base_ordinary_premises) - aspic_strict_rule = '\n'.join(str(strict_rule) - for strict_rule in argumentation_system.strict_rules) - aspic_defeasible_rule = '\n'.join(f'{defeasible_rule.id}: {str(defeasible_rule)}' - for defeasible_rule in argumentation_system.defeasible_rules) + aspic_axioms_value = \ + '\n'.join(str(axiom) + for axiom in argumentation_theory.knowledge_base_axioms) + aspic_ordinary_premises_value = \ + '\n'.join(str(premise) + for premise in argumentation_theory. + knowledge_base_ordinary_premises) + aspic_strict_rule = \ + '\n'.join(str(strict_rule) + for strict_rule in argumentation_system.strict_rules) + aspic_defeasible_rule = \ + '\n'.join(f'{defeasible_rule.id}: {str(defeasible_rule)}' + for defeasible_rule in argumentation_system. + defeasible_rules) aspic_ordinary_premise_preference_value = \ '\n'.join(f'{str(preference[0])} < {str(preference[1])}' - for preference in argumentation_theory.ordinary_premise_preferences.preference_tuples) + for preference in argumentation_theory. + ordinary_premise_preferences.preference_tuples) aspic_defeasible_rule_preference_vale = \ '\n'.join(f'{preference[0].id} < {preference[1].id}' - for preference in argumentation_system.rule_preferences.preference_tuples) - return aspic_axioms_value, aspic_ordinary_premises_value, aspic_strict_rule, aspic_defeasible_rule, \ - aspic_ordinary_premise_preference_value, aspic_defeasible_rule_preference_vale + for preference in argumentation_system.rule_preferences. + preference_tuples) + return aspic_axioms_value, aspic_ordinary_premises_value, \ + aspic_strict_rule, aspic_defeasible_rule, \ + aspic_ordinary_premise_preference_value, \ + aspic_defeasible_rule_preference_vale return '', '', '', '', '', '' @@ -231,24 +278,29 @@ def generate_random_argumentation_theory(nr_of_clicks: int): State('color-blind-mode', 'on'), prevent_initial_call=True ) -def create_argumentation_theory(axioms_str: str, ordinary_premises_str: str, strict_rules_str: str, - defeasible_rules_str: str, - ordinary_premise_preferences_str: str, defeasible_rule_preferences_str: str, - ordering_choice_value: str, ordering_link_value: str, - selected_arguments: Dict[str, List[str]], color_blind_mode: bool): +def create_argumentation_theory( + axioms_str: str, ordinary_premises_str: str, strict_rules_str: str, + defeasible_rules_str: str, ordinary_premise_preferences_str: str, + defeasible_rule_preferences_str: str, ordering_choice_value: str, + ordering_link_value: str, selected_arguments: Dict[str, List[str]], + color_blind_mode: bool): # Read the ordering ordering_specification = ordering_choice_value + '_' + ordering_link_value # Read the argumentation theory try: arg_theory = read_argumentation_theory( - axioms_str, ordinary_premises_str, strict_rules_str, defeasible_rules_str, ordinary_premise_preferences_str, + axioms_str, ordinary_premises_str, strict_rules_str, + defeasible_rules_str, ordinary_premise_preferences_str, defeasible_rule_preferences_str) except ValueError: - arg_theory = ArgumentationTheory(ArgumentationSystem({}, {}, [], []), [], []) + arg_theory = ArgumentationTheory(ArgumentationSystem( + {}, {}, [], []), [], []) # Generate the graph data for this argumentation theory - return get_argumentation_theory_graph_data(arg_theory, ordering_specification, selected_arguments, color_blind_mode) + return get_argumentation_theory_graph_data( + arg_theory, ordering_specification, selected_arguments, + color_blind_mode) @callback( @@ -266,13 +318,12 @@ def create_argumentation_theory(axioms_str: str, ordinary_premises_str: str, str Input('structured-evaluation-strategy', 'value'), prevent_initial_call=True ) -def evaluate_structured_argumentation_framework(axioms_str: str, ordinary_premises_str: str, - strict_rules_str: str, defeasible_rules_str: str, - ordinary_premise_preferences_str: str, - defeasible_rule_preferences_str: str, - ordering_choice_value: str, ordering_link_value: str, - active_item: str, - semantics_specification: str, acceptance_strategy_specification: str): +def evaluate_structured_argumentation_framework( + axioms_str: str, ordinary_premises_str: str, strict_rules_str: str, + defeasible_rules_str: str, ordinary_premise_preferences_str: str, + defeasible_rule_preferences_str: str, ordering_choice_value: str, + ordering_link_value: str, active_item: str, + semantics_specification: str, acceptance_strategy_specification: str): if active_item != 'Evaluation': raise PreventUpdate @@ -282,20 +333,29 @@ def evaluate_structured_argumentation_framework(axioms_str: str, ordinary_premis # Read the argumentation theory try: arg_theory = read_argumentation_theory( - axioms_str, ordinary_premises_str, strict_rules_str, defeasible_rules_str, ordinary_premise_preferences_str, + axioms_str, ordinary_premises_str, strict_rules_str, + defeasible_rules_str, ordinary_premise_preferences_str, defeasible_rule_preferences_str) except ValueError: - arg_theory = ArgumentationTheory(ArgumentationSystem({}, {}, [], []), [], []) + arg_theory = ArgumentationTheory( + ArgumentationSystem({}, {}, [], []), [], []) - ordering = get_ordering_by_specification(arg_theory, ordering_specification) - arg_framework = arg_theory.create_abstract_argumentation_framework('af', ordering) - frozen_extensions = get_argumentation_framework_extensions(arg_framework, semantics_specification) + ordering = get_ordering_by_specification(arg_theory, + ordering_specification) + arg_framework = arg_theory.create_abstract_argumentation_framework( + 'af', ordering) + frozen_extensions = get_argumentation_framework_extensions( + arg_framework, semantics_specification) - extensions = [set(frozen_extension) for frozen_extension in frozen_extensions] - accepted_formulas = get_accepted_formulas(extensions, acceptance_strategy_specification) + extensions = [set(frozen_extension) + for frozen_extension in frozen_extensions] + accepted_formulas = get_accepted_formulas( + extensions, acceptance_strategy_specification) extension_buttons = [] - formula_arguments = {formula: [] for formula in arg_theory.argumentation_system.language.keys()} + formula_arguments = { + formula: [] + for formula in arg_theory.argumentation_system.language.keys()} for extension in extensions: for argument in extension: assert isinstance(argument, InstantiatedArgument) @@ -303,23 +363,33 @@ def evaluate_structured_argumentation_framework(axioms_str: str, ordinary_premis formula_arguments[accepted_formula.s1].append(argument.name) out_arguments = {attacked for attacked in arg_framework.arguments - if any(argument in arg_framework.get_incoming_defeat_arguments(attacked) + if any(argument in arg_framework. + get_incoming_defeat_arguments(attacked) for argument in extension)} undecided_arguments = {argument for argument in arg_framework.arguments - if argument not in extension and argument not in out_arguments} - extension_readable_str = '{' + ', '.join(argument.short_name for argument in extension) + '}' - - extension_in_str = '+'.join(argument.name for argument in sorted(extension)) - extension_out_str = '+'.join(argument.name for argument in sorted(out_arguments)) - extension_undecided_str = '+'.join(argument.name for argument in sorted(undecided_arguments)) - extension_long_str = '|'.join([extension_in_str, extension_undecided_str, extension_out_str]) - extension_buttons.append(dbc.Button([extension_readable_str], color='secondary', - id={'type': 'extension-button', 'index': extension_long_str})) - - accepted_formula_buttons = [dbc.Button(formula.s1, color='secondary', - id={'type': 'formula-button-structured', - 'index': '+'.join(formula_arguments[formula.s1])}) - for formula in sorted(accepted_formulas)] + if argument not in extension and + argument not in out_arguments} + extension_readable_str = \ + '{' + ', '.join(argument.short_name + for argument in extension) + '}' + + extension_in_str = '+'.join(argument.name + for argument in sorted(extension)) + extension_out_str = '+'.join(argument.name + for argument in sorted(out_arguments)) + extension_undecided_str = \ + '+'.join(argument.name for argument in sorted(undecided_arguments)) + extension_long_str = '|'.join( + [extension_in_str, extension_undecided_str, extension_out_str]) + extension_buttons.append(dbc.Button([ + extension_readable_str], color='secondary', + id={'type': 'extension-button', 'index': extension_long_str})) + + accepted_formula_buttons = [dbc.Button( + formula.s1, color='secondary', + id={'type': 'formula-button-structured', + 'index': '+'.join(formula_arguments[formula.s1])}) + for formula in sorted(accepted_formulas)] return [html.B('The extension(s):'), html.Div(extension_buttons), @@ -333,17 +403,22 @@ def evaluate_structured_argumentation_framework(axioms_str: str, ordinary_premis Input({'type': 'formula-button-structured', 'index': ALL}, 'n_clicks'), State('selected-argument-store-structured', 'data'), ) -def mark_extension_in_graph(_nr_of_clicks_values_extension, _nr_of_clicks_values_formula, - old_selected_data: List[str]): - button_clicked_id = dash.callback_context.triggered[0]['prop_id'].split('.')[0] +def mark_extension_in_graph( + _nr_of_clicks_values_extension, _nr_of_clicks_values_formula, + old_selected_data: List[str]): + button_clicked_id = \ + dash.callback_context.triggered[0]['prop_id'].split('.')[0] if button_clicked_id == '': return old_selected_data button_clicked_id_content = json.loads(button_clicked_id) button_clicked_id_type = button_clicked_id_content['type'] button_clicked_id_index = button_clicked_id_content['index'] if button_clicked_id_type == 'extension-button': - in_part, undecided_part, out_part = button_clicked_id_index.split('|', 3) - return {'green': in_part.split('+'), 'yellow': undecided_part.split('+'), 'red': out_part.split('+')} + in_part, undecided_part, out_part = \ + button_clicked_id_index.split('|', 3) + return {'green': in_part.split('+'), + 'yellow': undecided_part.split('+'), + 'red': out_part.split('+')} elif button_clicked_id_type == 'formula-button-structured': return {'blue': button_clicked_id_index.split('+')} return [] @@ -367,37 +442,44 @@ def mark_extension_in_graph(_nr_of_clicks_values_extension, _nr_of_clicks_values Input('structured-explanation-form', 'value'), prevent_initial_call=True ) -def derive_explanation_structured(active_item: str, axioms, ordinary, strict, defeasible, premise_preferences, - rule_preferences, - choice, link, semantics, function, explanation_type, strategy, form): +def derive_explanation_structured( + active_item: str, axioms, ordinary, strict, defeasible, + premise_preferences, rule_preferences, choice, link, semantics, + function, explanation_type, strategy, form): if active_item != 'Explanation': raise PreventUpdate try: - arg_theory = read_argumentation_theory(axioms, ordinary, strict, defeasible, - premise_preferences, rule_preferences) + arg_theory = read_argumentation_theory( + axioms, ordinary, strict, defeasible, premise_preferences, + rule_preferences) except ValueError: - arg_theory = ArgumentationTheory(ArgumentationSystem({}, {}, [], []), [], []) + arg_theory = ArgumentationTheory(ArgumentationSystem( + {}, {}, [], []), [], []) ordering = get_ordering_by_specification(arg_theory, choice + '_' + link) - arg_framework = arg_theory.create_abstract_argumentation_framework('af', ordering) - frozen_extensions = get_argumentation_framework_extensions(arg_framework, semantics) + arg_framework = arg_theory.create_abstract_argumentation_framework( + 'af', ordering) + frozen_extensions = get_argumentation_framework_extensions( + arg_framework, semantics) if semantics == 'Grounded': extension = frozen_extensions accepted = extension else: - extension = [set(frozen_extension) for frozen_extension in frozen_extensions] + extension = [set(frozen_extension) + for frozen_extension in frozen_extensions] accepted = get_accepted_formulas(extension, strategy) - explanations = get_str_explanations(arg_theory, semantics, ordering, extension, accepted, function, + explanations = get_str_explanations(arg_theory, semantics, ordering, + extension, accepted, function, explanation_type, strategy, form) - # return html.Div([html.B('The Explanation(s):'), - # html.H6('\n {}'.format(str(explanations).replace('set()', '{}')))]) - - return html.Div([html.Div(html.B('Explanation(s) by formula:'))] + - [html.Div([ - html.B(explanation_key), - html.Ul([html.Li(str(explanation_value).replace('set()', '{}')) - for explanation_value in explanation_values])]) - for explanation_key, explanation_values in explanations.items()]) + return html.Div( + [html.Div(html.B('Explanation(s) by formula:'))] + + [html.Div([ + html.B(explanation_key), + html.Ul([html.Li(str(explanation_value).replace( + 'set()', '{}')) + for explanation_value in explanation_values])]) + for explanation_key, explanation_values in + explanations.items()]) diff --git a/src/py_arg_visualisation/pages/23_visualise_aba.py b/src/py_arg_visualisation/pages/23_visualise_aba.py index 4416d59..2e4f9aa 100644 --- a/src/py_arg_visualisation/pages/23_visualise_aba.py +++ b/src/py_arg_visualisation/pages/23_visualise_aba.py @@ -7,24 +7,31 @@ from dash.exceptions import PreventUpdate from py_arg.assumption_based_argumentation.classes.rule import Rule -from py_arg.assumption_based_argumentation.classes.aba_framework import AssumptionBasedArgumentationFramework -from py_arg_visualisation.functions.extensions_functions import get_abaf_extensions -from py_arg_visualisation.functions.extensions_functions import get_accepted_assumptions -from py_arg_visualisation.functions.graph_data_functions import get_aba_graph_data +from py_arg.assumption_based_argumentation.classes.aba_framework \ + import AssumptionBasedArgumentationFramework +from py_arg_visualisation.functions.extensions_functions import \ + get_abaf_extensions +from py_arg_visualisation.functions.extensions_functions import \ + get_accepted_assumptions +from py_arg_visualisation.functions.graph_data_functions import \ + get_aba_graph_data -dash.register_page(__name__, name='Visualise ABA Framework', title='Visualise ABA Framework') +dash.register_page(__name__, name='Visualise ABA Framework', + title='Visualise ABA Framework') def get_aba_layout(abaf, aba_evaluation): left_column = dbc.Col( dbc.Accordion([ dbc.AccordionItem(abaf, title='ABA Framework'), - dbc.AccordionItem(aba_evaluation, title='Evaluation', item_id='23-ABA-Evaluation'), + dbc.AccordionItem(aba_evaluation, title='Evaluation', + item_id='23-ABA-Evaluation'), ], id='23-ABA-evaluation-accordion') ) right_column = dbc.Col([ dbc.Row([ - dbc.Card(visdcc.Network(data={'nodes': [], 'edges': []}, id='23-ABA-instantiated-graph', + dbc.Card(visdcc.Network(data={'nodes': [], 'edges': []}, + id='23-ABA-instantiated-graph', options={'height': '500px'}), body=True), ]) ]) @@ -36,47 +43,64 @@ def get_aba_setting_specification_div(): dcc.Store(id='23-selected-argument-store-structured'), dbc.Col([ dbc.Row([ - dbc.Col([html.B('Choose a predefined ABA framework (optional)')]), + dbc.Col([html.B('Choose a predefined ABA framework ' + '(optional)')]), dbc.Col([dbc.Select(id='23-ABA-choose-predefined', options=[ {'label': '-', 'value': 'none'}, - {'label': 'ABA tutorial example 3.1', 'value': 'lasagna'}, - {'label': 'ABA tutorial example 5.1', 'value': 'semantics_test'}, - {'label': 'ABA tutorial example 5.2', 'value': 'semantics_test_2'}, - {'label': 'ABA tutorial example 5.3', 'value': 'semantics_test_3'}, - {'label': 'ABA tutorial example 5.4', 'value': 'semantics_test_4'}, - {'label': 'ABA tutorial Tweety example', 'value': 'tweety'}, - {'label': 'Difference Asms vs. Arg Semantics Semi-Stable', 'value': - 'semantics_exm_ss'}, + {'label': 'ABA tutorial example 3.1', + 'value': 'lasagna'}, + {'label': 'ABA tutorial example 5.1', + 'value': 'semantics_test'}, + {'label': 'ABA tutorial example 5.2', + 'value': 'semantics_test_2'}, + {'label': 'ABA tutorial example 5.3', + 'value': 'semantics_test_3'}, + {'label': 'ABA tutorial example 5.4', + 'value': 'semantics_test_4'}, + {'label': 'ABA tutorial Tweety example', + 'value': 'tweety'}, + {'label': 'Difference Asms vs. Arg ' + 'Semantics Semi-Stable', + 'value': 'semantics_exm_ss'}, ], value='none')])]), dbc.Row([ dbc.Col([html.B('Atoms')]), dbc.Col([html.B('Rules')]), ]), dbc.Row([ - dbc.Col([dbc.Textarea(id='23-ABA-L', - placeholder='Add ordinary atom per line. For example:\n a \n b \n p \n q', - value='', style={'height': '200px'})]), - dbc.Col([dbc.Textarea(id='23-ABA-R', - placeholder='Add one rule per line. For example:\n p <- a, b \n q <- p', - value='', style={'height': '200px'}), ]), + dbc.Col([dbc.Textarea( + id='23-ABA-L', + placeholder='Add ordinary atom per line. ' + 'For example:\n a \n b \n p \n q', + value='', style={'height': '200px'})]), + dbc.Col([dbc.Textarea( + id='23-ABA-R', + placeholder='Add one rule per line. ' + 'For example:\n p <- a, b \n q <- p', + value='', style={'height': '200px'}), ]), ]), dbc.Row([ dbc.Col([html.B('Assumptions')]), dbc.Col([html.B('Contraries')]), ]), dbc.Row([ - dbc.Col([dbc.Textarea(id='23-ABA-A', - placeholder='Add one assumption per line. For example:\n a \n b', - value='', style={'height': '200px'})]), - dbc.Col([dbc.Textarea(id='23-ABA-C', - placeholder='Add one assignment of a contrary per line. ' - 'For example:\n (a,p) \n (b,q) \n' - 'This means that the contrary of a is p and the contrary of b is q.', - value='', style={'height': '200px'}), ]), + dbc.Col([dbc.Textarea( + id='23-ABA-A', + placeholder='Add one assumption per line. ' + 'For example:\n a \n b', + value='', style={'height': '200px'})]), + dbc.Col([dbc.Textarea( + id='23-ABA-C', + placeholder='Add one assignment of a contrary per line. ' + 'For example:\n (a,p) \n (b,q) \n' + 'This means that the contrary of a is p and ' + 'the contrary of b is q.', + value='', style={'height': '200px'}), ]), ]), dbc.Row([ - dbc.Col([dbc.Alert(id='23-ABA-error-explanation', color='warning', is_open=False)]) + dbc.Col([dbc.Alert(id='23-ABA-error-explanation', + color='warning', is_open=False)]) ]) ]) ]) @@ -117,7 +141,8 @@ def get_aba_evaluation_specification_div(): layout = html.Div( children=[ html.H1('Visualisation of ABA Frameworks'), - get_aba_layout(get_aba_setting_specification_div(), get_aba_evaluation_specification_div()) + get_aba_layout(get_aba_setting_specification_div(), + get_aba_evaluation_specification_div()) ] ) @@ -127,7 +152,10 @@ def read_aba(aba_l_str: str, aba_r_str: str, aba_a_str: str, aba_c_str: str): Read the ABA framework from the str (in the four text fields). """ # Read atoms (language) - atoms = {atom for atom in aba_l_str.replace(' ', '').replace('.', '').split('\n') if atom} + atoms = { + atom + for atom in aba_l_str.replace(' ', '').replace('.', '').split('\n') + if atom} # Read rules cleaned_rule_str = aba_r_str.replace(' ', '').replace('.', '') @@ -151,10 +179,15 @@ def read_aba(aba_l_str: str, aba_r_str: str, aba_a_str: str, aba_c_str: str): rules.add(Rule(rule_str, antecedents, before_rule)) # Read assumptions - assumptions = {atom for atom in aba_a_str.replace(' ', '').replace('.', '').split('\n') if atom} + assumptions = { + atom + for atom in aba_a_str.replace(' ', '').replace('.', '').split('\n') + if atom} # Read contraries - cleaned_contrary_str = aba_c_str.replace(' ', '').replace('.', '').replace('(', '').replace(')', '') + cleaned_contrary_str = \ + aba_c_str.replace(' ', '').replace('.', '').replace('(', '').\ + replace(')', '') contraries = {} for contrary_str in cleaned_contrary_str.split('\n'): if ',' in contrary_str: @@ -162,7 +195,8 @@ def read_aba(aba_l_str: str, aba_r_str: str, aba_a_str: str, aba_c_str: str): if before_comma and after_comma: contraries[before_comma] = after_comma - return AssumptionBasedArgumentationFramework(assumptions, rules, atoms, contraries) + return AssumptionBasedArgumentationFramework(assumptions, rules, + atoms, contraries) @callback( @@ -176,10 +210,13 @@ def prefill_predefined(predefined_value): if predefined_value == 'none': return '', '', '', '' if predefined_value == 'lasagna': - language = 'happy \neating \ngood_food \nnot_eating \nno_fork \ndirty_hands \nfork \nclean_hands' - rules = 'happy <- good_food, eating \ngood_food <- \nnot_eating <- no_fork, dirty_hands' + language = 'happy \neating \ngood_food \nnot_eating \nno_fork \n' \ + 'dirty_hands \nfork \nclean_hands' + rules = 'happy <- good_food, eating \ngood_food <- \n' \ + 'not_eating <- no_fork, dirty_hands' assumptions = 'eating \nno_fork \ndirty_hands' - contraries = '(eating, not_eating) \n(no_fork, fork) \n(dirty_hands, clean_hands)' + contraries = '(eating, not_eating) \n(no_fork, fork) \n' \ + '(dirty_hands, clean_hands)' return language, rules, assumptions, contraries if predefined_value == 'semantics_test': language = 'a\nb\nca\ncb' @@ -189,7 +226,8 @@ def prefill_predefined(predefined_value): return language, rules, assumptions, contraries if predefined_value == 'semantics_test_2': language = 'a\nb\nc\nd\ne\nf\nca\ncb\ncc\ncd\nce\ncf' - rules = 'ca <- a\nca <- b\ncb <- a\ncc <- d\ncd <- c\nce <- c\nce <- d\ncf <- e' + rules = 'ca <- a\nca <- b\ncb <- a\ncc <- d\ncd <- c\nce <- c\n' \ + 'ce <- d\ncf <- e' assumptions = 'a\nb\nc\nd\ne\nf' contraries = '(a, ca)\n(b, cb)\n(c, cc)\n(d, cd)\n(e, ce)\n(f, cf)' return language, rules, assumptions, contraries @@ -251,17 +289,20 @@ def prefill_predefined(predefined_value): prevent_initial_call=True ) def create_abaf(aba_l_str: str, aba_r_str: str, aba_a_str: str, aba_c_str: str, - selected_arguments: Dict[str, List[str]], color_blind_mode: bool): + selected_arguments: Dict[str, List[str]], + color_blind_mode: bool): try: # Generate the graph data for this argumentation theory aba_framework = read_aba(aba_l_str, aba_r_str, aba_a_str, aba_c_str) error_message = '' alert_open = False except ValueError as value_error: - aba_framework = AssumptionBasedArgumentationFramework(set(), set(), set(), {}) + aba_framework = AssumptionBasedArgumentationFramework(set(), set(), + set(), {}) error_message = str(value_error) alert_open = True - graph_data = get_aba_graph_data.apply(aba_framework, selected_arguments, color_blind_mode) + graph_data = get_aba_graph_data.apply(aba_framework, selected_arguments, + color_blind_mode) return graph_data, error_message, alert_open @@ -276,8 +317,10 @@ def create_abaf(aba_l_str: str, aba_r_str: str, aba_a_str: str, aba_c_str: str, Input('23-ABA-evaluation-strategy', 'value'), prevent_initial_call=True ) -def evaluate_abaf(aba_l_str: str, aba_r_str: str, aba_a_str: str, aba_c_str: str, - active_item: str, semantics_specification: str, acceptance_strategy_specification: str): +def evaluate_abaf( + aba_l_str: str, aba_r_str: str, aba_a_str: str, aba_c_str: str, + active_item: str, semantics_specification: str, + acceptance_strategy_specification: str): if active_item != '23-ABA-Evaluation': raise PreventUpdate @@ -288,19 +331,23 @@ def evaluate_abaf(aba_l_str: str, aba_r_str: str, aba_a_str: str, aba_c_str: str abaf = AssumptionBasedArgumentationFramework(set(), set(), set(), {}) extensions = get_abaf_extensions.apply(abaf, semantics_specification) - accepted_assumptions = get_accepted_assumptions.apply(extensions, acceptance_strategy_specification) + accepted_assumptions = get_accepted_assumptions.apply( + extensions, acceptance_strategy_specification) extension_buttons = [] for extension in extensions: - extension_readable_str = '{' + ', '.join(assumption for assumption in extension) + '}' + extension_readable_str = \ + '{' + ', '.join(assumption for assumption in extension) + '}' - extension_buttons.append(dbc.Button(extension_readable_str, color='secondary', - id={'type': 'extension-button', 'index': extension_readable_str})) + extension_buttons.append(dbc.Button( + extension_readable_str, color='secondary', + id={'type': 'extension-button', 'index': extension_readable_str})) - accepted_assumptions_buttons = [dbc.Button(assumption, color='secondary', - id={'type': 'formula-button-structured', - 'index': '+'.join(assumption)}) - for assumption in sorted(accepted_assumptions)] + accepted_assumptions_buttons = [dbc.Button( + assumption, color='secondary', + id={'type': 'formula-button-structured', + 'index': '+'.join(assumption)}) + for assumption in sorted(accepted_assumptions)] return [html.B('The extension(s):'), html.Div(extension_buttons), diff --git a/src/py_arg_visualisation/pages/24_visualise_tweety_services_test.py b/src/py_arg_visualisation/pages/24_visualise_tweety_services_test.py index 89f8993..fbcb760 100644 --- a/src/py_arg_visualisation/pages/24_visualise_tweety_services_test.py +++ b/src/py_arg_visualisation/pages/24_visualise_tweety_services_test.py @@ -1,73 +1,97 @@ +import ast import base64 import json -from typing import List, Dict import re +from typing import List, Dict + import dash +import dash_bootstrap_components as dbc import visdcc from dash import html, callback, Input, Output, State, ALL, dcc from dash.exceptions import PreventUpdate -import dash_bootstrap_components as dbc -import ast -from py_arg.abstract_argumentation.classes.abstract_argumentation_framework import AbstractArgumentationFramework -from py_arg.abstract_argumentation.generators.abstract_argumentation_framework_generator import \ +from py_arg.abstract_argumentation.classes. \ + abstract_argumentation_framework import AbstractArgumentationFramework +from py_arg.abstract_argumentation.classes.argument import Argument +from py_arg.abstract_argumentation.generators. \ + abstract_argumentation_framework_generator import \ AbstractArgumentationFrameworkGenerator -from py_arg.abstract_argumentation.import_export.argumentation_framework_from_aspartix_format_reader import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_from_aspartix_format_reader import \ ArgumentationFrameworkFromASPARTIXFormatReader -from py_arg.abstract_argumentation.import_export.argumentation_framework_from_iccma23_format_reader import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_from_iccma23_format_reader import \ ArgumentationFrameworkFromICCMA23FormatReader -from py_arg.abstract_argumentation.import_export.argumentation_framework_from_json_reader import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_from_json_reader import \ ArgumentationFrameworkFromJsonReader -from py_arg.abstract_argumentation.import_export.argumentation_framework_from_trivial_graph_format_reader import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_from_trivial_graph_format_reader import \ ArgumentationFrameworkFromTrivialGraphFormatReader -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_aspartix_format_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_aspartix_format_writer import \ ArgumentationFrameworkToASPARTIXFormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_iccma23_format_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_iccma23_format_writer import \ ArgumentationFrameworkToICCMA23FormatWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_json_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_json_writer import \ ArgumentationFrameworkToJSONWriter -from py_arg.abstract_argumentation.import_export.argumentation_framework_to_trivial_graph_format_writer import \ +from py_arg.abstract_argumentation.import_export. \ + argumentation_framework_to_trivial_graph_format_writer import \ ArgumentationFrameworkToTrivialGraphFormatWriter -from py_arg_visualisation.functions.explanations_functions.explanation_function_options import \ +from py_arg_visualisation.functions.explanations_functions. \ + explanation_function_options import \ EXPLANATION_FUNCTION_OPTIONS -from py_arg_visualisation.functions.explanations_functions.get_af_explanations import \ - get_argumentation_framework_explanations -from py_arg_visualisation.functions.extensions_functions.get_accepted_arguments import get_accepted_arguments -from py_arg_visualisation.functions.extensions_functions.get_af_extensions import get_argumentation_framework_extensions -from py_arg_visualisation.functions.graph_data_functions.get_af_graph_data import get_argumentation_framework_graph_data -from py_arg_visualisation.functions.import_functions.read_argumentation_framework_functions import \ +from py_arg_visualisation.functions.explanations_functions. \ + get_af_explanations import get_argumentation_framework_explanations +from py_arg_visualisation.functions.extensions_functions. \ + get_accepted_arguments import get_accepted_arguments +from py_arg_visualisation.functions.extensions_functions. \ + get_af_extensions import get_argumentation_framework_extensions +from py_arg_visualisation.functions.graph_data_functions. \ + get_af_graph_data import get_argumentation_framework_graph_data +from py_arg_visualisation.functions.import_functions. \ + read_argumentation_framework_functions import \ read_argumentation_framework +from py_arg_visualisation.functions.tweety_services_functions import \ + tweety_services_handler -from py_arg_visualisation.functions.tweety_services_functions import tweety_services_handler -from py_arg.abstract_argumentation.classes.argument import Argument -dash.register_page(__name__, name='Visualise Tweety Services Test', title='Visualise Tweety Services') - +dash.register_page(__name__, name='Visualise Tweety Services Test', + title='Visualise Tweety Services') # Create layout elements and compose them into the layout for this page. - config = tweety_services_handler.TweetyServiceConfig() config.load() TWEETY_SERVICES_UP = True + def get_abstract_setting_specification_div(): return html.Div(children=[ dcc.Store(id='tweety-selected-argument-store-abstract'), dbc.Col([ - dbc.Row([dbc.Col(dbc.Button('Generate random', id='generate-random-af-button', n_clicks=0, - className='w-100')), - dbc.Col(dcc.Upload(dbc.Button('Open existing AF', className='w-100'), id='upload-af')) - ], className='mt-2'), + dbc.Row([dbc.Col( + dbc.Button('Generate random', id='generate-random-af-button', + n_clicks=0, + className='w-100')), + dbc.Col(dcc.Upload( + dbc.Button('Open existing AF', className='w-100'), + id='upload-af')) + ], className='mt-2'), dbc.Row([ dbc.Col([ html.B('Arguments'), dbc.Textarea(id='tweety-arguments', - placeholder='Add one argument per line. For example:\n A\n B\n C', + placeholder='Add one argument per line. ' + 'For example:\n A\n B\n C', value='', style={'height': '300px'}) ]), dbc.Col([ html.B('Attacks'), dbc.Textarea(id='tweety-attacks', - placeholder='Add one attack per line. For example: \n (A,B) \n (A,C) \n (C,B)', + placeholder='Add one attack per line. ' + 'For example: \n (A,B) \n (A,C) ' + '\n (C,B)', value='', style={'height': '300px'}), ]) ], className='mt-2'), @@ -76,9 +100,10 @@ def get_abstract_setting_specification_div(): dbc.InputGroupText('Filename'), dbc.Input(value='edited_af', id='24-tweety-filename'), dbc.InputGroupText('.'), - dbc.Select(options=[{'label': extension, 'value': extension} - for extension in ['JSON', 'TGF', 'APX', 'ICCMA23']], - value='JSON', id='24-tweety-extension'), + dbc.Select(options=[ + {'label': extension, 'value': extension} + for extension in ['JSON', 'TGF', 'APX', 'ICCMA23']], + value='JSON', id='24-tweety-extension'), dbc.Button('Download', id='24-tweety-download-button'), ], className='mt-2'), dcc.Download(id='24-tweety-download') @@ -93,34 +118,34 @@ def get_abstract_evaluation_div(): semantics_mapping = [{'label': sem, 'value': sem} for sem in semantics] except Exception: print('Tweety server down') - TWEETY_SERVICES_UP = False - semantics_mapping = [ - {'label': 'Admissible', 'value': 'Admissible'}, - {'label': 'Complete', 'value': 'Complete'}, - {'label': 'Grounded', 'value': 'Grounded'}, - {'label': 'Preferred', 'value': 'Preferred'}, - {'label': 'Ideal', 'value': 'Ideal'}, - {'label': 'Stable', 'value': 'Stable'}, - {'label': 'Semi-stable', 'value': 'SemiStable'}, - {'label': 'Eager', 'value': 'Eager'}, - ] + semantics_mapping = [ + {'label': 'Admissible', 'value': 'Admissible'}, + {'label': 'Complete', 'value': 'Complete'}, + {'label': 'Grounded', 'value': 'Grounded'}, + {'label': 'Preferred', 'value': 'Preferred'}, + {'label': 'Ideal', 'value': 'Ideal'}, + {'label': 'Stable', 'value': 'Stable'}, + {'label': 'Semi-stable', 'value': 'SemiStable'}, + {'label': 'Eager', 'value': 'Eager'}, + ] return html.Div([ html.Div([ dbc.Row([ dbc.Col(html.B('Semantics')), - dbc.Col(dbc.Select(options= semantics_mapping - , value='wad', id='tweety-evaluation-semantics')), + dbc.Col(dbc.Select(options=semantics_mapping, + value='wad', + id='tweety-evaluation-semantics')), ]), dbc.Row([dbc.Col(html.B('Timeout')), - dbc.Col(dbc.Input(type='number', min=0, step=1, value=500, - id='tweety-timeout-input'))]), + dbc.Col(dbc.Input(type='number', min=0, step=1, value=500, + id='tweety-timeout-input'))]), dbc.Row([ dbc.Col(html.B('Timeout unit')), - dbc.Col(dbc.Select(options= [{'label': 'ms', 'value': 'ms'}, - {'label': 'sec', 'value': 'sec'}] - , value='ms', id='tweety-timeout-unit-input'))]), - + dbc.Col(dbc.Select(options=[{'label': 'ms', 'value': 'ms'}, + {'label': 'sec', 'value': 'sec'}], + value='ms', + id='tweety-timeout-unit-input'))]), dbc.Row([ dbc.Col(html.B('Evaluation strategy')), @@ -139,9 +164,11 @@ def get_abstract_explanation_div(): return html.Div([ dbc.Row([ dbc.Col(html.B('Type')), - dbc.Col(dbc.Select(options=[{'label': 'Acceptance', 'value': 'Acceptance'}, - {'label': 'Non-Acceptance', 'value': 'NonAcceptance'}], - value='Acceptance', id='tweety-explanation-type'))]), + dbc.Col(dbc.Select( + options=[ + {'label': 'Acceptance', 'value': 'Acceptance'}, + {'label': 'Non-Acceptance', 'value': 'NonAcceptance'}], + value='Acceptance', id='tweety-explanation-type'))]), dbc.Row([ dbc.Col(html.B('Explanation function')), dbc.Col(dbc.Select(id='tweety-explanation-function')) @@ -152,19 +179,25 @@ def get_abstract_explanation_div(): left_column = dbc.Col( dbc.Accordion([ - dbc.AccordionItem(get_abstract_setting_specification_div(), title='Abstract Argumentation Framework'), - dbc.AccordionItem(get_abstract_evaluation_div(), title='Evaluation', item_id='Evaluation'), - dbc.AccordionItem(get_abstract_explanation_div(), title='Explanation', item_id='Explanation') + dbc.AccordionItem(get_abstract_setting_specification_div(), + title='Abstract Argumentation Framework'), + dbc.AccordionItem(get_abstract_evaluation_div(), title='Evaluation', + item_id='Evaluation'), + dbc.AccordionItem(get_abstract_explanation_div(), title='Explanation', + item_id='Explanation') ], id='tweety-evaluation-accordion') ) right_column = dbc.Col([ dbc.Row([ - dbc.Card(visdcc.Network(data={'nodes': [], 'edges': []}, id='tweety-argumentation-graph', + dbc.Card(visdcc.Network(data={'nodes': [], 'edges': []}, + id='tweety-argumentation-graph', options={'height': '500px'}), body=True), ]) ]) layout_abstract = dbc.Row([left_column, right_column]) -layout = html.Div([html.H1('Visualisation of abstract argumentation frameworks'), layout_abstract]) +layout = html.Div( + [html.H1('Visualisation of abstract argumentation frameworks'), + layout_abstract]) @callback( @@ -174,15 +207,21 @@ def get_abstract_explanation_div(): Input('upload-af', 'contents'), State('upload-af', 'filename') ) -def generate_abstract_argumentation_framework(_nr_of_clicks_random: int, af_content: str, af_filename: str): +def generate_abstract_argumentation_framework(_nr_of_clicks_random: int, + af_content: str, + af_filename: str): """ - Generate a random AF after clicking the button and put the result in the text box. + Generate a random AF after clicking the button and put the result in the + text box. """ if dash.callback_context.triggered_id == 'generate-random-af-button': - random_af = AbstractArgumentationFrameworkGenerator(8, 8, True).generate() - abstract_arguments_value = '\n'.join((str(arg) for arg in random_af.arguments)) - abstract_attacks_value = '\n'.join((f'({str(defeat.from_argument)},{str(defeat.to_argument)})' - for defeat in random_af.defeats)) + random_af = AbstractArgumentationFrameworkGenerator(8, 8, + True).generate() + abstract_arguments_value = '\n'.join( + (str(arg) for arg in random_af.arguments)) + abstract_attacks_value = '\n'.join( + (f'({str(defeat.from_argument)},{str(defeat.to_argument)})' + for defeat in random_af.defeats)) return abstract_arguments_value, abstract_attacks_value elif dash.callback_context.triggered_id == 'upload-af': content_type, content_str = af_content.split(',') @@ -190,19 +229,26 @@ def generate_abstract_argumentation_framework(_nr_of_clicks_random: int, af_cont name = af_filename.split('.')[0] if af_filename.upper().endswith('.JSON'): - opened_af = ArgumentationFrameworkFromJsonReader().from_json(json.loads(decoded)) + opened_af = ArgumentationFrameworkFromJsonReader().from_json( + json.loads(decoded)) elif af_filename.upper().endswith('.TGF'): - opened_af = ArgumentationFrameworkFromTrivialGraphFormatReader.from_tgf(decoded.decode(), name) + opened_af = ArgumentationFrameworkFromTrivialGraphFormatReader. \ + from_tgf(decoded.decode(), name) elif af_filename.upper().endswith('.APX'): - opened_af = ArgumentationFrameworkFromASPARTIXFormatReader.from_apx(decoded.decode(), name) + opened_af = ArgumentationFrameworkFromASPARTIXFormatReader. \ + from_apx(decoded.decode(), name) elif af_filename.upper().endswith('.ICCMA23'): - opened_af = ArgumentationFrameworkFromICCMA23FormatReader.from_iccma23(decoded.decode(), name) + opened_af = ArgumentationFrameworkFromICCMA23FormatReader. \ + from_iccma23(decoded.decode(), name) else: - raise NotImplementedError('This file format is currently not supported.') - - abstract_arguments_value = '\n'.join((str(arg) for arg in opened_af.arguments)) - abstract_attacks_value = '\n'.join((f'({str(defeat.from_argument)},{str(defeat.to_argument)})' - for defeat in opened_af.defeats)) + raise NotImplementedError( + 'This file format is currently not supported.') + + abstract_arguments_value = '\n'.join( + (str(arg) for arg in opened_af.arguments)) + abstract_attacks_value = '\n'.join( + (f'({str(defeat.from_argument)},{str(defeat.to_argument)})' + for defeat in opened_af.defeats)) return abstract_arguments_value, abstract_attacks_value return '', '' @@ -216,7 +262,8 @@ def generate_abstract_argumentation_framework(_nr_of_clicks_random: int, af_cont prevent_initial_call=True ) def create_abstract_argumentation_framework(arguments: str, attacks: str, - selected_arguments: Dict[str, List[str]], + selected_arguments: Dict[ + str, List[str]], color_blind_mode: bool): """ Send the AF data to the graph for plotting. @@ -226,10 +273,13 @@ def create_abstract_argumentation_framework(arguments: str, attacks: str, except ValueError: arg_framework = AbstractArgumentationFramework() - if dash.callback_context.triggered_id != 'tweety-selected-argument-store-abstract': + if dash.callback_context.triggered_id != \ + 'tweety-selected-argument-store-abstract': selected_arguments = None - data = get_argumentation_framework_graph_data(arg_framework, selected_arguments, color_blind_mode) + data = get_argumentation_framework_graph_data(arg_framework, + selected_arguments, + color_blind_mode) return data @@ -243,25 +293,32 @@ def create_abstract_argumentation_framework(arguments: str, attacks: str, prevent_initial_call=True, ) def download_generated_abstract_argumentation_framework( - _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, extension: str): - argumentation_framework = read_argumentation_framework(arguments_text, defeats_text) + _nr_clicks: int, arguments_text: str, defeats_text: str, filename: str, + extension: str): + argumentation_framework = read_argumentation_framework(arguments_text, + defeats_text) if extension == 'JSON': - argumentation_framework_json = ArgumentationFrameworkToJSONWriter().to_dict(argumentation_framework) + argumentation_framework_json = ArgumentationFrameworkToJSONWriter(). \ + to_dict(argumentation_framework) argumentation_framework_str = json.dumps(argumentation_framework_json) elif extension == 'TGF': argumentation_framework_str = \ - ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToTrivialGraphFormatWriter.write_to_str( + argumentation_framework) elif extension == 'APX': argumentation_framework_str = \ - ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToASPARTIXFormatWriter.write_to_str( + argumentation_framework) elif extension == 'ICCMA23': argumentation_framework_str = \ - ArgumentationFrameworkToICCMA23FormatWriter.write_to_str(argumentation_framework) + ArgumentationFrameworkToICCMA23FormatWriter.write_to_str( + argumentation_framework) else: raise NotImplementedError - return {'content': argumentation_framework_str, 'filename': filename + '.' + extension} + return {'content': argumentation_framework_str, + 'filename': filename + '.' + extension} @callback( @@ -278,15 +335,16 @@ def download_generated_abstract_argumentation_framework( ) def evaluate_abstract_argumentation_framework(arguments: str, attacks: str, active_item: str, - semantics: str, strategy: str, timeout:str, unit_timeout = str): + semantics: str, strategy: str, + timeout: str, unit_timeout=str): if active_item != 'Evaluation': raise PreventUpdate # Read the abstract argumentation framework. arg_framework = read_argumentation_framework(arguments, attacks) - + time = 0 status = 'SUCCESS' - tweety_service_response = ('',-1) + tweety_service_response = ('', -1) if TWEETY_SERVICES_UP: print(f'{arguments=}') @@ -295,7 +353,8 @@ def evaluate_abstract_argumentation_framework(arguments: str, attacks: str, arguments_list = arguments.split('\n') nr_arguments = len(arguments_list) print(f'{arguments_list=}') - arguments_id_mapping = dict(zip(arguments_list,range(1,len(arguments_list)+1))) + arguments_id_mapping = dict( + zip(arguments_list, range(1, len(arguments_list) + 1))) # Regular expression pattern to match (A,B) format pattern = r'\((\w+),(\w+)\)' @@ -303,7 +362,10 @@ def evaluate_abstract_argumentation_framework(arguments: str, attacks: str, matches = re.findall(pattern, attacks) # Convert matches to actual tuples attacks_list = [list(match) for match in matches] - attacks_id_mapped = [ [arguments_id_mapping[att[0]],arguments_id_mapping[att[1]]] for att in attacks_list] + attacks_id_mapped = [ + [arguments_id_mapping[att[0]], arguments_id_mapping[att[1]]] for + att + in attacks_list] config.payload.nr_of_arguments = nr_arguments config.payload.attacks = attacks_id_mapped config.payload.semantics = semantics @@ -311,66 +373,82 @@ def evaluate_abstract_argumentation_framework(arguments: str, attacks: str, config.payload.unit_timeout = unit_timeout tweety_service_response = tweety_services_handler.get_models(config) time = tweety_service_response[0]['time'] - unit_time = tweety_service_response[0]['unit_time'] + # unit_time = tweety_service_response[0]['unit_time'] status = tweety_service_response[0]['status'] if status == 'SUCCESS': try: - extensions = ast.literal_eval(tweety_service_response[0]['answer']) - if not (isinstance(extensions, list) and all(isinstance(item, set) for item in extensions)): + extensions = ast.literal_eval( + tweety_service_response[0]['answer']) + if not (isinstance(extensions, list) and all( + isinstance(item, set) for item in extensions)): # empty extensions get evaluated to dict instead of sets - for i,item in enumerate(extensions): - if isinstance(item,dict): - extensions[i] = set(extensions[i]) + for i, item in enumerate(extensions): + if isinstance(item, dict): + extensions[i] = set(extensions[i]) except (SyntaxError, ValueError): print("Invalid input string.") - - # Map ids back to argument names - id_arguments_mapping = { v:Argument(k) for k,v in arguments_id_mapping.items()} - extensions = [set(map(id_arguments_mapping.get, ext)) for ext in extensions] - - - - + # Map ids back to argument names + id_arguments_mapping = {v: Argument(k) for k, v in + arguments_id_mapping.items()} + extensions = [set(map(id_arguments_mapping.get, ext)) for ext in + extensions] else: - # Compute the extensions and put them in a list of sets. - frozen_extensions = get_argumentation_framework_extensions(arg_framework, semantics) - extensions = [set(frozen_extension) for frozen_extension in frozen_extensions] + frozen_extensions = get_argumentation_framework_extensions( + arg_framework, semantics) + extensions = [set(frozen_extension) for frozen_extension in + frozen_extensions] # Make a button for each extension. extension_buttons = [] if status == 'SUCCESS': for extension in sorted(extensions): - out_arguments = {attacked for attacked in arg_framework.arguments - if any(argument in arg_framework.get_incoming_defeat_arguments(attacked) - for argument in extension)} - undecided_arguments = {argument for argument in arg_framework.arguments - if argument not in extension and argument not in out_arguments} - extension_readable_str = '{' + ', '.join(argument.name for argument in sorted(extension)) + '}' - extension_in_str = '+'.join(argument.name for argument in sorted(extension)) - extension_out_str = '+'.join(argument.name for argument in sorted(out_arguments)) - extension_undecided_str = '+'.join(argument.name for argument in sorted(undecided_arguments)) - extension_long_str = '|'.join([extension_in_str, extension_undecided_str, extension_out_str]) - extension_buttons.append(dbc.Button([extension_readable_str], color='secondary', - id={'type': 'extension-button-abstract', 'index': extension_long_str})) + out_arguments = { + attacked for attacked in arg_framework.arguments + if any( + argument in arg_framework.get_incoming_defeat_arguments( + attacked) + for argument in extension)} + undecided_arguments = { + argument for argument in arg_framework.arguments + if argument not in extension and argument not in out_arguments} + extension_readable_str = '{' + ', '.join( + argument.name for argument in sorted(extension)) + '}' + extension_in_str = '+'.join( + argument.name for argument in sorted(extension)) + extension_out_str = '+'.join( + argument.name for argument in sorted(out_arguments)) + extension_undecided_str = '+'.join( + argument.name for argument in sorted(undecided_arguments)) + extension_long_str = '|'.join( + [extension_in_str, extension_undecided_str, extension_out_str]) + extension_buttons.append( + dbc.Button([extension_readable_str], color='secondary', + id={'type': 'extension-button-abstract', + 'index': extension_long_str})) # Based on the extensions, get the acceptance status of arguments. accepted_arguments = get_accepted_arguments(extensions, strategy) # Mke a button for each accepted argument. - accepted_argument_buttons = [dbc.Button(argument.name, color='secondary', id={'type': 'argument-button-abstract', - 'index': argument.name}) - for argument in sorted(accepted_arguments)] + accepted_argument_buttons = [ + dbc.Button(argument.name, color='secondary', + id={'type': 'argument-button-abstract', + 'index': argument.name}) + for argument in sorted(accepted_arguments)] else: accepted_argument_buttons = [] return html.Div([html.B('The extension(s):'), html.Div(extension_buttons), - html.B('The accepted argument(s):'), html.Div(accepted_argument_buttons), - html.P('Click on the extension/argument buttons to display the corresponding argument(s) ' - 'in the graph.'), - html.B('Time:'), html.Div(f'{time} {unit_timeout}'), - html.B('Status:'), html.Div(status), - html.B('Raw Respones:'), html.Div(json.dumps(tweety_service_response[0])), - - ]) + html.B('The accepted argument(s):'), + html.Div(accepted_argument_buttons), + html.P( + 'Click on the extension/argument buttons to display ' + 'the corresponding argument(s) ' + 'in the graph.'), + html.B('Time:'), html.Div(f'{time} {unit_timeout}'), + html.B('Status:'), html.Div(status), + html.B('Raw Respones:'), + html.Div(json.dumps(tweety_service_response[0])), + ]) @callback( @@ -379,17 +457,22 @@ def evaluate_abstract_argumentation_framework(arguments: str, attacks: str, Input({'type': 'argument-button-abstract', 'index': ALL}, 'n_clicks'), State('tweety-selected-argument-store-abstract', 'data'), ) -def mark_extension_or_argument_in_graph(_nr_of_clicks_extension_values, _nr_of_clicks_argument_values, +def mark_extension_or_argument_in_graph(_nr_of_clicks_extension_values, + _nr_of_clicks_argument_values, old_selected_data: List[str]): - button_clicked_id = dash.callback_context.triggered[0]['prop_id'].split('.')[0] + button_clicked_id = \ + dash.callback_context.triggered[0]['prop_id'].split('.')[0] if button_clicked_id == '': return old_selected_data button_clicked_id_content = json.loads(button_clicked_id) button_clicked_id_type = button_clicked_id_content['type'] button_clicked_id_index = button_clicked_id_content['index'] if button_clicked_id_type == 'extension-button-abstract': - in_part, undecided_part, out_part = button_clicked_id_index.split('|', 3) - return {'green': in_part.split('+'), 'yellow': undecided_part.split('+'), 'red': out_part.split('+')} + in_part, undecided_part, out_part = \ + button_clicked_id_index.split('|', 3) + return {'green': in_part.split('+'), + 'yellow': undecided_part.split('+'), + 'red': out_part.split('+')} elif button_clicked_id_type == 'argument-button-abstract': return {'blue': [button_clicked_id_index]} return [] @@ -401,7 +484,8 @@ def mark_extension_or_argument_in_graph(_nr_of_clicks_extension_values, _nr_of_c [Input('tweety-explanation-type', 'value')] ) def setting_choice(choice: str): - return EXPLANATION_FUNCTION_OPTIONS[choice], EXPLANATION_FUNCTION_OPTIONS[choice][0]['value'] + return EXPLANATION_FUNCTION_OPTIONS[choice], \ + EXPLANATION_FUNCTION_OPTIONS[choice][0]['value'] @callback( @@ -415,25 +499,38 @@ def setting_choice(choice: str): State('tweety-evaluation-strategy', 'value'), prevent_initial_call=True ) -def derive_explanations_abstract_argumentation_framework(active_item, - arguments: str, attacks: str, - semantics: str, explanation_function: str, - explanation_type: str, explanation_strategy: str): +def derive_explanations_abstract_argumentation_framework( + active_item, + arguments: str, + attacks: str, + semantics: str, + explanation_function: str, + explanation_type: str, + explanation_strategy: str): if active_item != 'Explanation': raise PreventUpdate # Compute the explanations based on the input. arg_framework = read_argumentation_framework(arguments, attacks) - frozen_extensions = get_argumentation_framework_extensions(arg_framework, semantics) - extensions = [set(frozen_extension) for frozen_extension in frozen_extensions] - accepted_arguments = get_accepted_arguments(extensions, explanation_strategy) - explanations = get_argumentation_framework_explanations(arg_framework, extensions, accepted_arguments, - explanation_function, explanation_type) - + frozen_extensions = get_argumentation_framework_extensions(arg_framework, + semantics) + extensions = [set(frozen_extension) for frozen_extension in + frozen_extensions] + accepted_arguments = get_accepted_arguments(extensions, + explanation_strategy) + explanations = get_argumentation_framework_explanations( + arg_framework, + extensions, + accepted_arguments, + explanation_function, + explanation_type) + # Print the explanations for each of the arguments. return html.Div([html.Div(html.B('Explanation(s) by argument:'))] + [html.Div([ html.B(explanation_key), - html.Ul([html.Li(str(explanation_value).replace('set()', '{}')) - for explanation_value in explanation_values])]) - for explanation_key, explanation_values in explanations.items()]) + html.Ul([html.Li( + str(explanation_value).replace('set()', '{}')) + for explanation_value in explanation_values])]) + for explanation_key, explanation_values in + explanations.items()]) diff --git a/src/py_arg_visualisation/pages/30_learn.py b/src/py_arg_visualisation/pages/30_learn.py index d631049..03939c0 100644 --- a/src/py_arg_visualisation/pages/30_learn.py +++ b/src/py_arg_visualisation/pages/30_learn.py @@ -2,7 +2,8 @@ from dash import html, dcc, callback, Input, Output, State import dash_bootstrap_components as dbc -from py_arg_learning.identify_grounded_extension import IdentifyGroundedExtension +from py_arg_learning.identify_grounded_extension import \ + IdentifyGroundedExtension from py_arg_learning.list_complete_extensions import ListCompleteExtensions from py_arg_learning.list_preferred_extensions import ListPreferredExtensions @@ -20,18 +21,22 @@ html.H1('Practice with argumentation exercises'), dbc.Col([ html.B('What would you like to practice?'), - dbc.Select(options=[{'label': option, 'value': option} for option in exercise_dict.keys()], + dbc.Select(options=[{'label': option, 'value': option} + for option in exercise_dict.keys()], value=list(exercise_dict.keys())[0], id='exercise-choice-dropdown'), html.Br(), - dbc.Card([], id='explanation-html', className='border-0 bg-transparent'), + dbc.Card([], id='explanation-html', + className='border-0 bg-transparent'), html.Br(), dbc.Button('Generate exercise', id='practice-button', n_clicks=0), html.Div([ html.Br(), html.Br(), - dbc.Card([], id='exercise-text', className='border-0 bg-transparent'), - dbc.Textarea(value='', id='answer-input-text-field', style={'width': '100%'}), + dbc.Card([], id='exercise-text', + className='border-0 bg-transparent'), + dbc.Textarea(value='', id='answer-input-text-field', + style={'width': '100%'}), html.Br(), dbc.Button('Check', id='check-button', n_clicks=0), html.Br(), @@ -65,14 +70,16 @@ def get_explanation_html(exercise_choice_value: str): State('30-exercise-div', 'style'), State('color-blind-mode', 'on') ) -def handle_button_click(_generate_button_clicks: int, _check_button_clicks: int, +def handle_button_click(_generate_button_clicks: int, + _check_button_clicks: int, exercise_choice_value: str, old_exercise_text: str, - user_solution: str, pre_generated_solutions, old_style: dict, - color_blind_mode: bool): + user_solution: str, pre_generated_solutions, + old_style: dict, color_blind_mode: bool): button_clicked = dash.ctx.triggered_id if button_clicked == 'practice-button': exercise_set = exercise_dict[exercise_choice_value] - exercise, graph_data, solutions = exercise_set.generate_exercise_and_solutions(color_blind_mode) + exercise, graph_data, solutions = \ + exercise_set.generate_exercise_and_solutions(color_blind_mode) rendered_exercise = [ html.B('Exercise'), exercise_set.render_exercise_instance(exercise, graph_data) @@ -80,6 +87,8 @@ def handle_button_click(_generate_button_clicks: int, _check_button_clicks: int, return rendered_exercise, solutions, '', '', {'display': 'block'} elif button_clicked == 'check-button': exercise_set = exercise_dict[exercise_choice_value] - feedback_text = exercise_set.get_feedback(user_solution, pre_generated_solutions) - return old_exercise_text, pre_generated_solutions, user_solution, feedback_text, {'display': 'block'} + feedback_text = exercise_set.get_feedback(user_solution, + pre_generated_solutions) + return old_exercise_text, pre_generated_solutions, user_solution, \ + feedback_text, {'display': 'block'} return '', [], '', '', old_style diff --git a/src/py_arg_visualisation/pages/41_canonical_af.py b/src/py_arg_visualisation/pages/41_canonical_af.py index 7f25f57..f61a24e 100644 --- a/src/py_arg_visualisation/pages/41_canonical_af.py +++ b/src/py_arg_visualisation/pages/41_canonical_af.py @@ -6,14 +6,19 @@ from dash import html, callback, Input, Output, State from py_arg.abstract_argumentation.classes.argument import Argument -from py_arg.abstract_argumentation.canonical_constructions import check_incomparable, check_contains_empty, \ +from py_arg.abstract_argumentation.canonical_constructions import \ + check_incomparable, check_contains_empty, \ check_unary, check_conf_sens, check_non_empty, check_tight -from py_arg.abstract_argumentation.canonical_constructions import check_dcl_tight, check_downward_closed -from py_arg.abstract_argumentation.canonical_constructions.canonical_af import construct_af_stage, construct_af_adm, \ +from py_arg.abstract_argumentation.canonical_constructions import \ + check_dcl_tight, check_downward_closed +from py_arg.abstract_argumentation.canonical_constructions.canonical_af \ + import construct_af_stage, construct_af_adm, \ construct_af_grd -from py_arg.abstract_argumentation.canonical_constructions.canonical_af import construct_af_stb, construct_af_cf, \ +from py_arg.abstract_argumentation.canonical_constructions.canonical_af \ + import construct_af_stb, construct_af_cf, \ construct_af_naive -from py_arg_visualisation.functions.graph_data_functions.get_af_graph_data import get_argumentation_framework_graph_data +from py_arg_visualisation.functions.graph_data_functions.get_af_graph_data \ + import get_argumentation_framework_graph_data dash.register_page(__name__, name='Canonical', title='Canonical') @@ -48,7 +53,8 @@ html.Td(id='41-cf-downward-closed'), html.Td(), html.Td(), html.Td(), html.Td(id='41-cf-non-empty'), - html.Td(), html.Td(dbc.Button('Generate', id='41-generate-conflict-free-button')) + html.Td(), html.Td(dbc.Button('Generate', + id='41-generate-conflict-free-button')) ]), html.Tr([ html.Td('Admissible'), html.Td(), @@ -56,7 +62,8 @@ html.Td(), html.Td(), html.Td(id='41-adm-contains-empty'), html.Td(id='41-adm-non-empty'), - html.Td(), html.Td(dbc.Button('Generate', id='41-generate-admissible-button')) + html.Td(), html.Td(dbc.Button('Generate', + id='41-generate-admissible-button')) ]), html.Tr([ html.Td('Grounded'), html.Td(), html.Td(), html.Td(), @@ -69,14 +76,16 @@ html.Td(), html.Td(), html.Td(id='41-stb-incomparable'), html.Td(), html.Td(), html.Td(), - html.Td(), html.Td(dbc.Button('Generate', id='41-generate-stable-button')) + html.Td(), html.Td(dbc.Button('Generate', + id='41-generate-stable-button')) ]), html.Tr([ html.Td('Naive'), html.Td(), html.Td(), html.Td(), html.Td(id='41-na-incomparable'), html.Td(id='41-na-dcl-tight'), html.Td(), html.Td(id='41-na-non-empty'), - html.Td(), html.Td(dbc.Button('Generate', id='41-generate-naive-button')) + html.Td(), html.Td(dbc.Button('Generate', + id='41-generate-naive-button')) ]), html.Tr([ html.Td('Stage'), html.Td(id='41-stg-tight'), @@ -84,7 +93,8 @@ html.Td(id='41-stg-incomparable'), html.Td(), html.Td(), html.Td(id='41-stg-non-empty'), - html.Td(), html.Td(dbc.Button('Generate', id='41-generate-stage-button')) + html.Td(), html.Td(dbc.Button('Generate', + id='41-generate-stage-button')) ]), ])]) @@ -95,7 +105,8 @@ dbc.Col([ html.B('Enter your set of extensions here'), dbc.Textarea(id='41-extension-sets-textarea', - placeholder='Put each set on a new line and represent sets as {X, Y, Z}.', + placeholder='Put each set on a new line and ' + 'represent sets as {X, Y, Z}.', style={'height': '200px'}), html.B('Properties and semantics'), properties_table, @@ -113,8 +124,10 @@ def read_extension_sets_from_str(extension_sets_str: str): input_extension_set = set() for extension in extensions_set: extension = extension.replace('{', '').replace('}', '') - argument_strs = [argument_str.strip() for argument_str in extension.split(',')] - argument_set = frozenset(Argument(argument_str) for argument_str in argument_strs + argument_strs = [argument_str.strip() + for argument_str in extension.split(',')] + argument_set = frozenset(Argument(argument_str) + for argument_str in argument_strs if argument_str) input_extension_set.add(argument_set) return input_extension_set @@ -226,9 +239,11 @@ def fill_properties_table(extension_sets_str: str): naive_realizable = non_empty and incomparable and dcl_tight stg_realizable = tight and incomparable and non_empty - return tight_style, conf_sens_style, downward_closed_style, incomparable_style, dcl_tight_style, \ + return tight_style, conf_sens_style, downward_closed_style, \ + incomparable_style, dcl_tight_style, \ contains_empty_style, non_empty_style, unary_style, \ - not cf_realizable, not adm_realizable, not grd_realizable, not stb_realizable, not naive_realizable, \ + not cf_realizable, not adm_realizable, not grd_realizable, \ + not stb_realizable, not naive_realizable, \ not stg_realizable, \ tight_value, downward_closed_value, non_empty_value, \ conf_sens_value, contains_empty_value, non_empty_value, \ @@ -277,13 +292,16 @@ def get_canonical_argumentation_framework(extension_sets_str: str, else: raise NotImplementedError - graph_data = get_argumentation_framework_graph_data(af, None, color_blind_mode) + graph_data = get_argumentation_framework_graph_data(af, None, + color_blind_mode) return [ html.B('Canonical argumentation framework'), dbc.Col(html.P('AF = (A, D) where A = {{{a}}} and D = {{{d}}}.'.format( a=', '.join(str(arg) for arg in af.arguments), - d='; '.join('(' + str(defeat.from_argument) + ', ' + str(defeat.to_argument) + ')' + d='; '.join('(' + str(defeat.from_argument) + ', ' + str( + defeat.to_argument) + ')' for defeat in af.defeats)))), - dbc.Col(visdcc.Network(data=graph_data, options={'height': '500px'}, id='canonical-graph')), + dbc.Col(visdcc.Network(data=graph_data, options={'height': '500px'}, + id='canonical-graph')), ] diff --git a/src/py_arg_visualisation/pages/42_canonical_abaf.py b/src/py_arg_visualisation/pages/42_canonical_abaf.py index 8fa32c2..c88e4bd 100644 --- a/src/py_arg_visualisation/pages/42_canonical_abaf.py +++ b/src/py_arg_visualisation/pages/42_canonical_abaf.py @@ -5,12 +5,17 @@ import visdcc from dash import html, callback, Input, Output, State -from py_arg.abstract_argumentation.canonical_constructions import check_incomparable, check_intersection_in, \ +from py_arg.abstract_argumentation.canonical_constructions import \ + check_incomparable, check_intersection_in, \ check_set_com_closed, check_contains_empty, check_non_empty -from py_arg.abstract_argumentation.canonical_constructions import check_set_conf_sens, check_downward_closed -from py_arg.assumption_based_argumentation.canonical_constructions import construct_abaf_com, construct_abaf_prf, \ - construct_abaf_st, construct_abaf_cf, construct_abaf_naive, construct_abaf_adm -from py_arg_visualisation.functions.graph_data_functions.get_af_graph_data import get_argumentation_framework_graph_data +from py_arg.abstract_argumentation.canonical_constructions import \ + check_set_conf_sens, check_downward_closed +from py_arg.assumption_based_argumentation.canonical_constructions import \ + construct_abaf_com, construct_abaf_prf, \ + construct_abaf_st, construct_abaf_cf, construct_abaf_naive, \ + construct_abaf_adm +from py_arg_visualisation.functions.graph_data_functions.get_af_graph_data \ + import get_argumentation_framework_graph_data dash.register_page(__name__, name='CanonicalABAF', title='CanonicalABAF') @@ -31,10 +36,12 @@ html.Th(html.Div(html.Span('Incomparable')), className='rotate'), html.Th(html.Div(html.Span('Non-Empty')), className='rotate'), html.Th(html.Div(html.Span('Downward-closed')), className='rotate'), - html.Th(html.Div(html.Span('Set-Conflict-Sensitive')), className='rotate'), + html.Th(html.Div(html.Span('Set-Conflict-Sensitive')), + className='rotate'), html.Th(html.Div(html.Span('Contains Empty Set')), className='rotate'), html.Th(html.Div(html.Span('Set-Comp-Closed')), className='rotate'), - html.Th(html.Div(html.Span('Contains-Intersection')), className='rotate'), + html.Th(html.Div(html.Span('Contains-Intersection')), + className='rotate'), html.Th(), ]), html.Tr([ @@ -96,7 +103,8 @@ dbc.Col([ html.B('Enter your set of extensions here'), dbc.Textarea(id='42-extension-sets-textarea', - placeholder='Put each set on a new line and represent sets as {X, Y, Z}.', + placeholder='Put each set on a new line and ' + 'represent sets as {X, Y, Z}.', style={'height': '200px'}), html.B('Properties and semantics'), properties_table, @@ -114,7 +122,8 @@ def read_extension_sets_from_str(extension_sets_str: str): input_extension_set = set() for extension in extensions_set: extension = extension.replace('{', '').replace('}', '') - argument_strs = [argument_str.strip() for argument_str in extension.split(',')] + argument_strs = [argument_str.strip() + for argument_str in extension.split(',')] argument_set = frozenset(argument_str for argument_str in argument_strs if argument_str) input_extension_set.add(argument_set) @@ -217,9 +226,11 @@ def fill_properties_table(extension_sets_str: str): adm_realizable = non_empty and set_conf_sens and contains_empty com_realizable = non_empty and set_comp_closed and intersection_in - return incomparable_style, non_empty_style, downward_closed_style, set_conf_sens_style, contains_empty_style, \ + return incomparable_style, non_empty_style, downward_closed_style, \ + set_conf_sens_style, contains_empty_style, \ set_comp_closed_style, intersection_in_style, \ - not stb_realizable, not pref_realizable, not cf_realizable, not naive_realizable, not adm_realizable, \ + not stb_realizable, not pref_realizable, not cf_realizable, \ + not naive_realizable, not adm_realizable, \ not com_realizable, \ incomparable_value, \ incomparable_value, non_empty_value, \ @@ -268,15 +279,20 @@ def get_canonical_argumentation_framework(extension_sets_str: str, else: raise NotImplementedError - graph_data = get_argumentation_framework_graph_data(abaf.generate_af(), None, color_blind_mode) + graph_data = get_argumentation_framework_graph_data(abaf.generate_af(), + None, color_blind_mode) return [ html.B('Canonical ABA framework'), - dbc.Col(html.P('D = (L, R, A, C) where L = {{{l}}}, R = {{{r}}}, A = {{{a}}} and C = {{{c}}}.'.format( - l=', '.join(str(atom) for atom in abaf.language), - r='; '.join(str(rule) for rule in abaf.rules), - a=', '.join(str(atom) for atom in abaf.assumptions), - c='; '.join('(' + str(atom) + ', ' + str(abaf.contraries[atom]) + ')' - for atom in abaf.contraries.keys())))), - dbc.Col(visdcc.Network(data=graph_data, options={'height': '500px'}, id='canonical-graph')), + dbc.Col(html.P( + 'D = (L, R, A, C) where L = {{{l}}}, R = {{{r}}}, ' + 'A = {{{a}}} and C = {{{c}}}.'.format( + l=', '.join(str(atom) for atom in abaf.language), + r='; '.join(str(rule) for rule in abaf.rules), + a=', '.join(str(atom) for atom in abaf.assumptions), + c='; '.join('(' + str(atom) + ', ' + + str(abaf.contraries[atom]) + ')' + for atom in abaf.contraries.keys())))), + dbc.Col(visdcc.Network(data=graph_data, options={'height': '500px'}, + id='canonical-graph')), ] diff --git a/src/py_arg_visualisation/pages/50_chat.py b/src/py_arg_visualisation/pages/50_chat.py index 1e81770..dd086cd 100644 --- a/src/py_arg_visualisation/pages/50_chat.py +++ b/src/py_arg_visualisation/pages/50_chat.py @@ -7,20 +7,28 @@ from dash import html, dcc, callback, Input, Output, State import dash_bootstrap_components as dbc -from py_arg.aspic.import_export.argumentation_system_from_json_reader import ArgumentationSystemFromJsonReader -from py_arg.aspic.import_export.argumentation_system_to_json_writer import ArgumentationSystemToJSONWriter -from py_arg.incomplete_aspic.algorithms.relevance.relevance_lister import FourBoolRelevanceLister -from py_arg.incomplete_aspic.algorithms.stability.stability_labeler import StabilityLabeler -from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import IncompleteArgumentationTheory - -dash.register_page(__name__, name='Inquiry Dialogue System', title='Inquiry Dialogue System') +from py_arg.aspic.import_export.argumentation_system_from_json_reader import \ + ArgumentationSystemFromJsonReader +from py_arg.aspic.import_export.argumentation_system_to_json_writer import \ + ArgumentationSystemToJSONWriter +from py_arg.incomplete_aspic.algorithms.relevance.relevance_lister import \ + FourBoolRelevanceLister +from py_arg.incomplete_aspic.algorithms.stability.stability_labeler import \ + StabilityLabeler +from py_arg.incomplete_aspic.classes.incomplete_argumentation_theory import \ + IncompleteArgumentationTheory + +dash.register_page(__name__, name='Inquiry Dialogue System', + title='Inquiry Dialogue System') left_column = dbc.Col( [ html.B('Argumentation system'), dbc.Row([ - dbc.Col([dbc.Button('Try fraud example', id='50-fraud-example-button')]), - dbc.Col([dcc.Upload(dbc.Button('Upload argumentation system'), id='50-chat-as-upload')]), + dbc.Col([dbc.Button('Try fraud example', + id='50-fraud-example-button')]), + dbc.Col([dcc.Upload(dbc.Button('Upload argumentation system'), + id='50-chat-as-upload')]), ]), html.B('Queryables'), dcc.Dropdown(multi=True, id='50-queryables-dropdown'), @@ -52,12 +60,15 @@ Input('50-fraud-example-button', 'n_clicks'), prevent_initial_call=True ) -def update_queryable_and_topic_options(argumentation_system_content, _fraud_example_clicks): +def update_queryable_and_topic_options(argumentation_system_content, + _fraud_example_clicks): triggered_id = dash.ctx.triggered_id if triggered_id == '50-fraud-example-button': - file_path = pathlib.Path(__file__).parent.parent / 'resources' / '02_2020_COMMA_Paper_Example.json' - opened_as = ArgumentationSystemFromJsonReader().read_from_json(str(file_path)) + file_path = pathlib.Path(__file__).parent.parent / 'resources' / \ + '02_2020_COMMA_Paper_Example.json' + opened_as = ArgumentationSystemFromJsonReader().read_from_json( + str(file_path)) queryable_values = [ 'citizen_tried_to_buy', 'citizen_sent_money', @@ -72,7 +83,8 @@ def update_queryable_and_topic_options(argumentation_system_content, _fraud_exam elif triggered_id == '50-chat-as-upload' and argumentation_system_content: content_type, content_str = argumentation_system_content.split(',') decoded = base64.b64decode(content_str) - opened_as = ArgumentationSystemFromJsonReader().from_json(json.loads(decoded)) + opened_as = ArgumentationSystemFromJsonReader().from_json(json.loads( + decoded)) queryable_values = [] topic_value = None else: @@ -81,9 +93,11 @@ def update_queryable_and_topic_options(argumentation_system_content, _fraud_exam pos_literals = [{'label': key, 'value': key} for key, value in opened_as.language.items() if value.is_positive] - all_literals = [{'label': key, 'value': key} for key in opened_as.language.keys()] + all_literals = [{'label': key, 'value': key} + for key in opened_as.language.keys()] as_to_json = ArgumentationSystemToJSONWriter().to_dict(opened_as) - return pos_literals, all_literals, queryable_values, as_to_json, topic_value, [] + return pos_literals, all_literals, queryable_values, as_to_json, \ + topic_value, [] @callback( @@ -92,24 +106,28 @@ def update_queryable_and_topic_options(argumentation_system_content, _fraud_exam Input('50-knowledge-base', 'value'), State('50-argumentation-system', 'data') ) -def update_knowledge_base_options(queryables, current_value, argumentation_system_content): +def update_knowledge_base_options(queryables, current_value, + argumentation_system_content): if not queryables: return [] - opened_as = ArgumentationSystemFromJsonReader().from_json(argumentation_system_content) + opened_as = ArgumentationSystemFromJsonReader().from_json( + argumentation_system_content) result = set() for queryable in queryables: queryable_literal = opened_as.language[queryable] - contradictories = [contra - for contra in queryable_literal.contraries_and_contradictories] + contradictories = \ + [contra for contra in + queryable_literal.contraries_and_contradictories] if not current_value or all(contra.s1 not in current_value for contra in contradictories): result.add(queryable) for contradictory in contradictories: contra_contradictories = \ [contra_contra - for contra_contra in contradictory.contraries_and_contradictories] + for contra_contra in + contradictory.contraries_and_contradictories] if not current_value or \ all(contra_contra.s1 not in current_value for contra_contra in contra_contradictories): @@ -125,12 +143,13 @@ def update_knowledge_base_options(queryables, current_value, argumentation_syste State('50-argumentation-system', 'data'), State('50-topic-dropdown', 'value') ) -def update_knowledge_base_options(positive_queryables, knowledge_base, - argumentation_system_content, topic_str): +def update_stability_status(positive_queryables, knowledge_base, + argumentation_system_content, topic_str): if not positive_queryables or not topic_str: return '' - opened_as = ArgumentationSystemFromJsonReader().from_json(argumentation_system_content) + opened_as = ArgumentationSystemFromJsonReader().from_json( + argumentation_system_content) queryables = set() for q in positive_queryables: @@ -146,14 +165,17 @@ def update_knowledge_base_options(positive_queryables, knowledge_base, knowledge_base_ordinary_premises=[] ) - stability_labeler_labels = StabilityLabeler().label(incomplete_argumentation_theory) + stability_labeler_labels = StabilityLabeler().label( + incomplete_argumentation_theory) topic_literal = opened_as.language[topic_str] topic_label = stability_labeler_labels.literal_labeling[topic_literal] if topic_label.is_stable: return 'The topic is ' + topic_label.stability_str.lower() + '.' relevance_lister = FourBoolRelevanceLister() - relevance_lister.update(incomplete_argumentation_theory, stability_labeler_labels) + relevance_lister.update(incomplete_argumentation_theory, + stability_labeler_labels) questions = relevance_lister.relevance_list[topic_literal] random_question = random.choice(list(questions)) - return 'The topic is not stable yet. Do you know something about ' + random_question.s1 + '?' + return 'The topic is not stable yet. Do you know something about ' + \ + random_question.s1 + '?' diff --git a/src/py_arg_visualisation/pages/90_pyarg.py b/src/py_arg_visualisation/pages/90_pyarg.py index 33ab9c8..8597049 100644 --- a/src/py_arg_visualisation/pages/90_pyarg.py +++ b/src/py_arg_visualisation/pages/90_pyarg.py @@ -5,15 +5,21 @@ layout = html.Div(children=[ html.H1('Welcome to PyArg!'), - html.P('This is a Python package and web interface for solving various problems in ' - 'computational argumentation.'), - html.P(['If you have any questions, feedback or ambitions to contribute, feel free to contact ', - html.A('Daphne Odekerken', href='mailto:d.odekerken@uu.nl?subject=PyArg'), + html.P('This is a Python package and web interface for solving various ' + 'problems in computational argumentation.'), + html.P(['If you have any questions, feedback or ambitions to contribute, ' + 'feel free to contact ', + html.A('Daphne Odekerken', + href='mailto:d.odekerken@uu.nl?subject=PyArg'), '.']), html.P('Contributors:'), html.Ul([ - html.Li(html.A('Daphne Odekerken', href='https://webspace.science.uu.nl/~3827887/')), - html.Li(html.A('Matti Berthold', href='https://www.informatik.uni-leipzig.de/~berthold/')), - html.Li(html.A('AnneMarie Borg', href='https://annemarieborg.nl/')), + html.Li(html.A('Daphne Odekerken', + href='https://webspace.science.uu.nl/~3827887/')), + html.Li(html.A( + 'Matti Berthold', + href='https://www.informatik.uni-leipzig.de/~berthold/')), + html.Li(html.A('AnneMarie Borg', + href='https://annemarieborg.nl/')), ]) ])