ajar.afdm.AFDM#

class ajar.afdm.AFDM[source]#

Bases: object

An Argumentation Framework for Decision-Making.

An AFDM contains arguments, and an attack (binary) relationship between arguments. It can be used to compute the grounded extension of arguments in a given situation (i.e., with only certain arguments activated).

__init__()[source]#

Create a new AFDM.

Methods

__init__()

Create a new AFDM.

add_argument(argument)

Add a new argument to the known arguments.

add_attack_relation(attacker, attacked)

Add a new attack between arguments.

arguments_countering(decision[, ...])

Return the arguments that counter a given decision.

arguments_supporting(decision[, ...])

Return the arguments that support a given decision.

compute_grounded_extension()

Compute the grounded extension.

get_attacked(argument[, return_arguments])

Return the arguments that are attacked by a given argument.

get_attackers(argument[, return_arguments])

Return the arguments that are attackers of a given argument.

is_alive(argument_name)

Return whether an argument is alive in this AFDM.

update_alive_in_grounded_extension()

Compute the grounded extension and update the arguments' aliveness.

Attributes

R

All attack relations known in this AFDM.

arguments

All arguments known in this AFDM.

A

The map of known arguments, indexed by their name for faster access.

attackers

A dictionary mapping arguments to their attackers.

attacked

A dictionary mapping arguments to the arguments that they attack.

decisions

The set of known decisions.

grounded

The list of arguments' names that are in the grounded extension at the current step.

A: Dict[str, Argument]#

The map of known arguments, indexed by their name for faster access.

To iterate over arguments, please see arguments.

property R: Iterable[Attack]#

All attack relations known in this AFDM.

To simplify usage and enforce types, attacks are represented by the Attack dataclass. In the comments, we will also note them as tuples, e.g., ('a', 'b') means that argument 'a' attacks 'b'.

This should be used to iterate over all attacks, but not when accessing the attackers of a specific argument (or, conversely, the arguments attacked by a specific argument). For these operations, the optimized way is to use the get_attackers() and get_attacked() methods, which internally use MultiMaps for performance.

_grounded_loop_condition(labels: Dict[str, str]) str | None[source]#

Find the next candidate for the grounded extension.

Internal method that should not be useful externally. It finds an argument which is still undecided, and for which all attackers have been killed (out), i.e., a suitable candidate for the grounded extension.

Parameters:

labels – The arguments’ labels when computing the grounded, i.e., a dictionary mapping each argument name to a label (undecided, in, or out).

Returns:

A new candidate argument, identified by its name, or None if there is no remaining candidate (i.e., the grounded is complete).

add_argument(argument: Argument) Argument[source]#

Add a new argument to the known arguments.

Parameters:

argument – The argument to add. If an argument with the same name already exists, a warning is raised, and the new argument overrides the previous one. The argument is deep-copied before it is added, so that this AFDM can be modified without any side effect on other AFDMs, if they share arguments.

Returns:

The new argument, which is a deep-copy of the given one.

add_attack_relation(attacker: str | Argument, attacked: str | Argument)[source]#

Add a new attack between arguments.

Parameters:
  • attacker – The attacker argument, either identified by its name, or the argument itself.

  • attacked – The attacked argument, either identified by its name, or the argument itself.

Raises:

An exception is raised if the arguments’ names (either passed directly as parameters, or obtained through the arguments themselves) are not known, i.e., no argument is associated to them in this AFDM builder.

property arguments: Iterable[Argument]#

All arguments known in this AFDM.

This is a shortcut to self.A.values(), allowing to access the arguments themselves (not the dict) easily.

arguments_countering(decision: str, ignore_aliveness: bool = False) List[Argument][source]#

Return the arguments that counter a given decision.

This function corresponds to the F_c set in our algorithm, and is mostly used to get the number of countering arguments, comparing it to the number of supporting arguments, and resulting in a scalar reward. Optionally, returns all arguments, even those that are “killed” (not alive).

Parameters:
  • decision – The decision that we are looking for. Typically, 'moral'.

  • ignore_aliveness – Whether to return only alive arguments (by default), or to ignore the aliveness and return all arguments supporting decision (when set to True).

Returns:

The list of arguments that counter decision, i.e., that have decision as part of their counter. When ignore_aliveness is False, only arguments that have their alive set to True are returned. Otherwise, this condition is ignored.

arguments_supporting(decision: str, ignore_aliveness: bool = False) List[Argument][source]#

Return the arguments that support a given decision.

This function corresponds to the F_f set in our algorithm, and is mostly used to get the number of supporting arguments, comparing it to the number of countering arguments, and resulting in a scalar reward. Optionally, returns all arguments, even those that are “killed” (not alive).

Parameters:
  • decision – The decision that we are looking for. Typically, 'moral'.

  • ignore_aliveness – Whether to return only alive arguments (by default), or to ignore the aliveness and return all arguments supporting decision (when set to True).

Returns:

The list of arguments that support decision, i.e., that have decision as part of their support. When ignore_aliveness is False, only arguments that have their alive set to True are returned. Otherwise, this condition is ignored.

attacked: Dict[str, Set[str]]#

A dictionary mapping arguments to the arguments that they attack.

In other words, attacked[x] = { y, z } means that x attacks y and z. More generally, it should be read as attacked[attacker] = set of attacked arguments.

This structure (dict of sets) is also known as a MultiMap (or MultiSet), and is optimal for performances, when getting all attacked arguments of a given argument, instead of iterating over the whole list of attack relations. The get_attacked() method offers is the public interface for getting attackers in an easy way (and also allows to return Arguments instead of their names).

Warning

This field should never be modified directly! Otherwise, the attackers attribute would not be updated, and the attack relationship would not be correctly set. Please use the add_attack_relation() method instead, which ensures both attribute are modified.

attackers: Dict[str, Set[str]]#

A dictionary mapping arguments to their attackers.

In other words, attackers[x] = { y, z } mean that y and z are attackers of x. More generally, it should be read as: attackers[attacked] = set of attackers.

This structure (dict of sets) is also known as a MultiMap (or MultiSet), and is optimal for performances, when getting all attackers of a given argument, instead of iterating over the whole list of attack relations. The get_attackers() method offers is the public interface for getting attackers in an easy way (and also allows to return Arguments instead of their names).

Warning

This field should never be modified directly! Otherwise, the attacked attribute would not be updated, and the attack relationship would not be correctly set. Please use the add_attack_relation() method instead, which ensures both attribute are modified.

compute_grounded_extension() List[str][source]#

Compute the grounded extension.

The grounded extension is one of the ways of computing the acceptable set of arguments, based on attacks between them.

Returns:

The list of names of arguments that are in the grounded extension, i.e., which are considered acceptable.

decisions: Set[str]#

The set of known decisions.

Decisions are retrieved from the arguments’ support and counter fields. As mentioned in their docs, in our current version, decisions are not really used. In practice, the default 'moral' decision will be the only one, i.e., arguments support or counter “The agent’s last action was moral with respect to the given moral value”.

get_attacked(argument: Argument | str, return_arguments=False) List[str] | List[Argument][source]#

Return the arguments that are attacked by a given argument.

Parameters:
  • argument – The desired argument, or its name.

  • return_arguments – Whether to return the attacked as arguments directly, or to return their names.

Returns:

The list of arguments that are attacked by argument, i.e., the arguments with name a such that (argument, 'a') are in R. When return_arguments is True, the returned list is composed of instances of Arguments; otherwise, it is composed of the arguments’ names (strings).

get_attackers(argument: Argument | str, return_arguments=False) List[str] | List[Argument][source]#

Return the arguments that are attackers of a given argument.

Parameters:
  • argument – The desired argument, or its name.

  • return_arguments – Whether to return the attackers as arguments directly, or to return their names.

Returns:

The list of arguments that attack argument, i.e., the arguments with name a such that ('a', argument) are in R. When return_arguments is True, the returned list is composed of instances of Arguments; otherwise, it is composed of the arguments’ names (strings).

grounded: List[str]#

The list of arguments’ names that are in the grounded extension at the current step.

The grounded extension must be re-computed each step, by taking into account the new situation, and thus the new aliveness of arguments.

is_alive(argument_name: str) bool[source]#

Return whether an argument is alive in this AFDM.

This is a shortcut for self.A[argument_name].alive, which also makes the error more explicit if the argument cannot be found.

Parameters:

argument_name – The name of the desired argument. Must be a valid key in A, otherwise an Exception is raised.

Returns:

The argument’s aliveness.

update_alive_in_grounded_extension()[source]#

Compute the grounded extension and update the arguments’ aliveness.

The grounded extension is computed based on arguments that are alive or not, and attacks. Then, the arguments are said to be alive if they are in the grounded; otherwise, they are not.

This method thus transitions from “activated arguments” (i.e., arguments that are true in the given situation) to “acceptable arguments” (i.e., arguments that are true and defend each other).