Calcul matriciel avec libgiac : manipulation du type matrice

Librairie C++ de calcul formel/ C++ symbolic computation library

Modérateur : xcasadmin

johan
Messages : 3
Inscription : mer. oct. 08, 2008 5:35 pm
Contact :

Calcul matriciel avec libgiac : manipulation du type matrice

Message par johan » jeu. janv. 08, 2009 3:15 pm

Bonjour,

Je souhaite utiliser la bibliothèque Giac pour effectuer du calcul matriciel (en commençant par la fonction padic_linsolve).

Je suis conscient que pour l'instant la documentation développeur n'est pas très fournie, et du coup je pense que mes problèmes peuvent en concerner d'autres (d'où mon post ici).

Je vais commencer par essayer d'expliquer le cheminement que j'ai suivi pour en arriver où je suis (c'est à dire, pas très loin...).

En cherchant dans le répertoire demo, je suis tombé sur pgcd.cc qui est un petit programme qui calcul l'intégrale d'une fonction (contrairement à son nom :). Comme c'est un programme très simple qui marche - et que c'est apparemment le seul en c++ parmi les exemples -, je suis parti de celui ci pour essayer de faire un petit programme chargeant un système d'équations linéaires (sous forme matriciel bien évidemment) et appelant la fameuse fonction padic_linsolve qui se trouve dans vecteur.h

Premières interrogations : le type matrice est un alias de vecteur qui est lui même une sorte de std::vector<gen> où gen est un type générique qui peut être un int :) J'ai bien vu la présence de fonction makevecteur pour fabriquer un vecteur à partir de quelques valeurs, mais aucune fonction pour faire (ou charger) une matrice ?

Je pensais avoir compris que gen peut aussi être un vecteur, et que donc une matrice étant un vecteur de vecteur, il suffirait alors d'utiliser des makevecteur imbriqués ? Quid de la différence entre lignes et colonnes ? Par exemple, si je veux la matrice [[1,2],[3,4]], dois-je écrire makevecteur (makevecteur (1,2), makevecteur (3,4)) ou
makevecteur (makevecteur (1,3), makevecteur (2,4)) ?

Mais surtout, j'ai un problème à l'execution lorsque j'essaye d'utilise makevecteur ainsi :

Code : Tout sélectionner

% g++ -W -Wall -g test_padic_linsolve.cc -lgiac -lgmp
% ./a.out 
*** glibc detected *** ./a.out: free(): invalid pointer: 0x08091000 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb6c37a85]
/lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb6c3b4f0]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb6e02b11]
./a.out[0x8048e9b]
./a.out(_ZNSt12_Vector_baseIN4giac3genESaIS1_EE13_M_deallocateEPS1_j+0x27)[0x8048ec5]
/usr/lib/libgiac.so.0(_ZNSt6vectorIN4giac3genESaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_+0x2d0)[0xb7215c5a]
/usr/lib/libgiac.so.0(_ZNSt6vectorIN4giac3genESaIS1_EE9push_backERKS1_+0x5e)[0xb7212106]
/usr/lib/libgiac.so.0(_ZN4giac11tab2vecteurEPNS_3genE+0x42)[0xb76bb2aa]
/usr/lib/libgiac.so.0[0xb77aa331]
/usr/lib/libgiac.so.0[0xb77ab339]
/usr/lib/libgiac.so.0[0xb7c4bb75]
/usr/lib/libgiac.so.0[0xb71cc2cd]
/lib/ld-linux.so.2[0xb7ef4990]
/lib/ld-linux.so.2[0xb7ef4ac3]
/lib/ld-linux.so.2[0xb7ee784f]

Deuxièmes interrogations : une fois la matrice chargé, y-a-t-il des facilités pour l'afficher ? Le mieux étant qu'en faisant std::cout << mat << std::endl; il m'affiche la matrice... mais je ne sais pas où trouver les fonctions d'affichage disponibles ?

Dernières interrogations : Toutes les fonctions, ou presque, on un paramètre GIAC_CONTEXT. J'ai cru comprendre que c'était lié à l'utilisation multi-threads... comment fait-on pour appeler une telle fonction ? Y-a-t'il une valeur par défaut, genre :

Code : Tout sélectionner

#define GIAC_CONTEXT (int = 0)
Voilà c'est tout pour la première vague de questions ;)
Johan, apprenti Gi@cien

parisse
Messages : 5739
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: Calcul matriciel avec libgiac : manipulation du type mat

Message par parisse » ven. janv. 09, 2009 7:18 am

johan a écrit :
Premières interrogations : le type matrice est un alias de vecteur qui est lui même une sorte de std::vector<gen> où gen est un type générique qui peut être un int :) J'ai bien vu la présence de fonction makevecteur pour fabriquer un vecteur à partir de quelques valeurs, mais aucune fonction pour faire (ou charger) une matrice ?
Pour le compilateur, il n'y a pas de difference entre vecteur et matrice, qui sont tous deux des std::vector<giac>, j'ai cree 2 typedef juste pour que ca soit plus clair dans les en-tetes de fonction. Une matrice, c'est un vecteur de gen dont les elements sont eux-memes des vecteurs (les lignes) de meme longueur.
On peut generer une matrice ou un vecteur avec les fonctions de la STL, ou avec la fonction makevecteur ou en utilisant le parser depuis une chaine de caracteres ou avec la fonction read depuis un fichier. Par exemple
gen g("[[1,2],[3,4]]",contextptr)
cree un gen de type matrice,
matrice m=*g._VECTptr;
permet d'acceder a cette matrice avec m[0] (ligne [1,2]) et m[1] (ligne [3,4]).
Je pensais avoir compris que gen peut aussi être un vecteur, et que donc une matrice étant un vecteur de vecteur, il suffirait alors d'utiliser des makevecteur imbriqués ? Quid de la différence entre lignes et colonnes ? Par exemple, si je veux la matrice [[1,2],[3,4]], dois-je écrire makevecteur (makevecteur (1,2), makevecteur (3,4)) ou
makevecteur (makevecteur (1,3), makevecteur (2,4)) ?
le 1er
Mais surtout, j'ai un problème à l'execution lorsque j'essaye d'utilise makevecteur ainsi :

Code : Tout sélectionner

% g++ -W -Wall -g test_padic_linsolve.cc -lgiac -lgmp
% ./a.out 
*** glibc detected *** ./a.out: free(): invalid pointer: 0x08091000 ***
...
Il me faudrait le source complet pour voir ce que ca donne chez moi.
Deuxièmes interrogations : une fois la matrice chargé, y-a-t-il des facilités pour l'afficher ? Le mieux étant qu'en faisant std::cout << mat << std::endl; il m'affiche la matrice... mais je ne sais pas où trouver les fonctions d'affichage disponibles ?
Il y a gen(m).print(contextptr) qui genere une std::string contenant la matrice.
Dernières interrogations : Toutes les fonctions, ou presque, on un paramètre GIAC_CONTEXT. J'ai cru comprendre que c'était lié à l'utilisation multi-threads... comment fait-on pour appeler une telle fonction ? Y-a-t'il une valeur par défaut, genre :

Code : Tout sélectionner

#define GIAC_CONTEXT (int = 0)
Voilà c'est tout pour la première vague de questions ;)
il suffit de creer un contexte
context ct;
puis d'appeler la fonction avec &ct comme dernier parametre. On peut aussi utiliser 0 comme valeur de contexte (qui refere a un contexte global).

a+
Dernière modification par parisse le mar. janv. 13, 2009 8:48 am, modifié 1 fois.

johan
Messages : 3
Inscription : mer. oct. 08, 2008 5:35 pm
Contact :

Message par johan » lun. janv. 12, 2009 11:09 pm

Merci Bernard pour ces réponses.

Voici le code qui provoque chez moi l'appel de free sur un pointeur non valide :

Code : Tout sélectionner

% cat test_padic_linsolve.cc
// -*- compile-command: "g++ -W -Wall test_padic_linsolve.cc -lgiac -lgmp" -*-
#include <giac/giac.h>
#include <giac/vecteur.h>

using namespace std;
using namespace giac;

int main()
{
   matrice a = makevecteur (makevecteur(1,2), makevecteur (3,4));
}
J'ai donc essayé la solution qui me semblait la plus pratique :

Code : Tout sélectionner

gen a ("[[1,2],[3,4]]");
Mais le compilateur ne trouve pas de constructeur à partir d'une chaîne de caractères uniquement... par contre, en cherchant dans gen.h, j'ai vu qu'il y avait cette méthode :

Code : Tout sélectionner

gen (const std::string & s,GIAC_CONTEXT); 
Et du coup, le code suivant fonctionne :

Code : Tout sélectionner

gen a ("[[1,2],[3,4]]", 0);
std::cout << a.print(0) << std::endl;
Dernière modification par johan le ven. janv. 16, 2009 4:16 pm, modifié 1 fois.
Johan, apprenti Gi@cien

parisse
Messages : 5739
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Message par parisse » mar. janv. 13, 2009 8:47 am

En effet, j'avais oublie d'indiquer la variable de contexte pour le constructeur a partir d'une chaine, je corrige dans le message correspondant.
Sinon, j'ai teste le code qui posait des problemes avec free (en corrigeant la ligne #include<giac>, il y a un probleme avec le logiciel de gestion du forum phpbb2, il mange le /giac.h), et chez moi ca fonctionne sans erreur, il faudrait compiler avec -g et lancer depuis gdb pour voir dans quel fonction de giac le probleme apparait chez vous.

johan
Messages : 3
Inscription : mer. oct. 08, 2008 5:35 pm
Contact :

Message par johan » ven. janv. 16, 2009 4:51 pm

Effectivement, pour la configuration de phpbb, il faut désactiver par défaut l'html afin d'eviter qu'il mange les </xxx>

Sinon voici le résultat avec gdb :

Code : Tout sélectionner

Program received signal SIGABRT, Aborted.
[Switching to Thread 0xb68fd980 (LWP 6785)]
0xb7f04410 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7f04410 in __kernel_vsyscall ()
#1  0xb6c15085 in raise () from /lib/tls/i686/cmov/libc.so.6
#2  0xb6c16a01 in abort () from /lib/tls/i686/cmov/libc.so.6
#3  0xb6c4db7c in ?? () from /lib/tls/i686/cmov/libc.so.6
#4  0xb6c55a85 in ?? () from /lib/tls/i686/cmov/libc.so.6
#5  0xb6c594f0 in free () from /lib/tls/i686/cmov/libc.so.6
#6  0xb6e20b11 in operator delete () from /usr/lib/libstdc++.so.6
#7  0x08049051 in __gnu_cxx::new_allocator<giac::gen>::deallocate (this=0xb7edb228, __p=0x8091000) at /usr/include/c++/4.2/ext/new_allocator.h:97
#8  0x0804907b in std::_Vector_base<giac::gen, std::allocator<giac::gen> >::_M_deallocate (this=0xb7edb228, __p=0x8091000, __n=1)
    at /usr/include/c++/4.2/bits/stl_vector.h:134
#9  0xb7233c5a in std::vector<giac::gen, std::allocator<giac::gen> >::_M_insert_aux () from /usr/lib/libgiac.so.0
#10 0xb7230106 in std::vector<giac::gen, std::allocator<giac::gen> >::push_back () from /usr/lib/libgiac.so.0
#11 0xb76d92aa in giac::tab2vecteur () from /usr/lib/libgiac.so.0
#12 0xb77c8331 in ?? () from /usr/lib/libgiac.so.0
#13 0xb77c9339 in ?? () from /usr/lib/libgiac.so.0
#14 0xb7c69b75 in ?? () from /usr/lib/libgiac.so.0
#15 0xb71ea2cd in _init () from /usr/lib/libgiac.so.0
#16 0xb7f12990 in ?? () from /lib/ld-linux.so.2
#17 0xb7f12ac3 in ?? () from /lib/ld-linux.so.2
#18 0xb7f0584f in ?? () from /lib/ld-linux.so.2
Il semblerait que le problème vient de la fonction giac::tab2vecteur
mais je suis entrain de me dire qu'il utilise libgiac.so de la version 0.8.2 de giac alors que je compile avec les headers de la version 0.9.... c'est peut-être la raison du problème.
Johan, apprenti Gi@cien

parisse
Messages : 5739
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Message par parisse » ven. janv. 16, 2009 6:17 pm

Oui, ça expliquerait, car j'ai changé la structure de données gen dans la version 0.9.0, pour que ça prenne moins de place en particulier sur les architectures 64 bits (si on compile avec -DSMARTPTR64, on arrive à 8 octets pour un gen au lieu de 16), ainsi que la façon de gérer les comptes de référence.
Attention, toutefois, la 0.9.0 n'a pas encore été beaucoup testée et j'y fais pas mal de modifs en ce moment, pour accélerer en particulier le calcul de PGCD de polynomes.

Répondre