Julia: sintaks baru untuk transpos

Dibuat pada 15 Mar 2017  ·  103Komentar  ·  Sumber: JuliaLang/julia

Sekarang .op umumnya adalah bentuk vektor dari op , sangat membingungkan bahwa .' berarti transpos daripada bentuk vektor dari ' (adjoint, alias ctranspose ). Masalah ini untuk membahas sintaks alternatif untuk transpose dan/atau adjoint.

linear algebra parser

Komentar yang paling membantu

Sangat menentang membuat tr(A) berarti transpos matriks - semua orang akan berpikir itu berarti jejak matriks: https://en.wikipedia.org/wiki/Trace_ (linear_algebra)

Semua 103 komentar

Andreas mencoba Aᵀ (dan mungkin Aᴴ ) di #19344, tetapi tidak diterima dengan baik. Kita juga bisa bermain kata pada ^ dengan tipe eksponen khusus T (dan mungkin H ) sedemikian rupa sehingga A^T ditranspos, tetapi itu juga agak teduh. Tidak yakin ada banyak opsi bagus lainnya yang masih agak/agak terlihat seperti notasi matematika.

Saya agak berpikir bahwa t(A) mungkin yang terbaik, tetapi sangat disayangkan untuk "mencuri" nama satu huruf lainnya.

Memindahkan komentar saya dari masalah lain (bukan berarti menyelesaikan apa pun, tapi ...):

+1 untuk menggunakan sesuatu selain .' .

Saya tidak dapat menemukan bahasa dengan sintaks khusus untuk transposisi, kecuali untuk APL yang menggunakan yang tidak terlalu jelas, dan Python yang menggunakan *X (yang akan membingungkan Julia). Beberapa bahasa menggunakan transpose(X) ; R menggunakan t(X) . Itu tidak cantik, tapi tidak lebih buruk dari .' . Setidaknya Anda tidak tergoda untuk menggunakan ' dengan mengacaukannya dengan .' : akan jelas bahwa ini adalah operasi yang sangat berbeda.

Lihat kode Rosetta . (BTW, contoh Julia sebenarnya menggambarkan transpos konjugasi ...)

Bisakah salah satu kutu lain digunakan? ` atau "

-100 untuk mengubah adjoint, karena itu adalah salah satu hal luar biasa yang membuat penulisan kode Julia sejelas menulis matematika, ditambah transpos konjugasi biasanya adalah apa yang Anda inginkan, jadi masuk akal untuk memiliki sintaks yang disingkat untuk itu.

Selama kita memiliki sintaks yang bagus untuk transpos konjugasi, operator postfix untuk transpos reguler tampaknya sebagian besar tidak perlu, jadi menjadikannya sebagai panggilan fungsi biasa tampaknya baik-baik saja bagi saya. transpose sudah bekerja; tidak bisakah kita menggunakan itu saja? Saya menemukan t(x) R-ism tidak menguntungkan, karena tidak jelas dari namanya apa yang sebenarnya harus dilakukan.

Menggunakan tanda centang yang berbeda akan agak aneh, misalnya A` dapat sangat mirip A' tergantung pada fontnya, dan A" terlihat terlalu mirip A'' .

Jika kita membuat perubahan di #20978, maka transpos postfix sebenarnya menjadi lebih berguna daripada sekarang. misalnya jika Anda memiliki dua vektor x dan y dan Anda ingin menerapkan f berpasangan pada mereka, Anda dapat melakukannya misalnya f.(x, y.') ... dengan #20978 , ini akan berlaku untuk array tipe arbitrer.

Sejujurnya, saya pikir pilihan terbaik kita adalah tetap membiarkannya apa adanya. Tidak ada saran yang tampak seperti peningkatan yang jelas bagi saya. .' memiliki keuntungan dari keakraban dari Matlab. . sebenarnya agak kongruen dengan sintaks dot-call dalam contoh seperti f.(x, y.') , dan menyarankan (agak benar) bahwa transpos "sekering" (tidak menghasilkan salinan sementara berkat RowVector dan generalisasi selanjutnya).

Faktanya, kita bahkan bisa melangkah lebih jauh, dan membuat f.(x, g.(y).') menjadi operasi peleburan. yaitu kami mengubah transpose .' menjadi non-rekursif ala #20978 dan kami memperluas semantiknya untuk menyertakan fusi dengan panggilan titik bersarang lainnya. (Jika Anda menginginkan versi non-fusing, Anda akan memanggil transpose .)

Saya sangat menyukai rencana itu, @stevenngj.

Satu kerutan: mungkin makro @. tidak mengubah y' menjadi y.' (karena itu salah). Namun, itu bisa mengubah y' menjadi semacam operasi adjoint yang menyatu.

Masalah utama adalah menemukan cara yang bersih untuk membuat f.(x, g.(y).') memiliki semantik sekering. Satu kemungkinan adalah mengubahnya menjadi f.(x, g.(y.')) dan karenanya menjadi broadcast(x,y -> f(x, g(y)), x, y.') ?

Perhatikan bahwa, agar ini berfungsi dengan baik, kita mungkin perlu mengembalikan metode transpose(x) = x fallback, dalam hal ini kita mungkin juga membiarkan transpose tetap rekursif.

Saya pikir memutuskan apakah transpose harus rekursif atau tidak adalah ortogonal apakah kita membuatnya berpartisipasi dalam fusi sintaks titik. Pilihan membuatnya non-rekursif tidak dimotivasi oleh itu.

@StefanKarpinski , jika mengembalikan fallback transpose(x) = x , maka sebagian besar motivasi untuk mengubahnya menjadi non-rekursif hilang.

Apa masalahnya jika fallback dipulihkan tetapi kami masih memiliki transpos menjadi non-rekursif?

@jebej , transpos rekursif lebih tepat bila digunakan sebagai operasi matematika pada operator linier. Jika saya ingat dengan benar, alasan utama untuk membuatnya non-rekursif adalah agar kita tidak perlu mendefinisikan fallback transpose(x) = x , daripada melempar MethodError.

Tetapi tidak buruk untuk memiliki fallback tetapi tetap non-rekursif.

Izinkan saya menambahkan dua komentar (saya telah membaca diskusi sebelumnya dan tidak memperhatikannya - maaf jika saya melewatkan sesuatu):

  • dokumentasi untuk permutedims mengatakan Ini adalah generalisasi transpos untuk array multi-dimensi. transpose , yang sebenarnya tidak.
  • Bagaimana seharusnya membuat transpos vektor x=["a", "b"] ? Sebenarnya y=x.' berfungsi dan membuat variabel baru tetapi getindex gagal. AFAIK Anda harus menggunakan reshape(x, 1, :) atau jauh lebih lambat hcat(x...) untuk mencapainya tetapi tidak wajar memiliki sintaks yang berbeda untuk Vector ( permutedims tidak berfungsi di sini ).

Apa kasus penggunaan Anda untuk mentranspos vektor string?

Pertimbangkan skenario berikut misalnya:

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

dan saya ingin menambahkan y setelah baris terakhir dari x . Dan cara paling sederhana adalah dengan vcat transpos y .

Muncul dalam praktik ketika secara bertahap mencatat data teks ke Matrix{String} (saya bisa menggunakan Vector{Vector{String}} ), tetapi seringkali matriks lebih berguna (atau sekali lagi ada pertanyaan bagaimana mengonversi Vector{Vector{String}} hingga Matrix{String} dengan menggabungkan elemen berurutan secara vertikal).

Kasus penggunaan lain: transpos adalah cara paling sederhana untuk membuat dua vektor ortogonal satu sama lain untuk menyiarkan fungsi melalui produk kartesius ( f.(v, w.') ).

Titik data: Kemarin saya menemukan pihak yang bingung dengan operator "broadcast-adjoint" postfix dan mengapa ia berperilaku seperti transpos. Terbaik!

FWIW, saya sangat merasa bahwa kita harus menyingkirkan sintaks .' . Sebagai seseorang yang lebih akrab dengan Julia daripada dengan Matlab, saya berharap itu berarti adjoint vektor dan saya benar-benar tersandung ketika tidak. Julia bukan Matlab dan tidak boleh terikat oleh konvensi Matlab - jika di Julia, titik berarti vektorisasi fungsi yang berdekatan, maka ini harus konsisten di seluruh bahasa dan tidak boleh secara acak memiliki satu pengecualian mengerikan yang .' secara resmi tidak terkait dengan ' .

Saya pikir tidak apa-apa untuk hanya memiliki transpose tanpa notasi "centang" khusus, karena sebagian besar waktu, itu disebut matriks bilangan real, jadi ' akan setara jika Anda benar-benar ingin menyimpan pengetikan. Jika kita ingin membuat versi fusing dari transpose, maka menurut saya .' adalah sintaks yang tepat.

Itu poin yang bagus. Bisa dibilang hanya adjoint yang membutuhkan sintaks super-kompak.

Sebut saja ini transpose dan tidak digunakan lagi .' . Di masa mendatang, kita dapat mempertimbangkan apakah kita ingin .' sebagai adjoint pointwise atau jika kita hanya ingin membiarkannya tidak digunakan lagi untuk menghindari menjebak pengguna Matlab.

Perhatikan bahwa saya baru saja mengambil paket terdaftar dan menemukan 600+ penggunaan .' , jadi ini tidak terlalu langka. Dan dengan panggilan titik / broadcast (yang hanya di 0.6 mulai sepenuhnya menangani data non-numerik), keinginan untuk dengan malas mentranspos array non-numerik (di mana adjoint kurang masuk akal) mungkin akan menjadi jauh lebih umum, jadi argumen untuk sintaks kompak agak diperkuat.

Maka sebaiknya kita menghentikan .' sesegera mungkin, sebelum lebih banyak kode terjebak dalam pola penggunaan yang buruk.

Mengapa itu buruk?

Masalahnya adalah .' sekarang tidak berarti seperti yang terlihat sebagai operator titik-titik.

Seperti yang saya katakan di atas, karena itu melanggar pola umum bahwa . berarti vektorisasi, dan sepertinya itu berarti adjoint yang divektorkan (terutama untuk seseorang yang tidak terbiasa dengan Matlab).

Saya pikir @stevenngj membuat poin yang bagus — ini terkait dengan keinginan untuk transpos non-rekursif sederhana.

Saya tahu itu tidak populer, tetapi saya mulai menyukai Andreas' #19344 untuk . Pada titik ini, saya lebih suka menghentikan penggunaan _all_ superscripts sebagai pengenal, dan menafsirkan _any_ trailing superscripts sebagai operator postfix. Ini juga memberikan jalan untuk menyelesaikan beberapa kerumitan di sekitar literal_pow menggunakan nomor superskrip. Ya, akan sangat menyedihkan kehilangan χ² dan seperti nama variabel, tapi saya pikir manfaatnya akan lebih besar daripada kerugiannya.

Pada titik ini, saya lebih suka menghentikan penggunaan _all_ superscripts sebagai pengenal, dan menafsirkan _any_ trailing superscripts sebagai operator postfix.

RIP kode saya
screenshot from 2017-11-09 22-08-25

Pada titik ini, saya lebih suka menghentikan penggunaan semua superskrip sebagai pengidentifikasi

Saya benar-benar tidak berpikir itu perlu, ketika kita hanya ingin T dan mungkin beberapa hal lain di masa depan.

Konsistensi yang bodoh…

Ya, sedikit tidak konsisten untuk menggunakan .' untuk transpos, tetapi semua alternatif yang diusulkan sejauh ini tampaknya lebih buruk. Bukan hal terburuk di dunia untuk mengatakan " .' adalah transpos, pengecualian dari aturan biasa tentang operator titik." Anda mempelajari ini dan melanjutkan.

Satu hal yang perlu diperhatikan yang dapat membantu mengatasi potensi kebingungan tentang .' bukan siaran titik adalah bahwa ini adalah operator postfix, sedangkan penyiaran awalan adalah op. dan infix adalah .op . Jadi kita dapat mengatakan bahwa . tidak berarti disiarkan ketika itu adalah postfix. Kegunaan lain dari postfix . adalah pencarian bidang, dan getfield(x, ') tidak masuk akal, sehingga berbeda dari arti lain.

(Yang mengatakan, saya lebih suka transpose(x) daripada menyimpan .' .)

@stevenngj Saya berani bertaruh bahwa banyak (mungkin sebagian besar) dari 600+ penggunaan .' dalam paket terdaftar yang Anda sebutkan di atas dapat diganti dengan ' tanpa biaya untuk keterbacaan, dan kode akan terus bekerja.

Mungkin tidak populer, tetapi mungkin masih ada postfix " dan ` ?

kegunaan dari .' dalam paket terdaftar yang Anda sebutkan di atas dapat diganti dengan ' tanpa biaya untuk keterbacaan, dan kode akan terus berfungsi.

Perhatikan bahwa setelah #23424 mendarat, kita akan dapat menggunakan transpose pada array string dan seterusnya, tetapi tidak adjoint . Praktik terbaik untuk penggunaan aljabar linier x.' kemungkinan besar akan menjadi sesuatu seperti conj(x') (semoga ini malas, yaitu gratis). Meskipun saya suka menggunakan .' untuk kekompakannya, mungkin menghilangkannya akan memaksa pengguna aljabar linier untuk menggunakan hal yang benar dan pengguna array-of-data untuk menggunakan transpose .

mungkin masih ada postfix " dan `?

Sintaks baru untuk transpose() tampaknya terlalu dini. IMHO akan lebih baik untuk mencela .' untuk diganti seperti yang Anda sarankan dengan conj(x') dan transpose sesuai kebutuhan.

Saya merasa bahwa .' sangat berguna di matlab terutama karena desakan matlab bahwa "semuanya adalah matriks" bersama dengan kurangnya aturan pengirisan yang koheren sehingga Anda sering perlu memasukkan transpos acak di berbagai tempat untuk mendapatkan hal-hal untuk bekerja.

Untuk meringkas argumen di sini:

  1. .' sekarang satu-satunya yang menonjol sebagai operator bertitik yang tidak berarti "terapkan operator tanpa titik secara elemen"; pengguna baru yang tidak berasal dari Matlab menemukan ini sebagai jebakan yang mengejutkan.

  2. .' sekarang secara efektif ambigu: maksud Anda transpose atau maksud Anda conj(x') ? Pada prinsipnya, setiap penggunaan warisan .' harus diperiksa untuk menentukan apakah itu mengubah indeks array 2 dimensi atau apakah itu melakukan "adjoint tak terkonjugasi".

Isu pertama bermasalah tetapi tidak fatal dengan sendirinya; masalah kedua adalah yang benar-benar buruk – ini bukan lagi satu operasi yang koheren, melainkan akan dibagi menjadi dua arti yang terpisah.

Saya baru menyadari bahwa jika kita pernah mengubah .' menjadi "elementwise adjoint", maka conj(x') kira-kira setara dengan x'.' dan conj(x)' kira-kira akan menjadi x.'' yang sangat dekat dengan x.' .

Mungkin tidak populer, tetapi mungkin masih ada postfix " dan `?

Salin kode tempel ke Slack dan lihat bahwa penghancuran penyorotan sintaks akan menjadi ...

Mampu mentranspos apa pun itu bagus karena memudahkan untuk "melintasi produk" melalui mekanisme pengiriman, dan kasus penggunaan singkat lainnya seperti itu. Masalah dengan tidak memiliki fallback yang mudah untuk hal-hal semacam ini adalah bahwa selalu peretasan yang akan kita lihat adalah dengan hanya mendefinisikan fallback transpose(x) = x (atau pada tipe Base, jadi ketik-pembajakan dalam paket) untuk membuat ini semacam itu bekerja dengan mudah. Itu membuat saya berpikir: mengapa bukan Complex yang aneh? Adjoin dari sebagian besar bilangan adalah dirinya sendiri, jadi adjoint dari kompleks adalah yang menjadi spesialisasi: tidak bisakah itu diperluas melampaui angka?

Saya melihat dua hal yang sangat terkait di sini:

1) x' tidak berfungsi untuk tipe non-angka, jadi kami ingin cara mudah melakukan ini untuk data lain
2) transpose(x) tidak sesederhana x.' . Ini sebagian besar untuk kasus (1), karena kasus penggunaan untuk transpos matriks kompleks jauh lebih jarang.

Tetapi alih-alih turun (2), mengapa tidak mencoba dan melakukan perbaikan yang wajar untuk (1)?

Mungkin perbaikan yang masuk akal hanyalah makro yang membuat ' berarti transpos alih-alih adjoint?

Tetapi alih-alih turun (2), mengapa tidak mencoba dan melakukan perbaikan yang wajar untuk (1)?

Kami sudah menyusuri jalan itu dan beberapa di dekatnya. Ada banyak diskusi yang dihasilkan yang mungkin dapat disaring oleh orang lain, tetapi secara ringkas, itu tidak berjalan dengan baik. Pada dasarnya, operasi matematika adjoint tidak masuk akal untuk hal-hal yang bukan angka. Menggunakan ' pada non-angka hanya karena Anda menyukai sintaks singkat itu buruk – ini adalah jenis permainan kata yang terburuk dari operator dan seharusnya tidak mengherankan bahwa hal-hal buruk terjadi dari penyalahgunaan makna semacam ini. Fungsi adjoint hanya boleh didefinisikan pada hal-hal yang masuk akal untuk dijadikan adjoint dan ' hanya boleh digunakan untuk mengartikan itu.

Ingat bahwa .' seperti yang saat ini digunakan pada dasarnya adalah dua operasi yang berbeda: transposisi array dan adjoint non-konjugasi. Masalah transpos rekursif menyoroti fakta bahwa ini adalah operasi yang berbeda dan oleh karena itu kita membutuhkan cara yang berbeda untuk mengekspresikannya. Orang-orang matematika tampaknya bersikeras bahwa operasi adjoint non-konjugasi adalah (a) penting, dan (b) berbeda dari pertukaran dimensi sederhana. Secara khusus, agar benar, adjoint non-konjugasi harus rekursif. Di sisi lain, menukar dimensi array generik seharusnya tidak bersifat rekursif. Jadi operasi ini perlu ditulis secara berbeda, dan penggunaan .' yang ada perlu disamarkan karena memiliki satu arti atau arti yang lain. Menghentikan .' adalah cara untuk memaksa ini.

Akhirnya, sementara saya merasa sangat yakin bahwa permutedims(x, (2, 1)) jelas terlalu merepotkan untuk menukar dimensi array 2d, saya menemukan argumen bahwa transpose(x) terlalu merepotkan dan tidak meyakinkan. Apakah operasi ini begitu umum sehingga memiliki nama fungsi yang sederhana dan jelas terlalu berlebihan? Betulkah? Apakah menukar dimensi array jauh lebih umum atau penting daripada semua hal lain dalam bahasa yang kami gunakan untuk nama fungsi dan sintaks panggilan fungsi? Notasi householder membuat adjoint cukup istimewa karena kita ingin menulis hal-hal seperti v'v , v*v' dan v'A*v . Itu sebabnya adjoint mendapatkan sintaks yang sangat bagus. Tapi menukar dimensi array? Itu tidak menjamin operator menurut saya.

Bukan argumen yang kuat, tetapi saya sering menggunakan operator ' untuk mencetak array yang lebih ringkas (bila digunakan sebagai wadah sederhana), misalnya ketika saya ingin melihat konten beberapa vektor sekaligus di layar saya ( dan selalu merasa frustrasi ketika gagal karena elemen tidak dapat dialihkan). Jadi sintaks singkat untuk REPL pasti berguna. (Juga, ini memudahkan orang yang terbiasa dengan array baris-utama, untuk memiliki cara sederhana untuk "mengganti urutan", khususnya ketika porting algoritme ke julia menggunakan array 2d; tapi jelas juga bukan argumen yang kuat). Hanya untuk mengatakan bahwa itu adalah sintaks singkat yang bagus yang tidak berguna hanya untuk ahli aljabar linier.

Saya telah mengomentari beberapa ide sintaks di https://github.com/JuliaLang/julia/pull/19344#issuecomment -261621763, pada dasarnya adalah:

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

Tetapi tanpa peretasan tentu saja, hanya gagasan bahwa mungkin ada semacam "aplikasi fungsi postfix" dan itu menuntut tanda kurung (x)f , versi bertitik bisa seperti ini (x).f ( xf akan menjadi pengenal, bahkan dengan f menjadi simbol superskrip).

Contoh peretasan ini dulu berfungsi pada 0.6 tetapi sekarang:

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            

Yang menyedihkan, saya awalnya ingin melakukan itu untuk kekuatan:

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 "³"

Yang saya pikir secara naif akan mengaktifkan sintaks seperti: n² = (n)² dan n³ = (n)³ Tetapi pengenal numerik apa pun dilarang berada di posisi pertama, namun (A)⁻¹ juga berfungsi, di mana ⁻¹ tadinya const ⁻¹ = inv .

Saya telah menerapkan peretasan serupa untuk InfixFunctions.jl .

Sebagai pengguna, saya bisa melakukan paket PostfixFunctions.jl , dan senang dengan apa pun yang Anda temukan terbaik di sini. Namun saat ini batasan sintaks ini:

  • menggunakan superindeks numerik di awal pengidentifikasi tidak diperbolehkan
  • superindex x * ᶠ di postfix (perkalian implisit dalam peretasan) (x)ᶠ tidak diizinkan

Tampak agak terlalu berlebihan bagi saya IMHO, saya ingin setidaknya dapat mendefinisikan pengidentifikasi yang dapat dimulai dengan superskrip numerik, atau lebih umum, hanya melarang karakter numerik aktual 0-9 dengan semantik angka, di awal pengenal, itu akan luar biasa. 😄.

Bersulang!

Lihat #10762 untuk beberapa diskusi tentang karakter angka lain sebagai pengenal.

Masalah lainnya terkait dengan #22089, sufiks operator. +ᵀ sekarang menjadi operator yang valid, yang (mungkin secara tidak sengaja) tidak mengizinkan pengidentifikasi yang hanya terdiri dari menggabungkan karakter dalam konteks di mana operator mungkin diharapkan. Itu sepertinya bug bagi saya. Agak aneh juga bahwa adalah pengidentifikasi yang valid tetapi -ᵀ tidak melakukan -(ᵀ) . Namun itu bukan akhir dari dunia, dan IMO memperbaikinya tidak ada gunanya kehilangan kemungkinan penggunaan lain dari .

Perhatikan bahwa menggunakan .' sebagai operator transpos postfix bahkan tidak ada di tabel di sini (terlepas dari apa yang dikatakan subjek masalah), pertimbangannya sebenarnya adalah apakah kita harus mempertahankan .' sebagai operator postfix untuk adjoint non-konjugat, yang akan menjadi rekursif. Ini kebetulan sering sama dengan transposisi, tetapi umumnya bukan operasi yang sama. Jika orang-orang aljabar linier bersedia membiarkan .' berarti transpos array generik, itu cerita yang berbeda, tetapi kesan saya adalah itu tidak dapat diterima.

@Ismael-VC, saya dapat melihat mengizinkan (x)ᵀ sebagai sintaks fungsi postfix untuk superskrip – karena apa lagi artinya? Saya pikir di mana proposal Anda mulai menggosok orang dengan cara yang salah memungkinkan pengenal apa pun diterapkan sebagai fungsi dalam sintaksis postfix. Saya akan membatasinya pada superskrip.

@StefanKarpinski , saya pikir konsensus itu tepat untuk memungkinkan .' berarti transposisi array non-rekursif, non-konjugasi (jika kita memiliki operator ini sama sekali), sedangkan ' adalah rekursif, konjugasi operasi gabungan.

Saya sangat, sangat membenci ide menggunakan untuk operator transpos postfix. Terlalu berguna untuk memiliki superscript dalam nama variabel, seperti aᵀa atau LᵀDL = ltdlfact(A) . (Selain fakta bahwa hanya menggunakan untuk operator sementara superskrip lain valid dalam mengidentifikasi akan menjadi aneh.)

Itu sama sekali bukan pemahaman saya – saya pikir orang-orang linalg mendukung untuk mempertahankan a.' apa adanya, yaitu artinya conj(a)' . Menyimpan .' tetapi mengubah artinya menjadi transpose array cukup berbeda – Saya tidak yakin bagaimana perasaan saya tentang itu. Saya setuju bahwa hanya memiliki sebagai operator postfix akan mengganggu dan tidak konsisten. Saya lebih suka @Ismael-VC (a)ᵀ proposal, namun, yang tidak akan mencegah menggunakan aᵀ sebagai nama.

Ingatan saya tentang diskusi itu mencerminkan ingatan Steven. Transpos rekursif, non-konjugasi jarang terjadi dan umumnya cukup aneh. Ringkasan yang layak di sini: https://github.com/JuliaLang/julia/issues/20978#issuecomment -316141984.

Saya pikir kita semua setuju bahwa postfix ' adalah adjoint dan harus tetap ada.
Saya pikir kita semua setuju bahwa postfix .' adalah sintaks yang kurang optimal.
Saya pikir sebagian besar setuju bahwa transpos non-rekursif (struktural) lebih berguna daripada transpos rekursif.

Oke, jadi poin yang sepertinya disetujui semua orang:

  1. Gunakan a' untuk adjoint(a)
  2. Gunakan conj(a)' atau conj(a') untuk adjoint (non-)konjugasi.

Jadi satu-satunya hal yang diperdebatkan adalah bagaimana menulis transpos array:

  • Sebagai a.' atau
  • Sebagai transpose(a) atau
  • Sebagai (a)ᵀ .

Apakah penilaian ini benar?

Ya, saya pikir begitu (di mana "array transpose" adalah non-rekursif).

Juga, seperti yang saya pahami, semua orang setuju bahwa transpose(a) pasti sintaks yang valid (dan non-rekursif), dan satu-satunya poin ketidaksepakatan adalah apakah .' dan/atau (a)ᵀ harus alternatif (sepenuhnya setara) sintaks yang valid.

Pendekatan (1) dari https://github.com/JuliaLang/julia/issues/20978#issuecomment -315902532, yang menerima sedikit dukungan (mis. https://github.com/JuliaLang/julia/issues/20978# issuecomment-316080448), tetap menjadi kemungkinan. Saya memiliki cabang yang menyadari pendekatan itu (memperkenalkan flip(A) ) yang dapat saya posting.

Untuk apa nilainya, saya mendukung penghentian .' . Kebingungan dan ambiguitas di utas ini adalah argumen yang kuat untuk melakukannya sendiri. Terbaik!

Saya percaya bahwa selama kita memiliki postfix ' , orang-orang akan ingin menggunakannya untuk menyiarkan f melalui produk vektor kartesius dengan f.(v, w') . Dan orang-orang akan ingin menggunakannya untuk membentuk kembali vektor string menjadi vektor baris header untuk struktur seperti tabel. Jadi sangat menarik bagi saya untuk memiliki pengganti yang sederhana dan mudah digunakan yang dapat kami arahkan kepada mereka.

Berikut adalah opsi yang belum kami pertimbangkan: A*' — bigraph baru. Notasi matematika umum mungkin menafsirkan ini sebagai conj(A)' , yang sebenarnya cukup dekat dengan yang kita inginkan. Itu telah tersedia pada 0,6, tetapi pada 0,7 kami mengizinkan penggunaan * untuk menggabungkan karakter… masih bisa diterapkan.

Saya tidak percaya postfix " dan ` tersedia karena literal string khusus yang diurai di luar akhir baris. Postfix * sendiri juga tidak tersedia karena alasan yang sama. Postfix prime A′ mungkin adalah salah satu pengidentifikasi unicode yang paling umum digunakan, jadi itu bahkan lebih dari Aᵀ .

Sejujurnya, setelah melihat kode saya, saya tidak menggunakan .' sama sekali, jadi transpose(a) mungkin baik-baik saja.

Perhatikan bahwa saya baru saja mengambil paket terdaftar dan menemukan 600+ penggunaan .', jadi ini tidak terlalu langka.

Apakah tempat ini diperiksa sama sekali untuk melihat apakah .' tidak digunakan di tempat yang ' akan baik-baik saja? Saya mulai berpikir bahwa itu mungkin benar lebih sering daripada tidak. Jika tidak, satu-satunya tempat di mana saya telah melihat penggunaan .' yang sah adalah sebelum label Plots.jl mengizinkan vektor (bukannya menginginkan vektor baris string), tetapi itu telah diubah. Untuk kode di mana saya sangat membutuhkan ini, saya pikir saya akan mulai melakukan T = transpose secara lokal, atau melempar makro untuk mengubah ' menjadi transpose .

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

akan baik-baik saja dengan saya untuk kasus langka itu.

orang akan ingin menggunakannya untuk menyiarkan f melalui produk kartesius vektor dengan f.(v, w'). Dan orang-orang akan ingin menggunakannya untuk membentuk kembali vektor string menjadi vektor baris header untuk struktur seperti tabel. Jadi sangat menarik bagi saya untuk memiliki pengganti yang sederhana dan mudah digunakan yang dapat kami arahkan kepada mereka.

Jika hanya muncul sekali dalam sebuah pernyataan, tidak apa-apa untuk hanya menggunakan transpose ?

Sintaks a*' untuk conjugate-adjoint cukup bagus, meskipun sepertinya bukan itu operasi yang membutuhkan sintaks yang lebih baik. &a akan segera tersedia dan menyarankan untuk menukar sesuatu, meskipun cukup berbeda dari notasi tradisional untuk ini.

Mungkin sudah waktunya untuk polling jerami?

Bagaimana seharusnya kita mengeja transpos struktural?

(kira-kira dalam urutan proposal; tidak ada penilaian pada nama emoji di sini)

  • 👍: A.' — ubah saja artinya, pertahankan sintaksnya tetap sama
  • Contoh: transpose(A) — tidak ada sintaks khusus
  • Jawaban: t(A) atau tr(A) — tidak ada sintaks khusus, tetapi ekspor nama yang lebih pendek
  • Catatan: Aᵀ — hanya dengan dan mungkin satu atau dua superskrip yang dibuat khusus dari pengidentifikasi
  • Catatan: (A)ᵀ — dengan semua superskrip terpisah dari pengenal yang berperilaku seperti operator postfix
  • ❤️: A*' — berkilau tepat di atas lembah yang luar biasa itu, itu berarti transpos struktural
  • Jika Anda lebih suka &A , beri tanda pada postingan Stefan tepat di atas (emoji kami habis)

Diskusi LinAlg memang berbicara tentang pemberian .’ untuk penggunaan transpos non-rekursif, karena conj(x’) relatif tidak umum. Namun adalah sintaks matematika dan benar-benar harus mengambil arti matematika (jika ada).

Sangat menentang membuat tr(A) berarti transpos matriks - semua orang akan berpikir itu berarti jejak matriks: https://en.wikipedia.org/wiki/Trace_ (linear_algebra)

Jika tidak mencela superskrip sebagai pengenal (yang mungkin harus dipertimbangkan secara serius sebelum 1.0) maka ᵀ(A) juga dimungkinkan.

Sehubungan dengan saran (A)ᵀ , saya mohon maaf karena sedikit menggagalkan diskusi ini dengan komentar berikut:

Saya tidak pernah terlalu peduli untuk memiliki tersedia sebagai operator unary, terutama karena Anda tetap akan mengetik √(...) segera setelah Anda ingin menerapkannya ke variabel yang lebih dari satu satu atau beberapa karakter. Selain itu, saya selalu menemukan perbedaan fungsi antara dan √a sangat artifisial. Mungkin masuk akal jika Anda tahu tentang kelas Unicode dll, tetapi bagi orang lain ini tampaknya tidak masuk akal. Tentu berguna untuk memiliki sebagai nama variabel yang valid, tetapi juga √a bisa menjadi nama variabel yang berguna untuk menyimpan akar kuadrat dari a jika Anda perlu menggunakannya beberapa kali waktu. Atau ekspresi yang lebih rumit seperti a²b dan akar kuadratnya a√b , di mana yang pertama adalah pengidentifikasi yang valid dan yang terakhir tidak. Di atas segalanya, saya suka konsistensi.

Jadi untuk konsistensi, saya suka proposal memiliki operator postfix saat menggunakan tanda kurung (A)ᵀ , (a)² , dalam kombinasi dengan menghapus operator unary Unicode (dan kerabatnya) sehingga itu juga dapat digunakan dalam pengidentifikasi (saat masih dapat diakses sebagai panggilan fungsi normal √(a) ).

Saya setuju 100% dengan apa yang @Jutho katakan dan pikirkan dalam beberapa kesempatan. Maukah Anda membuka masalah, @Jutho? Proposal: izinkan dalam nama pengenal, memerlukan √(x) untuk memanggil sebagai op.

pertanyaan selanjutnya -> bagaimana dengan 2 |> √ ?

Mari kita diskusikan di utas lain, tetapi singkatnya 2 |> √ berarti √(2) .

Alternatif lain, yang tidak memerlukan perubahan parser dan mudah diketik, adalah A^T untuk transpose (dengan mendefinisikan T menjadi tipe tunggal dengan metode ^ ). … oh, ternyata @mbauman juga punya ide ini. Agak jelek, tapi tidak lebih dari A.' .

Saya tidak memiliki keahlian, tetapi saya sangat tertarik dengan hasil diskusi ini sebagai siapa yang kemungkinan besar akan mengetik ribuan baris yang berisi ekspresi matriks dalam pekerjaan saya.

transpose(A) # with no special syntax memenangkan suara di atas, tetapi menyakitkan bagi mata dan jari saya.

Dalam python penggunaan umum mungkin dengan numpy dan banyak hal yang terlihat seperti berikut dan tidak terlalu buruk:

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)

Saya tidak ingin harus melakukan:

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

Ini benar-benar mengubah konsepsi mental transpos dari konvensi bahwa notasi matematika telah ditetapkan, yang merupakan penanda postfix, biasanya Aᵀ atau Aᵗ .

Secara pribadi saya sangat senang dengan A' yang bekerja di Julia v.0.6, sebelum diambil oleh adjoint. Apakah adjoint sangat sering digunakan?

Berikut adalah komentar saya dalam sebuah tabel:

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.

Secara pribadi saya sangat senang dengan A' yang bekerja di Julia v.0.6, sebelum diambil oleh adjoint. Apakah adjoint sangat sering digunakan?

Saya tidak mengerti, A' selalu menjadi tambahan dari A . Kami biasa memanggil fungsi yang mendasarinya ctranspose untuk transpos konjugasi, tetapi kami mengganti namanya menjadi istilah yang setara adjoint tanpa perubahan fungsi.

Jika Anda melakukan aljabar linier maka kemungkinan besar Anda menginginkan transpos konjugasi, jadi Anda akan mengetik A' daripada transpose(A) . Popularitas tidak mendefinisikan sintaks khusus untuk transpos non-konjugasi adalah (mungkin) sebagian karena fakta bahwa itu benar-benar tidak umum untuk sebagian besar penggunaan aljabar linier menginginkan transpos non-konjugasi.

Jika Anda mengerjakan aljabar linier maka ...

Jika alat Anda adalah palu maka ... :)

... Anda harus memikirkan kemungkinan Julia bisa berkembang ke bahasa pemrograman umum.

Mungkin tidak, mungkin akan tetap menjadi argumen aljabar linier - yang merupakan kemungkinan yang harus dipikirkan oleh programmer seperti saya. :)

@mahiki , Anda adalah contoh 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)

akan ditulis secara harfiah dalam Julia sebagai:

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

atau dengan asumsi bahwa vektor adalah baris dalam contoh NumPy itu dan akan menjadi kolom di Julia:

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

yang tampaknya sejelas dan matematis yang didapatnya. Jika data Anda nyata, maka adjoint dan transpose adalah operasi yang sama, itulah mengapa Anda menggunakan transpose di atas – tetapi secara matematis adjoint adalah operasi yang tepat. Seperti yang dikatakan @ararslan , X' selalu berarti adjoint di Julia (dan juga di Matlab). Itu sebelumnya disebut ctranspose kependekan dari " conjugate transpose " tetapi nama itu keliru karena properti yang mendefinisikan operator adalah itu

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

yang merupakan properti yang mendefinisikan adjoint Hermitian tetapi kebetulan dipenuhi oleh transpos konjugat ketika A adalah matriks kompleks. Itu sebabnya "adjoint" adalah istilah umum yang tepat untuk operator ini.

Semua yang dikatakan, saya memilih di atas untuk transpose(a) dan a.' karena saya pikir itu akan baik-baik saja untuk a.' berarti transpos struktural. Ini akan berfungsi seperti yang diharapkan, dan meskipun itu tidak akan rekursif dan karenanya tidak "benar secara matematis" dalam beberapa kode generik, membuatnya berfungsi seperti yang diharapkan tampaknya cukup baik. Dan memberi tahu orang-orang untuk mempertimbangkan menggunakan conj(a') dalam kode generik tampaknya seperti hal pendidikan daripada sesuatu yang kita benar-benar perlu untuk memukul kepala orang.

@mahiki Jika karena alasan tertentu Anda benar-benar perlu menggunakan transpose alih-alih adjoint berkali-kali dalam kode Anda, maka Anda dapat mendefinisikan makro yang lebih pendek seperti @t alias transpose (walaupun saya tahu solusi ini tidak ideal, terutama jika Anda menulis kode dengan orang lain).

Anda harus memikirkan kemungkinan Julia bisa berkembang ke bahasa pemrograman umum.

@Liso77 Sudah. Sebagai salah satu dari banyak contoh, Nanosoldier menjalankan server web yang mendengarkan acara GitHub dan menjalankan tolok ukur kinerja sesuai permintaan, semuanya di Julia. Itu penyimpangan, dan saya tidak ingin utas ini keluar dari topik.

Jika Anda mentranspos semacam matriks dengan data non-numerik—yang merupakan kasus penggunaan yang sepenuhnya valid—notasi transpos matematis sebenarnya tampak seperti permainan kata yang buruk. Dalam hal ini saya merasa akan lebih baik untuk lebih eksplisit tentang apa yang Anda minta, misalnya transpose (atau bahkan permutedims , tergantung pada kebutuhan spesifik Anda).

Jika Anda mentranspos semacam matriks dengan data non-numerik—yang merupakan kasus penggunaan yang sepenuhnya valid—notasi transpos matematis sebenarnya tampak seperti permainan kata yang buruk.

Karena A.' sebenarnya bukan "notasi transpos matematika" dalam pengertian biasa, saya tidak melihat bahwa ini adalah argumen untuk atau menentang.

Saya pikir @ararslan tidak menentang .' yang ada tetapi menentang pengenalan sintaks superscript-T. Saya cenderung setuju - jika yang Anda maksud adalah konsep aljabar linier dari adjoint, maka Anda harus menggunakan ' (bahkan jika matriks Anda nyata). Dan jika Anda memiliki matriks data non-numerik, maka tentu saja sah untuk mengubah dua indeks, tetapi operasi ini sebenarnya bukan "transpos" seperti yang biasa kita pikirkan, dan menggunakan notasi superskrip-T matematis adalah mungkin lebih cenderung membingungkan daripada memperjelas. Satu-satunya situasi di mana notasi superskrip-T benar-benar sesuai adalah jika Anda memiliki matriks numerik yang indeksnya ingin Anda ubah, tetapi Anda benar-benar tidak menginginkan operator linier adjoint. Situasi seperti itu pasti ada, tetapi mungkin terlalu jarang untuk membenarkan pengenalan sintaks baru.

... tapi operasi ini sebenarnya bukan "transpose" seperti yang biasa kita pikirkan, ...

Jika ini sangat tidak biasa mengapa ararslan dan banyak lainnya memilih ejaan struktural transpos sebagai transpose(A) ?

Terima kasih @StefanKarpinski @ararslan @ttparker. Saya harus kembali ke teks aljabar linier saya dan menemukan kembali adjoint, itu di sana baik-baik saja. Saya mengambil itu sebelum Analisis Kompleks, mungkin mengapa saya tidak memperhatikannya.

Saya senang bisa melakukan ini
gradient = (1/m) * (X'Θ - Y) * X'

Kebingungan saya berasal dari meluasnya penggunaan 'transpose' (sebagai superskrip T) dalam dokumen referensi, makalah, buku teks, dll, misalnya catatan kuliah stanford CS229 Andrew Ng , di mana kode Julia yang sesuai akan menggunakan adjoint sebagai dalam contoh tampilan bersih @StefanKarpinski di atas. Ini karena adjoint dan transpose setara dalam (kanan?) . pembaruan: yup

Sekarang notasi favorit saya untuk transpos adalah apa pun yang konsisten secara logis. Jelas .' bukan karena konflik dengan sintaks operator bertitik, dan saya tidak keberatan dengan transpose(A) tanpa sintaks khusus, karena tampaknya tidak ada sintaks khusus yang tersedia, kecuali untuk superskrip unicode.

Saya suka solusi @ttparker jika saya menemukan diri saya menulis banyak transpose, makro @t alias transpose .

Sekali lagi, saya salah mengatakan:

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

Terima kasih telah menanggapi komentar saya dengan serius meskipun fasilitas saya buruk dengan matematika tingkat pascasarjana.

(Dari wacana .)

Saya ingin ' menjadi operator pasca-perbaikan yang memetakan f' ke '(f) di mana Base.:'(x::AbstractMatrix) = adjoint(x) dan pengguna bebas menambahkan metode lain yang telah tidak ada hubungannya dengan adjoint. (Misalnya, beberapa orang mungkin ingin f' merujuk ke df/dt.)

Dengan sufiks operator yang diperkenalkan di 0.7, maka wajar jika f'ᵃ dipetakan ke 'ᵃ(f) , dan seterusnya, memungkinkan pengguna untuk mendefinisikan operator postfixnya sendiri. Ini akan memungkinkan untuk memiliki Base.:'ᵀ(x::AbstractMatrix) = transpose(x) dan Base.:'⁻¹(x::Union{AbstractMatrix,Number}) = inv(x) , dll.

Menulis A'ᵀ mungkin tidak sebersih Aᵀ , tetapi itu tidak memerlukan penghentian nama variabel yang diakhiri dengan .

Sepintas yang terlihat seperti itu bisa menjadi fitur non-breaking. Ini adalah kompromi yang sangat cerdas. Saya suka itu.

Tampaknya masuk akal bagi saya. Bagian tersulit adalah membuat nama untuk fungsi ' —sintaks awalan tidak berfungsi dalam kasus ini.

Bagian tersulit adalah menemukan nama untuk fungsi '

apostrophe ? Mungkin terlalu harfiah...

Apakah mungkin untuk membuat sintaks awalan berfungsi (misalnya, dengan sintaks (')(A) eksplisit?)? Jika tidak, maka itu masalah karena akan melanggar aturan if-you-can-define-the-symbol-name-then-you-can-override-its-syntax yang diperkenalkan oleh https://github.com/JuliaLang /julia/tarik/26380.

Sunting: tampaknya tersedia:

julia> (')(A)


ERROR: syntax: incomplete: invalid character literal

julia> (')(A) = 2


ERROR: syntax: incomplete: invalid character literal

Sayangnya ' adalah salah satu karakter yang paling sulit untuk digunakan sebagai nama pengenal, karena memperkenalkan jenis atom (karakter) yang berbeda, yang memiliki prioritas sangat tinggi (sama dengan prioritas pengenal itu sendiri). Misalnya, apakah (')' merupakan aplikasi ' untuk dirinya sendiri, atau sebuah paren terbuka yang diikuti oleh ')' literal?

Salah satu opsi yang tidak praktis dalam jangka pendek adalah mendeklarasikan literal karakter tidak bernilai ' , dan menggunakan makro string seperti c"_" sebagai gantinya.

Bagaimana jika ' mem-parsing sebagai pengidentifikasi ketika didahului oleh titik-kolon, sehingga Base.:' akan berfungsi?

Tentu saja (@__MODULE__).:'(x) = function_body mungkin agak rumit untuk ditulis, tetapi (x)' = function_body seharusnya bekerja dengan cara yang sama. Sunting: Tidak, karena (x)' harus dipetakan untuk memanggil ' di Base . Mendefinisikan fungsi ' dalam modul saat ini akan merepotkan, tetapi tidak akan ada alasan untuk melakukannya juga.

Atau bagaimana dengan membiarkan '' mengurai sebagai pengidentifikasi ' ketika itu akan diurai sebagai literal karakter kosong (yang saat ini merupakan kesalahan tingkat penguraian). Demikian pula, ''ᵃ akan diurai sebagai pengenal 'ᵃ , dll.

Segala sesuatu yang saat ini bukan kesalahan sintaks akan tetap diurai seperti sebelumnya (misalnya 2'' adalah postfix ' diterapkan dua kali ke 2 ), tetapi 2*'' sekarang akan parsing sebagai dua kali ' .

Tampaknya membingungkan bahwa kita akan memiliki a'' === a tetapi ''(a) === a' . Tampaknya lebih baik menggunakan Base.apostrophe sebagai nama (atau sesuatu seperti itu).

Mungkinkah lebih baik untuk membagi diskusi ini menjadi masalah Github baru, karena ini tentang sintaks ' yang tidak terkait langsung dengan transposisi matriks?

Apakah ada cara otomatis untuk membagi masalah, atau haruskah saya membuka yang baru dan menautkan ke diskusi di sini?

Yang terakhir

Satu-satunya situasi di mana notasi superskrip-T benar-benar sesuai adalah jika Anda memiliki matriks numerik yang indeksnya ingin Anda ubah, tetapi Anda benar-benar tidak menginginkan operator linier adjoint. Situasi seperti itu pasti ada, tetapi mungkin terlalu jarang untuk membenarkan pengenalan sintaks baru.

Saya kira saya terlalu terlambat untuk diskusi, tetapi saya ingin menunjukkan satu penggunaan yang menurut saya layak disebutkan: Menerapkan diferensiasi langkah kompleks ke fungsi bernilai nyata yang memiliki transpose di dalam dia. (Saya pribadi menemukan bahwa saya membutuhkan .' di MATLAB dan julia untuk alasan khusus ini.)

Saya akan memberikan contoh dengan beberapa kemunculan transpose (mungkin saya bisa menghindari melakukannya dengan cara ini?)

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

Intinya f dan Df harus didefinisikan menggunakan transpose dan tidak boleh menggunakan adjoint.

Saya tidak berpikir metode langkah kompleks sangat relevan di julia. Bukankah ini peretasan/solusi yang rapi untuk mendapatkan diferensiasi otomatis dalam kasus di mana suatu bahasa mendukung bilangan kompleks bawaan yang efisien, tetapi tipe angka Dual yang sama efisiennya tidak dapat ditentukan? Itu tidak terjadi di julia, yang memiliki perpustakaan diferensiasi otomatis yang sangat bagus.

Saya setuju tentang penggunaan Angka ganda alih-alih metode langkah kompleks dan itu adalah poin bagus yang Anda buat (saya pribadi telah mengganti semua evaluasi metode langkah kompleks saya dengan yang angka ganda di julia). Namun, saya pikir ini masih merupakan kasus penggunaan yang valid, untuk tujuan demonstrasi, trik pengajaran (lihat, misalnya, Nick Higham berbicara tentang metode langkah kompleks di Julia Con 2018 ), dan portabilitas (dengan kata lain, saya khawatir itu Versi kode MATLAB di atas menggunakan bilangan kompleks akan lebih bersih).

Berasal dari dunia Insinyur dan mungkin Fisikawan yang menggunakan array kompleks lebih dari array nyata, tidak memiliki operator transpos sedikit menyusahkan. (Representasi fasor kompleks untuk ketergantungan waktu harmonik ada di mana-mana di bidang kami.) Saya pribadi lebih menyukai sintaks numpy dari xH dan xT, meskipun satu-satunya pertimbangan saya adalah keringkasan .

Kepadatan operator transpos relatif terhadap transpos Hermitian adalah sekitar 1 banding 1 dalam kode saya. Jadi transpos tak terkonjugasi sama pentingnya bagi saya. Banyak penggunaan transpose adalah untuk membuat produk luar dan untuk mengukur array dengan benar untuk antarmuka ke kode lain atau untuk perkalian matriks.

Saya bermaksud untuk saat ini hanya menyediakan fungsi makro atau satu karakter untuk operasi, namun apa yang setara dengan fungsi lama, transpose() atau permutedims()?

transpose ditujukan untuk aljabar linier dan bersifat rekursif, dan permutedims adalah untuk pengaturan tipe data non-rekursif apa pun.

Sangat menarik Anda mengatakan Anda menggunakan transpose sebanyak adjoint. Saya dulu sama, tetapi sebagian besar karena saya cenderung membuat kesalahan di mana data saya nyata sehingga saya cenderung untuk mengubah posisi tetapi sebenarnya adjoint adalah operasi yang benar (digeneralisasi untuk kasus kompleks - adjoint adalah operasi yang tepat untuk algoritma saya). Ada (banyak) pengecualian yang valid, tentu saja.

Dalam segala hal yang berhubungan dengan elektrodinamika, Anda sering menggunakan vektor seperti ruang dan ingin menggunakan operasi vektor di R^n (biasanya n=3), yaitu transpose khususnya, meskipun vektor Anda bernilai kompleks karena Anda telah melakukan transformasi Fourier. Sepertinya @mattcbro sedang membicarakan aplikasi semacam ini.

Karena itu, ketika membaca diskusi sintaks, saya sering merenungkan bahwa bagi saya, secara pribadi, saya tidak dapat membayangkan bahwa sintaks yang sedikit lebih bertele-tele adalah hal yang memperlambat kecepatan atau efisiensi pemrograman saya. Memikirkan algoritme itu sendiri dan cara paling alami/efisien untuk mengimplementasikannya membutuhkan lebih banyak waktu.

Dalam segala hal yang berhubungan dengan elektrodinamika, Anda sering menggunakan vektor seperti ruang dan ingin menggunakan operasi vektor di R^n (biasanya n=3), yaitu transpos khususnya, meskipun vektor Anda bernilai kompleks karena Anda telah mengambil Fourier mengubah.

Belum tentu. Seringkali Anda menginginkan kuantitas rata-rata waktu dari amplitudo Fourier, dalam hal ini Anda menggunakan produk titik kompleks, misalnya [𝐄*×𝐇] adalah fluks Poynting rata-rata waktu dari komponen Fourier kompleks dan |𝐄|² adalah kerapatan energi vakum rata-rata waktu. Di sisi lain, karena operator Maxwell adalah (biasanya) operator simetris kompleks ("timbal balik"), Anda sering menggunakan "produk dalam" tak terkonjugasi untuk aljabar (dimensi tak hingga) pada bidang (𝐱) dll. semua ruang.

Itu benar, saya sering memiliki kata itu di kalimat pertama, tetapi tampaknya menghapusnya :-).

Nah kalau mau ke sana, besaran Elektromagnetik malah lebih ringkas ditulis dalam rumusan Aljabar Clifford, sering disebut Aljabar Geometris. Aljabar tersebut memiliki banyak automorfisme dan antiautomorfisme yang memainkan peran penting dalam perumusan teori, terutama ketika mempertimbangkan masalah hamburan.

Aljabar ini biasanya memiliki representasi matriks yang ringkas dan morfisme tersebut sering mudah dihitung melalui transpos kompleks, transpos Hermitian, dan konjugasi.

Namun demikian seperti yang saya nyatakan sebelumnya penggunaan utama saya dari transpos sering untuk mengatur array saya untuk antarmuka dengan array lain, kode lain, dan untuk mendapatkan matriks berlipat ganda untuk bekerja melawan dimensi yang benar dari array yang diratakan.

Saya pribadi lebih menyukai sintaks numpy dari xH dan xT

Mudah diimplementasikan sekarang di 1.0, dan harus efisien:

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 

Ini sangat mudah dan rapi. Kelemahannya adalah penggunaan ortogonal dari getproperty tidak saling melengkapi. Jadi siapa pun yang mengimplementasikan getproperty pada tipe matriks spesifik mereka perlu mengimplementasikan perilaku generik dengan tangan.

penggunaan ortogonal dari getproperty tidak menulis

Hmm. Saya ingin tahu apakah itu menyiratkan xT "seharusnya" diturunkan menjadi getproperty(x, Val(:T)) . Saya bergidik memikirkan apa yang akan terjadi pada kompiler yang buruk.

Saya yakin setiap orang memiliki pendapat mereka - tetapi bagi saya itu hampir merupakan fitur yang sulit untuk membangun antarmuka generik dari sintaks titik. Jangan salah paham, ini adalah fitur yang sangat hebat dan luar biasa untuk mendefinisikan struct seperti tuple bernama, dan seterusnya.

(Dimungkinkan juga untuk menambahkan lapisan pengiriman Val ke tipe Anda dengan cukup mudah).

Kode @c42f berfungsi seperti pesona. Sayangnya bagi saya, saya mencoba menulis kode yang berfungsi pada versi 0.64 dan lebih tinggi, yang memaksa saya untuk menggunakan transpose atau fungsi yang saya definisikan sendiri T(A) = transpose(A). Mungkin makro akan sedikit lebih bersih dan sedikit lebih efisien.

Untuk lebih jelasnya, saya tidak menyarankan mendefinisikan getproperty khusus ini adalah ide yang bagus untuk kode pengguna. Itu hanya akan merusak sesuatu dalam jangka panjang ;-) Meskipun mungkin suatu hari kita akan memiliki perasaan yang cukup baik atas konsekuensi yang dapat kita definisikan x.T dalam Base .

Tetapi secara umum, saya bertanya-tanya mengapa penggunaan properti semacam ini untuk mendefinisikan "getter" di antarmuka generik sebenarnya buruk. Misalnya, fungsi pengambil bidang generik saat ini memiliki masalah namespace besar yang hanya diselesaikan dengan penggunaan getproperty secara bijaksana. Jauh lebih baik untuk menulis x.A daripada menulis MyModule.A(x) , beberapa nama fungsi yang lebih jelek seperti get_my_A(x) , atau mengekspor nama yang sangat umum A dari pengguna modul. Satu-satunya masalah seperti yang saya lihat, adalah kemampuan yang diharapkan untuk mengesampingkan arti .B untuk subtipe secara independen dari .A yang didefinisikan secara umum pada tipe super. Karenanya komentar setengah serius tentang Val .

Ide lucu:

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

Karakternya terlihat seperti T tetapi sebenarnya adalah ' dengan bilah di atasnya. Tidak yakin apakah serius...

screen shot 2018-09-10 at 11 29 56

Ya, menurut saya juga seperti itu di GitHub. Tapi itu overbar. Salin dan tempel ke acara terminal saya:

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

Terlalu pintar dan manis. Saya masih suka menggabungkan karakter, dan menurut saya 'ᵀ bagus.

-100 untuk mengubah adjoint, karena itu adalah salah satu hal luar biasa yang membuat penulisan kode Julia sejelas menulis matematika, ditambah transpos konjugasi biasanya adalah apa yang Anda inginkan, jadi masuk akal untuk memiliki sintaks yang disingkat untuk itu.

Ada arogansi tertentu untuk pernyataan seperti ini. Pertimbangkan bahwa beberapa pengembang terbatas secara eksplisit _tidak_ menginginkan adjoint() tetapi _need_ transpose() .

Kasus dan poin bagi kami bekerja dengan perhitungan simbolis untuk pemodelan default ' operator akan menyebabkan misalnya pseudo-invers (A'*A)\(A *b) atau bentuk kuadrat v'*A*v untuk kembali secara keliru hasil yang panjang dan kompleks yang tidak dapat dikurangi.

Mungkin solusinya adalah semacam arahan kompiler yang menyatakan arti dari ' .

Apakah halaman ini membantu?
0 / 5 - 0 peringkat