[GiNaC-list] Re: math-polyglot (fwd)

Chris Dams Chris.Dams at mi.infn.it
Tue Jul 11 16:57:06 CEST 2006

Dear all,

For the international conference on mathematical software
(http://www.icms2006.unican.es/), I was invited to show how some problems
could be solved using GiNaC. Below you find the mail that I sent as an
answer. If somebody here can think of better solutions to the problems,
please post a message.

Best wishes,

---------- Forwarded message ----------
Dear Nobuki,

Below are solutions to the problems, insofar GiNaC addresses them.

Best wishes,

Type into ginsh: 1+2;
Answer: 3

integral(sqrt(1-x^2)): Symbolic integration is rather limited in GiNaC. It 
can only integrate polynomials.

Fourier transform of exp(-x^2): same.

Subgroups of S_5: GiNaC does not have functions to handle this kind of
group theory problem.

Type into ginsh: 4*atan(1);
Answer: Pi

Drawing a parabola: GiNaC does not have graphics capabilities. It would be 
possible to do the numerics in GiNaC and let the plotting handle by some 
other library/utility.

Drawing a saddle: same

Define a function and load it:
// Header file "myfun.h": //

GiNaC::ex myfun(const GiNaC::ex &x, const GiNaC::ex &y);

// Implementation file "myfun.C": //
#include "myfun.h"

using namespace GiNaC;

ex myfun(const ex &x, const ex &y)
   return x+y;

// Main file: test.C //

#include <iostream>
#include <ginac/ginac.h>
#include "myfun.h"

using namespace std;
using namespace GiNaC;

int main()
   cout << myfun(1,2) << endl;
   return 0;

Compiling myfun: g++ -O2 `ginac-config --cppflags`  -c myfun.C
Compiling main: g++ -O2 `ginac-config --cppflags`  -c test.C
Linking the two: g++ `ginac-config --libs` -o test test.o myfun.o
Running: ./test
Output: 3

Syllogistic: GiNaC does not have functions for logic. We can, however, 
write a function to test all posibilities in the thruthtable.
#include <iostream>
#include <ginac/ginac.h>

using namespace std;
using namespace GiNaC;

symbol True("True");
symbol False("False");

// Declare that implies is a GiNaC-function of two parameters.

// Automatic evaluation of implies in case that sufficiently many of the
// paramters are given as "True" and "False" in order to know the result;
// If not enough parameters are given, return the expression implies(x, 
ex implies_eval(const ex &x, const ex &y)
   if (x==False)
      return True;
   if (x==True)
      if (y==False)
         return False;
      else if (y==True)
         return True;

   // The .hold() indicates that this result should not be further 
   return implies(x, y).hold();

// Declare that the just-defined function is used for the evaluation of
// the function implies.
REGISTER_FUNCTION(implies, eval_func(implies_eval));

// Check if the expression x evaluates to True for any combination of
// True/False substitued for the subexpressions given in l.
bool check_truth(const ex &x, const lst &l)
   // Get the size of l.
   int num_expr = l.nops();
   // The number of possibilities to check.
   unsigned possibs = 1 << num_expr;

   // Loop over the possibilities to assign true and false to num_expr
   // subexpressions.
   for (unsigned i=0; i<possibs; ++i)
   {  exmap m; // To store by what the subexpressions are going to be 
      for (int j=0; j<num_expr; ++j)
         m[l.op(j)] = i&(1<<j) ? True : False;
      // Evaluate the expression for this particular posibility.
      ex result = x.subs(m);
      if (result != True)
         return false; // This is a C++ boolean, not ours.

   return true; // This is a C++ boolean, not ours.

int main()
   symbol P("P");
   symbol Q("Q");
   symbol R("R");
   ex syllogistic
      = implies(implies(P,Q), implies(implies(Q,R), implies (P, R)));
   bool holds = check_truth(syllogistic, lst(P,Q,R));
   if (holds)
      cout << syllogistic << " holds." << endl;
      cout << syllogistic << " does not hold." << endl;
   return 0;

implies(implies(P,Q),implies(implies(Q,R),implies(P,R))) holds.

Powers of a matrix:
In ginsh:
> evalm( [[0,1],[1,1]] ^ 1 );
> evalm( [[0,1],[1,1]] ^ 2 );
> evalm( [[0,1],[1,1]] ^ 3 );
> evalm( [[0,1],[1,1]] ^ 4 );
> evalm( [[0,1],[1,1]] ^ 5 );
> evalm( [[0,1],[1,1]]^1 * [[1],[1]] );
> evalm( [[0,1],[1,1]]^2 * [[1],[1]] );
> evalm( [[0,1],[1,1]]^3 * [[1],[1]] );
> evalm( [[0,1],[1,1]]^4 * [[1],[1]] );
> evalm( [[0,1],[1,1]]^5 * [[1],[1]] );

Kernel of an integral matrix:
#include <iostream>
#include <ginac/ginac.h>

using namespace std;
using namespace GiNaC;

int main()
   matrix m(2, 4);
   m = 1, 1, 1, 1,
       0, 2, 4, 5;

   symbol x1("x1"), x2("x2"), x3("x3"), x4("x4");
   matrix unknowns(4,1);
   unknowns = x1, x2, x3, x4;

   matrix rhs(2,1);
   rhs = 0, 0;

   cout << m.solve(unknowns, rhs) << endl;

   return 0;

Output: [[x3+3/2*x4],[-2*x3-5/2*x4],[x3],[x4]]

Draw a graph of the Lorentz equation: Not sure what advantage GiNaC could
bring here. No need for arbitrary precision arithmetic and GiNaC does not
have plotting facilities.

Elimination of variables: GiNaC does not have functions to solve systems 
of non-linear equations.

Factorization of polynomials: GiNaC only has squarefree factorization and 
this problem cannot be solved that way.

More information about the GiNaC-list mailing list