<!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>Debugging Programs using Formal Concept Analysis</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Artem Revenko</string-name>
          <email>viktorovich.revenko@mailbox.tu-dresden.de</email>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>National Research University Higher School of Economics Pokrovskiy bd.</institution>
          <addr-line>11, 109028 Moscow</addr-line>
          ,
          <country>Russia artem</country>
        </aff>
        <aff id="aff1">
          <label>1</label>
          <institution>Technische Universitat Dresden Zellescher Weg 12-14</institution>
          ,
          <addr-line>01069 Dresden</addr-line>
          ,
          <country country="DE">Germany</country>
        </aff>
      </contrib-group>
      <fpage>105</fpage>
      <lpage>112</lpage>
      <abstract>
        <p>The classi cation of possible errors in object intents is given and some possibilities of exploring them are discussed. Two techniques for nding some types of errors in new object intents are introduced. After comparing the better technique is developed further in order to guarantee the absence of certain errors given enough information. Based on this technique an approach for debugging source code is presented and discussed. It is shown that the new approach yields bug hypothesis in a strict logical form. Using the new approach it is possible to come closer to debugging programs on a logical level not checking executions line by line. An example of applying the new approach is presented.</p>
      </abstract>
      <kwd-group>
        <kwd>formal context analysis</kwd>
        <kwd>implication</kwd>
        <kwd>debugging</kwd>
      </kwd-group>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>-</title>
      <p>
        In this work we present a new approach to debug programs. This work was
inspired by the Delta Debugger project [
        <xref ref-type="bibr" rid="ref13">13</xref>
        ] where authors discuss the possibilities
of automatic debugging, namely isolation of failure-inducing inputs. However,
when it comes to nding actual causes of the failure it is still not possible to
automatically explain the failure logically. In some cases the nearest neighbour
technique yields good results, but usually near-probabilistic criteria like coverage
or chi-square are used [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ]. In this work we use recent advance in Formal Concept
Analysis in an attempt to nd logical dependencies between fails and successful
runs of a program. Several studies were performed to discover the possibilities
of using Formal Concept Analysis in software development. For example, in [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ]
and [
        <xref ref-type="bibr" rid="ref6">6</xref>
        ] authors use Formal Concept Analysis for building class hierarchies. In [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ]
FCA is used to determine dependencies on program trace. Authors reveal causal
dependencies and even are able to nd "likely invariants\ of program in special
cases. However, they do not consider the possibility of debugging. However, to
our best knowledge there are no works about applying Formal Concept Analysis
to program debugging.
      </p>
      <p>In this paper we rst introduce a new technique for nding errors in new
object intents. This technique was rst introduced in our previous work; we partly
repeat the results and refer to our previous work for more details. In this paper
we recall two di erent approaches for revealing errors in new object intents: one
based on computing the implication system of the context and another one based
on computing the closures of the subsets of the new object intent. Since
computing closures may be performed much faster we improve and generalize this
approach and nally obtain a procedure for nding all possible errors of the
considered types. We also provide experimental results to compare two approaches.
After that we present a new approach of debugging based on the discussed above
technique of nding errors in data. An example of debugging is provided.</p>
      <p>All sets and contexts we consider in this paper are assumed to be nite.
2</p>
    </sec>
    <sec id="sec-2">
      <title>Main De nitions</title>
      <p>Let G and M be sets. Let I G M be a binary relation between G and M .
Triple K := (G; M; I) is called a (formal) context.</p>
      <p>The set G is called a set of objects. The set M is called a set of attributes.</p>
      <p>Consider mappings ' : 2G ! 2M and : 2M ! 2G: '(X) := fm 2 M j
gIm for all g 2 Xg; (A) := fg 2 G j gIm for all m 2 Ag: For any X1; X2
G, A1; A2 M one has
Mappings ' and de ne a Galois connection between (2G; ) and (2M ; ), i.e.
'(X) A , (A) X. Usually, instead of ' and a single notation ( )0 is
used. ( )0 is sometimes called a derivation operator. For X G the set X0 is
called the intent of X and is denoted int(X). Similarly, for A M the set A0 is
called the extent of A and is denoted ext(A).</p>
      <p>Let Z M or Z G. (Z)00 is called the closure of Z in K. Applying Properties
1 and 2 consequently one gets the monotonicity property: for any Z1; Z2 G or
Z1; Z2 M one has Z1 Z2 ) Z100 Z200.</p>
      <p>Let m 2 M; X G, then m is called a negated attribute. m 2 X0 whenever no
x 2 X satis es xIm. Let A M ; A X0 i all m 2 A satisfy m 2 X0.</p>
      <p>An implication of K := (G; M; I) is de ned as a pair (A; B), written A ! B,
where A; B M . A is called the premise, B is called the conclusion of the
implication A ! B. The implication A ! B is respected by a set of attributes
N if A * N or B N . The implication A ! B holds (is valid) in K if it is
respected by all g0, g 2 G, i.e. every object, that has all the attributes from A,
also has all the attributes from B. Implications satisfy Armstrong rules :
A ! A
;</p>
      <p>A ! B
A [ C ! B
;</p>
      <p>A ! B; B [ C ! D</p>
      <p>A [ C ! D
A support of an implication in context K is the set of all objects of K, whose
intents contain the premise and the conclusion of the implication. A unit
implications is de ned as an implication with only one attribute in the conclusion,
i.e. A ! b, where A M; b 2 M . Every implication A ! B can be regarded as
the set of unit implications fA ! b j b 2 Bg. One can always observe only unit
implications without loss of generality.</p>
      <p>An implication basis of a context K is de ned as a set L of implications of K,
from which any valid implication for K can be deduced by the Armstrong rules
and none of the proper subsets of L has this property.</p>
      <p>
        A minimal implication basis is an implication basis minimal in the number of
implications. A minimal implication basis was de ned in [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ] and is known as
the canonical implication basis. In paper [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ] the premises of implications from
the canonical base were characterized in terms of pseudo-intents. A subset of
attributes P M is called a pseudo-intent, if P 6= P 00 and for every
pseudointent Q such that Q P , one has Q00 P . The canonical implication basis
looks as follows: fP ! (P 00 n P ) j P - pseudo-intentg.
      </p>
      <p>We say that an object g is reducible in a context K := (G; M; I) i 9X G :
g0 = T j0.</p>
      <p>j2X
3</p>
    </sec>
    <sec id="sec-3">
      <title>Types of Errors</title>
      <p>In this section we use the idea of data domain dependency. Usually objects and
attributes of a context represent entities. Dependencies may hold on attributes of
such entities. However, such dependencies may not be implications of a context
as a result of an error in object intents. Thereby, data domain dependencies
are such rules that hold on data represented by objects in a context, but may
erroneously be not valid implications of a context.</p>
      <p>In this work we consider only dependencies that do not have negations
of attributes in premises. As mentioned above there is no need to specially
observe non-unit implications. Consider possible types of such dependencies
(A M; b; c 2 M ):
The types 1 and 2 are most simple and common dependencies. In this work we
try to nd the algorithm to reveal these two types of dependencies and nd
corresponding errors.
4</p>
    </sec>
    <sec id="sec-4">
      <title>Finding Errors</title>
      <p>Below we assume that we are given a context (possibly empty) with correct data
and a number of new object intents that may contain errors. This data is taken
from some data domain and we may ask an expert whose answers are always
1. A ! b
2. A ! b
3. A ! b _ c
4. A ! , where
= a _ (b ^ c)</p>
      <p>is any logical formula not considered above, for example,
correct. However, we should ask as few questions as possible.</p>
      <p>We introduce two di erent approaches to nding errors. The rst one is based
on inspecting the canonical basis of a context. When adding a new object to the
context one may nd all implications from the canonical basis of the context
such that the implications are not respected by the intent of the new object.
These implications are then output as questions to an expert in form of unit
implications. If at least one of these implications is accepted, the object intent
is erroneous. Since the canonical basis is the most compact (in the number of
implications) representation of all valid implications of a context, it is guaranteed
that the minimal number of questions is asked and no valid dependencies of Type
1 are left out.</p>
      <p>
        Although this approach allows one to reveal all dependencies of Type 1, there
are several issues. The problem of producing the canonical basis with known
algorithms is intractable. Recent theoretical results suggest that the canonical
base can hardly be computed with better worst-case complexity than that of the
existing approaches ([
        <xref ref-type="bibr" rid="ref3">3</xref>
        ], [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]). One can use other bases (for example, see progress
in computing proper premises [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ]), but the algorithms known so far are still
too costly and non-minimal bases do not guarantee that the expert is asked the
minimal su cient number of questions.
      </p>
      <p>However, since we are only interested in implications corresponding to an
object, it may be not necessary to compute a whole implication basis. Here is
the second approach. Let A M be the intent of the new object not yet added
to the context. m 2 A00 i 8g 2 G : A g0 ) m 2 g0, in other words, A00
contains the attributes common to all object intents containing A. The set of
unit implications fA ! b j b 2 A00 n Ag can then be shown to the expert. If all
implications are rejected, no attributes are forgotten in the new object intent.
Otherwise, the object is erroneous. This approach allows one to nd errors of
Type 1.
5</p>
    </sec>
    <sec id="sec-5">
      <title>Improvements</title>
      <p>Obviously, applying the derivation operator two times is a much easier task than
computing the canonical basis, and can be performed in polynomial time.
However, the following case is possible. Let A M be the intent of the new object
such that @g 2 G : A g0. In this case A00 = M and the implication A ! A00 n A
has empty support. This may indicate an error of Type 2, because the object
intent contains a combination of attributes impossible in the data domain, but
the object may be correct as well. An expert could be asked if the combination
of attributes in the object intent is consistent in the data domain. For such a
question the information already input in the context is not used. More than
that, this question is not su cient to reveal an error of Type 1.
Proposition 1. Let K = (G; M; I); A</p>
      <p>M . The set</p>
      <p>IA = fB ! d j B 2 MCA; d 2 B00 n A [ A n Bg;
where MCA = fB 2 CAj@C 2 CA : B Cg and CA = fA \ g0 j g 2 Gg, is the set
of all unit implications (or their non-trivial consequences with some attributes
added in the premise) of Types 1 and 2 such that implications are valid in K,
not respected by A, and have not empty support.</p>
      <p>Proposition 1 allows one to nd an algorithm for computing the set of
questions to an expert revealing possible errors of Types 1 and 2. The pseudocode is
pretty straightforward and is not shown here for the sake of compactness.
Since computing the closure of a subset of attributes takes O(jGj jM j) time in
the worst case, and we need to compute respective closures for every object in
the context, the time complexity of the whole algorithm is O(jGj2 jM j).
We may now conclude that we are able to nd possibly broken dependencies of
two most common types in new objects. However, this does not always indicate
broken real dependency, as we not always have enough information already input
in our context. That is why we may only develop a hypothesis and ask an expert
if it holds.</p>
      <p>
        For more details, example, and proof of Proposition 1, please, refer to [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ].
6
6.1
      </p>
    </sec>
    <sec id="sec-6">
      <title>Debugging</title>
      <sec id="sec-6-1">
        <title>Context Preparation</title>
        <p>Normally debugging starts with a failure report. Such a report contains the input
on which the program failed. By this we mean that our program was not able to
output the expected result or did not nish at all. This implicitly de nes \goal"
function which is capable of determining either a program run was successful
or not. We could imagine a case where we do not have any successful inputs,
i.e. those inputs which were processed successfully by the program. However, it
does not seem reasonable. In a such a case the best option seems to rewrite the
code or look for obvious mistakes. Modern techniques of software development
suggests running tests even before writing code itself; unless the tests are passed
code is not considered nished. Therefore, successful inputs are at least those
contained in the test suites.</p>
        <p>As discussed in the beginning of this paper the problem of nding appropriate
inputs was considered by di erent authors. This problem is indeed of essential
importance for debugging. However, we do not aim at solving it. Instead we
assume that inputs are already found (using user reports, random generator, or
something else), processed (it is better if inputs are minimized, however, not
necessary), and are at hands. We focus on processing the program runs on given
inputs.</p>
        <p>Our approach consists in the following. We construct two contexts: rst with
successful runs as objects, second with failed runs. In both cases attributes are
the lines of the code (conveniently presented via line numbers). We put a cross if
during processing of the input the program has covered the corresponding line.
So in both cases we record the information about covered lines during processing
of the inputs. After contexts are ready we treat all the objects from the context
with failed runs as new objects and try to nd errors as described in the previous
sections. Expected output is an implication A ! B. The interpretation is as
follows; in successful runs whenever lines numbers A are covered, lines numbers
B are covered as well. For some reason in the inspected failed run this is not
the case. Debugging consists now in nding this reason. This is not absolutely
automatic debugging, however, we receive some more clues and may nd a bug
without checking the written code line by line. More than that, this approach is
strict, that is we say that it always happens, not with any probability. And it
corresponds to the real situation: the bug is there, not with any probability.
6.2</p>
      </sec>
      <sec id="sec-6-2">
        <title>Example</title>
        <p>
          Consider the following function written in Python (example taken from [
          <xref ref-type="bibr" rid="ref12">12</xref>
          ]):
        </p>
        <p>
          Listing 1.1: remove html markup [
          <xref ref-type="bibr" rid="ref12">12</xref>
          ]
1 def remove html markup ( s ) :
2 t a g = F a l s e
3 q u o t e = F a l s e
4 out = " "
5 f o r c in s :
6 i f ( c == '&lt; ' and
7 not q u o t e ) :
8 t a g = True
9 e l i f ( c == '&gt; ' and
10 not q u o t e ) :
11 t a g = F a l s e
12 e l i f ( c == ' " ' or
13 c == " ' " and
14 t a g ) :
15 q u o t e = not q u o t e
16 e l i f not t a g :
17 out = out + c
18 return out
        </p>
        <p>The goal of the function, as follows from its name, is to remove html markup
from the input, no matter if it occurs inside or outside quotes. Therefore, we
may formulate our goal as: no &lt; in output. Such a formulation does not allow us
to catch all the bugs (check input "foo" in contexts below), but it su ces for
our purposes.</p>
        <p>The function works as follows. After initialisation we have four \if" cases. The
rst and the second one checks if we have encountered a tag symbol outside of
quotes. If so, the value of \tag" is changed. The third one checks if we have
encountered a quote symbol inside tag. This is important for not closing a tag
if the closing symbol happens to be in one of the parameters (see inputs). If so,
the value of \quote" is changed. The last \if" adds the current character to the
output if we are outside the tag.</p>
        <p>We consider the following set of inputs: foo, &lt;b&gt;foo&lt;/b&gt;, "&lt;b&gt;foo&lt;/b&gt;",
"&lt;b&gt;a&lt;/b&gt;", "&lt;b&gt;&lt;/b&gt;", "&lt;&gt;", "foo", 'foo', &lt;em&gt;foo&lt;/em&gt;, "", &lt;""&gt;, &lt;p&gt;,
&lt;a href="&gt;"&gt;foo&lt;/a&gt;</p>
        <p>Using the given outputs we obtain two contexts:
Context with successful inputs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
foo
&lt;b&gt;foo&lt;/b&gt;
"foo"
'foo'
&lt;em&gt;foo&lt;/em&gt;
&lt;a href="&gt;"&gt;foo&lt;/a&gt;
""
&lt;""&gt;
&lt;p&gt;
"&lt;b&gt;foo&lt;/b&gt;"
"&lt;b&gt;a&lt;/b&gt;"
"&lt;b&gt;&lt;/b&gt;"
"&lt;&gt;"
Context with failed inputs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18</p>
        <p>It is easy to notice that the only di erence between failed inputs as context
objects is their names.</p>
        <p>Adding any of failed inputs to the rst context yields the following implication:
7; 13; 15 ! 8; 11
What is essentially said is if we happened to cover lines 7, 13, 15, we should have
also had been inside tag (lines 8 and 11). Given some thought and attention we
realize that this is absolutely true, because it is not clear how we could reach
line 15 without having \tag"= true, as this condition is checked in line 14.
In Python as well as in many other languages logical operation \and" has a higher
priority as \or", so condition of the third \if" (c == '"' or c == "'" and
tag) is implicitly transformed in (c == '"' or (c == "'" and tag)), that is
why on lines 12 and 13 brackets are forgotten. After debugging the condition
should look as follows: ((c == '"' or c == "'") and tag) and the program
runs correctly.</p>
      </sec>
    </sec>
    <sec id="sec-7">
      <title>Conclusion</title>
      <p>A technique for nding errors of two types in new object intents is presented.
As opposed to nding the canonical basis of the context the proposed algorithm
terminates much faster. Based on this technique an approach for debugging
source code is presented. This approach is capable of nding strict dependencies
between lines of source code covered in successful and failed runs. The output is
a logical expression which allows to debug the source code using the logic of the
program. This may get us one step closer to automated debugging.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1.
          <string-name>
            <given-names>Mikhail</given-names>
            <surname>Babin</surname>
          </string-name>
          and
          <string-name>
            <given-names>Sergei O.</given-names>
            <surname>Kuznetsov</surname>
          </string-name>
          .
          <article-title>Recognizing pseudo-intent is conpcomplete</article-title>
          .
          <source>Proc. 7th International Conference on Concept Lattices and Their Applications</source>
          , University of Sevilla, pages
          <volume>294</volume>
          {
          <fpage>301</fpage>
          ,
          <year>2010</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          2.
          <string-name>
            <given-names>Holger</given-names>
            <surname>Cleve</surname>
          </string-name>
          and
          <string-name>
            <given-names>Andreas</given-names>
            <surname>Zeller</surname>
          </string-name>
          .
          <article-title>Locating causes of program failures</article-title>
          .
          <source>In GruiaCatalin Roman</source>
          , William G. Griswold, and Bashar Nuseibeh, editors,
          <source>ICSE</source>
          , pages
          <volume>342</volume>
          {
          <fpage>351</fpage>
          . ACM,
          <year>2005</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          3.
          <string-name>
            <given-names>Felix</given-names>
            <surname>Distel</surname>
          </string-name>
          and
          <article-title>Bar s Sertkaya. On the complexity of enumerating pseudo-intents</article-title>
          .
          <source>Discrete Applied Mathematics</source>
          ,
          <volume>159</volume>
          (
          <issue>6</issue>
          ):
          <volume>450</volume>
          {
          <fpage>466</fpage>
          ,
          <year>2011</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          4.
          <string-name>
            <given-names>Bernhard</given-names>
            <surname>Ganter</surname>
          </string-name>
          .
          <article-title>Two basic algorithms in concept analysis</article-title>
          .
          <source>Preprint-Nr. 831</source>
          ,
          <year>1984</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          5.
          <string-name>
            <given-names>Bernhard</given-names>
            <surname>Ganter</surname>
          </string-name>
          , Gerd Stumme, and Rudolf Wille, editors.
          <source>Formal Concept Analysis, Foundations and Applications</source>
          , volume
          <volume>3626</volume>
          of Lecture Notes in Computer Science. Springer,
          <year>2005</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          6.
          <string-name>
            <given-names>Robert</given-names>
            <surname>Godin</surname>
          </string-name>
          and
          <string-name>
            <given-names>Petko</given-names>
            <surname>Valtchev</surname>
          </string-name>
          .
          <article-title>Formal concept analysis-based class hierarchy design in object-oriented software development</article-title>
          .
          <source>In Ganter et al. [5]</source>
          , pages
          <fpage>304</fpage>
          {
          <fpage>323</fpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          7.
          <string-name>
            <surname>J.-L. Guigues</surname>
            and
            <given-names>V.</given-names>
          </string-name>
          <string-name>
            <surname>Duquenne</surname>
          </string-name>
          .
          <article-title>Familles minimales d'implications informatives resultant d'un tableau de donnees binaires</article-title>
          .
          <source>Math. Sci. Hum</source>
          ,
          <volume>24</volume>
          (
          <issue>95</issue>
          ):
          <volume>5</volume>
          {
          <fpage>18</fpage>
          ,
          <year>1986</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          8. John L. Pfaltz.
          <article-title>Using concept lattices to uncover causal dependencies in software</article-title>
          .
          <source>In Proc. Int. Conf. on Formal Concept Analysis</source>
          ,
          <source>Springer LNAI 3874</source>
          , pages
          <fpage>233</fpage>
          {
          <fpage>247</fpage>
          ,
          <year>2006</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          9.
          <string-name>
            <given-names>Artem</given-names>
            <surname>Revenko</surname>
          </string-name>
          and
          <string-name>
            <given-names>Sergei O.</given-names>
            <surname>Kuznetsov</surname>
          </string-name>
          .
          <article-title>Finding errors in new object intents</article-title>
          .
          <source>In CLA 2012</source>
          , pages
          <fpage>151</fpage>
          {
          <fpage>162</fpage>
          ,
          <year>2012</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          10.
          <string-name>
            <surname>Uwe</surname>
            <given-names>Ryssel</given-names>
          </string-name>
          , Felix Distel, and
          <string-name>
            <given-names>Daniel</given-names>
            <surname>Borchmann</surname>
          </string-name>
          .
          <article-title>Fast computation of proper premises</article-title>
          .
          <source>In Amedeo Napoli and Vilem Vychodil</source>
          , editors,
          <source>International Conference on Concept Lattices and Their Applications</source>
          , pages
          <volume>101</volume>
          {
          <fpage>113</fpage>
          . INRIA Nancy {
          <article-title>Grand Est</article-title>
          and
          <string-name>
            <surname>LORIA</surname>
          </string-name>
          ,
          <year>2011</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          11.
          <string-name>
            <given-names>Gregor</given-names>
            <surname>Snelting</surname>
          </string-name>
          and
          <string-name>
            <given-names>Frank</given-names>
            <surname>Tip</surname>
          </string-name>
          .
          <article-title>Reengineering class hierarchies using concept analysis</article-title>
          .
          <source>SIGSOFT Softw. Eng. Notes</source>
          ,
          <volume>23</volume>
          (
          <issue>6</issue>
          ):
          <volume>99</volume>
          {
          <fpage>110</fpage>
          ,
          <string-name>
            <surname>November</surname>
          </string-name>
          <year>1998</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          12.
          <string-name>
            <given-names>Andreas</given-names>
            <surname>Zeller</surname>
          </string-name>
          .
          <article-title>Software debugging course</article-title>
          . https://www.udacity.com/course/cs259.
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          13.
          <string-name>
            <given-names>Andreas</given-names>
            <surname>Zeller</surname>
          </string-name>
          and
          <string-name>
            <given-names>Ralf</given-names>
            <surname>Hildebrandt</surname>
          </string-name>
          .
          <article-title>Simplifying and isolating failure-inducing input</article-title>
          .
          <source>IEEE Trans. Software Eng.</source>
          ,
          <volume>28</volume>
          (
          <issue>2</issue>
          ):
          <volume>183</volume>
          {
          <fpage>200</fpage>
          ,
          <year>2002</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>