COIN-OR::LEMON - Graph Library

Ticket #456: 1c978b5bcc65.patch

File 1c978b5bcc65.patch, 41.5 KB (added by Alpar Juttner, 6 years ago)
  • doc/CMakeLists.txt

    # HG changeset patch
    # User Alpar Juttner <alpar@cs.elte.hu>
    # Date 1363624879 -3600
    # Node ID 1c978b5bcc657cc3c0623b96d72f94cd60ae40a1
    # Parent  eb2f9d453070f2251c5c194610f0722d1670df31
    Use doxygen's own bibtex support (#456)
    
    diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
    a b  
    5151    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_3.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_3.eps
    5252    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_4.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_4.eps
    5353    COMMAND ${CMAKE_COMMAND} -E remove_directory html
    54     COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/bib2dox.py ${CMAKE_CURRENT_SOURCE_DIR}/references.bib >references.dox
    5554    COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
    5655    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    5756  )
  • doc/Doxyfile.in

    diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in
    a b  
    7777SHOW_NAMESPACES        = YES
    7878FILE_VERSION_FILTER    =
    7979LAYOUT_FILE            = "@abs_top_srcdir@/doc/DoxygenLayout.xml"
     80CITE_BIB_FILES         = "@abs_top_srcdir@/doc/references.bib"
    8081#---------------------------------------------------------------------------
    8182# configuration options related to warning and progress messages
    8283#---------------------------------------------------------------------------
  • doc/groups.dox

    diff --git a/doc/groups.dox b/doc/groups.dox
    a b  
    317317
    318318This group contains the common graph search algorithms, namely
    319319\e breadth-first \e search (BFS) and \e depth-first \e search (DFS)
    320 \ref clrs01algorithms.
     320\cite clrs01algorithms.
    321321*/
    322322
    323323/**
     
    326326\brief Algorithms for finding shortest paths.
    327327
    328328This group contains the algorithms for finding shortest paths in digraphs
    329 \ref clrs01algorithms.
     329\cite clrs01algorithms.
    330330
    331331 - \ref Dijkstra algorithm for finding shortest paths from a source node
    332332   when all arc lengths are non-negative.
     
    348348\brief Algorithms for finding minimum cost spanning trees and arborescences.
    349349
    350350This group contains the algorithms for finding minimum cost spanning
    351 trees and arborescences \ref clrs01algorithms.
     351trees and arborescences \cite clrs01algorithms.
    352352*/
    353353
    354354/**
     
    357357\brief Algorithms for finding maximum flows.
    358358
    359359This group contains the algorithms for finding maximum flows and
    360 feasible circulations \ref clrs01algorithms, \ref amo93networkflows.
     360feasible circulations \cite clrs01algorithms, \cite amo93networkflows.
    361361
    362362The \e maximum \e flow \e problem is to find a flow of maximum value between
    363363a single source and a single target. Formally, there is a \f$G=(V,A)\f$
     
    373373
    374374LEMON contains several algorithms for solving maximum flow problems:
    375375- \ref EdmondsKarp Edmonds-Karp algorithm
    376   \ref edmondskarp72theoretical.
     376  \cite edmondskarp72theoretical.
    377377- \ref Preflow Goldberg-Tarjan's preflow push-relabel algorithm
    378   \ref goldberg88newapproach.
     378  \cite goldberg88newapproach.
    379379- \ref DinitzSleatorTarjan Dinitz's blocking flow algorithm with dynamic trees
    380   \ref dinic70algorithm, \ref sleator83dynamic.
     380  \cite dinic70algorithm, \cite sleator83dynamic.
    381381- \ref GoldbergTarjan !Preflow push-relabel algorithm with dynamic trees
    382   \ref goldberg88newapproach, \ref sleator83dynamic.
     382  \cite goldberg88newapproach, \cite sleator83dynamic.
    383383
    384384In most cases the \ref Preflow algorithm provides the
    385385fastest method for computing a maximum flow. All implementations
     
    399399\brief Algorithms for finding minimum cost flows and circulations.
    400400
    401401This group contains the algorithms for finding minimum cost flows and
    402 circulations \ref amo93networkflows. For more information about this
     402circulations \cite amo93networkflows. For more information about this
    403403problem and its dual solution, see: \ref min_cost_flow
    404404"Minimum Cost Flow Problem".
    405405
    406406LEMON contains several algorithms for this problem.
    407407 - \ref NetworkSimplex Primal Network Simplex algorithm with various
    408    pivot strategies \ref dantzig63linearprog, \ref kellyoneill91netsimplex.
     408   pivot strategies \cite dantzig63linearprog, \cite kellyoneill91netsimplex.
    409409 - \ref CostScaling Cost Scaling algorithm based on push/augment and
    410    relabel operations \ref goldberg90approximation, \ref goldberg97efficient,
    411    \ref bunnagel98efficient.
     410   relabel operations \cite goldberg90approximation, \cite goldberg97efficient,
     411   \cite bunnagel98efficient.
    412412 - \ref CapacityScaling Capacity Scaling algorithm based on the successive
    413    shortest path method \ref edmondskarp72theoretical.
     413   shortest path method \cite edmondskarp72theoretical.
    414414 - \ref CycleCanceling Cycle-Canceling algorithms, two of which are
    415    strongly polynomial \ref klein67primal, \ref goldberg89cyclecanceling.
     415   strongly polynomial \cite klein67primal, \cite goldberg89cyclecanceling.
    416416
    417417In general, \ref NetworkSimplex and \ref CostScaling are the most efficient
    418418implementations.
     
    430430data are required to be integer).
    431431
    432432For more details about these implementations and for a comprehensive
    433 experimental study, see the paper \ref KiralyKovacs12MCF.
     433experimental study, see the paper \cite KiralyKovacs12MCF.
    434434It also compares these codes to other publicly available
    435435minimum cost flow solvers.
    436436*/
     
    471471\brief Algorithms for finding minimum mean cycles.
    472472
    473473This group contains the algorithms for finding minimum mean cycles
    474 \ref amo93networkflows, \ref karp78characterization.
     474\cite amo93networkflows, \cite karp78characterization.
    475475
    476476The \e minimum \e mean \e cycle \e problem is to find a directed cycle
    477477of minimum mean length (cost) in a digraph.
     
    487487function.
    488488
    489489LEMON contains three algorithms for solving the minimum mean cycle problem:
    490 - \ref KarpMmc Karp's original algorithm \ref karp78characterization.
     490- \ref KarpMmc Karp's original algorithm \cite karp78characterization.
    491491- \ref HartmannOrlinMmc Hartmann-Orlin's algorithm, which is an improved
    492   version of Karp's algorithm \ref hartmann93finding.
     492  version of Karp's algorithm \cite hartmann93finding.
    493493- \ref HowardMmc Howard's policy iteration algorithm
    494   \ref dasdan98minmeancycle, \ref dasdan04experimental.
     494  \cite dasdan98minmeancycle, \cite dasdan04experimental.
    495495
    496496In practice, the \ref HowardMmc "Howard" algorithm turned out to be by far the
    497497most efficient one, though the best known theoretical bound on its running
     
    647647Various LP solvers could be used in the same manner with this
    648648high-level interface.
    649649
    650 The currently supported solvers are \ref glpk, \ref clp, \ref cbc,
    651 \ref cplex, \ref soplex.
     650The currently supported solvers are \cite glpk, \cite clp, \cite cbc,
     651\cite cplex, \cite soplex.
    652652*/
    653653
    654654/**
  • doc/mainpage.dox.in

    diff --git a/doc/mainpage.dox.in b/doc/mainpage.dox.in
    a b  
    2525and <b>O</b>ptimization in <b>N</b>etworks</i>.
    2626It is a C++ template library providing efficient implementations of common
    2727data structures and algorithms with focus on combinatorial optimization
    28 tasks connected mainly with graphs and networks \ref DezsoJuttnerKovacs11Lemon.
     28tasks connected mainly with graphs and networks \cite DezsoJuttnerKovacs11Lemon.
    2929
    3030<b>
    3131LEMON is an <a class="el" href="http://opensource.org/">open&nbsp;source</a>
     
    3737
    3838The project is maintained by the
    3939<a href="http://www.cs.elte.hu/egres/">Egerv&aacute;ry Research Group on
    40 Combinatorial Optimization</a> \ref egres
     40Combinatorial Optimization</a> \cite egres
    4141at the Operations Research Department of the
    4242<a href="http://www.elte.hu/en/">E&ouml;tv&ouml;s Lor&aacute;nd University</a>,
    4343Budapest, Hungary.
    4444LEMON is also a member of the <a href="http://www.coin-or.org/">COIN-OR</a>
    45 initiative \ref coinor.
     45initiative \cite coinor.
    4646
    4747\section howtoread How to Read the Documentation
    4848
  • doc/min_cost_flow.dox

    diff --git a/doc/min_cost_flow.dox b/doc/min_cost_flow.dox
    a b  
    2626The \e minimum \e cost \e flow \e problem is to find a feasible flow of
    2727minimum total cost from a set of supply nodes to a set of demand nodes
    2828in a network with capacity constraints (lower and upper bounds)
    29 and arc costs \ref amo93networkflows.
     29and arc costs \cite amo93networkflows.
    3030
    3131Formally, let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{R}\f$,
    3232\f$upper: A\rightarrow\mathbf{R}\cup\{+\infty\}\f$ denote the lower and
  • lemon/capacity_scaling.h

    diff --git a/lemon/capacity_scaling.h b/lemon/capacity_scaling.h
    a b  
    6666  ///
    6767  /// \ref CapacityScaling implements the capacity scaling version
    6868  /// of the successive shortest path algorithm for finding a
    69   /// \ref min_cost_flow "minimum cost flow" \ref amo93networkflows,
    70   /// \ref edmondskarp72theoretical. It is an efficient dual
     69  /// \ref min_cost_flow "minimum cost flow" \cite amo93networkflows,
     70  /// \cite edmondskarp72theoretical. It is an efficient dual
    7171  /// solution method, which runs in polynomial time
    7272  /// \f$O(e\log U (n+e)\log n)\f$, where <i>U</i> denotes the maximum
    7373  /// of node supply and arc capacity values.
  • lemon/cost_scaling.h

    diff --git a/lemon/cost_scaling.h b/lemon/cost_scaling.h
    a b  
    9191  ///
    9292  /// \ref CostScaling implements a cost scaling algorithm that performs
    9393  /// push/augment and relabel operations for finding a \ref min_cost_flow
    94   /// "minimum cost flow" \ref amo93networkflows, \ref goldberg90approximation,
    95   /// \ref goldberg97efficient, \ref bunnagel98efficient.
     94  /// "minimum cost flow" \cite amo93networkflows, \cite goldberg90approximation,
     95  /// \cite goldberg97efficient, \cite bunnagel98efficient.
    9696  /// It is a highly efficient primal-dual solution method, which
    9797  /// can be viewed as the generalization of the \ref Preflow
    9898  /// "preflow push-relabel" algorithm for the maximum flow problem.
  • lemon/cycle_canceling.h

    diff --git a/lemon/cycle_canceling.h b/lemon/cycle_canceling.h
    a b  
    4747  ///
    4848  /// \ref CycleCanceling implements three different cycle-canceling
    4949  /// algorithms for finding a \ref min_cost_flow "minimum cost flow"
    50   /// \ref amo93networkflows, \ref klein67primal,
    51   /// \ref goldberg89cyclecanceling.
     50  /// \cite amo93networkflows, \cite klein67primal,
     51  /// \cite goldberg89cyclecanceling.
    5252  /// The most efficent one is the \ref CANCEL_AND_TIGHTEN
    5353  /// "Cancel-and-Tighten" algorithm, thus it is the default method.
    5454  /// It runs in strongly polynomial time O(n<sup>2</sup>e<sup>2</sup>log(n)),
     
    131131      SIMPLE_CYCLE_CANCELING,
    132132      /// The "Minimum Mean Cycle-Canceling" algorithm, which is a
    133133      /// well-known strongly polynomial method
    134       /// \ref goldberg89cyclecanceling. It improves along a
     134      /// \cite goldberg89cyclecanceling. It improves along a
    135135      /// \ref min_mean_cycle "minimum mean cycle" in each iteration.
    136136      /// Its running time complexity is O(n<sup>2</sup>e<sup>3</sup>log(n)).
    137137      MINIMUM_MEAN_CYCLE_CANCELING,
    138138      /// The "Cancel-and-Tighten" algorithm, which can be viewed as an
    139139      /// improved version of the previous method
    140       /// \ref goldberg89cyclecanceling.
     140      /// \cite goldberg89cyclecanceling.
    141141      /// It is faster both in theory and in practice, its running time
    142142      /// complexity is O(n<sup>2</sup>e<sup>2</sup>log(n)).
    143143      CANCEL_AND_TIGHTEN
  • lemon/grosso_locatelli_pullan_mc.h

    diff --git a/lemon/grosso_locatelli_pullan_mc.h b/lemon/grosso_locatelli_pullan_mc.h
    a b  
    4040  ///
    4141  /// \ref GrossoLocatelliPullanMc implements the iterated local search
    4242  /// algorithm of Grosso, Locatelli, and Pullan for solving the \e maximum
    43   /// \e clique \e problem \ref grosso08maxclique.
     43  /// \e clique \e problem \cite grosso08maxclique.
    4444  /// It is to find the largest complete subgraph (\e clique) in an
    4545  /// undirected graph, i.e., the largest set of nodes where each
    4646  /// pair of nodes is connected.
  • lemon/hartmann_orlin_mmc.h

    diff --git a/lemon/hartmann_orlin_mmc.h b/lemon/hartmann_orlin_mmc.h
    a b  
    9898  ///
    9999  /// This class implements the Hartmann-Orlin algorithm for finding
    100100  /// a directed cycle of minimum mean cost in a digraph
    101   /// \ref hartmann93finding, \ref dasdan98minmeancycle.
     101  /// \cite hartmann93finding, \cite dasdan98minmeancycle.
    102102  /// This method is based on \ref KarpMmc "Karp"'s original algorithm, but
    103103  /// applies an early termination scheme. It makes the algorithm
    104104  /// significantly faster for some problem instances, but slower for others.
  • lemon/howard_mmc.h

    diff --git a/lemon/howard_mmc.h b/lemon/howard_mmc.h
    a b  
    9898  ///
    9999  /// This class implements Howard's policy iteration algorithm for finding
    100100  /// a directed cycle of minimum mean cost in a digraph
    101   /// \ref dasdan98minmeancycle, \ref dasdan04experimental.
     101  /// \cite dasdan98minmeancycle, \cite dasdan04experimental.
    102102  /// This class provides the most efficient algorithm for the
    103103  /// minimum mean cycle problem, though the best known theoretical
    104104  /// bound on its running time is exponential.
  • lemon/karp_mmc.h

    diff --git a/lemon/karp_mmc.h b/lemon/karp_mmc.h
    a b  
    9898  ///
    9999  /// This class implements Karp's algorithm for finding a directed
    100100  /// cycle of minimum mean cost in a digraph
    101   /// \ref karp78characterization, \ref dasdan98minmeancycle.
     101  /// \cite karp78characterization, \cite dasdan98minmeancycle.
    102102  /// It runs in time O(ne) and uses space O(n<sup>2</sup>+e).
    103103  ///
    104104  /// \tparam GR The type of the digraph the algorithm runs on.
  • lemon/network_simplex.h

    diff --git a/lemon/network_simplex.h b/lemon/network_simplex.h
    a b  
    4141  ///
    4242  /// \ref NetworkSimplex implements the primal Network Simplex algorithm
    4343  /// for finding a \ref min_cost_flow "minimum cost flow"
    44   /// \ref amo93networkflows, \ref dantzig63linearprog,
    45   /// \ref kellyoneill91netsimplex.
     44  /// \cite amo93networkflows, \cite dantzig63linearprog,
     45  /// \cite kellyoneill91netsimplex.
    4646  /// This algorithm is a highly efficient specialized version of the
    4747  /// linear programming simplex method directly for the minimum cost
    4848  /// flow problem.
  • lemon/preflow.h

    diff --git a/lemon/preflow.h b/lemon/preflow.h
    a b  
    102102  ///
    103103  /// This class provides an implementation of Goldberg-Tarjan's \e preflow
    104104  /// \e push-relabel algorithm producing a \ref max_flow
    105   /// "flow of maximum value" in a digraph \ref clrs01algorithms,
    106   /// \ref amo93networkflows, \ref goldberg88newapproach.
     105  /// "flow of maximum value" in a digraph \cite clrs01algorithms,
     106  /// \cite amo93networkflows, \cite goldberg88newapproach.
    107107  /// The preflow algorithms are the fastest known maximum
    108108  /// flow algorithms. The current implementation uses a mixture of the
    109109  /// \e "highest label" and the \e "bound decrease" heuristics.
  • deleted file scripts/bib2dox.py

    diff --git a/scripts/bib2dox.py b/scripts/bib2dox.py
    deleted file mode 100755
    + -  
    1 #! /usr/bin/env python
    2 """
    3   BibTeX to Doxygen converter
    4   Usage: python bib2dox.py bibfile.bib > bibfile.dox
    5 
    6   This file is a part of LEMON, a generic C++ optimization library.
    7 
    8   **********************************************************************
    9 
    10   This code is the modification of the BibTeX to XML converter
    11   by Vidar Bronken Gundersen et al.
    12   See the original copyright notices below.
    13 
    14   **********************************************************************
    15 
    16   Decoder for bibliographic data, BibTeX
    17   Usage: python bibtex2xml.py bibfile.bib > bibfile.xml
    18 
    19   v.8
    20   (c)2002-06-23 Vidar Bronken Gundersen
    21   http://bibtexml.sf.net/
    22   Reuse approved as long as this notification is kept.
    23   Licence: GPL.
    24 
    25   Contributions/thanks to:
    26   Egon Willighagen, http://sf.net/projects/jreferences/
    27   Richard Mahoney (for providing a test case)
    28 
    29   Editted by Sara Sprenkle to be more robust and handle more bibtex features.
    30   (c) 2003-01-15
    31 
    32   1.  Changed bibtex: tags to bibxml: tags.
    33   2.  Use xmlns:bibxml="http://bibtexml.sf.net/"
    34   3.  Allow spaces between @type and first {
    35   4.  "author" fields with multiple authors split by " and "
    36       are put in separate xml "bibxml:author" tags.
    37   5.  Option for Titles: words are capitalized
    38       only if first letter in title or capitalized inside braces
    39   6.  Removes braces from within field values
    40   7.  Ignores comments in bibtex file (including @comment{ or % )
    41   8.  Replaces some special latex tags, e.g., replaces ~ with '&#160;'
    42   9.  Handles bibtex @string abbreviations
    43         --> includes bibtex's default abbreviations for months
    44         --> does concatenation of abbr # " more " and " more " # abbr
    45   10. Handles @type( ... ) or @type{ ... }
    46   11. The keywords field is split on , or ; and put into separate xml
    47       "bibxml:keywords" tags
    48   12. Ignores @preamble
    49 
    50   Known Limitations
    51   1.  Does not transform Latex encoding like math mode and special
    52       latex symbols.
    53   2.  Does not parse author fields into first and last names.
    54       E.g., It does not do anything special to an author whose name is
    55       in the form LAST_NAME, FIRST_NAME
    56       In "author" tag, will show up as
    57       <bibxml:author>LAST_NAME, FIRST_NAME</bibxml:author>
    58   3.  Does not handle "crossref" fields other than to print
    59       <bibxml:crossref>...</bibxml:crossref>
    60   4.  Does not inform user of the input's format errors.  You just won't
    61       be able to transform the file later with XSL
    62 
    63   You will have to manually edit the XML output if you need to handle
    64   these (and unknown) limitations.
    65 
    66 """
    67 
    68 import string, re
    69 
    70 # set of valid name characters
    71 valid_name_chars = '[\w\-:]'
    72 
    73 #
    74 # define global regular expression variables
    75 #
    76 author_rex = re.compile('\s+and\s+')
    77 rembraces_rex = re.compile('[{}]')
    78 capitalize_rex = re.compile('({[^}]*})')
    79 
    80 # used by bibtexkeywords(data)
    81 keywords_rex = re.compile('[,;]')
    82 
    83 # used by concat_line(line)
    84 concatsplit_rex = re.compile('\s*#\s*')
    85 
    86 # split on {, }, or " in verify_out_of_braces
    87 delimiter_rex = re.compile('([{}"])',re.I)
    88 
    89 field_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
    90 data_rex = re.compile('\s*(\w*)\s*=\s*([^,]*),?')
    91 
    92 url_rex = re.compile('\\\url\{([^}]*)\}')
    93 
    94 #
    95 # styles for html formatting
    96 #
    97 divstyle = 'margin-top: -4ex; margin-left: 10em;'
    98 
    99 #
    100 # return the string parameter without braces
    101 #
    102 def transformurls(str):
    103     return url_rex.sub(r'<a href="\1">\1</a>', str)
    104 
    105 #
    106 # return the string parameter without braces
    107 #
    108 def removebraces(str):
    109     return rembraces_rex.sub('', str)
    110 
    111 #
    112 # latex-specific replacements
    113 # (do this after braces were removed)
    114 #
    115 def latexreplacements(line):
    116     line = string.replace(line, '~', '&nbsp;')
    117     line = string.replace(line, '\\\'a', '&aacute;')
    118     line = string.replace(line, '\\"a', '&auml;')
    119     line = string.replace(line, '\\\'e', '&eacute;')
    120     line = string.replace(line, '\\"e', '&euml;')
    121     line = string.replace(line, '\\\'i', '&iacute;')
    122     line = string.replace(line, '\\"i', '&iuml;')
    123     line = string.replace(line, '\\\'o', '&oacute;')
    124     line = string.replace(line, '\\"o', '&ouml;')
    125     line = string.replace(line, '\\\'u', '&uacute;')
    126     line = string.replace(line, '\\"u', '&uuml;')
    127     line = string.replace(line, '\\H o', '&otilde;')
    128     line = string.replace(line, '\\H u', '&uuml;')   # &utilde; does not exist
    129     line = string.replace(line, '\\\'A', '&Aacute;')
    130     line = string.replace(line, '\\"A', '&Auml;')
    131     line = string.replace(line, '\\\'E', '&Eacute;')
    132     line = string.replace(line, '\\"E', '&Euml;')
    133     line = string.replace(line, '\\\'I', '&Iacute;')
    134     line = string.replace(line, '\\"I', '&Iuml;')
    135     line = string.replace(line, '\\\'O', '&Oacute;')
    136     line = string.replace(line, '\\"O', '&Ouml;')
    137     line = string.replace(line, '\\\'U', '&Uacute;')
    138     line = string.replace(line, '\\"U', '&Uuml;')
    139     line = string.replace(line, '\\H O', '&Otilde;')
    140     line = string.replace(line, '\\H U', '&Uuml;')   # &Utilde; does not exist
    141 
    142     return line
    143 
    144 #
    145 # copy characters form a string decoding html expressions (&xyz;)
    146 #
    147 def copychars(str, ifrom, count):
    148     result = ''
    149     i = ifrom
    150     c = 0
    151     html_spec = False
    152     while (i < len(str)) and (c < count):
    153         if str[i] == '&':
    154             html_spec = True;
    155             if i+1 < len(str):
    156                 result += str[i+1]
    157             c += 1
    158             i += 2
    159         else:
    160             if not html_spec:
    161                 if ((str[i] >= 'A') and (str[i] <= 'Z')) or \
    162                    ((str[i] >= 'a') and (str[i] <= 'z')):
    163                     result += str[i]
    164                     c += 1
    165             elif str[i] == ';':
    166                 html_spec = False;
    167             i += 1
    168    
    169     return result
    170 
    171 
    172 #
    173 # Handle a list of authors (separated by 'and').
    174 # It gives back an array of the follwing values:
    175 #  - num: the number of authors,
    176 #  - list: the list of the author names,
    177 #  - text: the bibtex text (separated by commas and/or 'and')
    178 #  - abbrev: abbreviation that can be used for indicate the
    179 #    bibliography entries
    180 #
    181 def bibtexauthor(data):
    182     result = {}
    183     bibtex = ''
    184     result['list'] = author_rex.split(data)
    185     result['num'] = len(result['list'])
    186     for i, author in enumerate(result['list']):
    187         # general transformations
    188         author = latexreplacements(removebraces(author.strip()))
    189         # transform "Xyz, A. B." to "A. B. Xyz"
    190         pos = author.find(',')
    191         if pos != -1:
    192             author = author[pos+1:].strip() + ' ' + author[:pos].strip()
    193         result['list'][i] = author
    194         bibtex += author + '#'
    195     bibtex = bibtex[:-1]
    196     if result['num'] > 1:
    197         ix = bibtex.rfind('#')
    198         if result['num'] == 2:
    199             bibtex = bibtex[:ix] + ' and ' + bibtex[ix+1:]
    200         else:
    201             bibtex = bibtex[:ix] + ', and ' + bibtex[ix+1:]
    202     bibtex = bibtex.replace('#', ', ')
    203     result['text'] = bibtex
    204    
    205     result['abbrev'] = ''
    206     for author in result['list']:
    207         pos = author.rfind(' ') + 1
    208         count = 1
    209         if result['num'] == 1:
    210             count = 3
    211         result['abbrev'] += copychars(author, pos, count)
    212 
    213     return result
    214 
    215 
    216 #
    217 # data = title string
    218 # @return the capitalized title (first letter is capitalized), rest are capitalized
    219 # only if capitalized inside braces
    220 #
    221 def capitalizetitle(data):
    222     title_list = capitalize_rex.split(data)
    223     title = ''
    224     count = 0
    225     for phrase in title_list:
    226          check = string.lstrip(phrase)
    227 
    228          # keep phrase's capitalization the same
    229          if check.find('{') == 0:
    230               title += removebraces(phrase)
    231          else:
    232          # first word --> capitalize first letter (after spaces)
    233               if count == 0:
    234                   title += check.capitalize()
    235               else:
    236                   title += phrase.lower()
    237          count = count + 1
    238 
    239     return title
    240 
    241 
    242 #
    243 # @return the bibtex for the title
    244 # @param data --> title string
    245 # braces are removed from title
    246 #
    247 def bibtextitle(data, entrytype):
    248     if entrytype in ('book', 'inbook'):
    249         title = removebraces(data.strip())
    250     else:
    251         title = removebraces(capitalizetitle(data.strip()))
    252     bibtex = title
    253     return bibtex
    254 
    255 
    256 #
    257 # function to compare entry lists
    258 #
    259 def entry_cmp(x, y):
    260     return cmp(x[0], y[0])
    261 
    262 
    263 #
    264 # print the XML for the transformed "filecont_source"
    265 #
    266 def bibtexdecoder(filecont_source):
    267     filecont = []
    268     file = []
    269    
    270     # want @<alphanumeric chars><spaces>{<spaces><any chars>,
    271     pubtype_rex = re.compile('@(\w*)\s*{\s*(.*),')
    272     endtype_rex = re.compile('}\s*$')
    273     endtag_rex = re.compile('^\s*}\s*$')
    274 
    275     bracefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
    276     bracedata_rex = re.compile('\s*(\w*)\s*=\s*{(.*)},?')
    277 
    278     quotefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
    279     quotedata_rex = re.compile('\s*(\w*)\s*=\s*"(.*)",?')
    280 
    281     for line in filecont_source:
    282         line = line[:-1]
    283 
    284         # encode character entities
    285         line = string.replace(line, '&', '&amp;')
    286         line = string.replace(line, '<', '&lt;')
    287         line = string.replace(line, '>', '&gt;')
    288 
    289         # start entry: publication type (store for later use)
    290         if pubtype_rex.match(line):
    291         # want @<alphanumeric chars><spaces>{<spaces><any chars>,
    292             entrycont = {}
    293             entry = []
    294             entrytype = pubtype_rex.sub('\g<1>',line)
    295             entrytype = string.lower(entrytype)
    296             entryid   = pubtype_rex.sub('\g<2>', line)
    297 
    298         # end entry if just a }
    299         elif endtype_rex.match(line):
    300             # generate doxygen code for the entry
    301 
    302             # enty type related formattings
    303             if entrytype in ('book', 'inbook'):
    304                 entrycont['title'] = '<em>' + entrycont['title'] + '</em>'
    305                 if not entrycont.has_key('author'):
    306                     entrycont['author'] = entrycont['editor']
    307                     entrycont['author']['text'] += ', editors'
    308             elif entrytype == 'article':
    309                 entrycont['journal'] = '<em>' + entrycont['journal'] + '</em>'
    310             elif entrytype in ('inproceedings', 'incollection', 'conference'):
    311                 entrycont['booktitle'] = '<em>' + entrycont['booktitle'] + '</em>'
    312             elif entrytype == 'techreport':
    313                 if not entrycont.has_key('type'):
    314                     entrycont['type'] = 'Technical report'
    315             elif entrytype == 'mastersthesis':
    316                 entrycont['type'] = 'Master\'s thesis'
    317             elif entrytype == 'phdthesis':
    318                 entrycont['type'] = 'PhD thesis'
    319 
    320             for eline in entrycont:
    321                 if eline != '':
    322                     eline = latexreplacements(eline)
    323 
    324             if entrycont.has_key('pages') and (entrycont['pages'] != ''):
    325                 entrycont['pages'] = string.replace(entrycont['pages'], '--', '-')
    326 
    327             if entrycont.has_key('author') and (entrycont['author'] != ''):
    328                 entry.append(entrycont['author']['text'] + '.')
    329             if entrycont.has_key('title') and (entrycont['title'] != ''):
    330                 entry.append(entrycont['title'] + '.')
    331             if entrycont.has_key('journal') and (entrycont['journal'] != ''):
    332                 entry.append(entrycont['journal'] + ',')
    333             if entrycont.has_key('booktitle') and (entrycont['booktitle'] != ''):
    334                 entry.append('In ' + entrycont['booktitle'] + ',')
    335             if entrycont.has_key('type') and (entrycont['type'] != ''):
    336                 eline = entrycont['type']
    337                 if entrycont.has_key('number') and (entrycont['number'] != ''):
    338                     eline += ' ' + entrycont['number']
    339                 eline += ','
    340                 entry.append(eline)
    341             if entrycont.has_key('institution') and (entrycont['institution'] != ''):
    342                 entry.append(entrycont['institution'] + ',')
    343             if entrycont.has_key('publisher') and (entrycont['publisher'] != ''):
    344                 entry.append(entrycont['publisher'] + ',')
    345             if entrycont.has_key('school') and (entrycont['school'] != ''):
    346                 entry.append(entrycont['school'] + ',')
    347             if entrycont.has_key('address') and (entrycont['address'] != ''):
    348                 entry.append(entrycont['address'] + ',')
    349             if entrycont.has_key('edition') and (entrycont['edition'] != ''):
    350                 entry.append(entrycont['edition'] + ' edition,')
    351             if entrycont.has_key('howpublished') and (entrycont['howpublished'] != ''):
    352                 entry.append(entrycont['howpublished'] + ',')
    353             if entrycont.has_key('volume') and (entrycont['volume'] != ''):
    354                 eline = entrycont['volume'];
    355                 if entrycont.has_key('number') and (entrycont['number'] != ''):
    356                     eline += '(' + entrycont['number'] + ')'
    357                 if entrycont.has_key('pages') and (entrycont['pages'] != ''):
    358                     eline += ':' + entrycont['pages']
    359                 eline += ','
    360                 entry.append(eline)
    361             else:
    362                 if entrycont.has_key('pages') and (entrycont['pages'] != ''):
    363                     entry.append('pages ' + entrycont['pages'] + ',')
    364             if entrycont.has_key('year') and (entrycont['year'] != ''):
    365                 if entrycont.has_key('month') and (entrycont['month'] != ''):
    366                     entry.append(entrycont['month'] + ' ' + entrycont['year'] + '.')
    367                 else:
    368                     entry.append(entrycont['year'] + '.')
    369             if entrycont.has_key('note') and (entrycont['note'] != ''):
    370                 entry.append(entrycont['note'] + '.')
    371             if entrycont.has_key('url') and (entrycont['url'] != ''):
    372                 entry.append(entrycont['url'] + '.')
    373 
    374             # generate keys for sorting and for the output
    375             sortkey = ''
    376             bibkey = ''
    377             if entrycont.has_key('author'):
    378                 for author in entrycont['author']['list']:
    379                     sortkey += copychars(author, author.rfind(' ')+1, len(author))
    380                 bibkey = entrycont['author']['abbrev']
    381             else:
    382                 bibkey = 'x'
    383             if entrycont.has_key('year'):
    384                 sortkey += entrycont['year']
    385                 bibkey += entrycont['year'][-2:]
    386             if entrycont.has_key('title'):
    387                 sortkey += entrycont['title']
    388             if entrycont.has_key('key'):
    389                 sortkey = entrycont['key'] + sortkey
    390                 bibkey = entrycont['key']
    391             entry.insert(0, sortkey)
    392             entry.insert(1, bibkey)
    393             entry.insert(2, entryid)
    394            
    395             # add the entry to the file contents
    396             filecont.append(entry)
    397 
    398         else:
    399             # field, publication info
    400             field = ''
    401             data = ''
    402            
    403             # field = {data} entries
    404             if bracedata_rex.match(line):
    405                 field = bracefield_rex.sub('\g<1>', line)
    406                 field = string.lower(field)
    407                 data =  bracedata_rex.sub('\g<2>', line)
    408 
    409             # field = "data" entries
    410             elif quotedata_rex.match(line):
    411                 field = quotefield_rex.sub('\g<1>', line)
    412                 field = string.lower(field)
    413                 data =  quotedata_rex.sub('\g<2>', line)
    414 
    415             # field = data entries
    416             elif data_rex.match(line):
    417                 field = field_rex.sub('\g<1>', line)
    418                 field = string.lower(field)
    419                 data =  data_rex.sub('\g<2>', line)
    420 
    421             if field == 'url':
    422                 data = '\\url{' + data.strip() + '}'
    423            
    424             if field in ('author', 'editor'):
    425                 entrycont[field] = bibtexauthor(data)
    426                 line = ''
    427             elif field == 'title':
    428                 line = bibtextitle(data, entrytype)
    429             elif field != '':
    430                 line = removebraces(transformurls(data.strip()))
    431 
    432             if line != '':
    433                 line = latexreplacements(line)
    434                 entrycont[field] = line
    435 
    436 
    437     # sort entries
    438     filecont.sort(entry_cmp)
    439    
    440     # count the bibtex keys
    441     keytable = {}
    442     counttable = {}
    443     for entry in filecont:
    444         bibkey = entry[1]
    445         if not keytable.has_key(bibkey):
    446             keytable[bibkey] = 1
    447         else:
    448             keytable[bibkey] += 1
    449 
    450     for bibkey in keytable.keys():
    451         counttable[bibkey] = 0
    452    
    453     # generate output
    454     for entry in filecont:
    455         # generate output key form the bibtex key
    456         bibkey = entry[1]
    457         entryid = entry[2]
    458         if keytable[bibkey] == 1:
    459             outkey = bibkey
    460         else:
    461             outkey = bibkey + chr(97 + counttable[bibkey])
    462         counttable[bibkey] += 1
    463        
    464         # append the entry code to the output
    465         file.append('\\section ' + entryid + ' [' + outkey + ']')
    466         file.append('<div style="' + divstyle + '">')
    467         for line in entry[3:]:
    468             file.append(line)
    469         file.append('</div>')
    470         file.append('')
    471 
    472     return file
    473 
    474 
    475 #
    476 # return 1 iff abbr is in line but not inside braces or quotes
    477 # assumes that abbr appears only once on the line (out of braces and quotes)
    478 #
    479 def verify_out_of_braces(line, abbr):
    480 
    481     phrase_split = delimiter_rex.split(line)
    482 
    483     abbr_rex = re.compile( '\\b' + abbr + '\\b', re.I)
    484 
    485     open_brace = 0
    486     open_quote = 0
    487 
    488     for phrase in phrase_split:
    489         if phrase == "{":
    490             open_brace = open_brace + 1
    491         elif phrase == "}":
    492             open_brace = open_brace - 1
    493         elif phrase == '"':
    494             if open_quote == 1:
    495                 open_quote = 0
    496             else:
    497                 open_quote = 1
    498         elif abbr_rex.search(phrase):
    499             if open_brace == 0 and open_quote == 0:
    500                 return 1
    501 
    502     return 0
    503 
    504 
    505 #
    506 # a line in the form phrase1 # phrase2 # ... # phrasen
    507 # is returned as phrase1 phrase2 ... phrasen
    508 # with the correct punctuation
    509 # Bug: Doesn't always work with multiple abbreviations plugged in
    510 #
    511 def concat_line(line):
    512     # only look at part after equals
    513     field = field_rex.sub('\g<1>',line)
    514     rest = field_rex.sub('\g<2>',line)
    515 
    516     concat_line = field + ' ='
    517 
    518     pound_split = concatsplit_rex.split(rest)
    519 
    520     phrase_count = 0
    521     length = len(pound_split)
    522 
    523     for phrase in pound_split:
    524         phrase = phrase.strip()
    525         if phrase_count != 0:
    526             if phrase.startswith('"') or phrase.startswith('{'):
    527                 phrase = phrase[1:]
    528         elif phrase.startswith('"'):
    529             phrase = phrase.replace('"','{',1)
    530 
    531         if phrase_count != length-1:
    532             if phrase.endswith('"') or phrase.endswith('}'):
    533                 phrase = phrase[:-1]
    534         else:
    535             if phrase.endswith('"'):
    536                 phrase = phrase[:-1]
    537                 phrase = phrase + "}"
    538             elif phrase.endswith('",'):
    539                 phrase = phrase[:-2]
    540                 phrase = phrase + "},"
    541 
    542         # if phrase did have \#, add the \# back
    543         if phrase.endswith('\\'):
    544             phrase = phrase + "#"
    545         concat_line = concat_line + ' ' + phrase
    546 
    547         phrase_count = phrase_count + 1
    548 
    549     return concat_line
    550 
    551 
    552 #
    553 # substitute abbreviations into filecont
    554 # @param filecont_source - string of data from file
    555 #
    556 def bibtex_replace_abbreviations(filecont_source):
    557     filecont = filecont_source.splitlines()
    558 
    559     #  These are defined in bibtex, so we'll define them too
    560     abbr_list = ['jan','feb','mar','apr','may','jun',
    561                  'jul','aug','sep','oct','nov','dec']
    562     value_list = ['January','February','March','April',
    563                   'May','June','July','August','September',
    564                   'October','November','December']
    565 
    566     abbr_rex = []
    567     total_abbr_count = 0
    568 
    569     front = '\\b'
    570     back = '(,?)\\b'
    571 
    572     for x in abbr_list:
    573         abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )
    574         total_abbr_count = total_abbr_count + 1
    575 
    576 
    577     abbrdef_rex = re.compile('\s*@string\s*{\s*('+ valid_name_chars +'*)\s*=(.*)',
    578                              re.I)
    579 
    580     comment_rex = re.compile('@comment\s*{',re.I)
    581     preamble_rex = re.compile('@preamble\s*{',re.I)
    582 
    583     waiting_for_end_string = 0
    584     i = 0
    585     filecont2 = ''
    586 
    587     for line in filecont:
    588         if line == ' ' or line == '':
    589             continue
    590 
    591         if waiting_for_end_string:
    592             if re.search('}',line):
    593                 waiting_for_end_string = 0
    594                 continue
    595 
    596         if abbrdef_rex.search(line):
    597             abbr = abbrdef_rex.sub('\g<1>', line)
    598 
    599             if abbr_list.count(abbr) == 0:
    600                 val = abbrdef_rex.sub('\g<2>', line)
    601                 abbr_list.append(abbr)
    602                 value_list.append(string.strip(val))
    603                 abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )
    604                 total_abbr_count = total_abbr_count + 1
    605             waiting_for_end_string = 1
    606             continue
    607 
    608         if comment_rex.search(line):
    609             waiting_for_end_string = 1
    610             continue
    611 
    612         if preamble_rex.search(line):
    613             waiting_for_end_string = 1
    614             continue
    615 
    616 
    617         # replace subsequent abbreviations with the value
    618         abbr_count = 0
    619 
    620         for x in abbr_list:
    621 
    622             if abbr_rex[abbr_count].search(line):
    623                 if verify_out_of_braces(line,abbr_list[abbr_count]) == 1:
    624                     line = abbr_rex[abbr_count].sub( value_list[abbr_count] + '\g<1>', line)
    625                 # Check for # concatenations
    626                 if concatsplit_rex.search(line):
    627                     line = concat_line(line)
    628             abbr_count = abbr_count + 1
    629 
    630 
    631         filecont2 = filecont2 + line + '\n'
    632         i = i+1
    633 
    634 
    635     # Do one final pass over file
    636 
    637     # make sure that didn't end up with {" or }" after the substitution
    638     filecont2 = filecont2.replace('{"','{{')
    639     filecont2 = filecont2.replace('"}','}}')
    640 
    641     afterquotevalue_rex = re.compile('"\s*,\s*')
    642     afterbrace_rex = re.compile('"\s*}')
    643     afterbracevalue_rex = re.compile('(=\s*{[^=]*)},\s*')
    644 
    645     # add new lines to data that changed because of abbreviation substitutions
    646     filecont2 = afterquotevalue_rex.sub('",\n', filecont2)
    647     filecont2 = afterbrace_rex.sub('"\n}', filecont2)
    648     filecont2 = afterbracevalue_rex.sub('\g<1>},\n', filecont2)
    649 
    650     return filecont2
    651 
    652 #
    653 # convert @type( ... ) to @type{ ... }
    654 #
    655 def no_outer_parens(filecont):
    656 
    657     # do checking for open parens
    658     # will convert to braces
    659     paren_split = re.split('([(){}])',filecont)
    660 
    661     open_paren_count = 0
    662     open_type = 0
    663     look_next = 0
    664 
    665     # rebuild filecont
    666     filecont = ''
    667 
    668     at_rex = re.compile('@\w*')
    669 
    670     for phrase in paren_split:
    671         if look_next == 1:
    672             if phrase == '(':
    673                 phrase = '{'
    674                 open_paren_count = open_paren_count + 1
    675             else:
    676                 open_type = 0
    677             look_next = 0
    678 
    679         if phrase == '(':
    680             open_paren_count = open_paren_count + 1
    681 
    682         elif phrase == ')':
    683             open_paren_count = open_paren_count - 1
    684             if open_type == 1 and open_paren_count == 0:
    685                 phrase = '}'
    686                 open_type = 0
    687 
    688         elif at_rex.search( phrase ):
    689             open_type = 1
    690             look_next = 1
    691 
    692         filecont = filecont + phrase
    693 
    694     return filecont
    695 
    696 
    697 #
    698 # make all whitespace into just one space
    699 # format the bibtex file into a usable form.
    700 #
    701 def bibtexwasher(filecont_source):
    702 
    703     space_rex = re.compile('\s+')
    704     comment_rex = re.compile('\s*%')
    705 
    706     filecont = []
    707 
    708     # remove trailing and excessive whitespace
    709     # ignore comments
    710     for line in filecont_source:
    711         line = string.strip(line)
    712         line = space_rex.sub(' ', line)
    713         # ignore comments
    714         if not comment_rex.match(line) and line != '':
    715             filecont.append(' '+ line)
    716 
    717     filecont = string.join(filecont, '')
    718 
    719     # the file is in one long string
    720 
    721     filecont = no_outer_parens(filecont)
    722 
    723     #
    724     # split lines according to preferred syntax scheme
    725     #
    726     filecont = re.sub('(=\s*{[^=]*)},', '\g<1>},\n', filecont)
    727 
    728     # add new lines after commas that are after values
    729     filecont = re.sub('"\s*,', '",\n', filecont)
    730     filecont = re.sub('=\s*([\w\d]+)\s*,', '= \g<1>,\n', filecont)
    731     filecont = re.sub('(@\w*)\s*({(\s*)[^,\s]*)\s*,',
    732                           '\n\n\g<1>\g<2>,\n', filecont)
    733 
    734     # add new lines after }
    735     filecont = re.sub('"\s*}','"\n}\n', filecont)
    736     filecont = re.sub('}\s*,','},\n', filecont)
    737 
    738 
    739     filecont = re.sub('@(\w*)', '\n@\g<1>', filecont)
    740 
    741     # character encoding, reserved latex characters
    742     filecont = re.sub('{\\\&}', '&', filecont)
    743     filecont = re.sub('\\\&', '&', filecont)
    744 
    745     # do checking for open braces to get format correct
    746     open_brace_count = 0
    747     brace_split = re.split('([{}])',filecont)
    748 
    749     # rebuild filecont
    750     filecont = ''
    751 
    752     for phrase in brace_split:
    753         if phrase == '{':
    754             open_brace_count = open_brace_count + 1
    755         elif phrase == '}':
    756             open_brace_count = open_brace_count - 1
    757             if open_brace_count == 0:
    758                 filecont = filecont + '\n'
    759 
    760         filecont = filecont + phrase
    761 
    762     filecont2 = bibtex_replace_abbreviations(filecont)
    763 
    764     # gather
    765     filecont = filecont2.splitlines()
    766     i=0
    767     j=0         # count the number of blank lines
    768     for line in filecont:
    769         # ignore blank lines
    770         if line == '' or line == ' ':
    771             j = j+1
    772             continue
    773         filecont[i] = line + '\n'
    774         i = i+1
    775 
    776     # get rid of the extra stuff at the end of the array
    777     # (The extra stuff are duplicates that are in the array because
    778     # blank lines were removed.)
    779     length = len( filecont)
    780     filecont[length-j:length] = []
    781 
    782     return filecont
    783 
    784 
    785 def filehandler(filepath):
    786     try:
    787         fd = open(filepath, 'r')
    788         filecont_source = fd.readlines()
    789         fd.close()
    790     except:
    791         print 'Could not open file:', filepath
    792     washeddata = bibtexwasher(filecont_source)
    793     outdata = bibtexdecoder(washeddata)
    794     print '/**'
    795     print '\page references References'
    796     print
    797     for line in outdata:
    798         print line
    799     print '*/'
    800 
    801 
    802 # main program
    803 
    804 def main():
    805     import sys
    806     if sys.argv[1:]:
    807         filepath = sys.argv[1]
    808     else:
    809         print "No input file"
    810         sys.exit()
    811     filehandler(filepath)
    812 
    813 if __name__ == "__main__": main()
    814 
    815 
    816 # end python script