Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

There are some software to analyse the cross references among codes (Java or C++). I used to use a software for code analysis under Windows many years before. But I can't remember the name. On linux, an example might be LXR Cross Referencer.

Is there a similar tool that can analyse the latex files to find out the cross references of theorems, lemmas, propositions and equations?

share|improve this question
    
Can you elaborate on what you mean by cross-referencing? –  percusse May 14 '12 at 10:58
1  
By cross-referencing, I mean to find out,for example, the following facts: (1) proof of Theorem 10.2 needs Lemma 10.1, Proposition 8.4 and Eq.(9.3); (2) Proposition 8.4 has been used in the proof of Theorem 10.2, Lemma 9.4 etc. –  Anand May 14 '12 at 11:03
1  
I can imagine doing this semiautomatically by wrapping the \ref macro in a macro of your own that writes the context of the reference to an external file (or saves it in an internal list). That would give the data "A uses B". Parsing/sorting that list would tell you also "B used by A". –  Ethan Bolker May 14 '12 at 13:09
1  
@Anand Sorry, I don't know an implementation. I think I know enough TeX to write one, which I would if I needed it. But I don't, and don't have the time. Maybe one of the wizards who watch SE regularly can do it quickly. –  Ethan Bolker May 14 '12 at 13:44
1  
reftex for emacs is great for tracking references across a large project provided you set up which file is the 'parent' and which ones are the 'children'. It comes bundled as part of AUCTeX. –  jon May 18 '12 at 14:36

1 Answer 1

up vote 17 down vote accepted
+100

Cross referencing in LaTeX uses quite simple schema - for every label it stores value of macro \@currentlabel and the page number in the aux file. There are packages, which extends this scheme, like titleref or zref, but it is still just label and some properties, which are then accessed with some form of \ref command.

What would be useful in this case, is something like RDF so one can construct complex graph of objects, their properties and relationships, like

Theorem Lorem is defined in the Section Ipsum on page 4 and it has Definition foo on page 5 and Example boo on page 6, is referenced on pages 3,7,89 etc...

In this model every label (object) can have any number of properties, which can be values, or other objects, which gives us directed graph of objects, properties and subjects. objects and properties are in form of prefix:name,

Now there is some simple rdf framework for LaTeX

First we define some core functions for saving and loading properties rdfref-core.sty

\ProvidesPackage{rdfref-core}
\RequirePackage{etoolbox}
\def\Nil{}%
\def\First#1#2{#1}
\def\Second#1#2{#2}

\def\parsecolon#1:#2\relax{\ifx#2\Nil\Nil\else#1\fi}%
\newcommand\RdfPrefix[1]{%
\parsecolon#1:\Nil\relax%
}
\newcommand\AddTriple[3]{%
\edef\rdf@object{#3}
\immediate\write\@auxout{\noexpand\LoadTriple{#1}{#2}{\rdf@object}}
}

\newcommand\SetProperty[3]{%
\protected@csxdef{rdf@#1@#2}{#3}%
}

\newcommand\GetProperty[2]{%
\ifcsdef{rdf@#1@#2}{%
\csuse{rdf@#1@#2}%
}{%
\PropertyNotDef{#1}{#2}%
}%
}
\newcommand\PropertyNotDef[2]{%
???%
%\typeout{rdf warning: subject #1 has no property #2}%
}

\newcommand\SubjectListAdd[2]{%
\listcsgadd{sbjlst@#1}{#2}
}
\newcommand\MapSubjectList[2]{%
\def\do##1{#2}%
\dolistcsloop{sbjlst@#1}%
}

\newcommand\PropertyListAdd[3]{%
\listcsgadd{prprtlst@#2}{{#1}{#3}}
}
\newcommand\MapPropertyList[2]{%
\def\do##1{#2}%
\dolistcsloop{prprtlst@#1}%
}


\newcommand\LoadTriple[3]{%
\SetProperty{#1}{#2}{#3}
\SubjectListAdd{#1}{#2}
\PropertyListAdd{#1}{#2}{#3}
}

Two useful functions are \MapPropertyList, which lets you to loop over all objects and subjects with given property and \MapSubjectList for loop over properties of given subject.

Now some helper functions, which emulates somehow latex cross-referencing system rdfref-user.sty:

\ProvidesPackage{rdfref-user}
\RequirePackage{rdfref-core,nameref}
\newwrite\exportfile
\def\RootObject{_:doc}

\def\CurrentObject{\RootObject}

\newcommand\AddRdfType[2]{%
\def\do##1{\csgdef{rdf:type@##1}{\noexpand\unexpanded{#2}}}
%\csgdef{rdf:type@#1}{\unexpanded{#2}}
\docsvlist{#1}
}
\newcommand\AddProperty[2]{%
\AddTriple{\CurrentObject}{#1}{#2}
}


\newcommand\WithObject[2]{%
\begingroup%
\def\CurrentObject{#1}%
\def\run{#2}
\run%
\endgroup%
}



\newcommand\rdflabel[1]{%
\AddTriple{#1}{doc:hasParent}{\CurrentObject}%
\AddTriple{#1}{doc:envir}{\@currenvir}%
\def\CurrentObject{#1}%
\ifcsdef{rdf:type@\GuessRdfType{#1}}%
{\csuse{rdf:type@\GuessRdfType{#1}}}%
{\typeout{Package rdfref error: unknown type of reference #1 :\GuessRdfType{#1}:}}%
\label{#1}
}

\newcommand\GuessRdfType[1]{%
% We first try if current environment is defined as type, if not, then guess type from the parameter
\ifcsdef{rdf:type@\@currenvir}{\@currenvir}{%
\ifx\RdfPrefix{#1}\Nil\Nil\else%
\RdfPrefix{#1}%
\fi%
}%
}

\newcommand\inputontology[1]{%
\makeatletter
\input{#1}
\makeatother
}

command \rdflabel constructs LaTeX label, so you can use normal constructs like \ref and \pageref and creates object with some default values and then call constructor which stores properties which are defined for object of given type. Type is deducted from object's surrounding environment, if it doesn't have set type, it is deducted from its prefix.

These constructors are defined in ontologies, which are normal TeX files with macro definitions, but which must be loaded after \begin{document}, because they need to write to the aux file.

theorem-ontology.tex

\newcommand\partOf[1]{%
\AddProperty{doc:partOf}{#1}
}


\AddRdfType{Theorem}{%
\AddProperty{rdf:type}{thm:theorem}
\AddProperty{doc:pageNo}{\thepage}
\AddProperty{rdfs:label}{\@currentlabel\ \@currentlabelname}
}
\AddRdfType{thr}{%
\AddProperty{rdf:type}{thm:theorem}
\AddProperty{doc:pageNo}{\thepage}
\AddProperty{rdfs:label}{\@currentlabel\ \@currentlabelname}
}
\AddRdfType{prop}{%
\AddProperty{rdf:type}{thm:proposition}
\AddProperty{doc:pageNo}{\thepage}
\AddProperty{rdfs:label}{\@currentlabel\ \@currentlabelname}
}

\AddRdfType{lem}{%
\AddProperty{rdf:type}{thm:lemma}
\AddProperty{doc:pageNo}{\thepage}
\AddProperty{rdfs:label}{\@currentlabel\ \@currentlabelname}
}


\AddRdfType{sec}{
\AddProperty{rdf:type}{sec:sectioning}
\AddProperty{doc:pageNo}{\thepage}
\AddProperty{rdfs:label}{\@currentlabel\ \@currentlabelname}
\AddProperty{doc:label}{\@currentlabel}
}
\AddRdfType{equation}{%
\AddProperty{rdf:type}{eq:equation}
\AddProperty{doc:pageNo}{\thepage}
\AddProperty{rdfs:label}{\@currentlabel\ \@currentlabelname}
}

\WithObject{sec:sectioning}{%
\AddProperty{rdfs:label}{Sectioning}
\AddProperty{rdf:type}{rdfs:Class}
}
\WithObject{thm:theorem}{%
\AddProperty{rdfs:label}{Theorem}
\AddProperty{rdf:type}{rdfs:Class}
}
\WithObject{thm:proposition}{%
\AddProperty{rdfs:label}{Proposition}
\AddProperty{rdf:type}{rdfs:Class}
}
\WithObject{thm:lemma}{%
\AddProperty{rdfs:label}{Lemma}
\AddProperty{rdf:type}{rdfs:Class}
}

\WithObject{eq:equation}{%
\AddProperty{rdfs:label}{Equation}
\AddProperty{rdf:type}{rdfs:Class}
}
\WithObject{rdfs:Class}{%
\AddProperty{rdfs:label}{Class}
}

you can see that we added constructors for some environments and prefixes. important property is rdf:type, which can be used for example if you want to loop over all theorems or equations. there are also properties doc:pageNo and rdfs:label, which are more or less traditional LaTeX cross-referencing properties. For every rdf:object there is also \WithObject macro, which set textual labels (rdfs:label) for these types.

there is also command \partOf, which declares current object as part of another object. It can be used in examples or definitions, to declare that they are part of some theorem. I do really know nothing about mathematical theorems, so this is really just an simple example, not anything useful. If you have idea about some useful properties, they can be easily added.

Now some sample file:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[]{tgschola}
\usepackage[T1]{fontenc}
%\catcode`\_=12
\usepackage[]{rdfref-user,lipsum,nameref,cleveref}
\usepackage{amsthm,thmtools,xstring}
\declaretheorem[name=Lemma,Refname={Lemma,Lemmas}]{lem}
\declaretheorem[name=Proposition,Refname={Proposition,Proposition}]{prop}
\declaretheorem[name=Theorem,Refname={Theorem,Theorems}]{thr}

\begin{document}
\inputontology{theorem-ontology.tex}
\section{Hello world}\rdflabel{sec:first}
\lipsum[1-2]
  \begin{lem}\rdflabel{thm:lem1}
    \partOf{thm:thr1}
    A lemma.
  \end{lem}

  \begin{prop}
    \rdflabel{thm:prop1}
    \partOf{thm:thr1}
    A proposition.
    %\renewcommand{\theenumi}{\thecor.\arabic{enumi}}
    \begin{enumerate}
      \item An item 
      \item Another one 
    \end{enumerate}
  \end{prop}

  \begin{thr}\rdflabel{thm:thr1}
    A theorem.
  \end{thr}

\begin{thr}[Euclid]
\rdflabel{thm:euclid}%
For every prime $p$, there is a prime $p’>p$.
In particular, the list of primes,
\begin{equation}\rdflabel{eq:1}
2,3,5,7,\dots
\end{equation}
is infinite.
\end{thr}

\end{document}

And if you want to export some graph, try this macro (Not much nice, but it shows some ways, how you can work with your properties graph):

\newcommand\ExportGraphviz[2]{%
digraph G\{
\forcsvlist{\listadd\typelist}{#1}
%\forcsvlist{\listadd\propertylist}{#2}
\def\worker##1##2{%
%"\ObjectLabel" -> \GetProperty{\First##1}
\edef\ppp{\GetProperty{##1}{##2}}
\typeout{Worker: ##1: ##1 : \ppp}
\IfSubStr{\ppp}{???}{}{%
"\ObjectLabel" -> %
\IfSubStr{\ppp}{:}{"\GetProperty{\GetProperty{\ppp}{rdf:type}}{rdfs:label}: \GetProperty{\ppp}{rdfs:label}"}{"\ppp"} %
%\GetProperty{##1}{##2} 
 [label="##2"];\\%
}
}
\MapPropertyList{rdf:type}{%
\xifinlist{\Second##1}{\typelist}{%
\edef\ObjectLabel{\GetProperty{\Second##1}{rdfs:label}: \GetProperty{\First##1}{rdfs:label}}%
%\ObjectLabel \& \Second##1\\}
\bgroup%
%\MapObjectList{\First##1}{}
\forcsvlist{\worker{\First##1}}{#2}%
\egroup
}%
{}%
}
\}
}

Because of some weird errors, I cannot do version which write to the file, so graphviz specification is simply printed to the document (really ugly, I know). It can be used in following way:

\ExportGraphviz{sec:sectioning,thm:theorem,eq:equation,thm:proposition,thm:proposition,thm:lemma}{doc:pageNo,doc:partOf,doc:hasParent}

First parameter is list of objects with given rdf:type which should be the exported, the second is list of properties. For some reason, on first run, when there is no aux file, it gives some errors, but after that, it should be OK

Resulting graph:

enter image description here

Also, it is easy using \MapPropertyList and \MapSubjectList to export data to some rdf serialization format, for example turtle and import them to some specialized rdf database, or visualization tool, and do many interesting things with them.

share|improve this answer
    
Dear michal.h21, thanks a lot for your codes. Beautifully done, although there is still some gap from the code analysis where a GUI is available with many features. I hope one day people realize the necessities of such a tool for LaTeX community and start to write one. You definitely deserve this 100 pints. Great thanks! :-) –  Anand May 19 '12 at 11:07

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.