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

I'm writing a paper and all my code is in Mathematica. The snippets are mostly simple, and consist of loops, maps, variables, and conditionals. I'd like add it to my paper, however, not many academic journals accept verbatim code in a specific language, and I'm short on time, so here is my question:

Does anyone know of a package that translates Mathematica functions and code to pseudo-code?

Of course there is no universal syntax pseudo-code, but I'll accept anything that is adequately general (bonus points for robust exportability to $\LaTeX$). Here are some examples of this utility in other languages:

When writing papers I always do the translation by hand, but enough is enough, Mathematica should excel at a high-level translation problem like this and at least get the bulk of the work done for me! I use the pseudocode environment from the fancybox package to typeset pseudocode into $\LaTeX$.

Please note that I fully intend on trying to write an answer to this myself, so don't down vote for the lack of code just yet! :)

share|improve this question
3  
+1, but I always wanted a package able to do it the other way around and can interpret my "Now get all those solutions" pseudocode comments –  belisarius Oct 29 '13 at 6:09
    
Me too! Alas that direction is much much harder :/ I have a friend who believes that smart and visual programming languages in the next 10 years will have this ability. –  M.R. Oct 29 '13 at 6:21
    
Perhaps SpokenString or CompilePrint could come in handy. –  Simon Woods Oct 29 '13 at 11:52
3  
But now with all those upvotes you sure gotta deliver ;-) –  Yves Klett Oct 29 '13 at 13:35
4  
IMO this is problematic due to the ill-defined nature of "pseudocode", dependent as it is on the expectations of the audience. I actually dislike pseudocode descriptions in papers since normally they are written in an inappropriately procedural style and often contain various bugs due to the fact that they can't actually be executed to check for correctness. I would suggest translating to some widely used, free and open language such as Python and providing the code in the supplementary materials. Another good alternative to pseudocode is a flowchart. –  Oleksandr R. Oct 29 '13 at 19:14
show 1 more comment

1 Answer

Here is my attempt to generate a pseudocode for algorithmicx package.

Current features

  • Functions (as SetDelayed)
  • Set
  • If with 2 and 3 arguments
  • While
  • Do (any number of variables of any type) New!
  • Return
  • Module, With, and Block
  • CompoundExpression (;)
  • Test functions (EvenQ, etc., and Not@EvenQ, etc.) New!
  • Indentation

Code

ClearAll[pseudocode, pscd]
SetAttributes[{pseudocode, pscd, texstring}, HoldFirst];

indent[n_] := "\n" <> ConstantArray[" ", n];

pscd[SetDelayed[f_[x___], code_], n_: 0, m_: 0] := 
  indent[n] <> "\\Function{" <> pscd@f <> "}{" <> 
   Riffle[pscd@Hold@x, ","] <> "}\n" <> pscd[code, n + m, m] <> 
   indent[n] <> "\\EndFunction\n";
(*SetDelayed as a function*)

pscd[pattern_, n_: 0, m_: 0] /; Head@Unevaluated@pattern === Pattern :=
   pscd /@ pattern // First;
(*remove patterns from arguments of functions*)

pscd[(Module | With | Block)[{vars___}, code_], n_: 0, m_: 0] := 
  Cases[Hold@vars, s_ /; Head@Unevaluated@s === Set :> pscd[s, n, m]] <> 
   pscd[code, n, m];
(*remove everything from Module,With,and Block except code and setting of variables*)

pscd[set_, n_: 0, m_: 0] /; Head@Unevaluated@set === Set := 
  indent[n] <> "\\State " <> 
   Riffle[pscd@# &@ReleaseHold[Hold @@@ Hold@set], " $\\gets$ "] <> "\n";
(*Set*)

pscd[CompoundExpression[code___], n_: 0, m_: 0] := 
 Riffle[pscd[Hold@code, n, m], "\n"] <> "\n"
(*...;...;*)

pscd[If[cond_, true_], n_: 0, m_: 0] := 
  indent[n] <> "\\If{" <> pscd@cond <> "}\n" <> pscd[true, n + m, m] <>
    indent[n] <> "\\EndIf\n";
(*if*)

pscd[If[cond_, true_, false_], n_: 0, m_: 0] := 
  indent[n] <> "\\If{" <> pscd@cond <> "}\n" <> pscd[true, n + m, m] <>
    indent[n] <> "\\Else\n" <> pscd[false, n + m, m] <> indent[n] <> 
   "\\EndIf\n";
(*if... else*)

pscd[While[cond_, code_], n_: 0, m_: 0] := 
  indent[n] <> "\\While{" <> pscd@cond <> "}\n" <> 
   pscd[code, n + m, m] <> indent[n] <> "\\EndWhile\n";
(*while*)

pscd[Do[code_, args__, arg1_], n_: 0, m_: 0] := 
  pscd[Do[Do[code, arg1], args], n, m];
(*nested do*)

pscd[Do[code_, {i2_}], n_: 0, m_: 0] := 
  indent[n] <> "\\Do{" <> pscd@i2 <> "}\n" <> pscd[code, n + m, m] <> 
   indent[n] <> "\\EndDo\n";
pscd[Do[code_, {i_, i2_}], n_: 0, m_: 0] := 
  pscd[Do[code, {i, 1, i2}], n, m];
pscd[Do[code_, {i_, i1_, i2_}], n_: 0, m_: 0] := 
  indent[n] <> "\\For{" <> pscd@i <> " = " <> pscd@i1 <> " \\ldots " <>
    pscd@i2 <> "}\n" <> pscd[code, n + m, m] <> indent[n] <> 
   "\\EndFor\n";
pscd[Do[code_, {i_, i1_, i2_, di_}], n_: 0, m_: 0] := 
  indent[n] <> "\\For{" <> pscd@i <> " = " <> pscd@i1 <> ", " <> 
   texstring[i1 + di] <> " \\ldots " <> pscd@i2 <> "}\n" <> 
   pscd[code, n + m, m] <> indent[n] <> "\\EndFor\n";
pscd[Do[code_, {i_, l_List}], n_: 0, m_: 0] := 
  indent[n] <> "\\For{" <> pscd@i <> " = " <> 
   Riffle[pscd /@ l, ", "] <> "}\n" <> pscd[code, n + m, m] <> 
   indent[n] <> "\\EndFor\n";
(*do*)

pscd[q_[x_], n_: 0, m_: 0] /; (Last@# == "Q" && LowerCaseQ@#[[-2]] &)@
   Characters@ToString@Unevaluated@q := 
 pscd@x <> " is " <> Riffle[StringCases[ToString@q, 
    A_?UpperCaseQ ~~ b__?LowerCaseQ :> ToLowerCase@A <> b], " "]
(* convert EvenQ[x] to "x is even" and so on *)

pscd[Not@q_[x_], n_: 0, m_: 0] /; (Last@# == "Q" && LowerCaseQ@#[[-2]] &)@
   Characters@ToString@Unevaluated@q := 
 pscd@x <> " is not " <> Riffle[StringCases[ToString@q, 
    A_?UpperCaseQ ~~ b__?LowerCaseQ :> ToLowerCase@A <> b], " "]
(* convert Not@EvenQ[x] to "x is not even" and so on *)

pscd[Return[x_], n_: 0, m_: 0] := 
  indent[n] <> "\\State \\textbf{return} " <> pscd@x <> "\n";
(*return*)

pscd[h_Hold, n_: 0, m_: 0] := 
 List @@ Function[{x}, pscd[x, n, m], HoldAll] /@ h
(*Automatically transform Hold[x,y,...] to {pscd[x],pscd[y],...}*)

pscd[code_, n_: 0, m_: 0] := texstring@HoldForm@code;
(*default*)

texstring[code_] := "$" <> code~ToString~TeXForm <> "$";
(*sometimes we need to convert without holding *)

Options[pseudocode] = {Indentation -> 2};
pseudocode[code_, OptionsPattern[]] := 
  CellPrint@TextCell[StringReplace[
     "\\begin{algorithmic}\n" <> 
      pscd[code, OptionValue@Indentation, OptionValue@Indentation] <> 
      "\\end{algorithmic}", "\n" .. :> "\n"], "Output"];

For indentation I use n and m variables. n is the current indentation and m is the step of the indentation.

Examples

Example 1

pseudocode[
 max[a_, b_] := Module[{r},
   If[a > b, r = a, r = b];
   Return[r]]
 ]

Output:

\begin{algorithmic}
  \Function{$\max$}{$a$,$b$}
    \If{$a>b$}
      \State $r$ $\gets$ $a$
    \Else
      \State $r$ $\gets$ $b$
    \EndIf
    \State \textbf{return} $r$
  \EndFunction
\end{algorithmic}

enter image description here

Example 2

pseudocode[
 gcd[a_, b_] := Module[{r = Mod[a, b], x = a, y = b},
   While[r != 0,
    x = y;
    y = r;
    r = Mod[x, y]
    ];
   Return[y]
   ]
 ]

Output:

\begin{algorithmic}
  \Function{$\gcd$}{$a$,$b$}
    \State $r$ $\gets$ $(a \bmod b)$
    \State $x$ $\gets$ $a$
    \State $y$ $\gets$ $b$
    \While{$r\neq 0$}
      \State $x$ $\gets$ $y$
      \State $y$ $\gets$ $r$
      \State $r$ $\gets$ $(x \bmod y)$
    \EndWhile
    \State \textbf{return} $y$
  \EndFunction
\end{algorithmic}

enter image description here

Example 3

Do[i = i + n + m + k + l, {n, 10}, {m, 5, 20}, {k, m, 30, 2}, 
   {l, {1, 3, 5, 8}}, {40}] // pseudocode

Output:

\begin{algorithmic}
  \For{$n$ = $1$ \ldots $10$}
    \For{$m$ = $5$ \ldots $20$}
      \For{$k$ = $m$, $m+2$ \ldots $30$}
        \For{$l$ = $1$, $3$, $5$, $8$}
          \Do{$40$}
            \State $i$ $\gets$ $i+n+m+k+l$
          \EndDo
        \EndFor
      \EndFor
    \EndFor
  \EndFor
\end{algorithmic}

enter image description here

Example 4

If[! HermitianMatrixQ[H], H = H + ConjugateTranspose[H]] // pseudocode

Output:

\begin{algorithmic}
  \If{$H$ is not hermitian matrix}
    \State $H$ $\gets$ $H+H^{\dagger}$
  \EndIf
\end{algorithmic}

enter image description here

$\LaTeX$ example file:

\documentclass[a4paper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{algpseudocode}
\algrenewcommand\textproc{}% Disable uppercase in functions

%necessary for "do ... times" constructions
\algblockdefx[DO]{Do}{EndDo}[1]{\textbf{do} #1 \textbf{times}}{\textbf{end do}}

\begin{document}

\begin{algorithmic}
        ...
\end{algorithmic}

\end{document}

Let me know if you find a bug!

share|improve this answer
add comment

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.