30 votes

Suggestions sur la syntaxe pour exprimer la formule mathématique de manière concise

Je suis en train d'élaborer domaine fonctionnel spécifique langage intégré au sein de C++ pour traduire les formules dans le code du travail de manière aussi concise et précise que possible.

J'ai posté un prototype dans les commentaires, il est d'environ deux cents lignes de long.

Droit maintenant, ma langue ressemble à quelque chose comme ceci (bon, en fait va ressembler):

// implies two nested loops j=0:N, i=0,j
(range(i) < j < N)[T(i,j) = (T(i,j) - T(j,i))/e(i+j)];

// implies summation over above expression
sum(range(i) < j < N))[(T(i,j) - T(j,i))/e(i+j)];

Je suis à la recherche de la syntaxe possible des améliorations/extensions ou juste des idées différentes sur l'exprimer en formules mathématiques le plus clairement et le plus précisément possible (dans toutes les langues, pas seulement en C++).

Pouvez-vous me donner quelques exemples de syntaxe concernant ma question qui peut être accompli dans la langue de votre choix que vous jugerez utiles. En particulier, si vous avez quelques idées sur la façon de traduire le code ci-dessus segments, je serais heureux de les entendre.

Je vous remercie.

Juste pour clarifier et donner une formule, mon objectif à court terme est d'exprimer la suivante

alt textalt text

l'expression concise où les valeurs en <> sont déjà calculé que le 4-dimensions des tableaux.

6voto

miked Points 1993

Si vous allez à la rédaction du présent pour l'ab-initio monde (qui je suppose à partir de votre MP2 équation) vous voulez faire, il est très clair et facile à exprimer des choses aussi proche de la définition mathématique que vous le pouvez.

Pour l'un, je n'aurais pas le compliqué range fonction. Ont-il définir une boucle, mais si vous souhaitez les boucles imbriquées, les spécifier à la fois:

Ainsi, au lieu de

(range(i) < j < N)[T(i,j) = (T(i,j) - T(j,i))/e(i+j)];

utilisation

loop(j,0,N)[loop(i,0,j)[T(i,j) = (T(i,j) - T(j,i))/e(i+j)]]

Et pour des choses comme la somme et le produit, faire de la syntaxe "hériter" du fait que c'est une boucle.

Ainsi, au lieu de

sum(range(i) < j < N))[(T(i,j) - T(j,i))/e(i+j)];

utilisation

sum(j,0,n)[loop(i,0,j)[(T(i,j) - T(j,i))/e(i+j)]]

ou si vous avez besoin d'une somme double

sum(j,0,n)[sum(i,0,j)[(T(i,j) - T(j,i))/e(i+j)]]

Puisqu'il semble que vous essayez de représenter la mécanique quantique des opérateurs, alors essayez de faire vos constructions de langage match de l'opérateur sur un nul 1-1 à base d'aussi près que possible. De cette façon, il est facile de traduire (et clair sur ce qui est en cours de traduction).

EDITÉ POUR AJOUTER

puisque vous êtes en train de faire de la chimie quantique, alors il est assez facile (à moins que la syntaxe va). Vous définissez les opérateurs qui travaillent toujours sur ce qui est de la droite et puis la seule chose dont vous avez besoin sont des parenthèses au groupe où un opérateur s'arrête.

Einstein notation est amusant où vous ne spécifiez pas les indices ou des limites et elles sont implicites en raison de la convention, cependant ce n'est pas faire un code clair et il est plus difficile de penser.

Pour les sommes, même si les limites implicites, elles sont toujours faciles à déterminer en fonction du contexte, de sorte que vous devriez toujours rendre les gens à les spécifier.

sum(i,0,n)sum(j,0,i)somme(a,-j,j)somme(b,-i,i)....

Puisque chaque opérateur travaille à la droite, de ses variables sont connues, donc j peux savoir à propos de moi, un peut savoir à propos de i et j et b peut savoir à propos de i,j, et un.

De mon expérience avec le quantum des chimistes (je suis de trop!) ils n'aiment pas la syntaxe compliquée qui diffère beaucoup de ce qu'ils écrivent. Ils sont heureux de séparer le double et le triple des sommes et intégrales dans une collection de singles, car ceux-ci sont juste abréviation de toute façon.

La symétrie n'est pas va être dur non plus. C'est juste une collection de swaps et ajoute ou se multiplie. J'aimerais faire quelque chose où vous spécifiez l'opération, qui contient une liste des éléments qui sont les mêmes et peuvent être échangés:

c2v(sigma_x,a,b)a+b

Ceci dit que a et b peuvent être considérés comme identiques des particules sous l'effet d'un c2v opération. Ce qui signifie que toute équation avec a et b tels que a+b après) doit être transformée en une combinaison linéaire de la c2v transformations. le sigma_x est l'opération dans c2v que vous souhaitez appliquer à votre fonction, (a+b). Si je me souviens bien, c'est 1/sqrt(2)((a+b)+(b+a)). Mais je n'ai pas de symétrie livre ici, de sorte que peut-être erroné.

3voto

Crazy Eddie Points 23778

Je préfère une plus grande séparation entre les boucles. Par exemple, je préfère cette autre notation pour votre deuxième exemple:

sum(range(j) < N)[sum(range(i) < j)[(T(i,j) - T(j,i))/e(i+j)]]

Je trouve aussi que la syntaxe difficile. Je pense que la gamme devrait être un seul composant. Je préfère quelque chose comme ceci:

j = range_iter(0,N)

Cela permettrait d'ouvrir pour range x(0,N); j = range.begin(); ou des solutions de rechange je ne peux pas penser dès maintenant.

Vous pourriez même:

j = range_iter(inc(0) => exc(N)); pour j parcourt [0,N).

De toute façon, idée intéressante. Pouvez-vous les fonctions qui en résulte être composé? Pouvez-vous demander les informations de domaine?

3voto

Timo Points 3221

Si vous êtes à la recherche pour plus de simplicité, vous devez prendre le désire des boucles encore plus loin. E. g., quelque chose comme ceci

T( i < j , j < N ) = ( T(i,j) - T(j,i) )/e(i+j)

ne fonctionnera que si vous réécrivez l'opérateur d'assignation = de se comporter normalement quelque chose comme a(i) = b(i) + c(i) , mais se comportent comme une sommation pour a(i<5) = b(i) + c(i). Supposons sommation commence à partir de 0, à moins que la limite inférieure est spécifié, par exemple, a(3<i<5), cochez la symbolique des limites supérieures et inférieures qui apparaissent comme la somme des indices et faire des double des sommes nécessaires. Si vous voulez la syntaxe à force de clarté, vous pouvez définir un capital de l'opérateur s=

T( i < j , j < N ) s= ( T(i,j) - T(j,i) )/e(i+j)

Je ne pense pas que vous pouvez obtenir tout plus propre que ce et encore ont peu d'usage général de la convivialité. Comme pour votre objectif à court terme, en utilisant la notion de spécification de la somme de l'indice en même temps que l'indice de ce qui apparaît à première, vous pourriez écrire.

E_MP2 s= EV( i < n1 , j < n2 , a < n3 , b < n4 ) *
         2 ( EV(a,b,i,j) - EV(a,b,j,i) ) / ( e(i)+e(j)-e(a)-e(b) )

lorsque vous déclarez explicitement que c'est une somme (à l'aide d' s=) faisant l'opérateur puis prendre la sommation des indices et des valeurs de limitation de la première instance d'un index s'affiche. Plus précisément, vous pouvez également utiliser une syntaxe (en supposant maintenant a,b fixe et i,j tels que par votre exemple)

E_MP2 s=(i<j,j<N) EV(i,j,a,b) *
                  2 ( EV(a,b,i,j) - EV(a,b,j,i) ) / ( e(i)+e(j)-e(a)-e(b) )

ce qui est tout à fait clair notationally.

Vous pouvez alors allez-y et prendre ce concept encore plus loin, par exemple, la définition de l'intégration de l'opérateur i= qui fait la même chose. I. e. il semble pour les instances de variables qui sont marqués vers le bas avec des limites et procède ensuite à intégrer l'expression à l'égard de ces variables

F i=(0<x<Pi) x^-1 * exp(-I x^2)

de même pour la somme, vous pouvez spécifier la limite lorsque x apparaît pour la première fois

F i= x[0,Pi]^-1 * exp(-I x^2)

où les crochets servent à différencier la notation de sommation, de sorte que vous n'avez pas à utiliser i= ou s= et peut utiliser à la fois la sommation et intégration à la même époque:

F(i) = G(i,j<10) * x[0,inf]^-1 * H(i,j,x)

2voto

pmr Points 30450

Je ne connais pas bien Phoenix et je ne peux que formuler des hypothèses sur ses capacités.

J'ai toujours aimé la façon dont Haskell me permet d'exprimer des plages sous forme de compréhension de liste. Il traduit bien de la notation mathématique réelle dans la construction du langage de programmation.

 [ i + j | i <- [1..10], j <- [1..10] ]
 

finirait comme quelque chose comme:

 [ i + j | i = range(1,10), j = range(1,10) ]
 

Malheureusement, je ne sais vraiment pas si cela est possible avec Phoenix.

1voto

 T = T - T'/e;
 

ou, si vous n'utilisez pas tout T

 T(0:i,0:j) = T(0:i,0:j) - T(0:i,0:j)'/e(0:i,0:j)
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X