Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
02/03/12 17:59:51 (12 years ago)
Author:
gkronber
Message:

#1773 added ExtLibs plugin for MathJax and implemented a view for symbolic data analysis models rendering the model in mathematical notation using MathJax in a webbrowser control

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs

    r7259 r7446  
    5757        StringBuilder strBuilder = new StringBuilder();
    5858        constants.Clear();
    59         strBuilder.AppendLine("% needs \\usepackage{amsmath}");
    60         strBuilder.AppendLine("\\begin{align*}");
    61         strBuilder.AppendLine("\\nonumber");
    6259        strBuilder.AppendLine(FormatRecursively(symbolicExpressionTree.Root));
    63         strBuilder.AppendLine("\\end{align*}");
    6460        return strBuilder.ToString();
    6561      }
     
    9288    private void FormatBegin(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
    9389      if (node.Symbol is Addition) {
    94         strBuilder.Append(@" ( ");
     90        strBuilder.Append(@" \left( ");
    9591      } else if (node.Symbol is Subtraction) {
    9692        if (node.SubtreeCount == 1) {
    97           strBuilder.Append(@"- ( ");
     93          strBuilder.Append(@"- \left( ");
    9894        } else {
    99           strBuilder.Append(@" ( ");
     95          strBuilder.Append(@" \left( ");
    10096        }
    10197      } else if (node.Symbol is Multiplication) {
     
    111107          strBuilder.Append(@" \cfrac{1}{" + node.SubtreeCount + @"}");
    112108        }
    113         strBuilder.Append(@" ( ");
     109        strBuilder.Append(@" \left( ");
    114110      } else if (node.Symbol is Logarithm) {
    115         strBuilder.Append(@"\log ( ");
     111        strBuilder.Append(@"\log \left( ");
    116112      } else if (node.Symbol is Exponential) {
    117         strBuilder.Append(@"\exp ( ");
     113        strBuilder.Append(@"\exp \left( ");
    118114      } else if (node.Symbol is Sine) {
    119         strBuilder.Append(@"\sin ( ");
     115        strBuilder.Append(@"\sin \left( ");
    120116      } else if (node.Symbol is Cosine) {
    121         strBuilder.Append(@"\cos ( ");
     117        strBuilder.Append(@"\cos \left( ");
    122118      } else if (node.Symbol is Tangent) {
    123         strBuilder.Append(@"\tan ( ");
     119        strBuilder.Append(@"\tan \left( ");
    124120      } else if (node.Symbol is GreaterThan) {
    125         strBuilder.Append(@"  ( ");
     121        strBuilder.Append(@"  \left( ");
    126122      } else if (node.Symbol is LessThan) {
    127         strBuilder.Append(@"  ( ");
     123        strBuilder.Append(@"  \left( ");
    128124      } else if (node.Symbol is And) {
    129         strBuilder.Append(@"   ( ");
     125        strBuilder.Append(@"   \left( ");
    130126      } else if (node.Symbol is Or) {
    131         strBuilder.Append(@"   ( ");
     127        strBuilder.Append(@"   \left( ");
    132128      } else if (node.Symbol is Not) {
    133         strBuilder.Append(@" \neg ( ");
     129        strBuilder.Append(@" \neg \left( ");
    134130      } else if (node.Symbol is IfThenElse) {
    135         strBuilder.Append(@" \operatorname{if}  ( 0 < ");
     131        strBuilder.Append(@" \operatorname{if}  \left( ");
    136132      } else if (node.Symbol is Constant) {
    137133        strBuilder.Append("c_{" + constants.Count + "} ");
     
    156152        strBuilder.Append(LagToString(currentLag));
    157153      } else if (node.Symbol is ProgramRootSymbol) {
     154        strBuilder
     155          .AppendLine("\\begin{align*}")
     156          .AppendLine("\\nonumber");
    158157      } else if (node.Symbol is Defun) {
    159158        var defunNode = node as DefunTreeNode;
     
    161160      } else if (node.Symbol is InvokeFunction) {
    162161        var invokeNode = node as InvokeFunctionTreeNode;
    163         strBuilder.Append(invokeNode.Symbol.FunctionName + @" ( ");
     162        strBuilder.Append(invokeNode.Symbol.FunctionName + @" \left( ");
    164163      } else if (node.Symbol is StartSymbol) {
    165164        strBuilder.Append("Result & = ");
     
    168167        strBuilder.Append(" ARG+" + argSym.ArgumentIndex + " ");
    169168      } else if (node.Symbol is Derivative) {
    170         strBuilder.Append(@" \cfrac{d ( ");
     169        strBuilder.Append(@" \cfrac{d \left( ");
    171170      } else if (node.Symbol is TimeLag) {
    172171        var laggedNode = node as ILaggedTreeNode;
    173172        currentLag += laggedNode.Lag;
    174173      } else if (node.Symbol is Power) {
    175         strBuilder.Append(@" ( ");
     174        strBuilder.Append(@" \left( ");
    176175      } else if (node.Symbol is Root) {
    177         strBuilder.Append(@" ( ");
     176        strBuilder.Append(@" \left( ");
    178177      } else if (node.Symbol is Integral) {
    179178        // actually a new variable for t is needed in all subtrees (TODO)
    180179        var laggedTreeNode = node as ILaggedTreeNode;
    181         strBuilder.Append(@"\sum_{t=" + (laggedTreeNode.Lag + currentLag) + @"}^0 ( ");
     180        strBuilder.Append(@"\sum_{t=" + (laggedTreeNode.Lag + currentLag) + @"}^0 \left( ");
    182181      } else if (node.Symbol is VariableCondition) {
    183182        var conditionTreeNode = node as VariableConditionTreeNode;
     
    186185        p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - c_{" + constants.Count + @"}   ";
    187186        constants.Add(conditionTreeNode.Threshold);
    188         strBuilder.Append(@" ( " + p + @"\cdot ");
     187        strBuilder.Append(@" \left( " + p + @"\cdot ");
    189188      } else {
    190189        throw new NotImplementedException("Export of " + node.Symbol + " is not implemented.");
     
    221220        strBuilder.Append(@" < ");
    222221      } else if (node.Symbol is And) {
    223         strBuilder.Append(@" > 0  ) \land (");
     222        strBuilder.Append(@" > 0  \right) \land \left(");
    224223      } else if (node.Symbol is Or) {
    225         strBuilder.Append(@" > 0  ) \lor (");
     224        strBuilder.Append(@" > 0  \right) \lor \left(");
    226225      } else if (node.Symbol is Not) {
    227226        throw new InvalidOperationException();
    228227      } else if (node.Symbol is IfThenElse) {
    229         strBuilder.Append(@" ) , (");
     228        strBuilder.Append(@" , ");
    230229      } else if (node.Symbol is ProgramRootSymbol) {
    231230        strBuilder.Append(@"\\" + Environment.NewLine);
     
    236235        strBuilder.Append(@"\\" + Environment.NewLine + " & ");
    237236      } else if (node.Symbol is Power) {
    238         strBuilder.Append(@") ^ { \operatorname{round} (");
     237        strBuilder.Append(@"\right) ^ { \operatorname{round} \left(");
    239238      } else if (node.Symbol is Root) {
    240         strBuilder.Append(@") ^ {  \cfrac{1}{ \operatorname{round} (");
     239        strBuilder.Append(@"\right) ^ {  \cfrac{1}{ \operatorname{round} \left(");
    241240      } else if (node.Symbol is VariableCondition) {
    242241        var conditionTreeNode = node as VariableConditionTreeNode;
    243         string p = @"1 / ( 1 + \exp ( - c_{" + constants.Count + "} ";
     242        string p = @"1 / \left( 1 + \exp \left( - c_{" + constants.Count + "} ";
    244243        constants.Add(conditionTreeNode.Slope);
    245         p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - c_{" + constants.Count + @"} ) ) )   ";
     244        p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - c_{" + constants.Count + @"} \right) \right) \right)   ";
    246245        constants.Add(conditionTreeNode.Threshold);
    247         strBuilder.Append(@" +  ( 1 - " + p + @" ) \cdot ");
     246        strBuilder.Append(@" +  \left( 1 - " + p + @" \right) \cdot ");
    248247      } else {
    249248        throw new NotImplementedException("Export of " + node.Symbol + " is not implemented.");
     
    253252    private void FormatEnd(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
    254253      if (node.Symbol is Addition) {
    255         strBuilder.Append(@" ) ");
     254        strBuilder.Append(@" \right) ");
    256255      } else if (node.Symbol is Subtraction) {
    257         strBuilder.Append(@" ) ");
     256        strBuilder.Append(@" \right) ");
    258257      } else if (node.Symbol is Multiplication) {
    259258      } else if (node.Symbol is Division) {
     
    262261          strBuilder.Append(" } ");
    263262      } else if (node.Symbol is Average) {
    264         strBuilder.Append(@" ) ");
     263        strBuilder.Append(@" \right) ");
    265264      } else if (node.Symbol is Logarithm) {
    266         strBuilder.Append(@" ) ");
     265        strBuilder.Append(@" \right) ");
    267266      } else if (node.Symbol is Exponential) {
    268         strBuilder.Append(@" ) ");
     267        strBuilder.Append(@" \right) ");
    269268      } else if (node.Symbol is Sine) {
    270         strBuilder.Append(@" ) ");
     269        strBuilder.Append(@" \right) ");
    271270      } else if (node.Symbol is Cosine) {
    272         strBuilder.Append(@" ) ");
     271        strBuilder.Append(@" \right) ");
    273272      } else if (node.Symbol is Tangent) {
    274         strBuilder.Append(@" ) ");
     273        strBuilder.Append(@" \right) ");
    275274      } else if (node.Symbol is GreaterThan) {
    276         strBuilder.Append(@" ) ");
     275        strBuilder.Append(@" \right) ");
    277276      } else if (node.Symbol is LessThan) {
    278         strBuilder.Append(@" ) ");
     277        strBuilder.Append(@" \right) ");
    279278      } else if (node.Symbol is And) {
    280         strBuilder.Append(@" > 0 ) ) ");
     279        strBuilder.Append(@" > 0 \right) \right) ");
    281280      } else if (node.Symbol is Or) {
    282         strBuilder.Append(@" > 0 ) ) ");
     281        strBuilder.Append(@" > 0 \right) \right) ");
    283282      } else if (node.Symbol is Not) {
    284         strBuilder.Append(@" ) ");
     283        strBuilder.Append(@" \right) ");
    285284      } else if (node.Symbol is IfThenElse) {
    286         strBuilder.Append(@" ) ) ");
     285        strBuilder.Append(@" \right) ");
    287286      } else if (node.Symbol is Constant) {
    288287      } else if (node.Symbol is LaggedVariable) {
    289288      } else if (node.Symbol is Variable) {
    290289      } else if (node.Symbol is ProgramRootSymbol) {
     290        strBuilder
     291          .AppendLine("\\end{align*}")
     292          .AppendLine("\\begin{align*}")
     293          .AppendLine("\\nonumber");
    291294        // output all constant values
    292295        if (constants.Count > 0) {
    293296          int i = 0;
    294297          foreach (var constant in constants) {
    295             strBuilder.AppendLine(@"\\");
    296             strBuilder.Append("c_{" + i + "} & = " + constant);
     298            // replace "." with ".&" to align decimal points
     299            var constStr = string.Format(System.Globalization.NumberFormatInfo.InvariantInfo, "{0:G5}", constant);
     300            if(!constStr.Contains(".")) constStr = constStr + ".0";
     301            constStr = constStr.Replace(".", "\\negthickspace&.");  // fix problem in rendering of aligned expressions
     302            strBuilder.Append("c_{" + i + "}& = & " + constStr);
     303            strBuilder.Append(@"\\");
    297304            i++;
    298305          }
    299306        }
     307        strBuilder.AppendLine("\\end{align*}");
    300308      } else if (node.Symbol is Defun) {
    301309      } else if (node.Symbol is InvokeFunction) {
    302         strBuilder.Append(@" ) ");
     310        strBuilder.Append(@" \right) ");
    303311      } else if (node.Symbol is StartSymbol) {
    304312      } else if (node.Symbol is Argument) {
    305313      } else if (node.Symbol is Derivative) {
    306         strBuilder.Append(@" ) }{dt} ");
     314        strBuilder.Append(@" \right) }{dt} ");
    307315      } else if (node.Symbol is TimeLag) {
    308316        var laggedNode = node as ILaggedTreeNode;
    309317        currentLag -= laggedNode.Lag;
    310318      } else if (node.Symbol is Power) {
    311         strBuilder.Append(@" ) } ");
     319        strBuilder.Append(@" \right) } ");
    312320      } else if (node.Symbol is Root) {
    313         strBuilder.Append(@" ) } ) } ");
     321        strBuilder.Append(@" \right) } } ");
    314322      } else if (node.Symbol is Integral) {
    315         var laggedTreeNode = node as ILaggedTreeNode;
    316         strBuilder.Append(@" ) ");
     323        strBuilder.Append(@" \right) ");
    317324      } else if (node.Symbol is VariableCondition) {
    318         strBuilder.Append(@"\left) ");
     325        strBuilder.Append(@"\right) ");
    319326      } else {
    320327        throw new NotImplementedException("Export of " + node.Symbol + " is not implemented.");
     
    331338
    332339    private string EscapeLatexString(string s) {
    333       return s.Replace(@"_", @"\_");
     340      return "\\text{" +
     341        s
     342         .Replace("\\", "\\\\")
     343         .Replace("{", "\\{")
     344         .Replace("}", "\\}")
     345         .Replace("%", "\\%")
     346        + "}";
    334347    }
    335348  }
Note: See TracChangeset for help on using the changeset viewer.