<!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 />
    <article-meta>
      <title-group>
        <article-title>The Blame Game for Property-based Testing</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Alberto Momigliano</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Mario Ornaghi</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>DI, Universita di Milano</institution>
        </aff>
      </contrib-group>
      <abstract>
        <p>We report on work in progress aiming to add blame features to property-based-testing in logic programming, in particular w.r.t. the mechanized meta-theory model checker Check. Once the latter reports a counterexample to a property stated in Prolog, a combination of abduction and proof explanation tries to help the user to locate the part of the program that is responsible for the unintended behavior. To evaluate whether these explanations are in fact useful, we need an unbiased collection of faulty programs, where the bugs location is unknown to us. We have thus implemented a mutation testing tool for Prolog that generates such a set. Preliminary experiments point to the usefulness of our blame allocator. The mutator is of independent interest, allowing us to gauge the e ectiveness of the various strategies of Check in nding bugs in Prolog speci cations.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>Introduction</title>
      <p>
        Property-based testing [
        <xref ref-type="bibr" rid="ref13">13</xref>
        ] (PBT) is a lightweight validation technique by which
we try to refute executable speci cations against automatically (typically in a
pseudo-random way) generated data. Once the idea broke out in the functional
programming community with QuickCheck, it spread to most programming
languages and turned also in a commercial enterprise [
        <xref ref-type="bibr" rid="ref15">15</xref>
        ].
      </p>
      <p>PBT has also a pedagogical value and our students seem to enjoy using it
during their functional programming coursework. After type-checking succeeds,
the PBT message \Ok, passed 100 tests ", whereby the tool reports the failure
to refute some property, gives the students a warm fuzzy feeling of having
written correct code. This feeling comes to a sudden halt when a counterexample
is reported, signaling a mismatch between code and speci cation. In our
experience, the student freezes, disconnects the brain, typically uttering something
like \Prof, there's a problem here", and refrains from taking any further action.</p>
      <p>Now, no-one likes to be wrong, not only students, and this is why testers and
programmers may be di erent entities in a software company. While a
counterexample to a property is a more useful response than, say, the false of a failed
logic programming query | or a core dump for that matter | we can do
better and go beyond the mere reporting of that counterexample; namely, try to
circumscribe the origin of the latter. After all, the program under test may be
arbitrarily large and, arguably, even partial solutions pinpointing the slice of the
program involved in an error can help pursuing the painful process of bug xing.</p>
      <p>
        \Where do bugs come from?" is a crucial question that has sparked a huge
amount of research. In this short paper, we report on preliminary work on
addressing a much, much smaller sub-problem: rst, the domain is mechanized
meta-theory model-checking [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ], that is the validation of the mechanization in
a logical framework of the meta-theory of programming languages and related
calculi [
        <xref ref-type="bibr" rid="ref10 ref11">11, 10</xref>
        ]. To x ideas, think about the formal veri cation of compiler
correctness [21] and look no further than [
        <xref ref-type="bibr" rid="ref18">18</xref>
        ] for more impressive case studies. In
this domain, the speci cations under validation correspond to the theorems that
the formal system under test should obey and are therefore trusted. Hence, we
put the blame of a counterexample on the system encoding, not on a possibly
erroneous property.
      </p>
      <p>
        Secondly, and consequently, we restrict to (nominal) logic programming, that
is to encoding written in Prolog [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ] and properties checked by Check [
        <xref ref-type="bibr" rid="ref5">5</xref>
        ]. Logic
programming, of course, is particularly suited to the task of blame assignment. In
fact, the related notion of declarative debugging [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ], starting with Shapiro's thesis,
originated there. Our approach may be applicable outside those two boundaries,
but we have not enough evidence to make any strong claim.
      </p>
      <p>Our blame tool is written in Prolog, a choice taken mostly out of
convenience, since it allows us the exibility to experiment with ideas by
metainterpretation, rather then wiring them in for good in Prolog's OCAML
implementation. In fact, meta-interpreters are forbidden by the interaction of the
strongly-typed nature of Prolog, together with its being a rst order language.</p>
      <p>We picture the architecture of the
tool in Fig. 1: we write models and
specs in Prolog and we pass them
to Check for validation. If a
counterexample is found, we translate the</p>
      <p>Prolog code to standard Prolog and
we feed it to our explanation tool
together with the said counterexample.</p>
      <p>The tool returns an explanation that
can be hopefully used to debug the</p>
      <p>Prolog model. And so on. This
architecture, of course, applies only to Fig. 1. Flow of the blame game</p>
      <p>Prolog code that can be faithfully executed in standard Prolog and therefore
does not support natively nominal features.
2</p>
    </sec>
    <sec id="sec-2">
      <title>A motivating example</title>
      <p>
        Suppose that we wish to study the following grammar (adapted from [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]), which
characterizes all the strings with the same number of a's and b0s:
S ::= . | bA | aB
A ::= aS | bAA
B ::= bS | aBB
Here's the bulk of the Prolog code, where we have omitted the obvious de
nitions of list-related predicates:
ab : type.
a,b : ab.
      </p>
      <p>pred ss(list(ab)).
pred bb(list(ab)).</p>
      <p>pred aa(list(ab)).
pred count(ab,list(ab),nat).
ss([]).
ss([b|W]) :- ss(W).
ss([a|W]) :- bb(W).
bb([b|W]) :- ss(W).
bb([a|VW]) :- bb(V), bb(W), append(V,W,VW).
aa([a|W]) :- ss(W).
aa([b|VW]) :- aa(V), aa(W), append(V,W,VW)
However, our encoding is awed | we ask the reader to suspend her disbelief,
since the bug is quite apparent. Still, it is easy to conjure an analogous scenario
where the grammar has dozens of productions and the bugs harder to spot.</p>
      <p>We shall use Check to debug it. We split the characterization of the
grammar into soundness and completeness properties:
#check "sound" 10 : ss(W), count(a,W,N1), count(b,W,N2) =&gt; N1 = N2.
#check "compl" 10 : count(a,W,N), count(b,W,N) =&gt; ss(W).</p>
      <p>The tool dutifully reports (at least) two counterexamples:
Checking for counterexamples to
sound: ss(W), count(a,W,N1), count(b,W,N2) =&gt; N1 = N2
Checking depth 1 2 3 Total: 0.000329 s:
N1 = z, N2 = s(z), W = [b]
compl: count(a,W,N), count(b,W,N) =&gt; ss(W)
Checking depth 1 2 3 4 5 6 7 8 9 Total: 0.016407 s:
N = s(z), W = [b,a]
Now that we have the counterexamples, where is the bug? More precisely, which
clause(s) shall we blame?</p>
      <p>The #check pragma of Check corresponds to speci cation formulas of the
form
8X: G</p>
      <p>A
where G is a goal and A an atomic formula (including equality and freshness
constraints). A ( nite) counterexample is a grounding substitution providing
values for X that satisfy the negation of (1): that is, such that (G) is derivable,
but the conclusion (A) is not. In this paper, we identify negation with
negationas-failure (NAF) and we will not make essential use of nominal features.</p>
      <p>The tool synthesizes (trusted) type-based exhaustive generators for the free
variables of the conclusion, so that NAF executes safely. A complete search
strategy, here naive iterative deepening, searches for a proof of:
9X: : G ^ gen[[ ]](X1) ^
^ gen[[ ]](Xn) ^ not(A)
(1)
(2)
To wit, completeness will be the query:</p>
      <p>9W. count(a,W,N), count(b,W,N), gen ablist(W), not(ss(W)).</p>
      <p>The predicate gen ablist(W) corresponds to the generator formula
gen[[list(ab)]](W ) for lists of a's and b's. In the soundness query we know by
mode analysis that we do not need generators for numerals.</p>
      <p>For a query such as the above and more in general such as (2) to unexpectedly
succeed, two (possibly overlapping) things may have gone wrong [22]:
MA: the atom A fails, whereas it belongs to the intended interpretation of its
de nition (missing answer );
WA: a bug in G creates some erroneous bindings, which again make A fail
(wrong answer ): some atom in G succeeds but it is not in the intended
model.</p>
      <p>
        Our \old-school" idea consists in coupling 1) abduction [
        <xref ref-type="bibr" rid="ref17">17</xref>
        ] to try and
diagnose MA's with 2) proof verbalization, that is presenting, at various levels of
abstraction, proof-trees for WA's as a means to explain where, if not why, the
WA occurred.
      </p>
      <p>
        Of course, since we do not know, in principle, which is which and the two
phenomena can occur simultaneously, we are going to use some simple
heuristics to drive this process. What we would rather keep our distance from is full
declarative debugging (see e.g., [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ]), as our experience suggests that making the
user the oracle potentially at each step is just too much work.
      </p>
      <p>Our notion of abduction is a simple-minded proof procedure that nds a set
of assumptions such that ; ` G0, but 6` G0 for given and G0. In our
limited setting here of rst-order logic programming, we, as expected, internalize
as a xed program P and we see as a (additive) conjunction of atoms A. An
abduction procedure depends on the selection of what the abducibles are. This
choice is related to which part of the program we trust and which we want to
investigate. The system will suggest abducibles based on the dependency graph
of the conclusion of the property under investigation, but we give the nal say
to the user, while trying to make it easy to change one's mind.</p>
      <p>We now work through the above example. Our tool reads into standard Prolog
the Prolog les, adding names to rules and treating type information as inactive
predicates via appropriate operator declarations. For example, here is the ss
predicate and related declarations:
ab :: type. a :: ab. b :: ab. pred ss(list(ab)).
ss([]) :- rule(s1).
ss([b|W]) :- rule(s2), ss(W).
ss([a|W]) :- rule(s3), bb(W).</p>
      <p>To begin with, we need to decide what to investigate and what to trust.
Consistently with our faith in properties, we will trust count and append:
trusted(append(_,_,_)). trusted(count(_,_,_)).</p>
      <p>The dependency graph suggests (quite unhelpfully here) to put all of aa,bb,ss
as abducibles.
assumable(ss(_)). assumable(bb(_)). assumable(aa(_)).</p>
      <p>For exposition sake, let us investigate the completeness bug rst, that is the
failure of ss([b,a]). This is a case of MA, since that string should be accepted.
The tool returns this explanation:
ss([b,a]) for rule s2, since:
ss([a]) for rule s3, since:</p>
      <p>bb([]) for assumed
Once you get used to the fairly primitive verbalization, you see that if it were
the case that bb([]) holds, then ss([b,a]) would have succeeded and the
counterexample not found. However, there is no production for b accepting the
empty string, so we should blame ss, namely either s2 or s3. By comparing the
clauses to the productions they are supposed to encode we see that the body of
s2 should be aa(W) and not ss(W).</p>
      <p>For the soundness bug, it is obvious that it is a case of WA. We trust
unication, the more since here it is just syntactic equality. Hence we need to
understand what went wrong in the premise ss(W) | remember, we trust count.
The tool answers:
ss([b]) for rule s2, since:</p>
      <p>ss([]) for fact s1.</p>
      <p>Since s1 is OK, it is again s2's fault. Once we x that bug, Check does not
report any more issues.
3</p>
    </sec>
    <sec id="sec-3">
      <title>How it works</title>
      <p>It is natural to split the de nitions of the program under test into builtin, which
we assume to be non problematic, and those we want to look into (pred, for
compatibility with Prolog type declarations). By default, every user-de ned
predicate is under suspicion. However, once a pred overcomes our scrutiny, or
we believe it, perhaps temporarily, to be well-behaved, we can graduate it to
being trusted and let it o the hook. Builtins and trusted predicates are not
meta-interpreted, that is we simply call them. Abducibles must be non-trusted
pred de nitions.</p>
      <p>
        The abduction/explanation mechanism can be formulated in terms of a
calculus AE (P ), based on the notion of proof-tree (see [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ], for example), whose
nodes are constructed with the following inference rules:
true &gt;
      </p>
      <p>G r
A
A
asm</p>
      <p>G1 G2
G1 ^ G2 ^</p>
      <p>Given a xed program P , rule r corresponds to a single SLD step with clause
A :- rule(r),G in P . Rules &gt;; ^; _ are self-explanatory. Rule asm closes a proof
whenever A is declared as abducible. The last two rules are somewhat di erent
(and hence the double bar): builtin and trusted both end the proof returning an
answer substitution: in the rst case if there is an external computation of the
builtin predicates. In the trusted case, we apply the rule only if there is a closed
proof-tree, i.e. without assumptions returning . In fact, this is not technically a
nitary rule, in the same sense that NAF is not; nevertheless, the way in which
we use the calculus, namely by replaying already found counterexamples, will
ensure that the rule is e ective. For example, the second clause for bb asks for
a computation of append(V,W,VW) where VW is ground. This is simply executed
as a Prolog query outside the calculus, returning the ground substitution .</p>
      <p>The meta-interpreter computes over those proof-trees, simultaneously
collecting abducible assumptions and Prolog terms encoding the proof-tree itself,
to be later verbalized. The meta-interpreter enjoys, we claim, the following
correctness property: a proof-tree computed by the meta-interpreter is a proof in
the calculus above. Conversely, for all goals G, if there is proof in AE (P ) of
G , the interpreter will produce a more general proof-tree for G with the same
sequence of rules.</p>
      <p>
        Proof verbalization Clearly, proof-trees of height 2 as the ones occurring in
Section 2 are not that di cult to interpret. However, we address the general case by
o ering various levels of explanation, from printing out the whole tree to instead
presenting a skeleton containing only the involved rule names. We currently do
this with di erent forms of printf, while it would be more exible to use a form
of proof distillation [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ], by which the proof-tree itself is pruned at the desired
level of explanation and only then verbalized.
      </p>
      <p>Heuristics Suppose you have a counterexample for property 8X: G A: how
do you go about trying to decide whether it is a MA or a WA? We suggest the
following steps with the blame tool:
1. if A is a builtin (including constraints) or a trusted predicate, it is clear that
it is a case of WA and we directly verbalize the proof tree of the premise(s).
2. Otherwise, we use abduction to investigate the failure of A; start by adding
A and its dependency graph as abducibles.
2.1 If the failure of A points to a case of MA, use the explanation mechanism
to see if there is a clause missing in the program or which clause is
otherwise involved.
2.2 If the set of assumptions found by abduction is \unreasonable", that is
we have atoms that should not hold in the intended model, it is likely a
case of WA and we turn to verbalizing the proof-tree for G.
4</p>
    </sec>
    <sec id="sec-4">
      <title>Mutation testing for</title>
    </sec>
    <sec id="sec-5">
      <title>Prolog</title>
      <p>
        Mutation analysis [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ] aims to evaluate software testing techniques with a form
of white box testing, whereby a source program is changed in a localized way by
introducing a single (syntactic) fault. The resulting program is called a \mutant"
and hopefully is also semantically di erent from its ancestor. A testing suite
should recognize the faulted code, which is known as \killing" the mutant. The
higher the number of killed mutants, the better the testing suite.
      </p>
      <p>
        What is the connection with our endeavor? A killed mutant is a good
candidate for blame assignment, since it should simulate reasonable bugs that occur
in a program without being planted by ourselves. This is justi ed by the
\competent programmer assumption" [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ], according to which programmers tend to
develop programs close to the correct version and thus the di erence between
current and correct code for each fault is small. A mutator provides us
(automatically) with a multitude of faulty programs to try and explain. At the same time,
such a tool helps to gauge the e ectiveness of Check in locating bugs, under
its various strategies. In previous work we either had to use faulty models from
the literature [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ], or to resort to manual generation of mutants [
        <xref ref-type="bibr" rid="ref19">19</xref>
        ] to compare
      </p>
      <p>Check with other PBT tools | but this is obviously biased, labor-intensive
and very hard to scale.</p>
      <p>
        We have thus developed a mutator for Prolog programs, with an emphasis
on trying to devise mutation operators for our intended domain, namely
models of programming languages artifacts. Those operators specify the mutations
that the tool will inject and therefore a mutator is as e ective as operators are
relevant. Mutation testing comes from imperative languages and the operators
thereby are pretty useless. Even operators proposed for declarative programs [
        <xref ref-type="bibr" rid="ref9">9,
20</xref>
        ] make only partial sense. In particular those in [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ] not only are completely
oblivious of Prolog's type discipline, but mostly address the operational
semantics of Prolog: clause reordering, permutation of cuts etc. Those are not relevant
to us, since the checker uses a complete search strategy and does not understand
cuts.
      </p>
      <p>Keeping in mind that we strive to produce mutants that cannot be detected
already by static analysis such as type checking in Prolog or singleton variable
analysis in standard Prolog, we have converged on this initial set of operators:
Clause mutations: deletion of a predicate in the body of a clause, deleting the
whole clause if a fact. Replacement of disjunction by conjunction and vice
versa.</p>
      <p>Operator mutations: arithmetic and relational operator mutation, say &lt; in
.</p>
      <p>Variable mutations: replacing a variable with an (anonymous) variable and
vice versa.</p>
      <p>Constant mutations: replacing a constant by a constant (of the same type),
or by an (anonymous) variable and vice versa.</p>
      <p>Prolog-speci c Removing freshness annotations (#), changing their scope or
confusing them with equality.</p>
      <p>In our implementation, a simple driver produces a given number of randomly
generated mutants from an Prolog source P and a list LM of mutation
operators. At every generation step we make a random choice of operator in LM and
of clause in P such that the operator is applicable, in the spirit of [27]. If the
mutant is new, i.e., it has not been produced before, it is passed to the next
phase: here, we try to weed out semantically equivalent mutants following the
proposal in [23] of comparing them with their ancestor on a nite portion of
input. We achieve this by asking Check to try to refute their equivalence up to
a given bound. Keeping the bound small makes this a fairly quick, if imperfect,
lter. If the mutant survives, we pass it again to Check, this time under the
property that the original model was supposed to satisfy. If it fails, we go back
to the ow in Fig. 1.</p>
      <p>
        We have been experimenting with the mutation and explanation of three
main case studies:
1. The preservation and progress property for the typed arithmetic language
in Chapter 8 of [25].
2. Non-interference for static ow information systems, which we had started
to address in [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ].
3. Type preservation for low-level abstract machines, as in [
        <xref ref-type="bibr" rid="ref19">19</xref>
        ].
While the results are encouraging, we are still in the process of collecting
evidence.
5
      </p>
    </sec>
    <sec id="sec-6">
      <title>Conclusions and future work</title>
      <p>We have given an \appetizer" of our approach to blame assignment for
counterexamples found by PBT. We have used old-fashioned ideas in the literature,
such as abduction and explanation trees, trying to strike a reasonable balance
with declarative debugging: we only ask for the user's input when we let her
decide if the answer given by abduction is sensible; this is quite di erent, we
argue, from the the constant prodding that declarative debugging requires. Our
approach is also much simpler (perhaps simple-minded) than previous work
aiming to explain why a query is true or false in a model, typically under the answer
set semantics, as in e.g. [26].</p>
      <p>There is so much work that lies in front of us: we need to gather more
experience using the tool, especially with a user who is di erent from the authors.
This is particularly crucial for tuning the amount of details in proof verbalization.</p>
      <p>Mutation testing for Prolog is of independent interest, besides the way we
have used it here. It allows us to evaluate how well Check performs in spotting
bugged models, similarly to the interaction of MuCheck [20] with QuickCheck.
However, designing mutation operators that make sense in our intended domain
is an open question, see [24] for the more general issue of mutations vs. real
faults. The operators that we have proposed are a starting point, but it would
be nice to provide the user with a basic DSL to encode her own.</p>
      <p>Finally, the main drawback of the current setup is that we can play the blame
game only for Prolog programs that are indeed Prolog code, i.e. that do not use
the nominal features, since they cannot be faithfully replayed in standard Prolog.
The new version, already under development, will instead handle the whole of</p>
      <p>
        Prolog, by porting the blame tool to the latter, where Prolog's programs are
rei ed in object-level clauses following the two-level approach [
        <xref ref-type="bibr" rid="ref12">12</xref>
        ].
20. D. Le, M. A. Alipour, R. Gopinath, and A. Groce. Mucheck: An extensible tool
for mutation testing of haskell programs. In ISSTA 2014, pages 429{432. ACM,
2014.
21. X. Leroy. Formal veri cation of a realistic compiler. CACM, 52(7):107{115, 2009.
22. L. Naish. A declarative debugging scheme. Journal of Functional and Logic
Programming, 1997(3):3{29, 1997.
23. A. J. O utt and J. Pan. Automatically detecting equivalent mutants and infeasible
paths. Software Testing, Veri cation and Reliability, 7(3):165{192, 1997.
24. M. Papadakis, D. Shin, S. Yoo, and D.-H. Bae. Are mutation scores correlated
with real fault detection? ICSE '18, pages 537{548. ACM, 2018.
25. B. C. Pierce. Types and Programming Languages. MIT Press, 2002.
26. C. Viegas Damasio, A. Analyti, and G. Antoniou. Justi cations for logic
programming. In P. Cabalar and T. C. Son, editors, LPNMR, pages 530{542. Springer,
2013.
27. L. Zhang, M. Gligoric, D. Marinov, and S. Khurshid. Operator-based and random
mutant selection: Better together. In ASE, pages 92{102. IEEE, 2013.
      </p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1.
          <string-name>
            <given-names>J.</given-names>
            <surname>Blachette</surname>
          </string-name>
          .
          <article-title>Picking Nits: A User's Guide to Nitpick for Isabelle/HOL</article-title>
          . TUM,
          <year>2018</year>
          . http://isabelle.in.tum.de/dist/doc/nitpick.pdf.
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          2.
          <string-name>
            <given-names>R.</given-names>
            <surname>Blanco</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Z.</given-names>
            <surname>Chihani</surname>
          </string-name>
          , and
          <string-name>
            <given-names>D.</given-names>
            <surname>Miller</surname>
          </string-name>
          .
          <article-title>Translating between implicit and explicit versions of proof</article-title>
          .
          <source>In CADE</source>
          , volume
          <volume>10395</volume>
          <source>of LNCS</source>
          , pages
          <volume>255</volume>
          {
          <fpage>273</fpage>
          . Springer,
          <year>2017</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          3.
          <string-name>
            <given-names>R.</given-names>
            <surname>Caballero</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Riesco</surname>
          </string-name>
          , and
          <string-name>
            <given-names>J.</given-names>
            <surname>Silva</surname>
          </string-name>
          .
          <article-title>A survey of algorithmic debugging</article-title>
          .
          <source>ACM Comput. Surv.</source>
          ,
          <volume>50</volume>
          (
          <issue>4</issue>
          ):
          <volume>60</volume>
          :1{
          <fpage>60</fpage>
          :
          <fpage>35</fpage>
          ,
          <string-name>
            <surname>Aug</surname>
          </string-name>
          .
          <year>2017</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          4.
          <string-name>
            <given-names>J.</given-names>
            <surname>Cheney</surname>
          </string-name>
          and
          <string-name>
            <given-names>A.</given-names>
            <surname>Momigliano</surname>
          </string-name>
          .
          <article-title>Mechanized metatheory model-checking</article-title>
          .
          <source>In PPDP</source>
          , pages
          <volume>75</volume>
          {
          <fpage>86</fpage>
          . ACM,
          <year>2007</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          5.
          <string-name>
            <given-names>J.</given-names>
            <surname>Cheney</surname>
          </string-name>
          and
          <string-name>
            <given-names>A.</given-names>
            <surname>Momigliano</surname>
          </string-name>
          .
          <article-title>Check: A mechanized metatheory model checker</article-title>
          .
          <source>TPLP</source>
          ,
          <volume>17</volume>
          (
          <issue>3</issue>
          ):
          <volume>311</volume>
          {
          <fpage>352</fpage>
          ,
          <year>2017</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          6.
          <string-name>
            <given-names>J.</given-names>
            <surname>Cheney</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Momigliano</surname>
          </string-name>
          , and
          <string-name>
            <given-names>M.</given-names>
            <surname>Pessina</surname>
          </string-name>
          .
          <article-title>Advances in property-based testing for Prolog</article-title>
          . In B. K. Aichernig and
          <string-name>
            <surname>C.</surname>
          </string-name>
          <article-title>A</article-title>
          . Furia, editors,
          <source>TAP</source>
          , volume
          <volume>9762</volume>
          <source>of LNCS</source>
          , pages
          <volume>37</volume>
          {
          <fpage>56</fpage>
          . Springer,
          <year>2016</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          7.
          <string-name>
            <given-names>J.</given-names>
            <surname>Cheney</surname>
          </string-name>
          and
          <string-name>
            <given-names>C.</given-names>
            <surname>Urban</surname>
          </string-name>
          .
          <article-title>Nominal logic programming</article-title>
          .
          <source>ACM Trans. Program. Lang. Syst.</source>
          ,
          <volume>30</volume>
          (
          <issue>5</issue>
          ):
          <volume>26</volume>
          :1{
          <fpage>26</fpage>
          :
          <fpage>47</fpage>
          ,
          <year>2008</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          8.
          <string-name>
            <given-names>N.</given-names>
            <surname>Dershowitz</surname>
          </string-name>
          and
          <string-name>
            <given-names>Y.</given-names>
            <surname>Lee</surname>
          </string-name>
          .
          <article-title>Logical debugging</article-title>
          .
          <source>J. Symb. Comput.</source>
          ,
          <volume>15</volume>
          (
          <issue>5</issue>
          /6):
          <volume>745</volume>
          {
          <fpage>773</fpage>
          ,
          <year>1993</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          9.
          <string-name>
            <given-names>A.</given-names>
            <surname>Efremidis</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Schmidt</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Krings</surname>
          </string-name>
          , and
          <string-name>
            <given-names>P.</given-names>
            <surname>Ko</surname>
          </string-name>
          <article-title>rner. Measuring coverage of prolog programs using mutation testing</article-title>
          .
          <source>CoRR</source>
          , abs/
          <year>1808</year>
          .07725,
          <year>2018</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          10.
          <string-name>
            <given-names>G.</given-names>
            <surname>Fachini</surname>
          </string-name>
          and
          <string-name>
            <given-names>A.</given-names>
            <surname>Momigliano</surname>
          </string-name>
          .
          <article-title>Validating the meta-theory of programming languages</article-title>
          .
          <source>In SEFM</source>
          , volume
          <volume>10469</volume>
          <source>of LNCS</source>
          , pages
          <volume>367</volume>
          {
          <fpage>374</fpage>
          . Springer,
          <year>2017</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          11.
          <string-name>
            <given-names>A. P.</given-names>
            <surname>Felty</surname>
          </string-name>
          and
          <string-name>
            <given-names>A.</given-names>
            <surname>Momigliano</surname>
          </string-name>
          .
          <article-title>Reasoning with hypothetical judgments and open terms in Hybrid</article-title>
          .
          <source>In PPDP</source>
          , pages
          <volume>83</volume>
          {
          <fpage>92</fpage>
          . ACM,
          <year>2009</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          12.
          <string-name>
            <given-names>A. P.</given-names>
            <surname>Felty</surname>
          </string-name>
          and
          <string-name>
            <given-names>A.</given-names>
            <surname>Momigliano</surname>
          </string-name>
          .
          <article-title>Hybrid - A de nitional two-level approach to reasoning with higher-order abstract syntax</article-title>
          .
          <source>J. Autom. Reasoning</source>
          ,
          <volume>48</volume>
          (
          <issue>1</issue>
          ):
          <volume>43</volume>
          {
          <fpage>105</fpage>
          ,
          <year>2012</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          13. G. Fink and
          <string-name>
            <given-names>M.</given-names>
            <surname>Bishop</surname>
          </string-name>
          .
          <article-title>Property-based testing: a new approach to testing for assurance</article-title>
          .
          <source>ACM SIGSOFT Software Engineering Notes</source>
          , pages
          <volume>74</volume>
          {
          <fpage>80</fpage>
          ,
          <year>July 1997</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          14.
          <string-name>
            <given-names>W.</given-names>
            <surname>Hodges</surname>
          </string-name>
          .
          <article-title>Logical features of Horn clauses</article-title>
          . In D. M.
          <string-name>
            <surname>Gabbay</surname>
            ,
            <given-names>C. J.</given-names>
          </string-name>
          <string-name>
            <surname>Hogger</surname>
            , and
            <given-names>J. A</given-names>
          </string-name>
          . Robinson, editors,
          <source>Handbook of Logic in Arti cial Intelligence and Logic Programming (Vol. 1)</source>
          , pages
          <fpage>449</fpage>
          {
          <fpage>503</fpage>
          . Oxford University Press, Inc.,
          <year>1993</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref15">
        <mixed-citation>
          15.
          <string-name>
            <given-names>J.</given-names>
            <surname>Hughes</surname>
          </string-name>
          .
          <article-title>Quickcheck testing for fun and pro t</article-title>
          .
          <source>In PADL'07, LNCS</source>
          , pages
          <volume>1</volume>
          {
          <fpage>32</fpage>
          , Berlin, Heidelberg,
          <year>2007</year>
          . Springer-Verlag.
        </mixed-citation>
      </ref>
      <ref id="ref16">
        <mixed-citation>
          16.
          <string-name>
            <given-names>Y.</given-names>
            <surname>Jia</surname>
          </string-name>
          and
          <string-name>
            <given-names>M.</given-names>
            <surname>Harman</surname>
          </string-name>
          .
          <article-title>An analysis and survey of the development of mutation testing</article-title>
          .
          <source>IEEE Trans. Softw</source>
          . Eng.,
          <volume>37</volume>
          (
          <issue>5</issue>
          ):
          <volume>649</volume>
          {
          <fpage>678</fpage>
          ,
          <string-name>
            <surname>Sept</surname>
          </string-name>
          .
          <year>2011</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref17">
        <mixed-citation>
          17.
          <string-name>
            <surname>A. C. Kakas</surname>
            ,
            <given-names>R. A.</given-names>
          </string-name>
          <string-name>
            <surname>Kowalski</surname>
            , and
            <given-names>F.</given-names>
          </string-name>
          <string-name>
            <surname>Toni</surname>
          </string-name>
          .
          <article-title>Abductive logic programming</article-title>
          .
          <source>Journal of Logic and Computation</source>
          ,
          <volume>2</volume>
          (
          <issue>6</issue>
          ):
          <volume>719</volume>
          {
          <fpage>770</fpage>
          ,
          <year>1992</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref18">
        <mixed-citation>
          18.
          <string-name>
            <given-names>C.</given-names>
            <surname>Klein</surname>
          </string-name>
          and et al.
          <article-title>Run your research: on the e ectiveness of lightweight mechanization</article-title>
          .
          <source>In POPL '12</source>
          , pages
          <fpage>285</fpage>
          {
          <fpage>296</fpage>
          , New York, NY, USA,
          <year>2012</year>
          . ACM.
        </mixed-citation>
      </ref>
      <ref id="ref19">
        <mixed-citation>
          19.
          <string-name>
            <given-names>F.</given-names>
            <surname>Komauli</surname>
          </string-name>
          and
          <string-name>
            <given-names>A.</given-names>
            <surname>Momigliano</surname>
          </string-name>
          .
          <article-title>Property-based testing of the meta-theory of abstract machines: an experience report</article-title>
          . In CILC, volume
          <volume>2214</volume>
          <source>of CEUR</source>
          , pages
          <volume>22</volume>
          {
          <fpage>39</fpage>
          ,
          <year>2018</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>