Julia: nouvelle syntaxe pour la transposition

CrĂ©Ă© le 15 mars 2017  Â·  103Commentaires  Â·  Source: JuliaLang/julia

Maintenant que .op est généralement la forme vectorisée de op , il est trÚs déroutant que .' signifie transpose plutÎt que la forme vectorisée de ' (adjoint, alias ctranspose ). Ce numéro est destiné à discuter des syntaxes alternatives pour la transposition et/ou l'adjoint.

linear algebra parser

Commentaire le plus utile

S'opposent trÚs fortement à ce tr(A) signifie une transposition matricielle - tout le monde va penser que cela signifie une trace matricielle : https://en.wikipedia.org/wiki/Trace_ (linear_algebra)

Tous les 103 commentaires

Andreas a essayĂ© Aᔀ (et peut-ĂȘtre Aᎎ ) dans #19344, mais cela n'a pas Ă©tĂ© trĂšs bien reçu. Nous pourrions Ă©galement jouer sur ^ avec des types d'exposants spĂ©ciaux T (et peut-ĂȘtre H ) tels que A^T est transposĂ©, mais c'est plutĂŽt louche aussi. Je ne suis pas sĂ»r qu'il existe de nombreuses autres bonnes options qui ressemblent encore un peu Ă  la notation mathĂ©matique.

Je pense en quelque sorte que t(A) pourrait ĂȘtre le meilleur, mais c'est malheureux de "voler" un autre nom d'une lettre.

Déplacer mon commentaire de l'autre problÚme (pas que cela résout quoi que ce soit, mais ...) :

+1 pour utiliser autre chose que .' .

Je n'ai pas pu trouver de langages avec une syntaxe spĂ©ciale pour la transposition, Ă  l'exception d'APL qui utilise le pas si Ă©vident ⍉ et Python qui utilise *X (ce qui serait dĂ©routant pour Julia). Plusieurs langages utilisent transpose(X) ; R utilise t(X) . Ce n'est pas joli, mais ce n'est pas pire que .' . Au moins, vous ĂȘtes moins tentĂ© d'utiliser ' en le confondant avec .' : il serait clair qu'il s'agit d'opĂ©rations trĂšs diffĂ©rentes.

Voir le code Rosetta . (BTW, l'exemple de Julia illustre en fait la transposition conjuguée ...)

L'une des autres tiques pourrait-elle ĂȘtre utilisĂ©e ? ` ou "

-100 pour changer d'adjoint, car c'est l'une des choses géniales qui rend l'écriture de code Julia aussi claire que l'écriture de mathématiques, et la transposition conjuguée est généralement ce que vous voulez de toute façon, il est donc logique d'avoir une syntaxe abrégée pour cela.

Tant que nous avons la belle syntaxe pour la transposition conjuguée, un opérateur postfixé pour la transposition réguliÚre semble généralement inutile, donc le simple fait d'en faire un appel de fonction régulier me semble bien. transpose fonctionne déjà ; ne pourrions-nous pas simplement utiliser cela? Je trouve le t(x) R-ism malheureux, car son nom ne dit pas clairement ce qu'il est censé faire.

Utiliser une coche différente serait un peu bizarre, par exemple A` peut ressembler beaucoup à A' selon la police, et A" ressemble trop à A'' .

Si nous apportons le changement dans # 20978, alors une transposition postfixée devient en fait plus utile qu'elle ne l'est maintenant. par exemple, si vous avez deux vecteurs x et y et que vous voulez leur appliquer f par paire, vous pouvez faire par exemple f.(x, y.') ... avec #20978 , cela sera applicable aux tableaux de types arbitraires.

HonnĂȘtement, je pense que notre meilleure option est toujours de le laisser tel quel. Aucune des suggestions ne me semble ĂȘtre une nette amĂ©lioration. .' a l'avantage d'ĂȘtre familier avec Matlab. Le . est en fait quelque peu conforme Ă  la syntaxe d'appel de points dans des exemples comme f.(x, y.') , et suggĂšre (un peu correctement) que la transposition "fuse" (elle ne produit pas de copie temporaire grĂące Ă  RowVector et ses futures gĂ©nĂ©ralisations).

En fait, nous pourrions mĂȘme aller plus loin et faire f.(x, g.(y).') une opĂ©ration de fusion. c'est-Ă -dire que nous changeons la transposition de .' pour qu'elle soit non rĂ©cursive ala #20978 et nous Ă©tendons sa sĂ©mantique pour inclure la fusion avec d'autres appels de points imbriquĂ©s. (Si vous voulez la version sans fusion, vous appelleriez transpose .)

J'aime beaucoup ce plan, @stevengj.

Un hic : vraisemblablement la macro @. ne transforme pas y' en y.' (car ce serait faux). Cela pourrait cependant transformer y' en une sorte d'opération adjointe fusionnée.

Le principal problÚme est de trouver un moyen propre de faire en sorte que f.(x, g.(y).') ait une sémantique de fusion. Une possibilité serait de le transformer en f.(x, g.(y.')) et donc en broadcast(x,y -> f(x, g(y)), x, y.') ?

Notez que, pour que cela fonctionne correctement, nous devrons peut-ĂȘtre restaurer la mĂ©thode de secours transpose(x) = x , auquel cas nous pourrions tout aussi bien laisser la transposition rester rĂ©cursive.

Je pense que dĂ©cider si la transposition doit ĂȘtre rĂ©cursive ou non est orthogonal Ă  la question de savoir si nous la faisons participer Ă  la fusion de la syntaxe Ă  points. Le choix de le rendre non rĂ©cursif n'est pas motivĂ© par cela.

@StefanKarpinski , si vous restaurez un repli transpose(x) = x , alors la plupart de la motivation pour le changer pour qu'il soit non récursif disparaßt.

Quel est le problÚme si le repli est restauré mais que la transposition est toujours non récursive ?

@jebej , la transposition récursive est plus correcte lorsqu'elle est utilisée comme opération mathématique sur des opérateurs linéaires. Si je me souviens bien, la principale raison de le rendre non récursif était de ne pas avoir à définir le repli transpose(x) = x , plutÎt que de lancer une MethodError.

Mais ce ne serait pas terrible d'avoir le repli tout en étant non récursif.

Permettez-moi d'ajouter deux commentaires (j'ai parcouru la discussion précédente et je ne les ai pas remarqués - désolé si j'ai omis quelque chose):

  • la documentation pour permutedims indique qu'il s'agit d'une gĂ©nĂ©ralisation de la transposition pour les tableaux multidimensionnels. transpose , ce qui n'est pas le cas.
  • Comment est-on censĂ© faire une transposĂ©e d'un vecteur x=["a", "b"] ? En fait, y=x.' fonctionne et crĂ©e une nouvelle variable mais getindex Ă©choue dessus. AFAIK, vous devez utiliser reshape(x, 1, :) ou beaucoup plus lent hcat(x...) pour y parvenir, mais il n'est pas naturel d'avoir une syntaxe diffĂ©rente pour Vector ( permutedims ne fonctionne pas ici ).

Quel est votre cas d'utilisation pour transposer un vecteur de chaßnes ?

Considérez le scénario suivant par exemple :

x = ["$(j+i)" for j in 1:3, i in 1:5]
y = ["$i" for i in 5:9]

et je veux ajouter y aprĂšs la derniĂšre ligne de x . Et le moyen le plus simple est de vcat une transposition de y .

Apparaßt en pratique lors de la journalisation incrémentielle de données textuelles dans un Matrix{String} (je pourrais utiliser Vector{Vector{String}} ), mais souvent la matrice est plus utile (ou alors encore une fois il y a une question comment convertir Vector{Vector{String}} à Matrix{String} en concaténant verticalement des éléments consécutifs).

Autre cas d'utilisation : la transposition est le moyen le plus simple de rendre deux vecteurs orthogonaux entre eux afin de diffuser une fonction sur le produit cartésien ( f.(v, w.') ).

Point de données : Hier, j'ai rencontré une partie confuse par l'opérateur postfixé "broadcast-adjoint" et pourquoi il se comporte comme une transposition. Meilleur!

FWIW, je pense fermement que nous devrions nous dĂ©barrasser de la syntaxe .' . En tant que personne plus familiĂšre avec Julia qu'avec Matlab, je m'attendais Ă  ce que cela signifie adjoint vectorisĂ© et j'ai vraiment trĂ©buchĂ© quand ce n'Ă©tait pas le cas. Julia n'est pas Matlab et ne devrait pas ĂȘtre liĂ©e par les conventions de Matlab - si dans Julia, un point signifie la vectorisation de la fonction adjacente, alors cela devrait ĂȘtre cohĂ©rent dans tout le langage et ne devrait pas avoir au hasard la seule horrible exception que .' n'est formellement pas liĂ© Ă  ' .

Je pense que c'est bien d'avoir juste transpose sans aucune notation spéciale "tick", puisque la grande majorité du temps, il est appelé sur une matrice de nombres réels, donc ' serait équivalent si vous vraiment envie d'économiser la frappe. Si nous voulons créer une version fusionnée de transpose, alors je ne pense vraiment pas que .' soit la bonne syntaxe.

C'est un bon point. On peut dire que seul l'adjoint a besoin d'une syntaxe super compacte.

Appelons simplement cela transpose et dĂ©prĂ©cions .' . À l'avenir, nous pourrons considĂ©rer si nous voulons .' comme adjoint ponctuel ou si nous voulons simplement le laisser obsolĂšte pour Ă©viter de piĂ©ger les utilisateurs de Matlab.

Notez que je viens de parcourir les packages enregistrĂ©s et que j'ai trouvĂ© plus de 600 utilisations de .' , donc ce n'est pas trĂšs rare. Et avec les appels de points / broadcast (qui n'ont commencĂ© Ă  gĂ©rer pleinement les donnĂ©es non numĂ©riques qu'en 0.6), le dĂ©sir de transposer paresseusement des tableaux non numĂ©riques (oĂč l'adjoint a moins de sens) deviendra probablement beaucoup plus courant, donc l'argument en faveur d'une syntaxe compacte est quelque peu renforcĂ©.

Ensuite, nous ferions mieux de déprécier .' dÚs que possible, avant que davantage de code ne soit piégé dans un mauvais modÚle d'utilisation.

Pourquoi est-ce mauvais?

Le problÚme est que .' ne signifie plus ce qu'il semble signifier en tant qu'opérateur pointillé.

Comme je l'ai dit ci-dessus, parce que cela viole le modÚle général selon lequel . signifie vectorisation, et semble signifier adjoint vectorisé (en particulier pour quelqu'un qui n'est pas familier avec Matlab).

Je pense que @stevengj fait valoir un bon point - cela est lié au désir d'une simple transposition non récursive.

Je sais que c'Ă©tait impopulaire, mais je commence Ă  privilĂ©gier le #19344 d'Andreas pour ᔀ . À ce stade, je prĂ©fĂ©rerais dĂ©prĂ©cier l'utilisation de _tous_ les exposants comme identifiants et interprĂ©ter _tous_ les exposants de fin comme des opĂ©rateurs postfixĂ©s. Cela donne Ă©galement un chemin vers la rĂ©solution de certains problĂšmes autour literal_pow en utilisant des nombres en exposant. Oui, ce serait triste de perdre χÂČ et autres noms de variables, mais je pense que les avantages l'emporteraient sur les inconvĂ©nients.

À ce stade, je prĂ©fĂ©rerais dĂ©prĂ©cier l'utilisation de _tous_ les exposants comme identifiants et interprĂ©ter _tous_ les exposants de fin comme des opĂ©rateurs postfixĂ©s.

RIP mon code
screenshot from 2017-11-09 22-08-25

À ce stade, je prĂ©fĂ©rerais dĂ©prĂ©cier l'utilisation de tous les exposants comme identifiants

Je ne pense vraiment pas que ce serait nĂ©cessaire, alors que nous voulons juste T et peut-ĂȘtre quelques autres choses Ă  l'avenir.

Une constance folle


Oui, il est lĂ©gĂšrement incohĂ©rent d'utiliser .' pour la transposition, mais toutes les alternatives proposĂ©es jusqu'Ă  prĂ©sent semblent ĂȘtre pires. Ce n'est pas la pire chose au monde de dire " .' est une transposition, une exception Ă  la rĂšgle habituelle concernant les opĂ©rateurs point". Vous apprenez cela et passez Ă  autre chose.

Une chose à noter qui peut aider à toute confusion potentielle sur le fait .' n'est pas une diffusion par points est qu'il s'agit d'un opérateur postfixé, alors que la diffusion préfixée est op. et l'infixe est .op . On peut donc dire que . ne veut pas dire diffusé quand c'est postfixé. L'autre utilisation du suffixe . est la recherche de champ, et getfield(x, ') n'a pas de sens, il est donc distinct des autres significations.

(Cela dit, je préfÚre transpose(x) plutÎt que de garder .' .)

@stevengj Je parierais que bon nombre (peut-ĂȘtre la plupart) des plus de 600 utilisations de .' dans les packages enregistrĂ©s que vous avez mentionnĂ©s ci-dessus pourraient ĂȘtre remplacĂ©es par ' sans frais pour la lisibilitĂ©, et le code continuerait Ă  travailler.

Peut-ĂȘtre pas populaire, mais il pourrait toujours y avoir des suffixes " et ` ?

utilisations de .' dans les packages enregistrĂ©s que vous avez mentionnĂ©s ci-dessus pourrait ĂȘtre remplacĂ© par ' sans frais pour la lisibilitĂ©, et le code continuerait Ă  fonctionner.

Notez qu'une fois #23424 atterri, nous pourrons utiliser transpose sur des tableaux de chaĂźnes et ainsi de suite, mais pas adjoint . La meilleure pratique pour l'utilisation de l'algĂšbre linĂ©aire de x.' deviendra trĂšs probablement quelque chose comme conj(x') (j'espĂšre que c'est paresseux, c'est-Ă -dire gratuit). Bien que j'aime utiliser .' pour sa compacitĂ©, peut-ĂȘtre que s'en dĂ©barrasser forcera les utilisateurs d'algĂšbre linĂ©aire Ă  utiliser la bonne chose et les utilisateurs de tableaux de donnĂ©es Ă  utiliser transpose Ă©pelĂ©.

il pourrait encore y avoir des suffixes " et ` ?

La nouvelle syntaxe pour transpose() semble plutĂŽt prĂ©maturĂ©e. À mon humble avis, il serait prĂ©fĂ©rable de simplement dĂ©prĂ©cier .' pour ĂȘtre remplacĂ© comme vous le suggĂ©rez par conj(x') et transpose selon les besoins.

J'ai l'impression que .' est si utile dans matlab principalement en raison de l'insistance de matlab sur le fait que "tout est une matrice" ainsi que du manque de rÚgles de découpage cohérentes telles que vous devez souvent insérer des transpositions aléatoires à divers endroits pour faire fonctionner les choses.

Pour résumer les arguments ici :

  1. .' est maintenant le seul opérateur en pointillé qui ne signifie pas "appliquer l'opérateur sans pointillé élément par élément" ; les nouveaux utilisateurs ne venant pas de Matlab trouvent que c'est un piÚge surprenant.

  2. .' est maintenant effectivement ambigu : vouliez-vous dire transpose ou vouliez-vous dire conj(x') ? En principe, chaque utilisation hĂ©ritĂ©e de .' doit ĂȘtre vĂ©rifiĂ©e pour dĂ©terminer s'il s'agit de permuter les indices d'un tableau Ă  2 dimensions ou s'il s'agit d'un "adjoint non conjuguĂ©".

Le premier problÚme est problématique mais pas fatal en soi ; le deuxiÚme problÚme est vraiment mauvais - ce n'est plus une seule opération cohérente, mais plutÎt elle sera divisée en deux significations distinctes.

Je viens de remarquer que si jamais nous changions .' pour signifier "adjoint Ă©lĂ©ment par Ă©lĂ©ment", alors conj(x') serait Ă  peu prĂšs Ă©quivalent Ă  x'.' et conj(x)' serait Ă  peu prĂšs x.'' qui est tellement proche de x.' 😬.

Peut-ĂȘtre pas populaire, mais il pourrait toujours y avoir des suffixes " et ` ?

Copiez-collez le code dans Slack et voyez que détruire la coloration syntaxique serait...

Pouvoir transposer n'importe quoi est agrĂ©able car cela facilite le "produit croisĂ©" via le mĂ©canisme de rĂ©partition, et d'autres cas d'utilisation courts et concis comme celui-ci. Le problĂšme de ne pas avoir de solution de repli facile pour ce genre de choses est que, invariablement, le hack que nous verrons consiste simplement Ă  dĂ©finir des solutions de repli transpose(x) = x (ou sur les types de base, donc le piratage de type dans les packages) pour faire cela genre de chose fonctionne facilement. Cela me fait penser : pourquoi n'est-ce pas Complex l'intrus ? L'adjoint de la plupart des nombres est lui-mĂȘme, donc l'adjoint du complexe est celui sur lequel se spĂ©cialiser : cela ne peut-il pas ĂȘtre Ă©tendu au-delĂ  des nombres ?

Je vois ici deux choses trÚs liées :

1) x' ne fonctionne pas pour les types non numériques, nous voulons donc un moyen de le faire facilement pour d'autres données
2) transpose(x) n'est pas aussi simple que x.' . C'est surtout pour les cas de (1), puisque les cas d'utilisation pour transposer des matrices complexes sont beaucoup plus rares.

Mais au lieu de descendre (2), pourquoi ne pas essayer de faire une correction raisonnable pour (1) ?

Peut-ĂȘtre qu'une solution raisonnable est juste une macro qui fait que ' signifie transposition au lieu d'adjoint ?

Mais au lieu de descendre (2), pourquoi ne pas essayer de faire une correction raisonnable pour (1) ?

Nous avons dĂ©jĂ  parcouru ce chemin et plusieurs adjacents. Il y a eu une grande quantitĂ© de discussions qui en ont rĂ©sultĂ© que quelqu'un d'autre peut peut-ĂȘtre distiller, mais en rĂ©sumĂ©, cela ne fonctionne pas bien. Fondamentalement, l'opĂ©ration mathĂ©matique adjoint n'a pas de sens sur des choses qui ne sont pas des nombres. Utiliser ' sur des non-nombres simplement parce que vous aimez la syntaxe concise est mauvais - c'est le pire type de calembour d'opĂ©rateur et il ne devrait pas ĂȘtre surprenant que de mauvaises choses dĂ©coulent de ce type d'abus de sens. La fonction adjoint ne doit ĂȘtre dĂ©finie que sur des choses dont il est logique de prendre l'adjoint et ' ne doit ĂȘtre utilisĂ© que pour signifier cela.

Rappelez-vous que .' tel qu'il est actuellement utilisĂ© est fondamentalement deux opĂ©rations diffĂ©rentes : la transposition de tableau et l'adjoint non conjuguĂ©. Le problĂšme de transposition rĂ©cursive met en Ă©vidence le fait que ce sont des opĂ©rations diffĂ©rentes et que nous avons donc besoin de diffĂ©rentes façons de les exprimer. Les matheux semblent catĂ©goriques sur le fait que l'opĂ©ration adjointe non conjuguĂ©e est (a) importante et (b) diffĂ©rente du simple Ă©change de dimensions. En particulier, pour ĂȘtre correct, l'adjoint non conjuguĂ© doit ĂȘtre rĂ©cursif. D'autre part, l'Ă©change des dimensions d'un tableau gĂ©nĂ©rique ne doit clairement pas ĂȘtre rĂ©cursif. Ces opĂ©rations doivent donc ĂȘtre Ă©crites diffĂ©remment et les utilisations existantes de .' doivent ĂȘtre dĂ©sambiguĂŻsĂ©es comme ayant une signification ou une autre. DĂ©prĂ©cier .' est un moyen de forcer cela.

Enfin, mĂȘme si je suis convaincu que permutedims(x, (2, 1)) est dĂ©finitivement trop gĂȘnant pour Ă©changer les dimensions d'un tableau 2d, je trouve l'argument selon lequel transpose(x) est trop gĂȘnant peu convaincant. Cette opĂ©ration est-elle si courante qu'avoir un nom de fonction simple et clair est trop? Vraiment? L'Ă©change des dimensions d'un tableau est - il beaucoup plus courant ou important que toutes les autres choses dans le langage pour lesquelles nous utilisons les noms de fonction et la syntaxe d'appel de fonction ? La notation de chef de mĂ©nage rend adjoint assez spĂ©cial puisque nous voulons Ă©crire des choses comme v'v , v*v' et v'A*v . C'est pourquoi adjoint obtient une trĂšs belle syntaxe. Mais Ă©changer les dimensions d'un tableau ? Cela ne justifie pas un opĂ©rateur Ă  mon avis.

Pas un argument solide, mais j'utilise souvent l'opĂ©rateur ' pour imprimer des tableaux de maniĂšre plus compacte (lorsqu'il est utilisĂ© comme de simples conteneurs), par exemple lorsque je veux voir le contenu de quelques vecteurs en mĂȘme temps sur mon Ă©cran ( et invariablement frustrĂ© quand il Ă©choue parce que les Ă©lĂ©ments ne peuvent pas ĂȘtre transposĂ©s). Donc, une courte syntaxe pour le REPL est vraiment pratique. (En outre, cela permet aux personnes habituĂ©es aux tableaux majeurs de lignes d'avoir un moyen simple de "changer l'ordre", en particulier lors du portage d'algorithmes sur julia Ă  l'aide de tableaux 2d; mais ce n'est certainement pas un argument solide non plus). Juste pour dire que c'est une belle syntaxe concise qui n'est pas seulement utile aux algĂ©bristes linĂ©aires.

J'avais commenté quelques idées de syntaxe sur https://github.com/JuliaLang/julia/pull/19344#issuecomment -261621763, en gros c'était :

julia> const ᔀ, ᎎ = transpose, ctranspose;

julia> for op in (ᔀ, ᎎ)
           <strong i="7">@eval</strong> Base.:*(x::AbstractArray{T}, f::typeof($op)) where {T<:Number} = f(x)
       end

julia> A = rand(2, 2)
2×2 Array{Float64,2}:
 0.919332  0.651938
 0.387085  0.16784

julia>  Aᔀ = (A)ᔀ    # variable definition and function application are both available!
2×2 Array{Float64,2}:
 0.919332  0.387085
 0.651938  0.16784

julia> Aᎎ = (A)ᎎ
2×2 Array{Float64,2}:
 0.919332  0.387085
 0.651938  0.16784

Mais sans le hack bien sĂ»r, juste l'idĂ©e qu'il peut y avoir une sorte "d'application de fonction postfixĂ©e" et qu'elle exige des parenthĂšses (x)f , les versions pointillĂ©es pourraient ĂȘtre comme ça (x).f ( xf serait un identifiant, mĂȘme si f est un exposant).

Cet exemple de hack fonctionnait sur 0.6 mais maintenant :

julia> Aᔀ = (A)ᔀ               
ERROR: syntax: invalid operator

julia> Aᔀ = (A)transpose       
2×2 Array{Float64,2}:          
 0.995848  0.549117            
 0.69401   0.908227            

julia> Aᎎ = (A)ᎎ               
ERROR: syntax: invalid operator

julia> Aᎎ = (A)ctranspose      # or adjoint or whatever
2×2 Array{Float64,2}:          
 0.995848  0.549117            
 0.69401   0.908227            

Ce qui est triste, je voulais à l'origine faire ça pour les pouvoirs:

julia> square(n) = n^2; cube(n) = n^3;

julia> Base.:*(n, f::typeof(square)) = f(n)

julia> Base.:*(n, f::typeof(cube)) = f(n)

julia> const ÂČ = square    # why?
syntax: invalid character "ÂČ"

julia> const Âł = cube    # why?
syntax: invalid character "Âł"

Ce que je pensais naĂŻvement permettrait une syntaxe comme: nÂČ = (n)ÂČ et nÂł = (n)Âł Mais tout identifiant numĂ©rique est interdit d'ĂȘtre en premiĂšre position, cependant (A)⁻Âč a Ă©galement fonctionnĂ©, oĂč ⁻Âč Ă©tait const ⁻Âč = inv .

J'ai implémenté un hack similaire pour InfixFunctions.jl .

En tant qu'utilisateur, je pourrais simplement faire un package PostfixFunctions.jl et ĂȘtre satisfait de ce que vous trouverez de mieux ici. Mais actuellement, ces restrictions de syntaxe :

  • l'utilisation de superindices numĂ©riques au dĂ©but d'un identifiant n'est pas autorisĂ©e
  • superindex x * ᶠ en suffixe (multiplication implicite dans le hack) (x)ᶠ non autorisĂ©

Cela me semble un peu trop Ă  mon humble avis, j'aimerais au moins pouvoir dĂ©finir des identifiants qui peuvent commencer par des exposants numĂ©riques, ou plus gĂ©nĂ©ralement, interdire uniquement les caractĂšres numĂ©riques rĂ©els 0-9 avec la sĂ©mantique numĂ©rique, au dĂ©but d'un identifiant, ce serait gĂ©nial. 😄

Acclamations!

Voir #10762 pour une discussion sur les autres caractÚres numériques comme identifiants.

L'autre problĂšme est liĂ© Ă  #22089, les suffixes d'opĂ©rateurs. +ᔀ est maintenant un opĂ©rateur valide, qui (probablement accidentellement) interdit les identifiants consistant uniquement Ă  combiner des caractĂšres dans des contextes oĂč un opĂ©rateur pourrait ĂȘtre attendu. Cela me semble ĂȘtre un bug. Il est Ă©galement un peu Ă©trange que ᔀ soit un identifiant valide mais que -ᔀ ne fasse pas -(ᔀ) . Cependant, ce n'est pas la fin du monde, et la rĂ©solution de l'OMI ne vaudrait pas la peine de perdre d'autres utilisations possibles de ᔀ .

Notez que l'utilisation .' comme opĂ©rateur de transposition postfixĂ© n'est mĂȘme pas sur la table ici (malgrĂ© ce que dit le sujet du problĂšme), la considĂ©ration est en fait de savoir si nous devrions garder .' comme opĂ©rateur postfixĂ© pour l'adjoint non conjuguĂ©, qui serait rĂ©cursif. Il s'agit souvent de la mĂȘme chose que la transposition, mais ce n'est gĂ©nĂ©ralement pas la mĂȘme opĂ©ration. Si les gens de l'algĂšbre linĂ©aire sont prĂȘts Ă  laisser .' signifie transposer un tableau gĂ©nĂ©rique, c'est une autre histoire, mais j'ai l'impression que ce n'est pas acceptable.

@Ismael-VC, je peux voir autoriser (x)ᔀ comme syntaxe de fonction postfixĂ©e pour les exposants - car qu'est-ce que cela signifierait d'autre? Je pense que lĂ  oĂč votre proposition commence Ă  frotter les gens dans le mauvais sens, c'est de permettre Ă  n'importe quel identifiant d'ĂȘtre appliquĂ© en tant que fonction dans la syntaxe postfixĂ©e. Je le limiterais aux exposants.

@StefanKarpinski , je pensais que le consensus était précisément d'autoriser .' signifie une transposition de tableau non récursive et non conjuguée (si nous avons cet opérateur), tandis que ' est le récursif, conjugué opération adjointe.

Je dĂ©teste vraiment, vraiment l'idĂ©e d'utiliser ᔀ pour un opĂ©rateur de transposition postfixĂ©. Il est bien trop utile d'avoir un exposant dans les noms de variables, comme aᔀa ou LᔀDL = ltdlfact(A) . (Outre le fait qu'utiliser uniquement ᔀ pour un opĂ©rateur alors que d'autres exposants sont valides dans les identifiants serait bizarre.)

Ce n'Ă©tait pas du tout ma comprĂ©hension - je pensais que les gens linalg Ă©taient en faveur de garder a.' tel quel, c'est-Ă -dire conj(a)' . Garder .' mais changer sa signification en transposition de tableau est assez diffĂ©rent - je ne suis pas sĂ»r de ce que je ressens Ă  ce sujet. Je suis d'accord qu'avoir seulement ᔀ comme opĂ©rateur postfix serait ennuyeux et incohĂ©rent. J'aime plutĂŽt la proposition (a)ᔀ @Ismael-VC, qui n'empĂȘcherait pas d'utiliser aᔀ comme nom.

Mon souvenir de ces discussions reflÚte celui de Steven. La transposition récursive non conjuguée est rare et généralement assez étrange. Résumé décent ici : https://github.com/JuliaLang/julia/issues/20978#issuecomment -316141984.

Je pense que nous sommes tous d'accord sur le fait que le suffixe ' est adjoint et devrait rester.
Je pense que nous sommes tous d'accord sur le fait que le suffixe .' est une syntaxe sous-optimale.
Je pense que la plupart conviennent que la transposition non récursive (structurelle) est plus utile qu'une transposition récursive.

Ok, donc les points sur lesquels tout le monde semble ĂȘtre d'accord :

  1. Utilisez a' pour adjoint(a)
  2. Utilisez conj(a)' ou conj(a') pour l'adjoint (non-)conjugué.

Donc, le seul point de discorde est de savoir comment écrire la transposition du tableau :

  • Comme a.' ou
  • Comme transpose(a) ou
  • Comme (a)ᔀ .

Cette Ă©valuation est-elle correcte ?

Oui, je pense que oui (oĂč la "transposition de tableau" est non rĂ©cursive).

De plus, si je comprends bien, tout le monde convient que transpose(a) devrait dĂ©finitivement ĂȘtre une syntaxe valide (et non rĂ©cursive), et les seuls points de dĂ©saccord sont de savoir si .' et/ou (a)ᔀ doit ĂȘtre une syntaxe valide alternative (complĂštement Ă©quivalente).

Approche (1) de https://github.com/JuliaLang/julia/issues/20978#issuecomment -315902532, qui a reçu un bon support (par exemple https://github.com/JuliaLang/julia/issues/20978# issuecomment-316080448), reste une possibilité. J'ai une branche réalisant cette approche (présentant flip(A) ) que je peux publier.

Pour ce que ça vaut, je soutiens la dépréciation .' . La confusion et l'ambiguïté dans ce fil est un argument fort pour le faire en soi. Meilleur!

Je crois que tant que nous aurons le suffixe ' , les gens voudront l'utiliser pour diffuser f sur un produit cartĂ©sien de vecteurs avec f.(v, w') . Et les gens voudront l'utiliser pour remodeler un vecteur de chaĂźnes en un vecteur ligne d'en-tĂȘtes pour une structure de type table. Il est donc impĂ©ratif pour moi d'avoir un remplacement simple et facile Ă  utiliser vers lequel nous pouvons les diriger.

Voici une option que nous n'avons pas envisagĂ©e : A*' — un nouveau bigraphe. La notation mathĂ©matique typique pourrait interprĂ©ter cela comme conj(A)' , ce qui est en fait assez proche de ce que nous voulons. Il Ă©tait disponible sur la version 0.6, mais sur la version 0.7, nous autorisons l'utilisation * pour concatĂ©ner des caractĂšres
 toujours utilisable, cependant.

Je ne crois pas que les suffixes " et ` soient disponibles en raison de l'analyse littĂ©rale de chaĂźne personnalisĂ©e au-delĂ  de la fin d'une ligne. Postfix * seul est Ă©galement indisponible pour la mĂȘme raison. Le suffixe prime Aâ€Č est probablement l'un des identifiants Unicode les plus couramment utilisĂ©s, c'est donc encore plus que Aᔀ .

HonnĂȘtement, aprĂšs avoir regardĂ© mon code, je n'utilise pas du tout .' , donc transpose(a) est probablement bien.

Notez que je viens de parcourir les packages enregistrés et que j'ai trouvé plus de 600 utilisations de .', donc ce n'est pas trÚs rare.

Cet endroit a-t-il Ă©tĂ© vĂ©rifiĂ© pour voir si .' n'a pas Ă©tĂ© utilisĂ© lĂ  oĂč ' aurait Ă©tĂ© correct ? Je commence Ă  penser que cela pourrait ĂȘtre vrai plus souvent qu'autrement. Sinon, le seul endroit oĂč j'ai vu une utilisation lĂ©gitime de .' Ă©tait avant que les Ă©tiquettes Plots.jl n'autorisent un vecteur (au lieu de cela, je voulais un vecteur ligne de chaĂźnes), mais cela a Ă©tĂ© changĂ©. Pour les codes oĂč j'en ai vraiment besoin souvent, je pense que je commencerais Ă  faire T = transpose localement, ou lancerais une macro pour changer ' en transpose .

<strong i="17">@transpose</strong> A = A'*A*B'*B*C'*C

serait trĂšs bien avec moi pour ce cas rare.

les gens voudront l'utiliser pour diffuser f sur un produit cartĂ©sien de vecteurs avec f.(v, w'). Et les gens voudront l'utiliser pour remodeler un vecteur de chaĂźnes en un vecteur ligne d'en-tĂȘtes pour une structure de type table. Il est donc impĂ©ratif pour moi d'avoir un remplacement simple et facile Ă  utiliser vers lequel nous pouvons les diriger.

S'il n'apparaßt qu'une seule fois dans une instruction, n'est-il pas acceptable d'utiliser simplement transpose ?

La syntaxe a*' pour conjugué-adjoint est plutÎt sympa, bien qu'il ne semble pas vraiment que ce soit l'opération pour laquelle nous ayons besoin d'une meilleure syntaxe. &a sera bientÎt disponible et suggÚre d'échanger des choses, bien que ce soit assez différent des notations traditionnelles pour cela.

Peut-ĂȘtre est-il temps pour un sondage de paille?

Comment devrions-nous Ă©peler la transposition structurelle ?

(à peu prÚs dans l'ordre de proposition ; pas de jugement sur les noms d'emoji ici)

  • 👍 : A.' — changez simplement le sens, gardez la mĂȘme syntaxe
  • 👎 : transpose(A) — pas de syntaxe spĂ©ciale
  • 😄 : t(A) ou tr(A) — pas de syntaxe spĂ©ciale, mais exporte un nom plus court
  • 🎉 : Aᔀ — avec seulement ᔀ et peut-ĂȘtre un ou deux exposants en casse spĂ©ciale Ă  partir des identifiants
  • 😕 : (A)ᔀ — avec tous les exposants sĂ©parĂ©s des identifiants se comportant comme des opĂ©rateurs suffixĂ©s
  • ❀ : A*' – glose juste au-dessus de cette Ă©trange vallĂ©e, cela signifie une transposition structurelle
  • Si vous prĂ©fĂ©rez &A , jetez un 🎉 sur le message de Stefan juste au-dessus (nous n'avons plus d'emoji)

Les discussions de LinAlg ont en effet parlĂ© de donner .’ Ă  une utilisation de transposition non rĂ©cursive, puisque conj(x’) est relativement rare. Cependant, ᔀ est une syntaxe mathĂ©matique et devrait vraiment prendre le sens mathĂ©matique (le cas Ă©chĂ©ant).

S'opposent trÚs fortement à ce tr(A) signifie une transposition matricielle - tout le monde va penser que cela signifie une trace matricielle : https://en.wikipedia.org/wiki/Trace_ (linear_algebra)

Si ce n'est pas le cas, dĂ©prĂ©cier les exposants en tant qu'identifiant (ce qui doit probablement ĂȘtre considĂ©rĂ© sĂ©rieusement avant la version 1.0), alors ᔀ(A) est Ă©galement une possibilitĂ©.

En ce qui concerne la suggestion (A)ᔀ , mes excuses pour avoir lĂ©gĂšrement fait dĂ©railler cette discussion avec la remarque suivante :

Je ne me suis jamais beaucoup souciĂ© d'avoir √ disponible comme opĂ©rateur unaire, d'autant plus que vous finirez de toute façon par taper √(...) dĂšs que vous voudrez l'appliquer Ă  une variable qui est plus qu'un un ou plusieurs personnages. De plus, j'ai toujours trouvĂ© la diffĂ©rence de fonctionnement entre aÂČ et √a trĂšs artificielle. Cela a probablement du sens si vous connaissez les classes Unicode, etc., mais pour quelqu'un d'autre, cela doit sembler absurde. Bien sĂ»r, il est utile d'avoir aÂČ comme nom de variable valide, mais de mĂȘme √a pourrait ĂȘtre un nom de variable utile pour stocker la racine carrĂ©e de a si vous avez besoin de l'utiliser plusieurs fois. Ou des expressions plus compliquĂ©es comme aÂČb et sa racine carrĂ©e a√b , oĂč le premier est un identifiant valide et le second non. Par-dessus tout, j'aime la cohĂ©rence.

Donc, pour des raisons de cohĂ©rence, j'aime la proposition d'avoir des opĂ©rateurs postfixĂ©s lors de l'utilisation de parenthĂšses (A)ᔀ , (a)ÂČ , en combinaison avec la suppression de l'opĂ©rateur unaire Unicode √ (et ses parents) afin que il peut Ă©galement ĂȘtre utilisĂ© dans les identificateurs (tout en restant accessible en tant qu'appel de fonction normal √(a) ).

Je suis d'accord Ă  100% avec ce que @Jutho a dit et j'y ai pensĂ© Ă  plusieurs reprises. Cela vous dĂ©rangerait-il d'ouvrir un problĂšme, @Jutho ? Proposition : autoriser √ dans les noms d'identifiant, exiger √(x) pour appeler en tant qu'op.

question suivante -> qu'en est-il de 2 |> √ ?

Discutons de √ dans un autre fil, mais en bref 2 |> √ signifie √(2) .

Une autre alternative, qui ne nécessiterait aucun changement d'analyseur et serait facile à taper, serait A^T pour la transposition (en définissant T comme étant un type singleton avec une méthode ^ ). 
 oh, je vois que @mbauman a eu cette idée aussi. C'est un peu moche, mais pas plus que A.' .

Je n'ai pas d'expertise, mais je suis trÚs investi dans le résultat de cette discussion car qui tapera probablement des milliers de lignes contenant des expressions matricielles au cours de mon travail.

transpose(A) # with no special syntax remporte le vote ci-dessus, mais me fait mal aux yeux et aux doigts.

En python, l'utilisation courante est probablement avec numpy et beaucoup de choses qui ressemblent Ă  ce qui suit et qui ne sont pas si mal :

import numpy as np
# define matrix X of n columns, with m rows of observations
error = X.dot(Theta.T) - Y
gradient = (1 / m) * (X.dot(Theta.T) - Y).T.dot(X)

Je ne voudrais pas avoir Ă  faire :

grad = 1/m * transpose(X * transpose(Theta) - Y)) * X

Cela change totalement la conception mentale de la transposition par rapport Ă  la convention sur laquelle la notation mathĂ©matique s'est Ă©tablie, qui est un signifiant postfixĂ©, gĂ©nĂ©ralement Aᔀ ou Aá”— .

Personnellement, je suis trÚs content de A' qui fonctionne dans Julia v.0.6, avant qu'il ne soit pris par adjoint. L'adjoint est-il trÚs souvent utilisé ?

Voici mes commentaires dans un tableau :

Aᔀ or Aá”—    if the world won't accept unicode operators, let them use transpose(A)
A'          close to math notation, easy to type and *especially* easy to read
A^'         this could signal `^` not to be parsed as Exponentiation.
A.'         conflicts with dotted operator syntax, but at face value OK
A^T or A^t  these are pretty good, but what if variable `T` is meant to be an exponent? 
A.T         same as numpy, same dotted operator collision
t(A)        nesting reverses semantics, 3 keystrokes and two of them with shift key.
transpose(A) with no special syntax     # please don't do this.

Personnellement, je suis trÚs content de A' qui fonctionne dans Julia v.0.6, avant qu'il ne soit pris par adjoint. L'adjoint est-il trÚs souvent utilisé ?

Je ne comprends pas, A' a toujours été l'adjoint de A . Nous avions l'habitude d'appeler la fonction sous-jacente ctranspose pour la transposition conjuguée, mais nous l'avons renommée en terme équivalent adjoint sans changement de fonctionnalité.

Si vous faites de l'algĂšbre linĂ©aire, vous ĂȘtes beaucoup plus susceptible de vouloir une transposition conjuguĂ©e de toute façon, donc vous taperez A' plutĂŽt que transpose(A) . La popularitĂ© de ne pas dĂ©finir de syntaxe spĂ©ciale pour les transpositions non conjuguĂ©es est (vraisemblablement) due en partie au fait qu'il n'est vraiment pas si courant pour la plupart des utilisations algĂ©briques linĂ©aires de vouloir la transposition non conjuguĂ©e.

Si vous faites de l'algÚbre linéaire, alors ...

Si votre outil est un marteau alors ... :)

... vous devez penser à la possibilité que Julia puisse évoluer vers un langage de programmation général.

Peut-ĂȘtre pas, peut-ĂȘtre que cela restera comme un argot d'algĂšbre linĂ©aire - ce qui est une possibilitĂ© Ă  laquelle doivent penser les programmeurs comme moi. :)

@mahiki , vous ĂȘtes un exemple NumPy :

import numpy as np
# define matrix X of n columns, with m rows of observations
error = X.dot(Theta.T) - Y
gradient = (1 / m) * (X.dot(Theta.T) - Y).T.dot(X)

s'écrirait littéralement en Julia comme suit :

error = X*Θ' - Y
gradient = (1/m) * (X*Θ' - Y)' * X

ou en supposant que les vecteurs sont des lignes dans cet exemple NumPy et seraient des colonnes dans Julia :

error = X'Θ - Y
gradient = (1/m) * (X'Θ - Y) * X'

qui semble Ă  peu prĂšs aussi clair et mathĂ©matique que possible. Si vos donnĂ©es sont rĂ©elles, alors l'adjoint et la transposition sont la mĂȘme opĂ©ration, ce qui explique peut-ĂȘtre pourquoi vous utilisez la transposition ci-dessus - mais mathĂ©matiquement l'adjoint est la bonne opĂ©ration. Comme @ararslan l' a dit, X' a toujours signifiĂ© adjoint dans Julia (et dans Matlab Ă©galement). Il s'appelait auparavant ctranspose abrĂ©viation de « transposition conjuguĂ©e » mais ce nom Ă©tait un abus de langage puisque la propriĂ©tĂ© dĂ©terminante de l'opĂ©rateur est que

dot(A*x, y) == dot(x, A'y)

qui est la propriété déterminante de l' adjoint hermitien mais qui est satisfaite par la transposée conjuguée lorsque A est une matrice complexe. C'est pourquoi "adjoint" est le bon terme générique pour cet opérateur.

Cela dit, j'ai votĂ© ci-dessus pour transpose(a) et a.' car je pense que ce serait bien pour a.' de signifier une transposition structurelle. Cela fonctionnerait comme prĂ©vu, et mĂȘme s'il ne serait pas rĂ©cursif et donc pas "mathĂ©matiquement correct" dans certains codes gĂ©nĂ©riques, le faire fonctionner comme prĂ©vu semble assez bon. Et dire aux gens d'envisager d'utiliser conj(a') dans du code gĂ©nĂ©rique semble ĂȘtre une chose Ă©ducative plutĂŽt que quelque chose dont nous avons vraiment besoin pour frapper les gens par-dessus la tĂȘte.

@mahiki Si, pour une raison quelconque, vous avez vraiment besoin d'utiliser transpose au lieu de adjoint plusieurs fois dans votre code, vous pouvez définir une macro plus courte comme @t qui alias transpose (bien que je sache que cette solution n'est pas idéale, surtout si vous écrivez votre code avec d'autres personnes).

vous devez penser à la possibilité que Julia puisse évoluer vers un langage de programmation général.

@ Liso77 C'est dĂ©jĂ  le cas. À titre d'exemple parmi tant d'autres, Nanosoldier exĂ©cute un serveur Web qui Ă©coute les Ă©vĂ©nements GitHub et exĂ©cute des tests de performance Ă  la demande, le tout dans Julia. C'est une digression cependant, et je ne veux pas que ce fil sorte du sujet.

Si vous transposez une matrice quelconque avec des donnĂ©es non numĂ©riques, ce qui est un cas d'utilisation tout Ă  fait valable, la notation de transposition mathĂ©matique semble en fait ĂȘtre un mauvais jeu de mots. Dans ce cas, je pense qu'il serait prĂ©fĂ©rable d'ĂȘtre plus explicite sur ce que vous demandez, par exemple transpose (ou mĂȘme permutedims , selon vos besoins spĂ©cifiques).

Si vous transposez une matrice quelconque avec des donnĂ©es non numĂ©riques, ce qui est un cas d'utilisation tout Ă  fait valable, la notation de transposition mathĂ©matique semble en fait ĂȘtre un mauvais jeu de mots.

Étant donnĂ© que A.' n'est pas vraiment une "notation de transposition mathĂ©matique" au sens habituel, je ne vois pas si c'est un argument pour ou contre.

Je pense que @ararslan ne s'oppose pas Ă  l'existant .' mais plutĂŽt Ă  l'introduction d'une syntaxe T en exposant. J'ai tendance Ă  ĂȘtre d'accord - si vous voulez dire le concept d'algĂšbre linĂ©aire d'adjoint, alors vous devriez utiliser ' (mĂȘme si votre matrice est rĂ©elle). Et si vous avez une matrice de donnĂ©es non numĂ©riques, alors il est bien sĂ»r parfaitement lĂ©gitime de permuter les deux indices, mais cette opĂ©ration n'est pas vraiment la "transposition" comme on le pense habituellement, et utiliser la notation mathĂ©matique en exposant-T est probablement plus susceptibles de confondre que de clarifier. La seule situation oĂč une notation en exposant-T serait vraiment appropriĂ©e est si vous avez une matrice numĂ©rique dont vous voulez permuter les indices, mais vous ne voulez vraiment pas l'opĂ©rateur linĂ©aire adjoint. De telles situations existent certainement, mais peuvent ĂȘtre trop rares pour justifier l'introduction d'une nouvelle syntaxe.

... mais cette opération n'est pas vraiment la "transposition" comme on a l'habitude de la penser, ...

Si c'est si inhabituel, pourquoi ararslan et bien d'autres votent pour l'orthographe de la transposition structurelle comme transpose(A) ?

Merci @StefanKarpinski @ararslan @ttparker. J'ai dû revenir à mon texte d'algÚbre linéaire et redécouvrir l'adjoint, c'est bien là-dedans. J'ai pris cela avant l'analyse complexe, probablement pourquoi je n'en ai pas tenu compte.

j'adore pouvoir faire ça
gradient = (1/m) * (X'Θ - Y) * X'

Ma confusion provient de l'utilisation gĂ©nĂ©ralisĂ©e de 'transposer' (en exposant T) dans les documents de rĂ©fĂ©rence, les articles, les manuels, etc., par exemple les notes de cours stanford CS229 d'Andrew Ng , oĂč le code Julia correspondant utiliserait adjoint comme dans l'exemple Ă©purĂ© de @StefanKarpinski ci-dessus. C'est parce que l'adjoint et la transposition sont Ă©quivalents en ℝ (n'est-ce pas ?) . mise Ă  jour : oui

Maintenant, ma notation préférée pour la transposition est simplement tout ce qui est logiquement cohérent. Il est clair .' n'est pas à cause d'un conflit avec la syntaxe de l'opérateur pointillé, et je n'ai aucune objection à ce que transpose(A) sans syntaxe spéciale, car aucune syntaxe spéciale sensée ne semble disponible, à l'exception d'un exposant unicode.

J'aime la solution @ttparker si je me retrouve Ă  Ă©crire beaucoup de transposition, macro @t qui alias transpose .

Encore une fois, je me suis trompé en disant :

transpose(A) with no special syntax # please don't do this.

Merci d'avoir pris mes commentaires au sérieux malgré ma faible facilité avec les mathématiques de niveau universitaire.

(Du discours .)

J'aimerais que ' soit un opĂ©rateur post-fixe qui mappe f' Ă  '(f) oĂč Base.:'(x::AbstractMatrix) = adjoint(x) et l'utilisateur est libre d'ajouter d'autres mĂ©thodes qui ont rien Ă  voir avec les adjoints. (Par exemple, certaines personnes pourraient aimer que f' fasse rĂ©fĂ©rence Ă  df/dt.)

Avec les suffixes d'opĂ©rateurs introduits dans la version 0.7, il serait alors naturel que f'ᔃ corresponde Ă  'ᔃ(f) , et ainsi de suite, permettant Ă  l'utilisateur de dĂ©finir ses propres opĂ©rateurs postfixĂ©s. Cela permettrait d'avoir Base.:'ᔀ(x::AbstractMatrix) = transpose(x) et Base.:'⁻Âč(x::Union{AbstractMatrix,Number}) = inv(x) , etc.

Écrire A'ᔀ n'est peut-ĂȘtre pas aussi propre que Aᔀ , mais cela ne nĂ©cessiterait pas de dĂ©prĂ©cier les noms de variables se terminant par ᔀ .

À premiĂšre vue, cela ressemble Ă  une fonctionnalitĂ© incassable. C'est un compromis trĂšs astucieux. Je l'aime bien.

Cela me semble raisonnable. Le plus difficile est de trouver un nom pour la fonction ' — la syntaxe de prĂ©fixe ne fonctionne pas dans ce cas.

Le plus dur est de trouver un nom pour la fonction '

apostrophe ? Peut-ĂȘtre trop littĂ©ral...

Est-il possible de faire fonctionner la syntaxe de préfixe (par exemple, avec une syntaxe (')(A) explicite ?) ? Sinon, c'est un problÚme car cela enfreindrait la rÚgle if-you-can-define-the-symbol-name-then-you-can-override-its-syntax introduite par https://github.com/JuliaLang /julia/pull/26380.

Edit : semble ĂȘtre disponible :

julia> (')(A)


ERROR: syntax: incomplete: invalid character literal

julia> (')(A) = 2


ERROR: syntax: incomplete: invalid character literal

Malheureusement, ' est l'un des caractĂšres les plus difficiles Ă  utiliser comme nom d'identifiant, car il introduit un autre type d'atome (caractĂšres), qui a une prioritĂ© trĂšs Ă©levĂ©e (Ă©gale Ă  la prioritĂ© des identifiants eux-mĂȘmes). Par exemple, (')' est-il une application de ' Ă  lui-mĂȘme, ou une parenthĂšse ouverte suivie d'un littĂ©ral ')' ?

Une option qui n'est pas pratique à court terme consiste à déclarer que les littéraux de caractÚres ne valent pas ' et à utiliser une macro de chaßne comme c"_" la place.

Que diriez-vous si ' est analysé comme un identifiant lorsqu'il est précédé d'un point-deux-points, de sorte que Base.:' fonctionnerait ?

Bien sĂ»r, (@__MODULE__).:'(x) = function_body peut ĂȘtre un peu lourd Ă  Ă©crire, mais (x)' = function_body devrait fonctionner de la mĂȘme maniĂšre. Edit : Non, puisque (x)' devrait correspondre Ă  l'appel de ' dans Base . DĂ©finir une fonction ' dans le module actuel serait fastidieux, mais il n'y aurait aucune raison de le faire non plus.

Ou que diriez-vous de laisser '' analyser comme identifiant ' alors qu'il aurait autrement Ă©tĂ© analysĂ© comme un littĂ©ral de caractĂšre vide (ce qui est actuellement une erreur au niveau de l'analyse). De mĂȘme, ''ᔃ serait analysĂ© comme l'identifiant 'ᔃ , etc.

Tout ce qui n'est pas actuellement une erreur de syntaxe serait toujours analysé comme avant (par exemple 2'' est le suffixe ' appliqué deux fois à 2 ), mais 2*'' le serait maintenant analyser comme deux fois ' .

Il semble déroutant que nous ayons a'' === a mais ''(a) === a' . Il semble préférable d'utiliser Base.apostrophe comme nom à la place (ou quelque chose comme ça).

Serait-il préférable de diviser cette discussion en un nouveau problÚme Github, puisqu'il s'agit d'une syntaxe ' qui n'est pas directement liée à la transposition de la matrice ?

Existe-t-il un moyen automatisé de diviser les problÚmes, ou dois-je simplement en ouvrir un nouveau et créer un lien vers la discussion ici ?

Le dernier

La seule situation oĂč une notation en exposant-T serait vraiment appropriĂ©e est si vous avez une matrice numĂ©rique dont vous voulez permuter les indices, mais vous ne voulez vraiment pas l'opĂ©rateur linĂ©aire adjoint. De telles situations existent certainement, mais peuvent ĂȘtre trop rares pour justifier l'introduction d'une nouvelle syntaxe.

Je suppose que je suis beaucoup trop tard pour la discussion, mais j'aimerais souligner une utilisation qui, Ă  mon avis, mĂ©rite d'ĂȘtre mentionnĂ©e : appliquer la diffĂ©renciation en Ă©tapes complexes Ă  une fonction Ă  valeur rĂ©elle qui a transpose Ă  l'intĂ©rieur de ce. (J'ai personnellement compris que j'avais besoin .' dans MATLAB et Julia pour cette raison particuliĂšre.)

Je vais donner un exemple avec plusieurs occurrences de transpose (peut-ĂȘtre que je pourrais Ă©viter de le faire de cette façon ?)

using LinearAlgebra

# f : Rⁿ → R
#     x  ↩ f(x) = xᔀ * x / 2
f(x) = 0.5 * transpose(x) * x

# Fréchet derivative of f
# Df : Rⁿ → L(Rⁿ, R)
#      x  ↩ Df(x) : Rⁿ → R (linear, so expressed via multiplication)
#                   h  ↩ Df(x)(h) = Df(x) * h
Df(x) = transpose(x) 

# Complex-step method version of Df
function CSDf(x) 
    out = zeros(eltype(x), 1, length(x))
        for i = 1:length(x)
        x2 = copy(x) .+ 0im
        h = x[i] * 1e-50
        x2[i] += im * h
        out[i] = imag(f(x2)) / h
    end
    return out
end

# 2nd Fréchet derivative
# D2f : Rⁿ → L(Rⁿ ⊗ Rⁿ, R)
#       x  ↩ D2f(x) : Rⁿ ⊗ Rⁿ → R (linear, so expressed via multiplication)
#                     h₁ ⊗ h₂ ↩ D2f(x)(h₁ ⊗ h₂) = h₁ᔀ * D2f(x) * h₂
D2f(x) = Matrix{eltype(x)}(I, length(x), length(x))

# Complex-step method version of D2f
function CSD2f(x)
    out = zeros(eltype(x), length(x), length(x))
    for i = 1:length(x)
        x2 = copy(x) .+ 0im
        h = x[i] * 1e-50
        x2[i] += im * h
        out[i, :] .= transpose(imag(Df(x2)) / h)
    end
    return out
end 

# Test on random vector x of size n
n = 5
x = rand(n)
Df(x) ≈ CSDf(x)
D2f(x) ≈ CSD2f(x)

# test that the 1st derivative is correct Fréchet derivative
xÏ” = √eps(norm(x))
for i = 1:10
    h = xÏ” * randn(n) # random small y
    println(norm(f(x + h) - f(x) - Df(x) * h) / norm(h)) # Fréchet check
end

# test that the 2nd derivative is correct 2nd Fréchet derivative
for i = 1:10
    h₁ = randn(n) # random h₁
    h₂ = xÏ” * randn(n) # random small h₂
    println(norm(Df(x + h₂) * h₁ - Df(x) * h₁ - transpose(h₁) * D2f(x) * h₂) / norm(h₂)) # FrĂ©chet check
end
# Because f is quadratic, we can even check that f is equal to its Taylor expansion
h = rand(n)
f(x + h) ≈ f(x) + Df(x) * h + 0.5 * transpose(h) * D2f(x) * h

Le point Ă©tant que f et Df doivent ĂȘtre dĂ©finis en utilisant transpose et ne doivent pas utiliser l'adjoint.

Je ne pense pas que la mĂ©thode des Ă©tapes complexes soit super pertinente dans julia. N'est-ce pas un hack / une solution de contournement pour obtenir une diffĂ©renciation automatique dans les cas oĂč un langage prend en charge des nombres complexes intĂ©grĂ©s efficaces, mais un type de nombre Dual efficace de maniĂšre Ă©quivalente ne peut pas ĂȘtre dĂ©fini? Ce n'est pas le cas dans julia, qui a de trĂšs belles bibliothĂšques de diffĂ©renciation automatique.

Je suis d'accord sur l'utilisation de numéros doubles au lieu de la méthode des étapes complexes et c'est un trÚs bon point que vous soulevez (personnellement, j'ai déjà remplacé toutes mes évaluations de la méthode des étapes complexes par des évaluations à deux numéros dans Julia). Cependant, je pense qu'il s'agit toujours d'un cas d'utilisation valable, à des fins de démonstration, d'enseignement d'astuces (voir, par exemple, Nick Higham parlant de la méthode des étapes complexes à Julia Con 2018 ) et de portabilité (en d'autres termes, je crains que La version MATLAB du code ci-dessus utilisant des nombres complexes serait plus propre).

Venant du monde des ingĂ©nieurs et peut-ĂȘtre des physiciens qui utilisent des tableaux complexes plus que de vrais tableaux, ne pas avoir d'opĂ©rateur de transposition est un peu pĂ©nible. (La reprĂ©sentation de phaseur complexe pour une dĂ©pendance temporelle harmonique est omniprĂ©sente dans notre domaine.) Personnellement, je prĂ©fĂ©rerais la syntaxe numpy de xH et xT, bien que ma seule considĂ©ration soit la concision.

La densité de l'opérateur de transposition par rapport à la transposition hermitienne est d'environ 1 à 1 dans mon code. Donc la transposition non conjuguée est tout aussi importante pour moi. Une grande partie de l'utilisation de la transposition consiste à créer des produits externes et à dimensionner correctement les tableaux pour l'interfaçage avec un autre code ou pour la multiplication matricielle.

J'ai l'intention pour l'instant de simplement fournir une macro ou une fonction de caractÚre pour l'opération, mais quel est l'équivalent correct de l'ancienne fonctionnalité, transpose() ou permutedims() ?

transpose est destiné à l'algÚbre linéaire et est récursif, et permutedims est destiné à l'arrangement non récursif de données de tout type.

Il est intĂ©ressant que vous disiez que vous utilisez autant la transposition que l'adjoint. J'avais l'habitude d'ĂȘtre le mĂȘme, mais surtout parce que j'avais tendance Ă  faire des erreurs lĂ  oĂč mes donnĂ©es Ă©taient rĂ©elles, donc j'avais tendance Ă  transposer mais en fait l'adjoint Ă©tait l'opĂ©ration correcte (gĂ©nĂ©ralisĂ© au cas complexe - l'adjoint Ă©tait la bonne opĂ©ration pour mon algorithme). Il y a (de nombreuses) exceptions valables, bien sĂ»r.

Dans tout ce qui concerne l'Ă©lectrodynamique, vous utilisez souvent des vecteurs de type spatial et souhaitez utiliser des opĂ©rations vectorielles dans R^n (gĂ©nĂ©ralement n=3), c'est-Ă -dire transpose en particulier, mĂȘme si vos vecteurs sont Ă  valeurs complexes parce que vous 'ai pris une transformĂ©e de Fourier. Il semble que @mattcbro parle de ce genre d'applications.

Cela Ă©tant dit, lorsque je lis des discussions sur la syntaxe, je pense souvent que pour moi, personnellement, je ne peux pas imaginer qu'une syntaxe lĂ©gĂšrement plus dĂ©taillĂ©e soit ce qui ralentit ma vitesse ou mon efficacitĂ© de programmation. Penser Ă  l'algorithme lui-mĂȘme et Ă  la maniĂšre la plus naturelle/efficace de l'implĂ©menter prend beaucoup plus de temps.

Dans tout ce qui concerne l'Ă©lectrodynamique, vous utilisez souvent des vecteurs de type spatial et souhaitez utiliser des opĂ©rations vectorielles dans R^n (typiquement n = 3), c'est-Ă -dire transposer en particulier, mĂȘme si vos vecteurs sont Ă  valeurs complexes car vous avez pris un Fourier transformer.

Pas nĂ©cessairement. Souvent, vous voulez des quantitĂ©s moyennes dans le temps Ă  partir des amplitudes de Fourier, auquel cas vous utilisez le produit scalaire complexe, par exemple œℜ[𝐄*×𝐇] est le flux de Poynting moyen dans le temps des composantes de Fourier complexes et ŒΔ₀|𝐄|ÂČ est un densitĂ© d'Ă©nergie du vide moyenne dans le temps. D'autre part, puisque l'opĂ©rateur de Maxwell est (typiquement) un opĂ©rateur Ă  symĂ©trie complexe ("rĂ©ciproque"), vous utilisez souvent un "produit intĂ©rieur" non conjuguĂ© pour l'algĂšbre (de dimension infinie) sur les champs 𝐄(đ±) etc. sur tout l'espace.

C'est vrai, j'avais souvent le mot dans la premiÚre phrase, mais je l'ai apparemment supprimé :-).

Eh bien, si vous voulez y aller, les quantités électromagnétiques sont écrites de maniÚre encore plus concise dans une formulation algébrique de Clifford, souvent appelée algÚbre géométrique. Ces algÚbres ont de multiples automorphismes et antiautomorphismes qui jouent un rÎle critique dans la formulation de la théorie, en particulier lorsque l'on considÚre des problÚmes de diffusion.

Ces algÚbres ont généralement une représentation matricielle concise et ces morphismes sont souvent facilement calculés via une transposition complexe, une transposition hermitienne et une conjugaison.

NĂ©anmoins, comme je l'ai dit plus tĂŽt, mon utilisation principale de la transposition est souvent d'organiser mes tableaux pour qu'ils s'interfacent avec d'autres tableaux, d'autres codes et pour que la multiplication matricielle fonctionne par rapport Ă  la dimension correcte d'un tableau aplati.

Personnellement, je préférerais la syntaxe numpy de xH et xT

Facile Ă  implĂ©menter maintenant en 1.0, et devrait ĂȘtre efficace :

function Base.getproperty(x::AbstractMatrix, name::Symbol)
    if name === :T
        return transpose(x) 
    #elseif name === :H # can also do this, though not sure why we'd want to overload with `'`
    #    return adjoint(x)
    else
        return getfield(x, name)
    end
end 

C'est Ă©tonnamment facile et plutĂŽt soignĂ©. L'inconvĂ©nient semble ĂȘtre que les utilisations orthogonales de getproperty ne se composent pas les unes avec les autres. Ainsi, toute personne implĂ©mentant getproperty sur son type de matrice spĂ©cifique devra implĂ©menter le comportement gĂ©nĂ©rique Ă  la main.

les utilisations orthogonales de getproperty ne composent pas

Hmm. Je me demande si cela implique que xT "devrait" avoir été abaissé à getproperty(x, Val(:T)) . Je frémis de penser à ce que cela ferait au pauvre compilateur.

Je suis sûr que tout le monde a son opinion - mais pour moi, c'est presque une fonctionnalité qu'il est difficile de créer une interface générique à partir de la syntaxe à points. Ne vous méprenez pas, c'est une fonctionnalité vraiment géniale et merveilleuse pour définir des structures nommées de type tuple, etc.

(Il est également possible d'ajouter assez facilement une couche de répartition Val à vos types).

Le code de @c42f fonctionne comme un charme. Malheureusement pour moi, j'essaie d'Ă©crire du code qui fonctionne sur les versions 0.64 et supĂ©rieures, ce qui m'oblige Ă  utiliser soit la transposition, soit ma propre fonction dĂ©finie T(A) = transpose(A). Peut-ĂȘtre qu'une macro aurait Ă©tĂ© un peu plus propre et lĂ©gĂšrement plus efficace.

Pour ĂȘtre clair, je ne suggĂšre pas que dĂ©finir ce getproperty particulier soit une bonne idĂ©e pour le code utilisateur. C'est juste susceptible de casser les choses Ă  plus long terme ;-) Bien qu'un jour nous aurons peut-ĂȘtre une bonne idĂ©e des consĂ©quences que nous pourrions avoir x.T dĂ©fini dans Base .

Mais d'une maniĂšre gĂ©nĂ©rale, je me demande pourquoi ce type d'utilisation de propriĂ©tĂ© pour dĂ©finir des "getters" dans des interfaces gĂ©nĂ©riques est en fait mauvais. Par exemple, les fonctions getter de champs gĂ©nĂ©riques ont actuellement un Ă©norme problĂšme d'espace de noms qui est simplement rĂ©solu par une utilisation judicieuse de getproperty . Il est bien plus agrĂ©able d'Ă©crire x.A que d'Ă©crire MyModule.A(x) , un nom de fonction plus long comme get_my_A(x) , ou d'exporter le nom extrĂȘmement gĂ©nĂ©rique A d'un utilisateur module. Le seul problĂšme tel que je le vois, est la possibilitĂ© attendue de remplacer la signification de .B pour les sous-types indĂ©pendamment du fait que .A soit dĂ©fini de maniĂšre gĂ©nĂ©rique sur un super type. D'oĂč le commentaire Ă  moitiĂ© sĂ©rieux sur Val .

Idée amusante :

julia> x'̄
ERROR: syntax: invalid character "̄"

Le caractÚre ressemble un peu à un T mais c'est en fait un ' avec une barre dessus. Pas sûr que ce soit sérieux...

screen shot 2018-09-10 at 11 29 56

Ouais, ça me ressemble aussi sur GitHub. Mais c'est un overbar. Copiez et collez dans mon terminal montre:

screen shot 2018-09-10 at 10 31 24 am

Trop malin et mignon. J'aime toujours les caractĂšres combinĂ©s, cependant, et je pense que 'ᔀ est bien.

-100 pour changer d'adjoint, car c'est l'une des choses géniales qui rend l'écriture de code Julia aussi claire que l'écriture de mathématiques, et la transposition conjuguée est généralement ce que vous voulez de toute façon, il est donc logique d'avoir une syntaxe abrégée pour cela.

Il y a une certaine arrogance dans une déclaration comme celle-ci. Considérez qu'une proportion finie de développeurs explicitement _ne veulent pas_ adjoint() mais _ont besoin_ transpose() .

Cas et point pour nous de travailler avec des calculs symboliques pour modĂ©liser l'opĂ©rateur ' par dĂ©faut entraĂźnerait par exemple le pseudo-inverse (A'*A)\(A *b) ou une forme quadratique v'*A*v pour revenir par erreur des rĂ©sultats longs et complexes qui ne peuvent ĂȘtre rĂ©duits.

Peut-ĂȘtre que la solution est une sorte de directive du compilateur dĂ©clarant la signification de ' .

Cette page vous a été utile?
0 / 5 - 0 notes