doc-src/TutorialI/Misc/document/Itrev.tex
author chaieb
Wed, 19 May 2004 11:23:59 +0200
changeset 14758 af3b71a46a1c
parent 13791 3b6ff7ceaf27
child 15481 fc075ae929e4
permissions -rw-r--r--
A new implementation for presburger arithmetic following the one suggested in technical report Chaieb Amine and Tobias Nipkow. It is generic an smaller. the tactic has also changed and allows the abstaction over fuction occurences whose type is nat or int.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9722
a5f86aed785b *** empty log message ***
nipkow
parents: 9721
diff changeset
     1
%
a5f86aed785b *** empty log message ***
nipkow
parents: 9721
diff changeset
     2
\begin{isabellebody}%
9924
3370f6aa3200 updated;
wenzelm
parents: 9844
diff changeset
     3
\def\isabellecontext{Itrev}%
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
     4
\isamarkupfalse%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
     5
%
10878
b254d5ad6dd4 auto update
paulson
parents: 10795
diff changeset
     6
\isamarkupsection{Induction Heuristics%
10397
e2d0dda41f2c auto update
paulson
parents: 10396
diff changeset
     7
}
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
     8
\isamarkuptrue%
9844
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
     9
%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    10
\begin{isamarkuptext}%
9844
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    11
\label{sec:InductionHeuristics}
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    12
\index{induction heuristics|(}%
9844
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    13
The purpose of this section is to illustrate some simple heuristics for
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    14
inductive proofs. The first one we have already mentioned in our initial
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    15
example:
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    16
\begin{quote}
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    17
\emph{Theorems about recursive functions are proved by induction.}
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    18
\end{quote}
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    19
In case the function has more than one argument
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    20
\begin{quote}
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    21
\emph{Do induction on argument number $i$ if the function is defined by
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    22
recursion in argument number $i$.}
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    23
\end{quote}
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    24
When we look at the proof of \isa{{\isacharparenleft}xs{\isacharat}ys{\isacharparenright}\ {\isacharat}\ zs\ {\isacharequal}\ xs\ {\isacharat}\ {\isacharparenleft}ys{\isacharat}zs{\isacharparenright}}
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    25
in \S\ref{sec:intro-proof} we find
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    26
\begin{itemize}
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    27
\item \isa{{\isacharat}} is recursive in
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    28
the first argument
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    29
\item \isa{xs}  occurs only as the first argument of
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    30
\isa{{\isacharat}}
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    31
\item both \isa{ys} and \isa{zs} occur at least once as
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    32
the second argument of \isa{{\isacharat}}
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    33
\end{itemize}
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    34
Hence it is natural to perform induction on~\isa{xs}.
9844
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    35
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    36
The key heuristic, and the main point of this section, is to
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    37
\emph{generalize the goal before induction}.
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    38
The reason is simple: if the goal is
9844
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    39
too specific, the induction hypothesis is too weak to allow the induction
10971
6852682eaf16 *** empty log message ***
nipkow
parents: 10950
diff changeset
    40
step to go through. Let us illustrate the idea with an example.
9844
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
    41
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    42
Function \cdx{rev} has quadratic worst-case running time
9792
bbefb6ce5cb2 *** empty log message ***
nipkow
parents: 9754
diff changeset
    43
because it calls function \isa{{\isacharat}} for each element of the list and
bbefb6ce5cb2 *** empty log message ***
nipkow
parents: 9754
diff changeset
    44
\isa{{\isacharat}} is linear in its first argument.  A linear time version of
9493
494f8cd34df7 *** empty log message ***
nipkow
parents: 9145
diff changeset
    45
\isa{rev} reqires an extra argument where the result is accumulated
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    46
gradually, using only~\isa{{\isacharhash}}:%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    47
\end{isamarkuptext}%
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    48
\isamarkuptrue%
9673
1b2d4f995b13 updated;
wenzelm
parents: 9644
diff changeset
    49
\isacommand{consts}\ itrev\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}{\isacharprime}a\ list\ {\isasymRightarrow}\ {\isacharprime}a\ list\ {\isasymRightarrow}\ {\isacharprime}a\ list{\isachardoublequote}\isanewline
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    50
\isamarkupfalse%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    51
\isacommand{primrec}\isanewline
9673
1b2d4f995b13 updated;
wenzelm
parents: 9644
diff changeset
    52
{\isachardoublequote}itrev\ {\isacharbrackleft}{\isacharbrackright}\ \ \ \ \ ys\ {\isacharequal}\ ys{\isachardoublequote}\isanewline
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    53
{\isachardoublequote}itrev\ {\isacharparenleft}x{\isacharhash}xs{\isacharparenright}\ ys\ {\isacharequal}\ itrev\ xs\ {\isacharparenleft}x{\isacharhash}ys{\isacharparenright}{\isachardoublequote}\isamarkupfalse%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    54
%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    55
\begin{isamarkuptext}%
9792
bbefb6ce5cb2 *** empty log message ***
nipkow
parents: 9754
diff changeset
    56
\noindent
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    57
The behaviour of \cdx{itrev} is simple: it reverses
9493
494f8cd34df7 *** empty log message ***
nipkow
parents: 9145
diff changeset
    58
its first argument by stacking its elements onto the second argument,
494f8cd34df7 *** empty log message ***
nipkow
parents: 9145
diff changeset
    59
and returning that second argument when the first one becomes
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    60
empty. Note that \isa{itrev} is tail-recursive: it can be
9493
494f8cd34df7 *** empty log message ***
nipkow
parents: 9145
diff changeset
    61
compiled into a loop.
494f8cd34df7 *** empty log message ***
nipkow
parents: 9145
diff changeset
    62
494f8cd34df7 *** empty log message ***
nipkow
parents: 9145
diff changeset
    63
Naturally, we would like to show that \isa{itrev} does indeed reverse
494f8cd34df7 *** empty log message ***
nipkow
parents: 9145
diff changeset
    64
its first argument provided the second one is empty:%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    65
\end{isamarkuptext}%
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    66
\isamarkuptrue%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    67
\isacommand{lemma}\ {\isachardoublequote}itrev\ xs\ {\isacharbrackleft}{\isacharbrackright}\ {\isacharequal}\ rev\ xs{\isachardoublequote}\isamarkupfalse%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    68
%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    69
\begin{isamarkuptxt}%
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    70
\noindent
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    71
There is no choice as to the induction variable, and we immediately simplify:%
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    72
\end{isamarkuptxt}%
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    73
\isamarkuptrue%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    74
\isacommand{apply}{\isacharparenleft}induct{\isacharunderscore}tac\ xs{\isacharcomma}\ simp{\isacharunderscore}all{\isacharparenright}\isamarkupfalse%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    75
%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    76
\begin{isamarkuptxt}%
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    77
\noindent
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    78
Unfortunately, this attempt does not prove
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    79
the induction step:
10420
ef006735bee8 *** empty log message ***
nipkow
parents: 10397
diff changeset
    80
\begin{isabelle}%
ef006735bee8 *** empty log message ***
nipkow
parents: 10397
diff changeset
    81
\ {\isadigit{1}}{\isachardot}\ {\isasymAnd}a\ list{\isachardot}\isanewline
10971
6852682eaf16 *** empty log message ***
nipkow
parents: 10950
diff changeset
    82
\isaindent{\ {\isadigit{1}}{\isachardot}\ \ \ \ }itrev\ list\ {\isacharbrackleft}{\isacharbrackright}\ {\isacharequal}\ rev\ list\ {\isasymLongrightarrow}\ itrev\ list\ {\isacharbrackleft}a{\isacharbrackright}\ {\isacharequal}\ rev\ list\ {\isacharat}\ {\isacharbrackleft}a{\isacharbrackright}%
9723
a977245dfc8a *** empty log message ***
nipkow
parents: 9722
diff changeset
    83
\end{isabelle}
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    84
The induction hypothesis is too weak.  The fixed
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    85
argument,~\isa{{\isacharbrackleft}{\isacharbrackright}}, prevents it from rewriting the conclusion.  
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    86
This example suggests a heuristic:
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    87
\begin{quote}\index{generalizing induction formulae}%
9754
a123a64cadeb *** empty log message ***
nipkow
parents: 9723
diff changeset
    88
\emph{Generalize goals for induction by replacing constants by variables.}
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    89
\end{quote}
9792
bbefb6ce5cb2 *** empty log message ***
nipkow
parents: 9754
diff changeset
    90
Of course one cannot do this na\"{\i}vely: \isa{itrev\ xs\ ys\ {\isacharequal}\ rev\ xs} is
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
    91
just not true.  The correct generalization is%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    92
\end{isamarkuptxt}%
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    93
\isamarkuptrue%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    94
\isamarkupfalse%
13791
3b6ff7ceaf27 *** empty log message ***
nipkow
parents: 13778
diff changeset
    95
\isacommand{lemma}\ {\isachardoublequote}itrev\ xs\ ys\ {\isacharequal}\ rev\ xs\ {\isacharat}\ ys{\isachardoublequote}\isamarkupfalse%
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    96
\isamarkupfalse%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
    97
%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    98
\begin{isamarkuptxt}%
2665170f104a Adding generated files
nipkow
parents:
diff changeset
    99
\noindent
9792
bbefb6ce5cb2 *** empty log message ***
nipkow
parents: 9754
diff changeset
   100
If \isa{ys} is replaced by \isa{{\isacharbrackleft}{\isacharbrackright}}, the right-hand side simplifies to
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   101
\isa{rev\ xs}, as required.
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   102
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   103
In this instance it was easy to guess the right generalization.
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   104
Other situations can require a good deal of creativity.  
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   105
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   106
Although we now have two variables, only \isa{xs} is suitable for
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   107
induction, and we repeat our proof attempt. Unfortunately, we are still
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   108
not there:
10362
c6b197ccf1f1 *** empty log message ***
nipkow
parents: 9924
diff changeset
   109
\begin{isabelle}%
c6b197ccf1f1 *** empty log message ***
nipkow
parents: 9924
diff changeset
   110
\ {\isadigit{1}}{\isachardot}\ {\isasymAnd}a\ list{\isachardot}\isanewline
10950
aa788fcb75a5 updated;
wenzelm
parents: 10878
diff changeset
   111
\isaindent{\ {\isadigit{1}}{\isachardot}\ \ \ \ }itrev\ list\ ys\ {\isacharequal}\ rev\ list\ {\isacharat}\ ys\ {\isasymLongrightarrow}\isanewline
aa788fcb75a5 updated;
wenzelm
parents: 10878
diff changeset
   112
\isaindent{\ {\isadigit{1}}{\isachardot}\ \ \ \ }itrev\ list\ {\isacharparenleft}a\ {\isacharhash}\ ys{\isacharparenright}\ {\isacharequal}\ rev\ list\ {\isacharat}\ a\ {\isacharhash}\ ys%
9723
a977245dfc8a *** empty log message ***
nipkow
parents: 9722
diff changeset
   113
\end{isabelle}
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   114
The induction hypothesis is still too weak, but this time it takes no
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   115
intuition to generalize: the problem is that \isa{ys} is fixed throughout
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   116
the subgoal, but the induction hypothesis needs to be applied with
9792
bbefb6ce5cb2 *** empty log message ***
nipkow
parents: 9754
diff changeset
   117
\isa{a\ {\isacharhash}\ ys} instead of \isa{ys}. Hence we prove the theorem
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   118
for all \isa{ys} instead of a fixed one:%
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   119
\end{isamarkuptxt}%
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
   120
\isamarkuptrue%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
   121
\isamarkupfalse%
13791
3b6ff7ceaf27 *** empty log message ***
nipkow
parents: 13778
diff changeset
   122
\isacommand{lemma}\ {\isachardoublequote}{\isasymforall}ys{\isachardot}\ itrev\ xs\ ys\ {\isacharequal}\ rev\ xs\ {\isacharat}\ ys{\isachardoublequote}\isamarkupfalse%
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
   123
\isamarkupfalse%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
   124
%
9844
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   125
\begin{isamarkuptext}%
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   126
\noindent
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   127
This time induction on \isa{xs} followed by simplification succeeds. This
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   128
leads to another heuristic for generalization:
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   129
\begin{quote}
9754
a123a64cadeb *** empty log message ***
nipkow
parents: 9723
diff changeset
   130
\emph{Generalize goals for induction by universally quantifying all free
8749
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   131
variables {\em(except the induction variable itself!)}.}
2665170f104a Adding generated files
nipkow
parents:
diff changeset
   132
\end{quote}
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   133
This prevents trivial failures like the one above and does not affect the
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   134
validity of the goal.  However, this heuristic should not be applied blindly.
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   135
It is not always required, and the additional quantifiers can complicate
13081
ab4a3aef3591 *** empty log message ***
nipkow
parents: 11866
diff changeset
   136
matters in some cases. The variables that should be quantified are typically
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   137
those that change in recursive calls.
9644
6b0b6b471855 *** empty log message ***
nipkow
parents: 9541
diff changeset
   138
9844
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   139
A final point worth mentioning is the orientation of the equation we just
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   140
proved: the more complex notion (\isa{itrev}) is on the left-hand
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   141
side, the simpler one (\isa{rev}) on the right-hand side. This constitutes
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   142
another, albeit weak heuristic that is not restricted to induction:
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   143
\begin{quote}
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   144
  \emph{The right-hand side of an equation should (in some sense) be simpler
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   145
    than the left-hand side.}
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   146
\end{quote}
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   147
This heuristic is tricky to apply because it is not obvious that
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   148
\isa{rev\ xs\ {\isacharat}\ ys} is simpler than \isa{itrev\ xs\ ys}. But see what
10971
6852682eaf16 *** empty log message ***
nipkow
parents: 10950
diff changeset
   149
happens if you try to prove \isa{rev\ xs\ {\isacharat}\ ys\ {\isacharequal}\ itrev\ xs\ ys}!
6852682eaf16 *** empty log message ***
nipkow
parents: 10950
diff changeset
   150
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   151
If you have tried these heuristics and still find your
10971
6852682eaf16 *** empty log message ***
nipkow
parents: 10950
diff changeset
   152
induction does not go through, and no obvious lemma suggests itself, you may
6852682eaf16 *** empty log message ***
nipkow
parents: 10950
diff changeset
   153
need to generalize your proposition even further. This requires insight into
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   154
the problem at hand and is beyond simple rules of thumb.  
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   155
Additionally, you can read \S\ref{sec:advanced-ind}
10971
6852682eaf16 *** empty log message ***
nipkow
parents: 10950
diff changeset
   156
to learn about some advanced techniques for inductive proofs.%
11458
09a6c44a48ea numerous stylistic changes and indexing
paulson
parents: 10971
diff changeset
   157
\index{induction heuristics|)}%
9844
8016321c7de1 *** empty log message ***
nipkow
parents: 9792
diff changeset
   158
\end{isamarkuptext}%
11866
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
   159
\isamarkuptrue%
fbd097aec213 updated;
wenzelm
parents: 11458
diff changeset
   160
\isamarkupfalse%
9722
a5f86aed785b *** empty log message ***
nipkow
parents: 9721
diff changeset
   161
\end{isabellebody}%
9145
9f7b8de5bfaf updated;
wenzelm
parents: 8749
diff changeset
   162
%%% Local Variables:
9f7b8de5bfaf updated;
wenzelm
parents: 8749
diff changeset
   163
%%% mode: latex
9f7b8de5bfaf updated;
wenzelm
parents: 8749
diff changeset
   164
%%% TeX-master: "root"
9f7b8de5bfaf updated;
wenzelm
parents: 8749
diff changeset
   165
%%% End: