Page 1 of 1

capturer la valeur renvoyée par solve dans une variable

Unread postPosted: 28 Jan 2015, 21:08
by solidsteak02
Bonjour,

Je suis nouveau ici et ai créé le topic car je ne trouve pas de solution à mon souci...
je cherche à automatiser un calcul que je suis régulièrement amené à effectuer en chimie

je souhaiterais écrire une fonction dans laquelle je rentre 2 équations, à 2 variables : f1(s,g) et f2(s,g).
ma fonction doit prendre la première fonction, en initialisant g à 1 et la résoudre pour trouver s
On injecte alors s dans f2(s,g)pour retrouver une valeur de g, que l'on réinjecte dans f1(s,g)...
et je réitère l'opération jusqu'à converger vers une valeur

Mon problème tient en deux points:

1/ je n'arrive pas à faire capturer la valeur renvoyée par la fonction solve() dans une variable que je pourrais réutiliser.
2/ma condition dans ma boucle ne renvoie pas de valeur true ou false...elle se présente comme suit: while (stmp-s)/s>0.005

Si quelqu'un a une idée... je serais bien avancé

En vous remerciant d'avance

Bonne journée

Re: capturer la valeur renvoyée par solve dans une variable

Unread postPosted: 28 Jan 2015, 21:13
by critor
Bonsoir,


Tu pourrais peut-être utiliser la fonction zeros() qui est plus adaptée que solve() au stockage des solutions dans une variable.
Image

Re: capturer la valeur renvoyée par solve dans une variable

Unread postPosted: 28 Jan 2015, 21:45
by solidsteak02
alors ça implique que je bidouille un poil mon équation pour que ça passe. c'est faisable et ça a l'air de marcher à peu près...
ceci dit je reste sceptique parce que la boucle while devrait fonctionner, et elle ne tourne pas...malgré la condition, qui est bonne (tant que a est supérieure à 0.005 la boucle doit tourner, et je fais afficher a juste avant l'entrée dans la boucle, qui me donne 69)

Re: capturer la valeur renvoyée par solve dans une variable

Unread postPosted: 28 Jan 2015, 22:11
by Bisam
La fonction "exp>list" (avec le triangle noir à la place de > ) fait exactement ce que tu veux : elle prend le résultat d'un "solve" et renvoie une liste contenant les différentes solutions.
Cf. le manuel pour plus d'explications.

Re: capturer la valeur renvoyée par solve dans une variable

Unread postPosted: 28 Jan 2015, 22:39
by solidsteak02
j'ai essayé ça en me documentant...mais je m'en suis probablement mal servi car elle me renvoyait des listes vides.

Tu aurais une idée concernant la boucle While?
je voulais qu'elle continue tant que ma valeur de s et celle de la précédente boucle soit à moins de 0.5% d'écart l'une de l'autre, mais il semblerait qu'elle ne se lance meme pas...
je posterai mon code demain si vous voulez, ce sera peut-etre plus clair...
Bonne nuit. =)

Re: capturer la valeur renvoyée par solve dans une variable

Unread postPosted: 28 Jan 2015, 23:26
by Bisam
Voici un code qui réalise l'algorithme que tu veux écrire :
Code: Select all
g:=1
stmp:=0
s:=exp@>list(solve(f1(s,g)=0,s),s)[1]
While abs(stmp-s)/s>0.005
  s:=stmp
  g:=exp@>list(solve(f2(s,g)=0,g),g)[1]
  stmp:=exp@>list(solve(f1(s,g)=0,s),s)[1]
EndWhile
Return s

Bien sûr, il faut avoir défini les fonctions "f1" et "f2" auparavant... mais je peux aussi t'expliquer comment faire cela.
Il se peut, bien sûr, que ce code ne fonctionne pas lorsque "solve" ne trouve aucune solution... ou pire si la suite des approximations successives diverge... mais je suppose qu'en pratique cela n'arrive jamais.

Re: capturer la valeur renvoyée par solve dans une variable

Unread postPosted: 29 Jan 2015, 17:02
by solidsteak02
En effet en pratique ça n'arrivera pas je pense en effet, mais c'est gentil d'y penser.

alors j'ai retenté, et avec ce code la fonction me renvoie qu'il y a trop d'arguments...je vois pas trop comment, mais bon...

Re: capturer la valeur renvoyée par solve dans une variable

Unread postPosted: 29 Jan 2015, 22:24
by solidsteak02
Rebonjour

Bon j'ai fait quelques tests...

voici mon code (j'ai commenté les disp dont je ne veux pas mais dont je me sers pour tester)

Code: Select all
Define LibPub iterasi(fcs,fcg,s,g)=
Func
:Local fcs,fcg,s,g,stmp
:s:=zeros(fcs,s)|g=1
:
:©Disp s
:©Disp g
:stmp:=1
:©Disp ((stmp-s)/(s)),s
:While ((stmp-s)/(s))>0.005
:g:=zeros(fcg,g)
:stmp:=s
:s:=zeros(fcs,s)
:EndWhile
:Disp s,g
:EndFunc


J'ai remplacé le exp@>list() car la doc disait qu'utiliser zeros() était plus pratique. Au passage ça m'évite d'avoir une erreur de dimension de matrice, que je ne sais pas résoudre.
J'ai la vague impression que la résolution de fcg en la variable g ne prend pas en compte la valeur de s que je cherche à entrer dedans...

j'ai fcg(s,g), et fcs(s,g), et je voudrais remplacer s dans fcs par la valeur que je viens de calculer à l'initialisation de la fonction...mais comme je le dis, j'ai l'impression qu'il ne veut pas accepter ce genre de choses

j'ai créé la variable stmp pour pouvoir effectuer un controle entre la valeur s et celle trouvée au tour de boucle précédent, quand les deux résultats sont à moins de 0.5%d'écart, je sors de la boucle et commande l'affichage de s et g

Je ne vois pas vraiment pourquoi ça marche pas, et donc ne sais pas comment le fixer :/

(si jamais ça intéresse quelqu'un s représente la nouvelle solubilité d'un sel après ajout d'une autre solution avec ion commun, et g représente le coefficient d'activité de ma solution(et g varie donc entre 0 et 1).

Re: capturer la valeur renvoyée par solve dans une variable

Unread postPosted: 29 Jan 2015, 23:00
by Bisam
Si tu donnes "fcs" et "fcg" en paramètres, ce sont pour la calculette des expressions.
A priori, ces expressions, même si elles contiennent les variables "s" et "g" dans leur expression, ne seront pas modifiées si tu changes les valeurs des variables dans ta fonction.

Il faut fabriquer des fonctions à l'intérieur de ta fonction.
Voici une méthode :
Code: Select all
Define LibPub iterasi(expr1, expr2, var1, var2)=
Func
:Local f1,f2,s,g,stmp
:expr("f1(" & string(var1) & "," & string(var2) & "):=" & string(expr1))
:expr("f2(" & string(var1) & "," & string(var2) & "):=" & string(expr2))
:
:s:=zeros(f1(s,1),s)
:
:©Disp s
:©Disp g
:stmp:=1
:©Disp ((stmp-s)/(s)),s
:While ((stmp-s)/(s))>0.005
:g:=zeros(f2(s,g),g)
:stmp:=s
:s:=zeros(f1(s,g),s)
:EndWhile
:Disp s,g
:EndFunc