Using SWISH To Realise Interactive Web Based Tutorials For Logic Based Languages
Using SWISH To Realise Interactive Web Based Tutorials For Logic Based Languages
FABRIZIO RIGUZZI
(e-mail: [email protected])
ROBERT KOWALSKI
Imperial College, London
(e-mail: [email protected])
TORBJÖRN LAGER
University of Gothenburg
(e-mail: [email protected])
FARIBA SADRI
Imperial College, London
(e-mail: [email protected])
MIGUEL CALEJO
Logical Contracts
(e-mail: [email protected])
Abstract
Programming environments have evolved from purely text based to using graphical user
interfaces, and now we see a move towards web based interfaces, such as Jupyter. Web
based interfaces allow for the creation of interactive documents that consist of text and
programs, as well as their output. The output can be rendered using web technology as,
e.g., text, tables, charts or graphs. This approach is particularly suitable for capturing data
analysis workflows and creating interactive educational material. This article describes
SWISH, a web front-end for Prolog that consists of a web server implemented in SWI-
Prolog and a client web application written in JavaScript. SWISH provides a web server
where multiple users can manipulate and run the same material, and it can be adapted
to support Prolog extensions. In this paper we describe the architecture of SWISH, and
describe two case studies of extensions of Prolog, namely Probabilistic Logic Programming
(PLP) and Logic Production System (LPS), which have used SWISH to provide tutorial
sites.
1 Introduction
Interactive languages such as Prolog traditionally provide a console to which you
type commands (queries) and where the output (answers) appear in textual form.
The programming environment consists of this interactive session, a code editor and
optionally tools for cross-referencing, profiling, testing, etc. These may be integrated
in a single front end called an Integrated Development Environment (IDE) such as
Emacs, Eclipse or Visual Studio.
Literate programming combines text about a program with the program itself in
a single document. This field was pioneered by Knuth, who created high quality
documentation and a Pascal program for TEX from a single document (Knuth 1984).
Note that in Knuth’s vision the text was more design documentation than merely
simple comments. For program development purposes literate programming evolved
into generating program documentation from source code based on properties of
the code itself such as class names or function names and structured comments.
Structured comments use the comment syntax of the target language, avoiding the
need for special programs to extract the program from the document. Well known
examples of this approach are the programs JavaDoc and Doxygen.
Notably for domains where programs are used to perform calculations on raw
(experimental) data and produce derived data and charts, the traditional literate
programming approach has been extended to include the result of the program such
as a table or chart in the document. The first interactive version of this approach,
called notebook interfaces, computational notebooks or data science notebooks was
introduced in 1988 by Mathematica 1.0 on the Macintosh.1
Modern web technologies such as HTML5, CSS3 and JavaScript allow for web
based versions of notebooks, simplifying their deployment. A good example of this
is Jupyter.2 The notebook interface paradigm is claimed3 to be particularly suited
to improve reproducibility in e.g., data science workflows and to provide interactive
educational material.
The benefits of interactive web based development environments and notebooks
for capturing workflows and education also apply to Prolog. How should Prolog be
part of these developments? There are two obvious options: (1) provide support
in an existing language independent environment such as Jupyter or (2) develop a
dedicated environment for Prolog and related languages. Prolog has a number of
distinctive features that are hard to support in systems that are designed for imper-
ative object oriented languages. First, the program-is-data feature, combined with
the absence of keywords complicates syntax highlighting, completion and explana-
tions when hovering, which are found in modern editors and expected by today’s
users. Second, non-determinism allows the generation of multiple answers for one
query, which requires a different query/answer interface. Third, a large subset of
queries is side effect free, which allows multiple users to use a single server through
1 https://en.wikipedia.org/wiki/Notebook_interface
2 http://jupyter.org/
3 http://blog.stephenwolfram.com/2016/09/how-to-teach-computational-thinking/
Using SWISH to realise interactive web based tutorials for logic based languages3
4 https://swish.swi-prolog.org
4 J. Wielemaker et al.
Editor pane
Answer pane with
runner
Render as
chessboard
Hover shows
details
Query pane
Fig. 1. Screendump of SWISH in ‘IDE’ mode. The left pane holds the source code editor,
while the top-right pane holds a query runner that exploits the current selected answer
renderer and buttons for continuing after the first answer. The bottom-right pane holds
the query editor with access to example queries stored in the source, query history, solution
modifiers, result presentation and a Run! button to start the query.
Examples This menu is filled from structured comments in the program. Such a
comment is formatted as below:
/** <examples>
?- reverse([a,b], L).
?- reverse([a,b], [b,a]).
*/
The examples menu provides a menu entry for adding the current query to the
5 https://codemirror.net/
Using SWISH to realise interactive web based tutorials for logic based languages5
The Solutions
menu
Fig. 2. The Solutions menu can be used to count results, order them, filter duplicates,
etc. The upper runner shows answers to the query as a table.
SWISH allows the user to save the program in the code editor. The user can
assign the program a meaningful name or accept a randomly created name. Once
a program is saved, it is associated to an URL of the form
https://swish.swi-prolog.org/p/<name>
that is persistent: it can be used to retrieve the program later and to share it with
other users. Saved programs are versioned using technology inspired by the GIT
SCM,6 where documents (programs) and their meta-data (author, time, relation
to previous version etc.) are identified by a cryptographic hash of the data. This
approach guarantees integrity of the data and simplifies concurrent and distributed
management of versions. The versioning system allows for using previous versions
as well as examining changes. The user can log into the system: in this case the
identity of the user is associated with the saved program.
Each program is associated with a chat room where users can discuss the current
6 https://git-scm.com/
6 J. Wielemaker et al.
program. SWISH has a general chat room for discussions not related to a specific
program.
After the user enters a query, the Run! button (bottom right hand corner) can
be used to execute the query. Pressing Run! collects the current program and query
and creates a runner instance which is discussed in the next section.
2.2.1 Debugging
The SWISH debugger is based on the traditional 4-port debugging model for Prolog
(Byrd 1980). The ports are events happening to goals in the procedural interpreta-
tion of the program:
call starting to prove the goal,
exit the goal was successfully proved,
fail the goal cannot be proved,
Using SWISH to realise interactive web based tutorials for logic based languages7
Fig. 3. With the ‘chess’ render library, a list of integers is interpreted as queens on a
chessboard. The user can select rendering as a ‘Prolog term’ to see the actual term.
Figure 4 shows the tracer in action on sublist/2 from the Lists example source.
The debugger was triggered by a break-point on line 10 set by clicking on the line-
number in the code editor. The debugging interaction is deliberately kept simple
and similar to traditional programming environments. A retry button is added to
the commonly seen ‘step into’, ‘step over’ and ‘step out’ for highlighting the feature
of Prolog of allowing the re-evaluation of a goal.
8 J. Wielemaker et al.
7 http://www.learnprolognow.org
8 http://lpn.swi-prolog.org
Using SWISH to realise interactive web based tutorials for logic based languages9
Query
Answer
Rendered using C3.js
Fig. 5. Screendump of SWISH in ‘notebook’ mode. The displayed notebook is from the Ex-
amples menu, showing statistics from the running SWISH server. The visible part contains
two queries, the bottom one being executed. The result is a chart showing the number
of running queries (Pengines), Prolog threads and visitors of the website. The result is
rendered using C3.js.
4 Extending SWISH
SWISH can be extended to support languages built on top of Prolog. We assume
that the new language uses Prolog syntax, typically extended with additional oper-
ators. We also assume we still have a program and queries about this program that
have zero, one or more answers.
To build an extension one needs to:
9 http://book.simply-logical.space/
10 J. Wielemaker et al.
Fig. 6. Screendump of Learn Prolog Now with an opened SWISH instance that shows
the collected source as well as example queries from the following text that are classified
as relating to this source. The embedded SWISH provides all functionality available in
the stand-alone SWISH. If the user presses the close button, SWISH is removed and the
original code re-appears.
• Provide syntax highlighting support for the target language. This implies
using the SWI-Prolog library prolog colour.pl.
• Add notebooks and programs that provide examples. Examples are added
to the directory examples. The directory contains a JSON index file that
organises the content of the Examples menu in the SWISH navigation bar.
Typically only a few notebooks with a single markdown cell describing the
available examples are added to the menu.
Using SWISH to realise interactive web based tutorials for logic based languages11
10 http://cplint.ml.unife.it
11 http://vlsi.colorado.edu/~fabio/
12 J. Wielemaker et al.
the program is compiled into an intermediate language from which the computa-
tion of the probability is easy. cplint on SWISH includes the PITA algorithm
(Riguzzi and Swift 2013) that compiles the program to a BDD and computes the
probability with a dynamic programming algorithm. However, exact inference is
intractable in general so approximate algorithms have been developed. cplint on
SWISH also includes MCINTYRE (Riguzzi 2013), which uses a Monte Carlo ap-
proach: the algorithm repeatedly samples the truth value of the query and the
probability of the query is given by the relative frequency of the true value.
In parameter learning, the user has a program for which he does not know the
probabilistic parameters and wants to induce them from data. In structure learning,
the user wants to induce both the structure of the clauses and the parameters from
data. In cplint on SWISH learning can be performed from sets of interpretations,
each expressing a possible state of the world. Some predicates are identified as
target, and true and false atoms of the target predicates in the interpretations are
used as positive and negative examples respectively.
EMBLEM (Bellodi and Riguzzi 2013) performs parameter learning in cplint on
SWISH using a special dynamic programming algorithm operating on BDDs. For
structure learning, cplint on SWISH includes SLIPCOVER (Bellodi and Riguzzi
2015), which performs a search in the space of clauses and scores them using the
likelihood of the data after parameter learning by EMBLEM, and LEMUR (Di
Mauro et al. 2015), which is similar to SLIPCOVER but uses Monte Carlo tree
search.
cplint on SWISH includes many examples of inference from various domains:
reasoning about actions, random walks, marketing, natural language, biology, puz-
zles, genetics, model checking, medicine, games, social networks, filtering, Bayesian
estimation and regression. These examples show the various features of the inference
modules: encoding Markov Logic Networks and stochastic logic programs, contin-
uous random variables, particle filtering, likelihood weighting, Metropolis-Hastings
sampling, rejection sampling, argument sampling, causal inference and computa-
tion of expectations, see (Riguzzi et al. 2016; Alberti et al. 2017; Nguembang Fadja
and Riguzzi 2017) for more details on the examples.
cplint on SWISH exploits the graphics capabilities of SWISH. For example,
Figure 7 shows a program for the computation of the probability of the existence
of a path between two nodes in a probabilistic graph (also known as the network
reliability problem). The graphviz rendering library of SWISH is used to draw the
probabilistic graph. The same library can be used to draw the BDD that is built
by the PITA for answering a query.
cplint on SWISH also uses the R for SWISH library, which provides an interface
to R both for computation and for graphics. Figure 8 presents a one-dimensional
Kalman filter example with a graph that shows how the probability density on the
position of the target changes with time.
SWISH also offers the possibility of adding rendering plugins. cplint on SWISH
for example adds a plugin for drawing two dimensional tile maps. Figure 9 shows
an example for the random generation of a two-dimensional tile map for a video
game.
Using SWISH to realise interactive web based tutorials for logic based languages13
Fig. 8. Screendump of cplint on SWISH with opened Kalman filter example together
with the results of a MCINTYRE query graphed with R.
14 J. Wielemaker et al.
Fig. 9. Screendump of cplint on SWISH with opened tile map generation example.
cplint on SWISH also includes learning examples, both for parameter learning
and for structure learning with SLIPCOVER and LEMUR: predicting whether a
machine should be fixed, classifying pictures containing geometrical objects (Bon-
gard problems), predicting the shopping behaviour of people, learning the parame-
ters of hidden Markov models, predicting whether a molecule is an active mutagenic
agent (the famous mutagenesis benchmark dataset (Srinivasan et al. 1996)), pre-
dicting the rating of courses of a university and learning the probabilistic effects of
actions in the Event Calculus.
The learned programs are shown in the answer pane using a specific rendering
library and can be applied to a testing set. Data analysts often find it useful to draw
the Received Operating Characteristic (ROC) and Precision Recall (PR) curves of
the performance of a model on the test set and to compute the areas under these
curves. cplint on SWISH includes the auc SWI-Prolog pack for such purpose and
can draw the curves using either R or C3.js: for example, Figure 10 shows a ROC
curve drawn with R.
cplint on SWISH also includes Aleph (Srinivasan 2007), one of the most in-
fluential Inductive Logic Programming (ILP) systems. It learns normal logic pro-
grams from examples and background knowledge and can be used as a baseline
for probabilistic ILP systems. Aleph has been ported from Yap to SWI-Prolog and
transformed into a module with conditional compilation directives as the cplint
algorithms in order to work in SWISH. It is now available as a SWI-Prolog pack.
Using SWISH to realise interactive web based tutorials for logic based languages15
Fig. 10. Screendump of cplint on SWISH with opened ROC and PR curves example.
Fig. 11. The first notebook in the Firststeps notebook in the Examples menu. The
SWISH editor was extended, higlighting LPS-specific keywords, fluents and events.
Models in LPS are defined by logic programs, which represent beliefs, and are gen-
erated incrementally, starting from an initial state, observing a stream of external
events, executing a stream of actions, and updating the current state. Updates are
performed using causal laws, which define the time-varying facts (or fluents) initi-
ated and terminated by events, including both external events and actions. Causal
laws are based on the Event Calculus (Kowalski and Sergot 1986), but are imple-
mented destructively, as in imperative computer languages. Analogously, events are
processed as streams, without remembering their past.
12 http://lps.doc.ic.ac.uk
18 J. Wielemaker et al.
including all states and events in between. In theory, time can be infinite. But in the
implementation, the final state, which can be overridden, is at time 20 by default.
The first notebook illustrates a passive agent without any goals and without the
ability to perform any actions. The second notebook illustrates an active agent,
which can perform the action of switching the light (on or off) for itself, and which
has the goal of switching the light as soon as it observes that the light is off:
if lightOff at T1 then switch from T1 to T2.
Here T 1 and T 2 are “time” (or state) variables. T 1 is implicitly universally quan-
tified and T 2 is implicitly existentially quantified. The quantifiers are not written
explicitly, because all variables in the antecedent of a rule are universally quantified,
and all variables that are only in the consequent are existentially quantified.
The explicit representation of time clarifies the meaning of sentences. However,
as a shortcut, time can often be left implicit. For example, the rule in this example
can also be written more simply in the form:
if lightOff then switch.
No matter how the rule is written, for the rule to be effective, switch needs to be
declared as an action. As a result, when the light is observed to be off at 4, the rule
generates an action of switching the light between 4 and 5. See Figure 14.
The first two notebooks illustrate agents whose only “beliefs” are “facts” or
causal laws. However, beliefs in LPS can also include logic programs that define
abstract concepts in terms of more concrete concepts, and logic programs that
define complex events and plans in terms of other events, actions and fluents. The
third notebook illustrates a logic program defining an intensional predicate happy
in terms of extensional predicates lightOn and lightOff :
happy(bob) if lightOn.
happy(dad) if lightOff.
Using SWISH to realise interactive web based tutorials for logic based languages19
Fig. 14. LPS execution timeline for the same program and same external events, but
with a reactive rule if lightOff at T 1 then switch from T 1 to T 2.
which prevents dad from going to more than one place at a time. The constraint is
necessary, because dad’s behaviour is governed by reactive rules that make him go
to a room whenever there is a light on in the room, and to turn the light off if it is
still on. In this example, times do not need to be written explicitly, because of the
restrictions on times in constraints.
Logic programs in LPS are pure Prolog programs, but are represented by Prolog
facts, and are executed by a Prolog meta-interpreter. The meta-interpreter im-
plements destructive updates, with its logical model generation semantics, using
Prolog’s assert and retract, which do not have a logical semantics. The use of Pro-
log to implement LPS means that auxiliary predicates in LPS can be defined by a
compiled Prolog program, as in the example in Figure 15. The example also shows
how LPS gives a simple, logical semantics to input-output, representing inputs as
observations of external events, outputs as actions, and the relationship between
inputs and outputs as a reactive rule. If the input is a request, then the rule may
optionally include additional arguments and conditions to determine, for example,
20 J. Wielemaker et al.
whether to fulfil the sender’s request, reply with a polite refusal, or block future
requests from the sender.
Models in LPS have two forms: A static form, which is needed for the logical
semantics, and in which fluents and events are included in one, all-encompassing
structure with timestamps; and a dynamic form, which is needed for practical im-
plementation, and in which only the current state and events are stored without
timestamps. Timelines display models in their static form. But models can also be
displayed in their dynamic form, as animations.
For this purpose, we have used the rendering facilities of SWISH to develop a
preliminary, declarative language for users to generate their own 2D animations.
Figure 16 illustrates an animation frame representing a single, current state in
Conway’s game of life, in the LPS examples notebook in the examples menu.
To obtain the animation, it suffices to specify the visual representation of fluents
and their 2D co-ordinates. For example, the Prolog clause:
d(X-Y,[center:[XX,YY], radius:5, type:circle, fillColor:green]) :-
XX is X*10, YY is Y*10.
expresses that the fluent X-Y, which represents the presence of a live cell at location
X-Y, is displayed as a green circle centred at [X ∗ 10, Y ∗ 10] with radius 5. The
transition from one state to the next is specified by reactive rules, such as the rule
that a live cell dies if it has less than two live neighbors:
Using SWISH to realise interactive web based tutorials for logic based languages21
13 http://logicalcontracts.com
22 J. Wielemaker et al.
legal documents in logical, executable form. LPS is well suited for such legal ap-
plications, because there is a natural correspondence between logic programs and
constitutive rules, which define legal concepts, between reactive rules and regulative
rules, which enforce legal obligations, and between constraints and prohibitions.
5 Architecture
SWISH consists of two parts. The client side, running in a browser, is implemented
as a series of jQuery plugins, using Bootstrap14 for styling and RequireJS15 for
package management. The server side is completely implemented in SWI-Prolog
(Wielemaker et al. 2008). It builds on top of the SWI-Prolog HTTP server libraries
(Wielemaker et al. 2008), the Pengines library (Lager and Wielemaker 2014) and
the IDE support libraries that provide data for auto completion, documentation
and highlighting. In the remainder of this section we first give a brief overview
of the available components, next we elaborate on some of these components and
finally we discuss the portability of the design.
• The program editor is used to edit programs, queries, HTML and Mark-
down. It is described in in Section 5.3.
• The query editor is derived from the code editor, providing additional access
to examples, history and modifying the query (count solutions, time, order,
distinct, etc.)
• A runner instance takes care of actually running a query. It is created from
zero or more source code fragments and a query. It allows for controlling the
query (ask for more solutions, abort or discard it) and collects the answers.
It can be asked to organise the answers in the traditional Prolog way as a
series of Var = Value statements or as a table, providing a solution as a row
of values.
• An answer instance is responsible for rendering a term that is part of the
answer. The baseline is a nested HTML <span> reflecting the syntactic com-
ponents of the term that allows for folding and unfolding terms. SWISH allows
for alternative term rendering using, e.g., tables, charts, graphs, etc. This may
be compared to the traditional portray/1 hook, but SWISH rendering can
exploit the full capabilities of HTML5, CSS, SVG and JavaScript. See Sec-
tion 5.6.
14 https://getbootstrap.com/
15 http://requirejs.org/
Using SWISH to realise interactive web based tutorials for logic based languages23
• A notebook instance is a list of cells built from the above components, see
Section 2.3. The notebook itself allows for adding, deleting and organising
cells and provides the necessary code to serialise the content as an HTML
document on the server and import other notebooks.
• The social infrastructure makes other users aware that they are operating on
the same program using an avatar. The avatar has a notification area that
indicates when a document is opened, closed or saved. Each document has an
associated chat room that allows users to discuss code and share queries.
go :-
non_existing(X).
The JavaScript client produces the tokens [ atom, atom, functor, punct, var, punct,
fullstop ]. The server analyses the program text and produces [ head (not called),
neck, goal (undefined), punct, var (singleton), punct, fullstop ]. The JavaScript to-
keniser examines both its own tokens and the server token list. If the tokens are
compatible (for example ‘atom’ is consistent with ‘head’), it uses the enriched server
information (head of a not-called predicate) to determine the colour and font. If
the tokens are not compatible (for example the client finds var and the server re-
ports atom, it schedules a request to the server for a revised list of enriched tokens.
This request is sent if the user pauses typing for two seconds. While waiting for
up-to-date enriched tokens, the JavaScript highlighting code heuristically tries to
re-synchronise and either uses the uncertain results or falls back to the plain tokens.
Heuristic re-synchronisation checks whether a single added, deleted or modified to-
ken gets the token stream in-sync. If this fails it tries to re-synchronise on a full-stop
with the next clause or directive.
A CodeMirror hover plugin is used to show basic information about tokens if the
pointer hovers over it. For goals, this includes where the goal is defined (ISO, SWI-
Prolog built-in, a library, locally) and the documentation summary information if
available. This information is requested from the server.
A CodeMirror template plugin is configured from templates (e.g.,
atom length(+Atom, -Length)) extracted from the SWI-Prolog manual and
PlDoc documentation of imported libraries. This plugin shows a menu of
applicable predicates with their templates when the user presses Control-Space.
Finally, if the compiler generates errors or warnings, these are inserted as notes
into the source code.
for synchronising writes to the journal file. The journal file facilitates fast discov-
ery of the available heads and fast tracking of changes by other SWISH instances.
The ability to run multiple SWISH servers on a shared or distributed file system
improves its scalability.
Files can be referenced by content using their hash or by name. The name can
be considered a version head and refers to the latest version with that name. The
file interface provides the following operations:
• Saving a file anonymously, which produces a randomly generated URL.
• Saving a file by name.
• Organise files using tags.
• Saving a new version.
• Merge changes if another user saved the same file.
• Show the available versions and modifications between versions.
• Forking a file under a new name. The history remains linked to the original.
Both the old and new name act as a revision head.
Prolog source files can include other programs on the same server using
:- include(filename)., including the latest version or :- include(hash). to
include a specific version.
17 https://www.youtube.com/watch?v=G_eYTctGZw8
Using SWISH to realise interactive web based tutorials for logic based languages27
:- use_rendering(Renderer, Options).
Each term is handed to all active renderers and finally to the built-in generic term
renderer that represents any term as writeq/1 using nested <span> elements. If one
or more of the special purpose renderers succeed, the output of the first is displayed,
together with a hover-menu that provides access to the other representations.
Currently, rendering plugins are not executed inside the Pengine, but by the
HTTP handler that returns a Pengine answer to the client. This is a consequence
of the Pengine interface that will be addressed in future versions as it prevents the
renderer from accessing global data, bypasses resource limitations imposed on the
Pengine and prevents supporting rendering hooks as part of the user program.
• It discovers a (meta-) goal for which it cannot deduce the called code. The
traditional example is read(X), call(X). If such a goal is encountered, it
signals an instantiation error, together with a trace that explains how the
insufficiently instantiated goal can be reached. Note that it can deal with
normal high-order predicates if the meta-argument is specified. For example,
the following goal is accepted as safe.
SWISH can be integrated in workflows with external tools and data. The integra-
tion options are embedding, downloading query results as CSV (comma separated
values), accessing SWISH as a service and accessing other services from SWISH.
SWISH can be embedded in a web page using an <iframe>. This is particularly
appealing for educational deployment: textual material can be interleaved with
SWISH frames. The SWISH interface can be preloaded with a background program
(an invisible program that is sent along with each query), a program (that appears
in the code editor), a query and examples that appear in the query editor. It can
also be preloaded with a notebook. See Section 3.
Both a runner and the notebook query editor provide a menu to download the
query answers as CSV. The subsequent dialogue allows for setting a limit on the
number of results and defining the projection, the variables to be included in the
CSV and the order of these variables.
SWISH offers the Pengine API (Application Programming Interface) to clients in
Prolog, JavaScript, Java, Ruby and Erlang. This API can be used to execute queries
against programs that are provided by the client or available as saved documents
on the SWISH server.
The client for Prolog offers a predicate for making non-deterministic RPC (remote
procedure calls), for example:
?- use_module(library(pengines)).
true.
?- pengine_rpc(’https://swish.swi-prolog.org’, member(X,[a,b,c])).
X = a ;
X = b ;
X = c.
?-
6 Related work
We are not aware of other initiatives that aim at developing a rich web-based
development environment for Prolog. There are web sites that allow running Prolog
online such as Tutorial Points.21 These sites either run your Prolog program as a
batch job or provide a classical terminal to access Prolog. None of the environments
we visited provide SWISH features such as notebooks or rendering Prolog answers
using web technology such as charts.
We do not compare SWISH with traditional editor or GUI based development
environments for Prolog such as GNU-Emacs or ProDT,22 because web-based en-
vironments provide both new opportunities such as shared access and pose new
challenges such as a more limited interface, limited bandwidth and high latency.
18 Such notes are displayed by CodeMirror, but they are not part of the user document.
19 http://visjs.org/docs/timeline
20 http://paperjs.org
21 https://www.tutorialspoint.com/execute_prolog_online.php
22 http://prodevtools.sourceforge.net/
30 J. Wielemaker et al.
Instead, we discuss three applications that served as inspiration for SWISH: JSFid-
dle,23 R-Studio24 and Jupyter Notebooks.25
• The initial inspiration for SWISH was JSFiddle. JSFiddle is an environment
for testing browser technology (HTML, CSS, JavaScript) and thus it is nat-
urally executed inside the user’s browser. SWISH programs are executed on
the server. For educational purposes, client side execution is probably feasi-
ble. For data analysis purposes remote execution allows users to control large
Prolog jobs on big servers from their browser.
• R-Studio (Gandrud 2013) is an interface to the R statistical package. Although
not a web application, it is based on the Qt webkit framework and uses web
based technology in the background. The R-studio interface has a similar
layout as SWISH, providing a source window, a console and an output window
that typically shows results as tables or charts.
• Jupyter notebooks (formerly IPython notebooks) (Rossant 2013) allow mixing
markdown or HTML text with Python code. When executed, the notebook
shows the text, sources and possible results as numbers, tables or charts.
SWISH embodies many of the ideas behind JSFiddle, R-Studio and Jupyter.
SWISH provides shared anonymous access like JSFiddle. Both the R-Studio ‘pro-
gram and output window’ and Jupyter notebook interfaces are available as they
serve different user communities in our experience.
Both R-Studio and Jupyter notebooks work on the basis of authenticated access.
Once access is obtained, any command may be executed. SWISH can operate both
as a public service granting access to non-intrusive queries that may be executed
concurrently on shared (typically read-only) data and as an authenticated service
to run arbitrary queries. The authenticated mode is often used for maintenance
purposes such as updating the server software or loading data for further shared
analysis.
Where Jupyter supports other languages using the notion of Jupyter kernels, such
support is not provided by SWISH. We believe that Prolog is sufficiently different
from the languages targeted by Jupyter to justify dedicated support. SWISH has
little to offer to compete with Jupyter on the languages that Jupyter supports
properly though.
Unlike JSFiddle, R-Studio and Jupyter, SWISH can easily be embedded into web
pages using an <iframe> element where the program, examples and queries can
be provided in the URL that loads SWISH. This feature can be used to transform
source code in a static HTML page into a SWISH instance using a simple JavaScript
call. This is demonstrated in Section 3.
cplint on SWISH is a system for PLP that uses SWISH to provide a web inter-
face to cplint. A related PLP system is ProbLog2 (Fierens et al. 2015), which has
also an online interface26 (Dries et al. 2015). The main difference between the web
23 https://jsfiddle.net/
24 http://www.rstudio.com/
25 http://jupyter.org
26 https://dtai.cs.kuleuven.be/problog/
Using SWISH to realise interactive web based tutorials for logic based languages31
interfaces of cplint on SWISH and ProbLog2 is that the first uses a Prolog-only
software stack, whereas the latter relies on several different technologies, including
Python 3 and external knowledge compilers.
ProbLog2 can also be used in Jupyter notebooks but, differently from SWISH,
cannot interface to R.
7 Discussion
We have not performed any direct user evaluations of SWISH. Given the pace of
development, different configurations and user communities, it is not feasible to
perform such a study with limited resources. Below we summarise the impact of
the system, including some lessons learned regarding using Prolog through a web
app, and discuss portability.
SWISH has been online (September 2017) for three years. It is extensively be-
ing used for Prolog education, as discussed in Section 3 and Section 4. Since its
launch, at least three independently developed educational sites have been launched:
cplint and LPS (described in this article) and the book Simply Logical (Flach
1994). The main server now has 35,420 programs stored with 68,806 revisions. Us-
age is strongly correlated with academic holidays, ranging from 36,415 queries per
week (July 31 - August 6, 2017) to 125,946 (May 7-14, 2017). Google link search
(link:swish.swi-prolog.org) reports 8,490 links. The popularity of the Github
repository, 198 stars and 48 forks compared to the main SWI-Prolog repository
with 223 stars and 53 forks is another indication of the impact of SWISH.
The development of SWISH and its usage as a public service demonstrates SWI-
Prolog’s ability for writing web services. Moreover, it represents an excellent stress-
test for SWI-Prolog. We have been forced to extend resource management, e.g.,
by limiting the program space associated with the temporary modules to avoid
extensive use of assert/1 causing the server to run out of memory. Timeout and
exception handling needed to be improved to avoid runaway queries. In particular,
resource exceptions such as stack overflows are frequent and need to be handled
reliably. Both scalability and reliability of multi-threaded execution needed to be
improved. We have now reached a level of stability were restarts due to software
upgrades (every one to two weeks) are more frequent than restarts due to crashes,
memory leaks or runaway queries. We have shown that SWI-Prolog-based servers
are capable of concurrently running arbitrary queries with bounds on resources.
The current browser infrastructure has proven to be sufficiently rich, portable and
performant for developing a web IDE for Prolog. Server-assisted semantic highlight-
ing has proven to be feasible, but the mechanism is rather fragile because it requires
synchronisation of two independent highlighting processes, one at the client and one
on the server. Besides providing shared access, a web front end allows for trans-
forming Prolog answers into rich graphical representations such as tables, charts,
graphs or the LPS timelines.
32 J. Wielemaker et al.
7.1 Portability
The SWISH client libraries are based on mature JavaScript libraries. The client
runs in all modern major browsers with HTML5, CSS and JavaScript support. It
is frequently tested on Firefox, Chrome, Safari and Internet Explorer 11.
The server code is basically non-portable. Many of the required libraries and
features are shared with at least one other Prolog implementation, but none is
capable to support the full range. Below we summarise the main issues.
• The scale of the involved Prolog libraries demands a closely compatible Pro-
log module system. Probably only SICStus and YAP can be used without
significant restucturing.
• The HTTP server libraries are heavily based on C code that interacts with
the SWI-Prolog foreign language interface to Prolog streams. YAP has copied
the low-level libraries and is capable to run an old version of these libraries.
• The Pengines library depends on the HTTP library and the multi-thread
interface. The SWI-Prolog thread API is also provided by YAP and XSB.
• The sandbox library (Section 5.7) assumes that whitelisted predicates both
have no side effects and are robust against stack overflows, cyclic terms, etc.
Few Prolog systems can satisfy this requirement. SICStus Prolog would be a
candidate.
• The semantic syntax highlighting depends on detailed source layout informa-
tion provided by read term/3. SWI-Prolog’s support for term layout is an
extended version of the Quintus Prolog term layout functionality.
• Significant parts of the code rely on SWI-Prolog version 7 extensions, notably
the dict and string types that facilitate a natural mapping between Prolog
and JSON data.
From the above list it should be clear that a fully functional port of SWISH
to another Prolog system is not immediately feasible. There is a more realistic
scenario though. In this setup, SWI-Prolog provides the web interface and most of
the development tools and another language, not even necessarily Prolog, provides
the query solving. The interface between the two can be based on inter-process
communication or, if the target system is safe and capable of supporting threads,
by linking the target system into the process and using the C interface.
Inter-process communication is already used in SWISH for embedding R.27 This
embedding is based on Rserve28 . Rserve consists of an R instance that is fully
initialised and optionally contains pre-loaded libraries. The R server provides a
TCP/IP or Unix socket and a binary protocol to manage sessions and R commands.
A new connection causes the server to fork a new child that handles the client.
Resource management and isolation are provided by running Rserve inside a Docker
based OS sandbox.29
27 http://www.swi-prolog.org/pack/list?p=rserve_client
28 https://cran.r-project.org/web/packages/Rserve/
29 https://github.com/JanWielemaker/rserve-sandbox
Using SWISH to realise interactive web based tutorials for logic based languages33
7.2 Scalability
The SWISH server is a monolithic SWI-Prolog program. Some parts of the inter-
action with SWISH are by nature stateful, notably query execution and syntax
highlighting, which maintains a clone of the user’s editor on the server. These parts
can be distributed over a pool of servers using a proxy server with support for
sticky sessions. Sticky session support implies that the proxy assigns a new user
to a random server and subsequently forwards all trafic from this user to the same
server. Other parts, such as serving the main page, icons, CSS, JavaScript and
manual pages can easily be offloaded from the Prolog server by using a caching
reverse proxy or serving them from another server. Secondary servers may also be
used to offload the chat and storage services. Extrapolating from resource usage on
the main public server we estimate that a single SWISH server can handle up to
about 1,000 concurrent users (dual Intel Xeon E5-2650) for a typical educational
workload.
8 Conclusions
This article presented SWISH, a web service that supports the execution of Prolog
and domain specific languages (DSLs) defined on top of Prolog from a browser.
SWISH provides an interface that is primarily targeted at program development
and testing as well as a notebook interface that is targeted at capturing workflows
for data analysis and tutorials. The SWISH server is a SWI-Prolog program where
user queries are executed by Pengines which are built from a Prolog thread and an
isolated temporary Prolog module. The monolithic approach provides easy deploy-
ment as well as shared access to, e.g., large pre-loaded Prolog knowledge bases.
The current interface provides a better interaction with and more control for
managing queries as well as small Prolog programs than the traditional Prolog
command line and Prolog IDEs. This makes it suitable for education and data
analysis. It is not yet suitable for the development of large applications. For these
scenarios, users expect support for modular program development, a richer editor
and a better debugger.
The current system does not provide much support for animating progress, such
as showing the moves while solving the towers of Hanoi puzzle. One option used
in LPS is to generate the entire animation and then use JavaScript to play the
animation in the user’s browser. Future versions may exploit the Pengine prompt
mechanism that is also used to implement read/1 to read from the browser, for
creating interactive animations. Currently, SWISH rendering plugins are executed
in the context of the HTTP reply mechanism rather than by the Pengine itself.
This implies that they are not sandboxed, they must be provided by the SWISH
installation and we cannot support user defined rendering plugins.
In data analysis scenarios some queries take long to execute and, if we provide a
result, we would like to be able to reliably reproduce this result and apply exactly
the same version of the analysis program to new data. For this purpose we are
34 J. Wielemaker et al.
developing a persistent answer cache based on a hash of the called predicate and
its dependencies.
Acknowledgements
This research was partially supported by the VRE4EIC project, a project that has
received funding from the European Union’s Horizon 2020 research and innovation
program under grant agreement 676247. The SWISH implementation of LPS was
developed under an EPSRC grant administered by Imperial College London. We
thank the referees for their helpful comments.
References
Alberti, M., Bellodi, E., Cota, G., Riguzzi, F., and Zese, R. 2017. cplint on
SWISH: Probabilistic logical inference with a web browser. Intelligenza Artificiale 11, 1,
47–64.
Bellodi, E. and Riguzzi, F. 2013. Expectation Maximization over binary decision
diagrams for probabilistic logic programs. Intelligent Data Analysis 17, 2, 343–363.
Bellodi, E. and Riguzzi, F. 2015. Structure learning of probabilistic logic programs by
searching the clause space. Theory and Practice of Logic Programming 15, 2, 169–212.
Blackburn, P., Bos, J., and Striegnitz, K. 2006. Learn prolog now! Vol. 7. College
Publications, London, UK.
Byrd, L. 1980. Understanding the Control Flow of Prolog Programs. In Logic Pro-
gramming Workshop. Department of Artificial Intelligence, University of Edinburgh,
Debrecen, Hungary.
De Raedt, L. and Kimmig, A. 2015. Probabilistic (logic) programming concepts. Ma-
chine Learning 100, 1, 5–47.
De Raedt, L., Kimmig, A., and Toivonen, H. 2007. ProbLog: A probabilistic Prolog
and its application in link discovery. In 20th International Joint Conference on Artificial
Intelligence, Hyderabad, India (IJCAI-07), M. M. Veloso, Ed. Vol. 7. AAAI Press, Palo
Alto, California USA, 2462–2467.
Denecker, M. 2000. Extending classical logic with inductive definitions. In Computa-
tional logicCL 2000. Springer, Cham, 703–717.
Di Mauro, N., Bellodi, E., and Riguzzi, F. 2015. Bandit-based monte-carlo structure
learning of probabilistic logic programs. Machine Learning 100, 1, 127–156.
Dries, A., Kimmig, A., Meert, W., Renkens, J., Van den Broeck, G., Vlasselaer,
J., and De Raedt, L. 2015. Problog2: Probabilistic logic programming. In Machine
Learning and Knowledge Discovery in Databases: European Conference, ECML PKDD
2015, Porto, Portugal, September 7-11, 2015, Proceedings, Part III, A. Bifet, M. May,
B. Zadrozny, R. Gavalda, D. Pedreschi, F. Bonchi, J. Cardoso, and M. Spiliopoulou,
Eds. Springer International Publishing, Cham, 312–315.
Fierens, D., den Broeck, G. V., Renkens, J., Shterionov, D. S., Gutmann, B.,
Thon, I., Janssens, G., and De Raedt, L. 2015. Inference and learning in proba-
bilistic logic programs using weighted boolean formulas. Theory and Practice of Logic
Programming 15, 3, 358–401.
Flach, P. 1994. Simply Logical: Intelligent Reasoning by Example. Wiley, Chichester,
UK.
Gandrud, C. 2013. Reproducible Research with R and R Studio. CRC Press, Boca Raton,
FL.
Using SWISH to realise interactive web based tutorials for logic based languages35