Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,19 @@ jobs:
python-version: '3.11'
- run: python -m pip install pytest
- run: python -m pytest -q tests

cpu-smoke:
runs-on: ubuntu-latest
env:
DGLBACKEND: pytorch
OMP_NUM_THREADS: '1'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.11'
- run: python -m pip install -r requirements-cpu.txt pytest
- run: python -m pytest -q tests
- run: python -m examples.gcn_demo
27 changes: 9 additions & 18 deletions AFGCNv2/README
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
The AFGCNv2 Solver is based on Python3. There are two major dependencies that must be installed prior to running the solver: pytorch, the deep learning engine used, and dgl, the graph library used.
AFGCNv2 is a historical competition-solver snapshot.

The solver is submitted to the approximate track and supports all the decision problems in that track (DC-PR, DS-PR, DC-ST, DS-ST, DC-CO, DS-CO, DC-SST, DS-SST, DC-STG, DS-STG, DS-ID).
This directory preserves solver.py, solver.sh, semantic-specific checkpoints,
thresholds and the accompanying paper. Its original environment is not the
root repository's CPU demo environment.

To run the solver please follow the following steps:
For the current documented and tested decision-solver workflow, use:
https://github.com/lmlearning/AFGCN

Install python3 if not installed. If the pip package manager is not installed, please install that as well.

Then to install the pre-requiste python libraries, please run the following commands:
pip install dgl -f https://data.dgl.ai/wheels/repo.html
pip install dglgo -f https://data.dgl.ai/wheels-test/repo.html
pip install torch
pip install scikit-learn

Once the pre-requisites have been put in place the solver can be called in the following manner, conforming to the solver requirements set out in the ICCMA 2023 call for solvers:

./solver.sh -p <problem> -f <file> -a <argument>

Example:

./solver.sh -p DS-ST -f myFile.tgf -a 2
For a self-contained GCN training example in this repository, see the root
README and examples/gcn_demo.py. Historical checkpoints should be interpreted
with the code, input format and configuration that produced them.
10 changes: 10 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cff-version: 1.2.0
message: "Please cite this software and the associated paper where applicable."
type: software
title: "AFGraphLib: Graph Learning for Abstract Argumentation"
authors:
- family-names: Malmqvist
given-names: Lars
repository-code: "https://github.com/lmlearning/AFGraphLib"
url: "https://github.com/lmlearning/AFGraphLib"
license: MIT
8 changes: 6 additions & 2 deletions GraphLib/dglutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
from dgl import DGLGraph
import networkx as nx
from dgl.nn.pytorch import GraphConv
from model import GCN
import numpy as np
from util import parseTGF,parseAPX, get_features, read_solution_file, get_credulous_labels, get_sceptical_labels, get_masks
if __package__:
from .model import GCN
from .util import parseTGF, parseAPX, get_features, read_solution_file, get_credulous_labels, get_sceptical_labels, get_masks
else:
from model import GCN
from util import parseTGF, parseAPX, get_features, read_solution_file, get_credulous_labels, get_sceptical_labels, get_masks

def load_graph(file_path, cutoff = 10000000, format="tgf"):

Expand Down
14 changes: 8 additions & 6 deletions GraphLib/inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
import torch.nn.functional as F
from dgl import DGLGraph
import networkx as nx
from dglutil import make_dgl_graph, merge_graphs, send_graph_to_device, load_graph
from util import parseTGF,get_features, read_solution_file, get_credulous_labels, get_masks,getRandomBatch, load_ckp
from model import GCN
if __package__:
from .dglutil import make_dgl_graph, merge_graphs, send_graph_to_device, load_graph
from .util import parseTGF, get_features, read_solution_file, get_credulous_labels, get_masks, getRandomBatch, load_ckp
from .model import GCN
else:
from dglutil import make_dgl_graph, merge_graphs, send_graph_to_device, load_graph
from util import parseTGF, get_features, read_solution_file, get_credulous_labels, get_masks, getRandomBatch, load_ckp
from model import GCN
import argparse
import pickle
import numpy as np
Expand Down Expand Up @@ -187,6 +192,3 @@ def detect_admbuster(nx_graph):
return False
else:
return True



5 changes: 4 additions & 1 deletion GraphLib/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
from dgl import DGLGraph
import networkx as nx
from dgl.nn.pytorch import GraphConv
from model import GCN
if __package__:
from .model import GCN
else:
from model import GCN
import numpy as np
import shutil

Expand Down
91 changes: 58 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,63 @@
# AFGraphLib: Graph Learning for Abstract Argumentation

Graph learning tools and research materials for **abstract argumentation**: representing arguments and attacks as graphs, then learning to predict argument acceptance.

## Explore the repository

| Path | Purpose |
| --- | --- |
| [GraphLib](GraphLib/) | Graph utilities, models and inference code. |
| [AFs](AFs/) | Example argumentation frameworks and associated solutions. |
| [AFGCNv2](AFGCNv2/) | Solver implementation, checkpoints and accompanying research material. |
| [AFGCN_new.py](AFGCN_new.py) | GCN experiment implementation. |
| [pyg_train.py](pyg_train.py) | Graph-learning training script. |

Start with the [model code](GraphLib/model.py) to inspect the architecture or the [solver documentation](AFGCNv2/README) to explore solving. Training scripts are research entry points; review their imports, data paths and configuration before running them.

## Related projects

- [AFGCN](https://github.com/lmlearning/AFGCN): dedicated solver and training repository.
- [FastAFGCN](https://github.com/lmlearning/FastAFGCN): quantized ONNX inference.
- [AFSubsample](https://github.com/lmlearning/AFSubsample): framework subsampling and analysis.

## Component tests
# AFGraphLib: Graph Learning for Abstract Argumentation

[![Tests](https://github.com/lmlearning/AFGraphLib/actions/workflows/tests.yml/badge.svg)](https://github.com/lmlearning/AFGraphLib/actions/workflows/tests.yml)

Graph-learning components and experimental materials for **predicting which arguments are accepted in a network of arguments and attacks**. The core contains DGL graph construction, acceptance-label utilities, GCN models and inference experiments.

**Start with the runnable GCN example below.** For the pretrained decision-solver workflow, see [AFGCN](https://github.com/lmlearning/AFGCN).

## Run a CPU example

Use Python 3.11 in an activated virtual environment, from the repository root. The pinned CPU environment supports Linux and Windows.

```bash
python -m pip install pytest
python -m pytest tests
python -m pip install -r requirements-cpu.txt pytest
python -m examples.gcn_demo
python -m pytest -q tests
```

The device-transfer helper is isolated in `GraphLib/device.py` and remains available
through `GraphLib.dglutil`. It uses the requested device and keeps the original
attribute if its transfer fails. The graph is modified in place; earlier successful
transfers are not rolled back. These tests use graph/tensor protocol doubles and do
not require DGL or validate GPU execution or model training.
The example fits the existing `GraphLib.model.GCN` to an illustrative four-argument framework: `a → b → c`, plus an isolated argument `d`. It prints a `[4, 1]` logits shape and a decreasing training loss. This is a small training demonstration with known labels, not a held-out accuracy result. No corpus or checkpoint download is required.

## Architecture and code map

```mermaid
flowchart LR
A[Arguments and directed attacks] --> G[DGL graph and node features]
G --> M[GraphConv layers and dropout]
M --> L[Per-argument logits]
L --> T[Task-specific acceptance decisions]
```

| Path | What to inspect |
| --- | --- |
| [examples/gcn_demo.py](examples/gcn_demo.py) | A complete graph → model → loss → backward-pass example. |
| [GraphLib/model.py](GraphLib/model.py) | Graph convolutional model definitions. |
| [GraphLib/dglutil.py](GraphLib/dglutil.py) | Graph construction and batching helpers. |
| [GraphLib/util.py](GraphLib/util.py) | Framework parsing and acceptance-label utilities. |
| [GraphLib/inference.py](GraphLib/inference.py) | Grounded reasoning and neural-inference experiments. |
| [AFs](AFs/) | Research frameworks and solution files, stored with Git LFS. |
| [AFGCNv2](AFGCNv2/) | Historical competition solver snapshot and its paper. |

The library modules support package imports from the repository root and the original script-style imports from inside `GraphLib`. Older standalone experiment scripts retain their original paths and configurations; the CPU example is the maintained first-run workflow.

## Research context

See [Approximating Problems in Abstract Argumentation with Graph Convolutional Networks](https://www-users.york.ac.uk/peter.nightingale/aij-argumentation-2024.pdf), by Lars Malmqvist, Tangming Yuan and Peter Nightingale, for the research approach and experimental evaluation. A smoke run here does not reproduce those experiments.

Use [CITATION.cff](CITATION.cff) to cite this software, and cite the paper separately when discussing its findings.

## Data and validation

The demo runs without Git LFS. For the research corpus, install Git LFS and fetch the required `AFs/` paths; text files beginning with `version https://git-lfs.github.com/spec/v1` are pointers, not graph data. To keep an initial clone small, set `GIT_LFS_SKIP_SMUDGE=1` before cloning.

CI checks real CPU forward/backward execution, both import styles and device-transfer failure handling. The transfer helper preserves graph identity and keeps the current attribute if conversion fails; earlier successful transfers are not rolled back. Full historical training and GPU execution are separate reproduction tasks.

## Development

Run the tests above before opening a PR. For a bug report, include the smallest framework that reproduces it, the command, package versions and expected versus actual behavior. Keep benchmark changes accompanied by split definitions, seeds and run logs.

## Related projects and license

[AFGCN](https://github.com/lmlearning/AFGCN) · [ExplainableArgGCN](https://github.com/lmlearning/ExplainableArgGCN) · [AFSubsample](https://github.com/lmlearning/AFSubsample)

## License

See [LICENSE](LICENSE).
Code is available under the [MIT license](LICENSE).
41 changes: 41 additions & 0 deletions examples/gcn_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Fit the existing GCN to a four-argument illustrative framework on CPU."""
import json
import os
os.environ.setdefault("DGLBACKEND", "pytorch")

import dgl
import torch
import torch.nn.functional as F

from GraphLib.model import GCN


def run_demo():
torch.manual_seed(7)
torch.set_num_threads(1)
# a -> b -> c, plus isolated d. Grounded labels: a, c, d are accepted.
graph = dgl.add_self_loop(dgl.graph(([0, 1], [1, 2]), num_nodes=4))
features = torch.eye(4)
labels = torch.tensor([[1.0], [0.0], [1.0], [1.0]])
model = GCN(graph, in_feats=4, n_hidden=8, n_classes=1,
n_layers=1, activation=F.relu, dropout=0.0)
optimizer = torch.optim.Adam(model.parameters(), lr=0.03)
initial_loss = F.binary_cross_entropy_with_logits(model(features), labels).item()
for _ in range(40):
optimizer.zero_grad()
loss = F.binary_cross_entropy_with_logits(model(features), labels)
loss.backward()
optimizer.step()
model.eval()
with torch.no_grad():
logits = model(features)
final_loss = F.binary_cross_entropy_with_logits(logits, labels).item()
return {
"example": "illustrative training fit, not a held-out benchmark",
"arguments": 4, "attacks": 2, "logits_shape": list(logits.shape),
"initial_loss": round(initial_loss, 6), "final_loss": round(final_loss, 6),
}


if __name__ == "__main__":
print(json.dumps(run_demo(), indent=2))
7 changes: 7 additions & 0 deletions requirements-cpu.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# CPU demo/runtime, tested with Python 3.11 on Linux and Windows.
--extra-index-url https://download.pytorch.org/whl/cpu
torch==2.7.0+cpu
dgl==1.1.2
numpy==1.26.4
scipy==1.15.3
networkx==3.4.2
29 changes: 29 additions & 0 deletions tests/test_cpu_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import importlib
import subprocess
import sys
from pathlib import Path

import pytest

pytest.importorskip("torch")
pytest.importorskip("dgl")

from examples.gcn_demo import run_demo


def test_real_gcn_forward_and_training_step():
result = run_demo()
assert result["logits_shape"] == [4, 1]
assert 0 <= result["final_loss"] < result["initial_loss"]


@pytest.mark.parametrize("name", ["model", "util", "dglutil", "inference"])
def test_library_imports_from_repository_root(name):
assert importlib.import_module("GraphLib." + name)


def test_legacy_script_imports_still_work():
root = Path(__file__).resolve().parents[1]
result = subprocess.run([sys.executable, "-c", "import model, util, dglutil, inference"],
cwd=root / "GraphLib", capture_output=True, text=True)
assert result.returncode == 0, result.stderr
Loading