12
votes

Comment augmenter la taille de la matrice sur la volée en Fortran?

Mon programme est en cours d'exécution, étiqueter des "clusters" qu'il trouve, puis en faisant des vérifications pour voir si des clusters voisins ont une étiquette supérieure à celle du groupe actuel. Il y a un deuxième tableau qui tient la «bonne» étiquette de cluster. S'il estime que le nième groupe adjacent est étiqueté correctement, cet élément est attribué à 0, sinon l'attribue à l'étiquette correcte (par exemple si le nième site a la étiquette 2 et un voisin est étiqueté 3, le 3ème élément de la labelarray est défini sur 2). J'ai une bonne raison de faire ça, honnête!

Tout ce que je veux, c'est pouvoir attribuer le nième élément du labelarray à la volée. J'ai regardé des tableaux allocatables et déclarer des choses comme labelarray (*) mais je ne comprends pas vraiment ceux-ci, malgré la recherche sur le Web et Stackoverflow.

Donc, toute aide pour le faire serait génial.


0 commentaires

3 Réponses :


7
votes

Si vous déclarez une matrice allouée, vous utilisez defered Shape dans le formulaire réel,

allouatable :: labelarray (::) code> p>

P> P> P> P> P> P> P> P >

réel, dimension (:), allouacable :: labelarray code> p>

avec le nombre de classements de signification (nombre d'index) de votre tableau. P>

Si le tableau est non alloué, vous utilisez p> xxx pré>

avec le nombre correct d'index. Par exemple, allouer (labelarray (2: 3, -1: 5)) code> pour la matrice avec des index 2 à 3 dans la mesure 1 et -1 à 5 dans la dimension 2. P>

pour Changement de dimension Vous devez annouez d'abord le tableau en utilisant P>

 labelArray = [labelArray, new_element]


5 commentaires

C'est donc une déclaration valide? Allocate (labelarray (taille (labelarray) +1)) Tout ce que je veux, c'est augmenter la taille lorsque j'ajoute un élément.


Non ce n'est pas possible. Vous ne pouvez pas modifier la dimension allouée de la matrice. Ce serait de compliquer. Le programme devrait faire de toute façon une copie tout à fait. Vous devez 1) faire un nouveau tableau plus grand et copier sur elle, ou 2) faire une copie de votre tableau, deallocate it, allouer il est plus grand et copiez les valeurs enregistrées arrière. Si votre compilateur le prend en charge, vous pouvez utiliser mobile_alloc , au lieu de copier, vous n'avez pas à annouez votre tableau, juste allouer plus grand et copiez les valeurs enregistrées. .


En fait, trop compliqué ... il y a realloc en C, mais Fortran ne l'a pas.


Cela doit être le record du temps le plus long entre deux parties de commentaire.


Je vais fixer une date sur mon calendrier pour revenir à cette réponse dans 10 ans pour battre ce disque. Il est une fois une fois, il a vécu une personne qui n'a pas fini ses phrases avant



11
votes

Voici une question de dépassement de pile avec certains exemples de code montrant plusieurs façons d'utiliser des tableaux allocalisables Fortran: Comment obtenir primat-incontrôlable en tant que sortie d'une fonction de Fortran : déclarer, allouer, tester des tests d'étant déjà alloué, en utilisant Le nouveau Move_ALLOC et l'allocation sur la mission. Non indiqué Il y a une distribution explicite, car les exemples utilisent bougy_alloc et distribution automatique sur la sortie d'une procédure.

P.s. Si vous souhaitez ajouter plusieurs éléments, vous devez penser à votre approche de la structure de données. L'ajout d'un élément à la fois en cultivant une matrice n'est pas une approche efficace. Pour cultiver un tableau de N éléments à N + 1 en Fortran signifie probablement créer un nouveau tableau et copier tous les éléments existants. Une structure de données plus appropriée pourrait être une liste liée. Vous pouvez créer une liste liée à Fortran en créant un type défini par l'utilisateur et en utilisant des pointeurs. Vous chaînez les membres ensemble, pointant de l'un à l'autre. Les frais généraux pour ajouter un autre membre est mineur. L'inconvénient est qu'il est plus facile d'accéder aux membres de la liste dans l'ordre. Vous n'avez pas la capacité facile d'un tableau, en utilisant des indices pour accéder aux membres dans n'importe quel ordre.

info sur les listes liées à Fortran que j'ai trouvées sur le Web: http://www-uxsup.csx.cam.ac.uk/courses/fortran/paper_12.pdf et http://www.iag.uni-sttgart.de/iag/institut/abteilungen/numerik/images/4/ 4c / pointeur_introduction.pdf


8 commentaires

Alors, regardez ce que @vladimir a écrit, et votre lien, est ce code acceptable? allouer (TEMP (Taille (labelarray) +1)) // TEMP (: Taille (labelarray)) = labelarray // appelez mobile_alloc (TEMP, labelArray)


Ça a l'air correct. Si la taille de la matrice est grande, elle peut être inefficace en raison de la copie causée par la déclaration d'affectation.


Ok, quand je l'ai couru avec un tableau surdimensionné, il n'y avait pas de nombreux éléments réels. Je suis restreint l'utilisation de Fortran90 cependant, et je ne pensais pas que cela avait des pointeurs?


Fortran 90 a des pointeurs. Si vous êtes limité à Fortran 90 (il y a longtemps!), Vous ne pourrez pas utiliser mobile_ALLOC, car c'est un ajout FORTRAN 2003. Le remplacement consiste à annoncer Labelarray, allouez Lakearray à la nouvelle taille, attribuer à Lakearray, puis distribuer la temp.


Je mets dans le code Move_ALLOC et la compilée ne me crie pas. J'ai mis dans le code de distribution maintenant et cela ne crie toujours pas. Je dois corriger un problème d'attribution de tableau avant que je sache cela fonctionnait cependant.


Je reçois maintenant un Segfault à une ligne de code apparemment arbitraire, qui ne concerne pas le morceau de code avec l'allocation et la répartition. Je suis un peu confus quant à la raison pour laquelle cela serait. Si je déplace l'allocation / la répartition de la répartition, SEGFAULTS sur la ligne de distribution: DealLocate (labelarray) . Une idée pourquoi?


@PureFerret Post code exemple s'il vous plaît? Segfault sur la ligne de DealLocate signifie probablement que vous essayez de rétrograder un tableau / index qui n'a pas été attribué.


J'ai repéré ce qui se passe mal; Oui, je n'ai pas alloué Lakearray avant de traiter. Ira correction. EDIT: Cela fonctionne maintenant. Merci tout le monde!



1
votes

Commentaire tardive ... Vérifiez les recettes numériques pour Fortran 90. Ils ont mis en place une belle fonction de réaffecte qui était conforme à la Fortran 90. Vos matrices doivent être attribuées au pointeur dans ce cas, non attribuées allouées.

La fonction reçoit l'ancien tableau et la taille souhaitée et renvoie un pointeur sur le nouveau tableau redimensionné.

Si possible, utilisez Fortran 95 ou 2003. Si 2003 est impossible, alors 95 est un bon compromis. Il fournit une meilleure syntaxe de pointeur.


0 commentaires