Value-based argumentation (VAF)
The argumentation-values crate adds value-based argumentation frameworks to the workspace. This page is the conceptual overview; for API details see the rustdoc.
Bench-Capon (2003) extended Dung frameworks with values — each argument promotes a value, and an audience is an ordering over values. Different audiences reach different rational conclusions from the same framework. Our implementation supports the multi-value generalisation from Kaci & van der Torre (2008).
Types at a glance
use argumentation::ArgumentationFramework;
use argumentation_values::{Audience, Value, ValueAssignment, ValueBasedFramework};
let mut base = ArgumentationFramework::new();
base.add_argument("h1");
base.add_argument("c1");
base.add_attack(&"h1", &"c1").unwrap();
base.add_attack(&"c1", &"h1").unwrap();
let mut values = ValueAssignment::new();
values.promote("h1", Value::new("life"));
values.promote("c1", Value::new("property"));
let vaf = ValueBasedFramework::new(base, values);
let life_first = Audience::total([Value::new("life"), Value::new("property")]);
assert!(vaf.accepted_for(&life_first, &"h1").unwrap());
assert!(!vaf.accepted_for(&life_first, &"c1").unwrap());
Defeat semantics (Kaci & van der Torre 2008, Pareto)
Given attack (A, B) in the underlying Dung framework and audience X, A defeats B in the audience-conditioned graph iff:
for every value
v_bpromoted by B, there exists some valuev_apromoted by A such thatv_bis not strictly preferred overv_aunder X.
Single-value (Bench-Capon 2003) is the degenerate case where each argument promotes exactly one value.
Special cases:
- A or B promotes no value → A defeats B (no preference can intervene).
- A value is unranked in the audience → considered incomparable (no strict preference); attacker side wins ties.
Acceptance modes
| Method | Cost | Use case |
|---|---|---|
accepted_for(&audience, &arg) | Polynomial-ish (one preferred-extension call) | Runtime: "what does this character believe?" |
subjectively_accepted(&arg) | NP-complete; capped at 6 distinct values | Authoring: "is there any audience under which X is accepted?" |
objectively_accepted(&arg) | co-NP-complete; capped at 6 distinct values | Authoring: "is X accepted under every audience? (i.e., universally compelling)" |
MultiAudience::common_grounded(&vaf) | k × preferred extensions, where k = audience count | Multi-character scenes: "which proposals does the whole council agree on?" |
The ENUMERATION_LIMIT cap on subjective/objective queries is per Dunne & Bench-Capon (2004). Past 6 values, methods return Err(Error::AudienceTooLarge) — use a fixed-audience query instead.
Hal & Carla, worked
The canonical example. See the engine-driven scene for the live version.
let mut base = ArgumentationFramework::new();
for a in ["h1", "c1", "h2", "c2"] { base.add_argument(a); }
base.add_attack(&"h1", &"c1").unwrap(); // life attacks property
base.add_attack(&"c1", &"h1").unwrap(); // property attacks life
base.add_attack(&"c2", &"h2").unwrap(); // Carla's "my only dose" defeats fairness appeal
base.add_attack(&"h2", &"c1").unwrap(); // Hal's poverty attacks property
let mut values = ValueAssignment::new();
values.promote("h1", Value::new("life"));
values.promote("c1", Value::new("property"));
values.promote("h2", Value::new("fairness"));
values.promote("c2", Value::new("life"));
let vaf = ValueBasedFramework::new(base, values);
// Audience 1: life > property → Hal goes free.
let life_first = Audience::total([Value::new("life"), Value::new("property")]);
let g1 = vaf.grounded_for(&life_first).unwrap();
assert!(g1.contains("h1") && g1.contains("c2"));
// Audience 2: property > life → Hal punished.
let property_first = Audience::total([Value::new("property"), Value::new("life")]);
let g2 = vaf.grounded_for(&property_first).unwrap();
assert!(g2.contains("c1") && g2.contains("c2"));
Encounter bridge integration
encounter-argumentation ships ValueAwareScorer for runtime use:
use encounter_argumentation::{
EncounterArgumentationState, SchemeActionScorer, ValueAwareScorer,
Audience, Value,
};
let state = EncounterArgumentationState::new(catalog);
state.set_audience("alice", Audience::total([Value::new("duty"), Value::new("survival")]));
state.set_audience("bob", Audience::total([Value::new("survival"), Value::new("duty")]));
let scorer = ValueAwareScorer::new(
SchemeActionScorer::new(knowledge, registry, baseline_scorer, 0.3),
&state,
0.2,
);
Per-character audiences flow through the scorer at resolve time — Alice and Bob score the same affordance differently when their value orderings differ.
See the wiring per-character values how-to for a complete worked example.
APX format I/O
ASPARTIX-compatible APX format with VAF extension:
arg(h1).
arg(c1).
att(h1, c1).
att(c1, h1).
val(h1, life).
val(c1, property).
valpref(life, property).
Use argumentation_values::apx::from_apx(text) to parse, to_apx(&vaf, &audience) to serialise. Round-trips preserve the framework + audience. Useful for importing benchmark VAFs from the literature or exporting scenes for analysis in ASPARTIX.
Bibliography
- Bench-Capon (2003) — the original VAF paper.
- Atkinson & Bench-Capon (2007) — practical reasoning over VAFs.
- Kaci, S. & van der Torre, L. (2008). "Preference-based argumentation: Arguments supporting multiple values." International Journal of Approximate Reasoning 48(3): 730–751.
- Dunne, P.E. & Bench-Capon, T. (2004). "Complexity in Value-Based Argument Systems." JELIA 2004: 360–371.
- Bodanza, G.A. & Freidin, E. (2023). "Confronting value-based argumentation frameworks with people's assessment of argument strength." Argument & Computation 14(3): 247–273. — empirical critique; informs why we expose
SchemeActionScorer's direct value-importance scoring alongside the orthodox VAF defeat semantics.
Further reading
- Hal & Carla — the engine-driven scene this implementation was built around.
- Open areas — what's still on the roadmap (probabilistic AF, ADF, dialogue games, dynamic AF).
- Wiring per-character values — how-to.