<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta>
      <journal-title-group>
        <journal-title>CILC</journal-title>
      </journal-title-group>
    </journal-meta>
    <article-meta>
      <title-group>
        <article-title>Logic, Leaves, and Labels: Visualizing SELinux Trees with ASP Chef</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Mario Alviano</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Pietro Macrì</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>DeMaCS, University of Calabria</institution>
          ,
          <addr-line>87036 Rende (CS)</addr-line>
          ,
          <country country="IT">Italy</country>
        </aff>
      </contrib-group>
      <pub-date>
        <year>2025</year>
      </pub-date>
      <volume>40</volume>
      <fpage>25</fpage>
      <lpage>27</lpage>
      <abstract>
        <p>Visualizing security policies is no easy task, especially when they come from the labyrinthine world of SELinux. In this article, we explore how ASP Chef, a logic programming platform for structured reasoning and templated output, can be enhanced with tree visualization capabilities via the integration of the ApexTree framework. By introducing a new tree/2 functor within the Mustache-based templating system of ASP Chef, we enable logicbased generation of structured tree data, seamlessly translatable into the JSON format of ApexTree. As a concrete and security-relevant use case, we focus on SELinux policy rules, which define access control through 4-tuples of subjects, objects, classes, and permissions. We demonstrate how to extract, filter, and interpret meaningful fragments of these policies using ASP and Lua scripting within ASP Chef. Nodes and links are programmatically generated to construct readable trees, enabling intuitive inspection of policy paths from user roles to allowed actions. We further enhance interpretability by integrating LLMs into the workflow, automatically generating natural language descriptions of the policy logic. The result is an expressive and interactive visualization of SELinux permissions.</p>
      </abstract>
      <kwd-group>
        <kwd>eol&gt;Answer Set Programming</kwd>
        <kwd>ASP Chef</kwd>
        <kwd>policy visualization</kwd>
        <kwd>security policies</kwd>
      </kwd-group>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>1. Introduction</title>
      <p>
        Answer Set Programming (ASP) is a well-established declarative paradigm for solving complex
combinatorial problems, rooted in nonmonotonic logic and stable model semantics [
        <xref ref-type="bibr" rid="ref1 ref2 ref3 ref4 ref5">1, 2, 3, 4, 5</xref>
        ]. Thanks
to its expressiveness and robust reasoning capabilities, ASP has been successfully employed across
domains such as security policy analysis [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ] and configuration [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ]. Despite the growing availability
of eficient solvers like clingo [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ], integrating ASP with user-friendly visual representations remains
a practical challenge, particularly in domains that involve rich hierarchical structures. To bridge this
gap, ASP Chef [
        <xref ref-type="bibr" rid="ref10 ref9">9, 10</xref>
        ] was introduced as a web-based environment for building interactive pipelines
(recipes) over ASP computations. ASP Chef enables users to ground, solve, filter, and visualize answer
sets through a browser-based interface that supports both logic-based reasoning and web-ready content
generation. In particular, recent developments have introduced template-driven output generation via
Mustache templates [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ], allowing ASP users to declaratively render structured outputs in formats such
as JSON, Markdown, or CSV, without the need for glue code or external scripts.
      </p>
      <p>Among the visualization libraries now supported in ASP Chef is ApexTree (https://apexcharts.com/
apextree/), a modern and lightweight JavaScript framework designed for rendering interactive tree
structures from JSON-based specifications. ApexTree excels in presenting hierarchical data in a clear
and dynamic way, supporting features such as collapsible branches, customizable labels, and animated
transitions. These characteristics make it particularly attractive for exploring logical relationships and
nested dependencies that naturally arise in domains such as security policies, data hierarchies, and
structured documents. To enable seamless integration with ApexTree, ASP Chef introduces a novel
tree/2 functor within its Mustache-based templating system. This functor plays a central role in the
declarative specification of tree structures from within ASP programs. The first argument of tree/2
serves as a unique identifier for the tree, allowing multiple trees to be defined and distinguished within
the same template, while the second argument captures the structural or configurational aspects of the
tree. Specifically, it supports:
• Node declarations, represented as pairs of node identifiers and string labels, allowing each node
to be uniquely referenced and visually rendered with meaningful content;
• Edge definitions, encoded as pairs of parent and child node identifiers, capturing the hierarchical
topology of the tree;
• Root specification, where a node is designated as the starting point for rendering;
• Layout customization, i.e., how subtrees are inserted within node labels;
• Visual separators, which define how nodes or branches are delimited in the rendered output.</p>
      <p>When a template is applied to an interpretation, ASP Chef automatically collects all instances of
tree/2 from the answers to the Mustache queries in the template, interprets them based on their type
(node, edge, root, layout), and compiles a valid ApexTree-compatible JSON object (or a diferent object
based on the provided elements). This process is fully encapsulated within the templating engine, and
requires no imperative programming, no JavaScript coding, and no external transformation scripts. The
user writes logic rules to define tree components as ASP facts, and the system takes care of generating
the visualization-ready data structure. This integration exemplifies the design philosophy of ASP
Chef: to empower users to express both logical content and presentation logic declaratively, without
sacrificing modularity or expressiveness. It allows developers, researchers, and students to construct
rich, navigable tree visualizations directly from answer sets, essentially turning abstract logic programs
into concrete, interpretable structures. This is especially valuable in domains like security analysis,
where hierarchical relationships (e.g., from user roles to permissions) are key to understanding system
behavior, and where visual exploration can provide critical insights that textual output alone might
obscure.</p>
      <p>This paper also presents a case study demonstrating the use of the new tree visualization capabilities
in the domain of SELinux policy analysis (a particularly intricate and security-critical context where
reasoning over hierarchical structures is both natural and necessary). SELinux (Security-Enhanced
Linux) policies govern access control by specifying which subjects (e.g., user or process types) are
permitted to interact with which objects (e.g., files, sockets, services), and in what ways. These rules
are typically expressed as 4-tuples in the form</p>
      <p>allow subject object :class permission;
where:
• subject denotes the initiating entity, such as a process domain;
• object refers to the target entity being accessed;
• class defines the category of the object (e.g., file, system, service);
• permission specifies the allowed operation (e.g., read, write, execute).</p>
      <p>While compact in syntax, these policies form dense, interconnected structures that are dificult to
interpret without tool support, especially when multiple permissions apply across layered abstractions.
To address this, we leverage ASP Chef to declaratively filter, structure, and visualize selected portions
of an SELinux policy. The process begins with the specification of one or more subject–object pairs of
interest. ASP rules are then used to traverse the space of policy rules, extracting the corresponding
classes and permissions to construct a multilevel representation of access chains. This access graph
is encoded using ASP facts that define the hierarchical relationships among policy elements. These
facts are then interpreted through the tree/2 functor to produce a structured representation of the
policy segment as a tree, where the root corresponds to the initiating subject, and branches represent
the propagation of access rights through object–class–permission links. The resulting tree is rendered
in-browser via ApexTree, allowing users to interactively explore access chains, collapse or expand
branches, and trace the permissions available to specific roles within the system.</p>
      <p>To further improve interpretability, we augment this visualization pipeline with support for Large
Language Models (LLMs). Using the Mustache-based templating system of ASP Chef, we can generate
prompts for LLMs by automatically converting filtered policy facts into natural language sentences
or SELinux-style statements (e.g., allow sysadm_t init_t:system reboot;). These statements are
passed to the LLM, which returns human-readable summaries explaining the intent and implications
of the selected rules. This natural language output is rendered using Markdown components within
ASP Chef, providing a narrative interpretation alongside the interactive tree view. Together, these
components ofer a comprehensive, declarative, and human-friendly interface for exploring SELinux
policies, transforming abstract rule sets into intuitive structures and readable explanations. This case
study highlights how ASP Chef can be used not only as a logic programming platform, but also as a
bridge between formal reasoning and interactive security analysis.</p>
      <p>All in all, this work showcases how the integration of logic programming, templated content
generation, and interactive web visualization can make complex security configurations more transparent and
accessible. The declarative nature of the approach allows users to reason about policy subsets, construct
trees, and generate human-readable explanations, all within a single, self-contained environment.</p>
    </sec>
    <sec id="sec-2">
      <title>2. Background</title>
      <sec id="sec-2-1">
        <title>2.1. SELinux Policies</title>
        <p>Security-Enhanced Linux (SELinux) is a security architecture integrated into the Linux kernel that
provides mandatory access control (MAC) mechanisms to restrict the actions that processes can perform
on system resources. Unlike discretionary access control (DAC), where permissions are granted at the
discretion of resource owners, SELinux enforces centrally defined policies that apply system-wide and
cannot be overridden by individual users or applications. At the heart of SELinux lies a label-based
policy model. Every subject (e.g., process) and object (e.g., file, socket, device) in the system is associated
with a security context, typically composed of a user, a role, and a type. Among these, the type field
plays a crucial role in access control decisions and is the primary focus of SELinux policies. Policy rules
specify which subject types can access which object types, and under what conditions.</p>
        <p>The core policy primitive in SELinux is the allow rule, which specifies explicit permissions granted
by the security policy. These rules are written in the following form:</p>
        <p>allow subject object :class permission;
Each such rule authorizes a process running under the specified subject type to perform the designated
permission on a resource labeled with the given object type and class. The elements of the rule can be
interpreted as follows:
• subject refers to the type associated with the process attempting the operation. In SELinux,
this type (also called a domain) encapsulates the security identity of the process. For example,
sysadm_t identifies privileged processes associated with system administration tasks.
• object is the type assigned to the target resource, such as a file, socket, or process. These types
classify system resources according to their intended usage or sensitivity. For instance, var_log_t
denotes log files under /var/log, while init_t may represent the system initialization process.
• class specifies the category of the object being accessed. This determines the set of valid
permissions that can be applied. Common classes include file, dir (directory), unix_stream_socket,
and process. Each class has its own permission vocabulary (e.g., read, write, connectto).
• permission defines the specific action that is allowed on the object. Permissions vary depending on
the class of the object: for files, typical permissions include read, write, execute, getattr, and
open; for sockets, they may include connectto, sendto, and recvfrom; for processes, permissions
such as sigkill and ptrace are available.</p>
        <p>Together, these four components define a fine-grained access control matrix that governs the interactions
between labeled subjects and objects on the system. Each rule is a single entry in this matrix, permitting
a specific interaction between a domain and a resource. Because SELinux uses a default-deny model
(i.e., denying all actions not explicitly allowed) these allow rules are essential to enabling the functional
behavior of the system.</p>
        <p>For example, the rule:</p>
        <p>allow sysadm_t var_log_t:file read;
permits processes running in the sysadm_t domain to perform the read operation on any resource
labeled with type var_log_t and class file (i.e., to read system log files).</p>
        <p>Because SELinux policies can span thousands of such rules, they form a dense and hierarchical
structure that can be dificult to interpret and audit manually. For instance, a single subject might
be allowed to access dozens of object types, each with multiple classes and permissions. Moreover,
alternative permission paths may exist to accomplish the same high-level operation, increasing the
cognitive load on administrators and auditors.</p>
        <p>Example 1. Let us suppose an administrator (subject: sysadm_t) wants to view the contents of system
logs (object: var_log_t), which are typically stored in files under /var/log. Depending on how the
logs are accessed, two alternative permission paths may apply:
(a) Direct File Access:
allow sysadm_t var_log_t:file read;
allow sysadm_t var_log_t:file open;
allow sysadm_t var_log_t:file getattr;
This path corresponds to using tools like cat, less, or tail to directly open and read log files
from the filesystem (e.g., cat /var/log/messages).
(b) Indirect Access via Journalctl:
allow sysadm_t systemd_logind_t:dbus dbus;
allow sysadm_t journalctl_t:unix_stream_socket connectto;
allow sysadm_t journal_data_t:file read;
allow sysadm_t journalctl_exec_t:file use;
This path models access via a service like journalctl (e.g., journalctl -xe), where logs are
obtained indirectly through inter-process communication, and require diferent permissions than
raw file access.</p>
        <p>Both plans achieve the same functional goal (i.e., viewing logs) but they operate at diferent abstraction
levels (raw file vs. high-level service), involve diferent SELinux object types, and rely on diferent
communication mechanisms (filesystem vs. IPC). ■</p>
      </sec>
      <sec id="sec-2-2">
        <title>2.2. Answer Set Programming</title>
        <p>
          Answer Set Programming (ASP) is a declarative programming paradigm centered on the representation
of knowledge and reasoning over complex domains. An ASP program consists of a finite set of rules,
each expressing how certain facts (known as atoms) can be derived from other conditions. A typical
rule includes a head, which denotes a possible conclusion (either a single atom or a disjunction/choice
among atoms), and a body, which specifies the conditions under which the head holds. These conditions
are formed from a conjunction of literals, possibly including aggregates, comparisons, or arithmetic
expressions. Formally, an ASP program Π gives rise to a set of answer sets (or stable models), each
representing a self-consistent collection of atoms that satisfies all rules of Π under a specific stability
condition [
          <xref ref-type="bibr" rid="ref12">12</xref>
          ]. This condition guarantees that each true atom is supported (i.e., justified by the program)
and that no smaller subset of atoms forms a valid model. A program may admit zero, one, or multiple
answer sets, depending on how non-determinism and constraints are used. This allows ASP to naturally
encode and solve combinatorial search problems and explore alternative solutions.
        </p>
        <p>To define the desired output of a program, ASP includes output directives, i.e., the #show directive.
These serve to restrict the visible portion of each answer set, efectively projecting it onto a user-specified
view. A show directive has the general form:</p>
        <p>#show p() : conjunctive_query.
where p() is a term pattern, and conjunctive_query is a condition to obtain terms from the processed
interpretation. This feature is crucial in practice, as ASP answer sets can be large and contain many
auxiliary atoms used for intermediate derivations. Through #show directives, users can isolate the
atoms that represent the meaningful outcomes of a computation, especially useful when such outcomes
are to be rendered, visualized, or exported.</p>
        <p>The expressiveness of ASP and its ability to handle incomplete knowledge, default reasoning, and
constraints make it particularly well-suited for domains such as security policy analysis, where one
must reason over what is permitted, forbidden, or undefined under a given specification. To illustrate
the basics of ASP, consider the following example.</p>
        <p>Example 2 (Continuing Example 1). The scenario is modeled in ASP as follows:
% Subject attempting the operation
subject("sysadm_t").
% Policies granted to the subject
policy("sysadm_t", "journal_data_t", "file", read).
policy("sysadm_t", "journalctl_t", "unix_stream_socket", connectto).
policy("sysadm_t", "journalctl_exec_t", "file", use).
policy("sysadm_t", "systemd_logind_t", "dbus", communicate).
policy("sysadm_t", "var_log_t", "file", read).
policy("sysadm_t", "var_log_t", "file", open).
policy("sysadm_t", "var_log_t", "file", getattr).
% many more facts like these
% Permission paths: each represents a complete way to view logs
path(a, "var_log_t", "file", read).
path(a, "var_log_t", "file", open).
path(a, "var_log_t", "file", getattr).
path(b, "systemd_logind_t", "dbus", communicate).
path(b, "journalctl_t", "unix_stream_socket", connectto).
path(b, "journal_data_t", "file", read).
path(b, "journalctl_exec_t", "file", use).
% Choose exactly one path to validate
{selected_path(P) : path(P, _, _, _)} = 1.
% Derive required permissions from selected path
required(O,C,P) :- selected_path(Path), path(Path,O,C,P).
% Check which permissions are granted
granted(O,C,P) :- subject(S), policy(S,O,C,P).
% Valid path only if all required permissions are granted
:- required(O,C,P), not granted(O,C,P).
% Output the path and matched permissions
#show subject/1.
#show required/3.
#show selected_path/1.
#show granted/3.</p>
        <p>If all permissions for a path are available, the program will return an answer set with the selected path
and its granted permissions (in this case, either plan a or b). If multiple paths are valid (e.g., if both sets
are granted), the ASP solver may return multiple answer sets, one per valid path. If no path is fully
supported, the program yields no answer set, indicating that the subject cannot view the logs.</p>
        <p>The above program can be extended with the following weak constraint
:∼ granted(O,C,P). [1@1, O, C, P]
to prefer shorter paths (e.g., path a with 3 permissions vs. path b with 4). Alternatively,
to prefer paths involving less objects (within their classes), regardless of the number of permissions on
the involved objects. ■</p>
        <p>
          For further details on the syntax and semantics of ASP, including advanced rule types, aggregates,
and standard directives, we refer the reader to the ASP-Core-2 standard [
          <xref ref-type="bibr" rid="ref13">13</xref>
          ], which defines the common
specification adopted by modern solvers and development environments.
        </p>
      </sec>
      <sec id="sec-2-3">
        <title>2.3. ASP Chef</title>
        <p>An operation  is a function receiving in input a sequence of interpretations and producing in output a
sequence of interpretations. Operations may produce side outputs (e.g., a graph visualization) and accept
parameters to influence their behavior. An ingredient is an instantiation of a parameterized operation
with side output. A recipe is a tuple of the form (encode, Ingredients, decode), where Ingredients is
a (finite) sequence 1⟨1⟩, . . . , ⟨⟩ of ingredients, and encode and decode are Boolean values.
If encode is true, the input of the recipe is mapped to [[__base64__("")]], where  = Base64 (in )
(i.e., the Base64–encoding of the input string in ). After that, the ingredients are applied one after
another. Finally, if decode is true, every occurrence of __base64__(s) is replaced with (the ASCII string
associated with) Base64 − 1(). Among the operations supported by ASP Chef there are Encode⟨, ⟩ to
extend every interpretation in input with the atom (""), where  = Base64 (); Search Models⟨Π, ⟩
to replace every interpretation  in input with up to  answer sets of Π ∪ {(). | () ∈ }; Show⟨Π⟩
to replace every interpretation  in input with the projected answer set Π ∪ {(). | () ∈ } (where
Π comprises only #show directives. Optimize⟨Π, ⟩ to replace every interpretation  in input with up
to  optimal answer sets of Π ∪ {(). | () ∈ }.</p>
        <p>Example 3. The problem from Example 2 can be addressed in ASP Chef by a recipe comprising a single
Search Models⟨Π, 1⟩, where Π is the program in Example 2 (we will use Optimize if the weak constraint
is included in Π). Alternatively, a recipe separating computational and presentational aspects would
move the #show directives in a second ingredient Show. ■</p>
        <p>
          Several operations in ASP Chef support expansion of Mustache templates [
          <xref ref-type="bibr" rid="ref11">11</xref>
          ]; among them, there are
Expand Mustache Queries, @vis.js/Network (to visualize graphs), Tabulator (to arrange data in interactive
tables), and ApexCharts (to produce diferent kinds of charts). A Mustache template comprises queries
of the form {{ Π }}, where Π is an ASP program with #show directives—alternatively, {{= () :
conjunctive_query }} for {{ #show () : conjunctive_query. }}. Intuitively, queries are expanded
using one projected answer set of Π ∪ {(). | () ∈ }, where  is the interpretation on which the
template is applied on. Separators can be specified using the predicates separator/1 (for tuples of
terms), and term_separator/1 (for terms within a tuple). The varadic predicate show/* extends a
shown tuple of terms (its first argument) with additional arguments that enable repeating tuples in
output and can be used as sorting keys (using predicate sort/1). Moreover, Mustache queries can use
@string_format(format, . . .) to format a string using the given format string and arguments, and
lfoating-point numbers are supported with the format real("NUMBER"). Format strings can also be
written as (multiline) f-strings of the form {{f". . ."}}, using data interpolation ${expression:format }
to render expression according to the given format .
        </p>
        <p>Example 4. Recipes from Example 3 can be further extended by including ingredients to visualize input
and computed solution graphically. To this aim, the following Mustache template can be combined with
@vis.js/Network to obtain the graph shown in Figure 1:
Note that Mustache queries are used to define nodes and links in the graph starting from facts in the
computed answer set. A recipe addressing the selection problem and producing the visualization shown
in Figure 1 is available at https://asp-chef.alviano.net/s/CILC2025/selinux-network. ■</p>
      </sec>
    </sec>
    <sec id="sec-3">
      <title>3. Adding Trees to Mustache Templates</title>
      <p>To enable the declarative construction of tree-like data structures in ASP Chef, we introduce the functor
tree(TreeID, Term), where TreeID is a symbolic identifier for the tree instance, and Term encodes
either a structural element (i.e., root, node or link) or a configuration directive (i.e., children_on or
separator). All tree/2 atoms belonging to the same TreeID are collected during template expansion
and processed together to produce a hierarchical tree representation. The processing involves three key
steps, described below, which are applied to every Mustache query within the expanded template.
Collection of Facts. All answers of the form tree(TreeID, Term) are extracted. For each TreeID,
we collect:
• Node declarations: node(ID, Label) to assign a string label to node ID;
• Link declarations: link(Parent, Child) to define directed edges from Parent to Child;
• Root declaration: root(ID) to define the starting node for the tree;
• Rendering format: children_on(Placeholder) to specify how children are included in the node
label (optional);
• Separator: separator(SEP) to specify the delimiter used to join multiple children (optional).
Recursive Tree Construction. The tree is constructed starting from the declared root node, say
id_0. The construction proceeds recursively as follows: Let label_0 be the string associated with node
id_0—i.e, the answer includes node(id_0, label_0). Let c_1, . . ., c_n be the identifiers of all children
of id_0—i.e., the answer includes link(id_0, c_i), for i = 1..n. The string representation of the
root node is constructed by embedding the recursively rendered children into the placeholder specified
by children_on(Placeholder). If no children_on directive is provided, the default placeholder is
{CHILDREN}. Similarly, the children of a node are joined using the value of the separator directive,
which defaults to “, ” (comma followed by space). Each child c_i is recursively processed using the
same procedure.</p>
      <p>Example 5. Consider the following set of ASP facts:
expr(link(1,2)).
expr(link(1,5)).
expr(link(2,3)).
expr(link(2,4)).
expr(link(5,6)).</p>
      <p>expr(link(5,7)).</p>
      <p>They represent the expression (3 + 5) × (2 − 1) (infix notation) using Polish notation (prefix notation):
x + 3 5 - 2 1. We can easily obtain the Polish representation with the following Mustache template:
{{= tree(mytree, Term) : expr(Term) }}
Note that we are using @ as a placeholder for children, and the empty string as separator. A recipe is
available at https://asp-chef.alviano.net/s/CILC2025/polish-notation. ■
Integration with ApexTree. To support interactive tree visualizations within ASP Chef, we
integrated the ApexTree framework, a lightweight JavaScript library for rendering tree structures from
JSON data. ApexTree expects a configuration object that includes both display settings and a hierarchical
data structure representing the tree. The core configuration object passed to ApexTree typically follows
this structure (simplified for illustration):
{ "data": {
"name": "Root Label",
"children": [
{ "name": "Child A", "children": [...] },
{ "name": "Child B", "children": [] } ]
} }
Each node in the tree is represented by a JSON object with at least a "name" field (string label), and
optionally a "children" array listing its subtrees. ASP Chef allows users to define the data field of this
object declaratively by writing logic programs that emit facts of the form tree(TreeID, Term). During
template expansion, ASP Chef processes all such facts and assembles them into the corresponding
JSON tree as described in the previous paragraphs. A typical Mustache template to configure ApexTree
within ASP Chef may look like the following:
{ data: {{
#show tree(my_tree, root(Node)) : tree(Node,_), not tree(_,Node).
#show tree(my_tree, node(Node, @string_format("{id: '%s', name: '%s',
children: [{CHILDREN}] }", Node, Name))) : node(Node,Name).</p>
      <p>#show tree(my_tree, link(A,B)) : tree(A,B).
}},
options: ... }
Above, the tree is retrieved from the interpretation in input, specifically from the binary predicate tree
representing parent-child edges. Note that the string representation of nodes is obtained using format
strings, and children are placed as expected by ApexTree.</p>
      <p>Example 6 (Continuing Example 5). An interactive view on the arithmetic expression is obtained with
the following Mustache template:
{ data: {{
#show tree(my_tree, root(Node)) : expr(root(Node)).
#show tree(my_tree, node(Node, @string_format("{id: '%s', name: '%s',
children: [{CHILDREN}] }", Node, @string_sub(Name,1,-3)))) :
expr(node(Node,Name)).</p>
      <p>#show tree(my_tree, link(A,B)) : expr(link(A,B)).
}},
options: {
width: 800, height: 700, siblingSpacing: 30,
direction: 'left', borderWidth: 2, enableExpandCollapse: true,
fontSize: '20px', fontFamily: 'sans-serif' }
}
The JSON object resulting by the application of the above template is interpreted by the new ApexTree
operation of ASP Chef to obtain the visualization shown in Figure 2. ■</p>
    </sec>
    <sec id="sec-4">
      <title>4. Application: Visualizing SELinux Policies</title>
      <p>To demonstrate the practical utility of the tree/2 functor and ApexTree integration, we
developed a complete ASP Chef recipe (https://asp-chef.alviano.net/s/selinux/visualizing-policies#pit0500/
asp-chef-short-links) aimed at visualizing SELinux policies as tree structures. The input to this recipe
consists of the set of standard policy rules available in SELinux-enabled systems (such as those found in
a typical Fedora distribution). Each rule is modeled as a fact of the form</p>
      <p>policy(S, O, C, P).
representing an allow rule where subject type S is granted permission P on object type O and class C.
The recipe unfolds in several declarative steps, illustrated in the following.</p>
      <p>Filtering the Policy Space. The first ingredient filters the policy set to retain only those rules that
involve a selected pair of subject and object types. This is achieved using a Search Models operation:
{ select(S,O) : subject(S), object(O) } = 1.</p>
      <p>needed_policy(S,O,C,P) :- select(S,O), policy(S,O,C,P).</p>
      <p>Users can choose from predefined facts of the form subject("sysadm_t") and object("init_t") to
explore the permissions of interest. This filtering focuses the analysis and visualization on a manageable
subset of the overall policy.</p>
      <p>Assigning Unique Node Identifiers. To encode the policy structure as a tree, each relevant entity
(subject, object, class, permission) must be uniquely identified. This is handled via a Lua @-term script:
ids = {}
counter = 2
function get_id(name, parent)
key = tostring(parent) .. "_" .. tostring(name)
if ids[key] == nil then
ids[key] = counter
counter = counter + 1
end
end
return ids[key]
This function ensures that each node receives a consistent and unique identifier, even when the same
name appears under diferent parents.</p>
      <p>Defining Tree Nodes. A second Search Models ingredient constructs the hierarchical structure by
associating each node with its parent:
node(root, none, Subject) :- needed_policy(Subject, _, _, _).
node(ID, Subject, Object) :- needed_policy(Subject, Object, _, _),</p>
      <p>ID = @get_id(Object, Subject).
node(ID, Object, Class) :- needed_policy(_, Object, Class, _),</p>
      <p>ID = @get_id(Class, Object).
node(ID, Class, Permission) :- needed_policy(_, _, Class, Permission),</p>
      <p>ID = @get_id(Permission, Class).</p>
      <p>The tree starts at the subject, which is labeled as the root node. Subsequent nodes represent object
types, classes, and permissions, forming a logical path through the policy rule.</p>
      <p>Establishing Tree Links. Using the derived nodes, the edges of the tree are defined with:
tree(root, Node) :- node(root, none, Subject), node(Node, Subject, Object).
tree(Node1, Node2) :- node(Node1, Subject, Object), node(Node2, Object, Class),
node(root, none, Subject).
tree(Node1, Node2) :- node(Node1, Object, Class), node(Node2, Class, Permission).
These rules connect nodes in a layered fashion: subject → object → class → permission.
Selecting Relevant Output. To keep the output concise, only node declarations and tree links are
shown using a Select Predicates operation, which is essentially equivalent to a Show ingredient with the
following directives:
#show needed_policy/4.
#show node/3.</p>
      <p>#show tree/2.</p>
      <p>Encoding the Tree for ApexTree. Finally, the tree is rendered using an Encode operation with a
Mustache template. The template is similar to the one reported in Example 6, and produces a JSON tree
structure ready to be consumed by ApexTree. The result is an interactive, navigable tree that shows how
a subject type (e.g., sysadm_t) can traverse the policy space to reach various permissions over an object
type (e.g., init_t). This hierarchical view enables users to explore SELinux policies in an intuitive
way. We refer Figure 3 for an example comparing the permissions of two subjects, namely users with
the roles sysadm_t and dbadm_t, on the object mysqld_t: We observe that sysadm_t is granted fewer
permissions than dbadm_t, reflecting the core principle of SELinux that even administrative domains
such as the traditional root user do not possess unrestricted authority by default.</p>
      <sec id="sec-4-1">
        <title>4.1. Enhancing Interpretability with LLMs</title>
        <p>SELinux policies define granular access control rules that regulate interactions among processes, files,
sockets, and other system entities. Due to their sheer size and complexity, these policies are often
dificult to inspect manually, especially when attempting to understand the precise set of permissions
granted to a specific subject in a given security context. While the tree visualizations described earlier
provide a structural view of access relationships, they do not directly explain the implications of the
policies in natural language. To bridge this gap, we integrate Large Language Models (LLMs) into ASP
Chef recipes to generate human-readable explanations of selected policy fragments.</p>
        <p>The approach involves constructing messages dynamically using ASP rules. We specify a system
prompt to instruct the LLM on its role:</p>
        <p>You are an expert in SELinux policy management and your task is to create a detailed text
starting from a specific set of policies.</p>
        <p>Then, using @string_format function and Mustache templating, we construct the LLM input based on
the filtered policy data:
message(user(@string_format( "allow %s %s:%s %s;", S,O,C,P)) )
:</p>
        <p>needed_policy(S,O,C,P).</p>
        <p>Here, needed_policy/4 captures the subset of policies relevant to the subject–object pair selected
by the user. For the application discussed in this section, and the permissions shown in Figure 3, the
rendering of the template is the following:
allow sysadm_t mysqld_t:unix_stream_socket connectto;
allow dbadm_t mysqld_t:unix_stream_socket connectto;
allow dbadm_t mysqld_t:process signull;
allow dbadm_t mysqld_t:process sigchld;
allow dbadm_t mysqld_t:process sigstop;
allow dbadm_t mysqld_t:process getattr;
allow dbadm_t mysqld_t:process sigkill;
allow dbadm_t mysqld_t:process ptrace;
The resulting messages (i.e., the fixed system message, and the user message generated by expanding
the Mustache template) are sent to the LLM using the @LLMs/Chat Completion operation of ASP
Chef, and the response is rendered as Markdown within the recipe interface.</p>
        <p>This integration enables users to obtain high-level summaries of the selected policy logic (e.g., what
permissions a process in the sysadm_t domain has when interacting with mysqld_t processes) without
requiring deep knowledge of SELinux syntax or semantics. An excerpt is shown in Figure 4. It also
facilitates explanation-based auditing and helps bridge the gap between low-level rule inspection and
practical security understanding.</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>5. Related Work</title>
      <p>
        Eforts to improve the interpretability and usability of ASP have long emphasized the need for
visualization tools capable of rendering the structure and meaning of answer sets. Early systems such
as ASPViz [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ], IDPD3 [
        <xref ref-type="bibr" rid="ref15">15</xref>
        ], and Kara [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ] pioneered the idea of encoding visual elements directly
as ASP facts, which could then be interpreted by external renderers. These tools enabled users to
describe shapes, layouts, colors, and animations in a logic-based format, bridging symbolic reasoning
and graphical output.
      </p>
      <p>
        More recent tools such as clingraph [
        <xref ref-type="bibr" rid="ref17">17</xref>
        ] and ASPECT [
        <xref ref-type="bibr" rid="ref18">18</xref>
        ] have continued this trend, ofering
highlevel declarative languages to describe visualizations of ASP outputs. While these systems significantly
enhance expressiveness and produce exportable graphics, they typically rely on auxiliary rendering
engines and may require complex local installations.
      </p>
      <p>
        ASP Chef [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ] introduced its first visualization mechanism in [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ] through the Graph ingredient,
enabling users to generate network-like visualizations directly from ASP recipes. Inspired by ASPViz
and its successors, this feature allowed users to express graph structures as logic programs and produce
visual feedback without imperative code.
      </p>
      <p>In contrast to these systems, recent developments in ASP Chef adopt a template-based approach to
visualization, grounded in the use of Mustache templates. Rather than embedding visualization logic in
the ASP program, the user defines the output format declaratively, and the template engine fills in the
data extracted from the answer sets. This model-driven strategy allows ASP Chef to interface directly
with modern browser-based visualization libraries, including:
• @vis.js/Network for dynamic graph rendering,
• Tabulator for interactive data tables,
• ApexCharts for plotting time series, bar charts, and more,
• and now, ApexTree for hierarchical tree structures.</p>
      <p>The work presented in this paper builds on this foundation by introducing a new tree/2 functor,
which enables users to define tree-structured data declaratively using ASP. By embedding structural and
layout information in logic programs, users can automatically generate interactive tree visualizations
without writing any JavaScript or low-level JSON. This stands in contrast to earlier systems that either
required explicit visual encoding logic or used tightly coupled visual interpreters.</p>
      <p>
        To the best of our knowledge, no previous ASP visualization system supports hierarchical tree
rendering through templated JSON generation. Furthermore, the application of these visualizations to
SELinux policy exploration is novel. Prior work has addressed logic-based access control analysis [
        <xref ref-type="bibr" rid="ref6 ref7">6, 7</xref>
        ],
but none have leveraged ASP to construct interactive, layered visualizations of security policies, let
alone integrated them with LLMs for natural language explanation.
      </p>
    </sec>
    <sec id="sec-6">
      <title>6. Conclusion</title>
      <p>We introduced a new extension to ASP Chef for declarative tree visualization, centered around the
tree/2 functor and Mustache-based JSON templating. This approach enables ASP programs to produce
structured tree data, rendered interactively using the ApexTree framework. Our solution supports
browser-native visualizations without requiring manual scripting, and we demonstrated its efectiveness
through a case study on SELinux policy analysis. By representing access control rules as tree structures,
we made complex policies easier to explore and interpret. In summary, this work enhances ASP Chef
with:
• Declarative tree construction via tree/2;
• Templated JSON generation through Mustache;
• Native integration with ApexTree for visualization;
• Application to real-world hierarchical domains like SELinux.</p>
      <p>These contributions make ASP outputs more interpretable and lay the groundwork for future integrations
with richer interactive tools.</p>
    </sec>
    <sec id="sec-7">
      <title>Acknowledgments</title>
      <p>This work was supported by the Italian Ministry of University and Research (MUR) under PRIN project
PRODE “Probabilistic declarative process mining”, CUP H53D23003420006, under PNRR project FAIR
“Future AI Research”, CUP H23C22000860006, under PNRR project Tech4You “Technologies for climate
change adaptation and quality of life improvement”, CUP H23C22000370006, and under PNRR project
SERICS “SEcurity and RIghts in the CyberSpace”, CUP H73C22000880001; by the Italian Ministry of
Health (MSAL) under POS projects CAL.HUB.RIA (CUP H53C22000800006) and RADIOAMICA (CUP
H53C22000650006); by the Italian Ministry of Enterprises and Made in Italy under project STROKE 5.0
(CUP B29J23000430005); under PN RIC project ASVIN “Assistente Virtuale Intelligente di Negozio” (CUP
B29J24000200005); and by the LAIA lab (part of the SILA labs). Mario Alviano is member of Gruppo
Nazionale Calcolo Scientifico-Istituto Nazionale di Alta Matematica (GNCS-INdAM).</p>
    </sec>
    <sec id="sec-8">
      <title>Declaration on Generative AI</title>
      <p>During the preparation of this work, the authors used ChatGPT-4o for grammar and spelling check.
After using this tool, the authors reviewed and edited the content as needed and take full responsibility
for the publication’s content.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <given-names>G.</given-names>
            <surname>Brewka</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Eiter</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Truszczynski</surname>
          </string-name>
          ,
          <article-title>Answer set programming at a glance</article-title>
          ,
          <source>Commun. ACM</source>
          <volume>54</volume>
          (
          <year>2011</year>
          )
          <fpage>92</fpage>
          -
          <lpage>103</lpage>
          . doi:
          <volume>10</volume>
          .1145/2043174.2043195.
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>E.</given-names>
            <surname>Erdem</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Gelfond</surname>
          </string-name>
          ,
          <string-name>
            <given-names>N.</given-names>
            <surname>Leone</surname>
          </string-name>
          ,
          <article-title>Applications of answer set programming</article-title>
          ,
          <source>AI Mag</source>
          .
          <volume>37</volume>
          (
          <year>2016</year>
          )
          <fpage>53</fpage>
          -
          <lpage>68</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <given-names>V.</given-names>
            <surname>Lifschitz</surname>
          </string-name>
          , Answer Set Programming, Springer,
          <year>2019</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <given-names>R.</given-names>
            <surname>Kaminski</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Romero</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Schaub</surname>
          </string-name>
          ,
          <string-name>
            <given-names>P.</given-names>
            <surname>Wanko</surname>
          </string-name>
          ,
          <article-title>How to build your own asp-based system?!</article-title>
          ,
          <string-name>
            <given-names>Theory</given-names>
            <surname>Pract</surname>
          </string-name>
          . Log. Program.
          <volume>23</volume>
          (
          <year>2023</year>
          )
          <fpage>299</fpage>
          -
          <lpage>361</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <given-names>M.</given-names>
            <surname>Alviano</surname>
          </string-name>
          ,
          <string-name>
            <given-names>C.</given-names>
            <surname>Dodaro</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Fiorentino</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Previti</surname>
          </string-name>
          ,
          <string-name>
            <given-names>F.</given-names>
            <surname>Ricca</surname>
          </string-name>
          ,
          <article-title>ASP and subset minimality: Enumeration, cautious reasoning and muses</article-title>
          ,
          <source>Artif. Intell</source>
          .
          <volume>320</volume>
          (
          <year>2023</year>
          )
          <fpage>103931</fpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <given-names>S.</given-names>
            <surname>Sartoli</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A. S.</given-names>
            <surname>Namin</surname>
          </string-name>
          ,
          <article-title>Modeling adaptive access control policies using answer set programming</article-title>
          ,
          <source>J. Inf. Secur. Appl</source>
          .
          <volume>44</volume>
          (
          <year>2019</year>
          )
          <fpage>49</fpage>
          -
          <lpage>63</lpage>
          . URL: https://doi.org/10.1016/j.jisa.
          <year>2018</year>
          .
          <volume>10</volume>
          .007. doi:
          <volume>10</volume>
          .1016/J. JISA.
          <year>2018</year>
          .
          <volume>10</volume>
          .007.
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <given-names>J.</given-names>
            <surname>Hu</surname>
          </string-name>
          ,
          <string-name>
            <surname>K. M. Khan</surname>
            ,
            <given-names>Y.</given-names>
          </string-name>
          <string-name>
            <surname>Bai</surname>
            ,
            <given-names>Y. Zhang,</given-names>
          </string-name>
          <article-title>Constraint-enhanced role engineering via answer set programming</article-title>
          , in: H. Y. Youm, Y. Won (Eds.),
          <source>7th ACM Symposium on Information, Compuer and Communications Security, ASIACCS '12</source>
          , Seoul, Korea, May 2-
          <issue>4</issue>
          ,
          <year>2012</year>
          , ACM,
          <year>2012</year>
          , pp.
          <fpage>73</fpage>
          -
          <lpage>74</lpage>
          . URL: https://doi.org/10.1145/2414456.2414499. doi:
          <volume>10</volume>
          .1145/2414456.2414499.
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <given-names>M.</given-names>
            <surname>Gebser</surname>
          </string-name>
          ,
          <string-name>
            <given-names>R.</given-names>
            <surname>Kaminski</surname>
          </string-name>
          , B. Kaufmann, T. Schaub,
          <article-title>Multi-shot ASP solving with clingo</article-title>
          ,
          <source>Theory Pract. Log. Program</source>
          .
          <volume>19</volume>
          (
          <year>2019</year>
          )
          <fpage>27</fpage>
          -
          <lpage>82</lpage>
          . doi:
          <volume>10</volume>
          .1017/S1471068418000054.
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <given-names>M.</given-names>
            <surname>Alviano</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            <surname>Cirimele</surname>
          </string-name>
          ,
          <string-name>
            <given-names>L. A.</given-names>
            <surname>Rodriguez</surname>
          </string-name>
          <string-name>
            <surname>Reiners</surname>
          </string-name>
          ,
          <article-title>Introducing ASP recipes and ASP Chef</article-title>
          , in: ICLP Workshops, volume
          <volume>3437</volume>
          <source>of CEUR Workshop Proceedings, CEUR-WS.org</source>
          ,
          <year>2023</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <given-names>M.</given-names>
            <surname>Alviano</surname>
          </string-name>
          ,
          <string-name>
            <given-names>L. A.</given-names>
            <surname>Rodriguez</surname>
          </string-name>
          <string-name>
            <surname>Reiners</surname>
          </string-name>
          ,
          <article-title>ASP chef: Draw and expand</article-title>
          , in: P. Marquis,
          <string-name>
            <given-names>M.</given-names>
            <surname>Ortiz</surname>
          </string-name>
          , M. Pagnucco (Eds.),
          <source>Proceedings of the 21st International Conference on Principles of Knowledge Representation and Reasoning</source>
          , KR 2024, Hanoi,
          <source>Vietnam. November 2-8</source>
          ,
          <year>2024</year>
          ,
          <year>2024</year>
          . URL: https: //doi.org/10.24963/kr.2024/68. doi:
          <volume>10</volume>
          .24963/KR.
          <year>2024</year>
          /68.
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          [11]
          <string-name>
            <given-names>M.</given-names>
            <surname>Alviano</surname>
          </string-name>
          ,
          <string-name>
            <given-names>W.</given-names>
            <surname>Faber</surname>
          </string-name>
          ,
          <string-name>
            <given-names>L. A.</given-names>
            <surname>Rodriguez</surname>
          </string-name>
          <string-name>
            <surname>Reiners</surname>
          </string-name>
          , ASP Chef grows Mustache to look better,
          <year>2025</year>
          . URL: https://arxiv.org/abs/2505.24537. arXiv:
          <volume>2505</volume>
          .
          <fpage>24537</fpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          [12]
          <string-name>
            <given-names>M.</given-names>
            <surname>Gelfond</surname>
          </string-name>
          ,
          <string-name>
            <given-names>V.</given-names>
            <surname>Lifschitz</surname>
          </string-name>
          ,
          <article-title>Logic programs with classical negation</article-title>
          , in: D.
          <string-name>
            <surname>Warren</surname>
          </string-name>
          , P. Szeredi (Eds.),
          <source>Logic Programming: Proc. of the Seventh International Conference</source>
          ,
          <year>1990</year>
          , pp.
          <fpage>579</fpage>
          -
          <lpage>597</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          [13]
          <string-name>
            <given-names>F.</given-names>
            <surname>Calimeri</surname>
          </string-name>
          ,
          <string-name>
            <given-names>W.</given-names>
            <surname>Faber</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Gebser</surname>
          </string-name>
          , G. Ianni,
          <string-name>
            <given-names>R.</given-names>
            <surname>Kaminski</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Krennwallner</surname>
          </string-name>
          ,
          <string-name>
            <given-names>N.</given-names>
            <surname>Leone</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Maratea</surname>
          </string-name>
          ,
          <string-name>
            <given-names>F.</given-names>
            <surname>Ricca</surname>
          </string-name>
          , T. Schaub,
          <article-title>ASP-Core-2 input language format</article-title>
          ,
          <source>Theory Pract. Log. Program</source>
          .
          <volume>20</volume>
          (
          <year>2020</year>
          )
          <fpage>294</fpage>
          -
          <lpage>309</lpage>
          . URL: https://doi.org/10.1017/S1471068419000450. doi:
          <volume>10</volume>
          .1017/S1471068419000450.
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          [14]
          <string-name>
            <given-names>O.</given-names>
            <surname>Clife</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M. D.</given-names>
            <surname>Vos</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Brain</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J. A.</given-names>
            <surname>Padget</surname>
          </string-name>
          ,
          <article-title>ASPVIZ: declarative visualisation and animation using answer set programming</article-title>
          ,
          <source>in: ICLP</source>
          , volume
          <volume>5366</volume>
          of Lecture Notes in Computer Science, Springer,
          <year>2008</year>
          , pp.
          <fpage>724</fpage>
          -
          <lpage>728</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          [15]
          <string-name>
            <given-names>R.</given-names>
            <surname>Lapauw</surname>
          </string-name>
          , I. Dasseville,
          <string-name>
            <given-names>M.</given-names>
            <surname>Denecker</surname>
          </string-name>
          ,
          <article-title>Visualising interactive inferences with IDPD3</article-title>
          ,
          <source>CoRR abs/1511</source>
          .00928 (
          <year>2015</year>
          ).
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          [16]
          <string-name>
            <given-names>C.</given-names>
            <surname>Kloimüllner</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Oetsch</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Pührer</surname>
          </string-name>
          ,
          <string-name>
            <given-names>H.</given-names>
            <surname>Tompits</surname>
          </string-name>
          ,
          <article-title>Kara: A system for visualising and visual editing of interpretations for answer-set programs</article-title>
          ,
          <source>in: INAP/WLP</source>
          , volume
          <volume>7773</volume>
          of Lecture Notes in Computer Science, Springer,
          <year>2011</year>
          , pp.
          <fpage>325</fpage>
          -
          <lpage>344</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>
          [17]
          <string-name>
            <given-names>S.</given-names>
            <surname>Hahn</surname>
          </string-name>
          ,
          <string-name>
            <given-names>O.</given-names>
            <surname>Sabuncu</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Schaub</surname>
          </string-name>
          , T. Stolzmann,
          <article-title>Clingraph: A system for asp-based visualization</article-title>
          ,
          <source>Theory Pract. Log. Program</source>
          .
          <volume>24</volume>
          (
          <year>2024</year>
          )
          <fpage>533</fpage>
          -
          <lpage>559</lpage>
          . URL: https://doi.org/10.1017/s147106842400005x. doi:
          <volume>10</volume>
          .1017/S147106842400005X.
        </mixed-citation>
      </ref>
      <ref id="ref18">
        <mixed-citation>
          [18]
          <string-name>
            <given-names>A.</given-names>
            <surname>Bertagnon</surname>
          </string-name>
          ,
          <string-name>
            <surname>M.</surname>
          </string-name>
          <article-title>Gavanelli, ASPECT: answer set representation as vector graphics in latex</article-title>
          ,
          <source>J. Log. Comput</source>
          .
          <volume>34</volume>
          (
          <year>2024</year>
          )
          <fpage>1580</fpage>
          -
          <lpage>1607</lpage>
          . URL: https://doi.org/10.1093/logcom/exae042. doi:
          <volume>10</volume>
          .1093/ LOGCOM/EXAE042.
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>