Julia: Estado dos produtos internos na Base

Criado em 15 jan. 2018  ·  146Comentários  ·  Fonte: JuliaLang/julia

Se um usuário precisar definir produtos internos personalizados para espaços gerais de Hilbert, qual é o estado atual em Base para esse tipo de generalização? https://github.com/JuliaLang/julia/issues/16573 é um problema relacionado, mas menos geral. Minha preocupação é com novos tipos que não são arrays.

Eu gostaria de propor renomear dot para inner , ou talvez direcionar os usuários para definir inner(x,y) como um produto interno geral entre objetos x e y , incluindo o caso do array:

inner(x::AbstractVector, y::AbstractVector) = dot(x, y)

Caso a mudança seja razoável, poderia fazer parte do Julia v1.0?

linear algebra

Comentários muito úteis

Isso deve ser fechado, já que o #27401 está mesclado agora?

Todos 146 comentários

Você poderia explicar um pouco mais sobre seu caso de uso e por que tê-lo em Base em vez de apenas defini-lo em seu pacote é benéfico? Um exemplo concreto seria melhor. Você espera várias definições inner em pacotes carregados simultaneamente?

Acho que ter uma interface formal para esses espaços matemáticos ajudará os usuários a explorar melhor o sistema de tipos. Por exemplo, eu esperaria que os métodos de agrupamento funcionassem em qualquer espaço métrico. Se eu pudesse definir meu tipo com um produto interno, eu me beneficiaria de Clustering.jl pronto para uso (após o pacote ser corrigido de acordo). Muitos outros algoritmos baseados em distância ou baseados em projeção também podem ser generalizados.

Como exemplo concreto, me deparei com essa limitação hoje tentando definir uma geometria para dados de composição: https://github.com/juliohm/CoDa.jl Prefiro me especializar em uma função inner bem conhecida definido em Base do que definir minha própria interface que ninguém mais saberá.

Por que não estender dot para seus tipos de espaço Hilbert? Tenho certeza de que foi projetado para ser o produto interno genérico em mente.

O conceito de produto escalar é mais estrito do que o conceito de produto interno. Enquanto este último é definido para espaços gerais, um produto escalar só é definido quando existe a noção de um sistema de coordenadas definido por uma base finita. A semântica de dot(x,y) é x'*y onde x e y representam as coordenadas dos objetos em um mundo cartesiano. Os livros didáticos de matemática raramente mencionam o termo produto escalar, pois os autores geralmente estão interessados ​​em tratar o material em espaços mais gerais (não necessariamente finitos nem euclidianos).

Para distinguir ainda mais, em um espaço de Hilbert com produto interno <x,y> (ou inner(x,y) ) os objetos podem ser infinitos e a semântica x'*y não se aplica. Por exemplo, na análise de dados funcionais os objetos são as funções f e g e o produto interno geralmente é obtido por integração numérica: inner(f,g) = quadrature(f*g) . Chamar essa operação de produto escalar é enganoso.

Outro exemplo, como apontei no meu pacote CoDa.jl , são os dados de composição. Objetos de composição estão em um mundo simplex para o qual a operação x'*y não faz sentido. No entanto, existe uma transformação isométrica (a transformação de razão logarítmica) que pode ser usada para mapear composições em outra geometria, onde pode-se aplicar o produto escalar com coordenadas. Trabalhar com coordenadas não é necessário, mas é uma prática comum neste campo. O resultado pode ser transformado novamente no espaço original onde os objetos existem.

Não vejo vantagem em manter o termo dot na linguagem, mas se alguém pedir compatibilidade com versões anteriores, a generalização inner(x::AbstractVector, y::AbstractVector) = dot(x,y) funciona perfeitamente.

Você pode detalhar as objeções para essa mudança?

Você pode detalhar as objeções para essa mudança?

Geralmente exigimos uma quantidade razoável de justificativa para adicionar novas funções públicas à Base, essa é a objeção. Isso pode ser fornecido por um pacote InnerProducts . Por que ele precisa ser construído na própria linguagem? Esta foi a primeira pergunta que @andreasnoack fez acima – obteve uma resposta um tanto vaga de "Acho que ter uma interface formal para esses espaços matemáticos ajudará os usuários a explorar melhor o sistema de tipos". Não há razão para que uma interface definida em um pacote seja menos formal do que uma em Base. O que ter Base.inner oferece que InnerProducts.inner não oferece? Esta é uma pergunta genuína que poderia ter uma resposta convincente, mas não sei qual seria essa resposta, e é por isso que a pergunta está sendo feita.

Não vejo um bom argumento para definir um conceito matemático básico como produtos internos em outros lugares que não estejam em Base. Uma linguagem cujo principal público é o pessoal da computação científica se beneficiaria de uma terminologia correta. Por que o conceito de norm está definido em Base.LinAlg e inner , que está na mesma coorte, deve ser definido em um pacote? Além dessa inconsistência, a linguagem já possui dot , o que me faz pensar por que deveria ter algo tão específico ao invés de um conceito mais geral?

Então você quer todos os conceitos matemáticos possíveis na linguagem base? Não ter algo definido na Base não força as pessoas a usarem a terminologia errada. A função norm é exportada de LinAlg porque é definida e usada em LinAlg . Semelhante para dot . Você está propondo que dot seja renomeado para inner ?

Então você quer todos os conceitos matemáticos possíveis na linguagem base?

Eu nunca disse isso.

Não ter algo definido na Base não força as pessoas a usarem a terminologia errada.

Tenho certeza que não. Promover a terminologia errada é o problema. Pessoas com formação menos matemática adotarão o uso do ponto porque o veem no Base. O uso do termo produto "ponto" para representar o conceito de produto interno está incorreto. Também é prejudicial para a comunidade matemática, que luta de vez em quando para consertar essas cicatrizes que a terminologia errada deixou. Os alunos da minha geração estão constantemente tendo que consultar livros antigos para acertar a terminologia, isso não deveria ser o caso.

Você está propondo que o ponto deve ser renomeado para interior

Isso já seria uma grande melhoria na minha opinião. Veja todos os exemplos que dei acima sobre dados funcionais e de composição. As pessoas nessas comunidades nunca usariam o termo dot em seu trabalho. "ponto" é mais um termo de ciência da computação do que qualquer outra coisa.

Renomear dot para inner é uma proposta bem diferente de adicionar inner à Base além de dot . Essa é mais uma questão de "terminologia correta", que você e outros linalgs terão que responder, embora eu me lembre de que fizemos isso uma vez e concluímos que dot era o nome correto para o que essa função implementa.

Renomear dot para inner é uma proposta bem diferente do que adicionar inner à Base além do dot.

Isto é o que eu propus na minha primeira mensagem neste tópico:

Eu gostaria de propor renomear dot para inner, ou talvez direcionar os usuários para definir inner(x,y) como um produto interno geral entre os objetos x e y

Repito, produto escalar é o termo incorreto para a operação que estou discutindo aqui. Produto interno, externo, escalar... esses são objetos matemáticos. "produto escalar" é um objeto computacional: obtém duas sequências de números e executa x1*y1 + x2*y2 + ... xn*yn , uma operação inútil em outros espaços matemáticos.

Eu tinha focado na segunda opção que você propôs, que parece ter adicionado Base.inner com um fallback para chamar Base.dot . Qualquer uma das opções é possível, mas ambas requerem alguma justificativa: para adicionar uma nova operação, é preciso uma razão pela qual ela não pode estar apenas em um pacote (sobre o que foi a parte inicial desta discussão); para renomear, é preciso decidir que dot é o nome errado e inner é o correto (para o que a conversa parece ter se voltado).

@juliohm Provavelmente vale a pena (re)afirmar que há um esforço ativo atualmente tentando encolher Base e incentivar o uso de pacotes. Neste caso dot parece estar correto para todos os tipos que participam da álgebra linear fornecida em Julia padrão (ou seja Number e Array - então sim, existe um definido, conhecido , base finita em todos os casos - portanto, não acho que cometemos um erro de terminologia, embora possa haver escolhas melhores). Não sou contra esta proposta - mas queria apontar isso para esclarecer por que você pode estar enfrentando alguma resistência "latente" à mudança.

Também vale a pena ter em mente que um bom número de recém-chegados Julia pode estar familiarizado com um produto escalar, mas não com um produto interno (digamos, eles fizeram um pouco de física na universidade, mas não são especialistas em matemática), então também há algumas razões para mantenha dot (sem mencionar que temos um operador infixo com o qual ele corresponde - poderíamos apenas mapeá-lo para inner , suponho, mas isso é um pouco menos óbvio). Também não temos uma função outer , ou uma variedade de outras operações possíveis.

Assim, há um fardo para fazer um caso razoável de como colocar isso em Base (ou LinAlg ) é estritamente melhor do que colocar isso em um pacote de usuário. A principal razão parece ser fornecer uma interface que pode ser compartilhada e estendida por outros - isso é um resumo razoável? O argumento sobre permitir que o código genérico do Clustering.jl funcione com seu produto interno parece bastante convincente. Além disso, no contexto em que parecemos estar dividindo LinAlg em um pacote stdlib - eu estava pensando que se eu fosse criar um pacote chamado LinearAlgebra eu provavelmente ficaria feliz em incluir um inner Função

Obrigado @andyferris por compartilhar seus pensamentos. Eu vejo a resistência muito claramente, o que é algo que não me deixa muito animado. No entanto, estou curioso sobre como essa proposta específica leva ao aumento de código? Para mim, parece uma mudança trivial no código com grande melhoria na abstração. O exemplo com Clustering.jl é apenas um de muitos, pense em qualquer método baseado em kernel que possa ser feito para funcionar com tipos arbitrários de Julia para os quais existe a noção de produto interno. MultivariateStats.jl tem muitos deles.

Em relação ao comentário sobre LinAlg dividido em um pacote separado, concordo que parece um bom lugar para encapsular produtos matemáticos. Estou assumindo que este pacote LinearAlgebra do futuro seria importado em uma sessão Julia por padrão e assim todos os usuários teriam acesso ao conceito de inner , outer , etc agora mesmo.

Sim, as bibliotecas padrão são todas construídas junto com a imagem do sistema Julia e estão disponíveis por padrão. Pelo menos para a série v1.x ninguém precisará digitar using LinAlg (acho que não será renomeado LinearAlgbebra , aliás, acabei de inventar isso como um concorrente hipotético) .

Para esclarecer, ele seria carregado com o padrão Julia para que você não precisasse instalar nada, mas ainda teria que escrever using LinAlg para obter os nomes que exporta.

É aqui que fica estranho, certo, já que obteremos os métodos * e assim por diante sem using LinAlg ? (em outros termos, LinAlg é um tipo pirata).

Sim, é basicamente onde teremos que traçar a linha: Base deve definir o máximo de funcionalidade de álgebra linear necessária para tornar LinAlg não um pirata, então matmul é definido em Base porque Array e * ambos são. Tipos de matriz funky e operações não-base vivem lá.

Deixe-me dar um exemplo concreto e perguntar como você resolveria isso com a interface atual, talvez isso possa esclarecer as coisas para mim.

O objetivo é realizar a análise fatorial com dados composicionais. Tenho um tipo chamado Composition e um produto interno no espaço de composições. Eu coleto muitas amostras (por exemplo, amostras de rochas) e coloco todas elas em um grande Vector{Composition} (por exemplo, composição = %água, %grão, %ar). Agora eu quero chamar um algoritmo de análise fatorial implementado em outro pacote (por exemplo, MultivariateStats.jl) neste vetor de dados. Como você implementaria isso genericamente sem ter um produto inner importado por padrão?

O que eu entendi dos últimos comentários é que tanto MultivariateStats.jl quanto CoDa.jl teriam que depender de LinAlg.jl. A dependência em MultivariateStats.jl é apenas para trazer o nome inner para o escopo. A dependência em CoDa.jl é definir um método para inner que pode ser chamado por MultivariateStats.jl. É isso que você está sugerindo?

Parece que Composition{D} é um espaço vetorial dimensional D sob + e * .

Eu ficaria bastante tentado a definir o espaço vetorial dual.

Assim, você pode definir adjoint(::Composition) -> DualComposition e *(::DualComposition, ::Composition) -> scalar (atualmente inner ). DualComposition não teria que fazer muito, exceto segurar um Composition dentro.

A primeira frase em https://en.wikipedia.org/wiki/Dot_product parece sugerir que dot poderia ser uma operação em quaisquer dois iteráveis. Poderíamos torná-lo recursivo e defini-lo para Number , e definir inner como a função abstrata de álgebra linear, que por acaso se sobrepõe para Number e AbstractArray .

Obrigado @andyferris , agradeço seus pensamentos sobre o espaço duplo. Eu prefiro não confiar em um novo tipo para essa tarefa. A solução final é desnecessariamente complexa.

O que estou interessado em entender é por que algo como:

inner(x,y) = sum(x.*y)
norm(x) = sqrt(inner(x,x))

export inner, norm

não é bem-vindo na Base? Estou assumindo que isso é tudo o que é necessário para definir os nomes das funções genericamente para os usuários da linguagem se especializarem. Tenha em mente que estou fazendo essas perguntas com o interesse genuíno de entender o ponto de vista dos desenvolvedores principais. Eu quero dizer isso antes que a conversa vá na direção errada novamente.

Do ponto de vista de alguém interessado em matemática em geral, não parece natural ter esses conceitos não exportados por padrão e, em vez disso, tê-los definidos dentro de LinAlg . Eu penso em LinAlg como implementações desses conceitos de alto nível para tipos de array. Talvez todo o meu trabalho não exija álgebra linear em arrays, mas eu ainda poderia me beneficiar do conceito de produto interno entre pacotes (por exemplo, MultivariateStats.jl, Clustering.jl). Além disso, talvez eu não queira ter LinAlg como uma dependência no meu pacote porque não é.

Se eu puder enfatizar ainda mais, existe o conceito de produto interno, que é independente de matrizes. Este conceito é representado pela instrução export inner em Base. Existe a implementação de produtos internos para objetos do tipo array representando as coordenadas inner(x,y) = sum(x.*y) . Esta operação pode ser definida como um método de fallback no Base como acima, se necessário.

Outro exemplo de caso de uso são os métodos Krylov. Se você tem, por exemplo, espaços de funções com produtos internos, então você pode usar métodos de Krylov para aproximar um problema linear ou autoproblema em um pequeno subespaço de dimensão finita desse espaço de função de dimensão infinita.

Eu também tenho meus próprios objetos que formam um espaço vetorial/Hilbert, mas não fazem parte de <: AbstractArray . Da analogia que também arrays com rank N>1 formam espaços vetoriais e podem ser usados ​​como 'vetores' em métodos Krylov, passei a confiar no uso de vecdot e vecnorm sendo a noção generalizada de produto interno e norma. Então estou desenvolvendo um pacote com métodos Krylov que usa funções como operadores lineares e onde os 'vetores podem ser de qualquer tipo, desde que objetos desse tipo suportem vecdot , vecnorm e alguns outras coisas ( scale! , zero , ...). Mas talvez isso esteja abusando do significado desses conceitos no Base, então seria bom endireitar a interface correta aqui.

Certo - vecdot pode ser renomeado para inner .

(Agora estou vagamente me perguntando se norm deve realmente ser chamado matrixnorm para matrizes com norm sempre correspondendo inner . Parece que talvez existam dois coisas acontecendo com norm que está causando algumas dificuldades em generalizá-lo)

Na verdade, para objetos gerais semelhantes a vetores, também é útil consultar a dimensão do espaço vetorial (por exemplo, para verificar se a dimensão Krylov não deve ser maior que a dimensão do espaço completo no meu caso de uso de exemplo). O exemplo de arrays aninhados mostra que length não é o conceito correto aqui, ou seja, precisaria haver alguma noção recursiva de comprimento para esses casos.

Agora para o exemplo de uso de matrizes aninhadas como um vetor geral, vecdot e vecnorm são em alguns casos nem mesmo a noção correta de produto interno e norma, como discutido em #25093, ou seja, eles são não chamando recursivamente vecdot e vecnorm . Minha interpretação dessas funções como um produto interno genérico e função de norma é o que desencadeou #25093, mas parece que isso pode não ser como essas funções foram planejadas (não tenho certeza do que elas pretendiam fazer).

Portanto, concordo que precisamos de uma interface consistente aqui para ser usada em todos os pacotes, que, portanto, pertençam a um local central (provavelmente não na Base, mas certamente em uma Biblioteca Padrão, por exemplo, de modo que seja necessário fazer using VectorSpaces ). Quanto à nomeação, vejo duas opções:

Opção 1 (minha interpretação até agora):
o prefixo vec indica a propriedade desse objeto ao interpretá-lo como um vetor genérico, portanto

  • vecdot e vecnorm para matrizes aninhadas são fixos (PR #25093)
  • uma nova definição veclength é adicionada

Opção 2 (provavelmente melhor): use nomes matematicamente mais corretos

  • inner
  • dimension
  • Mas o que fazer com norm ?

E, finalmente, apenas pingando @stevengj , pois ele certamente terá alguns comentários úteis; minhas desculpas se isso for inconveniente.

O nome é a parte menos interessante de tudo isso. Eu tenho zero problemas com o uso da função dot para se referir a um produto interno geral para espaços de Hilbert arbitrários. Não apenas não há outro significado razoável para, por exemplo, "produto escalar de duas funções", é bastante comum ver "produto escalar de funções" em uso informal, especialmente em ambientes pedagógicos onde se tenta enfatizar a analogia com vetor de dimensão finita espaços.

@juliohm , inner(x,y) = sum(x.*y) nem é um produto interno em geral, então isso seria um fallback terrível para colocar na base.

Mas dot já não está calculando o produto interno correto (na verdade falhando) para vários objetos em Base que se comportam como vetores, por exemplo, arrays com classificação N>1 ou arrays aninhados (vetores aninhados sendo o único caso onde funciona corretamente). Além disso, o nome genérico norm torna-se ambíguo para matrizes, pois concordo com a escolha atual de que esta retorne a norma induzida, mas ocasionalmente a "norma vetorial" (norma de Frobenius) também é necessária.

Portanto, minha proposta de menor impacto seria deixar de lado a semântica vecnorm(x) = norm(vec(x)) e interpretar vecnorm(x) como "para x ser um objeto de algum tipo genérico que se comporta como um espaço vetorial, calcule a norma vetorial correspondente de x " (e similar com vecdot ). Embora esta seja uma mudança na interpretação (e, portanto, na documentação), a implementação/ação real para objetos em Base não seria muito diferente (PR #25093) e produziria o mesmo resultado para a maioria dos casos (rank N arrays de escalares ou de vetores). Uma função veclength(x) que retorna a dimensão de espaço vetorial correspondente de x completaria a interface.

Os pacotes personalizados devem aprender a implementar essas funções quando definem novos tipos que se comportam como vetores.

é muito comum ver "produto escalar de funções" em uso informal, especialmente em ambientes pedagógicos onde se tenta enfatizar a analogia com espaços vetoriais de dimensão finita

Por favor, não diga que o nome não é importante, porque é. Vou repetir pela enésima vez: produto interno e produto escalar não são a mesma coisa. Qualquer material sério expondo trabalhos com espaços abstratos de Hilbert nunca usará "ponto". Se você preferir confiar na Wikipédia em vez das minhas palavras, aqui estão as definições copiadas e coladas:

Produto Interno

Na álgebra linear, um espaço de produto interno é um espaço vetorial com uma estrutura adicional chamada produto interno. Essa estrutura adicional associa cada par de vetores no espaço a uma quantidade escalar conhecida como produto interno dos vetores.

Produto escalar

Em matemática, o produto escalar ou produto escalar é uma operação algébrica que recebe duas sequências de números de igual comprimento (geralmente vetores coordenados) e retorna um único número.


Essa resistência em melhorar a terminologia e a consistência matemática na linguagem é desmotivadora. Não importa quantos fatos eu apresente a você, não importa o número de exemplos e casos de uso, não há contra-argumento além de "Estou bem com ponto".

@juliohm , a terminologia é uma questão de convenção, não de correção. Concordo que no uso formal para espaços de Hilbert, especialmente os de dimensão infinita, o termo "produto interno" é usado praticamente exclusivamente. Mas, como eu disse, se você pesquisar no Google "funções do produto ponto", também encontrará muitos usos informais dessa terminologia. Se você disser "pegue um produto escalar de dois elementos deste espaço de Hilbert", todo matemático saberá que você está se referindo a um produto interno, mesmo para espaços de dimensão infinita, então não há perigo real de confusão, porque não há outro generalização padrão do termo "produto escalar". É por isso que não considero o debate ortográfico de "ponto" versus "interno" uma questão central.

É importante decidir sobre a semântica que se quer aqui, e o conjunto de funções que os tipos devem implementar se definirem um novo espaço de Hilbert ou espaço de Banach. Atualmente, se você deseja definir um tipo que representa um novo espaço de Hilbert, você deve definir dot e norm (já que atualmente não temos um fallback para o último), e acho que adjoint se você quiser o mapeamento para um objeto de espaço duplo.

Como o @Jutho diz, tudo isso é complicado pelo caso de array-of-arrays, já que existem várias coisas possíveis que se pode querer lá. Como não há nomes padronizados para todas as semânticas possíveis, é difícil encontrar nomes/semânticas que satisfaçam a todos. Veja o #25093 para a discussão da semântica vecdot . Eu não tenho uma boa resposta aqui, eu mesmo.

Algumas possibilidades aqui

  1. Soma de x[i]' * y[i] . Atualmente, isso é dot(x,y) . Não é um produto interno para vetores de matrizes (onde dá uma matriz), e atualmente não está definido tudo para matrizes multidimensionais.
  2. Soma de dot(x[i], y[i]) , inclusive para arrays multidimensionais e conj(x)*y para Number . Atualmente, isso é vecdot(x,y) .
  3. Alguma função, por exemplo inner(x,y) definida para ser sempre um verdadeiro produto interno, e para arrays faça somar inner(x[i],y[i]) — essencialmente o "vecdot recursivo" que @Jutho quer. Mas então, para matrizes A , esse produto interno é inconsistente com a norma induzida norm(A) que é nossa definição atual norm . Para consertá-lo, teríamos que alterar norm(A) para que as matrizes fossem padronizadas para a norma de Frobenius, o que potencialmente seria uma mudança de grande alcance.

Uma questão (discutida parcialmente em #25093) é se precisamos de todos os três na Base, ou se podemos nos safar com dois (e quais dois, e como os chamamos). A proposta do @Jutho , no meu entender, é essencialmente eliminar a opção 2 na Base e depois usar vecdot e vecnorm para a opção 3. Então temos um verdadeiro produto interno, mas a terminologia é bastante exclusivo para Julia, e um pouco estranho para, por exemplo, espaços de Hilbert de dimensão infinita. Isso não seria o fim do mundo, é claro.

Outra possibilidade (independente do que fazemos com vecdot ) seria (voltar) a exigir que dot fosse um verdadeiro produto interno. ou seja, elimine o comportamento 1 e torne dot(x::AbstractVector, y::AbstractVector) igual a sum dot(x[i],y[i]) . Ainda não o defina para arrays multidimensionais (para ficar consistente com norm ).

Minha inclinação pessoal atual seria definir dot como um verdadeiro produto interno (que deve ser consistente com norm ), alterando-o para a soma de dot(x[i],y[i]) para vetores (ou seja, alterando o caso de vetor de matrizes) e continuando a não defini-lo para matrizes multidimensionais. Em seguida, defina vecdot para chamar recursivamente vecdot como @Jutho sugere, com um fallback vecdot(x,y) = dot(x,y) . Finalmente, digamos que os novos tipos "Hilbert-space" devem definir dot e norm . Esta parece ser a mudança menos disruptiva e mais compreensível para mim.

(Um fallback norm(x) = sqrt(real(dot(x,x))) também é uma possibilidade, embora seja um pouco perigoso, pois é vulnerável a estouros espúrios. Observe que não podemos usar sqrt(dot(x,x)) como fallback por motivos técnicos: queremos um Real resultado, não um resultado Complex .)

Obrigado @stevengj por esta reação informativa. Apenas um pequeno comentário:

com um substituto vecdot(x,y) = dot(x,y) . Finalmente, digamos que os novos tipos "Hilbert-space" devem definir dot e norm .

Há dois problemas com isso. vecdot(x,y) = dot(x,y) fallback não pode existir, pois vecdot já aceita argumentos Any para lidar com iteradores gerais. O segundo problema é que, se dot e norm são expostos como o verdadeiro produto interno e norma que qualquer vetor como tipo de usuário deve definir, então mesmo ao escrever um pacote com, por exemplo, métodos Krylov que deve funcionar com vetores completamente genéricos como tipos, ainda não funcionará para o caso em que o usuário deseja usar matrizes aninhadas ou multidimensionais como objetos semelhantes a vetores. Portanto, eu argumentaria que vecdot e vecnorm são o produto interno geral e a norma de objetos semelhantes a vetores. Isso também se encaixa bem com o fato de que, para matrizes, a maioria das pessoas realmente espera que norm seja a norma matriz/operador induzida.

Quanto a um caso de uso real (para mostrar que este não é um caso excepcional). Matrizes estocásticas têm um maior autovalor (Perron-Frobenius) para o qual o autovetor correspondente representa uma distribuição de probabilidade de ponto fixo. Na generalização quântica da mesma, a distribuição de probabilidade se generaliza para uma matriz definida positiva (a matriz densidade) e tal matriz é o ponto fixo (autovetor correspondente ao maior autovalor) de um mapa completamente positivo, ou seja, o mapa rho -> sum(A[i] rho A[i]^\dagger for i = 1:N) onde rho é a matriz de densidade e A[i] é uma matriz para cada i (conhecidos como os operadores de Kraus que representam o mapa completamente positivo). Para grandes dimensões de matriz, um método de Arnoldi é ideal para encontrar a matriz de densidade de ponto fixo.

Minha inclinação pessoal atual seria definir dot como um produto interno verdadeiro (que deve ser consistente com a norma), alterando-o para soma de dot(x[i],y[i]) para vetores. Finalmente, digamos que novos tipos de "espaço de Hilbert" devem definir ponto e norma.

Isso já é uma grande melhoria. Documentar dot para ter a semântica inner no Base permitirá pelo menos que os usuários definam seus próprios espaços sem importar bibliotecas desnecessárias. Não estou feliz com a nomenclatura, mas pelo menos a funcionalidade estaria disponível para quem precisar.

Sim, acho que será bom ter uma interface documentada para implementar para tipos "Hilbert-space".

Claro, pensando nessa interface genérica para espaços vetoriais, se ela inclui norm como sugerido acima, então essa deve ser a norma de Frobenius para matrizes (e generalizar para matrizes de dimensão superior, uma vez que todas as matrizes são elementos de um vetor espaço). Nesse caso, precisaríamos de uma função "norma de operador" separada para matrizes ( matnorm ou opnorm ou algo assim, ou um argumento de palavra-chave em norm ...).

@andyferris , observe meu último comentário. norm e dot não podem se tornar a interface geral do espaço de Hilbert, pois eles nem funcionam em objetos como vetores em Julia, como matrizes de dimensão superior e matrizes aninhadas. Portanto vecdot e vecnorm são candidatos 'melhores' (no sentido de menos quebra) para isso.

Revivendo este tópico, que considero bastante relevante para o tipo de matemática que espero fazer com a língua num futuro próximo. Existe um consenso sobre o que será feito para melhorar a generalidade e a semântica dos produtos internos?

Aqui está a parte da minha ontologia matemática pessoal relativa ao produto.
Se isso pudesse ajudar a escovar a memória / trazer consenso

Bônus: sem referências da wikipedia

Neste ponto, a proposta de @Jutho em #25093 parece ser a mudança menos disruptiva, mesmo que a terminologia vec* seja um pouco estranha para mim neste contexto.

Concordo que a terminologia vec* é estranha. É por isso que renomear as funções para que tenham nomes padrão seria benéfico para todos os usuários.

Também concordo que a terminologia vec* é estranha.

Concordo, como alternativa a vecdot poderíamos introduzir um novo método inner , mas não conheço um bom nome para "substituir" vecnorm . Na verdade, não acho vecnorm tão ruim assim, norma vetorial é um termo bem estabelecido e explícito para a operação que queremos.

O problema básico aqui é com matrizes e arrays multidimensionais, para os quais o usual norm(A) não corresponde a um produto interno, assim como com arrays de arrays como discutido acima. Alguma desambiguação (por exemplo vec* ou fro* ) é necessária nesses casos para indicar qual produto interno é pretendido.

Você pode ter uma função inner cujo padrão é vecdot , mas é um pouco bobo ter dois nomes para a mesma função, e ainda há o problema de como chamar a norma.

Eu também acho estranho o nome vecdot , na verdade, eu nem sabia que existia e tinha feito minha própria função para ele... chamada inner .

Meu entendimento é que podemos apenas depreciar o ímpar vecdot em favor de inner e dar a ele a semântica do produto interno para que os usuários implementem seus próprios espaços.

Quanto ao norm , isso eu não sei. Abri esta edição para discutir produtos internos, talvez outra edição seja apropriada para discutir o estado das normas na Base.

Suponho que poderíamos ter inner(x,y) e innernorm(x) = sqrt(inner(x,x)) (com casos especiais otimizados para evitar estouro) em vez de vecdot e vecnorm . innernorm é um pouco incomum, mas é razoavelmente claro no contexto.

Polegares para cima para esta mudança. Os nomes inner e innernorm são claros e consistentes com os conceitos. Eu gostaria que eles pudessem chegar a Julia v1.0.

inner e innernorm parecem-me bem.

Eu ainda diria que, na minha opinião, nossa função norm não se encaixa muito bem na função genérica de Julia e no sistema de despacho e o que eu chamaria de "interfaces claras" onde o despacho não deveria estar fazendo escolhas semânticas, apenas escolhas de implementação. Eu pessoalmente preferiria que pudéssemos dizer " norm retorna a norma de um elemento de um espaço vetorial", onde matrizes e operadores lineares ainda são elementos de espaços vetoriais (você pode adicioná-los e multiplicá-los por um escalar) . Também poderíamos ter, por exemplo, " opnorm retorna a norma do operador de um operador linear" (ou matnorm ou qualquer outra coisa).

No momento temos " norm retorna a norma de um elemento de um espaço vetorial, a menos que o elemento também seja um operador linear, caso em que forneceremos a norma do operador". Pessoalmente, sinto que a expedição nunca deve ser surpreendente.

Ou seja, eu preferiria uma função que sempre faz a norma vetorial e outra função que sempre faz a norma do operador, e nenhuma função que tenta fazer as duas coisas.

Gosto ainda melhor @andyferris :+1: Normas específicas que não são as normas induzidas pelo produto interno no espaço poderiam ter um nome mais específico. O nome norm significaria exatamente norm(x) = sqrt(inner(x,x)) e poderia ser redefinido conforme necessário para tipos de usuário.

Eu pessoalmente preferiria que pudéssemos dizer " norm retorna a norma de um elemento de um espaço vetorial"

A atual função norm satisfaz essa definição. Para matrizes, calcula a norma induzida (operador), que é uma norma perfeitamente válida para um espaço vetorial . (Espaços vetoriais não precisam ter produtos internos ou normas.)

Você pode estar um pouco confuso sobre a definição de uma "norma" se achar que a norma do operador não é uma "norma de um espaço vetorial".

Essa também é uma distinção útil entre norm e innernorm . Se você definir norm , eu diria que isso implica apenas que você tem um espaço Banach (ou pelo menos um espaço vetorial normalizado). Se você definir innernorm , isso implica que você tem um espaço de Hilbert (ou pelo menos um espaço de produto interno) e que essa norma é consistente com inner .

Por exemplo, a integração numérica adaptativa (ala quadgk) é algo que requer apenas um espaço vetorial normalizado, não um espaço de produto interno.

Claro, desculpe, talvez eu tenha sido um pouco impreciso demais com minha linguagem. Obviamente, existem muitas normas válidas para um espaço vetorial, incluindo várias normas de operadores.

Acho que o que estou querendo dizer é que talvez eu prefira a escolha de qual norma seja mais explícita do que implícita? E que se você usar a mesma função (sem, por exemplo, argumentos de palavras-chave adicionais), você obtém a "mesma" norma, caso em que o Euclidiano parece uma escolha um tanto defensável para AbstractArray .

Essa também é uma distinção útil entre norm e innernorm . Se você define norma, eu diria que isso implica apenas que você tem um espaço de Banach (ou pelo menos um espaço vetorial normado). Se você definir innernorm , isso implica que você tem um espaço de Hilbert (ou pelo menos um espaço de produto interno) e que essa norma é consistente com inner .

Isso parece razoável, mas eu ainda me pergunto por que, se um objeto tiver um innernorm , ele precisaria de um norm diferente ? Alternativamente, eu proporia que a interface para o espaço Banach requer norm enquanto uma interface para espaços de produtos internos forneceria norm e inner . Essas funções podem ser usadas em código genérico que espera objetos de Banach ou espaços de produto interno conforme apropriado (EDIT: com o pensamento de que o código que funciona em espaços de Banach também funcionará automaticamente em espaços de produto interno).

Acho que você está propondo que norm(x) sempre se refere a algum tipo de norma euclidiana elementar (ou seja, uma norma de Frobenius para matrizes), ou seja, basicamente o que vecnorm é agora módulo o caso recursivo. Neste caso podemos também redefinir dot(x,y) para ser o produto interno correspondente ( inner também funciona, mas dot tem a vantagem de uma variante infixa x ⋅ y ).

Eu estou bem com isso em princípio, mas isso seria uma mudança radical e pode ser um pouco tarde antes de 0.7 para conseguir isso…

L2 é um bom padrão em alta dimensão também?
Este artigo fala sobre distância, mas pode ser que também diga respeito à norma
https://stats.stackexchange.com/questions/99171/why-is-euclidean-distance-not-a-good-metric-in-high-dimensions

Nesse caso, podemos redefinir ponto(x,y) para ser o produto interno correspondente (interno também funciona, mas ponto tem a vantagem de uma variante infixa x ⋅ y)

Podemos nos livrar de dot inteiramente? A notação infixa não deve estar relacionada com a existência de uma função chamada dot . Basta definir o infixo com o método inner para arrays de Julia. Isso é possível?

Isso é realmente o que é, o produto escalar: uma notação conveniente x ⋅ y para produtos internos entre vetores xey em R^n com geometria euclidiana.

@stevengj Acho que é um bom resumo, sim.

@ o314 L2 é um bom padrão em alta dimensionalidade? Possivelmente não, mas eu realmente odiaria se, por exemplo, a norma escolhida por norm(v::AbstractVector) dependesse de length(v) :) Eu também não gostaria de adivinhar se minha matriz ou matriz de dimensão superior é "muito grande para L2" - eu sugiro que talvez isso deva ser explicitamente marcado pelo usuário?

@juliohm Isso é definitivamente possível, embora, como mencionado, essas mudanças sejam inovadoras que estamos sugerindo. (Novamente, modulo o que fazer no caso recursivo e discussões anteriores sobre as possíveis diferenças entre inner e dot ).

@stevengj , minha interpretação do que @andyferris estava sugerindo é que, por causa da tipagem de pato, é difícil decidir se um usuário deseja interpretar um objeto como um vetor (e usar um vetor correspondente p -norm) ou como um operador (e calcule uma p -norma induzida). Então, acho que não há escolha a não ser especificar explicitamente qual comportamento é desejado. A abordagem atual é um pouco estranha no sentido de que norm tenta adivinhar implicitamente se deve escolher a norma vetorial ou a norma induzida com base na entrada, e vecnorm é uma maneira de especificar explicitamente que você deseja a norma vetorial (e é também por isso que não acho vecnorm um nome tão ruim). Uma mudança mais radical seria tornar norm sempre o padrão para a norma vetorial e especificar explicitamente quando você deseja a norma induzida, usando um argumento (palavra-chave) ou uma função completamente diferente.

Por outro lado, também não me importo com o nome innernorm , que é explícito por ser uma norma baseada em produto interno (ou seja, sempre p=2 no caso euclidiano). Acho difícil julgar se objetos personalizados (vec)norm devem suportar um argumento opcional p como parte da interface, pois em alguns dos meus casos de uso, apenas p=2 é fácil computar.

Isso é realmente o que é, o produto escalar: uma notação conveniente x ⋅ y para produtos internos entre vetores xey em R^n com geometria euclidiana.

Concordo com isso, no sentido de que não me lembro de ter visto a notação x ⋅ y no contexto de espaços vetoriais gerais (por exemplo, complexos). Eu acho que apenas a notação matemática (x,y) ou a notação Dirac < x | y > é usada nesses casos. No eletromagnetismo, muitas vezes se usa E ⋅ B para vetores no espaço euclidiano tridimensional, e mesmo que se use notação complexa (ou seja, fasores), isso não implica conjugação complexa. Se necessário, a conjugação complexa é indicada explicitamente em tais casos. Então eu não me importaria se dot se tornasse sum(x_i * y_i) sem conjugação complexa ou Hermitiana, e inner se tornasse o produto interno correto para espaços gerais de produto interno. Infelizmente, isso provavelmente não pode ser feito em um único ciclo de lançamento.

L2 é um bom padrão em alta dimensionalidade? Possivelmente não, mas eu realmente odiaria se, por exemplo, a norma escolhida por norm(v::AbstractVector) dependesse de length(v) :) Eu também não gostaria de adivinhar se minha matriz ou matriz de dimensão superior é "muito grande para L2" - sugiro que talvez isso deva ser explicitamente marcado pelo usuário?

Trabalho no mundo BIM onde lidamos com 2d e 3d, mas também 4d, 5d, 6d podem ser 7d. Nós nunca vamos mais longe. A qualquer momento sabemos em quais dimensões trabalhamos e qual algoritmo está envolvido. Isso é bastante o suficiente.

Não consigo expressar o ponto de vista das pessoas que trabalham no ML, recuperação de informação etc. Aí, pode ser que seja normal é melhor. O que é importante no meu ponto de vista é a adivinhação e a estabilidade. Não ficarei chocado se as pessoas no ML precisarem de padrões diferentes para suas coisas. Se não houver confusão. Por exemplo. é decidido explicitamente e estaticamente em tempo de compilação. É até um luxo se permanecer estável e consistente durante a aplicação de algo.

Inspirado em array:similar Não totalmente implementado e testá-lo.

norm2 = x -> x |> inner |> sqrt
norminf = ...
NMAX = 10
for N in 1:NMAX
    <strong i="13">@eval</strong> begin norm(a::Array{T,N}) where {T} = norm2 end
end
norm(a::Array{T,n}) where {T} = norminf

Podemos nos livrar do ponto completamente? A notação infixa não deve estar relacionada à existência de uma função chamada ponto. Basta definir o infixo com o método interno para arrays de Julia. Isso é possível?

norm(x::AbstractVector, p::Real=2) = vecnorm(x, p) # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L498
vecdot(x::Number, y::Number) = conj(x) * y # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L657
dot(x::Number, y::Number) = vecdot(x, y) # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L659
function dot(x::AbstractVector, y::AbstractVector) # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L677

# Call optimized BLAS methods for vectors of numbers
dot(x::AbstractVector{<:Number}, y::AbstractVector{<:Number}) = vecdot(x, y) # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L698

Dot / vecdot implica usar conjugado e decidir quando ir ao BLAS. isso tem que ser manipulado em algum lugar. Mas isso deve ser gerenciável em um único namespace.

L2 é um bom padrão em alta dimensionalidade? Possivelmente não

L2 também é a norma mais comum para espaços de dimensão infinita (por exemplo, funções). Eu acho que é um padrão razoável esperar para qualquer espaço vetorial.

Obviamente você quer ter outras normas disponíveis também. Se redefinirmos norm(x) para ser L2 elemento a elemento sempre que possível, então norm(x, p) seria Lₚ elemento a elemento, e precisaríamos de alguma outra função (por exemplo opnorm ) para o correspondente induzido/ normas do operador.

Concordo com isso, no sentido de que não me lembro de ter visto a notação x ⋅ y no contexto de espaços vetoriais gerais (por exemplo, complexos).

Eu dei várias citações em outro tópico, IIRC (por exemplo, BLAS usa dot para produto escalar complexo, e você pode encontrar fontes pedagógicas mesmo usando o termo para produtos internos de funções). O próprio termo "produto interno" é geralmente introduzido como "uma generalização de um produto escalar". Eu não acho que ninguém ficará muito surpreso com a notação de dot para um produto interno euclidiano, e é conveniente ter um operador infixo.

Poderíamos manter dot como está e introduzir inner , é claro, mas acho que isso criaria uma dicotomia confusa - nos casos mais comuns, as funções seriam equivalentes, mas em casos estranhos (por exemplo, matrizes de matrizes) eles seriam diferentes.

Mas, novamente, pode ser um pouco tarde para mudanças de última hora, então talvez tenhamos que recorrer a innernorm e inner . De qualquer forma, alguém precisaria criar um PR o mais rápido possível.

Se uma medida razoável de consenso se formar, posso dedicar um pouco de largura de banda para explorar a implementação em uma escala de tempo relevante (curta), incluindo possíveis mudanças de ruptura. Aprecio o esforço para esclarecer a semântica dessas operações e dar-lhes nomes explícitos. Melhor!

Vejo duas opções principais:

  • Sem quebra, adiciona um recurso: inner(x,y) e innernorm(x) . Substituindo vecdot e vecnorm e recursiva para matrizes de matrizes.

  • Quebrando: mude norm(x,p=2) para ser sempre elemento a elemento e recursivo, substituindo vecnorm , e introduza uma nova função opnorm para a norma operador/induzida. Faça dot(x,y) o produto escalar elemento a elemento correspondente, substituindo vecdot . (Alternativa: renomear para inner , mas é bom ter um operador infixo e é chato ter dot e inner .)

Se eu estivesse projetando coisas do zero, eu preferiria 2, mas pode ser muito perturbador mudar silenciosamente o significado de norm .

Uma opção intermediária seria definir inner e innernorm (descontinuando vecdot e vecnorm ), e depreciando norm(matrix) para opnorm . Então, na versão 1.0, reintroduza norm(matrix) = innernorm(matrix) . Dessa forma, as pessoas podem eventualmente usar inner e norm , e deixamos dot como a besta ímpar atual para vetores de matrizes (coincidindo com inner para vetores de números).

Uma curiosidade sobre innernorm é que você quer uma maneira de especificar as normas L1 ou Linf "elementwise", mas nenhuma delas corresponde a um produto interno, então innernorm(x,p) é um pouco impróprio.

Eu gosto da sua opção intermediária.

Como dito acima, gosto do nome innernorm(x) porque implica p=2 e não deve haver um segundo argumento . Tenho objetos para os quais só sei calcular a norma do produto interno. Mas com o atual (vec)norm , não está claro para mim se o argumento p faz parte da interface Base assumida e, portanto, não sei se devo omitir o segundo argumento ou dar suporte mas, em seguida, verifique explicitamente p != 2 e produza um erro.

Mas vejo o problema de não ter nenhuma maneira não obsoleta de fazer vecnorm(matrix, p!=2) durante o estágio intermediário de sua proposta.

Também gosto da opção intermediária - definitivamente queremos passar por um ciclo adequado de depreciação das normas, em vez de fazer uma mudança imediata. (Como usuário, as mudanças de última hora me assustam, mas vejo que a correção de depreciações no meu código para v1.0 é como um investimento em código limpo e claro para o futuro).

Nós realmente precisaríamos de innernorm ou poderíamos apenas usar vecnorm por enquanto (e descontinuar vecnorm em favor de norm mais tarde)?

Na verdade, não vejo nenhum alvoroço em potencial em simplesmente substituir dot por inner ... Também acho que está claro o suficiente que o produto interno deve ser uma generalização de produtos escalares.

As alterações podem ser implementadas em dois PRs separados:

  1. Substitua dot por inner e dê o significado generalizado. Opcionalmente, faça a notação infixa \cdot apontar para o interno entre os arrays de Julia.
  2. Mais discussões e ciclos de depreciação em torno das variantes e terminologia da norma.

Meu entendimento é que o PR 1 poderia ser mesclado antes do Julia v1.0. Não está quebrando.

Substituir dot por inner ainda estaria quebrado porque dot atualmente não é um produto interno verdadeiro para arrays de arrays - então você estaria mudando o significado, não apenas renomeando. Sou a favor de mudar o significado para ser um verdadeiro produto interno, mas se você mudar o significado (definindo-o como o verdadeiro produto interno), não vejo problema em continuar a soletrar como dot .

Então, poderíamos fazer o seguinte em 0.7:

  1. Descontinuar norm(matrix) para opnorm(matrix) e norm(vector of vectors) para vecnorm .
  2. Descontinuar dot([vector of arrays], [vector of arrays]) para uma chamada para sum .
  3. Diga que vecdot(x,y) e vecnorm(x, p=2) são produtos/normas internas euclidianas (para p=2 ), e torne-os recursivos (o que é um pouco problemático, mas na prática provavelmente não é grande coisa) .

Então, em 1.0:

  1. Descontinuar vecnorm para norm e vecdot para dot . (Não tenho certeza se isso é permitido pelas regras da versão 1.0, @StefanKarpinski?)

(Observe que a função numpy.inner , surpreendentemente, nem sempre é um produto interno. Mas a terminologia do NumPy em inner e dot tem sido estranha por um tempo.)

As razões pelas quais eu prefiro continuar soletrando como dot :

  • É bom ter uma ortografia infixa.
  • Para não-matemáticos que operam em espaços vetoriais de dimensão finita comuns, dot é um nome mais familiar para o produto interno euclidiano. (Os matemáticos se ajustarão facilmente ao uso do nome dot para a função de produto interno em espaços de Hilbert arbitrários - "produto escalar" não tem outro significado possível para esses espaços.)
  • Ter inner e dot seria confuso, pois eles coincidiriam em alguns casos, mas talvez não em outros (se mantivermos o significado atual dot ).
  • Fora da álgebra linear, inner tem muitos outros significados potenciais em ciência da computação e, portanto, é um pouco irritante exportar esse nome do Base.

Você pode elaborar sobre sua oposição ao nome interior? eu ainda não entendo
é por isso que você prefere ir contra uma terminologia que todos neste tópico parecem
concordar?

Em terça-feira, 15 de maio de 2018, 5h13 Steven G. Johnson [email protected]
escrevi:

(Observe que o numpy.inner
https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.inner.html
função, surpreendentemente, nem sempre é um produto interno.)


Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/JuliaLang/julia/issues/25565#issuecomment-389144575 ,
ou silenciar o thread
https://github.com/notifications/unsubscribe-auth/ADMLbdcpeWo7M4prYz76NoqUPIkfVPP3ks5tysZlgaJpZM4ReGXu
.

Nenhum dos motivos me convence:

>

  • É bom ter uma variante infixa.

Sim, e a notação infixa ainda pode existir independentemente da renomeação para
interior como explicado acima.

>

  • Para não-matemáticos que operam em dimensões finitas comuns
    espaços vetoriais, ponto é um nome mais familiar para o interior euclidiano
    produtos. (Os matemáticos se ajustarão facilmente ao uso do nome ponto para
    a função de produto interno em espaços de Hilbert arbitrários - "produto escalar" não tem
    outro significado possível para tais espaços.)

Este argumento não é bom: vamos ensinar às pessoas comuns o erro
terminologia porque eles são preguiçosos e não podem aprender uma nova palavra apropriada,
e forçar os matemáticos a usar a terminologia errada contra sua vontade.

>

  • Ter o interior e o ponto seria confuso, pois eles
    coincidem em alguns casos, mas talvez não em outros (se mantivermos o ponto atual
    significado).

Não precisamos de ambos, livre-se do nome menos geral, que concordamos ser
ponto neste ponto.

>

  • Fora da álgebra linear, a interna tem muitos outros potenciais
    significados na ciência da computação e, portanto, é um pouco irritante
    exporte este nome da Base.

Fora da álgebra linear, posso encontrar muitos usos para o ponto. Ainda mais para o
notação de ponto infixo significando coisas completamente diferentes.

>

Estou repostando o último post do @juliohm com formatação fixa.


Nenhum dos motivos me convence:

É bom ter uma variante infixa.

Sim, e a notação infixa ainda pode existir independentemente da renomeação para inner conforme explicado acima.

Para não-matemáticos que operam em espaços vetoriais de dimensão finita comuns, ponto é um nome mais familiar para o produto interno euclidiano. (Os matemáticos se ajustarão facilmente ao uso do nome ponto para a função de produto interno em espaços de Hilbert arbitrários - "produto escalar" não tem outro significado possível para esses espaços.)

Este argumento não é bom: vamos ensinar às pessoas comuns a terminologia errada porque elas são preguiçosas e não podem aprender uma nova palavra apropriada, e forçar os matemáticos a usar a terminologia errada contra sua vontade.

Ter o interior e o ponto seria confuso, pois eles coincidiriam em alguns casos, mas talvez não em outros (se mantivermos o significado atual do ponto).

Não precisamos de ambos, livre-se do nome menos geral, que concordamos ser ponto neste momento.

Fora da álgebra linear, internal tem muitos outros significados potenciais em ciência da computação e, portanto, é um pouco irritante exportar esse nome do Base.

Fora da álgebra linear, posso encontrar muitos usos para o ponto. Ainda mais para a notação de ponto infixo significando coisas completamente diferentes.

Sim, e a notação infixa ainda pode existir independentemente da renomeação para inner conforme explicado acima.

Você certamente pode definir const ⋅ = inner , mas sua terminologia é inconsistente. Eu pensei que você não gostasse de usar o "produto escalar" como um produto interno geral?

forçar os matemáticos a usar a terminologia errada contra sua vontade

Os matemáticos sabem que a terminologia não é certa nem errada, é apenas convencional ou não convencional (e talvez consistente ou inconsistente). (E a maioria das pessoas não vai para a matemática porque tem uma paixão pela ortografia prescritiva.) Na minha experiência, se você disser aos matemáticos que na mecânica quântica um vetor é chamado de "estado", o adjunto é chamado de "punhal", e um vetor dual é chamado de "sutiã", eles são sublimemente despreocupados. Da mesma forma, acho que nenhum matemático experiente piscará mais de uma vez se você disser a eles que em Julia um produto interno é escrito dot(x,y) ou x ⋅ y , especialmente porque os termos já são entendidos como sinônimos em muitos contextos. (Duvido que você encontre algum matemático que não saiba instantaneamente que você está se referindo a um produto interno se disser "pegue o produto escalar de duas funções neste espaço de funções".)

Por outro lado, para pessoas que não são matemáticas treinadas e não foram expostas a espaços abstratos de produtos internos (ou seja, a maioria dos usuários), minha experiência é que a terminologia desconhecida é mais um obstáculo. "Como faço para obter um produto escalar de dois vetores em Julia?" se tornará um FAQ.

Não há realmente nenhuma dificuldade matemática aqui a ser resolvida além de escolher a semântica. A questão da ortografia é puramente uma questão de conveniência e uso.

Fora da álgebra linear, posso encontrar muitos usos para o ponto. Ainda mais para a notação de ponto infixo significando coisas completamente diferentes.

Exceto que Julia e muitas outras linguagens de programação têm dot há anos e não tem sido um problema. inner seria uma nova quebra.

Em última análise, a ortografia desta (ou de qualquer outra) função é uma questão menor em comparação com a semântica e o caminho de depreciação, mas acho que o saldo tende a favor de dot .

Você certamente pode definir const ⋅ = internal, mas sua terminologia é inconsistente. Eu pensei que você não gostasse de usar o "produto escalar" como um produto interno geral?

Acho que você ainda não entendeu. Não há inconsistência em chamar dot um produto interno. É um produto interno, muito específico e inútil para muitos de nós. Nada mais do que sum(x.*y) .

Se o termo dot acabar em Julia tendo a semântica de inner , isso será um desastre histórico que posso garantir que muitos se sentirão incomodados. Posso prever professores em sala de aula explicando coisas como: "Sabe, agora vamos definir o produto interno do nosso espaço, mas em Julia alguém (@stevengj) decidiu chamá-lo de ponto".

Vou me certificar de que vou capturar este tópico para referência futura, se isso acabar acontecendo.

Você é o único @stevengj que insiste na terminologia dot , ninguém mais manifestou oposição a ela. Seria bom se você pudesse reconsiderar esse fato antes de tomar uma decisão.

É um produto interno, muito específico e inútil para muitos de nós. Nada mais do que soma(x.*y).

Se você acha que "produto escalar" só pode se referir ao produto interno euclidiano em ℝⁿ, então você não deve definir const ⋅ = inner , você deve definir apenas ⋅(x::AbstractVector{<:Real}, y::AbstractVector{<:Real}) = inner(x,y) .

Você não pode ter as duas coisas: inner pode usar como um sinônimo infixo (nesse caso, o operador infixo está "errado" em sua linguagem e a nomenclatura é inconsistente) ou não tem um sinônimo infixo (exceto em um caso especial).

Posso prever professores em sala de aula explicando coisas como: "Sabe, agora vamos definir o produto interno do nosso espaço, mas em Julia alguém (@stevengj) decidiu chamá-lo de ponto".

Ha ha, estou disposto a aguentar o calor desse professor indignado imaginário. Sério, você precisa olhar mais ao redor se acha que o termo "produto escalar" só é usado em ℝⁿ, ou que os matemáticos ficam indignados se o termo for usado em outros espaços de Hilbert.

isso vai ser um desastre histórico

A sério?

Essa discussão parece estar se desgastando além do que se poderia considerar um ambiente acolhedor, civil e construtivo . As opiniões e origens diferem, mas evite fazer ataques pessoais ou colocar a culpa em alguém e assuma que todas as partes estão debatendo seus pontos de boa fé.

Posso prever professores em sala de aula explicando coisas como: "Sabe, agora vamos definir o produto interno do nosso espaço, mas em Julia alguém (@stevengj) decidiu chamá-lo de ponto".

Também pode valer a pena notar aqui que Steven _é_ um professor. :piscadela:

Também estou em dúvida sobre a remoção de dot em favor de inner . O termo dot é bastante utilizado, e não ter a função em Julia, quando está em Python e MATLAB seria surpreendente. No entanto, também gosto do termo inner , pois é mais apropriado para espaços vetoriais não ℝⁿ e especialmente matrizes.

Aliás, enquanto eu estava testando o que os métodos estavam fazendo em Julia, notei que dot só funciona em vetores/matrizes reais. Isso é intencional?

Ter o interior e o ponto seria confuso, pois eles coincidiriam em alguns casos, mas talvez não em outros (se mantivermos o significado atual do ponto).

@stevengj Seria completamente ridículo substituir vecdot por inner e também manter dot ? No momento, esse problema exato que você está descrevendo já existe, apenas com vecdot em vez de inner .

OK... ansioso, quais são as sugestões de live? Eles devem:

  • Abrace dot como um produto interno genérico para uma ampla variedade de tipos. Já é recursivo corretamente em vetores de vetores, mas faríamos isso funcionar em matrizes, etc ( @jebej eu não sinto que ter dot e inner é útil, e como Steven diz, pelo menos coloquialmente usamos dot para significar produto interno com bastante frequência, e isso não é incorreto - é apenas terminologia).
  • Considere tornar norm um pouco mais consistente com o dot acima e em todos os AbstractArray , eventualmente introduzindo, por exemplo opnorm para as normas do operador (em AbstractMatrix ) e ter (em notação nova para antiga) norm(matrix) == vecnorm(matrix) após depreciações adequadas. Neste ponto, talvez não precisemos mais de vecdot e vecnorm ?

Isso está certo? Acho que isso pelo menos nos levaria a uma história de álgebra linear relativamente consistente com interfaces "limpas", onde o código genérico pode usar dot e norm como um par confiável para trabalhar com espaços de produtos internos independente do tipo.

@andyferris , sim, acho que se fizermos essa alteração, precisamos apenas de dot e norm (que agora são as operações euclidianas recursivas em matrizes ou matrizes de matrizes de qualquer dimensionalidade, embora para norma também definimos norm(x,p) p-norm) e opnorm , e não temos mais vecdot ou vecnorm .

Observe que a mudança para dot é uma mudança de ruptura porque dot atualmente não é um produto interno verdadeiro para vetores de matrizes (#22392), algo que foi debatido por muito tempo em #22220 ( ponto em que a eliminação vecdot não foi considerada IIRC). No entanto, isso foi introduzido na versão 0.7, portanto, não quebra nenhum código real lançado. Na verdade, dot em 0,6 já é o produto escalar euclidiano em matrizes de dimensionalidade arbitrária, um pouco por acidente (#22374). A alteração sugerida aqui restauraria e estenderia esse comportamento 0.6 e alteraria norm para ser consistente com ele.

Uma questão é se norm(x,p) chamaria norm(x[i]) ou norm(x[i],p) recursivamente. Ambos são comportamentos potencialmente úteis. Eu me inclino para o primeiro porque é mais geral - x[i] pode ser algum espaço vetorial normado arbitrário que apenas define norm mas não a p-norm. Chamar norm recursivamente também é o que vecnorm faz agora, então é consistente com a depreciação de vecnorm para norm .

@jebej , dot no master e 0.6 funciona para mim em matrizes complexas: dot([3im],[4im]) retorna corretamente 12+0im , por exemplo.

Outro ponto positivo sobre mudar norm(matrix) para ser a norma Frobenius é que é muito mais barato. É comum usar apenas norm(A-B) para ter uma noção de quão grande é a diferença entre duas matrizes, mas não se importar muito com a escolha específica da norma, mas muitos usuários não perceberão que o padrão atual norm(matrix) requer que calculemos o SVD.

Maravilhoso ver o consenso se formando em torno de vários pontos importantes! :) (A menos que alguém me vença (por favor, se você tiver largura de banda!) ou uma tag alfa seja atingida antes, darei uma chance à implementação dos pontos de consenso atuais após o envio #26997.) Melhor!

Outro link para referência futura: https://math.stackexchange.com/a/476742

Para ilustrar a má nomenclatura que está sendo adotada aqui conscientemente , e a má decisão imposta por uma única mente. Os produtos de ponto e internos têm propriedades matemáticas diferentes. Você está forçando toda uma comunidade contra o que é bem conhecido na literatura matemática.

E para futuros leitores, o que deveria ter sido feito se tivéssemos uma decisão coletiva:

# make dot what it is, a NOTATION
⋅(x::AbstractVector, y::AbstractVector) = sum(x[i]*y[i] for i in indices(x))

# replace the name dot by the more general inner
inner(x, y) = # anything

Acho que seremos as primeiras pessoas no universo a empregar o termo "produto escalar" para um produto interno em qualquer coisa , menos em ℝⁿ. Ainda bem que consegui impor minha vontade neste tópico (principalmente chantageando os outros desenvolvedores) para forçar essa inovação ao mundo! O produto escalar não será mais relegado a mera "notação": em vez disso, será um símbolo que significa um produto interno (como todos devem saber, atribuir significados a símbolos é o oposto de "notação").

Muito boa tomada de decisão :clap: foi definitivamente um consenso. Leia os comentários acima e você verá como todos concordaram. :+1:

Ou talvez eu deva citar alguns comentários para que fique bem claro como foi um consenso:

>

Certo - o vecdot pode ser renomeado como interno

por @andyferris

Opção 2 (provavelmente melhor): use nomes matematicamente mais corretos

interno
dimensão
Mas o que fazer com a norma?

por @Jutho

Concordo, como alternativa ao vecdot poderíamos introduzir um novo método interno

por @Jutho

Também acho estranho o nome vecdot, aliás, nem sabia que existia e tinha feito minha própria função para ele... chamada inner.

por @jebej

E muitos mais...

As pessoas podem debater ferozmente umas com as outras e levantar muitos pontos de desacordo, mas ainda assim chegar a um consenso (embora nem sempre unanimidade) sendo persuadidas e equilibrando os prós/contras. (Concordo que há prós e contras de cada opção aqui.) Lamento que o resultado que parece (provavelmente!) estar gelificando aqui não seja o resultado que você preferiu, mas não tenho certeza de como você pensa Eu "impus" minha vontade.

(Não que qualquer decisão final tenha sido tomada, é claro – ainda não há um PR, muito menos algo mesclado.)

Eu só gostaria que pudéssemos tomar uma decisão baseada na audiência do idioma. Se alguém escolhe Julia como ferramenta, tenho certeza que a pessoa pelo menos já ouviu falar do termo inner produto. É um conceito bastante popular e longe de ser exótico. Coisas exóticas incluem "homologia persistente", "teoria quântica", isso é menos difundido, e eu seria contra incluir esse tipo de terminologia.

Afinal, eu só quero ter uma linguagem que seja a melhor linguagem para computação científica, matemática, etc.

@juliohm , todos os argumentos foram baseados nas necessidades de quem achamos que o público é, e todos nós estamos tentando fazer de Julia uma linguagem tão boa quanto possível. Pessoas razoáveis ​​podem chegar a diferentes conclusões sobre terminologia, já que a matemática não determina a ortografia.

Em primeiro lugar, como mencionado acima, certamente posso concordar com a proposta atual de @stevengj e manter dot como o nome geral do produto interno. Além disso, não gosto da forma como esta discussão está indo e certamente gostaria de ser citado corretamente. @juliohm , a segunda citação que você me atribui não é minha.

Dito isto, gostaria de mencionar o seguinte como alimento para reflexão na consideração dos prós e contras. Os seguintes são principalmente contras, mas concordo com os profissionais mencionados por @stevengj. Pode haver facilmente casos de uso separados para ter dot apenas significar sum(x[i]*y[i] for i ...) . Nos casos em que a notação de ponto infixo é mais usada em matemática, esse é, de fato, o significado típico. Como um produto interno, a notação de ponto infixo é tipicamente (embora certamente não exclusivamente) reservada para espaços vetoriais reais. Outros casos de uso incluem habilitar coisas como σ ⋅ n com σ um vetor de matrizes Pauli e n um vetor de escalares. Esta foi uma das motivações por trás da forma dot está atualmente implementado, como foi apontado para mim em algum outro tópico. O fato de BLAS ter decidido usar apenas dot para vetores reais e fazer uma distinção entre dotu e dotc para vetores complexos é outra questão a ser considerada. Pessoas com experiência em BLAS podem ficar confusas se, tendo vetores complexos, desejam calcular dot(conj(u),v) ou dot(u,v) quando desejam o produto interno verdadeiro (ou seja dotc ). Além disso, eles podem procurar uma maneira de fazer dotu sem primeiro fazer uma cópia conjugada do vetor em mãos.

@Jutho a citação é sua, seu comentário completo está copiado abaixo:

Concordo, como alternativa ao vecdot poderíamos introduzir um novo método interno, mas não conheço um bom nome para "substituir" o vecnorm. Na verdade, não acho vecnorm tão ruim assim, a norma vetorial é um termo bem estabelecido e explícito para a operação que queremos.

De qualquer forma, a citação pretende mostrar qual é o desejo de muitos aqui (pelo menos como um primeiro pensamento natural) quando pensamos sobre esse assunto. Se você mudou seu desejo ao longo do tempo, isso é outra história. Eu mesmo nunca tiraria o termo "ponto" da minha cabeça durante qualquer modelagem com espaços de Hilbert. Parece antinatural e inconsistente com o que aprendi.

@Jutho : Além disso, eles podem procurar uma maneira de fazer dotu sem primeiro fazer uma cópia conjugada do vetor em mãos.

A possibilidade de exportar uma função dotu surgiu de tempos em tempos (veja por exemplo #8300). Eu concordo que isso às vezes é uma função útil: um "produto interno" euclidiano não conjugado (não é mais realmente um produto interno) que é uma forma bilinear simétrica (não sesquilinear) dotu(x,y) == dotu(y,x) (não conjugada) mesmo para espaços vetoriais complexos . Mas a utilidade dessa operação não se limita a ℂⁿ - por exemplo, esse tipo de produto geralmente aparece em espaços vetoriais de dimensão infinita (funções) para as equações de Maxwell como consequência da reciprocidade (essencialmente: o operador de Maxwell em materiais com perdas típicos é análogo a uma "matriz complexa-simétrica" ​​- simétrica sob o "produto interno" não conjugado. Então, se definirmos dot(x,y) o produto interno euclidiano geral (com o primeiro argumento conjugado), seria bastante natural definir uma função dotu(x,y) para o produto euclidiano não conjugado em qualquer espaço vetorial onde faz sentido. Eu não vejo a possibilidade de uma função dotu como um argumento contra dot , no entanto. Na maioria dos casos, quando você está trabalhando com espaços vetoriais complexos, você deseja o produto conjugado, então esse é o comportamento padrão correto.

Mas eu concordo que uma possibilidade seria definir dot(x,y) = sum(x[i]'*y[i] for i = 1:length(x)) , que é como está atualmente definido em master (não 0.6), e definir inner(x,y) como o produto escalar verdadeiro. Isso tem a vantagem de fornecer ambas as funções, as quais podem ser úteis em certos casos. No entanto, temos então duas funções que quase sempre coincidem, exceto matrizes de matrizes, e suspeito que seria um pouco confuso decidir quando usar uma ou outra. Muitas pessoas escreveriam dot quando queriam dizer inner , e isso funcionaria bem para eles na maioria dos casos, mas seu código faria algo inesperado se fosse passado um array de matrizes. Minha suspeita é que em 99% dos casos as pessoas querem o verdadeiro produto interno, e a versão "soma do produto" pode ser deixada para um pacote, se realmente for necessário (em vez de apenas chamar sum ).

@juliohm , interpretei mal sua postagem, pois pensei que os nomes estavam acima (em vez de abaixo) das respectivas citações, portanto, pensei que você atribuiu a citação de @jebej a mim. Minhas desculpas por isso.

@stevengj , eu certamente não estava pensando em ter dot(x,y) = sum(x[i]'*y[i] for i = 1:length(x)) como um padrão razoável. No caso como σ ⋅ n , a conjugação complexa/hermitiana do primeiro ou segundo argumento é desnecessária. Então, o que eu estava dizendo é que, em muitos (mas não em todos) casos em que a notação de ponto infixo é usada em fórmulas científicas, seu significado coincide com dotu , ou seja, sum(x[i]*y[i] for i = 1:length(x)) sem conjugação, também como produto interno em espaços vetoriais reais ou como alguma construção mais geral.

Então, se eu fosse fazer uma proposta alternativa (embora eu não esteja necessariamente defendendo), é ter duas funções:

  • dot(x,y) = sum(x[i]*y[i] for i...) , que ainda é o produto interno correto para vetores reais (que é provavelmente o caso de uso das pessoas que estão menos ou não familiarizadas com o termo produto interno), mas também permite construções mais gerais como σ ⋅ n , e é, portanto, a função correspondente à notação infixa

  • inner(x,y) sendo o produto interno sempre válido, com conjugação e recursão, que será usado por pessoas em contextos técnicos mais gerais.

Não estou defendendo isso como uma boa escolha para adotar na linguagem Julia, mas acho que é assim que ela é usada em grande parte da literatura. Quando o ponto infixo é usado, é como um produto interno no contexto de vetores reais, ou em alguma construção mais geral onde significa apenas contração. Quando se pretende um produto interno geral em espaços vetoriais arbitrários, a maioria da literatura científica (mas você certamente mostrou contra-exemplos) muda para <u,v> ou <u|v> (onde na primeira notação ainda há discussão sobre qual dos dois argumentos é conjugado).

Eu poderia viver com essa proposta, mas também poderia viver tendo apenas dot como produto interno geral. No final das contas, é uma questão de ter uma boa documentação, e eu também não posso acreditar que alguém iria tropeçar nessa escolha de "design".

@Jutho , concordo que não é incomum definir dot apenas para significar contração. Certamente, pode-se encontrar exemplos nos dois sentidos. Por exemplo, em linguagens de programação e bibliotecas populares:

  • Não conjugado: Numpy dot (e, bizarramente, inner ), Mathematica's Dot , Maxima . , BLAS dotu

  • Conjugado: Matlab dot , Fortran's DOT_PRODUCT , Maple DotProduct , Petsc VecDot , Numpy vdot , BLAS dotc (note que a falta de sobrecarga no Fortran 77 tornou impossível chamar isso dot mesmo que eles quisessem), o ponto de Eigen

Por um lado, o produto interno conjugado é geralmente introduzido em livros didáticos como a extensão "natural" da noção de "produto escalar" para vetores complexos - a versão não conjugada é, em certo sentido, uma extensão "não natural", na medida em que geralmente não é o que você quer. (Considere o fato de que, das linguagens que fornecem uma função dot conjugada em suas bibliotecas padrão — Matlab, Fortran, Julia, Maple — apenas o Maple fornece uma variante não conjugada, sugerindo uma falta de demanda.) por outro lado, uma função dotu não conjugada é conveniente (como suplemento) em certos casos especiais (alguns dos quais mencionei acima).

Se tivermos dot e inner , suspeito que muitas pessoas acabarão usando dot por acidente quando realmente querem que seu código seja inner genérico. (Eu aposto que o inner do Numpy não é conjugado devido a um acidente - eles o implementaram com matrizes reais em mente e não pensaram no caso complexo até que fosse tarde demais para mudar, então eles adicionaram o desajeitado vdot .) Considerando que se tivermos dot e (possivelmente) dotu , ficará mais claro que dot é a escolha padrão e dotu é a variante de caso especial.

(Concordo que ⟨u,v⟩ , ⟨u|v⟩ ou (u,v) são notações mais comuns para produtos internos em espaços de Hilbert arbitrários - eles são o que eu normalmente uso - mas essas notações são uma não iniciante para Julia. Houve alguma discussão sobre a análise de colchetes Unicode como chamadas de função/macro, por exemplo, # 8934 e # 8892, mas nunca foi a lugar nenhum e parece improvável que isso mude em breve.)

Concordo plenamente com sua avaliação @stevengj .

Eu também.

Suspeito que é hora de um de nós brincar com qualquer implementação em um PR e ver como isso sai.

@Jutho Eu sempre vi o produto escalar com matrizes de Pauli como uma abreviação para uma contração sobre tensores de ordem superior ... um dos espaços vetoriais é real, 3D.

Concordo que ⟨u,v⟩, ⟨u|v⟩, ou (u,v) são notações mais comuns para produtos internos em espaços de Hilbert arbitrários—elas são o que eu costumo usar—mas essas notações não são iniciais para Julia.

Seria realmente possível fazer ⟨u,v⟩ funcionar.

@StefanKarpinski : Seria realmente possível fazer ⟨u,v⟩ funcionar.

Absolutamente, e apoiar esta notação precisa foi sugerido em #8934, mas nunca foi a lugar nenhum. (Observe também que os colchetes angulares têm outros usos comuns, por exemplo, ⟨u⟩ geralmente denota uma média de algum tipo.) Ele não quebra e ainda pode ser adicionado em algum ponto, mas não parece razoável esperar no próximo prazo. Também é muito lento digitar \langle<tab> x, y \rangle<tab> , então não é muito conveniente do ponto de vista de programação para uma operação elementar.

e não podemos sobrecarregar <> para isso, certo?

Não

Não posso dizer que li todos os comentários deste tópico gigantesco, mas só quero destacar alguns pontos, alguns dos quais já foram feitos antes:

  • Distinguir entre ponto e interior parece excessivamente pedante. Na verdade, aos meus ouvidos, parece absurdo porque em francês há apenas um termo - "produto escalar" - e é difícil diferenciar entre coisas que para mim têm o mesmo nome ;-)
  • Quando você vem de numpy e trabalha com arrays complexos, ter dot sendo conjugado por padrão é a melhor coisa de todas. Nenhum ponto de decisão aqui, eu só queria dizer como estou feliz por não ter mais que fazer esses conj(dot()) s!
  • Ter duas funções que têm o mesmo comportamento na maioria dos casos mas às vezes diferem é um design ruim, e tem e vai causar confusão, com código que deveria estar chamando uma na verdade chamando a outra, simplesmente porque o usuário não conhece melhor. Isso é particularmente irritante com norm : se você estiver codificando um algoritmo de otimização e quiser parar sempre que norm(delta x) < eps , você escreverá norm . Mas então você quer otimizar wrt uma imagem ou algo assim, você executa seu código, e de repente ele inicia em um SVD impossível de matar (porque BLAS) de uma grande matriz. Isso não é acadêmico, causou problemas no Optim.jl e, sem dúvida, em outros pacotes também. Ninguém vai saber que vecnorm existe a menos que tenha uma razão específica para procurá-lo.
  • Com base no ponto anterior, qualquer solução que mescle dot e vecdot e norm e vecnorm é boa, mesmo que remova um pouco de flexibilidade na casos array-of-arrays. Para normas, eu acrescentaria que muitas vezes ao trabalhar com coisas nas quais existem várias normas definidas (por exemplo, matrizes), o que o usuário quer é chamar norm para obter uma norma, sem se importar particularmente com qual delas. As normas induzidas são mais frequentemente de interesse teórico do que prático devido à sua intratabilidade computacional. Eles também são específicos para a interpretação 2D-array-como-operador, em vez de 2D-array-como-storage (uma imagem é um array 2D, mas não é um operador em nenhum sentido útil). É bom ter a possibilidade de computá-los, mas eles não merecem ser o padrão norm . Padrões razoáveis, simples e bem documentados que têm alternativas detectáveis ​​são melhores do que tentativas de inteligência (se o usuário quiser fazer algo inteligente, deixe-o fazer explicitamente).

Portanto, +1 em @stevengj 's

sim, acho que se fizermos essa mudança, então precisamos apenas de ponto e norma (que agora são as operações euclidianas recursivas em matrizes ou matrizes de matrizes de qualquer dimensionalidade, embora para norma também definamos norma(x,p) para ser a p-norm) e opnorm, e não tem mais vecdot ou vecnorm.

Uma alternativa mais "juliana" para norma/opnorm pode ser ter um tipo de operador, que poderia envolver um array 2D, no qual norm faz opnorm. Isso pode ser feito no nível de pacotes (vários dos quais já existem)

Eu prefiro digitar opnorm(matrix) do que norm(Operator(matrix))

Vou falar da galeria de amendoim aqui e dizer que gosto de onde isso está indo— vecnorm e vecdot sempre me incomodaram. A necessidade de pedir explicitamente a norma do operador – que sempre me pareceu bastante especializada – parece muito mais sensata do que ter que pedir uma norma que é muito mais rápida e fácil de calcular (por exemplo, a norma de Frobenius). Escrever opnorm parece uma boa interface para pedir a norma do operador relativamente especializado.

Eu também sinto que ter uma distinção sutil entre dot e inner pode levar a confusão e uso indevido desenfreado. Ensinar os usuários sobre qual função eles devem _suposto_ usar quando ambas as funções fazem o que eles querem e uma delas é mais fácil tende a não funcionar muito bem. Minha impressão é que é relativamente raro em código genérico que sum(x*y for (x,y) in zip(u,v)) seja realmente o que você quer quando um produto interno verdadeiro ⟨u,v⟩ realmente existe. Quando isso é realmente o que se deseja, é bastante fácil, claro e eficiente (porque Julia é o que é) apenas escrever algo assim para calculá-lo.

Chamar a função u⋅v dot ou inner parece ser a parte menos importante de tudo isso. Tenho quase certeza de que nenhuma das escolhas seria vista pelos historiadores como um desastre — embora a noção de que os historiadores se importariam certamente seja lisonjeira. Por um lado, se concordamos em manter o significado do "verdadeiro produto interno" de u⋅v , então sim, inner é o termo matemático mais correto. Por outro lado, quando há uma sintaxe com um nome de função correspondente, ela tende a confundir menos os usuários quando o nome corresponde à sintaxe. Como a sintaxe aqui usa um ponto, essa regra prática suporta a ortografia desta operação como dot . Talvez este seja um caso razoável para definir const dot = inner e exportar ambos? Então as pessoas podem usar ou estender o nome que preferirem, pois são a mesma coisa. Se alguém quiser usar um nome para outra coisa, pode, e o outro nome permanecerá disponível com seu significado padrão. É claro que isso resultaria em três nomes exportados para a mesma função— dot , inner e — o que parece um pouco excessivo.

É uma opção para remover o símbolo ou substituí-lo por <u,v> ?

Comentários:

  • Deixa clara a intenção. Compare estes dois exemplos:
<u,v> * M * x

vs.

u ⋅ v * M * x
  • A sintaxe <u,v> implica associação: primeiro operamos em u e v e depois o resto da expressão segue.

  • Se um usuário se esforçou para digitar <u,v> , é muito improvável que ele tenha em mente um simples sum(x[i]*y[i]) . O símbolo é fácil de pular com os olhos e tem muitas outras conotações. Particularmente, em álgebra linear, para um espaço vetorial V sobre um corpo F, o produto de um escalar α ∈ F com um vetor v ∈ V é denotado α ⋅ v em vários livros didáticos.

  • A remoção ou substituição de também eliminaria o problema de vários nomes sendo exportados. Seria necessário apenas exportar inner e <,> para produtos internos gerais, com a implementação padrão para matrizes correspondendo à semântica de soma iterável.

  • Se alguém precisar definir um produto escalar por vetor como descrito acima para um espaço vetorial V sobre um corpo F, ele poderá definir a notação para isso. O espaço vetorial seria então totalmente definido com uma sintaxe curta e agradável e poderia ser estendido para um espaço de Hilbert definindo ainda <u,v> .

Definitivamente, não podemos usar a sintaxe <u,v> ; a sintaxe que podemos usar é ⟨u,v⟩ — observe os colchetes Unicode, não os sinais menor que e maior que, < e > . Também temos u'v como sintaxe para algo que é um produto escalar ou um produto interno? (não tenho certeza qual...)

Sim, desculpe, a versão unicode dele. Seria muito claro para ler. Também resolveria esse problema com vários nomes e liberaria para outros fins.

Eu não acho que queremos usar para qualquer outro propósito – isso parece confuso.

Apenas imaginando o quão maravilhoso seria poder escrever um código que se parece com:

⟨α ⋅ u, v⟩ + ⟨β ⋅ w, z⟩

para vetores abstratos (ou tipos) u,v,w,z ∈ V e escalares α, β ∈ F .

u'v é um produto interno (e um produto escalar, se você seguir a convenção conjugada) apenas para matrizes 1d, não para matrizes, por exemplo. (Esta é outra razão pela qual é inútil limitar o ponto infixo a matrizes 1d, já que já temos uma notação concisa para esse caso.)

Stefan, “termo matemático correto” é um erro de categoria – correção matemática não é um conceito que se aplica à terminologia/notação. (Substitua “convencional” por “correto”. Mas então a preocupação se torna menos urgente).

Mais casos de uso: https://stackoverflow.com/questions/50408177/julia-calculate-an-inner-product-using-boolean-algebra

E uma derivação formal de produtos internos booleanos usando a notação ⟨,⟩ : https://arxiv.org/abs/0902.1290

EDIT: link fixo para papel

O que você acha da proposta de sintaxe de colchetes angulares? Resolveria as questões levantadas aqui?

Então, qual é a sua proposta exatamente? É mais ou menos isso:

  1. Descontinuar dot para inner
  2. Descontinuar u⋅v para ⟨u,v⟩

Então não haveria nenhuma função dot e nenhum operador ?

Essa mudança seria algo razoável?

Desculpe a demora em responder, estou em uma conferência com acesso limitado à internet.

E apenas para clareza e completude, qual é a contraproposta aqui? Fazer nada?

Para esclarecer ainda mais a proposta, há uma mudança semântica envolvida: produtos internos generalizados.

Atenção: agora debatemos isso até o ponto em que há um risco real de não chegar ao 0,7 alfa. Isso não significa que não possa ser alterado após o alfa, mas haverá muito mais relutância em mudar as coisas depois disso.

Sim, eu gostaria de ter as habilidades para enviar um PR há muito tempo. Está além das minhas habilidades fazer isso acontecer, mesmo que eu ache uma característica extremamente importante.

Mesmo descontando a questão da sintaxe do operador, ainda há alguma complexidade com sombreamento de nomes e depreciações de vários estágios para cada conjunto de conceitos semânticos ( dot e vecdot atuais e norm e vecnorm ).

Para o lado dot , parece que todo o espaço de opções (novamente operadores de desconto) é:

I. Quebre dot silenciosamente em vetores de arrays alterando o comportamento em 0.7 para um produto interno sem um depwarn padrão (embora você possa avisar que o comportamento está sendo alterado). Substitua vecdot para dot em 0,7 também.
II. Na versão 0.7, deprecie vecdot em todas as entradas para inner .
III. Em 0.7, deprecie dot em vetores de arrays para sua definição, e dot em outras entradas e vecdot em todas as entradas para inner .
4. Na versão 0.7, deprecie dot e vecdot em vetores de matrizes para funções não exportadas ou para suas definições, e vecdot em todas as outras entradas para dot . Na versão 1.0, adicione dot em vetores de arrays com semântica de produto interno.

Para o lado da norma, há algum consenso em torno de um único caminho (em 0.7, descontinuar norm em matrizes para opnorm e possivelmente descontinuar vecnorm para innernorm ; em 1.0 , adicione norm em matrizes com a semântica atual vecnorm ), mas isso também resulta em um nome extra em 1.0 (ou vecnorm ou innernorm ); novamente, uma maneira de evitar isso pode ser depreciar vecnorm em 0,7 para sua definição ou para uma função não exportada como Base.vecnorm em vez de um nome exportado.

...Eu acho que. Espero não ter tornado as coisas mais pastosas do que já eram.

Alguém familiarizado com a base de código pode enviar um PR para a mudança?

Podemos separar as coisas normais com as quais todos parecem concordar e fazer isso pelo menos? A parte dot versus inner é um pouco mais controversa, mas não vamos deixar isso atrapalhar a parte que não é.

@StefanKarpinski , observe que eles são um pouco acoplados: para tipos em que você tem um produto de ponto (interno) e uma norma, eles devem ser consistentes.

Ok, eu realmente não me importo para que lado isso vai. Quem faz o trabalho decide.

Eu tinha um PR ( #25093 ) para fazer vecdot se comportar como um produto interno verdadeiro (e vecnorm como a norma correspondente), tornando-os recursivos. Isso pode ser útil como ponto de partida de como os futuros dot e norm devem se parecer. Infelizmente, minha falta de habilidades em git me fez estragar aquele PR, então eu o fechei, planejando voltar a ele depois que a nova sintaxe de iteração fosse concluída.

No entanto, ter acabado de se tornar pai pela segunda vez há alguns dias significa que atualmente não há slots de "tempo livre" no meu calendário.

tendo acabado de ser pai pela segunda vez há alguns dias

Parabéns Juto! 🎉

Sim, parabéns!

Parece que pode haver algum consenso em torno da ideia de ter dot e inner , onde:

  1. inner é um produto interno recursivo verdadeiro
  2. dot = dot(x,y) = sum(x[i]'*y[i] for i = 1:length(x)) conjugado ou não e, portanto, se sobrepõe a dot para Vector{<:Number} ou Vector{<:Real}

Em relação a:

Muitas pessoas escreveriam dot quando queriam dizer internal, e funcionaria bem para elas na maioria dos casos, mas seu código faria algo inesperado se fosse passado uma matriz de matrizes.

Não acredito que isso seria um problema. Como esta é uma operação bastante incomum, eu esperaria que as pessoas pelo menos tentassem para ver o que ela faz e/ou olhassem a documentação.

Eu acho que o acima seria uma grande mudança, e não muito perturbadora, já que a semântica de dot não é alterada na maioria dos casos.

Parece que pode haver algum consenso se formando em torno da ideia de ter dot e inner

Pelo contrário, a discussão de https://github.com/JuliaLang/julia/issues/25565#issuecomment -390069503 em parece favorecer um ou outro, mas não ambos, como, por exemplo, estabelecido em https://github. com/JuliaLang/julia/issues/25565#issuecomment -390388230 e bem suportado com reações.

Talvez inner (e também dot ) devam ser produtos internos/ponto/escalares recursivos e o comportamento antigo poderia ser implementado em funções como dotc(x,y) = sum(x[i]' * y[i] for i in eachindex(x)) e dotu(x,y) = sum(transpose(x[i]) * y[i] for i in eachindex(x)) ? Os nomes dotu e dotc corresponderiam aos nomes BLAS correspondentes.

(Concordo que ⟨u,v⟩, ⟨u|v⟩, ou (u,v) são notações mais comuns para produtos internos em espaços de Hilbert arbitrários—elas são o que eu costumo usar—mas essas notações não são iniciais para Julia Houve alguma discussão sobre a análise de colchetes Unicode como chamadas de função/macro, por exemplo, #8934 e #8892, mas nunca foi a lugar nenhum e parece improvável que isso mude em breve.)

@stevengj , quando você adicionou este parágrafo a um comentário anterior, você quis dizer que a sintaxe ⟨u,v⟩ é difícil de implementar na linguagem?

Alguma chance desse recurso chegar ao Julia v1.0? Tenho tantas ideias e pacotes que dependem da noção de produtos internos gerais. Por favor, deixe-me saber se eu devo diminuir minhas expectativas. Desculpe pelo lembrete constante.

Você não viu #27401?

Obrigado @jebej e obrigado @ranocha por assumir a liderança :heart:

quando você adicionou este parágrafo a um comentário anterior, você quis dizer que a sintaxe ⟨u,v⟩ é difícil de implementar na linguagem?

Não é tecnicamente difícil adicionar ao analisador, mas provou ser difícil chegar a um consenso sobre como (e se) representar colchetes personalizados no idioma. Veja a discussão em #8934, que não deu em nada há 4 anos e não foi revivida desde então. (Acrescente isso ao fato de que em campos diferentes as pessoas usam os mesmos colchetes para muitas coisas diferentes, por exemplo, ⟨u⟩ é usado para médias de conjuntos em física estatística.) Outra questão, levantada em #8892, é a semelhança visual de muitos Unicode diferentes colchetes.

Obrigado @stevengj , agradeço os esclarecimentos. Já estou muito empolgado com o fato de termos produtos internos gerais padronizados em todos os pacotes. :100: Talvez a notação de colchetes angulares possa brilhar em outro ciclo de lançamento no futuro. Não tão importante, mas bastante conveniente para poder escrever código que é literalmente como a matemática em nossas publicações.

Se ⟨args...⟩ for uma sintaxe válida para chamar o operador anglebrackets ou algo assim (o que chamar a função que essa sintaxe chama é realmente um pouco complicado, pois não temos nenhum precedente), então as pessoas poderiam optem pelo significado que quiserem para a sintaxe.

@StefanKarpinski , o argumento em # 8934 era que deveria ser uma macro. Acho que nunca chegamos a um consenso.

(Se decidirmos na Base que anglebrackets(a,b) significa inner(a,b) , isso desencorajará as pessoas de "optar pelo significado que quiserem" porque a decisão já terá sido tomada.
Não é uma escolha terrível, é claro, mas pode ser desnecessário atribuir um significado a isso na Base, desde que sejam analisados.)

Não me lembro dos detalhes dessa discussão, mas fazer uma macro parece obviamente uma má ideia para mim.

Com o nº 27401, acho que podemos considerar que os produtos internos estão sendo levados a sério.

Tradicionalmente, um problema é encerrado apenas quando o PR relevante é mesclado...

Claro, podemos deixar em aberto, eu acho. Só queria tirá-lo do rótulo de triagem.

Isso deve ser fechado, já que o #27401 está mesclado agora?

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

omus picture omus  ·  3Comentários

ararslan picture ararslan  ·  3Comentários

yurivish picture yurivish  ·  3Comentários

felixrehren picture felixrehren  ·  3Comentários

wilburtownsend picture wilburtownsend  ·  3Comentários