arg2p 0.19.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- arg2p/__init__.py +63 -0
- arg2p/__main__.py +49 -0
- arg2p/_jvm.py +145 -0
- arg2p/_version.py +2 -0
- arg2p/arg2p.py +271 -0
- arg2p/flags.py +224 -0
- arg2p/jars/Java-WebSocket-1.6.0.jar +0 -0
- arg2p/jars/annotations-13.0.jar +0 -0
- arg2p/jars/arg2p-jvm-0.19.0.jar +0 -0
- arg2p/jars/causality-solver-jvm-0.19.0.jar +0 -0
- arg2p/jars/core-jvm-0.19.0.jar +0 -0
- arg2p/jars/core-jvm-3.0.5.jar +0 -0
- arg2p/jars/dsl-core-jvm-3.0.5.jar +0 -0
- arg2p/jars/dsl-solve-jvm-3.0.5.jar +0 -0
- arg2p/jars/dsl-theory-jvm-3.0.5.jar +0 -0
- arg2p/jars/dsl-unify-jvm-3.0.5.jar +0 -0
- arg2p/jars/io-lib-jvm-3.0.5.jar +0 -0
- arg2p/jars/kotlin-reflect-2.4.21.jar +0 -0
- arg2p/jars/kotlin-stdlib-2.4.21.jar +0 -0
- arg2p/jars/kotlin-stdlib-jdk7-2.4.21.jar +0 -0
- arg2p/jars/kotlin-stdlib-jdk8-2.4.21.jar +0 -0
- arg2p/jars/kt-math-jvm-0.10.2.jar +0 -0
- arg2p/jars/okio-jvm-3.18.2.jar +0 -0
- arg2p/jars/parallel-solver-jvm-0.19.0.jar +0 -0
- arg2p/jars/parser-core-jvm-3.0.5.jar +0 -0
- arg2p/jars/parser-impl-jvm-3.0.5.jar +0 -0
- arg2p/jars/parser-theory-jvm-3.0.5.jar +0 -0
- arg2p/jars/slf4j-api-2.0.13.jar +0 -0
- arg2p/jars/solve-jvm-3.0.5.jar +0 -0
- arg2p/jars/theory-jvm-3.0.5.jar +0 -0
- arg2p/jars/unify-jvm-3.0.5.jar +0 -0
- arg2p/jars/utils-jvm-3.0.5.jar +0 -0
- arg2p/jre/bin/api-ms-win-core-console-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-console-l1-2-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-datetime-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-debug-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-errorhandling-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-fibers-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-fibers-l1-1-1.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-file-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-file-l1-2-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-file-l2-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-handle-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-heap-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-interlocked-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-kernel32-legacy-l1-1-1.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-libraryloader-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-localization-l1-2-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-memory-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-namedpipe-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-processenvironment-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-processthreads-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-processthreads-l1-1-1.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-profile-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-rtlsupport-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-string-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-synch-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-synch-l1-2-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-sysinfo-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-sysinfo-l1-2-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-timezone-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-core-util-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-conio-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-convert-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-environment-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-filesystem-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-heap-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-locale-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-math-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-multibyte-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-private-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-process-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-runtime-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-stdio-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-string-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-time-l1-1-0.dll +0 -0
- arg2p/jre/bin/api-ms-win-crt-utility-l1-1-0.dll +0 -0
- arg2p/jre/bin/java.dll +0 -0
- arg2p/jre/bin/java.exe +0 -0
- arg2p/jre/bin/javaw.exe +0 -0
- arg2p/jre/bin/jimage.dll +0 -0
- arg2p/jre/bin/jli.dll +0 -0
- arg2p/jre/bin/keytool.exe +0 -0
- arg2p/jre/bin/management.dll +0 -0
- arg2p/jre/bin/msvcp140.dll +0 -0
- arg2p/jre/bin/net.dll +0 -0
- arg2p/jre/bin/nio.dll +0 -0
- arg2p/jre/bin/server/jvm.dll +0 -0
- arg2p/jre/bin/syslookup.dll +0 -0
- arg2p/jre/bin/ucrtbase.dll +0 -0
- arg2p/jre/bin/vcruntime140.dll +0 -0
- arg2p/jre/bin/vcruntime140_1.dll +0 -0
- arg2p/jre/bin/verify.dll +0 -0
- arg2p/jre/bin/zip.dll +0 -0
- arg2p/jre/conf/jaxp.properties +180 -0
- arg2p/jre/conf/logging.properties +63 -0
- arg2p/jre/conf/net.properties +168 -0
- arg2p/jre/conf/security/java.policy +46 -0
- arg2p/jre/conf/security/java.security +1650 -0
- arg2p/jre/conf/security/policy/README.txt +54 -0
- arg2p/jre/conf/security/policy/limited/default_US_export.policy +6 -0
- arg2p/jre/conf/security/policy/limited/default_local.policy +14 -0
- arg2p/jre/conf/security/policy/limited/exempt_local.policy +13 -0
- arg2p/jre/conf/security/policy/unlimited/default_US_export.policy +6 -0
- arg2p/jre/conf/security/policy/unlimited/default_local.policy +6 -0
- arg2p/jre/legal/java.base/ADDITIONAL_LICENSE_INFO +37 -0
- arg2p/jre/legal/java.base/ASSEMBLY_EXCEPTION +27 -0
- arg2p/jre/legal/java.base/LICENSE +347 -0
- arg2p/jre/legal/java.base/aes.md +36 -0
- arg2p/jre/legal/java.base/asm.md +36 -0
- arg2p/jre/legal/java.base/c-libutl.md +35 -0
- arg2p/jre/legal/java.base/cldr.md +109 -0
- arg2p/jre/legal/java.base/icu.md +518 -0
- arg2p/jre/legal/java.base/public_suffix.md +399 -0
- arg2p/jre/legal/java.base/siphash.md +150 -0
- arg2p/jre/legal/java.base/unicode.md +103 -0
- arg2p/jre/legal/java.base/wepoll.md +34 -0
- arg2p/jre/legal/java.base/zlib.md +27 -0
- arg2p/jre/legal/java.logging/ADDITIONAL_LICENSE_INFO +1 -0
- arg2p/jre/legal/java.logging/ASSEMBLY_EXCEPTION +1 -0
- arg2p/jre/legal/java.logging/LICENSE +1 -0
- arg2p/jre/legal/java.management/ADDITIONAL_LICENSE_INFO +1 -0
- arg2p/jre/legal/java.management/ASSEMBLY_EXCEPTION +1 -0
- arg2p/jre/legal/java.management/LICENSE +1 -0
- arg2p/jre/legal/java.naming/ADDITIONAL_LICENSE_INFO +1 -0
- arg2p/jre/legal/java.naming/ASSEMBLY_EXCEPTION +1 -0
- arg2p/jre/legal/java.naming/LICENSE +1 -0
- arg2p/jre/legal/java.net.http/ADDITIONAL_LICENSE_INFO +1 -0
- arg2p/jre/legal/java.net.http/ASSEMBLY_EXCEPTION +1 -0
- arg2p/jre/legal/java.net.http/LICENSE +1 -0
- arg2p/jre/legal/java.security.sasl/ADDITIONAL_LICENSE_INFO +1 -0
- arg2p/jre/legal/java.security.sasl/ASSEMBLY_EXCEPTION +1 -0
- arg2p/jre/legal/java.security.sasl/LICENSE +1 -0
- arg2p/jre/legal/java.xml/ADDITIONAL_LICENSE_INFO +1 -0
- arg2p/jre/legal/java.xml/ASSEMBLY_EXCEPTION +1 -0
- arg2p/jre/legal/java.xml/LICENSE +1 -0
- arg2p/jre/legal/java.xml/bcel.md +219 -0
- arg2p/jre/legal/java.xml/dom.md +77 -0
- arg2p/jre/legal/java.xml/jcup.md +31 -0
- arg2p/jre/legal/java.xml/xalan.md +255 -0
- arg2p/jre/legal/java.xml/xerces.md +229 -0
- arg2p/jre/legal/jdk.crypto.ec/ADDITIONAL_LICENSE_INFO +1 -0
- arg2p/jre/legal/jdk.crypto.ec/ASSEMBLY_EXCEPTION +1 -0
- arg2p/jre/legal/jdk.crypto.ec/LICENSE +1 -0
- arg2p/jre/legal/jdk.unsupported/ADDITIONAL_LICENSE_INFO +1 -0
- arg2p/jre/legal/jdk.unsupported/ASSEMBLY_EXCEPTION +1 -0
- arg2p/jre/legal/jdk.unsupported/LICENSE +1 -0
- arg2p/jre/lib/classlist +1503 -0
- arg2p/jre/lib/jrt-fs.jar +0 -0
- arg2p/jre/lib/jvm.cfg +2 -0
- arg2p/jre/lib/jvm.lib +0 -0
- arg2p/jre/lib/modules +0 -0
- arg2p/jre/lib/security/blocked.certs +39 -0
- arg2p/jre/lib/security/cacerts +0 -0
- arg2p/jre/lib/security/default.policy +251 -0
- arg2p/jre/lib/security/public_suffix_list.dat +0 -0
- arg2p/jre/lib/tzdb.dat +0 -0
- arg2p/jre/lib/tzmappings +506 -0
- arg2p/jre/release +2 -0
- arg2p/model.py +102 -0
- arg2p/parallel.py +160 -0
- arg2p/py.typed +0 -0
- arg2p/values.py +59 -0
- arg2p-0.19.0.dist-info/METADATA +61 -0
- arg2p-0.19.0.dist-info/RECORD +168 -0
- arg2p-0.19.0.dist-info/WHEEL +5 -0
- arg2p-0.19.0.dist-info/entry_points.txt +2 -0
- arg2p-0.19.0.dist-info/top_level.txt +1 -0
arg2p/__init__.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Arg2P from Python: structured argumentation in Prolog (ASPIC+, ABA, abstract frameworks, ...), the library of the JVM
|
|
3
|
+
run through JPype, on the Java runtime the package bundles.
|
|
4
|
+
|
|
5
|
+
>>> from arg2p import Arg2p
|
|
6
|
+
>>> Arg2p.of("r1 : [] => a.\nr2 : [] => -a.\nsup(r1, r2).").answer("a").in_statements
|
|
7
|
+
['a']
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .arg2p import Answer, Arg2p, Arg2pError, Builder, Causality, Solution, Solutions
|
|
11
|
+
from .flags import (
|
|
12
|
+
ConflictModel,
|
|
13
|
+
Flags,
|
|
14
|
+
GraphBuilder,
|
|
15
|
+
GraphExtension,
|
|
16
|
+
GraphLanguage,
|
|
17
|
+
OrderingComparator,
|
|
18
|
+
OrderingPrinciple,
|
|
19
|
+
Profile,
|
|
20
|
+
Semantics,
|
|
21
|
+
StatementLabelling,
|
|
22
|
+
)
|
|
23
|
+
from .model import Argument, Attack, Graph, LabelledArgument, Support
|
|
24
|
+
from .parallel import EvaluationResponse, LocalCluster, Response, ThreadedCluster
|
|
25
|
+
from .values import Struct, Value, Var
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
from ._version import __version__
|
|
29
|
+
except ImportError: # a package built without Gradle
|
|
30
|
+
__version__ = "0.0.0"
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"Answer",
|
|
34
|
+
"Arg2p",
|
|
35
|
+
"Arg2pError",
|
|
36
|
+
"Argument",
|
|
37
|
+
"Attack",
|
|
38
|
+
"Builder",
|
|
39
|
+
"Causality",
|
|
40
|
+
"ConflictModel",
|
|
41
|
+
"EvaluationResponse",
|
|
42
|
+
"Flags",
|
|
43
|
+
"Graph",
|
|
44
|
+
"GraphBuilder",
|
|
45
|
+
"GraphExtension",
|
|
46
|
+
"GraphLanguage",
|
|
47
|
+
"LabelledArgument",
|
|
48
|
+
"LocalCluster",
|
|
49
|
+
"OrderingComparator",
|
|
50
|
+
"OrderingPrinciple",
|
|
51
|
+
"Profile",
|
|
52
|
+
"Response",
|
|
53
|
+
"Semantics",
|
|
54
|
+
"Solution",
|
|
55
|
+
"Solutions",
|
|
56
|
+
"StatementLabelling",
|
|
57
|
+
"Struct",
|
|
58
|
+
"Support",
|
|
59
|
+
"ThreadedCluster",
|
|
60
|
+
"Value",
|
|
61
|
+
"Var",
|
|
62
|
+
"__version__",
|
|
63
|
+
]
|
arg2p/__main__.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""The labels of the statements of a theory, from the command line: python -m arg2p theory.pl [-q query] ..."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import sys
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from .arg2p import Arg2p, Arg2pError
|
|
10
|
+
from .flags import Flags, Profile, Semantics
|
|
11
|
+
from .values import text
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main(argv: Optional[list[str]] = None) -> int:
|
|
15
|
+
parser = argparse.ArgumentParser(prog="arg2p", description="Evaluates a theory of arg2p.")
|
|
16
|
+
parser.add_argument("theory", help="the file of the theory (- for the standard input)")
|
|
17
|
+
parser.add_argument("-q", "--query", action="append", help="a statement to evaluate (all of them by default)")
|
|
18
|
+
parser.add_argument("-p", "--profile", choices=[it.value for it in Profile], help="the profile of the theory")
|
|
19
|
+
parser.add_argument("-s", "--semantics", choices=[it.value for it in Semantics], help="the semantics")
|
|
20
|
+
arguments = parser.parse_args(argv)
|
|
21
|
+
theory = sys.stdin.read() if arguments.theory == "-" else open(arguments.theory, encoding="utf-8").read()
|
|
22
|
+
flags = Flags.defaults()
|
|
23
|
+
if arguments.profile:
|
|
24
|
+
flags.graph_build_mode(Profile(arguments.profile))
|
|
25
|
+
if arguments.semantics:
|
|
26
|
+
flags.argument_labelling_mode(Semantics(arguments.semantics))
|
|
27
|
+
try:
|
|
28
|
+
arg2p = Arg2p.of(theory, flags)
|
|
29
|
+
if arguments.query:
|
|
30
|
+
for query in arguments.query:
|
|
31
|
+
answer = arg2p.answer(query)
|
|
32
|
+
print(
|
|
33
|
+
f"{query}: in {text(answer.in_statements)}, out {text(answer.out_statements)}, "
|
|
34
|
+
f"und {text(answer.und_statements)}"
|
|
35
|
+
)
|
|
36
|
+
else:
|
|
37
|
+
for index, graph in enumerate(arg2p.graphs()):
|
|
38
|
+
if index:
|
|
39
|
+
print()
|
|
40
|
+
for label in ("in", "out", "und"):
|
|
41
|
+
print(f"{label}: {', '.join(sorted(graph.conclusions(label)))}")
|
|
42
|
+
except Arg2pError as error:
|
|
43
|
+
print(f"arg2p: {error}", file=sys.stderr)
|
|
44
|
+
return 1
|
|
45
|
+
return 0
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
sys.exit(main())
|
arg2p/_jvm.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""The JVM running arg2p: started once, at the first use, with the jars of the package, on the Java runtime it
|
|
2
|
+
bundles (that of the system, for a package without one)."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import glob
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import threading
|
|
10
|
+
from typing import Any, Callable, TypeVar
|
|
11
|
+
|
|
12
|
+
import jpype
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T")
|
|
15
|
+
|
|
16
|
+
_lock = threading.Lock()
|
|
17
|
+
|
|
18
|
+
#: The jars of the package, copied there by ``./gradlew :python:pythonJars``
|
|
19
|
+
JARS = os.path.join(os.path.dirname(__file__), "jars")
|
|
20
|
+
|
|
21
|
+
#: The Java runtime the package bundles, made there by ``./gradlew :python:pythonRuntime``
|
|
22
|
+
RUNTIME = os.path.join(os.path.dirname(__file__), "jre")
|
|
23
|
+
|
|
24
|
+
#: The stack of the threads of the JVM: resolution goes deep (the tests of arg2p run with the same)
|
|
25
|
+
STACK = os.environ.get("ARG2P_STACK", "512m")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def classpath() -> list[str]:
|
|
29
|
+
"""The jars of arg2p: those of ``ARG2P_CLASSPATH`` if set, those of the package otherwise."""
|
|
30
|
+
stated = os.environ.get("ARG2P_CLASSPATH")
|
|
31
|
+
if stated:
|
|
32
|
+
return stated.split(os.pathsep)
|
|
33
|
+
jars = sorted(glob.glob(os.path.join(JARS, "*.jar")))
|
|
34
|
+
if not jars:
|
|
35
|
+
raise RuntimeError(
|
|
36
|
+
"No jar of arg2p in " + JARS + ": copy them with ./gradlew :python:pythonJars, "
|
|
37
|
+
"or set ARG2P_CLASSPATH"
|
|
38
|
+
)
|
|
39
|
+
return jars
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def jvm_path() -> str:
|
|
43
|
+
"""
|
|
44
|
+
The library of the JVM: that of ``ARG2P_JVM`` if set, of the runtime the package bundles if it does, of the system
|
|
45
|
+
otherwise (JAVA_HOME, or where JPype finds one).
|
|
46
|
+
"""
|
|
47
|
+
stated = os.environ.get("ARG2P_JVM")
|
|
48
|
+
if stated:
|
|
49
|
+
return stated
|
|
50
|
+
library = {"win32": ("bin", "server", "jvm.dll"), "darwin": ("lib", "server", "libjvm.dylib")}.get(
|
|
51
|
+
sys.platform, ("lib", "server", "libjvm.so")
|
|
52
|
+
)
|
|
53
|
+
bundled = os.path.join(RUNTIME, *library)
|
|
54
|
+
return bundled if os.path.exists(bundled) else jpype.getDefaultJVMPath()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def start() -> None:
|
|
58
|
+
"""Starts the JVM, unless it runs already (started by another library: the jars of arg2p must be on its path)."""
|
|
59
|
+
with _lock:
|
|
60
|
+
if not jpype.isJVMStarted():
|
|
61
|
+
jpype.startJVM(
|
|
62
|
+
jvm_path(), f"-Xss{STACK}", "-Dslf4j.internal.verbosity=ERROR", classpath=classpath(), convertStrings=True
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def jclass(name: str) -> Any:
|
|
67
|
+
"""The Java class [name], the JVM started."""
|
|
68
|
+
start()
|
|
69
|
+
return jpype.JClass(name)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@jpype.JImplements("java.lang.Runnable", deferred=True)
|
|
73
|
+
class _Task:
|
|
74
|
+
def __init__(self, function: Callable[[], Any]) -> None:
|
|
75
|
+
self.function = function
|
|
76
|
+
self.value: Any = None
|
|
77
|
+
self.error: BaseException | None = None
|
|
78
|
+
|
|
79
|
+
@jpype.JOverride
|
|
80
|
+
def run(self) -> None:
|
|
81
|
+
try:
|
|
82
|
+
self.value = self.function()
|
|
83
|
+
except BaseException as error: # noqa: BLE001 - raised again by the caller
|
|
84
|
+
self.error = error
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@jpype.JImplements("java.util.concurrent.ThreadFactory", deferred=True)
|
|
88
|
+
class _Threads:
|
|
89
|
+
@jpype.JOverride
|
|
90
|
+
def newThread(self, runnable: Any) -> Any:
|
|
91
|
+
# daemons, not to hold the JVM when Python exits; their stack is the one of -Xss (see STACK)
|
|
92
|
+
thread = jpype.JClass("java.lang.Thread")(runnable, _THREAD)
|
|
93
|
+
thread.setDaemon(True)
|
|
94
|
+
return thread
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
_THREAD = "arg2p"
|
|
98
|
+
_pool: Any = None
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _threads() -> Any:
|
|
102
|
+
"""The threads running arg2p, made as calls need them and kept for the next ones (a minute idle)."""
|
|
103
|
+
global _pool
|
|
104
|
+
with _lock:
|
|
105
|
+
if _pool is None:
|
|
106
|
+
_pool = jpype.JClass("java.util.concurrent.Executors").newCachedThreadPool(_Threads())
|
|
107
|
+
return _pool
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def run(function: Callable[[], T]) -> T:
|
|
111
|
+
"""The result of [function], run on a thread of the JVM, whose stack resolution needs (see STACK)."""
|
|
112
|
+
start()
|
|
113
|
+
if str(jpype.JClass("java.lang.Thread").currentThread().getName()) == _THREAD:
|
|
114
|
+
return function() # already on one
|
|
115
|
+
task = _Task(function)
|
|
116
|
+
_threads().submit(task).get()
|
|
117
|
+
if task.error is not None:
|
|
118
|
+
raise task.error
|
|
119
|
+
return task.value
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@jpype.JImplements("kotlin.jvm.functions.Function1", deferred=True)
|
|
123
|
+
class _Function:
|
|
124
|
+
def __init__(self, function: Callable[[Any], Any]) -> None:
|
|
125
|
+
self.function = function
|
|
126
|
+
|
|
127
|
+
@jpype.JOverride
|
|
128
|
+
def invoke(self, value: Any) -> Any:
|
|
129
|
+
return self.function(value)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def function1(function: Callable[[Any], Any]) -> Any:
|
|
133
|
+
"""[function] as a Kotlin function of one argument returning Unit."""
|
|
134
|
+
unit = jclass("kotlin.Unit").INSTANCE
|
|
135
|
+
|
|
136
|
+
def invoke(value: Any) -> Any:
|
|
137
|
+
function(value)
|
|
138
|
+
return unit
|
|
139
|
+
|
|
140
|
+
return _Function(invoke)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def jarray(name: str, values: list[Any]) -> Any:
|
|
144
|
+
"""A Java array of the class [name], of [values]."""
|
|
145
|
+
return jpype.JArray(jclass(name))(values)
|
arg2p/_version.py
ADDED
arg2p/arg2p.py
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"""A solver of arg2p: its answers, graphs and solutions, and the causality tests on its theory."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any, Callable, Iterator, Optional
|
|
7
|
+
|
|
8
|
+
import jpype
|
|
9
|
+
|
|
10
|
+
from . import _jvm
|
|
11
|
+
from .flags import Flags
|
|
12
|
+
from .model import Graph, graph_from_jvm
|
|
13
|
+
from .values import Value, from_jvm
|
|
14
|
+
|
|
15
|
+
_API = "it.unibo.tuprolog.argumentation"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Arg2pError(Exception):
|
|
19
|
+
"""An evaluation halted by an error: a theory its profile refuses, a goal that cannot be parsed, ..."""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def call(function: Callable[[], Any]) -> Any:
|
|
23
|
+
"""The result of [function], run on a thread of the JVM, an exception of arg2p raised as an Arg2pError."""
|
|
24
|
+
|
|
25
|
+
def guarded() -> Any:
|
|
26
|
+
try:
|
|
27
|
+
return function()
|
|
28
|
+
except jpype.JException as error:
|
|
29
|
+
if error.getClass().getName() == f"{_API}.Arg2pException":
|
|
30
|
+
raise Arg2pError(str(error.getMessage())) from None
|
|
31
|
+
raise
|
|
32
|
+
|
|
33
|
+
return _jvm.run(guarded)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass(frozen=True)
|
|
37
|
+
class Answer:
|
|
38
|
+
"""The statements for a query labelled in, out and und (see Arg2p.answer)."""
|
|
39
|
+
|
|
40
|
+
in_statements: list[Value] = field(default_factory=list)
|
|
41
|
+
out_statements: list[Value] = field(default_factory=list)
|
|
42
|
+
und_statements: list[Value] = field(default_factory=list)
|
|
43
|
+
# the answer of the library of the JVM, for label
|
|
44
|
+
_answer: Any = field(default=None, compare=False, repr=False)
|
|
45
|
+
|
|
46
|
+
def label(self, statement: str) -> Optional[str]:
|
|
47
|
+
"""The label of [statement], Prolog text: in, out or und, None for a statement the query did not label."""
|
|
48
|
+
if self._answer is None:
|
|
49
|
+
raise ValueError("Not the answer of a solver")
|
|
50
|
+
label = call(lambda: self._answer.label(statement))
|
|
51
|
+
return None if label is None else str(label)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Solution:
|
|
55
|
+
"""A solution of a goal: yes, no or halt (an error), with the values a yes solution binds to its variables."""
|
|
56
|
+
|
|
57
|
+
def __init__(self, solution: Any) -> None:
|
|
58
|
+
self._solution = solution
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def is_yes(self) -> bool:
|
|
62
|
+
return bool(self._solution.isYes())
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def is_no(self) -> bool:
|
|
66
|
+
return bool(self._solution.isNo())
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def is_halt(self) -> bool:
|
|
70
|
+
return bool(self._solution.isHalt())
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def query(self) -> str:
|
|
74
|
+
"""The goal, as a yes solution solves it (its variables bound), otherwise as it was asked, as Prolog text."""
|
|
75
|
+
return str(self._solution.getQuery())
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def error(self) -> Optional[str]:
|
|
79
|
+
"""The error of a halt solution."""
|
|
80
|
+
error = self._solution.getError()
|
|
81
|
+
return None if error is None else str(error)
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def variables(self) -> list[str]:
|
|
85
|
+
"""The variables of the goal a yes solution binds."""
|
|
86
|
+
return [str(name) for name in self._solution.getVariables()]
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def bindings(self) -> dict[str, Value]:
|
|
90
|
+
"""The values a yes solution binds to the variables of the goal, by their names."""
|
|
91
|
+
return {str(entry.getKey()): from_jvm(entry.getValue()) for entry in self._solution.getBindings().entrySet()}
|
|
92
|
+
|
|
93
|
+
def value(self, name: str) -> Optional[Value]:
|
|
94
|
+
"""The value a yes solution binds to the variable of the goal named [name]."""
|
|
95
|
+
value = self._solution.value(name)
|
|
96
|
+
return None if value is None else from_jvm(value)
|
|
97
|
+
|
|
98
|
+
def text(self, name: str) -> Optional[str]:
|
|
99
|
+
"""The value a yes solution binds to the variable of the goal named [name], as Prolog text."""
|
|
100
|
+
written = self._solution.text(name)
|
|
101
|
+
return None if written is None else str(written)
|
|
102
|
+
|
|
103
|
+
def __repr__(self) -> str:
|
|
104
|
+
return str(self._solution.toString())
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class Solutions:
|
|
108
|
+
"""The solutions of a goal, computed one at a time as they are asked for: with has_next and next, or iterated."""
|
|
109
|
+
|
|
110
|
+
def __init__(self, solutions: Any) -> None:
|
|
111
|
+
self._solutions = solutions
|
|
112
|
+
|
|
113
|
+
def has_next(self) -> bool:
|
|
114
|
+
return bool(_jvm.run(self._solutions.hasNext))
|
|
115
|
+
|
|
116
|
+
def next(self) -> Solution:
|
|
117
|
+
return Solution(_jvm.run(self._solutions.next))
|
|
118
|
+
|
|
119
|
+
def to_list(self, limit: Optional[int] = None) -> list[Solution]:
|
|
120
|
+
"""The solutions left, at most [limit] of them."""
|
|
121
|
+
return [Solution(it) for it in _jvm.run(lambda: self._solutions.toList(2**31 - 1 if limit is None else limit))]
|
|
122
|
+
|
|
123
|
+
def __iter__(self) -> Iterator[Solution]:
|
|
124
|
+
return self
|
|
125
|
+
|
|
126
|
+
def __next__(self) -> Solution:
|
|
127
|
+
# the next solution, if there is one, in a single call
|
|
128
|
+
found = _jvm.run(lambda: self._solutions.next() if self._solutions.hasNext() else None)
|
|
129
|
+
if found is None:
|
|
130
|
+
raise StopIteration
|
|
131
|
+
return Solution(found)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class Causality:
|
|
135
|
+
"""
|
|
136
|
+
Whether a statement of the theory of a solver causes another, on the grounded labelling of the theory and of its
|
|
137
|
+
interventions: the NESS test, as published (Pisano, Prakken, Sartor, Liepina; ICAIL 2025) and revised, and the
|
|
138
|
+
but-for test. The statements are Prolog text; an intervention is a list of statements.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
def __init__(self, causality: Any) -> None:
|
|
142
|
+
self._causality = causality
|
|
143
|
+
|
|
144
|
+
def ness(self, cause: str, effect: str) -> Optional[Value]:
|
|
145
|
+
"""Whether [cause] is a NESS cause of [effect] (the revised condition): the intervention, None if it is not."""
|
|
146
|
+
return _optional(call(lambda: self._causality.ness(cause, effect)))
|
|
147
|
+
|
|
148
|
+
def ness_original(self, cause: str, effect: str) -> Optional[Value]:
|
|
149
|
+
"""Whether [cause] is a NESS cause of [effect] as published: the intervention, None if it is not."""
|
|
150
|
+
return _optional(call(lambda: self._causality.nessOriginal(cause, effect)))
|
|
151
|
+
|
|
152
|
+
def ness_intervention(self, intervention: str, effect: str) -> bool:
|
|
153
|
+
"""Whether [intervention], a list of statements, meets the revised NESS condition for [effect]."""
|
|
154
|
+
return bool(call(lambda: self._causality.nessIntervention(intervention, effect)))
|
|
155
|
+
|
|
156
|
+
def ness_original_intervention(self, intervention: str, effect: str) -> bool:
|
|
157
|
+
"""Whether [intervention], a list of statements, meets the NESS condition for [effect] as published."""
|
|
158
|
+
return bool(call(lambda: self._causality.nessOriginalIntervention(intervention, effect)))
|
|
159
|
+
|
|
160
|
+
def but_for(self, cause: str, effect: str) -> bool:
|
|
161
|
+
"""Whether [cause] is a but-for cause of [effect]."""
|
|
162
|
+
return bool(call(lambda: self._causality.butFor(cause, effect)))
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _optional(value: Any) -> Optional[Value]:
|
|
166
|
+
return None if value is None else from_jvm(value)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class Arg2p:
|
|
170
|
+
"""
|
|
171
|
+
A solver of arg2p for a theory, as Prolog text, with its flags: it answers queries (answer), gives the graph of
|
|
172
|
+
each labelling (graphs), solves Prolog goals (solve) and tests causality (causality).
|
|
173
|
+
|
|
174
|
+
>>> Arg2p.of("r1 : [] => a.\\nr2 : [] => -a.\\nsup(r1, r2).").answer("a").in_statements
|
|
175
|
+
['a']
|
|
176
|
+
|
|
177
|
+
The context of the solver keeps a branch for every stage of a resolution, numbered from 0: active_branch is the
|
|
178
|
+
last one, graph_at the graph of any of them, and context_facts what a branch stores.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
def __init__(self, arg2p: Any) -> None:
|
|
182
|
+
self._arg2p = arg2p
|
|
183
|
+
self.causality = Causality(arg2p.getCausality())
|
|
184
|
+
|
|
185
|
+
@staticmethod
|
|
186
|
+
def of(theory: str = "", flags: Optional[Flags] = None) -> Arg2p:
|
|
187
|
+
"""A solver of arg2p for [theory], Prolog text, with [flags] (Flags.defaults() otherwise)."""
|
|
188
|
+
return Arg2p.builder().theory(theory).flags(flags or Flags.defaults()).build()
|
|
189
|
+
|
|
190
|
+
@staticmethod
|
|
191
|
+
def builder() -> Builder:
|
|
192
|
+
"""A solver of arg2p, as it is described."""
|
|
193
|
+
return Builder()
|
|
194
|
+
|
|
195
|
+
@staticmethod
|
|
196
|
+
def version() -> str:
|
|
197
|
+
"""The version of arg2p, the released one for a release."""
|
|
198
|
+
return str(_jvm.jclass(f"{_API}.Arg2p").version())
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def theory(self) -> str:
|
|
202
|
+
"""The theory, as Prolog text."""
|
|
203
|
+
return str(self._arg2p.getTheory())
|
|
204
|
+
|
|
205
|
+
def answer(self, query: str) -> Answer:
|
|
206
|
+
"""The statements for [query], Prolog text, labelled in, out and und (raises Arg2pError if it halts)."""
|
|
207
|
+
answer = call(lambda: self._arg2p.answer(query))
|
|
208
|
+
return Answer(
|
|
209
|
+
[from_jvm(it) for it in answer.getInStatements()],
|
|
210
|
+
[from_jvm(it) for it in answer.getOutStatements()],
|
|
211
|
+
[from_jvm(it) for it in answer.getUndStatements()],
|
|
212
|
+
answer,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
def graphs(self) -> list[Graph]:
|
|
216
|
+
"""The graph of each labelling of the theory: several for a semantics with several (preferred, stable, ...)."""
|
|
217
|
+
return call(lambda: [graph_from_jvm(graph) for graph in self._arg2p.graphs()])
|
|
218
|
+
|
|
219
|
+
def graph(self) -> Graph:
|
|
220
|
+
"""The graph of the last resolution: the one of its last stage."""
|
|
221
|
+
return call(lambda: graph_from_jvm(self._arg2p.graph()))
|
|
222
|
+
|
|
223
|
+
def graph_at(self, branch: int) -> Graph:
|
|
224
|
+
"""The graph of the context branch [branch]."""
|
|
225
|
+
return call(lambda: graph_from_jvm(self._arg2p.graphAt(branch)))
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def active_branch(self) -> int:
|
|
229
|
+
"""The context branch of the last stage of the last resolution."""
|
|
230
|
+
return int(call(self._arg2p.getActiveBranch))
|
|
231
|
+
|
|
232
|
+
def solve(self, goal: str) -> Solutions:
|
|
233
|
+
"""The solutions of [goal], Prolog text, computed one at a time as they are asked for."""
|
|
234
|
+
return Solutions(call(lambda: self._arg2p.solve(goal)))
|
|
235
|
+
|
|
236
|
+
def context_facts(self, branch: int, goal: str) -> Solutions:
|
|
237
|
+
"""What the context branch [branch] stores matching [goal], Prolog text: the solutions of context_check/2."""
|
|
238
|
+
return Solutions(call(lambda: self._arg2p.contextFacts(branch, goal)))
|
|
239
|
+
|
|
240
|
+
def add(self, theory: str) -> None:
|
|
241
|
+
"""Adds the clauses of [theory], Prolog text, to the theory."""
|
|
242
|
+
call(lambda: self._arg2p.add(theory))
|
|
243
|
+
|
|
244
|
+
def load(self, theory: str) -> None:
|
|
245
|
+
"""Replaces the theory with [theory], Prolog text."""
|
|
246
|
+
call(lambda: self._arg2p.load(theory))
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class Builder:
|
|
250
|
+
"""A solver of arg2p, as it is described: its theory, its flags, and where what it prints goes."""
|
|
251
|
+
|
|
252
|
+
def __init__(self) -> None:
|
|
253
|
+
self._builder = _jvm.jclass(f"{_API}.Arg2p").builder()
|
|
254
|
+
|
|
255
|
+
def theory(self, theory: str) -> Builder:
|
|
256
|
+
"""The theory, as Prolog text."""
|
|
257
|
+
self._builder.theory(theory)
|
|
258
|
+
return self
|
|
259
|
+
|
|
260
|
+
def flags(self, flags: Flags) -> Builder:
|
|
261
|
+
"""The flags (Flags.defaults() otherwise)."""
|
|
262
|
+
self._builder.flags(flags.jvm())
|
|
263
|
+
return self
|
|
264
|
+
|
|
265
|
+
def output(self, consumer: Callable[[str], Any]) -> Builder:
|
|
266
|
+
"""The function receiving what the solver prints (the standard output otherwise)."""
|
|
267
|
+
self._builder.output(_jvm.function1(lambda printed: consumer(str(printed))))
|
|
268
|
+
return self
|
|
269
|
+
|
|
270
|
+
def build(self) -> Arg2p:
|
|
271
|
+
return Arg2p(call(self._builder.build))
|