<!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 Program Code Using Implicative Dependencies</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>
      <abstract>
        <p>Based on the technique for nding errors in new object intents a method of debugging source code is presented. This method is capable of nding strict implicative dependencies between lines of source code covered in successful and failed runs. The output is a logical expression. Using the new method 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 method is presented. Possibilities of further development are discussed.</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>Introduction</title>
      <p>
        Automatic debugging is not a new topic in science and is investigated by many
computer scientist. For example, in [
        <xref ref-type="bibr" rid="ref16">16</xref>
        ] authors investigate a novel method of
\relative debugging" which consists in comparing particular values of data
structures. In [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ] and [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ] authors survey di erent approaches to automatic debugging.
In the well known work [19] the Delta Debugger tool is presented; authors
introduce an approach to 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. Usually near-probabilistic criteria like chi-square are
used [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ]. Somehow it does not correspond to the correctness of the program as
a program bug is either present or not.
      </p>
      <p>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.
For example, it could be that as long as a particular part of \if" statement
is not covered during the program run (i.e. a particular conditional clause is
not satis ed) the program runs successfully; this would mean that a bug lies
probably in this particular part of the program.</p>
      <p>Implications which can be derived from data tables (formal context)
represent strong logical dependencies between attributes. We use this advantage of
implications to introduce a way of debugging program code following the logic
of a program.</p>
      <p>
        Several studies were performed to discover the possibilities of using Formal
Concept Analysis in software development. For example, in [17] and [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ] authors
use Formal Concept Analysis for building class hierarchies. In [
        <xref ref-type="bibr" rid="ref13">13</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. A
very interesting work on fault localization is presented in [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ]. However, to our
best knowledge there are no works about applying Formal Concept Analysis to
program debugging.
      </p>
      <p>
        In our previous work [
        <xref ref-type="bibr" rid="ref14">14</xref>
        ] we have introduced two approaches to revealing
errors in new object intents. In this paper we recall them; one is based on
computing the implication system of the context and another one is 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.
      </p>
      <p>After that we present a method of debugging based on the discussed above
technique of nding errors in data. We provide an example and discuss the
possibilities of further development.
2</p>
    </sec>
    <sec id="sec-2">
      <title>Main De nitions</title>
      <p>
        In what follows we keep to standard de nitions of FCA [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ]. Let G and M be sets
and 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: Mappings ' and
de ne a Galois connection between (2G; ) and (2M ; ), i.e. '(X) A ,
(A) X. Hence, for any X1; X2 G, A1; A2 M one has
Usually, instead of ' and a single notation ( )0 is used. ( )0 is usually called a
derivation operator. For X G the set X0 is called the intent of X. Similarly,
for A M the set A0 is called the extent of 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="ref11">11</xref>
        ] and is known as the
canonical implication basis. In [
        <xref ref-type="bibr" rid="ref6">6</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 pseudo-intent 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</p>
      <p>All sets and contexts we consider in this paper are assumed to be nite.
3</p>
    </sec>
    <sec id="sec-3">
      <title>Finding 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>Every object in a context is described by its intent. In the data domain
there may exist dependencies between attributes. 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. In this work
we try to nd the algorithm to reveal the following two most simple and common
types of dependencies (A M; b; c 2 M ):
1. If there is A in an object intent, there is also b, which is represented by the
implication A ! b
2. If there is A in an object intent, there is no b, which can be symbolically
represented as A ! b
If we have no errors in a context, all the dependencies of Type 1 are deducible
from implication basis. However, if we have not yet added enough objects in the
context, we may get false consequence. Nevertheless, it is guaranteed that none
of valid dependencies is lost, and, as we add objects without errors we reduce
the number of false consequences from the implication basis.</p>
      <p>The situation is di erent if we add an erroneous object. It may violate a
dependency valid in the data domain. In this case, until we nd and correct the
error, we are not able to deduce all dependencies valid in the data domain from
the implication basis, no matter how many correct objects we add afterwards.</p>
      <p>We aim to restore valid dependencies and therefore correct errors.</p>
      <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 correct. However, we should ask as few questions as possible.</p>
      <p>We quickly recall two di erent approaches to nding errors introduced in
our previous works. 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 even with polynomial delay ([
        <xref ref-type="bibr" rid="ref5">5</xref>
        ], [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ], [
        <xref ref-type="bibr" rid="ref12">12</xref>
        ]). One can
use other bases (for example, see progress in computing proper premises [
        <xref ref-type="bibr" rid="ref15">15</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.</p>
      <p>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.</p>
      <p>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).</p>
      <p>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 the proof of Proposition 1, please, refer to
[
        <xref ref-type="bibr" rid="ref14">14</xref>
        ].
4
4.1
      </p>
    </sec>
    <sec id="sec-4">
      <title>Debugging</title>
      <sec id="sec-4-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
suggest 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 method 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 the processing of the input the program has covered the corresponding
line. So in both cases we record the information about covered lines during the
processing of the inputs. After the 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 implication of the form A ! B. The
interpretation is as follows: in successful runs whenever lines A are covered, lines
B are covered as well. However, in the inspected failed run lines A were covered
and lines B were not covered. Debugging consists now in nding the reason why
lines B were not covered in the processing of the failed run.</p>
        <p>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 method is logically strict, it does not deal with any kind of
probability. This corresponds to the real situation: the bug is or is not there,
not with any probability.
4.2</p>
      </sec>
      <sec id="sec-4-2">
        <title>Example</title>
        <p>Consider the following function written in Python (example taken from [18]):</p>
        <p>Listing 1.1: remove html markup [18]
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 (as seen from the contexts below the input "foo" has
enabled the program to reach the line 15 which should not have happened, but
it is considered as a successful run), 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>We run the function on every input and check if the output contains the
symbol \&lt;". If it does not, the run was successful. We also record the lines
coverage during every run, gather this information, and construct two context:</p>
        <p>It is easy to notice that in the processing of every failed input the same
lines are covered. Therefore, the only di erence between di erent objects in the
context with failed runs is the names of the objects.</p>
        <p>Inspecting any of the failed inputs in the context with successful runs using
the described above technique for nding errors yields the following implication:
7; 13; 15 ! 8; 11</p>
        <p>What is essentially said is the following: in a successful run if the lines 7, 13,
and 15 were covered then the lines 8 and 11 were also covered; in every failed
run the lines 7, 13, and 15 were covered, but the lines 8 and 11 were not covered.
We now expect the mentioned above lines and their impact to the program run.</p>
        <p>If the line 7 is covered then the condition in the line 6 was met. Therefore,
the line 7 is covered whenever there is the symbol \&lt;" in the input.</p>
        <p>If the line 13 is covered then the condition in the line 12 was not met and the
conditions of the rst two \if" clauses were not met. This means that for some
symbol from the input we should not change the value of \tag" and the symbol
is not \"".</p>
        <p>If the line 15 was covered then the condition of the third \if" clause was met
and the conditions of the rst two \if" clauses were not met. Therefore, some
symbol in the input was either \"" or \'" and the \tag" was set to True.</p>
        <p>If the line 8 was not covered then the value of \tag" was never set to True
(because we do not have this variable set to True elsewhere in our program and
originally it is initialized to False). There is no need to go further to the line 11
in our investigation, because we have already found a contradiction. The value
of \tag" should have been set to True to reach the line 15, but it was never set
to True. From this we can deduce that possibly the condition of the third \if"
clause erroneously evaluates to True without checking that \tag" equals True.</p>
        <p>The key to this puzzle is the following. In Python as well as in many other
languages logical operation \and" has a higher priority than \or", so condition
of the third \if" (c == '"' or c == "'" and tag) is implicitly transformed
in (c == '"' or (c == "'" and tag)). In other words 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.
4.3</p>
      </sec>
      <sec id="sec-4-3">
        <title>Further Development</title>
        <p>The sequence in which the lines of code were covered contains even more
information about the execution of a program. This information may reveal even
more dependencies in the working ow of a program. It may also happen that
the only di erence between successful and failed runs is in the sequence in which
the lines are covered, whereas the set of covered lines remains the same. In this
manner we also take into account the sequential aspect of the loop that is not
taken into account in the previous example.</p>
        <p>It is not di cult to extend the introduced method with this new feature.
For this purpose we change the attributes of our context. Now an attribute
contains two numbers: the rst number corresponds to the preceding covered
line and the second number corresponds to the succeeding covered line. The
information from the original modi cation of the method may still be captured
with attributes that have the same line number two times. However, we may
be not interested in the absolute precedence relation between the lines, because
this information is excessive and di cult to interpret while the size of the set of
attributes increases dramatically. That is why we also introduce a new parameter
containing information about the delay of interest. Below we are only interested
in the precedence relation within this delay, i.e. not more than the dealy number
of lines should be covered between the two speci ed lines in order to add them
to the relation I.</p>
        <p>The number of attributes for this case, assuming that any line may precede
and succeed any other line including itself, is jM jd, where d is the delay.</p>
        <p>Unfortunately, the result obtained using this modi cation may be di cult to
interpret even if the delay is small. It makes sense to consider this modi cation
only if the standard modi cation does not yield any results.</p>
        <p>For the remove_html_markup function and d = 1 we obtain the following
results:
1. (10; 10); (12; 15) ! (8; 8); (11; 11); (10; 11); (11; 5); (9; 10); (7; 8);
(17; 17); (9; 12); (15; 5); (13; 13); (13; 16); (16; 16); (16; 17);
2. (17; 17); (15; 5) ! (10; 10); (7; 7);
3. (13; 13); (15; 15); (7; 7) ! (9; 12); (16; 17); (12; 15); (15; 5);</p>
        <p>(8; 8); (11; 11); (10; 11); (11; 5); (9; 10); (7; 8); (12; 13).</p>
        <p>In the result we still have the same obtained dependency as we had before,
namely Implication 3. However, we have two more obtained results that reveal
more structural features of the bug. An interpretation of this result is left to the
reader.</p>
        <p>For example, we consider Implication 1. Actually already in the premise of
this implication we can recognize a clue to nding the bug. Indeed, having a
pair 12 and 15 with delay 1 means the following: after the line 12 the execution
jumped to the line 15. After checking only condition in the line 12 (which
happened to be true) execution jumped to the consequence. As already described,
the interpreter has understood the condition as a disjunction and has only
evaluated the rst expression (which would be enough in case of disjunction).
5</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>Conclusion</title>
      <p>Based on the procedure for nding errors in new object intents a method of
debugging source code was proposed. This method nds strict dependencies
between source code coverage in successful and failed runs. The output of the
debugging method is a logical expression which allows one to nd bugs following
the implicit logic of the program. Further modi cation of the method is possible
(described above), however, it leads to results that are di cult to interpret.
Acknowledgements The author was supported by German Academic
Exchange Service (DAAD).</p>
      <p>Author thanks Sergei Kuznetsov and other participants of the project
Mathematical Models, Algorithms, and Software Tools for Intelligent Analysis of
Structural and Textual Data supported by the Basic Research Program of the
National Research University Higher School of Economics for discussion and useful
remarks.
17. Gregor Snelting and Frank Tip. Reengineering class hierarchies using concept
analysis. SIGSOFT Softw. Eng. Notes, 23(6):99{110, November 1998.
18. Andreas Zeller. Software debugging course.</p>
      <p>https://www.udacity.com/course/cs259.
19. Andreas Zeller and Ralf Hildebrandt. Simplifying and isolating failure-inducing
input. IEEE Trans. Software Eng., 28(2):183{200, 2002.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1.
          <string-name>
            <given-names>Hiralal</given-names>
            <surname>Agrawal</surname>
          </string-name>
          .
          <article-title>Towards automatic debugging of computer programs</article-title>
          .
          <source>Technical report, ph.d. thesis</source>
          , Purdue University,
          <year>1991</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          2.
          <string-name>
            <surname>Mikhail</surname>
            <given-names>A.</given-names>
          </string-name>
          <string-name>
            <surname>Babin</surname>
            and
            <given-names>Sergei O.</given-names>
          </string-name>
          <string-name>
            <surname>Kuznetsov</surname>
          </string-name>
          .
          <article-title>Computing premises of a minimal cover of functional dependencies is intractable</article-title>
          .
          <source>Discrete Applied Mathematics</source>
          ,
          <volume>161</volume>
          (
          <issue>6</issue>
          ):
          <volume>742</volume>
          {
          <fpage>749</fpage>
          ,
          <year>2013</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          3.
          <string-name>
            <given-names>Peggy</given-names>
            <surname>Cellier</surname>
          </string-name>
          , Mireille Ducasse, Sebastien Ferre, and
          <string-name>
            <given-names>Olivier</given-names>
            <surname>Ridoux</surname>
          </string-name>
          .
          <article-title>Formal concept analysis enhances fault localization in software</article-title>
          .
          <source>In Raoul Medina and Sergei A</source>
          . Obiedkov, editors,
          <source>ICFCA</source>
          , volume
          <volume>4933</volume>
          of Lecture Notes in Computer Science, pages
          <volume>273</volume>
          {
          <fpage>288</fpage>
          . Springer,
          <year>2008</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          4.
          <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="ref5">
        <mixed-citation>
          5.
          <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="ref6">
        <mixed-citation>
          6.
          <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="ref7">
        <mixed-citation>
          7.
          <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="ref8">
        <mixed-citation>
          8.
          <string-name>
            <given-names>Bernhard</given-names>
            <surname>Ganter</surname>
          </string-name>
          and
          <string-name>
            <given-names>Rudolf</given-names>
            <surname>Wille</surname>
          </string-name>
          .
          <source>Formal Concept Analysis: Mathematical Foundations</source>
          . Springer,
          <year>1999</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          9.
          <string-name>
            <given-names>Michael</given-names>
            <surname>Gerndt</surname>
          </string-name>
          .
          <article-title>Towards automatic performance debugging tools</article-title>
          .
          <source>In AADEBUG</source>
          ,
          <year>2000</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          10.
          <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. [7]</source>
          , pages
          <fpage>304</fpage>
          {
          <fpage>323</fpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          11.
          <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="ref12">
        <mixed-citation>
          12.
          <string-name>
            <surname>Sergei</surname>
            <given-names>O.</given-names>
          </string-name>
          <string-name>
            <surname>Kuznetsov</surname>
            and
            <given-names>Sergei A.</given-names>
          </string-name>
          <string-name>
            <surname>Obiedkov</surname>
          </string-name>
          .
          <article-title>Some decision and counting problems of the duquenne-guigues basis of implications</article-title>
          .
          <source>Discrete Applied Mathematics</source>
          ,
          <volume>156</volume>
          (
          <issue>11</issue>
          ):
          <year>1994</year>
          {
          <year>2003</year>
          ,
          <year>2008</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          13.
          <string-name>
            <surname>John L. Pfaltz</surname>
          </string-name>
          .
          <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="ref14">
        <mixed-citation>
          14.
          <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="ref15">
        <mixed-citation>
          15.
          <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="ref16">
        <mixed-citation>
          16. Aaron James Searle.
          <source>Automatic relative debugging</source>
          .
          <year>2006</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>