Julia: أخذ ناقل ينقل على محمل الجد

تم إنشاؤها على ١٠ نوفمبر ٢٠١٣  ·  417تعليقات  ·  مصدر: JuliaLang/julia

من @ alanedelman :

يجب علينا حقًا التفكير مليًا في الكيفية التي يجب أن يؤدي بها تبديل المتجه إلى إرسال طرق A_*op*_B* . يجب أن يكون من الممكن تجنب الأنواع الجديدة والرياضيات القبيحة. على سبيل المثال ، المتجه "المتجه الذي ينتج متجهًا (# 2472 ، # 2936) ، والمتجه" ينتج مصفوفة ، والمتجه "الذي ينتج عنه مصفوفة (# 2686) كلها رياضيات سيئة.

ما يناسبني رياضيًا (والذي يتجنب تقديم نوع جديد) هو أنه بالنسبة إلى البعد الواحد Vector v :

  • v' ليس عملية (أي إرجاع v ) ،
  • v'v أو v'*v هو عدد قياسي ،
  • v*v' مصفوفة و
  • v'A أو v'*A (حيث A AbstractMatrix ) هو ناقل

يعكس التحويل العام _N- الأبعاد ترتيب المؤشرات. يجب أن يكون المتجه ، الذي يحتوي على فهرس واحد ، ثابتًا أثناء النقل.

من الناحية العملية ، نادرًا ما يستخدم v' بمعزل عن الآخرين ، وعادة ما يتم مواجهته في منتجات متجه المصفوفة ومنتجات مصفوفة المصفوفة. قد يكون من الأمثلة الشائعة إنشاء نماذج ثنائية الخطوط v'A*w وأشكال تربيعية v'A*v التي تُستخدم في التدرجات المترافقة ، وحواجز رايلي ، إلخ.

السبب الوحيد لتقديم نوع Transpose{Vector} هو تمثيل الفرق بين المتجهات المتغيرة والمتغيرة ، وأنا لا أجد هذا مقنعًا بما فيه الكفاية.

arrays breaking design linear algebra

التعليق الأكثر فائدة

بام

ال 417 كومينتر

على سبيل المثال ، المتجه "المتجه الذي ينتج متجهًا (# 2472 ، # 2936) ، والمتجه" ينتج مصفوفة ، والمتجه "الذي ينتج عنه مصفوفة (# 2686) كلها رياضيات سيئة.

إن الازدواج المزدوج لمساحة متجهة ذات أبعاد محدودة متشابه معها ، وليس متطابقًا. لذا فأنا لست واضحًا بشأن مدى سوء هذه الرياضيات. والأكثر من ذلك أننا نميل إلى التستر على التمييز بين الأشياء المتشابهة في الرياضيات ، لأن أدمغة الإنسان جيدة في التعامل مع هذا النوع من الغموض الزلق وفعل الشيء الصحيح. بعد قولي هذا ، أوافق على أنه يجب تحسين هذا ، ولكن ليس لأنه غير صحيح رياضيًا ، بل لأنه مزعج.

كيف يمكن v' == v ، لكن v'*v != v*v ؟ هل من المنطقي أكثر مما كنا نظن أن يكون x' * y المشغل الخاص به؟

إن الازدواج المزدوج لمساحة متجهة ذات أبعاد محدودة متشابه معها ، وليس متطابقًا.

(أتحدث الآن باسمي) إنه ليس مجرد متماثل ، إنه متماثل بشكل طبيعي ، أي أن التماثل مستقل عن اختيار الأساس. لا يمكنني التفكير في تطبيق عملي يستحق التمييز بين هذا النوع من التماثل والهوية. IMO يأتي عامل الانزعاج من إجراء هذا النوع من التمييز.

هل من المنطقي أكثر مما كنا نظن أن يكون x' * y المشغل الخاص به؟

كان هذا هو الانطباع الذي خرجت به من مناقشة هذا المساء مع @ alanedelman.

أعتقد أن ما يطلبه جيف صحيح فيما يتعلق بالمال ... لقد بدأ يبدو مثل x'_y و x_y 'يحقق المزيد
أكثر من أي وقت مضى.

أنا في اتفاق عنيف معstefan. لم يكن المقصود من الرياضيات السيئة أن تعني ، الرياضيات الخاطئة ، كانت كذلك
من المفترض أن تعني الرياضيات المزعجة. هناك الكثير من الأشياء الصحيحة تقنيًا ، ولكنها ليست لطيفة جدًا ....

إذا اتبعنا هذا المنطق ، فإليك خيارين أمامنا

يبقى x_x خطأ ..... ربما مع اقتراح "ربما تريد استخدام النقطة"
أو x_x هو المنتج النقطي (لا أحب هذا الاختيار)

إذا كان x و x' هما نفس الشيء ، إذا كنت تريد أن يعني dot(x,y) (x')*y dot(x,y) فهذا يعني أن x*y هو أيضًا dot(x,y) . لا يوجد مخرج من ذلك. يمكننا أن نجعل x'y و x'*y عملية مختلفة ، لكنني لست متأكدًا من أن هذه فكرة رائعة. يريد الناس أن يكونوا قادرين على وضع هذا بين قوسين بالطريقة الواضحة وجعله يعمل.

أود أن أشير إلى أنه إذا سمحنا بدولار x*x يعني المنتج النقطي ، فلن يكون هناك عودة بشكل أساسي. سوف يتم وضع هذا في كود الناس في كل مكان والقضاء عليه سيكون كابوسًا. لذا ، التماثل الطبيعي أم لا ، هذه ليست رياضيات بحتة وعلينا التعامل مع حقيقة أن الأشياء المختلفة في الكمبيوتر مختلفة.

فيما يلي مناقشة عملية للتمييز بين "up tuples" و "down tuples" التي تعجبني:

http://mitpress.mit.edu/sites/default/files/titles/content/sicm/book-ZH-79.html#٪ _idx_3310

فهو يتجنب بحذر كلمات مثل "ناقل" و "مزدوج" ، ربما لتجنب إزعاج الناس. أجد تطبيق المشتقات الجزئية مقنعًا على الرغم من:

http://mitpress.mit.edu/sites/default/files/titles/content/sicm/book-ZH-79.html#٪ _sec_Temp_453

سبب آخر للتمييز بين M[1,:] و M[:,1] هو أن سلوك البث لدينا حاليًا يسمح بهذا السلوك الملائم للغاية: M./sum(M,1) هو مؤشر ستوكاستيك العمود و M./sum(M,2) هو صف عشوائي. . يمكن القيام بنفس الشيء للتطبيع إذا "أصلحنا" الوظيفة norm للسماح للتطبيق عبر الصفوف والأعمدة بسهولة. بالطبع ، لا يزال بإمكاننا الحصول على مصفوفات إرجاع sum(M,1) و sum(M,2) بدلاً من المتجهات لأعلى ولأسفل ، لكن هذا يبدو قليلاً.

أنا أحب فكرة ناقلات صعودا وهبوطا. تكمن المشكلة في تعميمها على أبعاد أعلى بطريقة ليست مجنونة تمامًا. أو يمكنك فقط جعل المتجهات حالة خاصة. لكن هذا شعور خاطئ أيضًا.

صحيح أن أعلى / أسفل قد تكون نظرية منفصلة. يبدو أن نهج التعميم هو بنية متداخلة تأخذ الأشياء في اتجاه مختلف. من المحتمل جدًا أن يكون هناك سبب لعدم تسميتها بالنواقل.

أيضًا ، سيجعل x*y = dot(x,y) * غير مترابط ، كما في x*(y*z) مقابل (x*y)*z . آمل حقًا أن نتمكن من تجنب ذلك.

نعم. بالنسبة لي ، هذا غير مقبول تمامًا. أعني تقنيًا أن النقطة العائمة * غير ارتباطية ، لكنها تقريبًا ترابطية ، في حين أن هذا سيكون غير ارتباطي بشكل صارخ.

نتفق جميعًا على أن x*x يجب ألا يكون المنتج النقطي.

يبقى السؤال ما إذا كان يمكننا التفكير في v'w و v'*w كمنتج نقطي -
أنا حقا أحب هذا العمل بهذه الطريقة.

JeffBezanson وأنا

الاقتراح هو ما يلي:

v' خطأ للمتجهات (هذا ما تفعله mathematica)
v'w و v'*w منتج نقطي (النتيجة = الحجمي)
v*w مصفوفة منتج خارجية (النتيجة = مصفوفة)

لا يوجد تمييز بين متجهات الصفوف والأعمدة. احببت هذا على اي حال
وكان سعيدًا برؤية سابقة الرياضيات
من mathematica: http://reference.wolfram.com/mathematica/tutorial/VectorsAndMatrices.html
نظرًا للطريقة التي تستخدم بها Mathematica القوائم لتمثيل المتجهات والمصفوفات ، فلن تضطر أبدًا إلى التمييز بين متجهات "الصف" و "العمود"

يجب أن يدرك المستخدمون أنه لا توجد نواقل صف .... فترة.

وبالتالي إذا كان M مصفوفة

M[1,:]*v خطأ ..... (بافتراض أننا نتعامل مع M[1,:] هو عدد قياسي
قد يقترح التحذير تجربة dot أو '* أو M[i:i,:]

M[[1],:]*v أو M[1:1,:]*v هو متجه بطول 1 (هذا هو سلوك جوليا الحالي على أي حال)

بخصوص المشكلة وثيقة الصلة في https://groups.google.com/forum/#!topic/julia -users / L3vPeZ7kews

تقوم Mathematica بضغط أقسام المصفوفة التي تشبه العددية:

m = Array[a, {2, 2, 2}] 


Out[49]= {{{a[1, 1, 1], a[1, 1, 2]}, {a[1, 2, 1], 
   a[1, 2, 2]}}, {{a[2, 1, 1], a[2, 1, 2]}, {a[2, 2, 1], a[2, 2, 2]}}}

In[123]:= Dimensions[m]
Dimensions[m[[All, 1, All]]]
Dimensions[m[[2, 1, All]]]
Dimensions[m[[2, 1 ;; 1, All]]]

Out[123]= {2, 2, 2}

Out[124]= {2, 2}

Out[125]= {2}

Out[126]= {1, 2}

[تحرير: تنسيق التعليمات البرمجية -StefanKarpinski]

تضمين التغريدة

بافتراض أننا نذهب مع M [1 ،:] هو عدد قياسي

تقصد أن M [1 ،:] مجرد متجه؟

نعم آسف. كان عقلي يعني أن M [1 ،:] كان يعالج العدد 1 :-)

تستخدم Mathematica الفترة . بدلاً من العلامة النجمية *
ثم يذهب إلى 9 ياردات كاملة ويجعل (متجه. متجه) في عددي ، بالضبط ما نتجنبه
بعلامة النجمة.

ليس هناك شك في العديد من المشاكل المتعلقة بهذه الفترة ، أحدها أنها ليست كذلك
تبدو مثل "النقطة" في المنتج النقطي ، والأخرى التي تتعارض معها
قراءة "نقطة العملية" للنقطة ،

يقدم Unicode بشكل رائع حرفًا يسمى "مشغل النقطة"
(char(8901)) الذي يمكننا تخيل تقديمه

لذلك يمكننا جعل (v ⋅ w) مرادفًا لـ (v'*w)

باختصار ، موضوع الاقتراح الحالي للمناقشة هو

  1. وبالتالي فإن الفهرسة العددية تقتل البعد
    A[i,:] متجه كما هو A[:,i,j]
  2. فهرسة المتجهات سميكة
    إرجاع A[ i:i , : ] أو A[ [i], : ] مصفوفة من صف واحد
  3. v'w أو v'*w هو المنتج النقطي للناقلات (وبالمثل v*w' للمنتج الخارجي)
  4. v' غير محدد للمتجهات (وجّه المستخدم إلى permutedims(v,1) ؟؟؟؟)
  5. يُرجع v*A متجهًا إذا كانت A مصفوفة
  6. يُرجع v⋅w أيضًا المنتج النقطي (لكنه لا يصل إلى حد . للرياضيات من خلال العمل على المصفوفات
  7. v*w غير معرّف للمتجهات لكن التحذير قد يوجه المستخدم بإقتراحات جيدة بما في ذلك

العواقب هي أن

أ. إذا التزمت بجميع المتجهات كونها متجهات عمود ، فإن كل شيء يعمل
ب. إذا جعلت كل شيء مصفوفة ، فكل شيء يعمل بالتأكيد ، ومن السهل جعل كل شيء مصفوفة
ج. إذا كان عقلك لا يستطيع تمييز متجه صف من مصفوفة صف واحد ، فمن المحتمل أنك ستتعلم
بأدب ورشاقة
د. هذا الترميز النقطي هو نوع من المتعة للعين

الاقتراح 5) يبدو غريبًا جدًا بالنسبة لي. أنا أفضل v'*A حتى يكون واضحًا أنك تستخدم المتجه الثنائي. هذا مهم بشكل خاص في المساحات المتجهية المعقدة حيث لا يكون الثنائي مجرد تحويل "شكل".

أريد أن أكرر صدى v وتسوية أعمدة المصفوفة A بواسطة هذه القيم؟ حاليًا ، يمكن للمرء استخدام A ./ v' . هذا لطيف للغاية لمعالجة البيانات.

أسئلة جيدة

لا يحول مخططي دون أخذ الاقتران المعقد لـ v والتعدد بواسطة A v'*A
وجميع الحالات المختلفة الأخرى التي لم أذكرها صراحة بعد ، لكنني أستطيع ذلك بسهولة

يمكننا القضاء على 5
ربما هذا مرغوب فيه
لا يتوافق مع قاعدة متجه العمود الخاص بي

هذا النهج في البث لطيف ومبهج
أحد الحلول الآن هو A ./ v[:,[1]]

لديها ميزة توثيق البعد الذي يتم بثه
ويعمم على المصفوفات ذات الأبعاد الأعلى

أوه ، والحل v[:,[1]] له فضيلة عدم أخذ المرافق المعقدة
وهو على الأرجح ما ينوي المستخدم .....

أحب هذين المثالين لأن الأول هو مثال للجبر الخطي
حيث يُطلب اقتران معقد كثيرًا ، ولكن المثال الثاني هو
مثال بيانات متعددة الأبعاد حيث نريد أن تعمل الأشياء في جميع الأبعاد
ليس فقط للمصفوفات ، ونحن على الأرجح لا نريد اقترانًا معقدًا

يتطلب # 552. هذه هي المرة الثالثة التي يتم عرضه فيها خلال الأسبوعين الماضيين.

سبب آخر للتمييز بين M [1 ،:] و M [:، 1] هو أن سلوك البث لدينا حاليًا يسمح بهذا السلوك المريح جدًا: M. /sum (M،1) هو عمود عشوائي و M. 2) غير عشوائي. يمكن القيام بالشيء نفسه للتطبيع إذا "أصلحنا" الوظيفة المعيارية للسماح بالتطبيق على الصفوف والأعمدة بسهولة. بالطبع ، لا يزال بإمكاننا الحصول على مصفوفات إرجاع مجموع (M ، 1) ومجموع (M ، 2) بدلاً من المتجهات لأعلى ولأسفل ، ولكن هذا يبدو بعيدًا بعض الشيء.

يبدو لي أنه بينما يكون سلوك البث أمرًا رائعًا في بعض الأحيان ، ينتهي بك الأمر إلى الضغط على وحدات التعتيم الإضافية هذه بنفس القدر. وبالتالي ، فإن الاضطرار إلى القيام بالعكس في بعض الأوقات أمر جيد إذا كان باقي النظام أجمل (وأعتقد أن إسقاط الأبعاد القياسية سيجعل النظام أجمل). وبالتالي سوف تحتاج إلى وظيفة مثل

julia> widen(A::AbstractArray,dim::Int) = reshape(A,insert!([size(A)...],dim,1)...)
# methods for generic function widen
widen(A::AbstractArray{T,N},dim::Int64) at none:1

والتي ستسمح برمز مثل M ./ widen(sum(M,2),2) أو A ./ widen(v,1) (انظر مثال blakejohnson أعلاه)

م [: ، 0 ،:] و v [: ، 0] ؟؟؟؟؟

أنا أكثر مع blakejohnson بشأن مسألة التخفيض ؛ أنا شخصياً أعتقد أنه من الواضح أن الأبعاد squeeze أكثر من widen لها. أظن أنني سأبحث دائمًا في المستندات لمعرفة ما إذا كان widen يُدرج البعد في الفهرس المشار إليه أو بعده ، وسيصبح الترقيم أكثر تعقيدًا إذا كنت تريد التوسيع على أبعاد متعددة في وقت واحد. (ما الذي يفعله widen(v, (1, 2)) للمتجه v ؟) لا شيء من هذه المشكلات لـ squeeze .

بغض النظر عما إذا كنا سنتوسع أو نضغط على الوضع الافتراضي ، أعتقد أن جوليا يجب أن تتبع زمام المبادرة من numpy عندما يتعلق الأمر بالتوسيع والسماح بشيء مثل v[:, newaxis] . لكنني أعتقد أنني أفضل الاحتفاظ بالأبعاد بدلاً من التخلص منها ، فمن الصعب اكتشاف خطأ حيث قمت عن طريق الخطأ بالتوسيع بطريقة خاطئة أكثر مما حدث عندما ضغطت بطريقة خاطئة (والتي عادةً ما تعطي خطأ).

في قائمة alanedelman
أشعر بذلك

تُرجع v * A متجهًا إذا كانت A مصفوفة

ليست جيدة.

يجب أن يكون v_A خطأ إذا لم يكن A 1x1 (عدم تطابق نطاق الفهرس)
يجب أن تكون v'_A هي الطريقة الصحيحة للقيام بذلك.

تتمثل إحدى طرق معالجة هذه المشكلة في تحويل المتجه v تلقائيًا إلى مصفوفة nx1 (عند الحاجة)
وتعامل دائمًا مع v 'كمصفوفة 1xn (لا تقم أبدًا بتحويل ذلك إلى متجه أو مصفوفة nx1)
كما نسمح بتحويل مصفوفة 1 × 1 تلقائيًا إلى رقم قشارة (عند الحاجة).

أشعر أن هذا يمثل طريقة متسقة وموحدة للتفكير في الجبر الخطي. (رياضيات جيدة)

هناك طريقة موحدة للتعامل مع كل هذه المشكلات وهي السماح بالتحويل التلقائي (النوع؟) (عند الحاجة)
بين مصفوفة الحجم (ن) ، (ن ، 1) ، (ن ، 1،1) ، (ن ، 1،1 ، 1) إلخ (ولكن ليس بين مصفوفات الحجم (ن ، 1) و (1 ، ن) )
(مثلما نقوم تلقائيًا بتحويل رقم حقيقي إلى رقم مركب عند الحاجة)

في هذه الحالة يمكن تحويل مصفوفة ذات حجم (1،1) إلى رقم (عند الحاجة) (انظر # 4797)

شياو جانج (فيزيائي)

هذا يترك v'_A ومع ذلك .... أريد حقًا v'_A * w للعمل

انطباعي عن الجبر الخطي في جوليا هو أنه منظم إلى حد كبير مثل جبر المصفوفة ، على الرغم من وجود المقاييس والمتجهات الحقيقية (التي أعتقد أنها جيدة!)

دعونا نفكر في كيفية التعامل مع منتج مثل x*y*z*w ، حيث قد يكون كل عامل عدديًا أو متجهًا أو مصفوفة ، ربما مع تبديل عليه. يحدد جبر المصفوفة حاصل ضرب المصفوفات ، حيث يكون حجم المصفوفة n x m . تتمثل إحدى الطرق في توسيع هذا التعريف بحيث يمكن استبدال n أو m بـ absent ، والذي سيكون بمثابة قيمة واحد فيما يتعلق بحساب المنتج ، ولكنها تستخدم للتمييز بين العددية والمتجهات من المصفوفات:

  • العدد القياسي سيكون absent x absent
  • سيكون المتجه (العمود) هو n x absent
  • سيكون متجه الصف absent x n

من الناحية المثالية ، نود ترتيب الأشياء بحيث لا نحتاج أبدًا إلى تمثيل متجهات الصفوف ، ولكن سيكون ذلك كافيًا لتنفيذ عمليات مثل x'*y و x*y' . لدي شعور بأن هذه هي نكهة المخطط الذي يبحث عنه الكثير منا.

لكنني بدأت أشك في أن حظر نواقل الصفوف في هذا النوع من المخططات سيكون بتكلفة عالية. مثال: ضع في اعتبارك كيف سنحتاج إلى وضع أقواس للمنتج لتجنب تشكيل متجه صف في أي خطوة وسيطة: ( a عددى ، u و v متجهات)

a*u'*v = a*(u'*v) // a*u' is forbidden
v*u'*a = (v*u')*a // u'*a is forbidden

لتقييم منتج x*y'*z مع تجنب إنتاج متجهات الصفوف ، سنحتاج إلى معرفة أنواع العوامل قبل اختيار ترتيب الضرب! إذا كان على المستخدم القيام بذلك بنفسه ، فإنه يبدو كعقبة أمام البرمجة العامة. ولست متأكدًا من كيفية قيام جوليا بذلك تلقائيًا بطريقة عاقلة.

سبب آخر لعدم إصلاح ترتيب الضرب مقدمًا: يبدو أنني أتذكر أن هناك فكرة لاستخدام البرمجة الديناميكية لاختيار ترتيب التقييم الأمثل وهو *(x,y,z,w) لتقليل عدد العمليات المطلوبة. من المحتمل أن يتداخل أي شيء نقوم به لتجنب تكوين متجهات الصف مع هذا.

لذا في الوقت الحالي ، يبدو أن إدخال نوع متجه منقول هو البديل الأكثر عقلانية بالنسبة لي. سيؤدي ذلك ، أو القيام بكل شيء كما هو الحال الآن ولكن إسقاط أبعاد مفردة لاحقة عند الاحتفاظ بها ، إلى حدوث خطأ.

التحويل هو مجرد طريقة خاصة لتبديل الأوضاع. إذا سمحت لـ v.' حيث يكون v متجهًا ، فيجب أن يُرجع permutedims(v,[2 1]) نفس الشيء بالضبط. إما أن يقوم كلاهما بإرجاع نوع متجه خاص للصف ، أو يقدم بعدًا جديدًا.

لا يبدو وجود نوع خاص لمتجهات الصف حلاً جيدًا بالنسبة لي ، لأن ما الذي ستفعله بشأن الأنواع الأخرى من متجهات mode-n ، على سبيل المثال ، permutedims([1:4],[3 2 1]) ؟ أحثك أيضًا على أخذ الجبر متعدد الخطوط في الاعتبار قبل اتخاذ أي قرار.

toivoh ذكر ذلك

"يتمثل أحد الأساليب في توسيع هذا التعريف بحيث يمكن الاستعاضة عن n أو m بـ" الغائب "، مما قد يعمل كقيمة واحد فيما يتعلق بحساب المنتج ، ولكنه يُستخدم للتمييز بين الحجمي والمتجهات من المصفوفات:

  1. سيكون العدد القياسي غائبًا عن x
  2. a (عمود) متجه سيكون nx غائبًا
  3. سيكون متجه الصف غير موجود xn "

في الجبر الخطي المتعدد (أو للموترات عالية الراند) ، فإن الاقتراح أعلاه يتوافق مع الاستخدام الغائب للتمثيل
العديد من مؤشرات النطاق 1 ، أي الحجم (م ، ن ، غائب) قد تتوافق مع (م ، ن) ، (م ، ن ، 1) ، (م ، ن ، 1،1) ، إلخ.

إذا استخدمنا هذا التفسير للغياب ، فعندئذٍ 1. و 2. لا بأس به ولطيف أن يكون لديك ، لكن 3. قد لا يكون جيدًا.
لا نريد خلط المصفوفات ذات الحجم (1، n) و (1،1، n).

لست متخصصًا في نظرية التنسور ، لكنني استخدمت جميع الأنظمة المذكورة أعلاه (_ بدون أي حزم إضافية) لمشاريع جوهرية تتضمن الجبر الخطي.

[TL؛ DR: تخطي إلى الملخص]

فيما يلي السيناريوهات الأكثر شيوعًا التي وجدت فيها حاجة إلى قدر أكبر من العمومية في معالجة الصفيف من عمليات متجه المصفوفة الشائعة:

(1) التحليل الوظيفي: على سبيل المثال ، بمجرد استخدام دالة Hessian لوظيفة ذات قيمة متجهية ، فإنك تحتاج إلى موترات ذات ترتيب أعلى للعمل. إذا كنت تكتب كثيرًا من الرياضيات ، فسيكون من الصعب للغاية استخدام قواعد خاصة لهذه الحالات.

(2) مراقبة التقييم: على سبيل المثال ، بالنظر إلى أي منتج يمكن حسابه ، يجب أن يكون المرء قادرًا على حساب أي كيان فرعي لذلك المنتج بشكل منفصل ، لأن المرء قد يرغب في دمجه مع كيانات فرعية متعددة مختلفة لتشكيل منتجات مختلفة. وبالتالي فإن قلق Toivo بشأن ، على سبيل المثال ، حظر a*u' ليس مجرد مشكلة تجميع ، بل هو اهتمام برمجي ؛ المتغير الأكثر شيوعًا هو الحوسبة المسبقة لـ x'Q لحساب النماذج التربيعية x'Q*y1 ، x'Q*y2 ، ... (حيث يجب أن يتم ذلك بالتتابع).

(3) تبسيط الكود: عدة مرات عند التعامل مع العمليات الحسابية التي تم تعيينها عبر مجموعات بيانات متعددة الأبعاد ، وجدت أنه يمكن استبدال 6-7 أسطر من التكرار الغامض أو كود تعيين الوظائف بواحدة أو اثنتين من عمليات الصفيف الموجزة في الأنظمة التي توفر عمومية مناسبة. أكثر قابلية للقراءة وأسرع بكثير.

فيما يلي تجربتي العامة مع الأنظمة المذكورة أعلاه:

MATLAB: اللغة الأساسية محدودة بما يتجاوز عمليات المصفوفة المتجهية الشائعة ، لذلك ينتهي الأمر عادةً بكتابة حلقات مع فهرسة.

NumPy: قدرة أكثر عمومية من MATLAB ، لكنها فوضوية ومعقدة. بالنسبة لكل حالة مشكلة غير بديهية تقريبًا ، كان علي أن أشير إلى التوثيق ، وحتى في ذلك الوقت وجدت أحيانًا أنه كان علي تنفيذ بعض عمليات المصفوفة بنفسي التي شعرت أنه كان يجب تحديدها بشكل بديهي. يبدو أن هناك العديد من الأفكار المنفصلة في النظام بحيث يواجه أي مستخدم ومطور مشكلة تلقائيًا في تخمين كيف سيفكر الآخر في شيء ما. عادة ما يكون من الممكن إيجاد طريقة قصيرة وفعالة للقيام بذلك ، ولكن هذه الطريقة ليست واضحة دائمًا للكاتب أو القارئ. على وجه الخصوص ، أشعر أن الحاجة إلى توسيع الأبعاد الفردية تعكس فقط الافتقار إلى العمومية في تنفيذ المشغلين التطبيقيين (على الرغم من أن البعض قد يجدها أكثر سهولة).

Mathematica: نظيف وعمومي جدًا - على وجه الخصوص ، تم تصميم جميع المشغلين ذوي الصلة مع وضع سلوك موتر عالي المستوى في الاعتبار. إلى جانب Dot ، انظر على سبيل المثال المستندات الخاصة بـ Transpose و Flatten / Partition و Inner / Outer. من خلال الجمع بين هذه العمليات فقط ، يمكنك بالفعل تغطية معظم حالات استخدام المصفوفة ، وفي الإصدار 9 ، تمت إضافة عمليات جبر موتر إضافية إلى اللغة الأساسية. الجانب السلبي هو أنه على الرغم من أن طريقة Mathematica لفعل شيء ما نظيفة ومعقولة (إذا كنت تعرف اللغة) ، فقد لا تتوافق بشكل واضح مع التدوين الرياضي المعتاد للقيام بذلك. وبالطبع فإن العمومية تجعل من الصعب معرفة كيفية أداء الكود.

scmutils: بالنسبة للتحليل الوظيفي ، فهو نظيف وعام ويوفر أكثر العمليات الحسابية بديهية (الكتابة والقراءة) من أي مما سبق. إن فكرة المجموعة لأعلى / لأسفل هي في الحقيقة مجرد امتداد أكثر اتساقًا وأكثر عمومية لما يفعله الناس غالبًا في الرياضيات المكتوبة باستخدام علامات التبديل ، واصطلاحات التمايز ، وغيرها من المفاهيم شبه الموحدة ؛ لكن كل شيء يعمل فقط. (لكتابة أطروحة الدكتوراه الخاصة بي ، انتهى بي الأمر إلى تطوير تدوين متسق لا لبس فيه يشبه تدوين الرياضيات التقليدي ولكنه متشابه في بناء جملة SICM الخاص بـ Sussman & Wisdom.) وقد استخدموه أيضًا لتطبيق الهندسة التفاضلية [1] ، والذي يحتوي على ألهم منفذ إلى SymPy [2]. لم أستخدمه لتحليل البيانات ، لكنني أتوقع أنه في سياق مصفوفة عام حيث أردت فقط نوعًا واحدًا من الصفوف (مثل قائمة الرياضيات) ، يمكنك فقط اختيار واحد ("up") حسب الاصطلاح. مرة أخرى ، يحجب التعميم اعتبارات الأداء بالنسبة للمبرمج ، لكنني آمل أن يكون هذا مجالًا يمكن أن تتفوق فيه جوليا.

ملخص

أعتقد أن النوع المتجه المنقول المقترح يجب أن يوصف بأنه المجموعة "لأسفل" الأكثر عمومية في scmutils ، بينما المتجهات العادية ستكون المجموعات "up". إن وصفهم بشيء مثل "ناقل" و "ناقل متجه" ربما يكون أكثر منطقية للناس من تسميتهم "لأعلى" و "لأسفل" (على حساب الإيجاز). هذا من شأنه أن يدعم ثلاث فئات من الاستخدام:

(1) لتحليل البيانات ، إذا كان الناس يريدون فقط المصفوفات المتداخلة ، فإنهم يحتاجون فقط إلى "المتجه" ؛
(2) بالنسبة للجبر الخطي المتجهي الأساسي ، يمكن للناس استخدام "المتجه" و "المتجه المنقول" في المراسلات المباشرة مع الاصطلاح الرياضي ("المصفوفة" ستكون مكافئة لـ "ناقل متجه" لـ "المتجه") ؛
(3) لعمليات الموتر الأعلى مرتبة (حيث يكون هناك توحيد أقل ويضطر الناس عادة إلى التفكير على أي حال) ، يجب أن يدعم التطبيق العمومية الكاملة للنظام الحسابي من النوعين.

أعتقد أن هذا النهج يعكس الإجماع الناشئ أعلاه لنتائج العمليات المختلفة ، باستثناء أن تلك الحالات التي اعتبرتها المنشورات السابقة أخطاء ( v' و v*A ) ستعطي في الواقع معنى (وغالبًا ما تكون مفيدة ) النتائج.

[1] http://dspace.mit.edu/handle/1721.1/30520
[2] http://krastanov.wordpress.com/diff-geometry-in-python/

يبدو أن thomasmcoffee كما لو كنت تنادي بالتمييز الصريح بين النواقل المشتركة والمتناقضة.

سأفكر في ذلك كتطبيق شائع ، لكنه محدد بشكل مفرط لما أدافع عنه: بالنسبة لي ، هذا له معنى هندسي يعني تقييدًا لمؤشرات الأرقام المستطيلة (للتمثيلات المنسقة). نظرًا لأنني أتخيل (بدون خبرة في هذا المجال) أن مكتبة مناسبة لوظائف جبر التنسور مع المصفوفات القياسية ستكون كافية عادةً لهذا الغرض ، فأنا أتعاطف مع وجهة نظر آلان القائلة بأن هذا وحده ليس مقنعًا بما يكفي لتقديم نظام من نوعين في اللغة الأساسية.

أنا أفكر بشكل أساسي في التطبيقات الأخرى التي تعتمد على بنية متداخلة أكثر عمومية ، على سبيل المثال ، حساب التفاضل والتكامل على وظائف الحجج المتعددة ذات الأبعاد المختلطة ، والتي سيكون من الصعب تطويرها كـ "إضافة" لاحقًا إذا لم تدعم اللغة الأساسية هذا التمييز. ربما نعني نفس الشيء.

تكمن مشكلة المتجهات لأعلى ولأسفل في أنك تحتاج إلى توسيع الفكرة لتشمل المصفوفات العامة. وبخلاف ذلك ، تصبح المتجهات شيئًا خاصًا ومنفصلة عن المصفوفات ، بدلاً من مجرد حالة ذات بعد واحد من المصفوفة ، مما قد يؤدي إلى فوضى كاملة من المشكلات الفظيعة. لقد فكرت كثيرًا في كيفية القيام بذلك ، لكنني لم أتوصل إلى أي شيء مقبول. إذا كان لديك أي أفكار جيدة حول كيفية التعميم السليم للمتجهات لأعلى ولأسفل على المصفوفات ، فأنا أحب سماعها.

مجرد محاولة استقراء هذه الفكرة. كما أفهمها ، من أجل استخدام مصفوفة لحساب المتجهات لأعلى ولأسفل ، تحتاج إلى الإشارة لكل بُعد سواء كان لأعلى أو لأسفل. بشكل عام ، يمكن تحقيق ذلك عن طريق لف مصفوفة في شيء مثل

immutable UpDownTensor{T, N, UPMASK} <: AbstractArray{T, N}
    A::AbstractArray{T, N}
end

حيث UPMASK سيكون قناعًا صغيرًا للإشارة إلى الأبعاد الموجودة. ثم يمكن تنفيذ العمليات على المصفوفات غير المغلفة من خلال توفير UPMASK افتراضيًا كدالة N : ستتجه المتجهات بشكل افتراضي إلى أعلى واحد ، والمصفوفات إلى الأولى للأعلى والثانية للأسفل ؛ ثم لست متأكدًا من كيفية استمراره بشكل معقول.

بعض الأفكار العشوائية:

  • هل يمكن تمثيل الأشكال التربيعية / ثنائية الخطوط بشكل أفضل من خلال بعدين سفليين؟
  • إذا كان التحويل يتوافق مع التقليب لأعلى / لأسفل لكل بُعد ، أعتقد أننا سنحصل أيضًا على نوع مصفوفة منقولة مع البعد الأول لأسفل والثاني لأعلى.
  • يمكن تمثيل الأنماط الأعلى التي تتوافق مع الإعداد الافتراضي مباشرةً بواسطة المصفوفة الأساسية بدلاً من تغليفها.

حسنًا ، هذا بالتأكيد تعميم واحد لنوع Transposed ، وله بالتأكيد بعض المزايا. لست متأكدا ما إذا كان ذلك ممكنا.

أعتقد أن اقتراح Toivo هو إدراك معقول لما كنت أدافع عنه أعلاه. بالنسبة لي ، فإن الوضع الافتراضي الأكثر منطقية هو الاستمرار في الاتجاهات المتناوبة في أوامر أعلى: على سبيل المثال ، إذا قدم شخص ما مكونات سلسلة الطاقة كمصفوفات غير مغلفة ، فإن هذا سيفعل الشيء الصحيح.

ولكن عند مزيد من التفكير ، أعتقد أنه قد يكون من القوي جدًا الجمع بين الفكرتين: (1) التمييز بين المتجهات لأعلى ولأسفل و (2) التمييز بين المصفوفات والمتجهات. ثم يمكن أن يكون لديك أشياء حيث تكون بعض الأبعاد مرتفعة ، وبعضها أسفل ، والبعض الآخر "محايد". السبب في التمييز بين المصفوفات والمتجهات هو أن المصفوفات ، من الناحية اللغوية ، مخصصة للتنظيم (تجميع أشياء متعددة من نفس الأنواع) ، في حين أن المتجهات مخصصة للتنسيق (تمثل مساحات متعددة الأبعاد). تكمن قوة الجمع بين كلا التمييزين في كائن واحد في أنه يمكن أن يخدم كلا الغرضين في وقت واحد. سيتم التعامل مع الأبعاد المحايدة وفقًا لقواعد البث ، في حين سيتم التعامل مع الأبعاد الأعلى / الأسفل وفقًا لقواعد حساب الموتر.

بالعودة إلى مثال سابق لي ، لنفترض أنك تحسب عددًا من النماذج التربيعية x'Q*y1, x'Q*y2, ... لمتجهات مختلفة y1, y2, ... . بعد SICM ، قم بالإشارة إلى مجموعات (ناقلات الأعمدة) بمقدار (...) و down tuples (متجهات الصفوف) بواسطة [...] . إذا كنت ترغب في القيام بذلك كله مرة واحدة ، وكنت عالقًا مع up / down فقط ، فستكون الطريقة التقليدية هي دمج yi في مصفوفة Y = [y1, y2, ...] باستخدام مجموعة down (من up tuples) ، واحسب r = x'Q*Y ، مما يمنحك النتائج في مجموعة down tuple r . ولكن ماذا لو كنت تريد ضرب كل من هذه النتائج في متجه (عمود) v ؟ لا يمكنك عمل r*v ، لأنك ستحصل على انكماش (منتج نقطي). يمكنك تحويل r إلى مجموعة up ، ثم الضرب ، مما يعطيك نتائجك في مجموعة up (من up tuples). لكن افترض أنك بحاجة إلى tuple لأسفل في الخطوة التالية؟ من الناحية الدلالية ، لديك بُعد يمر عبر حساباتك ويمثل مجموعة من الأشياء التي تريد بثها دائمًا ؛ ولكن لتحقيق ذلك في عالم أعلى / أسفل بشكل صارم ، عليك الاستمرار في إجراء تحويلات عشوائية تعتمد على السياق لاستنباط السلوك الصحيح.

في المقابل ، افترض أن لديك أيضًا مجموعات محايدة (صفائف) ، يُشار إليها {...} . ثم تكتب بشكل طبيعي ys = {y1, y2, ...} كمصفوفة (من مجموعات up) ، بحيث يكون r = x'Q*ys مصفوفة ، و r*v أيضًا مصفوفة (من مجموعات up). كل شيء منطقي ، ولا حاجة إلى تحويلات تعسفية.

يقترح ستيفان أن تمييز المصفوفات 1-D عن المتجهات لأعلى / لأسفل أمر كارثي ، لكنني أعتقد أن هذه المشكلة يتم حلها من خلال حقيقة أن معظم الوظائف لها معنى عندما تعمل على المتجهات _ أو_ على المصفوفات ، ولكن ليس _ أيهما_. (أو ، على المصفوفات _ أو_ على مصفوفات المتجهات _ أو_ على متجهات المصفوفات _ أو_ على مصفوفات المصفوفات ، ولكن ليس _either_. وهكذا.) لذا مع قواعد التحويل المناسبة ، لم أفكر في حالة شائعة لن تفيد الشيء الصحيح تلقائيًا. ربما شخص ما يستطيع؟

عند البحث بشكل أعمق [1] ، اكتشفت أن scmutils يميز في الواقع ما يسمونه "النواقل" من المجموعات الأعلى والأسفل تحت الغطاء ؛ ولكن يتم حاليًا إعداد قواعد التحويل بحيث يتم تعيين هذه "المتجهات" إلى مجموعات تصل إلى مجموعات (كما اقترحت سابقًا) كلما دخلوا إلى العالم لأعلى / لأسفل ، مع التحذير "نحتفظ بالحق في تغيير هذا التنفيذ للتمييز نواقل النظام من مجموعات up ". (ربما يمكن لشخص ما في الحرم الجامعي أن يسأل GJS عما إذا كان لديه أي أفكار محددة في الاعتبار.) نظام Sage [2] يفصل إلى حد كبير التعامل مع المصفوفات من المتجهات والمصفوفات (حاليًا لا يوجد دعم أساسي للموترات) ، والمشكلات الوحيدة التي واجهتها مع هذا يتعلق بافتقاره للتحويل المدمج بينهما في الحالات التي من الواضح أنها منطقية.

[1] http://groups.csail.mit.edu/mac/users/gjs/6946/refman.txt --- بدءًا من "الكائنات الهيكلية"
[2] http://www.sagemath.org/

كنت أتحدث إلى jiahao على مائدة الغداء وذكر أن فريق جوليا كان يحاول معرفة كيفية تعميم عمليات الجبر الخطي على مصفوفات ذات أبعاد أعلى. قبل عامين قضيت عدة أشهر في التفكير في هذا لأنني كنت بحاجة إليه من أجل KroneckerBio. كنت أرغب في مشاركة مقاربتي.

لنفكر فقط في حاصل الضرب بين مصفوفتين في الوقت الحالي. عمليات أخرى لها نفس التعميم. الأنواع الثلاثة الأكثر شيوعًا للمنتجات عند التعامل مع المصفوفات هي المنتج الخارجي والمنتج الداخلي والمنتج elementwise. عادة ما نفكر في إجراء عمليات مثل هذه بين كائنين ، مثل inner(A,B) أو A*B . عند القيام بهذه العمليات على مصفوفات ذات أبعاد أعلى ، فإنها لا تتم بين المصفوفات ككل ، ولكن بين أبعاد معينة من المصفوفات. تحدث عمليات فرعية خارجية / داخلية / عنصرية متعددة في عملية واحدة بين مصفوفتين ويجب تعيين كل بُعد من كل مجموعة لعملية فرعية واحدة بالضبط (إما بشكل صريح أو افتراضي). بالنسبة للمنتجات الداخلية والعناصر ، يجب إقران بُعد واحد على اليسار بأبعاد متساوية الحجم على اليمين. لا يجب إقران أبعاد المنتج الخارجية. في معظم الأوقات ، يقوم المستخدم إما بمنتج داخلي أو منتج عنصري بين زوج من الأبعاد ومنتج خارجي لجميع الآخرين. يُعد المنتج الخارجي افتراضيًا جيدًا لأنه الأكثر شيوعًا ولا يلزم إقرانه.

عادةً ما أفكر في الأبعاد على أنها تسمية بدلاً من ترتيبها ، تمامًا مثل محاور x و y و z للمخطط. ولكن إذا كنت تريد أن يتمكن المستخدمون فعليًا من الوصول إلى المصفوفات عن طريق الفهرسة المطلوبة (مثل A[1,2,5] بدلاً من A[a1=1, a3=5, a2=2] ) ، فيجب أن يكون لديك إجراء ثابت لطلب نتائج العملية. أقترح ترتيب النتيجة من خلال سرد جميع أبعاد المصفوفة الأولى متبوعة بسرد جميع أبعاد المصفوفة الثانية. يتم تقليص أي أبعاد شاركت في منتج داخلي ، وبالنسبة للأبعاد التي شاركت في منتج عنصري ، يتم ضغط البعد من المصفوفة الثانية فقط.

سأقوم بتدوين بعض الرموز لهذا. لا تتردد في Juliafy ذلك. اجعل A مصفوفة تتكون من a1 بواسطة a2 a3 و اجعل B مصفوفة تساوي b1 بمقدار b2 . لنفترض أن array_product(A, B, inner=[2, 1], elementwise=[3, 2]) سيأخذ المنتج الداخلي بين الأبعاد a2 و b1 ، المنتج elementwise بين a3 و b2 ، و المنتج الخارجي a1 . ستكون النتيجة مصفوفة a1 a3 .

يجب أن يكون واضحًا أنه لا يوجد عامل ثنائي أو وحيد سيكون له معنى كبير في سياق المصفوفات ذات الأبعاد الأعلى. أنت بحاجة إلى أكثر من وسيطين لتحديد ما يجب فعله بكل بُعد. ومع ذلك ، يمكنك استعادة سهولة الجبر الخطي عن طريق جعل مشغلي Matlab اختصارًا لعمليات المصفوفة على البعدين الأولين فقط:

ماتلاب A*B هو array_product(A, B, inner=[2,1]) .

Matlab A.' هو permute(A, B, [2,1]) حيث يبقى التباين دون تغيير جميع الأبعاد أعلى من عدد الوسيطة الثالثة.

يمكنك اختيار ما إذا كنت تريد رمي الأخطاء أم لا عندما تكون أبعاد المصفوفات أكبر من 2 أو حتى لا تساوي 2 ، كما تفعل Mathematica مع عمليات النقل المتجه. إذا كنت تستخدم حسابات المصفوفات العامة فقط ، فليس عليك أن تقرر ما إذا كنت ستأخذ اقتراحwenxgwen ، لأن هناك القليل من الجوانب السلبية في اللغة المكتوبة ديناميكيًا.

لقد كتبت وصفًا أكثر

شكرا للمنظور! لقد وجدت هذا مفيدًا للغاية لفهم نوع الوحش الذي يمثله منتج مصفوفة * عامة.

قد يكون من المثير للاهتمام إجراء إسناد ترافقي لمقترحات مضاعفة المصفوفة متعددة الأبعاد مع الدلالات المقترحة لمشغل ضرب المصفوفة في PEP 0465 . خاصه:

يتم ترقية مدخلات المتجه 1d إلى 2d عن طريق إلحاق "1" مسبقًا أو إلحاقه بالشكل ، ويتم تنفيذ العملية ، ثم تتم إزالة البعد الإضافي من الإخراج. يُضاف الرقم 1 دائمًا إلى "الخارج" للشكل: مُسبقًا للوسيطات اليسرى ، وإلحاقه بالوسيطات اليمنى. والنتيجة هي أن المصفوفة @ المتجه والمتجه @ المصفوفة كلاهما قانوني (بافتراض أشكال متوافقة) ، وكلاهما يعيد متجهات 1d ترجع vector @ vector رقماً قياسياً ... إن عدم ملاءمة هذا التعريف للمتجهات 1d هو أنها تجعل @ غير ترابطي في بعض الحالات ((Mat1 @ vec) @ Mat2! = Mat1 @ (vec @ Mat2)). ولكن يبدو أن هذه حالة يتفوق فيها التطبيق العملي على النقاء

تتسبب الكتابة البطيئة في بايثون في مشكلة خاصة. بطبيعة الحال ، يجب أن تكون المصفوفات والمصفوفات قابلة للتبادل (نفس البيانات الأساسية). ولكن نظرًا لأن بايثون لا تشجع على فحص النوع ، لا يتم إرسال المصفوفات إلى الواجهة الصحيحة في بداية دالة تتوقع مصفوفة والعكس صحيح. هذا هو السبب في أنه يجب أن يكون لديهم أحرف عامل مختلفة. جوليا مع التحقق من نوع وقت التشغيل و convert لا تعاني من هذا الغموض.

من PEP 0465:

إن عدم ملاءمة هذا التعريف للمتجهات 1d هو أنه يجعل @ غير ترابطي في بعض الحالات ((Mat1 @ vec) @ Mat2! = Mat1 @ (vec @ Mat2))

بشكل ملحوظ ، يمكن أن ينتج عن هذا النوع من التعريف نتائج غير صحيحة في Mathematica ، لأن Dot ( . ) يُفترض أنه ارتباط ( Flat ) عند تقييمه بشكل رمزي (كما هو الحال مع f أدناه ، ولكن ليس بـ g ):

In[1]:= f=X.(y.Z);
g:=X.(y.Z)

In[3]:= Block[{
X=Array[a,{2,2}],
y=Array[b,2],
Z=Array[c,{2,2}]
},{f,g}]

Out[3]= {{(a[1,1] b[1]+a[1,2] b[2]) c[1,1]+(a[2,1] b[1]+a[2,2] b[2]) c[2,1],(a[1,1] b[1]+a[1,2] b[2]) c[1,2]+(a[2,1] b[1]+a[2,2] b[2]) c[2,2]},{a[1,1] (b[1] c[1,1]+b[2] c[2,1])+a[1,2] (b[1] c[1,2]+b[2] c[2,2]),a[2,1] (b[1] c[1,1]+b[2] c[2,1])+a[2,2] (b[1] c[1,2]+b[2] c[2,2])}}

In[4]:= SameQ@@Expand[%]
Out[4]= False

من drhagen :

جوليا مع التحقق من نوع وقت التشغيل وطرق convert لا تعاني من هذا الغموض.

هذا هو سبب شعوري بالحل الصحيح لـ Julia _should_ السماح للبيانات نفسها بالتمييز بين الدلالات الشبيهة بالصفيف (للبث الشامل) والدلالات الشبيهة بالتوتر (للتقلص المحتمل).

أنا لست سلطة هنا بأي حال من الأحوال ، لكنني لا أعتقد أن نوع التجميع التعسفي-الأبعاد العام ( Array ) يجب أن يدعم عاملًا يقوم بعمل نقطي. لا يمكن تعريف هذا المشغل بشكل معقول لهذا النوع لأن المنتج النقطي يمكن أن يكون بين أي بعدين ، مما يتطلب وسيطات إضافية لا يمكن توفيرها لمشغل ثنائي. ينطبق الأمر نفسه على جميع عمليات الجبر الخطي ، inv ، transpose ، إلخ.

للعمل في المجال الرياضي للجبر الخطي ، يجب أن يكون هناك ثلاثة أنواع أخرى ، Matrix ، ColumnVector ، و RowVector ، والتي فيها جميع عوامل ووظائف الجبر الخطي العادي العمل كالمعتاد.

الآن بعد أن تم تحديد بنية النوع جيدًا ، يمكنك تسهيل الأمر على المستخدم عن طريق إضافة تحويل ضمني لـ Matrix إلى Array{2} ، ColumnVector إلى Array{1} ، و RowVector إلى Array{2} (لست متأكدًا من ذلك) ، Array{2} إلى Matrix و Array{1} إلى ColumnVector .

يسمح اقتراحي أعلاه (https://github.com/JuliaLang/julia/issues/4774#issuecomment-32705055) لكل بُعد من أبعاد بنية متعددة الأبعاد بتمييز ما إذا كان يحتوي على محايد ("مجموعة" / "مجموعة") ، أو أعلى (" العمود ") ، أو لأسفل (" الصف ") دلالات. أعتقد أن ما تصفه هو حالة خاصة.

تتمثل ميزة هذا النهج العام في أنه حتى في العمليات الحسابية ذات أبعاد البيانات أو المساحة المتعددة ، يمكنك جعل المشغلين يفعلون الشيء الصحيح دون تحديد الأبعاد التي يجب أن يعملوا عليها بشكل صريح. أعتقد أننا نتفق على أنه ، على الأقل في جوليا ، من الأسهل بكثير للمستخدم أن يحدد مرة واحدة معنى بيانات الإدخال عن طريق اختيار معلمات النوع ، بدلاً من الاضطرار إلى تحديد معنى كل عملية من خلال استدعاء كل مثيل بـ حجج إضافية تعطي مؤشرات الأبعاد. لا يزال من الممكن استخدام التحويلات الضمنية أو الصريحة ، بتعميم كامل الأبعاد ، في الحالات التي يجب فيها تغيير المعنى في منتصف الطريق بطرق غير معتادة.

thomasmcoffee أنا أحب

  1. يعتبر مفهوم الثنائيات كمتميز أمرًا حيويًا لأي دلالات منطقية متسقة مع الذات.
  2. إن التطبيق المخصص لجبر الموتر باستخدام عوامل تشغيل ذات معلمات (أو أي شيء خارجي عن البيانات المتعلقة بهذه المسألة) هو أمر غير سار من الناحية الجمالية.

كانت أكبر الشكاوى التي تلقيتها في ذلك الوقت (وكانت بصوت عالٍ) تتعلق بالضبط بنوع الإزعاج الذي تحله دلالاتك الثلاثية (إضافة فكرة مجموعة محايدة). لطيف! لم تخطر ببالي هذه الفكرة أبدًا ، لكنها أصبحت منطقية جدًا الآن لدرجة أنك وضعتها هناك. أود حقًا استخدام مثل هذا النظام ، وأعني العمل الحقيقي. سيكون من الجميل أن تستوعب جوليا هذا!

يبدو أن ما تصفه يا رفاق هو الموترات العادية. أشك في أن هذه حالة استخدام شائعة بدرجة كافية وحدها لتبرير التواجد في المكتبة القياسية ، حيث إن حالتي الاستخدام الأخريين (المجموعات والجبر الخطي) أكثر شيوعًا. ومع ذلك ، إذا كان من الممكن دمجها بسلاسة ، فسأدعمها. هل يمكنك إعطاء بعض الأمثلة لما قد تبدو عليه بعض العمليات الشائعة في ظل هذا النظام ، مثل ضرب المصفوفة المتجهة ، وضرب المصفوفة العددية ، وتوزيع إضافة مصفوفة واحدة على مصفوفة من المصفوفات ، وما إلى ذلك؟

أعتقد أنك على حق يا ديفيد. نحن نتحدث حقًا عن حالتي استخدام.

يحتاج معظم الناس مثلك إلى المجموعة الفرعية من الجبر الخطي
قل. حتى هناك أنا أدعو إلى الحفاظ على التمييز بين v و v.

ما أريده حقًا (أدخل الكشف عن الجشع هنا) هو Tensors
حالة من الدرجة الأولى (أو قريبة) ... بالقرب من السرعة الأصلية (في الحالة المحدودة ،
مقارنة بأداء الجبر الخطي) مع تركيب سهل ، بدون إجهاد
مشكلات في الكتابة ، مع تشفير / تناقض مشترك في البيانات ، وليس ملزمين
المشغلين. بمجرد تحديد دلالات البيانات ، يجب أن تكون العمليات
فقط اعمل. بطة تنسورال الكتابة.

ربما تنتمي الموترات و TDT في حزمة وليست جوهرية ، فقط في
أسباب الشعبية النسبية. ولكن مثل إعلان جوليا
يقول الاستقلال ، ولدت جوليا من الجشع. ومثلما يقول جوردون جيكو ،
الطمع شيء جيد. :)
في 21 آذار (مارس) 2014 ، الساعة 3:14 صباحًا ، كتب "David Hagen" [email protected] :

يبدو أن ما تصفه يا رفاق هو الموترات العادية. أشك في أن هذا هو
حالة الاستخدام الشائعة بدرجة كافية وحدها لتبرير التواجد في المكتبة القياسية ، مثل
حالتي الاستخدام الأخريين (المجموعات والجبر الخطي) أكثر بكثير
مشترك. ومع ذلك ، إذا كان من الممكن دمجها بسلاسة ، فسأدعمها.
هل يمكنك إعطاء بعض الأمثلة لما ستبدو عليه بعض العمليات الشائعة
تحت هذا النظام ، مثل مضاعفة المصفوفة المتجهية ، المصفوفة العددية
الضرب ، وتوزيع جمع مجموعة واحدة على مجموعة من
المصفوفات ، وما إلى ذلك؟

قم بالرد على هذه الرسالة الإلكترونية مباشرة أو tHubhttps: //github.com/JuliaLang/julia/issues/4774#issuecomment -38262998
.

أعتقد أن التكامل السلس يمكن تحقيقه بالتأكيد بالنظر إلى عائلة غنية بدرجة كافية. بتوسيع https://github.com/JuliaLang/julia/issues/4774#issuecomment -32693110 أعلاه ، قد يبدأ بشكل افتراضي مثل هذا:

immutable AbstractTensorArray{T, N, UPMASK, DOWNMASK} <: AbstractArray{T, N}
    A::AbstractArray{T, N}
end
# where !any(UPMASK & DOWNMASK)

typealias AbstractColumnVector{T} AbstractTensorArray{T, 1, [true], [false]}
typealias AbstractRowVector{T} AbstractTensorArray{T, 1, [false], [true]}
typealias AbstractMatrix{T} AbstractTensorArray{T, 2, [false, true], [true, false]}

(حاليًا AbstractMatrix{T} ببساطة الأسماء المستعارة AbstractArray{T, 2} ؛ من المحتمل أن يتم استخدام اسم آخر هنا)

من هنا تبدو التطبيقات التالية منطقية:

  1. طريقة transpose المعممة ، بعد إعادة ترتيب الأبعاد ومؤشرات UPMASK و DOWNMASK المقابلة ، ثم تقوم بتبادل UPMASK و DOWNMASK. لن تتأثر الأبعاد المحايدة.
  2. عادةً ما يتم تحويل أي أنواع فرعية من AbstractArray{T, N} افتراضيًا إلى الأنواع الفرعية المتناوبة AbstractTensorArray{T, N, [..., false, true, false, true], [..., true, false, true, false]} في عمليات الموتر. هذا يحافظ على الدلالات الموجودة في بناء جملة مصفوفة جوليا الخاصة للمتجهات والمصفوفات.
  3. يتم استخدام طريقة المُنشئ (على سبيل المثال ، array ) مقابل AbstractTensorArray لإنتاج أبعاد محايدة ، ويمكن دمج AbstractTensorArray s الأخرى (أو الأنواع القابلة للتحويل إليها) لإنشاء AbstractTensorArray مع بُعد محايد من المستوى الأعلى.

النظر في أمثلة drhagen :

مضاعفة المصفوفة المتجهات ، الضرب بالمصفوفة العددية

c = 1               # Int
v = [1, 2]          # Array{Int, 1}
M = [[1, 2] [3, 4]] # Array{Int, 2}

# scalar-array
c * M               # UNCHANGED: *(Int, Array{Int, 2}) => Array{Int, 2}

# matrix-vector
M * v               # *(Array{Int, 2}, Array{Int, 1}) => *(Matrix{Int}, ColumnVector{Int}) => ColumnVector{Int}

# vector-matrix
v' * M              # transpose(Array{Int, 1}) => transpose(ColumnVector{Int}) => RowVector{Int}
                    # *(RowVector{Int}, Array{Int, 2}) => *(RowVector{Int}, Matrix{Int}) => RowVector{Int}

# (1-array)-(2-array)
v .* M              # UNCHANGED: .*(Array{Int, 1}, Array{Int, 2}) => Array{Int, 2}

(باستخدام Matrix مع تعريف مطابق لتعريف AbstractMatrix أعلاه)

توزيع إضافة مصفوفة واحدة على مصفوفة من المصفوفات

أعتبر هذا يعني ، من الناحية الدلالية ، إضافة متجه واحد على مصفوفة من المتجهات ، إضافة مصفوفة واحدة على مصفوفة من المصفوفات ، وما إلى ذلك:

# vector-(vector-array)
ws = array([1, 2], [3, 4])
                    # TensorArray{Int, 2, [false, true], [false, false]}
v + ws              # +(Array{Int, 1}, TensorArray{Int, 2, [false, true], [false, false]}) => +(ColumnVector{Int}, TensorArray{Int, 2, [false, true], [false, false]}) => TensorArray{Int, 2, [false, true], [false, false]}
# => array([2, 4], [4, 6])

# array-(vector-array)
u = array(1, 2)     # TensorArray{Int, 1, [false], [false]}
u + ws              # +(TensorArray{Int, 1, [false], [false]}, TensorArray{Int, 2, [false, true], [false, false]}) => TensorArray{Int, 2, [false, true], [false, false]}
# => array([2, 3], [5, 6])
# alternatively:
v .+ ws             # .+(Array{Int, 1}, TensorArray{Int, 2, [false, true], [false, false]}) => TensorArray{Int, 2, [false, true], [false, false]}
# => array([2, 3], [5, 6])
# same effect, but meaning less clear:
v .+ M              # UNCHANGED: .+(Array{Int, 1}, Array{Int, 2}) => Array{Int, 2}
# => [[2, 4] [4, 6]]

# matrix-(matrix-array)
Ns = array([[1, 2] [3, 4]], [[5, 6] [7, 8]])
                    # TensorArray{Int, 2, [false, false, true], [false, true, false]}
M + Ns              # +(Array{Int, 2}, TensorArray{Int, 2, [false, false, true], [false, true, false]}) => +(Matrix{Int}, TensorArray{Int, 2, [false, false, true], [false, true, false]}) => TensorArray{Int, 2, [false, false, true], [false, true, false]}
# => array([[2, 4] [6, 8]], [[6, 8] [10, 12]])

بالنظر إلى المثال السابق الذي قدمته حول قياس المتجه v بواسطة عدة أشكال تربيعية مختلفة x'M*w1, x'M*w2, ... ، للحصول على نتيجة نهائية x'M*w1*v, x'M*w2*v, ... :

x = v
x' * M * ws * v     # *(RowVector{Int}, Array{Int, 2}) => *(RowVector{Int}, Matrix{Int}) => RowVector{Int}
                    # *(RowVector{Int}, TensorArray{Int, 2, [false, true], [false, false]}) => TensorArray{Int, 1, [false], [false]}
                    # *(TensorArray{Int, 1, [false], [false]}, Array{Int, 1}) => *(TensorArray{Int, 1, [false], [false]}, ColumnVector{Int}) => TensorArray{Int, 1, [false, true], [false, false]}
# => array([27, 54], [59, 118])

في هذا التطبيق النظري ، افترضت أن AbstractArray تُرك وشأنه ، وبالتالي فإن AbstractTensorArray يشكل "مساحته" الخاصة في التسلسل الهرمي للنوع. يمكن تبسيط الأمور إذا تم استبدال عائلة AbstractArray بأكملها ببساطة بـ AbstractTensorArray ، لكن هذه مناقشة أخرى.

في سياق حزمة لشيء ما في فيزياء الكم ، كنت ألعب بتحديد نوع الموتر الخاص بي (في الواقع أكثر من نوع واحد). في البداية ، كان لدي أيضًا فكرة عن المؤشرات تأتي في نسختين (أعلى وأسفل ، وارد وصادر ، متغير ومخالف ، كيفما تريد تسميته) ، مع تخزين هذه المعلومات إما في حقل في النوع أو حتى في اكتب المعلمة. بعد فترة ، قررت أن هذا مجرد مشكلة كبيرة. من الأسهل بكثير ربط مؤشرات الموتر بمساحة متجهية (وهو ما كنت أقوم به بالفعل على أي حال) والسماح لمساحة المتجه هذه بأن يكون لها ثنائي مختلف. عمليًا ، من خلال فضاء المتجه ، أعني فقط نوع جوليا البسيط الذي يلف أبعاد الفضاء وما إذا كان ثنائيًا أم لا. إذا كان فهرس الموتر مرتبطًا بمساحة متجه عادية ، فهو مؤشر صعودي ، وإذا كان مرتبطًا بمؤشر مزدوج ، فهو مؤشر هبوط. هل تريد العمل مع الموترات / المصفوفات التي لا يوجد تمييز لها ، ما عليك سوى تحديد نوع فضاء متجه مختلف لا يميز بين فضاء المتجه العادي وثنائي.

في هذا الاقتراح ، يمكنك فقط التعاقد مع مؤشرات الموتر المرتبطة بمساحات المتجهات التي تكون ثنائية بعضها البعض. ctranspose (= اقتران Hermitian) يرسم مساحة المتجه لكل فهرس على ثنائيته (جنبًا إلى جنب مع تبديل المؤشرات في حالة المصفوفة ، وتعريف مفضل للموترات ذات الترتيب الأعلى) إلخ.

بالطبع ، لم يتم تعريف التحويل الطبيعي والاقتران المعقد جيدًا في هذا الإعداد (أي أن هذه ليست مفاهيم أساسية مستقلة)

في أضيق الحدود ، يبدو شيئًا كالتالي:

immutable Space
    dim::Int
    dual::Bool
end
Space(dim::Int)=Space(dim,false) # assume normal vector space by default
dual(s::Space)=Space(s.dim,!s.dual)

matrix=Tensor((Space(3),dual(Space(5))))
# size is no longer sufficient to characterise the tensor and needs to be replaced by space
space(matrix) # returns (Space(3),dual(Space(5))) 
space(matrix') # returns (Space(5),dual(Space(3)))

بالطبع ، يمكنك اختراع بعض النحو حتى لا تضطر إلى كتابة الفضاء باستمرار. يمكنك إنشاء نوع فضاء مختلف يكون فيه الثنائي (الثنائيات) == s من أجل الحصول على موترات لا تميز بين المؤشرات الأعلى والأسفل ، وما إلى ذلك. ولكن بالطبع لا توجد طريقة يمكن دمجها في نوع Array القياسي لجوليا دون كسر كل شيء ...

لطالما تساءلت عن سبب عدم وجود علاقة أوثق بين كيفية استخدام الموترات في الهندسة / الفيزياء وكيفية التعامل معها في البرامج الرياضية. لقد وجدت محادثة تبادل مكدس مثيرة للاهتمام حول هذا الموضوع ... http://math.stackexchange.com/questions/412423/differences-between-a-matrix-and-a-tensor. هنا ، أيضًا ، كان منشورًا مرجعيًا جيدًا.
http://www.mat.univie.ac.at/~neum/physfaq/topics/tensors

أستخدم Matlab كثيرًا في عمليات الحوسبة العلمية اليومية ، لكنني مبتدئ في Julia. هنا ، لاحظت أن هناك الكثير من المناقشات حول مضاعفة المصفوفة عالية الأبعاد ونقلها أو غيرها من عمليات المصفوفات المماثلة. أقترح إلقاء نظرة على http://www.mathworks.com/matlabcentral/fileexchange/8773-multiple-matrix-multiplications--with-array-expansion-enabled

يتبع بشكل أساسي بناء الجملة المشابه لما ذكرهdrhagen في منشور سابق ، مثل array_product (A، B، inner_A_dim = [1، 2]، inner_B_dim = [3، 4]) لمنتج بين المصفوفتين A و B على الأبعاد الداخلية المعطاة.

هذه حزمة Matlab واحدة يمكنها تطبيق عمليات الضرب أو التحويل على بعض الأبعاد المحددة. يوجد دليل في الحزمة حول كيفية تنفيذ هذه العمليات في Matlab ، لكنني أعتقد أن نظرية الرياضيات يجب أن تنطبق على اللغات الأخرى أيضًا. تتمثل فكرتهم في تنفيذ عمليات المصفوفة عن طريق تجنب استخدام الحلقات For ، والاعتماد في الغالب على إعادة تشكيل المصفوفة وما إلى ذلك. لذلك ، فهو سريع للغاية في ماتلاب. لا أعرف ما إذا كانت جوليا أشبه بالعمليات الموجهة أو العمليات المنحرفة (يبدو أنها الأخيرة). أشعر أن العملية الموجهة هي ميزة لعمليات المصفوفة عالية الأبعاد ، إذا كان النواة يدعمها. ربما يجب أن نفكر بصدق في هذا النوع من عمليات المصفوفة في هذه المرحلة.

للرجوع اليها: تطبيق آخر مشابه في Matlab لعملية INV هنا: http://www.mathworks.com/matlabcentral/fileexchange/31222-inversion-every-2d-slice-for-arbitrary-multi-dimension-array

لاحظ أيضًا أنه بعد إصدار حزمة دعم تشغيل مصفوفة Matlab في عام 2005 ، يتم الاحتفاظ بسجل التنزيل بمستوى عالٍ حتى اليوم. كما هو الحال في تجربتي العملية ، يتم استخدام عمليات المصفوفة بشكل متكرر في الفيزياء وغيرها من المجالات. أود أن أقول ، إذا كان لدى Julia وظائف مماثلة لتشغيل المصفوفات ذات الأحجام العشوائية ، فستصبح اللعبة ممتعة للغاية!

تصويت آخر هنا لحل alanedelman المقترح نحو القمة. هذا مثال محفز.

الآن ، شريحة الصف هي صفيف ثنائي الأبعاد ، بينما شريحة العمود عبارة عن صفيف 1d ؛ وهو غير متماثل بشكل غريب وقبيح:

julia> A = randn(4,4)
4x4 Array{Float64,2}:
  2.12422    0.317163   1.32883    0.967186
 -1.0433     1.44236   -0.822905  -0.130768
 -0.382788  -1.16978   -0.19184   -1.15773
 -1.2865     1.21368   -0.747717  -0.66303

julia> x = A[:,1]
4-element Array{Float64,1}:
  2.12422
 -1.0433
 -0.382788
 -1.2865

julia> y = A[1,:]
1x4 Array{Float64,2}:
 2.12422  0.317163  1.32883  0.967186

على وجه الخصوص ، هذا يعني أنه لا يمكنني ضرب صف في عمود واستخراج رقم دون القيام ببعض التلاعب القبيح بشكل رهيب مثل

julia> dot(y[:],x)
2.4284575954571106
julia> (y*x)[1]
2.42845759545711

إنه ليس اقتراحًا متماسكًا ما لم تجعل '* عامل تشغيل خاص ، وهو أمر مشكوك فيه إلى حد كبير ، منذ ذلك الحين لا يعني x'*y و (x')*y نفس الشيء. علاوة على ذلك ، سيجعل الضرب غير ترابطي.

أفهم الصعوبات مع x_y 'و y'_x. قد يكون من الأفضل العلاج
المنتجات الداخلية والخارجية كعمليات منفصلة ، باستخدام على سبيل المثال النقطة (). (ربما
أيضًا باستخدام cdot؟)

ولكن ما هي الحجج التي تؤيد وجود شريحة على طول الأول
البعد يعيد كائنًا بعده يختلف عن شريحة على طول
البعد الثاني؟ من أجل الاتساق ، يبدو أنه في كل مرة تقطع ،
يجب أن يتقلص حجم الكائن الناتج بمقدار واحد.

يوم الأربعاء ، 16 يوليو ، 2014 الساعة 8:17 مساءً ، Stefan Karpinski [email protected]
كتب:

إنه ليس اقتراحًا متماسكًا إلا إذا قمت بإجراء "* عامل تشغيل خاص ، والذي
مشكوك فيه إلى حد كبير ، لأن x'_y و (x ') _ y لا تعنيان نفس الشيء.
علاوة على ذلك ، سيجعل الضرب غير ترابطي.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/4774#issuecomment -49254346.

مادلين أوديل
مرشح دكتوراه في الهندسة الحسابية والرياضية
جامعة ستانفورد
www.stanford.edu/~udell

madeleineudell ، أتفق معك ، لكن هذه مشكلة مختلفة ، راجع # 5949. على الرغم من أنه يبدو أن هذه القضية قد أغلقت ، لا أتذكر أنه كان هناك اتفاق أو نتيجة واضحة.

بمجرد أن ننتقل إلى طرق عرض المصفوفة ، سيصبح من الأسهل استكشاف هذه الاتجاهات. على وجه الخصوص ، فإن قول slice(A, i, :) يمنحك السلوك الذي تريده. (إنه يفعل ذلك الآن ، ولكن على حساب تقديم نوع أبطأ ، SubArray.)

من وجهة نظر رياضية بحتة ، تأتي جميع القضايا المعروضة هنا من الخلط بين (والارتباك بين) ما نعنيه بالمصفوفات وما نعنيه بالمتجهات / الموترات / المصفوفات. المصفوفات ، من الناحية المفاهيمية ، هي مجرد قوائم (أو ، في حالة المصفوفات n-dim ، قوائم قوائم). على هذا النحو ، لا توجد مواصفات طبيعية لعمليات مثل ضرب المصفوفات ، والتبديل ، وما إلى ذلك. في حين أن الوظائف مثل العناصر الثابتة ، والعمليات الحكيمة ، والعمليات الخاصة بالمحور (الوسط ، الوسيط ، إلخ) منطقية ويمكن تعريفها بشكل فريد في بطريقة طبيعية ، لا يمكن أن تكون العمليات مثل المنتجات النقطية.

كما ذكرنا سابقًا ، فإن المتجهات والموترات عبارة عن كائنات هندسية ، وفي حين أنه من الممكن تمثيلها باستخدام المصفوفات ، فإن هذه التمثيلات لا تحتوي على نفس ثراء البنية مثل الكائنات الرياضية التي تمثلها. إن تبديل المصفوفة ذات 1 خافت هو no-op؛ إن تبديل المتجه هو مزدوج. يمكن تعريف تبديل المصفوفة ثنائية الأبعاد بشكل فريد وطبيعي على أنه تبديل لأبعادها ، ولكن هذا لا ينطبق بشكل عام على الموترات: في حين أن الحالة الطبيعية تحمل المرتبة (1،1) الموترات (الملقب بالمصفوفات) ، موتر رتبة (2،0) ينقل إلى موتر رتبة (0،2). مرة أخرى ، من خلال التعامل مع الموترات كمصفوفات ، يتم فقد المعلومات الهندسية التي تجعل الموترات موترات.

هذا مهم عند تحديد عمليات مثل المنتجات النقطية. المنتج النقطي له معنى هندسي محدد (إسقاط متجه واحد على الفضاء المزدوج المحدد بواسطة ناقل ثان) ، وبالتالي فإن التعريف المتسق للمنتجات النقطية يتطلب الحفاظ على المعلومات الهندسية الواردة في المتجهات. قد يتيح استخدام بعض الافتراضات إمكانية استخدام المصفوفات مع استمرار تغطية غالبية حالات الاستخدام ، ولكن هذه الافتراضات فوضوية (كما يتضح من المقترحات المختلفة في هذا الموضوع) وتجعل الأمور أكثر صعوبة على أي شخص يحتاج إلى بنية أغنى من الموترات .

لذلك ، اعتبر هذا تصويتًا قويًا لصالح اقتراح thomasmcoffee لتضمين نوع مستخرج أكثر ثراءً. أفضّل شخصيًا هو أن عمليات مثل التحويل والمنتجات النقطية لم يتم تعريفها حتى للمصفوفات ، ولكن كما أظن أن معظم الناس لن يشاركوا هذا الرأي ، أود على الأقل القدرة على إنشاء موترات حقيقية إذا دعت الحاجة.

يبدو أن المعنى العملي لهذا المنظور هو أنه يجب تحديد المصفوفات بمجموعة فرعية من الموترات ، ويجب أن ينتج عن نقل مصفوفة 1-d DualVector أو ربما خطأ. وجهة نظري هي أن هذا يماثل العمليات على الأعداد الحقيقية التي تعطي الأعداد المركبة.

سيكون وجهة نظري أن عائلة AbstractArray العامة ، وهي حاوية بيانات (متعددة الأبعاد) ، هي عامة بما يكفي لتكون جزءًا غير مسؤول من أي لغة برمجة تقنية. الموتر الذي يتبع قواعد رياضية صارمة ، على الرغم من أنني أهتم به كثيرًا ، فهو كائن جيد لحزمة مخصصة. في الواقع ، أنا أعمل على شيء على غرار ما حدده jdbates في https://github.com/Jutho/TensorToolbox.jl . وهي حتى الآن غير موثقة وغير مختبرة إلى حد كبير. لقد كتبته للأشياء التي أحتاجها شخصيًا في فيزياء الجسم الكمومية ، لكنني آمل أن يتم بناؤها بطريقة عامة بما فيه الكفاية وقابلة للتوسيع لتكون مفيدة للمجتمع الأكبر من علماء الرياضيات والفيزياء الذين يهتمون بالعمل مع الموترات.

لإعطاء بعض التفاصيل (منسوخة من منتدى JuliaQuantum): قررت تحديد تسلسل هرمي لنوع جديد للموترات ، وهذا مستقل عن نوع AbstractArray لجوليا (على الرغم من أن Tensor الأساسي هو مجرد غلاف لـ Array). من المفترض أن يعمل هذا النوع من التسلسل الهرمي بطريقة أكثر رسمية قليلاً. ترتبط مؤشرات الموتر بمسافات متجهة (يشار إليها من الآن فصاعدًا باسم مسافات الفهرس) ، وإذا كان نوع مساحة المتجه التي يرتبط بها مؤشر الموتر مختلفًا عن ثنائيها ، فإن هذا يتوافق مع موتر يميز بين المؤشرات المتغيرة والمتناقضة.

لذا فإن الجزء الأول من الحزمة هو الجزء المجرد لتعريف المساحات المتجهة ، حيث أذهب لمطابقة نوع التسلسل الهرمي لكائنات Julia مع التسلسل الهرمي الرياضي لمسافات المتجهات. يأتي فضاء المتجه العام V في أربعة أنواع ، تتوافق مع نظرية التمثيل للمجموعة الخطية العامة على V ، أي V نفسها (التمثيل الأساسي) ، و Con (V) ، و dual (V) ، و dual (conj (V)). للمساحات المتجهة الحقيقية ، conj (V) = V ولا يوجد سوى V وثنائي (V) ، يتوافق مع المتجهات المتغيرة والمتغيرة. ثم هناك مساحات المنتج الداخلية ، وفي المستوى الأعلى من التسلسل الهرمي توجد المساحات الإقليدية ، وهي مساحات داخلية للمنتج مع منتج داخلي إقليدي قياسي (أي أساس متعامد). في الفيزياء ، من المفيد أيضًا التفكير في الفراغات المتجهة التي تتحلل إلى قطاعات مختلفة ، أي يتم تصنيفها من خلال التمثيلات غير القابلة للاختزال لأفعال التناظر.

الموترات هي كائنات تعيش في (فضاء فرعي من) منتج الموتر لبعض المساحات المتجهة الأولية. ومع ذلك ، بصرف النظر عن Tensor القياسي ، وهو كائن يعيش في فضاء منتج الموتر لمساحات الفهرس الخاصة به ، يمكن للمرء أن يبني موترات تعيش في مثل القطاع الثابت لمنتج موتر للمساحات المصنفة بواسطة irreps ، الفضاء الجزئي المتماثل أو غير المتماثل لـ منتج موتر من مسافات متطابقة ، ... يمكن أن يكون للفرد مسافات متجهة فرميونية كمساحات مؤشر ، مما يعني أن تبديل مؤشرات الموتر سيحدث تغييرات معينة في العلامات اعتمادًا على قطاعات التكافؤ ، إلخ ...

ثم من المفترض أن تكون هناك عمليات معينة محددة على الموترات ، وأهمها موتر الانكماش ، ولكن أيضًا ، على سبيل المثال ، العوامل المتعامدة (تحلل القيمة المفردة) إلخ. أخيرًا ، يجب أن تكون هناك خرائط خطية ترسم موترًا على موتر آخر. إنهم يستحقون نوعًا خاصًا حيث لا يرغب المرء عادةً في ترميزها بالكامل كمصفوفة ، بل بطريقة يمكن حساب منتج متجه المصفوفة بكفاءة ، لاستخدامه في الأساليب التكرارية (لانكسوس ، إلخ). تقوم الحزمتان الموجودتان لدي حتى الآن (TensorOperations.jl و LinearMaps.jl) بتنفيذ هذه الوظيفة للمصفوفات القياسية ، وسوف يقوم صندوق أدوات الموتر قيد الإنشاء بزيادة التحميل / إعادة تعريفها من أجل التسلسل الهرمي الجديد AbstractTensor.

آمل أن تكون هذه الحزمة عامة بما فيه الكفاية بحيث تكون مفيدة أيضًا لمجتمع الفيزياء / الرياضيات الأوسع. على سبيل المثال ، إذا أتى شخص ما لإنشاء حزمة للعمل مع المشعبات ، فيمكنه بعد ذلك تحديد مساحة متجه TangentSpace على أنها فضاء فرعي من InnerProductSpace المجرد ، ويمكنه بعد ذلك على الفور إنشاء موترات تعيش في منتج موتر لعدد قليل من المساحات المماسية والتماسية. في الواقع ، أفكر في تقسيم الجزء الخاص بتعريف الفراغات المتجهة إلى حزمة منفصلة ، والتي يمكن أن تنمو إلى حزمة لتحديد الهياكل / الكائنات الرياضية.

أخيرًا ، يأتي interop مع julia القياسي من استدعاء tensor على معيار Array ، والذي يلفه في كائن من النوع Tensor مع المؤشرات المرتبطة بمسافات من النوع CartesianSpace . هذا هو الفضاء المتجه الحقيقي القياسي R ^ n مع المنتج الإقليدي ، حيث لا يوجد تمييز بين الفهرس المتغاير والمتباين. أعتقد أن هذا يستلزم أفضل ما هو جوليا أراي القياسي.

JeffBezanson ، أنا متناقض فيما يتعلق بمعاملة المصفوفات

أنا لا أعارض اقتراح Jutho بتقسيم ميكانيكا التنسور إلى حزمة منفصلة. ربما يكون محقًا في أن عدد المستخدمين الذين يحتاجون إلى ميكانيكا موتر كاملة أقل بكثير من عدد الأشخاص الذين يريدون فقط عمليات مصفوفة مباشرة. السؤال الذي نحاول حقًا طرحه هنا هو "في أي مجال يجب أن يقع الجبر الخطي؟"

إن آلية الجبر الخطي هي مجموعة فرعية جوهرية بدرجة كافية من آلية جبر التنسور ، والتي ، في رأيي على الأقل ، ليس من المنطقي تنفيذ الأول دون تنفيذ الأخير أيضًا. يتم تمثيل العمليات مثل v'M بشكل أكثر إيجازًا وثباتًا إذا كان لدينا فكرة عن المتجهات المشتركة والمتناقضة ، ولكن هذا يضعنا بالفعل في معظم الطريق نحو عمليات الموتر العامة.

أتفق معك في أن هذا يشبه من الناحية المفاهيمية العمليات على الأعداد الحقيقية التي تُرجع الأعداد المركبة.

ضع في اعتبارك الصور: يمكن اعتبار الصورة حقلاً متجهًا على مشعب (ثنائي الأبعاد عادةً). يمنحك قصر هذا الحقل على شبكة مستطيلة بنية تريد ، بطبيعة الحال ، تمثيلها باستخدام مصفوفة ثلاثية الأبعاد. ومع ذلك ، هذا في الحقيقة مجرد تعيين من مساحة نقاط الشبكة إلى مساحة المتجه {R ، G ، B} ، لذا فإن المعنى الهندسي للأبعاد الأولى والثانية (تسميات x و y للشبكة) يختلف عن المعنى الهندسي للبعد الثالث (وهو في الواقع ناقل).

على الرغم من أن هذا لا يعالج رسالتك العامة أو يسلبها منها ، فإن موترات بنية اللون ، والتي أتطلع إلى استخدامها لمشروع ما.

في 23 أغسطس 2014 الساعة 20:36 ، كتب jdbates [email protected] :

JeffBezanson ، أنا متناقض فيما يتعلق بمعاملة المصفوفات

أوافق على أن الموترات لا تحل محل المصفوفات. هذا المثال أعلاه هو في الواقع بنية رياضية مختلفة (أي حزمة متجه أو حزمة موتر بشكل عام) والتي يمكن تمثيل تمثيلها أيضًا كمصفوفة متعددة الأبعاد عن طريق اختيار شبكة للإحداثيات المتعددة وأساس لجزء مساحة المتجه. لذلك في الواقع ، يمكن أن يكون لديك كائنات / هياكل رياضية مختلفة محددة جيدًا بطريقة مستقلة عن الإحداثيات / مستقلة عن الأساس ولكن يمكن تمثيلها (بعد اختيار نظام إحداثيات أو أساس) كمصفوفة متعددة الأبعاد. لذا فإن المصفوفات متعددة الأبعاد لا تقتصر بالتأكيد على تمثيل الموترات. كما تفشل الطريقة الأخرى أيضًا ، حيث لا تتمتع جميع الموترات بتمثيل مناسب باستخدام مصفوفة متعددة الأبعاد. هذا هو الحال فقط عندما تستخدم أساسًا معينًا يُعرف باسم أساس المنتج ، والذي يتم الحصول عليه من خلال أخذ المنتج المباشر لجميع المجموعات الممكنة من نواقل الأساس الفردية لمساحات المتجه المتضمنة في مساحة منتج الموتر. في بعض الحالات ، على سبيل المثال عند استخدام الموترات في فضاء فرعي ثابت للتماثل من مساحة منتج الموتر ، لم يعد هذا التمثيل ممكنًا وتحتاج إلى تحديد أساس مختلف للمساحة الكاملة ، فيما يتعلق بالموتر الذي يتم تمثيله قائمة أرقام طويلة أحادية البعد.

أنا لا أعارض اقتراح Jutho بتقسيم ميكانيكا التنسور إلى حزمة منفصلة. ربما يكون محقًا في أن عدد المستخدمين الذين يحتاجون إلى ميكانيكا موتر كاملة أقل بكثير من عدد الأشخاص الذين يريدون فقط عمليات مصفوفة مباشرة. السؤال الذي نحاول حقًا طرحه هنا هو "في أي مجال يجب أن يقع الجبر الخطي؟"

إن آلية الجبر الخطي هي مجموعة فرعية جوهرية بدرجة كافية من آلية جبر التنسور ، والتي ، في رأيي على الأقل ، ليس من المنطقي تنفيذ الأول دون تنفيذ الأخير أيضًا. يتم تمثيل العمليات مثل v'M بشكل أكثر إيجازًا وثباتًا إذا كان لدينا فكرة عن المتجهات المشتركة والمتناقضة ، ولكن هذا يضعنا بالفعل في معظم الطريق نحو عمليات الموتر العامة.

أتفق معك في أن هذا يشبه من الناحية المفاهيمية العمليات على الأعداد الحقيقية التي تُرجع الأعداد المركبة.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub.

هناك العديد من التفسيرات المحتملة للمصفوفات ، ولا يكون تفسير الموتر دائمًا (أو حتى عادةً) منطقيًا. ضع في اعتبارك الصور: يمكن اعتبار الصورة حقلاً متجهًا على مشعب (ثنائي الأبعاد عادةً). يمنحك قصر هذا الحقل على شبكة مستطيلة بنية تريد ، بطبيعة الحال ، تمثيلها باستخدام مصفوفة ثلاثية الأبعاد. ومع ذلك ، هذا في الحقيقة مجرد تعيين من مساحة نقاط الشبكة إلى مساحة المتجه {R ، G ، B} ، لذا فإن المعنى الهندسي للأبعاد الأولى والثانية (تسميات x و y للشبكة) يختلف عن المعنى الهندسي للبعد الثالث (وهو في الواقع ناقل).

لقد كان هذا النوع من التمييز فقط الذي كنت أحاول التقاطه في اقتراح AbstractTensorArray النظري لـ https://github.com/JuliaLang/julia/issues/4774#issuecomment -38333295 من خلال السماح لكل من المصفوفة والموترة تشبه الأبعاد. بموجب هذا المخطط ، أتوقع أن أمثل مثالك كـ

AbstractTensorArray{Uint8, 3, [false, true, false], [true, false, false]}

بحيث تكون أبعاد x و y و RGB "لأسفل" و "لأعلى" و "محايدة" ، على التوالي. يمكن للعمليات الهندسية (على سبيل المثال ، التحويلات الأفينية) معالجة أبعاد إحداثيات الشبكة بطريقة تشبه الموتر أثناء تعيين قيم RGB بطريقة تشبه المصفوفة. (إذا كنت تريد لاحقًا معالجة قيم RGB هندسيًا ، فسيتعين عليك تغيير القناع صراحةً لهذا الغرض ، لكني أعتقد أن (أ) أقل شيوعًا أن يتم تطبيق نوعين مختلفين من العمليات الهندسية على مساحات فرعية مختلفة من نفس جدول البيانات ، و (ب) في هذه الحالة ، من المحتمل أن يؤدي التحويل الصريح إلى _تحسين_ وضوح الكود.)

لم أفكر في التمثيلات المترافقة التي يذكرها Jutho ، لكن يبدو لي أن هذا التعميم يمكن معالجته من خلال توسيع نهج التقنيع نفسه ، للمساحات المعقدة.

السؤال الذي نحاول حقًا طرحه هنا هو "في أي مجال يجب أن يقع الجبر الخطي؟"

بمجرد تحديد التصميم لكيفية تشغيل العمليات الشبيهة بالمصفوفة والموترة معًا ، يمكن تعريف كيانات الجبر الخطي فقط من خلال حالات خاصة (مثل الأسماء المستعارة التي استخدمتها أعلاه) ، بحيث يمكن لمستخدم الجبر الخطي الخالص أن يكون غافلًا عن التسلسل الهرمي للموتر المعمم بالكامل حتى يتم الاحتياج إليه (ولكن لن تضطر إلى إعادة كتابة الأشياء إذا ومتى كانت كذلك). لذلك لن أرى أي مشكلة (باستثناء ربما سخام) في وضع كل شيء في القاعدة.

بحيث تكون أبعاد x و y و RGB "لأسفل" و "لأعلى" و "محايدة" ، على التوالي. يمكن للعمليات الهندسية (على سبيل المثال ، التحويلات الأفينية) معالجة أبعاد إحداثيات الشبكة بطريقة تشبه الموتر أثناء تعيين قيم RGB بطريقة تشبه المصفوفة. (إذا كنت تريد لاحقًا معالجة قيم RGB هندسيًا ، فسيتعين عليك تغيير القناع صراحةً لهذا الغرض ، لكني أعتقد أن (أ) أقل شيوعًا أن يتم تطبيق نوعين مختلفين من العمليات الهندسية على مساحات فرعية مختلفة من نفس جدول البيانات ، و (ب) في هذه الحالة ، من المحتمل أن يؤدي التحويل الصريح إلى تحسين وضوح الكود.)

أعتقد أنك تمزج شيئًا ما هنا. في المناقشة أعلاه ، تم توضيح أن إحداثيات x و y لا تحمل تفسير الفضاء المتجه ، حيث يمكن أن تتوافق مع الإحداثيات على مشعب منحني تعسفي ، وليس بالضرورة مساحة مسطحة. كان بُعد RGB هو الذي تم إعطاؤه تفسير المتجه ، على الرغم من أن هذا قد لا يكون في الواقع هو الخيار الأفضل ، كما يبدو أنني أتذكر (ليس لدي خلفية مناسبة في معالجة الصور) أن مساحة اللون منحنية أيضًا. أيضًا ، حتى في الحالة التي يشكل فيها المجال (x و y) مساحة متجهية ، فلماذا يكون x و y لأعلى ولأسفل ، أو كان هذا مجرد مثال على تدوينك؟

على أي حال ، بدأت أيضًا مع TensorToolbox.jl من خلال الإشارة إلى المؤشرات المتغايرة والمتناقضة كنوع من المعلمات أو القناع ، ولكن سرعان ما أصبح هذا كابوسًا كاملاً ، ولهذا السبب تحولت إلى تمثيل حيث كل موتر هو عنصر في بعض فضاء متجه ، ولإجراء العمليات ، يتعين على المرء التحقق من تطابق المسافات ، تمامًا مثلما تحتاج إلى التحقق من تطابق الأحجام عند إجراء عمليات باستخدام المصفوفات.

لم تحمل إحداثيات x و y تفسير الفضاء المتجه

آسف ، لقد بالغت في قراءة "شبكة مستطيلة" --- أعتقد أن

كل موتر هو عنصر لبعض فضاء متجه

تبدو فكرة جيدة - سأكون مهتمًا برؤية بعض الأمثلة عن كيفية عملها للمستخدم (لم أتمكن من قراءة الكود كثيرًا).

لدي اقتراح جديد لهذه القضية.


(1) تقطيع على غرار APL.

size(A[i_1, ..., i_n]) == tuple(size(i_1)..., ..., size(i_n)...)

على وجه الخصوص ، هذا يعني أن "الشرائح المفردة" - أي الشرائح التي يكون المؤشر فيها عدديًا أو صفري الأبعاد - يتم إسقاطها دائمًا و M[1,:] و M[:,1] كلاهما متجهين ، بدلاً من كون أحدهما متجهًا بينما الآخر عبارة عن مصفوفة صف ، أو أي تمييز آخر من هذا القبيل.


(2) تقديم أنواع أغلفة Transpose و ConjTranspose للمتجهات والمصفوفات. بمعنى آخر ، شيء من هذا القبيل:

immutable Transpose{T,n,A<:AbstractArray} <: AbstractArray{T,n}
    array::A
end
Transpose{T,n}(a::AbstractArray{T,n}) = Transpose{T,n,typeof(a)}(a)

وجميع الطرق المناسبة لجعل هذه تعمل كما ينبغي للمتجهات والمصفوفات. قد نرغب في قصره على العمل للمتجهات والمصفوفات فقط ، لأنه من غير الواضح ما الذي يجب أن يعنيه النقل العام للأبعاد التعسفية (على الرغم من أن مجرد عكس الأبعاد أمر مغري). عندما تكتب a' تحصل على ConjTranspose(a) وبالمثل v.' تنتج Transpose(a) .


(3) تحديد طرق متخصصة مختلفة للناقلات والمصفوفات المنقولة (المقترنة) ، مثل:

*(v::Transpose{T,1}, w::AbstractVector) = dot(v.array,w)
*(v::AbstractVector, w::Transpose{T,1}) = [ v[i]*w[j] for i=1:length(v), j=1:length(w) ]

إلخ ، بما في ذلك استبدال جميع الوظائف الرهيبة At_mul_B والتحليل الخاص مع البناء الكسول (المترافق) متبوعًا بالإرسال على الأنواع Transpose و ConjTranspose .


(4) قصر عمليات البث على الحالات التي تكون فيها الوسائط ذات أحجام أو مصفوفات لها نفس عدد الأبعاد. وبالتالي ، فإن ما يلي الذي يعمل حاليًا كما هو موضح سيفشل:

julia> M = rand(3,4);

julia> M./M[1,:]
3x4 Array{Float64,2}:
 1.0       1.0       1.0      1.0
 0.516884  0.675712  2.11216  9.0797
 1.00641   0.726229  2.48336  4.38751

julia> M./M[:,1]
3x4 Array{Float64,2}:
 1.0  0.891557  0.561464  0.103968
 1.0  1.16552   2.29433   1.82633
 1.0  0.643353  1.38544   0.453257

بدلاً من ذلك ، سيتعين عليك القيام بشيء مثل هذا:

julia> M./M[[1],:]
3x4 Array{Float64,2}:
 1.0       1.0       1.0      1.0
 0.516884  0.675712  2.11216  9.0797
 1.00641   0.726229  2.48336  4.38751

julia> M./M[:,[1]]
3x4 Array{Float64,2}:
 1.0  0.891557  0.561464  0.103968
 1.0  1.16552   2.29433   1.82633
 1.0  0.643353  1.38544   0.453257

أعتقد أن هذا الاقتراح يحل جميع المشكلات الرئيسية التي نواجهها حاليًا:

  1. سلوك التقطيع المتماثل - لم تعد الأبعاد الزائدة خاصة.
  2. v'' === v .
  3. v' == v .
  4. v'w هو المنتج النقطي لـ v و w - على وجه الخصوص ، هو عدد قياسي ، وليس متجهًا من عنصر واحد.
  5. v*w' هو المنتج الخارجي لـ v و w .
  6. M*v هو ناقل.
  7. M*v' خطأ.
  8. v'*M هو ناقل متجه.
  9. v*M خطأ.
  10. تختفي المعاملات At_mul_B والتحليل الخاص.

: +1: لكل هذا. لقد قمت ببعض الأعمال في 2 و 3 في # 6837 ، لكني لم أنتهي منها. simonbyrne نظر أيضا في ذلك.

+1 أيضًا. يبدو أنه سيوفر سلوكًا متسقًا تمامًا في كل مكان.

الجزء الوحيد الذي يسبب الاضطراب في هذا الاقتراح هو أن M[1,:] هو متجه عمودي ضمنيًا وليس مصفوفة صف أفقية بشكل واضح. خلاف ذلك ، إنها في الواقع مجموعة من التغييرات السلسة جدًا وغير التخريبية (نأمل ذلك). كان الظهور الرئيسي (بالنسبة لي) هو أن سلوك تقطيع APL يمكن دمجه مع عمليات النقل البطيئة. إذا حصلنا على موافقة ، يمكننا التوصل إلى خطة وتقسيم العمل. آمل حقًا أن تسمح عمليات النقل البطيئة والوظائف المرحلية ببعض تقليل وتبسيط الشفرة.

نعم من فضلك! من المحتمل أن يسمح تبديل الموتر بأي تبديل محدد من قبل المستخدم ، مع عكس التعتيم كإعداد افتراضي.

من المحتمل أن يسمح تبديل الموتر بأي تبديل محدد من قبل المستخدم ، مع عكس التعتيم كإعداد افتراضي.

يبدو أن هذا سيعقد النوع كثيرًا ، ربما يمكننا الحصول على نوع PermuteDims يسمح بتبديل البعد الكسول التعسفي.

@ Stefan : تبدو هذه فكرة جيدة جدًا للعمل على المتجه و 2-dim
الجبر. فقط بعض التحديات:

  1. فيما يتعلق بحالات الصفيف متعددة الأبعاد: لمصفوفة A ذات أبعاد
    (i_1 ، i_2 ، ... ، i_n) ، إذا كان أحد يريد تطبيق تبديل الموضع على [i_2 ، i_3]
    الأبعاد - أو حتى التجزئة على أبعاد [i_2، i_4]. يمكنك أن تفعل ذلك في
    التعريف الجديد للتبديل؟
  2. فيما يتعلق بالبعد الفردي: من الممكن أن تكون شريحة مفردة
    غادر عمدا. هل يجب أن تحتفظ جوليا بهذا البعد الفردي بعد
    عملية حسابية؟ على سبيل المثال ، إذا حدد أحد المتجه كمصفوفة V في
    بعد (2،1) ، ويريد ضرب المدور بمصفوفة A في
    البعد (2،3،4). هل يمكنك الحصول على نتيجة v '* A في البعد
    (1،3،4)؟

يوم الخميس ، 16 أكتوبر 2014 ، الساعة 2:31 مساءً ، Stefan Karpinski [email protected]
كتب:

المسبب الوحيد في الواقع هو أن M [1 ،:] متجه (عمودي)
بدلا من مصفوفة الصف. بخلاف ذلك ، يكون الأمر سلسًا جدًا ،
مجموعة من التغييرات غير التخريبية (نأمل ذلك). كان عيد الغطاس الرئيسي (بالنسبة لي)
يمكن دمج سلوك تقطيع APL مع عمليات النقل البطيئة. إذا وصلنا
بالموافقة ، يمكننا وضع خطة وتقسيم العمل. أنا اتمنى
تسمح عمليات النقل البطيئة والوظائف المرحلية ببعض تقليل الشفرة و
تبسيط.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/4774#issuecomment -59425385.

فيما يتعلق بالسؤال الثاني والثالث: بعد أن حصلت على طعنة خشنة في ذلك ، توصلت إلى استنتاج مفاده أن ناقل الحركة المتجه لا ينبغي أن يكون نوعًا فرعيًا من AbstractVector ، وإلا فسيصبح كل شيء فوضويًا (انظر المناقشة في # 6837). أعتقد أن الطريقة الأكثر عقلانية للمضي قدمًا هي استخدام Transpose{T,A} <: AbstractMatrix{T} ، ونوع Covector منفصل (+ متغيرات Conjugate )

المشكلة المهمة الأخرى التي واجهتها هي أنك غالبًا ما تريد الإرسال على نوع مصفوفة معينة ، أو تبديلها ، أو نقلها المقترن. لسوء الحظ ، لم أتمكن من التوصل إلى طريقة للتعبير عن هذا من خلال آلات النوع الموجودة (انظر مناقشة القائمة البريدية هذه ). بدون هذا ، أخشى أن نكون في الكثير من @eval -ing أكثر من 3x3 مجموعات ممكنة من الحجج.

simonbyrne ،

لقد أشرت (في المنتديات الأقل شهرة ، لذلك من المحتمل أن يكون هناك إشارة موجزة هنا) أن البديل المحتمل هو التعامل مع كل الأشكال _ داخليًا_ ، من خلال توسيع أنواع الفهارس التي يمكن أن تستخدمها المصفوفات الفرعية. على وجه الخصوص ، يمكن أن يكون لدى المرء نوع "نطاق متغير" من شأنه أن يمنح شكلاً منقولاً إلى المصفوفة الفرعية ، حتى عندما تكون المصفوفة الأصلية Vector . (راجع https://github.com/JuliaLang/julia/blob/d4cab1dd127a6e13deae5652872365653a5f4010/base/subarray.jl#L5-L9 إذا لم تكن على دراية بكيفية تنفيذ / إمكانية تنفيذ المصفوفات الفرعية.)

لست متأكدًا مما إذا كانت هذه الاستراتيجية البديلة تجعل الحياة أسهل أم أصعب. يقلل من عدد الأنواع التي تواجه خارجيًا ، مما قد يعني أن المرء يحتاج إلى طرق أقل. (كشخص _ لا يزال_ يملأ الطرق المفقودة بسبب انتقال Color في Images ، يبدو هذا كشيء جيد.) من ناحية أخرى ، في حالة عدم وجود إرسال مثلث مناسب ، يمكن أن جعل الأمر أكثر صعوبة إلى حد ما في كتابة أساليب انتقائية ، والتي قد تؤدي إلى تفاقم المشاكل التي أثارتها simonbyrne.

أي أفكار ستكون موضع ترحيب كبير.

بصرف النظر عن هذه التفاصيل ، أحب شكل اقتراح StefanKarpinski . أنا لست ملتزمًا بفهرسة نمط APL ، لكنني أعتقد أنه خيار أفضل من القواعد المشتقة من Matlab التي لدينا الآن.

فكرتان:

  • إذا أصبحت الفهرسة مثل A[[2], :] اصطلاحية ، فيبدو من التبذير بعض الشيء أن تضطر إلى إنشاء متجه لمجرد التفاف الفهرس الفردي 2 . هل يجب أن نأخذ في الاعتبار السماح بـ A[(2,), :] لنفس الشيء ، أو شيء مشابه؟ أعتقد أن نطاق عنصر واحد على ما يرام ، ولكن سيكون من الجيد أن يكون لديك بناء جملة مناسب تقريبًا مثل [2] .
  • إذا احتجنا إلى مطابقة عدد الأبعاد لإجراء البث ، فيجب أن تكون هناك طريقة بسيطة لإضافة أبعاد مفردة إلى مصفوفة ، ربما شيء مثل فهرسة numpy's newaxis .

كنت أفكر في اقتراح أن الفهرسة بالفواصل المنقوطة ، على سبيل المثال لا A[2;:] ، يمكن أن تكون وضع فهرسة مختلف حيث يكون للنتيجة دائمًا نفس عدد الأبعاد مثل A - أي عدم إسقاط الفواصل المفردة والفهرسة باستخدام أي شيء له مرتبة أكثر من واحد يعتبر خطأ. قررت ترك ذلك خارج الاقتراح الأساسي من أجل البساطة ، ولكن يبدو أن شيئًا كهذا يبدو جيدًا.

أستطيع أن أرى المخاوف التي عبر عنها simonbyrne . ومع ذلك ، من حيث المبدأ ، فإن covector هو أيضًا مجرد ناقل يعيش في فضاء ناقل مختلف ، أي الفضاء المزدوج. لذا فإن جعل النوع Transpose أو Covector ليس نوعًا فرعيًا من AbstractArray يبدو أيضًا غير سار إلى حد ما. الحل المحتمل ، الذي سيكون تغييرًا كبيرًا وربما لن يتم النظر فيه (لكنني أردت أن أذكره على أي حال) هو إعطاء عائلة AbstractArray بأكملها معلمة نوع إضافية trans ، والتي يمكن أن تحتوي على قيم :N أو :T أو :C . بالنسبة لجميع الطرق التي تفترض فقط أن المتجه هو قائمة أرقام أحادية البعد ، فلن يحتاجوا إلى التمييز بين القيم المختلفة لهذه المعلمة النهائية ، وبالتالي يمكن أن تظل تعريفات الطريقة المقابلة كما هي الآن.

بالنسبة إلى المصفوفات ذات الأبعاد N مع N> 2 ، هناك خيارات متنوعة. يعطي إما transpose خطأ ومن المستحيل إنشاء كائن من النوع AbstractArray{3,Float64,trans} حيث trans!=:N ، أو ، بدلاً من ذلك ، :T يعني فقط الصف الرئيسي و transpose للمصفوفة العامة لها تأثير عكس جميع الأبعاد. أعتقد أن هذا الأخير هو أيضًا العرف المقبول من قبل أولئك الأشخاص الذين يستخدمون تدوين Penrose الرسومي (انظر http://en.wikipedia.org/wiki/Penrose_graphical_notation على الرغم من أن التحويل لم يتم شرحه هناك ، ولكن انظر أيضًا الكتاب المقتبس من قبل Cvitanović).

لا أرى حقًا أن دور التباديل التعسفي للفهرس يتم دعمه بواسطة transpose ، فهناك permutedims لذلك ، وربما بعض النهج الكسول باستخدام المصفوفات الفرعية المجددة. بالإضافة إلى ذلك ، فإن الدافع الرئيسي لهذه المشكلة هو تبسيط حديقة حيوان A_mul_B ، ولا يتم دعم (ولا ينبغي) دعم تقلصات الموتر ذات الترتيب الأعلى من خلال الضرب العادي على أي حال.

أنا متأكد من أن هناك بعض المشكلات الجديدة المتعلقة بهذا النهج والتي لم أفكر فيها بعد.

أعتقد أنني توصلت إلى حل معقول لمشكلة الإرسال هنا .

يبدو اقتراح Jutho مثيرًا للاهتمام ، وأعتقد أنه يستحق الاستكشاف. لسوء الحظ ، فإن الطريقة الحقيقية الوحيدة لتقييم هذه الأشياء هي محاولة تنفيذها.

@ toivoh ،

  • سيحتفظ A[2:2,:] أيضًا بالبعد ، وهذا لا يتطلب تخصيصًا أو أي بنية جديدة.
  • شيء مثل newaxis يبدو ممكنًا بشكل بارز. في الواقع ، مع الهندسة المعمارية في # 8501 ، يبدو أنه من الممكن إنشاء بث مباشر عن طريق الفهرسة: احصل على نوع فهرس يتحول دائمًا إلى 1 بغض النظر عن القيمة التي يملأها المستخدم في تلك الفتحة.

المشكلة مع 2:2 هي التكرار إذا كان هناك تعبير طويل للفهرس بدلاً من 2 . لكن بالطبع يمكنك دائمًا تحديد الوظيفة الخاصة بك لإنشاء نطاق من فهرس.

عرض جيد جدا: +1 :.

ذكرني لماذا نريد v' == v ؟

لا نحتاج ذلك حقًا ولكنه نوع من اللطيف نظرًا لأن ثنائية الفضاء المتجه (ذات الأبعاد المحدودة) متشابهة بالنسبة لها.

أو بشكل أقوى ، نظرًا لأن مصفوفات جوليا لا تميز بين المؤشرات المتغايرة والمتناقضة ، فمن المنطقي فقط التفكير في هذا على أنه نواقل في الفضاء الديكارتي (المقياس الإقليدي = مصفوفة الهوية = دلتا كرونكر) ، حيث يكون الفضاء المزدوج طبيعيًا. متماثل.

لست متأكدًا من أننا نريد v '== v ، لكنني أعتقد أن هذا أمر متعامد جدًا
البقية. هل نريد أن نقارن بين مصفوفة عمود ومتجه متساويين إذا كانا
لديك عناصر متساوية؟

هذه في الواقع قضية مختلفة لأن لديهم أعدادًا مختلفة من الأبعاد.

على وجه الخصوص ، يزيل هذا الاقتراح بشكل فعال التعريف بين المتجه ومصفوفة العمود - لأنه إذا قمت بتقسيم المصفوفة أفقيًا أو رأسيًا ، فستحصل على متجه في كلتا الحالتين. في السابق ، كان بإمكانك نوعًا من تجاهل الأبعاد المفردة الزائدة - أو التظاهر بوجود أكثر مما كان موجودًا بالفعل. لن يكون من الجيد القيام بذلك لأن المتجه يمكن أن يأتي من أي شريحة من المصفوفة.

هل من المنطقي أن تقوم convert بشيء من 1-d إلى 2-d عن طريق إضافة بُعد فردي لاحق؟

مع هذا الاقتراح ، أعتقد أنه قد لا يكون فكرة جيدة بعد الآن. ولكن ربما نظرًا لأن المتجهات لا تزال تتصرف مثل الأعمدة بينما تتصرف المتجهات مثل الصفوف.

شيء واحد أشرت إليه في # 8416 هو أن sparsevec مزيف بشكل فوضوي كمصفوفة CSC ذات عمود واحد في الوقت الحالي. يجب أن يكون Sparse قادرًا على التوافق مع هذا بشكل جيد إلى حد ما بمجرد تنفيذ نوع متجه متفرق مناسب 1-d (والذي قد يكون أبسط حالة مفيدة لنوع Nd COO عام ، يحتاج فقط إلى الكتابة).

مجرد أخذ كل هذا في. إذن ما يلي لن يعمل؟

A [1 ،:] * A * A [:، 1] # صف من عمود مصفوفة * مصفوفة * من مصفوفة ؟؟؟

انت كتبت

v'w هو حاصل الضرب القياسي لـ v و w - على وجه الخصوص ، إنه متجه عددي ، وليس متجهًا من عنصر واحد.

أيضا v '* w عددية؟

تعجبني فكرة النقطة (x ، y) التي تأخذ أي عنصرين شكلهما (1 ، ... ، 1 ، م ، 1 ، ... ، 1) و
إعادة المنتج النقطي مهما كان الأمر. لكني لا أريد أن تعطي x * y النقطة (x ، y) بهذا المعنى
ما لم يكن x متغيرًا و y متجهًا.

لست متأكدًا مما إذا كانت هذه فكرة ساخنة ولكن ربما يكون الأمر جيدًا إذا
كان A [:، 1،1] ناقلًا وكان A [1،:، 1] أو A [:، 1،:] متجهين.
من الأفضل أن تتبع بُعدًا للمتجه - الفتحة التي أنت عليها
يُسمح لها بالتعاقد مع الموتر ، مع وجود الجبر الخطي القياسي
1 (متجهات الصف) ومتجهات العمود 2.

في رأيي ، كان التحديان الرئيسيان اللذان سبق أن تناولناهما في هذه المسألة هما:

(أ) كيفية التمييز بين دلالات الموتر (للتقلصات) ودلالات الصفيف (للبث) عند العمل على بيانات متعددة الأبعاد ؛
(ب) كيفية تضمين الجبر الخطي الواضح والمريح ضمن إطار عمل متسق يعمم على أبعاد أعلى.

ليس من الواضح بالنسبة لي كيف يتعامل هذا الاقتراح مع أي من هاتين المسألتين. بقدر ما أستطيع أن أقول ، لتحقيق (أ) لا يزال يتطلب تلاعب المستخدم المخصص (كما هو الحال مع وظائف اليوم) ؛ وللتعامل مع (B) باستخدام أغلفة كسولة سيتطلب شيئًا مثل ملحقات SubArray التي اقترحها timholy ، وعند هذه النقطة تصبح نسخة كسولة من نهج التقنيع الذي نوقش منذ بعض الوقت. يمكنني تخيل تقديم دعم إضافي لـ (أ) باستخدام آلية كسولة مشابهة (مثل نوع غلاف List ) ، ولكن في كل هذه الحالات يبدو لي أن الكسل يجب أن يكون إستراتيجية اختيارية.

لا أعرف كم عدد مشاركة وجهة نظر Jutho القائلة بأن "تقلصات موتر

عندما تقول ، "... لها حدود تصميمها في هذا الصدد (كما ناقشت أعلاه) ، فهي مدعومة على الأقل" ، هل تتحدث عن وظيفة مفقودة ، أو شيء أساسي حول المتجهات وعمليات النقل التي لا يمكن معالجتها في مستوى أعلى ، أم بإضافة وظائف؟

هل هناك أي شيء بخصوص هذا الاقتراح _تعارض_ مع تحسين نقاطك (أ) و (ب)؟

لا أرى حقًا كيف يتم دعم تقلصات الموتر بواسطة عامل الضرب القياسي matlabs * ، أو من خلال أي وظيفة أخرى مضمنة في matlab لهذه المسألة. لدى Numpy وظيفة مضمنة (نسيت الاسم) ولكنها أيضًا محدودة إلى حد ما بقدر ما أتذكر.

أنا أيضًا أحتاج إلى تقلصات التوتر في شكلها الأكثر عمومية طوال الوقت ، وهذا هو بالضبط سبب علمي أن تحديد انكماش التوتر الأكثر عمومية ، ناهيك عن تنفيذه بكفاءة ، ليس بالأمر السهل تمامًا. لهذا السبب جادلت بضرورة وجود وظائف خاصة لهذا ، بدلاً من محاولة حشر بعض وظائف نصف العمل أو بالأحرى وظائف محددة في المشغلين القياسيين في قاعدة جوليا ، والتي لا تغطي نصف حالات الاستخدام. ولكن يسعدني أن أغير رأيي ، على سبيل المثال ، إذا كان هناك تقلص "معياري" أكثر أهمية / فائدة من أي تقلص آخر؟ ولكن قد يكون هذا معتمداً بشكل كبير على المجال وبالتالي فهو غير مناسب كقاعدة عامة للتبني في قاعدة جوليا

19-أكتوبر -2014 الساعة 22:52 بعد ذلك thomasmcoffee [email protected] het volgende geschreven

في رأيي ، كان التحديان الرئيسيان اللذان سبق أن تناولناهما في هذه المسألة هما:

(أ) كيفية التمييز بين دلالات الموتر (للتقلصات) ودلالات الصفيف (للبث) عند العمل على بيانات متعددة الأبعاد ؛
(ب) كيفية تضمين الجبر الخطي الواضح والمريح ضمن إطار عمل متسق يعمم على أبعاد أعلى.

ليس من الواضح بالنسبة لي كيف يتعامل هذا الاقتراح مع أي من هاتين المسألتين. بقدر ما أستطيع أن أقول ، لتحقيق (أ) لا يزال يتطلب تلاعب المستخدم المخصص (كما هو الحال مع وظائف اليوم) ؛ وللتعامل مع (B) باستخدام أغلفة كسولة سيتطلب شيئًا مثل ملحقات SubArray التي اقترحها timholy ، وعند هذه النقطة تصبح نسخة كسولة من نهج التقنيع الذي نوقش منذ بعض الوقت. يمكنني تخيل تقديم دعم إضافي لـ (أ) باستخدام آلية كسولة مماثلة (مثل نوع غلاف القائمة) ، ولكن في كل هذه الحالات يبدو لي أن الكسل يجب أن يكون إستراتيجية اختيارية.

لا أعرف كم عدد مشاركة وجهة نظر Jutho القائلة بأن "تقلصات موتر

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub.

هذا هو الانكماش على المؤشر الأخير من A والفهرس الأول من B
نوع من مثل نقطة الرياضيات

function contract(A,B)
   s=size(A)
   t=size(B)
   reshape(reshape(A, prod(s[1:end-1]), s[end]) *  reshape(B,t[1],prod(t[2:end])) , [s[1:end-1]... t[2:end]...]...)
end

لقد كنت دائمًا قادرًا على إجراء تقلصات عامة مع إعادة تشكيل ، وتقلبات ، وربما معقدة
يقارن عند الحاجة أكثر أو أقل مثل ما ورد أعلاه

لست متأكدًا من المشكلة الكبيرة في الموترات حقًا ، فلماذا لا يمكننا فقط تنفيذ عدد قليل منها
المهام؟

نعم بالضبط. في هذه القضية ، كل ما نريد أن نستقر عليه للمضي قدمًا هو

  1. ما هي أبعاد الفهرسة؟ يبدو "نمط APL" غير مثير للجدل.
  2. ماذا يعطي vector' ؟

بالنسبة لانقباضات التوتر ، مع الأنواع المناسبة والوظائف المرحلية ، أعتقد أنه يمكننا بالفعل الحصول على تطبيقات عالية الأداء.

شعوري هو أن المتوترين سيهتمون بأنفسهم وعلينا أن نكون متأكدين
أن مستخدمي الجبر الخطي لا يشعرون بالإحباط.

قلقي الأكبر هو ذلك

(خذ صفًا من صفيف ثنائي الأبعاد) * (صفيف ثنائي الأبعاد) * (خذ عمودًا من صفيف ثنائي الأبعاد)

وهي عملية شائعة لن تنجح إلا إذا أخذناها
(خذ صفًا) مع covector أو ربما أفضل من ذلك
ضع علامة عليها بفهرس فتحة عام.

JeffBezanson ، عندما أقول إن هذه العمليات مدعومة ، أعني أن أنواع البيانات والوظائف المضمنة مصممة خصيصًا مع وضعهم في الاعتبار ، على سبيل المثال ، مثل دالة Mathematica Dot . وبالتالي ، بالنسبة للمستخدم ، هناك طريقة مضمنة وموثقة و / أو واضحة للقيام بأشياء معينة. بالنسبة لأي تصميم ، من الممكن تحقيق الدعم لأي شيء عن طريق إضافة وظائف ، تمامًا كما هو الحال مع التنفيذ الحالي ؛ لذا فهي ليست قضية تعارض تقني ، إنها قضية تصميم.

Jutho ، أنا لا أستخدم MATLAB كثيرًا ، لذا لا يمكنني التعليق. أوافق على أن تصميم NumPy أقل تماسكًا من تصميم Mathematica (كما ناقشت أعلاه) ، ولكنه يدعم أيضًا مجموعة أكثر ثراءً من السلوكيات. أوافق على أن الجبر الخطي الأساسي يجب أن يترك آلية التنسور العامة غير مرئية للمستخدمين الذين لا يحتاجون إليها ، ولكن نظرًا للسمات اللغوية الرائعة لجوليا ، لا يبدو من الضروري تقديم تطبيقات متباينة لهم ، كما فعل كل من NumPy و Mathematica اضطر للقيام به إلى حد ما. بدا لي أن هذه المشكلة تتعلق ، جزئيًا على الأقل ، بإيجاد النظام الموحد الصحيح لكليهما ، للكشف عن التخصصات التي يجب استخدامها لحالات الجبر الخطي الشائعة: على سبيل المثال ، ما يجب فعله حول vector' .

A [1 ،:] * A * A [:، 1] # صف من عمود مصفوفة * مصفوفة * من مصفوفة ؟؟؟

صحيح - عليك كتابة A[1,:]' * A * A[:,1] .

أيضا v '* w عددية؟

نعم ، v'w هي نفس الشيء. أحد الأشياء الجيدة في هذا الاقتراح هو أنه يزيل تمامًا الاختراقات النحوية الرخيصة.

لست متأكدًا مما إذا كانت هذه فكرة ساخنة ...

أنا لا أعتقد أنه هو. أحد أهداف هذا الاقتراح هو جعل قواعد التقطيع والفهرسة متناظرة وهذا من شأنه أن يجعل أحد المؤشرات مميزًا ، والذي يبدو لي أنه يهزم الهدف بأكمله. إذا كان التقطيع سيكون غير متماثل ، فقد نحافظ أيضًا على السلوك الحالي.

thomasmcoffee عليك فقط أن تكون أكثر تحديدًا. بالطبع يريد الجميع أن تكون الأشياء متماسكة وموثقة وواضحة وما إلى ذلك. السؤال هو ، هل الاقتراح المطروح على الطاولة يخدم تلك الأهداف؟ ربما لا يؤثر الاقتراح الحالي على تلك الأهداف على الإطلاق ، وهذا أمر جيد - طالما أنه يؤدي إلى تحسن في مكان آخر ، فلا يزال لدينا تحسن صاف.

لذا اسمحوا لي أن أفهم هذا

إذا لم يكن A مربعًا

| | الحالي | المقترحة | ماتلاب |
| --- | --- | --- | --- |
| أ * أ [1 ،:] | لا | نعم | لا |
| أ * أ [1 ،:] '| نعم | لا | نعم |
| أ [: ، 1] أ | لا |
أ [:، 1] ' أ | نعم | نعم | نعم |

وإذا كانت A مربعة

| | الحالي | المقترحة | ماتلاب |
| --- | --- | --- | --- |
| أ * أ [:، 1] | نعم | نعم | نعم |
| أ * أ [:، 1] '| لا | لا | لا |
| أ [1 ،:] أ | لا |
أ [1 ،:] ' أ | لا | نعم | لا |

أقسم أنني نشرت للتو إجابة على هذا ولكن بطريقة ما اختفت في الأثير. هذا كله صحيح. في الترتيب الحالي ، تحتاج إلى التفكير فيما إذا كنت تأخذ شريحة صف أو شريحة عمود بالإضافة إلى ما إذا كنت تضرب على اليسار أو اليمين عند تحديد ما إذا كنت تريد التبديل أم لا (يتم نقل الأعمدة إلى اليسار ، والصفوف هي منقول إلى اليمين). في الاقتراح ، ما عليك سوى التفكير في الجانب الذي تضرب فيه - فأنت دائمًا تنقل إلى اليسار ، وليس إلى اليمين أبدًا.

هل سيكون بخير إذا

dot(x,y) و dot(x.',y) و dot(x,y.') و dot(x.',y.') تعطي جميعها نفس العدد؟

أي Σᵢ مرفق (xᵢ) * yᵢ

بهذه الطريقة يمكن للمرء أن يفعل النقطة (س ، أ * ص) دون التفكير كثيرًا

هذه الأمثلة من alanedelman تشعر A[i; :] ؟)

ولكن بعد ذلك قد ترغب في أن تعطي covector في الحالة أعلاه.

alanedelman ، لا أرى أي سبب لعدم وجود هذه الأساليب الخاصة بـ dot وتعطي نفس النتيجة.

لقد كنت دائمًا قادرًا على إجراء تقلصات عامة مع إعادة تشكيل ، وتقلبات ، وربما معقدة
يقارن عند الحاجة أكثر أو أقل مثل ما ورد أعلاه

هذا هو بالضبط كيف يتم تنفيذه في وظيفة tensorcontract في TensorOperations.jl ، إذا اخترت طريقة BLAS ، وهي بالتأكيد الأسرع للتوترات الكبيرة. لقد كتبت أيضًا تطبيقًا أصليًا لجوليا ، باستخدام وظيفة Cartesian.jl (ونأمل أن تستخدم يومًا ما الوظائف المرحلية) التي تلغي الحاجة إلى permutedims (تخصيص ذاكرة إضافي) وتكون أسرع بالنسبة للتوتر الأصغر.

كنت فقط أرد على الادعاء الكاذب بأن matlab يوفر وظائف مضمنة لهذا الأمر الذي لا توفره جوليا. يتوفر كل من إعادة التشكيل والمستقيمات في جوليا. يحتوي Numpy بالفعل على وظيفة tensordot التي تقوم بذلك بالضبط ، ولكنها لا تسمح لك بتحديد ترتيب الفهرس لموتّر الإخراج ، لذلك لا تزال بحاجة إلى permutedims بعد ذلك إذا كان لديك ترتيب إخراج معين في الاعتبار.

لكن هذا بعيد جدًا عن الموضوع الحالي ، وهو في الواقع الحصول على سلوك متسق لجبر المتجهات والمصفوفة.

+1 لاقتراح ستيفان. يبدو أنه يعطي دلالات واضحة للغاية ولكنها مرنة بدرجة كافية. باعتباري مستخدمًا للجبر الخطي ، حتى لو اعتاد على بناء جملة أسلوب MATLAB ، فقد وجدت القواعد بسيطة بما يكفي لاستخدامها.

أنا في حيرة من أمري حول ما يفترض أن يعنيه ' بشكل عام. إذا كان v متجهًا ، فإن v' هو transpose . إذا كان a مصفوفة ثنائية الأبعاد ، فإن a' سيكون الآن transpose أيضًا. يبدو أن كلاهما قد تم تعريفهما من أجل القدرة على تكوين b' * a بسهولة عن طريق التعاقد على البعد الأول b مع البعد الأول a .

يبدو أنه لا يوجد إجماع على تعريف a' عندما يكون بُعد a > 2. لم أسمع أحدا يقترح أي شيء آخر غير عكس الأبعاد، وهذا يتزامن مع b' * a التعاقد البعد الأول من b مع البعد الأول من a .

أعتقد أنه سيكون من الجيد لو تمكنا من تحديد ما يفعله ' بإيجاز دون الإشارة إلى حجم الشيء الذي يعمل عليه.

يبدو من المعقول أن يكون لديك وظيفة انكماش أخرى متاحة في Base للحالات العامة ، على سبيل المثال contract(a, b, 2, 3) للتعاقد على البعد الثاني من a مع البعد الثالث من b .

بالمناسبة ، dot(a,b) == a'*b عندما يكون a و b متجهات ، لكن dot(a,b) غير معرّف حاليًا للمصفوفات. هل يمكننا الحصول على dot(a,b) = trace(a'*b) ؟

madeleineudell : أنا في حيرة من

أشارك في هذا القلق. يمكنك أن تأخذ الخصائص 2-5 و 7 و 8 و 10 في اقتراحي على أنها الخصائص المميزة. أي تريد هذا أن يحمل:

  • v' ذو بعد واحد لكنه ليس متجهًا
  • v'' === v
  • v' == v
  • v'w هو عدد قياسي
  • v*w' مصفوفة
  • v'*M هو نفس النوع مثل v'
  • M' ثنائي الأبعاد لكن ليس مصفوفة ، ربما عرض مصفوفة

على وجه الخصوص ، لا توجد قيود على ما يعنيه أو يفعله للصفائف ذات الأبعاد الأعلى. إن النظرية العامة حول ماهية المتغيرات التي تتضمن أبعادًا أعلى ستكون أمرًا رائعًا ، لكنني لست مقتنعًا أنه يمكن فعلها دون تعقيد الأمور كثيرًا ، على سبيل المثال من خلال وجود أبعاد أعلى / أسفل أو تسمية كل بُعد بمؤشر.

من الواضح على الأقل أن القاعدة العامة لـ ' ليست أنها ستعكس الأبعاد ، لأن هذا ليس ما ستفعله للمتجهات والمتجهات.

القاعدة البسيطة الوحيدة التي يمكنني التفكير فيها والتي تلتقط السلوك أعلاه لكل من المتجهات ، والمتجهات ، والمصفوفات هي تبديل البعدين الأولين (المتجه له بعد ثانٍ غائب والمشترك له غائب أول وثاني حاضر).

في 20 أكتوبر 2014 ، في الساعة 09:05 ، كتب toivoh [email protected] :

من الواضح على الأقل أن القاعدة العامة لـ "ليست أنها ستعكس الأبعاد ، لأن هذا ليس ما ستفعله للمتجهات والنواقل.

القاعدة البسيطة الوحيدة التي يمكنني التفكير فيها والتي تلتقط السلوك أعلاه لكل من المتجهات ، والمتجهات ، والمصفوفات هي تبديل البعدين الأولين (المتجه له بعد ثانٍ غائب والمشترك له غائب أول وثاني حاضر).

أود أن أزعم أن هذا ليس صحيحًا إذا كنت تريد التفكير في الموترات العامة. قد يكون هذا صحيحًا إذا كنت تفكر فقط في المصفوفات والمتجهات باعتبارها بعض الكتل التي تحتوي على أرقام ، وتفكر في v كعمود و v كصف.

ومع ذلك ، إذا كنت تعتقد أن v كعنصر من عناصر فضاء متجه ، و w = v 'كطريقة لتعيين v إلى عنصر w في الفضاء المزدوج V_ ، فإن w لا يزال متجهًا ، أي كائن أحادي البعد. بشكل عام ، يحتاج المرء إلى مقياس لتعريف هذا التعيين من V إلى V_ ، أي w_i = g_ {i، j} v ^ j. الآن إذا كان V مساحة ديكارتية ، أي R ^ n بالمقياس الإقليدي القياسي ، فإن V * يكون متماثلًا بشكل طبيعي مع V وهذا يعني أنه لا توجد فكرة عن المؤشرات العلوية أو السفلية (متغير أو مخالف) وبالتالي فإن w_i = v_i = v ^ i = w ^ i. أود أن أزعم أن هذه هي الحالة المستخدمة في معظم البرمجة ، أي الحالة التي تحتاج إلى دعم من قبل Julia Base. (بالنسبة لمساحة متجه معقدة ، يكون V * متماثلًا بشكل طبيعي لـ Vbar ، مساحة المتجه المقترنة ، وبالتالي يكون التعيين الطبيعي w_i = conj (v ^ i).)

إن الاصطلاح للدلالة على المتجهات كأعمدة بأرقام ، والمتجهات المزدوجة كصفوف بها أرقام ، وبالتالي المصفوفات (وهي عناصر V \ otimes V_) ككتل بها أرقام مريحة للغاية ، ولكنها تتوقف بمجرد أن تريد أيضًا التفكير في الأبعاد الأعلى المصفوفات ، أي عناصر مساحات منتج الموتر الأعلى. في هذه الحالة ، "متجه الصف" ، أي كائن ثنائي الأبعاد حيث يكون البعد الأول له الحجم 1 ، لقولها في مصطلحات matlab / julia ، هو بعض عناصر مساحة منتج الموتر V1 \ otimes V2 ، حيث يحدث V1 يكون R (أو مساحة أخرى أحادية البعد). أوافق على أن هذا قد لا يكون ما تريده كسلوك افتراضي ، ولكن مما أفضل أنه لا ينبغي على المرء فقط محاولة تعريف التحويل لمصفوفة عامة والإشارة إلى permutedims ، كما يفعل matlab. إن عكس البعدين الأولين لموتّر عام مثل الاصطلاح الافتراضي لا معنى له. نقل عنصر من بعض مساحة منتج الموتر الأعلى V1 \ otimes V2 \ otimes… \ otimes Vn ليس له تعريف فريد. تنبع اتفاقية عكس جميع الأبعاد من تمثيل رسومي ملائم بواسطة Penrose ، كما هو مشار إليه أعلاه. بالإضافة إلى ذلك ، هذا هو الذي يحدد مساحة المصفوفة (V \ otimes V_) لنفسها (V * \ otimes V * = V \ otimes V ).

يمكنني رؤية طريقتين للمضي قدمًا:
1) اجعل عامل التشغيل الملائم (وربما حتى *) يعمل مع مصفوفات تعسفية ذات ترتيب أعلى باستخدام بعض الاصطلاحات المختارة ، ضمن إعداد الموترات الديكارتية (أي عدم التمييز بين المؤشرات العليا أو الدنيا). قد يجلب هذا بعض النتائج المدهشة لحالات الاستخدام النموذجية.

2) قصر 'و * على المتجهات والمصفوفات. خطأ في المصفوفات ذات الترتيب الأعلى. أعتقد أن هذا هو النهج الأكثر شيوعًا (مثل Matlab إلخ).

هذا المنشور يأخذ جانبًا آخر من الموقف الذي اتخذته العام الماضي ، وذلك

استكشاف التناقض من كلا الجانبين.

آمل أن يكون هذا جيد.
لقد أصابني أخيرًا أن هناك منطقًا للنهج الحالي ، لكن لم يتم توضيحه مطلقًا.
بدا الأمر وكأنه اختراق إلى حد أنه أزعجني. بطريقة ما الآن بعد أن فهمت
أنا أحب ذلك أكثر.

في النهج الحالي ، تكون جميع المصفوفات ذات أبعاد لانهائية مع إسقاط ضمني 1.
قد يعني عامل الفاصلة العليا "تبادل البعدين الأولين ،
ولكن في الواقع كما هو موجود اليوم ، فهذا يعني

ndim (أ) <= 2؟ interchange_first_two_dims: no_op

آسف إذا رأى الجميع ذلك وفاتته للتو. كان عقلي متعثرًا
بفكرة أن النواقل كانت ذات بعد واحد ، وليست ذات بعد لانهائي ، و
لذلك يجب أن يعكس المنقل الأبعاد ، وبالتالي يكون no_op.

أنا بخير مع الفاصلة العليا تفعل هذا ، أو الفاصلة العليا تتبادل دائمًا
البعدين الأولين - لا أعتقد أنني أهتم. أعتقد أن الفاصلة العليا موجودة
للجبر الخطي وليس الجبر متعدد الخطوط.

تلاعبت بما إذا كانت نجمة الفاصلة العليا ("*") (إن أمكن! أو أي شيء آخر إذا كان مستحيلًا)
يجب أن يعني بعد العقد الأخير إلى البعد الأول (مثل نقطة الرياضيات)
ولديها فهرسة apl وليس لها مشتركات. جزء من عقلي لا يزال يعتقد أنه يستحق الاستكشاف ،
لكن بينما أستيقظ ، يبدو أن النهج الحالي يبدو أفضل وأفضل.
(لنرى كيف أشعر لاحقًا اليوم)

لا أندم على بدء هذا الموضوع العام الماضي ، لكني أتساءل مرة أخرى ما هي الحالات
يزعج الناس حقًا اليوم ... هل يمكننا الحصول على قائمة من الأمثلة؟ ... وعما إذا كان
إن تسليط الضوء على هذه الحالات أفضل من تغيير ما نقوم به.

لقد قرأت هذا الموضوع بالكامل وأطلعت على العديد من المبادئ - وهذا أمر جيد ،
ولكن ليس هناك حالات استخدام كافية لوضع رأسي حول الأشياء

أستطيع أن أقول إنني كثيرًا ما أزعجتني

[1 2 3] # ndims == 2
[1،2،3] # ndims == 1
[1؛ 2؛ 3] # ndims == 1

في الأساس لأنني لا أستطيع تذكر ذلك.

مجرد تجربة فكرية. ما الوظيفة التي ستفقد إذا أعدنا تعريف * لتعمل كعامل تقلص مشابه لما يدور في خلد '* ؟ ألن تلغي الحاجة إلى ' في العمليات الجبرية الخطية على الإطلاق (بصرف النظر عن العمل كمحوّل للمصفوفات)؟ يمكنني فقط أن أرى أنه سيحرمنا من المنتج الخارجي w*v' ، والذي يمكن استبداله بسهولة بـ outer(w,v) .

تحرير: بافتراض أن تشريح APL هو. على سبيل المثال A[1,:]*A*A[:,1] ستحصل على النتيجة المتوقعة دون الحاجة إلى نقل المعامل الأول بـ ' .

فكرت في هذا أيضا. أعتقد أن v * w كونه منتجًا نقطيًا يبدو مجرد تحميل زائد على المنشطات
قد يكون ذلك عرضة للخطأ.
هذا مكان واحد حيث لا تبدو نقطة الرياضيات سيئة للغاية.

لتلخيص ذلك ، يبدو أن العقد الأخير إلى الأول معقول ، ولكن
ما إذا كان يمكن أن يكون الفاصلة العليا نجمة أو يمكن أن تكون * أو يجب أن تكون نقطة
لديه مشاكل.

ليست ذات صلة إلى حد ما ولكنها ليست منفصلة تمامًا ...
أود أن أشير إلى أن النقطة النجمية التي يقرأها الجميع على أنها دوت ستار في الأصل (قيل لي) كانت
من المفترض أن تكون نقطة نجمة لأن عامل POINTWISE هو ما
كان من المفترض

أستطيع أن أقول إنني كثيرًا ما أزعجتني

[1 2 3] # ndims == 2
[1،2،3] # ndims == 1
[1؛ 2؛ 3] # ndims == 1

في الأساس لأنني لا أستطيع تذكر ذلك.

لطالما فكرت في السؤال "لماذا لا نستخدم فقط , ؟"

ما الوظيفة التي ستفقد إذا أعدنا تعريف * لتكون بمثابة عامل تقلص مشابه لما يدور في خلد

سوف نفقد الارتباط: على سبيل المثال ، (M*v)*v سيعطي dot(v,M*v) (عددية) ، بينما M*(v*v) سيعطي M.*dot(v,v) (مصفوفة).

لماذا لا نجعل فقط dot عامل الانكماش (وهو ليس ترابطي على أي حال)؟ يمكننا أيضًا تحديد تقلصات الطلبات الأعلى ، على سبيل المثال ddot(A::Matrix,B::Matrix) == A⋅⋅B == trace(A'*B) .

فهل أفهم بشكل صحيح أن الغرض الوحيد من إدخال ناقل الحركة المتجه هو إنقاذنا من عدم الترابط * ؟ يمكن إصلاح الغموض في مثال alanedelman عن طريق نقل أحد المتجهات ( M*v*v' مقابل M*v'*v ) ولكن يمكن فعل الشيء نفسه مع الأقواس ( M*(v*v) مقابل (M*v)*v ) بدون كل متاعب تنفيذ تبديل المتجهات (كما أشار Jutho بالفعل إلى أن تنفيذ تبديل

في الواقع M*(v*v) و (M*v)*v يتم تحليلهما حاليًا كـ

*(M, v, v)

للسماح بمنتج مصفوفة يعمل على تحسين ترتيب الضرب استنادًا إلى أحجام الوسائط ، لذلك يجب تغيير المحلل اللغوي أيضًا.

لكن على الأقل شخصيًا أعتقد أن الترابط أمر كبير جدًا. عليك أن تترجم بين الرياضيات ومعظم لغات البرمجة ؛ بالنسبة لجوليا ، ما زلت آمل ألا تضطر إلى الترجمة كثيرًا.

(كما أوضحتJutho بالفعل أن تنفيذ التحويل

لا أعتقد أن هذا بالضبط ما قلته.

ما الوظيفة التي ستفقد إذا أعدنا تعريف * لتكون بمثابة عامل تقلص مشابه لما يدور في خلد

سنفقد الترابطية: على سبيل المثال (M_v) _v سيعطي النقطة الحالية (v، M_v) (عددية) ، بينما M_ (v_v) ستعطي M._dot (v، v) (مصفوفة).

لماذا لا نجعل النقطة عامل الانكماش (وهو ليس ترابطي على أي حال)؟ يمكننا أيضًا تحديد تقلصات الرتبة الأعلى ، على سبيل المثال ddot (A :: Matrix، B :: Matrix) == A⋅⋅B == trace (A '* B).

باستخدام هذا السطر من التفكير ، لم نعد بحاجة إلى عامل الضرب للمتجهات والمصفوفات بعد الآن ، يمكننا فقط كتابة كل شيء بدلالة النقطة:
أ ∙ ب
أ ∙ v
ت ∙ أ ∙ ث
ت ∙ ث

هذا مجرد اقتراح pwl ولكن مع * تم استبداله

لكن على الأقل شخصيًا أعتقد أن الترابط أمر كبير جدًا. عليك أن تترجم بين الرياضيات ومعظم لغات البرمجة ؛ بالنسبة لجوليا ، ما زلت آمل ألا تضطر إلى الترجمة كثيرًا.

أعتقد أن جزءًا من المشكلة هو أنه حتى في الرياضيات هناك أعراف مختلفة. يفكر من منظور الرياضيات المتجهية للصف والعمود ، أو هل نريد سلوكًا أكثر تجريدًا من حيث العوامل الخطية والمسافات المزدوجة (حيث أعتقد أن عامل التشغيل لا يتم ضربه بمتجه ، بل يتم تطبيقه على متجه ، فلماذا لا نكتب A (v) بدلاً من A * v أو A v)؟

لست في حاجة كبيرة إلى بناء جملة مريح ، فأنا شخصياً أفضل كتابة النقطة (v ، w) على v '* w في كل مرة ، لأن السابق يعبر بشكل أكثر وضوحًا عن الأساس للعملية الرياضية المستقلة (في الواقع ، يحتاج المرء أولاً إلى تعريف المنتج القياسي قبل رسم الخرائط الطبيعية من المتجهات إلى المتجهات المزدوجة حتى يمكن تعريفها)

آسف لكونك جاهلًا جدًا ، ولكن لماذا بالضبط لا يمكن أن يكون M[1, :] منقولًا ، يتصرف مثل v' ؟

سأضيف إلى قائمة الأشياء التي تزعجني

1.

[1 2 3] # ndims == 2
[1,2,3] # ndims == 1
[1;2;3] # ndims == 1

2.
v=rand(3)
v' * v لديه ndims == 1 (اقتراح StefanKarpinski يصلح هذا)
(v' * v)/( v' * v ) لديه ndims ==2 (هذا حقًا يزعجني وسيتم إصلاحه أيضًا)

ما زلت لا أريد حقا covectors
وفهرسة apl هي شيء أستمر في الانتقال إليه ذهابًا وإيابًا
--- ما زلت أفكر ، لكني أحب أن أرى قائمة الأشياء التي
الناس في جوليا الحالية

أنا بالتأكيد أحب فكرة cdotالتعاقد مع آخر مؤشر على المؤشر الأول بالإضافة إلى عامل التشغيل *
والسماح بالنقطة (أ ، ب ، ..) يسمح بالمفاهيم العامة جدًا.

على الرغم من اصطلاح تسمية Numpy (وربما ظهور رسالتي السابقة) ، لدي مشاعر مختلطة إلى حد ما حول استخدام النقطة لتقلصات التوتر العام. هذه هي الجملة الأولى من ويكيبيديا:

في الرياضيات ، المنتج النقطي ، أو المنتج القياسي (أو أحيانًا المنتج الداخلي في سياق الفضاء الإقليدي) ، هو عملية جبرية تأخذ متتابعين متساويين الطول من الأرقام (عادةً ما تنسق المتجهات) وتعيد رقمًا واحدًا.

في رأيي أيضًا ، يجب أن تعيد النقطة عددًا قياسيًا.

@ brk00 ، المشكلة في سؤالك هي أنه ليس من الواضح كيفية توسيع هذا إلى شرائح ذات أبعاد أعلى / مصفوفات ذات مرتبة أعلى (أنا لا أحب الأبعاد العالمية لهذا).

آسف لكونك جاهلًا جدًا ، ولكن لماذا بالضبط لا يمكن أن يكون M [1،:] منقولًا ، يتصرف مثل v '؟

يمكن ، لكن كيف تعمم هذا؟

Jutho ، أنا آسف ، كان يجب أن أصيغها بشكل مختلف. قصدت عبارة "نقل عنصر من مساحة منتج موتر ذات رتبة أعلى [...] ليس له تعريف فريد" ، لذلك لا يوجد دافع رياضي لإدخال تعريف معين ، أو لتعريفه على الإطلاق.

@ alanedelman :

سأضيف إلى قائمة الأشياء التي تزعجني

[1 2 3] # ndims == 2
[1،2،3] # ndims == 1
[1؛ 2؛ 3] # ndims == 1

سلوك التسلسل لا علاقة له بهذه المشكلة. دعونا لا نزيد من تعكير المياه.

تعجبني بالتأكيد فكرة التعاقد مع المؤشر الأخير للفهرس الأول بالإضافة إلى عامل التشغيل *
والسماح بالنقطة (أ ، ب ، ..) يسمح بالمفاهيم العامة جدًا.

هذا أيضا عرضي. دعنا نركز على المصفوفات والتقطيع.


في النهج الحالي ، تكون جميع المصفوفات ذات أبعاد لانهائية مع إسقاط ضمني 1.

هذا ليس صحيحا حقا. إذا كان هذا صحيحًا ، فلن يكون هناك تمييز بين ones(n) ، ones(n,1) ، ones(n,1,1) ، إلخ. ولكن هذه كلها كائنات مختلفة ذات أنواع مختلفة لا تتساوى حتى مع كل منها آخر. نحن نبذل بعض الجهد لتنفيذ الأشياء بحيث تتصرف _بالمثل _ ولكن هذا بعيد كل البعد عن كون المصفوفات في الواقع ذات أبعاد غير محدودة.


قائمة الأشياء المزعجة حاليًا تعكس إلى حد كبير (مجموعة فرعية من) الخصائص الرائعة لاقتراحي أعلاه. يسمى:

  1. سلوك التقطيع غير المتماثل - الأبعاد الزائدة خاصة.
  2. v'' !== v - في الحقيقة v'' != v ؛ هذا لأنهم ليس لديهم نفس الرتبة.
  3. v' != v - نفس الصفقة.
  4. v'w متجه ذو عنصر واحد ، وليس عددًا.
  5. نحتاج إلى تحليل خاص لـ A*_mul_B* ، وهو أفظع شيء على الإطلاق.

أتفق مع معظم نقاط StefanKarpinski ، باستثناء v' == v بت: لا أعتقد أن هذه النقاط يجب أن تكون متساوية. نعم ، قد تكون متشابهة لكنها لا تزال كائنات مختلفة ، من حيث أنها تتصرف بشكل مختلف تمامًا: المصفوفات M و M' هي أيضًا متشابهة ولكن لا أعتقد أننا نريد أن تكون متساوية (إلا إذا كانوا من الهرمي بالطبع).

كانت وجهة نظري العامة للأنواع Covector أنها ستكون خفيفة الوزن نسبيًا: بخلاف العمليات الأساسية (الضرب والإضافة وما إلى ذلك) ، سنتجنب تحديد عدد كبير جدًا من العمليات (حتى أنني سأتردد في تحديد الفهرسة) ). إذا كنت تريد أن تفعل شيئًا به ، فيجب عليك تحويله مرة أخرى إلى متجه والقيام بأشياءك هناك.

+1 لمقابلةsimonbyrne ، بما في ذلك موافقته العامة على رأيStefanKarpinski .

أتفق أيضًا معsimonbyrne.

نعم ، هناك أنواع مختلفة من v و v' ، لكننا نعتبر بالفعل أن أنواع المصفوفات المختلفة التي لها نفس الشكل والبيانات متساوية - على سبيل المثال speye(5) == eye(5) . لماذا يختلف كوفكتور عن المتفرق؟

آمل أن يبث المشاهدون مثل مصفوفات الصفوف. بالنسبة إلى المصفوفات A و B التي تعتبر متساوية ، فإنها تثبت ذلك حتى الآن

all(A .== B)

وهو ما لن يكون هو الحال إذا كان أحدهم متجهًا وواحدًا مشمولًا.

بالنسبة لي ، فإن covector يشبه مصفوفة الصف أكثر من كونه متجهًا أو مصفوفة العمود.

أعتقد أن السؤال الرئيسي هو ما هو size(v' )؟ إذا كانت الإجابة هي (length(v),) فأعتقد أن v == v' يجب أن يكون صحيحًا. إذا كان size(v') == (1,length(v)) فمن المحتمل أن يكون خطأ ، ولكن يمكن القول إذن أن v' == reshape(v,1,length(v)) يجب أن يكون صحيحًا. لذا فإن السؤال هو هل يجب أن يكون v' نوعًا خاصًا من المتجهات أم نوعًا خاصًا من المصفوفة؟

أنا مقتنع بشكل متزايد بأن هذه المشكلة تتعلق حقًا بما يعنيه التحويل حقًا.

Covectors ليسوا في الواقع مصفوفات ، ولذا لا أعتقد أنه يمكننا حقًا تحديد "الشكل" الذي لديهم. يتم تعريف covector حقًا بما يفعله ، وهذا هو *(::Covector, ::Vector) يعطي عددًا: نظرًا لأن أي AbstractVector لا يفعل ذلك ، فهو ليس الشيء نفسه حقًا.

قد تكون هناك مشكلة أخرى في الحقل المعقد: هل سيكون لدينا v' == v أو v.' == v ؟

simonbyrne :

يتم تعريف covector حقًا بما يفعله ، وهذا هو *(::Covector, ::Vector) يعطي عددًا: نظرًا لأن أي AbstractVector لا يفعل ذلك ، فهو ليس الشيء نفسه حقًا.

وهذه نقطة جيدة حقا. ومع ذلك ، قد يكون الأمر محبطًا إذا لم يتم استخدام v' ككائن. ربما يكون الأسلوب الصحيح هو التعامل مع v' كمصفوفة صف مضحكة بدلاً من متجه مضحك.

ربما يكون الأسلوب الصحيح هو التعامل مع v كمصفوفة صف مضحكة بدلاً من متجه مضحك.

نوعًا ما ، لكنني لا أعتقد أنه يجب أن يكون نوعًا فرعيًا من AbstractMatrix أيضًا: أعتقد أن AbstractCovector يجب أن يكون من النوع ذي المستوى الأعلى. يسعدني تحديد length(::Covector) ، لكن لا أعتقد أنه يجب علينا تحديد طريقة size .

لست متأكدًا من التعامل مع البث: ما لم نتمكن من التوصل إلى معايير معقولة ، سأخطئ في عدم تحديد طرق البث.

يبدو أن هذه المناقشة تتقارب نحو استخدام المحولات والمتجهات مثل استخدامها في الهندسة ، أي فكر في كل شيء على أنه مصفوفات. فكر في النواقل كعمود والحمل الحراري كصف. هذا جيد للمتجهات والخرائط الخطية في الفضاء الديكارتي (حالة الاستخدام النموذجية) ، ولكنه يبدأ بالفشل إذا حاول المرء التعميم على الجبر متعدد الخطوط أو على مساحات متجهية عامة وما إلى ذلك. يبدو أن هناك العديد من الالتباسات التي تنشأ من حقيقة أن المساحات الديكارتية ، الكثير من الأشياء متكافئة ولا تعادل المساحات العامة. أنا لست بالضرورة معارضًا لهذا السلوك الافتراضي لجوليا ، لكنني حقًا لا أتفق مع بعض العبارات المذكورة أعلاه كما لو كانت "صحيحة رياضيًا". لذا اسمحوا لي أن تناقض هؤلاء أدناه.

في 20 أكتوبر 2014 ، الساعة 17:39 ، كتب Simon Byrne [email protected] :

أتفق مع معظم نقاط StefanKarpinski ، باستثناء v '== v بت: لا أعتقد أن هذه النقاط يجب أن تكون متساوية. نعم ، قد يكونان متشابهين لكنهما لا يزالان كائنات مختلفة ، من حيث أنهما يتصرفان بشكل مختلف تمامًا: المصفوفتان M و M 'متشابهتان أيضًا ، لكن لا أعتقد أننا نريدهما أن يكونا متساويين (إلا إذا كانا هرميتيين بالطبع).

هذا البيان لا معنى له على أي مستوى.

1) ، أعتقد أنك تسيء استخدام معنى التماثل هنا. متشابهة هي علاقة بين مسافتين (في هذا الإعداد). بشكل عام ، لكل فضاء متجه (حقيقي) V هناك مسافة مزدوجة V * للوظائف الخطية (للمساحات المعقدة ، هناك أيضًا مساحة مترافقة وثنائية الفضاء المترافق). عادةً ما تكون هذه مساحة مختلفة ، ولا يوجد حتى تعيين فريد أو طبيعي من واحد إلى آخر ، أي بشكل عام لا يوجد معنى لربط العناصر v من V بالعناصر phi من V *. العملية العامة الوحيدة هي تطبيق الدالة الخطية ، أي أن phi (v) عددية.

يمكن تحديد التعيين الطبيعي من V إلى V * بمجرد أن يكون لديك شكل ثنائي الخطي V x V -> الحجميات ، عادةً منتج / مقياس داخلي. يمكن بعد ذلك تعريف phi_i = g_ {i، j} v ^ j.

2) ، في الواقع لا توجد عملية طبيعية مرتبطة بـ "تبديل متجه" (انظر النقطة 3). يأتي هذا الالتباس من تحديد المتجهات باستخدام مصفوفات العمود.
بوضعه على الأرجح قويًا جدًا ، أود في الواقع أن أرى أي حالة استخدام لنقل المتجه لا يمكنك الحصول عليها باستخدام النقطة وربما بعض عمليات المنتج الخارجي / المنتج الموتر؟

ومع ذلك ، إذا كنت تريد استخدام التحويل كطريقة لتعيين المتجهات إلى متجهات مزدوجة ، أي لتعيين v في V إلى بعض phi = v 'في V_ ، فأنت تفترض أنك تعمل مع المنتج الداخلي الإقليدي القياسي (g_ { i، j} = delta_ {i، j}). في هذه المرحلة ، أنت تقضي على التمييز بين المؤشرات المتغيرة والمتناقضة ، فأنت تعمل أساسًا مع الموترات الديكارتية ، ويصبح V و V متماثلان بشكل طبيعي. كما هو مذكور أعلاه ، w_i = v ^ i = v_i = w ^ i ، لذا نعم ، v == w وأود أن أقول إنه لا يوجد شيء يميز هذين الاثنين.

3) تم تعريف عملية "التحويل" في الأصل فقط للخرائط الخطية من V -> W (http://en.wikipedia.org/wiki/Dual_space#Transpose_of_a_linear_map) ، وفي الواقع حتى هناك قد لا تعني ما تعتقده. تبديل الخريطة الخطية A: V-> W هي خريطة A ^ T من W _-> V_ ، أي أنها تعمل على المتجهات في W_ ، على متجهات مزدوجة ، وتنتج عناصر V_ ، أي متجهات V. وهذا يعني ، إذا فكرت في الأمر من حيث المنقول المعتاد A ^ T للمصفوفة A ، فإن هذه المصفوفة A ^ T يجب أن تتضاعف مع الأعمدة التي تمثل المتجهات في W * وأن العمود الذي يخرج من هذا يمثل مشتركًا لـ V في هذه المرحلة ، فشل تحديد المتجهات المزدوجة مع متجهات الصف بالفعل.

ومع ذلك ، في حالة الاستخدام النموذجية للمساحات المتجهة الحقيقية حيث يتم تحديد V * و W * بـ V و W عبر المنتج الداخلي الإقليدي القياسي ، يمكن تحديد تبديل الخريطة الخطية مع النقطة المجاورة لتلك الخريطة الخطية ، والتي هي بالفعل خريطة من V-> W كما يعتقد معظم الناس هي أيضًا حالة تبديل الخريطة. في الحالة المعقدة ، يفشل هذا لأن تبديل المصفوفة العادي (بدون اقتران معقد) يكون منطقيًا فقط كخريطة W _-> V_ ، كخريطة W-> V فهي ليست أساسًا تعريفًا مستقلًا وبالتالي فهي غير ذات مغزى تشغيليًا.

فيما يتعلق بما يجب أن يعنيه التحويل للمصفوفات ذات الأبعاد الأعلى ، ضمن نهج matlab / الهندسة الذي نتقارب معه: يجب أن يكون خطأً ، ولا يتم تعميمه. هذا لا يعني أنه لا توجد طريقة لتعريفه. المشكلة هي ، ما الذي تمثله مصفوفة الرتبة الأعلى. هل هي عنصر في مساحة منتج الموتر V1 \ otimes V2 \ otimes… \ otimes VN ، هل هي خريطة متعددة الخطوط تعمل على V1 x V2 x… x VN ، هل هي خريطة خطية من بعض مساحة منتج الموتر V1 \ otimes V2 \ otimes ... \ otimes VN إلى مساحة منتج موتر أخرى W1 \ otimes W2 \ otimes… \ otimes WM؟ بالنسبة للحالة ثنائية الأبعاد ، هناك حل. تحديد الخرائط الخطية A: V-> W مع المتجهات في W \ otimes V_ ، يتوافق التحويل بمعنى الخريطة الخطية مع عكس المسافات في مساحة منتج الموتر هذا ، A ^ i_j -> A_j ^ i مع A ^ T في V_ \ otimes W = V * \ otimes W _ ، وهي بالفعل خريطة من W_ -> V. الشيء الجميل في عكس الأبعاد للكائنات ذات الترتيب الأعلى هو أنه يحتوي على تمثيل رسومي مناسب.

في الختام ، أعتقد أن المشكلة تكمن في ما إذا كانت Julia's Vector بحاجة إلى التقاط خصائص ناقل عام تعسفي بالمعنى الرياضي ، أو ما إذا كان يمثل عمودًا من الأرقام ، أو قائمة ، ... متجه الكلمات ، موتر ، ... - معاني مستقلة تشغيلية وأساسية في الرياضيات ، والتي قد تتعارض مع نوع العمليات التي تريد تعريفها في جوليا فيكتور. في الاتجاه المعاكس ، فإن بعض الكائنات هي في الواقع نواقل من وجهة النظر الرياضية (متجهات مزدوجة ، إلخ) والتي ربما لا ينبغي تحديدها مع Julia Vectors ، لأن نوع Julia (Abstract) Vector القياسي ليس لديه طريقة للتمييز بين فراغات المتجهات المختلفة.

في هذا الصدد ، هناك بعض عدم التناسق ، لأن مصطلح المصفوفة أقل حِملًا ، حتى من وجهة النظر الرياضية ، المصفوفة هي مجرد تمثيل مناسب لخريطة خطية في أساس معين. لاحظ أن هناك أيضًا العديد من الحالات التي لا تريد فيها تمثيل الخريطة الخطية كمصفوفة ، ولكن بدلاً من ذلك كدالة (ظهرت هذه المشكلة من قبل في حجج eigs وغيرها). في هذا الصدد ، أستطيع أن أرى لماذا لم يكلف matlab نفسه عناء امتلاك ناقل ، هيكل أحادي البعد حقًا. في هذا النهج ، يتم تفسير كل شيء على أنه "مصفوفة" ، أي كتلة بها أرقام ، على أي حال.

سؤال؟ اسمحوا c أن يكون covector. ما هو FFT (ج)؟

الجواب: fft (c ')' الذي يأخذ اقترانات معقدة بطرق يحتمل أن تكون غير متوقعة
بالمقارنة مع fft (c)

قد يستفيد المستخدمون فقط من كونها غير محددة
(أو ربما يكون هذا مفيدًا للمستخدمين ، إذا تم توثيقه جيدًا ؟؟)

أراهن أن هناك الكثير من هذه الأنواع من الأشياء

أظن أن الشيء الصحيح الذي يجب فعله في Base في الوقت الحالي هو تحديد:

  • covector مرات ناقل آخر
  • covector ضرب مصفوفة
  • covector 'للحصول على ناقل

+1 لأدنى حد من الدعم للمشاركين في الوقت الحالي.

نعم ، +1.

لذلك إذا ذكرت أنني متأكد من ذلك
يجب أن يكون المعيار (covector ، q) هو المعيار (المتجه ، p) حيث 1 / p + 1 / q = 1
من عدم المساواة هولدر ، الذي لن يتم تنفيذه لفترة طويلة. :-)

شكرا لله على p = q = 2

لن يكون هذا صعب التنفيذ:

norm(c::Covector, q::Integer) = norm(c.vector, q/(1-q))

ربما ترغب في بعض عمليات الفحص الإضافية لتجنب q == 0 و q == 1 .

أعتقد أن q == 1 سيكون بخير

ميد فينليج هيلسن

أندرياس نواك

2014-10-22 15:19 GMT-04: 00 Stefan Karpinski [email protected] :

لن يكون هذا صعب التنفيذ:

معيار (c :: Covector، q :: Integer) = معيار (c.vector، q / (1-q))

ربما تريد إجراء بعض الفحوصات الإضافية لتجنب q == 0 و q == 1.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/4774#issuecomment -60139762.

أنا أعمل على كتابة مقترح covector (والذي أؤيده في الغالب) ، ولكن قد يكون من المفيد أن أنشر الآن نقطة واحدة توضح فكرة

النواقل ليست نواقل ، لكن وصف السبب ليس واضحًا دائمًا. إن covector (أو ناقل حمالة الصدر ، كما يسميه الفيزيائيون) هو دالة خطية تأكل المتجه وتبث رقمًا هو منتج نقطي.

أكثر دقة:

  • دع V = V(F) و W = W(F) يكونان متجهين فوق بعض حقول العناصر F ،
  • v و w يكونان متجهين هما عناصر V و W على التوالي ،
  • <.,.> منتج داخلي مثل <.,.> : V × W → F و v, w ↦ <v, w>

covector المقابل لـ v هو الوظيفة الخطية v' : W → F التي تؤدي التعيين w ↦ <v, w> .

ينتهي الوصف المعتاد بقول أن v' هو عنصر من مساحة مزدوجة V* مع عدم ذكر الكثير عن المساحة المزدوجة _is_.

بالنسبة لأشخاص علوم الكمبيوتر ، هناك وصف بسيط لـ v' ككريم للمنتج الداخلي فيما يتعلق بمعاملته الأولى ، و V* كمجموعة من الوظائف ذات معلمة واحدة الكاري مع ناقلات أولى مختلفة.

قد تكون مقالة ويكيبيديا هذه مفيدة في التوفيق بين الرموز المختلفة المرتبطة بالوصفين ، لكنهما يعبران عن نفس المفهوم تمامًا.

أيضًا ، اعتقدت في البداية أنه يجب عدم السماح بالفهرسة في covector. ومع ذلك ، فإن فهرسة v'[1] تعادل تطبيق v' على متجه الأساس المتعارف عليه e₁ = (1, 0, ...) ، بحيث يمكن تعريف v'[1] على أنه <v, e₁> . المزيد من دلالات الفهرسة العامة مثل 1:n تتبع بشكل طبيعي من تطبيق v' على مصفوفة إسقاط مناسبة مع كون كل عمود متجهًا أساسيًا.

بالنظر إلى دلالات الفهرسة للمشتركين في سياق # 987 ، فإن هذا يعطي سببًا آخر لكون المتجهات ليست AbstractVector s: من غير الممكن بشكل عام فهرسة v' بثمن بخس لأن الأمر كله يعتمد على مدى غلاء الكميات مثل <v, e₁> للحساب. بشكل عام ، يمكن أن يكون لديك منتج داخلي محدد فيما يتعلق بالمصفوفة <v, w> = v'*A*w وتكلفة الفهرسة يهيمن عليها منتج matvec A*w (أو A'*v ) ، وهو بالتأكيد مكلف للغاية بحيث لا يمكن اعتباره AbstractVector .

بما أننا نتحدث عن DFTs والمعايير ... فقد خطر ببالي اليوم

إذا كان f دالة لمتجه وتنتج عددًا قياسيًا ، فأود أن يكون diff(f) دالة تقبل Vector وتنتج Covector بحيث يكون f(x) ~= f(x0) + diff(f)(x0) * (x-x0) . الاستخدام الشائع جدًا للتدرج هو الحصول على تقريب خطي للتغير التدريجي في ناتج الوظيفة بالنظر إلى التغيير التدريجي في الإدخال. إذا كان الإدخال متجهًا ، فمن الطبيعي أن يكون التدرج شيئًا يتقلص على طول جميع أبعاد الإدخال.

ولكن إذا كنت سأذهب إلى تطبيق النسب المتدرج ، فسوف أحتاج إلى إضافة (نسخة مصغرة من) التدرج اللوني عند x لنفسه. وبهذا المعنى ، فإن التدرج هو متجه يشير إلى أقصى اتجاه ، ويتناسب معياره مع معدل التغيير على طول هذا الاتجاه الأكثر انحدارًا.

يقول حدسي إن "تدرج دالة إدخال المتجه عند نقطة ما هو covector" أكثر أهمية.

أظن أن الشيء الصحيح الذي يجب فعله في Base في الوقت الحالي هو تعريف:

covector مرات ناقل آخر
covector ضرب مصفوفة
covector 'للحصول على ناقل

على الرغم من الانطباع الذي قد تكون حصلت عليه من مشاركاتي المروعة السابقة ، +1 لهذا.

ومع ذلك ، بعض الملاحظات على هذا:

أنا أعمل على كتابة مقترح covector (والذي أؤيده في الغالب) ، ولكن قد يكون من المفيد أن أنشر الآن نقطة واحدة توضح فكرة

النواقل ليست نواقل ، لكن وصف السبب ليس واضحًا دائمًا. إن covector (أو ناقل حمالة الصدر ، كما يسميه الفيزيائيون) هو دالة خطية تأكل المتجه وتبث رقمًا هو منتج نقطي.

أعتقد أنه يمكن تعريف المتجهات المزدوجة / المتجهات المزدوجة (أفضل أيضًا مصطلح الوظائف الخطية) دون وجود منتج داخلي. كل ما تحتاجه هو منتج داخلي إذا كنت تريد تحديد تعيين من V إلى V *

أكثر دقة:

دع V = V (F) و W = W (F) يكون متجهًا على بعض مجالات العناصر F ،
تكون v و w متجهين يمثلان عناصر V و W على التوالي ،
<. ،.> منتج داخلي مثل <.،.>: V × W → F and v، w ↦
إنه أمر غريب جدًا ، وأعتقد أنه من المستحيل ، أن يكون هناك منتج داخلي محدد بين مسافتين متجهتين مختلفتين V و W. كيف تحدد خاصية التحديد الإيجابي؟
covector المقابل لـ v هو الوظيفة الخطية v ': W → F التي تقوم بعملية التعيين w ↦.

ينتهي الوصف المعتاد بقول أن v 'عنصر من مساحة مزدوجة V * مع عدم ذكر الكثير عن ماهية المساحة المزدوجة.

أعتقد أنه من الواضح جدًا ، بالتأكيد بالنسبة للحالة ذات الأبعاد المحدودة ، أن الفضاء المزدوج ، باسمه ذاته ، هو فضاء متجه. ومع ذلك ، فإن ملخص حديثي السابق هو أن نوع متجه جوليا (الملخص) أشبه بالقائمة. يمكن استخدامه لتمثيل متجهات معينة ، وهياكل بيانات أخرى أحادية البعد لا تحتوي على البنية الرياضية للمتجه ، ولكنها ليست عامة بما يكفي لالتقاط جميع الكائنات التي هي متجهات رياضية (حيث لا يمكنها التمييز بين المتجهات المختلفة مساحات).

بالنظر إلى دلالات الفهرسة للمتجهات المشتركة في سياق # 987 يعطي سببًا آخر لكون المتجهات ليست متجهات مجردة: ليس من الممكن بشكل عام فهرسة v 'بثمن بخس لأن كل هذا يتوقف على مدى تكلفة الكميات مثل= v'_A_w ويهيمن منتج matvec A_w (أو A'_v) على تكلفة الفهرسة ، وهو بالتأكيد مكلف للغاية بحيث لا يمكن اعتباره ناقلًا مستخلصًا.

هذا نوع من حجة الحلقة. كما هو مذكور أعلاه ، فإن الوظيفة الخطية (covector) أكثر عمومية وتوجد حتى بالنسبة للمساحات المتجهة بدون منتج داخلي. ثانيًا ، عندما يكون المقياس مصفوفة محددة موجبة A ، فإن التعيين الطبيعي من المتجه v إلى covector هو بالفعل v'_A. ومع ذلك ، ما هو هذا v 'هنا؟ هل هو بالفعل تعيين من v إلى covector مختلف معرّف فيما يتعلق بالمعيار الإقليدي القياسي (مع هوية كمقياس)؟ لا ليست كذلك. إذا كانت النواقل تحتوي على مؤشرات متناقضة (عليا) ، وكانت المتجهات لها مؤشرات متغيرة (أقل) ، فإن المتري A يحتوي على مؤشرين منخفضين ويكون المنتج الداخلي= v ^ i A_ {i، j} v ^ j. ولذا يمكن كتابة هذا التعيين كـ (مع phi covector المرتبط بالمتجه v) كـ phi_j = v ^ i A_ {i، j}. (لاحظ أن هذا يختلف عن عامل تشغيل خطي نموذجي ، والذي يكون على شكل w ^ i = O ^ i_j v ^ j). ومن ثم ، فإن v في هذا التعبير v'_A لا يزال هو الذي يحتوي على فهرس علوي ، ولا يزال نفس المتجه.

لذا ، في الواقع ، إحدى النقاط التي كنت أحاول توضيحها أعلاه ، هي أن الناس غالبًا ما يكتبون v 'عندما لا يحاولون حقًا العمل مع شخص مشهور. إنهم يحاولون فقط كتابة التعبيرات المحددة في المتجهات ، مثل المنتج الداخليأو شيء مثل v ^ i A_ {i، j} w ^ j ضمن تمثيل المصفوفة المألوف كـ v'_A_w. حتى المنتج الداخلي الإقليدي القياسي v'w يجب قراءته كـ v ^ i delta_ {i، j} w ^ j ولا يتطلب إدخال مسخنات بالحمل الحراري. كما ذكرنا سابقًا ، أعتقد أن استخدام أدوات التبديل المناسبة الفعلية التي ليست شكلاً خفيًا من المنتجات العددية محدود إلى حد ما في معظم التطبيقات. يكتب الناس فقط v 'ليكونوا قادرين على استخدام صيغة المصفوفة الملائمة ، ولكن ما يفعلونه حقًا هو حساب المنتجات الداخلية وما إلى ذلك والتي يتم تحديدها فيما يتعلق بالناقلات ، وليس المتجهات.

جانبا ، كانت هناك بعض الملاحظات من قبل حول ارتباط الضرب إذا كان لدينا v '== v كما في اقتراح ستيفان الأصلي. ومع ذلك ، حتى بدون هذا ، لن أقول إن * هو ترابطي ، حتى لو كان v 'مشهورًا لا يتم تحديده مع ناقلات عادية:
A_ (v'_w) مصفوفة
(A_v ') _ w ينتج خطأ

إن التدرج اللوني للدالة ذات القيمة العددية هو في الواقع أحد التطبيقات المناسبة للمتجهات ، أي بدون جدال ، يكون التدرج متغيرًا. ما يُفترض ضمنيًا في تطبيقات مثل التدرج المترافق هو أن هناك مقياسًا (وفي الواقع مقياسًا معكوسًا) لرسم خريطة لهذه المتجهات مرة أخرى في المتجهات. وإلا فلا فائدة من القيام بشيء مثل x ^ i (متجه الموقع) + alpha g_i (التدرج اللوني). الطريقة الصحيحة لكتابة هذا هي x ^ i + alpha delta ^ {i، j} g_j حيث delta ^ {i، j} هو المقياس العكسي. إذا حاول المرء تحديد تقنيات التحسين على متشعبات ذات مقياس غير تافه ، فعندئذٍ يحتاج المرء إلى أخذ هذا المقياس (العكسي) في الاعتبار. يوجد كتاب جميل عن هذا:
http://sites.uclouvain.be/absil/amsbook/
وحزمة matlab المقابلة:
http://www.manopt.org

في 22 أكتوبر 2014 ، الساعة 22:52 ، كتب goretkin [email protected] :

بما أننا نتحدث عن DFTs والمعايير ... فقد خطر ببالي اليوم

إذا كانت f هي دالة لمتجه وتنتج عددًا قياسيًا ، فأنا أود أن تكون diff (f) دالة تقبل المتجه وتنتج Covector بحيث تكون f (x) ~ = f (x0) + diff (f) ( x0) * (x-x0). الاستخدام الشائع جدًا للتدرج هو الحصول على تقريب خطي للتغير التدريجي في ناتج الوظيفة بالنظر إلى التغيير التدريجي في الإدخال. إذا كان الإدخال متجهًا ، فمن الطبيعي أن يكون التدرج متجهًا.

ولكن إذا كنت سأعمل على تطبيق النسب المتدرج ، فسوف أحتاج إلى إضافة (نسخة مصغرة من) التدرج اللوني عند x إلى نفسه. وبهذا المعنى ، فإن التدرج هو متجه يشير إلى أقصى اتجاه ، ويتناسب معياره مع معدل التغيير على طول هذا الاتجاه الأكثر انحدارًا.

حدسي يقول إن التدرج هو عامل مشترك أكثر أهمية.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub.

A_ (v'_w) مصفوفة
(A_v ') _ w ينتج خطأ

يا للحماقة.

b2e4d59001f67400bbcc46e15be2bbc001f07bfe05c7c60a2f473b8dae6dd78a

كان هذا الموضوع متأخراً عن مشاركة تحتوي على صورة فكاهية.

Jutho أعترف بأنني لا أستخدم الشكل الأكثر عمومية للمساحة المزدوجة ، لكنني لا أرى كيف يكون وصفي دائريًا على الإطلاق نظرًا لاختياري لتحديد مساحة مزدوجة باستخدام إطار مساحة Banach. إن شكليات الفضاء في Banach هي بالفعل مبالغة في المساحات المتجهة ذات الأبعاد المحدودة على أي حال.

التعميم ليس المصطلح الصحيح في الواقع. ما كنت أحاول قوله في تلك الفقرة هو أنه يمكنني عكس هذا الخط المنطقي فيما يتعلق بالتقييم الفعال للمدخلات ، لأنه على سبيل المثال في حالة التدرج (المترافق) في الفتحات المنحنية ، أعتقد أن التدرج اللوني (covector) g_i يمكن حساب

  1. الفضاء المزدوج هو بالتأكيد فضاء متجه ، وبالتالي فإن عناصره عبارة عن نواقل. ومع ذلك ، لا ينبغي أن يكون الهدف هو أن تكون جميع الكائنات التي لها المعنى الرياضي للمتجه نوعًا فرعيًا من جوليا AbstractVector ، ولا يجب أن تكون جميع الكائنات التي هي أنواع فرعية من AbstractVector لها الخصائص الرياضية المناسبة من ناقلات. بهذا المعنى ، يعجبني الاسم Matrix أكثر بكثير من الاسم Vector ، لأنه يحتوي على دلالة أقل بكثير. ومن ثم ، أعتقد أنه يمكنني الموافقة على حقيقة أنه ، مهما كان نوع Covector الذي يتم تقديمه كجزء من هذا الاقتراح ، يجب ألا يكون نوعًا فرعيًا من AbstractVector أو حتى AbstractArray ، حتى في الحالات التي يكون فيها V * متماثلًا بشكل طبيعي مع V (الفضاء الديكارتي ، والذي يشكل على الأرجح نصف التطبيقات).
  2. يتيح لك المنتج الداخلي إنشاء تعيين من V إلى V_ ، ولكنه ليس شرطًا أساسيًا لوجود V_. بالتأكيد ، هذا يبدو وكأنه مشكلة غير ذات صلة لأنه في البرمجة لديك دائمًا مساحة متجهة ذات أبعاد محدودة وهناك دائمًا منتج داخلي (على الرغم من أنه قد لا يكون ذا صلة بالتطبيق) ، ولكن النقطة العملية التي كنت أحاول القيام بها جعل هذا. هناك تطبيقات مناسبة للمشتركين في البرمجة ، مثل مثال التدرج اللوني الجميل من قبل v' ، فهم لا يحاولون حقًا إنشاء covector ، بل يحاولون فقط كتابة خط ثنائي التعيين بين متجهين (على سبيل المثال V x V إلى scalar) ، كما في v'_A_w = v ^ i A_ {i، j} w ^ j أو حتى v'w = v ^ i delta_ {i، j} w ^ j باستخدام تمثيل المصفوفة المناسب. أفضل أن أكتب dot(v,A*w) صراحة ، لكن هذا اختيار شخصي. نظرًا لعدم وجود معلومات حول المؤشرات العلوية أو السفلية في المصفوفات ، يمكن للمرء إنشاء حالات استخدام حيث يمكن أن يكون كلاهما في تعبير قياسي مثل v'*A*w كلاهما v' و w إما متجهات أو متجهات بالمعنى الرياضي. النتيجة الوحيدة لذلك هي أنني لست متأكدًا مما إذا كنت سعيدًا حقًا باستدعاء نوع v' Covector ، تمامًا مثل الاسم Vector فهو يحتوي على الكثير من الرياضيات دلالة قد لا يكون لها ما يبررها في معظم التطبيقات ، مما يؤدي بعد ذلك إلى المزيد من المناقشات (غير ذات الصلة في الغالب) مثل هذا تمامًا.

jutho +1 لأن التدرج متنوع
تعلمت هذا لأول مرة من أطروحة الدكتوراه لستيف سميث واستخدمت هذه الفكرة
لشرح هذه الفكرة الغامضة للتدرج المترافق لحسابات القيمة الذاتية بوضوح
التي اعتاد الناس التحدث عنها في الكيمياء والفيزياء.

لقد شعرت بالذهول بشكل متزايد حول مدى الاتساق الداخلي
ومكتفٍ بذاته هو عالم الموترات من المرتبة 2 مع مؤشر علوي واحد وآخر سفلي هو.
هذا ما نسميه تقليديًا حسابات المصفوفة أو مجرد الجبر الخطي القديم البسيط.
هيك ، بينما يمكنني العثور على الكثير من الأمثلة مثل القاعدة (v ، p) أو fft (v) حيث الوظائف
تختلف إذا كانت نواقل أو ناقلات ، فأنا حقًا ليس لدي مثال واحد جيد (حتى الآن!)
لدالة مختلفة بشكل طبيعي في متجه ومصفوفة عمود واحد.
(شخص ما يساعدني ، بالتأكيد يجب أن يكون هناك واحد ، حتى كثير !!)

أنا أيضًا منذ عدة سنوات حتى الآن كنت مهتمًا مثل jutho هذا المتجه المجرد
لم تجد المساحات طريقها إلى جوليا بعد ، أتذكر الدردشة معStefanKarpinski
عن هذا في السبورة منذ سنوات. لا تزال الاهتمامات الشاملة
1) يجب أن يتمتع القادمون الجدد إلى جوليا بتجربة سهلة و
2) الأداء
يجب أن يتفوق على هذه الأشياء الفاخرة.

كنتيجة للحديث مع jiahao ، لقد مميزين جدًا:
الجبر الخطي (المصفوفات التي تحتوي على كونترا واحد وتكوين واحد) وهناك موترات بسيطة
(الجميع مشارك ، لا كونترا). هذا الأخير يعمل بشكل جيد في APL an Mathematica.
الأول يشمل الجبر الخطي وقد تم التقاطه بشكل أفضل في MATLAB من قبل
لقد تم تطعيمهم على مصفوفات ذات أبعاد أعلى من 2. هناك عمومية أكمل
الذي بدا بعد كلمة مع JeffBezanson وكأنه لم يكن مجنونًا جدًا.

بالمناسبة ، أعتقد أن الأمر استغرق حوالي عام إن لم يكن أكثر ، لكننا أخيرًا نتعامل مع هذا بجدية :-)

بخصوص
A_ (v'_w) مصفوفة
(A_v ') _ w ينتج خطأ

فقط ضرب المصفوفة "*" هو ترابطي. لم تكن مصفوفة الأوقات العددية المثقلة بالحمل أبدًا
ترابطي. ولا حتى في الرياضيات ، ولا حتى في MATLAB.

A_ (v'_w) مصفوفة
(A_v ') _ w ينتج خطأ

مسكة جيدة. هل هناك أي حالات بالرغم من عدم وجود أخطاء تنتج إجابات مختلفة؟ سؤال ذو صلة: ما الذي يجب أن يفعله المقياس القياسي؟

لم تكن مصفوفة الأزمنة العددية المحملة بالزيادة مرتبطة أبدًا. ولا حتى في الرياضيات ، ولا حتى في MATLAB.

العمليات التي تتضمن المصفوفات والقياسات فقط هي عمليات ترابطية (انظر النقطة 3). نظرًا لأنه يمكننا التعامل مع المتجهات على أنها مصفوفات عمود واحد ، فإن تضمينها لا يسبب مشكلة أيضًا. التجعد هنا هو أن Covector هو عامل يمكنه تقليل الأبعاد (متجهات الخريطة إلى الحجم القياسي) ، لذلك لست متأكدًا من كيفية تناسب ذلك.

تعد إضافة المصفوفة العددية مصدر قلق أكبر ، لأن ذلك يفسد التوزيع (على الرغم من أنني إذا كنت أتذكر بشكل صحيح ، أعتقد أن النقاش قد تم حله للحفاظ عليه):

(A+s)*v != A*v + s*v

هذا ملخص رائع للغاية:

كنتيجة للحديث مع jiahao ، لقد مميزين جدًا:
الجبر الخطي (المصفوفات التي تحتوي على كونترا واحد وتكوين واحد) وهناك موترات بسيطة
(الجميع مشارك ، لا كونترا).

من الواضح أن هذه المناقشة لا تتعلق بدعم الحالة الأكثر عمومية ، وهذا أمر محير للغاية بالنسبة للأشخاص الذين لا يحتاجون إلى العمومية الكاملة ، ولا يمكن تضمينهم في التسلسل الهرمي AbstractArray الحالي وهو أكثر ملاءمة للحزمة (التي أعمل عليها بالفعل على). لكن المناقشة هي في الواقع ، أي من هذين العالمين الخاصين نريد دعمهما ، لأنهما غير متوافقين بشكل متبادل.

في السابق ، جميع المتجهات v هي أعمدة ، وكل v' عبارة عن متجهات مشتركة وجميع المصفوفات عبارة عن عوامل تشغيل خطية V-> W (على سبيل المثال ، تعيش في W ⊗ V_). الخرائط V x V -> scalar (على سبيل المثال v ^ i A_ {i، j} w ^ j) لأن هذا يتطلب مصفوفة ذات مؤشرين منخفضين (مثل العيش في V_ ⊗ W_) بالطبع ، لا يزال بإمكانك استخدامه عمليًا وكتابته كـ v'_A*w ، لكنه نوع من التعارض مع التسمية المختارة للكائنات. بالإضافة إلى ذلك ، لا يحدد المكان الذي تعيش فيه مصفوفات الترتيب الأعلى.

تحل الحالة الأخيرة هذه المشكلة نظرًا لأنها (V == V *) ، ولكنها تؤدي إلى نتائج مفاجئة مثل v' == v . بالإضافة إلى ذلك ، يقتصر هذا الحل فعليًا على المساحات المتجهية الحقيقية ، لأنه حتى في المساحات المعقدة ذات المنتج الداخلي الإقليدي القياسي (أي "الفضاء الديكارتي المعقد") ، فإن المساحة المزدوجة لا تتشابه بشكل طبيعي مع V بل مرتبطة (V) (V شريط) ، فضاء المتجه المقترن (انظر مساحات هيلبرت في http://en.wikipedia.org/wiki/Complex_conjugate_vector_space)

فيما يتعلق بعدم الترابط ، في هذا الصدد ، فإن السلوك الحالي ، حيث v'*v لا ينتج عددًا بل مصفوفة ، هو في الواقع أكثر اتساقًا ، منذ ذلك الحين A*(v'*v) و (A*v')*v ينتج خطأ

يمكن أيضًا حل جانب "الجبر الخطي" للأشياء في خيارات مختلفة لكيفية تمثيل المتجهات والمتجهات:

  • The Covector ، المعروف أيضًا باسم "ناقل الصف المضحك" الذي ناقشناه مؤخرًا.
  • دلالات "لا توجد نواقل حقيقية" التي تخلط (متجهات N مثل مصفوفات Nx1) ، (متجهات الصف N مثل مصفوفات 1xN) ، التي أقرتها Matlab وما شابه ذلك.
  • طريقة جوليا الحالية - لا تخلط بين متجهات N الكثيفة ومصفوفات Nx1 ، وقم بدمج متجهات N المتفرقة ومصفوفات Nx1 ، وتمثل متجهات الصف N كمصفوفات 1xN.

أتساءل عما إذا كان من الضروري تمامًا الخلط أيضًا (العددية ، والمتجهات 1 ، والمصفوفات 1 × 1) في عالم "عدم وجود نواقل حقيقية" ؛ كنت أنا و alanedelman نناقش هذا بالأمس وفي الجبر الخطي العددي ، يتم استخدام تبديل المتجه * العددية والعدادية * في كل مكان ، ومع ذلك ، فإن المتجه * المنتج القياسي هو المنتج الذي لا يهتم إذا كان يعمل (N ،) * ( ،) أو (N ، 1) * (1،1).

1) في نهاية اليوم أهم الأشياء أ) سهولة الاستخدام و ب) الأداء.
2) يجب أن يكون العالمان قادرين على التعايش في وئام تام. عند القيام بعمل هندسي ، فإن رأيي هو أنه لا يوجد شيء أكثر سهولة وبديهية من تدوين الموتر. اقتراح واحد ، إذا جاز لي ، قد يكون لتمكين علامة بيئة أو يمكن استيراد حزمة في بداية البرنامج. سيسمح ذلك بسهولة الاستخدام ومنطق البرمجة المباشر. أليس هذا ممكنًا أم يجب أن نختار مخططًا شاملاً واحدًا؟

يبدو أن هناك خياران
1) تمكين استيراد صندوق أدوات أو رقعة أو علامة بيئية للعمل بشكل متزامن
2) بناء لغة قادرة على توحيد العوالم الخاصة ، ومع ذلك تظل سهلة الاستخدام وسريعة

لست متأكدًا من مدى نجاح هذا ، لكنني عثرت على مجال بحث مثير للاهتمام.

هل لي أن أوجه انتباهكم إلى:

مجموعة أبحاث الجبر الهندسي
http://www.mrao.cam.ac.uk/~clifford/pages/introduction.htm

دورة محاضرة في الجبر الهندسي
http://www.mrao.cam.ac.uk/~clifford/ptIIIcourse/course99/

التطبيقات الفيزيائية للجبر الهندسي
http://www.mrao.cam.ac.uk/~clifford/ptIIIcourse/

لغة رياضية موحدة للفيزياء والهندسة في القرن الحادي والعشرين
http://www.mrao.cam.ac.uk/٪7Eclifford/publications/ps/dll_millen.pdf

الجبر الهندسي
http://arxiv.org/pdf/1205.5935v1.pdf

أسس حساب الجبر الهندسي
http://link.springer.com/book/10.1007٪2F978-3-642-31794-1

حساب الجبر الهندسي
http://link.springer.com/book/10.1007٪2F978-1-84996-108-0

بعد النظر في هذا الأمر أكثر قليلاً ، يبدو رائعًا حقًا.

طالما تم الفصل بين الجبر والهندسة ، فإن تقدمهما كان بطيئًا واستخداماتهما محدودة ؛ لكن عندما اتحد هذان العلمان ، فقد أعار كل منهما قواهما المتبادلة ، وسارا معًا نحو الكمال.

  • جوزيف لويس لاجرانج

تخيل أنك بحاجة إلى نظارات ولا تعرف أنك بحاجة إلى نظارات. ثم ، عندما تحصل على نظارات ، يتغير العالم بشكل غير متوقع. GA مثل النظارات لداخل عقلك.

  • بابلو كولابينتو

يبدو أن هذا الرجل لديه الفكرة الصحيحة ... https://github.com/wolftype/versor

تحتوي مكتبات عمليات المصفوفة النموذجية على وظائف مضمنة نموذجية لضرب المتجهات والمصفوفة. يجمع الجبر الهندسي بين العديد من الرياضيات الأخرى (المصفوفة ، والموتر ، والمتجه ، والجبر الكذب). إن Versor متشابه ، ولكن على المنشطات ، حيث يطلق على المتجهات والمصفوفات المتناثرة ذات الأحجام المختلفة فقط المقاطع المتعددة وتمثل العناصر الهندسية التي تتجاوز اتجاهات xyz ومصفوفات التحويل فقط. الدوائر ، والخطوط ، والكرات ، والمستويات ، والنقاط كلها عناصر جبرية ، مثلها مثل المشغلين الذين يدورون ، ويلويون ، ويمددون ، ويثني هذه المتغيرات. كل من هذه العناصر والمشغلين عبارة عن نواقل متعددة تتكاثر معًا بعدة طرق مختلفة.

يتناول هذا الفيديو بعض التفاصيل الجيدة حول Versor ، لغة الرياضيات المبرمجة GA.
https://www.youtube.com/watch؟v=W4p-e-g37tg

هذه هي الشرائح لهذا. https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/generic_spaces.pdf

يمكنك إجراء بعض حسابات الموتر المذهلة ، بسهولة حقًا ، محسّنة للسرعة عند التجميع.

@ esd100 ، أعتقد أنه سيكون من المفيد إبقاء المناقشة حول هذا الموضوع مركزة على القضية المحددة في العنوان.

johnmyleswhite لقد بحثت عن مصطلح "tensor" وقد ورد ذكره 171 مرة (الآن 172 مرة). بينما أتفق مع بيانك ، بشكل عام ، يحتوي هذا الموضوع على 157 تعليقًا (الآن 158) ، بعضها يتعامل بشكل مباشر وغير مباشر مع عنوان المنشور الأصلي (أخذ نقل المتجه على محمل الجد). أعتقد أن رسالتي تتعامل بشكل غير مباشر مع عنوان المنشور الأصلي من خلال تقديم منظور متزايد لما يمكن فعله بالتطبيقات الجديدة لرياضيات التنسور ، عبر الجبر الهندسي. رأيي هو أن بناء هذا النوع من القوة عالية الأبعاد التي يمتلكها فيرسور في جوليا سيكون ميزة مفيدة إضافية لجوليا. كان عنوان فيديو اليوتيوب هو "البرمجة العامة للمساحات العامة: ترجمة الجبر الهندسي مع C ++ 11". لا أفهم لماذا لا يمكن أن تكون جوليا بدلاً من C ++. ثم مرة أخرى ، أنا لست عالم رياضيات أو عالم كمبيوتر.

@ esd100 الجبر الهندسي مثيرة للاهتمام ، لكنها ليست أكثر الأشياء التي تغطيها هذه المشكلة عمومًا. الجبر الهندسي الذي سنهتم به في المقام الأول هو الجبر Clifford الحقيقي Cl (R ^ n ، I) ؛ ومع ذلك ، سنكون مهتمين أيضًا بجبر Clifford الأخرى التي ليست _جبر هندسي ، مثل Clifford algebras مثل المتجهات المعقدة Cl (C ^ n ، I) أو حتى الجبر فوق الحقول التعسفية أو الحلقات غير التبادلية Cl (F ^ n ، I) . علاوة على ذلك ، لا نريد حصر أنفسنا بالضرورة في جبر كليفورد ، لكننا نريد أن نفكر في كيفية تعميم الجبر الخطي على إعداد جبر الموتر الأكثر عمومية حيث لا يتم تعريف الأشكال التربيعية (المنتجات الداخلية) بالضرورة.

في إعداد الجبر الموتر ، فإن اقتراح " v' هو اقتراح غير عملي " في OP منطقيًا تمامًا ، نظرًا لأنه يعمم باستمرار على الامتدادات ثنائية الجبر التي تؤدي إلى موتر الفحم حيث يكون اقتراح "v" ينتج covector "أمرًا طبيعيًا جدًا. لست متأكدًا من كيفية تعميم اقتراح "عدم وجود متجه حقيقي" في جبر موتر.

jiahao شكرا

لست متأكدًا مما إذا كانت هذه المناقشة لا تزال جارية ، لكنني أردت مشاركة رأيي لأن هذه القضايا هي بعض من أهم (ومزعج) أجزاء مني باستخدام جوليا. أتفق مع بعض ما ورد أعلاه والبعض الآخر لا أوافقه.

في الأساس ، أعتقد أننا بحاجة إلى إدراك هذا: سيحتاج جميع مستخدمي Julia إلى مصفوفات سريعة ومتعددة الأبعاد (لتخزين البيانات) كما تم تنفيذها بالفعل في Julia. سيكون العديد / معظم المستخدمين مهتمين أيضًا بالجبر الخطي ، وتعد المصفوفات المذكورة أعلاه طريقة ملائمة لتعبئة البيانات الموجودة في المتجهات والمصفوفات. سيريد عدد قليل من المستخدمين القيام بجبر موتر عام (متعدد الخطوط).

السؤال هو كيف نوسع هذه المصفوفات "العارية" إلى المفاهيم الرياضية للجبر الخطي؟ كيف تجعل بناء الجملة يشبه الرياضيات العادية؟ هل سيكون الناس مرتاحين لأن v ''! = v؟ إلخ ، إلخ.

أول شيء هو أننا لا نريد أن نجعل المصفوفات أسوأ ، فقط حتى نتمكن من إجراء الجبر الخطي. لا نريد إضافة بيانات إضافية إلى Vector أو وسائط قالب غير ضرورية إلى Array. نريد أن نكون أسرع مثل C / C ++ عندما لا نقوم بالجبر الخطي (ونأمل أن تكون أسرع مثل C / fortran ، عندما نكون كذلك).

الشيء الثاني الذي يجب أن ندركه جميعًا ، هو أن تقلص التوتر الكامل متعدد الأبعاد يتطلب كميات كبيرة من المعلومات الإضافية. بالنسبة إلى الموترات ثنائية الأبعاد ، اكتب أي عملية ضرب مثل A_B'_C * D ... بينما بالنسبة إلى الموترات العامة ، من الطبيعي التفكير في رسم بياني لتعريف الانكماش (مخطط شبكة موتر ، أو رسم بياني عامل - نفس الشيء ينطبق بالعديد من الأسماء المختلفة). بالنسبة إلى الموترات عالية الأبعاد ، من المنطقي لف المصفوفات المجردة وتزيينها بمساحات متجهة ، وما إلى ذلك لتتبع كل شيء. يمكن القيام بذلك في حزم مثل تلك التي يعمل عليها Jutho (وربما غيرها). لا جدوى من النظر في معنى "على موترات ثلاثية الأبعاد + - لن يهتم أحد باستخدام هذه الوظيفة عند وجود العناصر المؤقتة ، أو إذا كانوا يستخدمون حزمة موتر مخصصة.

سيحتاج المستخدمون الأساسيون إلى مضاعفة المصفوفات وإضافة المتجهات وما إلى ذلك. سوف يرغبون في تبديل المصفوفات. سوف يريدون أيضًا منتجًا داخليًا ومنتجًا خارجيًا. سواء أعجبك ذلك أم لا ، يتم تحديد هذه بالاقتران مع مساحة مزدوجة. نحن نعلم ما تعنيه هذه الأعداد الحقيقية والأعداد المركبة ، ونعرفها مسبقًا. ونعم ، صحيح أن المساحة المزدوجة لمساحة متجهة محدودة حقيقية تبدو وكأنها في الأساس نفس الشيء ، وأعتقد أن هذا هو ما يفسد المشكلة برمتها. أكبر مشكلة حالية هي أنه ليس لدينا متجه مزدوج مناسب. بدونها ، لا يمكننا "كتابة" المعادلات في جوليا كما نفعل على الورق والقلم - مشكلة كبيرة! والأهم من ذلك ، ليس لدينا v '' = v. هذا غير بديهي للغاية.

سيرغب الناس أو يحتاجون فقط إلى إنشاء متجه مزدوج لأداء المنتجات الداخلية أو الخارجية. يعد الغلاف الزخرفي البسيط لإخبار المترجم ما يجب فعله عندما يواجه * حلاً معقولًا ويجب ألا يكون له أي وقت تشغيل إضافي. أعتقد أن هذه المتجهات المزدوجة / المتجهات المزدوجة يجب أن تكون قابلة للفهرسة ، قابلة للإضافة / قابلة للطرح ، مضروبة في عدد قياسي ، مضروبة في متجه (إرجاع عددية) ومضروبة في مصفوفة (إرجاع covector) - وهذا كل شيء! لن أقوم صراحةً بإجراء الاقتران المعقد للمتجهات المعقدة - التي يمكن تضمينها في المنتج النقطي ، والمنتج الخارجي ، والفهرسة ، وما إلى ذلك لتحسين السرعة / الذاكرة.

لست قلقًا من أننا نضيف تعقيدًا إلى نظام الكتابة. أعتقد أن هذا ضروري لتلخيص الرياضيات كما تعلمها المستخدمون في المدرسة الثانوية والجامعة: أن يكون لديك ترابطية * (حيثما تكون محددة جيدًا) ، وأن يكون لديك v '' = v ، وأن يكون لديك كل من "حمالات الصدر" و "مجموعات" (I أستخدم هنا تدوين ديراك للجبر الخطي) ، إلخ.

راجع للشغل إذا تم تنفيذ هذه الأشياء في Julia 0.4 ، فأنا غافل! ما زلت أعمل على فهم 0.3.4 ...

andyferris ، أتفق بشكل عام مع كل هذا. أعتقد أنه يمكن تعديل اقتراحي هنا بشكل طفيف ويعمل بشكل جيد: بدلاً من أن يكون M*v' خطأ ، اجعله ينتج عنه covector وبدلاً من أن يكون v*M خطأ ، اجعله ينتج متجهًا. بالنسبة لي ، هذا يصل إلى M كونه حياديًا حول ما إذا كانت أبعاده أعلى أم لأسفل - يمكنك كتابة v'*M*w أو v*M*w' لمنتج داخلي وسيعمل أي منهما.

يعتقد أحدهم أن هناك مصفوفات صفية رئيسية وعمودية كبيرة ووجود M.' يتغير من واحد إلى الآخر وبالمثل يكون v' هو الاختلاف الرئيسي في v - له نفس الشكل ولكن يتم تخزينه من الناحية النظرية بالترتيب الآخر. لست متأكدا من هذا بالرغم من ذلك.

+1 إلى andyferris . أعتقد أيضًا أننا نريد فقط أنواع غلاف بسيطة Transpose و ConjTranspose تسمح لنا باستخدام صيغة جبر المصفوفة الموجزة لكتابة منتجات المتجهات والمصفوفات وعمليات النقل منها. فيما يتعلق بالنقطة 2 من اقتراح StefanKarpinski ، لن AbstractArray ولن أجعل الأنواع جزءًا من التسلسل الهرمي للنوع AbstractArray نفسه. يجب أن يكون Transpose(x) هو النوع الذي ينتج عن كتابة x' في تعبير ويسمح بتأجيل التقييم / التقييم الكسول ، اعتمادًا على باقي التعبير ، عن طريق إرسال Transpose لبقية العمليات في التعبير (والذي من المحتمل أن يكون عامل الضرب * في 99.9٪ من الحالات). ومع ذلك ، يجب أن يكون الأشخاص قادرين أيضًا على إعطاء هذا الصياغة معنى للأنواع الجديدة التي قد لا تكون جزءًا من التسلسل الهرمي AbstractArray ، مثل كائنات عامل المصفوفة أو الأنواع الأخرى لتعريف عوامل التشغيل الخطية على سبيل المثال.

بالنسبة للحالة المحددة للمصفوفات والمتجهات ، لا أرى حقًا حالة استخدام M*v' ، لكنني لا أعارضها بشكل جوهري. الشيء المهم هو أنه يفي بالتوقعات الأساسية (أي القواعد 2،4،5،6 و 8 في نهاية اقتراح ستيفان).

ربما تكون النقطة الأخيرة الرئيسية للمناقشة هي التفاعل مع التقطيع. هل يجب أن تكون شريحة الصف من المصفوفة تلقائيًا Transpose ؟ تصويتي هنا على قواعد تقطيع APL حيث ليس هذا هو الحال.

Jutho ، الدافع هو جعل * ترابطية - A*(v'w) و (A*v')*w كلاهما يعمل وينتج نفس النتائج ، modulo non-associativity لنوع العنصر الأساسي (على سبيل المثال ، عائم- نقطة).

من أجل (A*v')*w لإعطاء نفس النتيجة A*(v'*w) ، A*v' سوف تحتاج إلى أن يكون N=3 مجموعة. غير أن ما كان في الحسبان؟ لقد فاتني هذا تماما.

حسنًا ، ممتع جدًا ، لدي بعض التعليقات.

نحتاج أولاً إلى معالجة المستخدمين الأساسيين. بشكل أساسي ، يعد استخدام Array{T,n} كـ n تخزين الأبعاد أولًا وقبل كل شيء وظيفته الأساسية. يجب أن يكون منطقيًا للمبرمجين الذين ليس لديهم فكرة عن الجبر الخطي ولكنهم يريدون معالجة البيانات في جوليا. لهذا السبب ، لا يمكن لشريحة مصفوفة إرجاع متجه مشترك تحت أي ظرف من الظروف! هذا هو مفهوم الجبر الخطي الصارم الذي ينطبق فقط على أنواع بيانات معينة T والتي يمكن أن تحدد فضاء متجه وثنائي (مثل البيانات الرقمية أو "الحقول").

يمكنني الذهاب في كلتا الحالتين مع تقطيع APL. يبدو بديهيًا بدرجة كافية. إنه نوع مستقر ولا يفعل أي شيء مفاجئ. على الرغم من أنني لا أعتقد أنه من الضروري إجراء هذا التغيير لجعل الجبر الخطي متسقًا ذاتيًا ... قد يكون لطيفًا (على الرغم من أنه قد يكون تغييرًا مفاجئًا). أجد أنه من المقلق أن يكون حجم M[1,:] 1xn و M[:,1] هو الحجم n (وليس nx1) ... يبدو غير متماثل للغاية ... لكنني أعتقد أنه تذكير جيد بكيفية سير الأمور وضعت في الذاكرة. على أي حال .. يجب إجراء هذا التغيير فقط إذا كان من المنطقي تخزين البيانات المجردة ومعالجتها. بالنسبة لي ، هذا التغيير متعامد مع مناقشة الجبر الخطي.

لذا ، حتى لو لم نطبق قواعد تقطيع APL ، فلا يزال بإمكاننا إنقاذ الجبر الخطي ذي المعنى بشكل مباشر تمامًا. إذا كنت ترغب في i عشر ناقلات عمود من M الدعوة colvec(M,i) وإذا كنت ترغب في i عشر الصف شارك متجه M الدعوة rowvec(M,i) . إذا كان i عبارة عن tuple أو متجه ، فيمكنه إرجاع tuple أو متجه أو متجه (co) (هل يمكن أن يكون هذا مفيدًا في التفكير في الموازاة في بعض الحالات؟). إذا كنت تفضل مصفوفة ، فما عليك سوى استخدام رمز الفهرسة العادي. إذا استخدمنا قواعد تقطيع APL ، فإن نفس الشيء مفيد جدًا في التمييز بين عمل شرائح الصفوف والأعمدة برمز * . (يحتاج المرء إلى التفكير في كيفية تصرف الاقتران المعقد مع rowvec ).

بهذه الطريقة ، إذا كنت تقوم بالجبر الخطي ، فسيكون كل شيء منطقيًا ولن يضطر المستخدم إلى القلق بشأن قاعدة التقطيع المحددة التي تنفذها جوليا. عامل التشغيل ' سيعمل فقط على المتجهات والمتجهات (لتغيير الزخرفة) وعلى المصفوفات (إما بطريقة مباشرة أو كسولة). قد يكون من الأسهل تذكر كيفية استخراج النواقل الأساسية من تكوين eigendecomposition ، والتي يبدو أنني دائمًا أنساها.

بالنسبة إلى * ، أعتقد أن جبر المصفوفة / المتجه في جوليا يجب أن يعمل بحيث يبدو وكأنه رياضيات كمعامل مضاعف ولا يحب أبدًا عامل منتج الموتر بين متجهين ، ومتجهين ، ومصفوفتين ، إلخ يجب ألا تسمح بـ M*v' ، لأنه في الرياضيات بشكل صارم تحتاج إلى كتابة المعادلة برمز "\ otimes" (علامة الأوقات داخل دائرة) وليس رمز الضرب القياسي. استخدام رمز الضرب معناه غير واضح! لا يمكننا الحصول على w*M*v' == v'*M*w لأن ضرب المصفوفة ليس تبادليًا. مرة أخرى مقابل M*v'*v لا معنى للحديث عن ارتباط * . يمكنك إما تفسير هذا على أنه innerproduct(outerproduct(M,v'),v) الذي يتطلب رمزين مختلفين للضرب ، أو كضرب عددي M * innerproduct(v',v) حيث يكون من المنطقي استخدام * لكليهما. مع هذا التعبير ، قد نحتاج إلى وضع أقواس ، أو ربما يمكن للمجمع البحث عن ترتيب ذي معنى للعمليات (لاحظ هنا أن أسرع ترتيب للتقييم هو أيضًا ما أعتبره الترتيب الصحيح الوحيد للتقييم).

باستخدام المتجهات والمتجهات والمصفوفات ، يمكننا الحصول على نظام جبري يتوافق مع الرياضيات القياسية. عندما تريد إجراء حاصل الضرب الخارجي بين متجهين ، أو متجهين ، أو مصفوفتين ، فأنت تنتقل بطبيعتها إلى الجبر متعدد الخطوط ، أو جبر الموتر العام. هنا يمكن أن يكون لديك مصفوفات ومتجهات تتضاعف مثل kron(M,N) باستخدام رمز جديد. أو قد تطلب من المستخدمين استخدام حزمة جبر كاملة متعددة الخطوط. أو أيا كان ... يبدو خارج نطاق السؤال الأصلي (الذي كان قبل 14 شهرًا ، راجع للشغل ...)

للتلخيص ، أرى أربعة أشياء مميزة تقريبًا تحدث هنا:

  1. تحسين تقسيم Array s للبيانات العشوائية باستخدام قواعد APL slicing.
  2. اجعل الجبر الخطي في جوليا أكثر سهولة واتساقًا تمامًا مع الرياضيات عن طريق إضافة بعض المفاهيم البسيطة: المتجهات وطريقة لاستخراج المتجهات والمتجهات من المصفوفات ، والعمليات بين المتجهات والمصفوفات ، وما إلى ذلك ، قد لا يلاحظ العديد من المستخدمين وجود متجهات ، منذ ذلك الحين سيستمر استخدام مصفوفات 1xn و nx1 في العمل كما هو متوقع ، وسيتصرف المتجه بنفس الطريقة.
  3. للسرعة ، قم بتنفيذ التقييم الكسول لـ transpose ، conj ، إلخ باستخدام أنواع التفاف تشبه إلى حد كبير covector ، ولكن للمصفوفات أيضًا.
  4. قم بتطوير حزمة موتر للأغراض العامة وربما إضافتها إلى المكتبة القياسية.

ربما سيكون الأول فقط هو تغيير جذري؟ يقوم الآخرون بتحسين أو إضافة الوظائف الحالية. يمكن تنفيذها جميعًا بشكل مستقل إلى حد ما ، وربما تكون جميعها أشياء جديرة بالاهتمام. (ملاحظة إذا كنت تريد تقطيع APL ، أوصي بذلك قريبًا ، قبل أن تصبح جوليا "كبيرة" جدًا وتكسر الكثير من الحزم ، إلخ).

نعم ، آسف ، اقتراحي بالسماح بـ M*v' لا معنى له حقًا لأن الطرق المختلفة لربط المنتجات تنتج أشكالًا مختلفة تمامًا. لذا ، أعتقد أننا إذا أردنا تغيير هذا اقتراحي الأصلي هو السبيل للذهاب. حتى الآن يبدو أن هذا هو أفضل مزيج مع سلوك تقطيع APL. بالطبع ، ما إذا كنا نريد سلوك تقطيع APL أم لا هو اعتبار أعلى مستوى.

أردت فقط أن أقول بعض الأشياء وأرجو أن تأخذها مع حبة ملح. إنهم مجرد رأي وأنا أعلم أن رأيي ليس له وزن كبير. ومع ذلك ، صدمني شيء واحد عندما كنت أقرأ تعليق

@ esd100 صحيح ، لقد فكرت في ذلك. لكن مع جوليا ، اعتقدت أننا نريد أن نكون _ جشعين _... أردنا تلبية أغراض عديدة ، والتفوق في أشياء كثيرة. قد تكون هناك أسباب علمية حقيقية للتلاعب بالبيانات غير الرقمية. قد يكون هناك علماء حاليون أو سابقون من مستخدمي Julia يرغبون في القيام بمزيد من البرمجة العامة. كانت نقطتي السابقة هي أننا يجب ألا نجعل Array أبطأ أو نأخذ المزيد من الذاكرة من خلال إعطائها مجالًا إضافيًا للتحدث عن التحويل / الاقتران.

إذا قام أحدهم بإجراء تقطيع APL ، فيجب أن تُرجع شرائح الصف أو العمود نفس الكائن. كان السؤال: بدون تقطيع APL ، ما هو أفضل شيء يمكن إرجاعه مقابل M[1,:] ؟ حسنًا ، إذا قام M[1,:,:,:,:] بإرجاع Array{T,n} ، فأنا أشعر أنه قد يربك الجميع إذا أعاد M[1,:] covector{T} . ماذا لو تركنا M = zeros(3,3,3) واستدعينا M[1,:] ، والذي يُرجع حاليًا مصفوفة 1x9؟ هل يجب أن نجعل هذا مشروبًا أيضًا؟ ماذا لو كان M Array{String,3} ؟

بالنسبة لي ، قد يبدو هذا مفاجئًا ومربكًا. كما أنه لا يتوافق مع تغييرات تقطيع APL ، إذا كان ذلك سيحدث في المستقبل. وبالتالي ، كنت أقترح إضافة وظائف جديدة لأغراض الجبر الخطي ، rowvec(M,i) و colvec(M,i) . إنها ليست مثالية ، فهي تضيف وظائف جديدة ... ولكن على الأقل من الواضح ما يجب أن تعيده لأغراض الجبر الخطي. كان الشيء الوحيد الذي يمكن أن أفكر فيه والذي كان له خصائص لطيفة للمصفوفات العامة وخصائص لطيفة للجبر الخطي (جنبًا إلى جنب مع نوع covector) ، مع عدم محاولة تلبية الجبر متعدد الخطوط. إذا كان لدى أي شخص تدوين أجمل لاستخراج المصفوفات من المصفوفات ، فسيكون ذلك رائعًا أيضًا!

@ esd100 : أنا متأكد من أن المبرمجين هم الجمهور الذي صممت جوليا من أجله. الحوسبة العلمية هي قوة Julias ولكن هناك العديد من مستخدمي Julia يستخدمونها فقط كلغة برمجة للأغراض العامة.

أتفق مع andyferris على أنه يتعين على المرء فصل متطلبات الموتر عن متطلبات الحاوية.

بدون قراءة الموضوع بالكامل ، مشكلتي الشخصية هي أنه إذا كان لدي مصفوفة ثلاثية الأبعاد A (مثل بيانات التصوير المقطعي) وقم بذلك

imagesc( data[1,:,:] )

هذا لا يعمل. يجب أن تكون IMHO data[1,:,:] و data[:,1,:] و data[:,:,1] مصفوفات ثنائية الأبعاد (أو مصفوفات فرعية). أستخدم حاليًا وظيفة squeeze ذاتية التحديد للتغلب على هذه المشكلة.

مرة أخرى ، هذا مجرد رأيي وهو رأي غير مهم على الإطلاق ، نظرًا لأنني بعيد عن العمل. أشعر أنه عند تطوير تطبيق ما ، يجب أن يحتوي على مجموعة من مبادئ التصميم التي توجهه. يجب على البناة إرسال رسالة واضحة وموحدة حول الغرض منها وهويتها. إذا كان تطوير منصة حوسبة تقنية سريعة وبديهية ومعقدة هو الهدف وهذه هي قوة جوليا ، إذن التزم بها. لا ترسل إشارات مختلطة بمحاولة جعل الغرض منها مناسبًا لجمهور المبرمجين العامين.

النقطة المهمة هي أنه حتى بالنسبة للتطبيقات العلمية أو الرياضية البحتة ، هناك العديد من التفسيرات المتضاربة ، على سبيل المثال ، هناك العديد من العناصر الرياضية التي يمكنك تمثيلها باستخدام المتجهات والمصفوفات ، وبالتالي لا ينبغي للمرء اتخاذ خيارات محددة للغاية.

من الأفضل أن يكون لديك حزم مخصصة لتلبية احتياجات تخصصات محددة تتبع مجموعة محددة من الاتفاقيات.

jutho إن شعوري استندت إليه في استنتاجك بأن الحزم "أفضل" مقارنة بالبدائل؟

هذا بسيط للغاية. تنتمي الوظائف المهمة لمعظم مستخدمي Julia إلى Base. الوظائف الأكثر خصوصية تنتمي إلى الحزمة.

بالطبع ليس من السهل رسم خط هنا. لكن أفضل طريقة للحصول على شيء ما في الأساس هي إنشاء حزمة بحيث يمكن للعديد من الأشخاص اختبار ذلك. تم تطوير العديد من الوظائف الأساسية التي استقرت في Base لأول مرة في حزمة.

@ esd100 ، لا أفهم سؤالك تمامًا. في النهاية ، ما يجب أن توفره اللغة العلمية هو هياكل البيانات وطرق التمثيل والحساب باستخدام الكائنات النموذجية المستخدمة في العلوم. لكن بعض هياكل البيانات قد تكون مفيدة لتمثيل بنى رياضية مختلفة ، وفي بعض الأحيان قد يكون التمثيل المختلف مناسبًا لكائنات من نفس النوع. ومن ثم ، فإن ربط بنية رياضية ثابتة بنوع بيانات قد يكون مقيدًا للغاية بالنسبة لبعض التخصصات ، ومعقدًا للغاية بالنسبة للتخصصات الأخرى. لذلك لا ينبغي متابعة هذا في قاعدة جوليا ، ولكن من خلال حزم محددة تحاول فقط تلبية احتياجات تخصص واحد.

فيما يتعلق بالمناقشة الحالية ، يتوقع كل شخص يعمل مع المتجهات والمصفوفات إمكانية تبديل متجه ، وأن يكون لديك v ^ T * w = عددية. ولكن يمكن استخدام هذه المتجهات والمصفوفات لتمثيل عدد من الأشياء المختلفة ، وهذا سيعتمد على الأرجح على المجال / التخصص. لقد أعطيت أمثلة على أن v ^ T قد لا يكون covector فعليًا في المشاركات أعلاه.

في 11 كانون الثاني (يناير) 2015 ، الساعة 18:10 ، كتب esd100 [email protected] :

jutho https://github.com/jutho شعوري الداخلي هو أنك على حق ، لكنني أتساءل ما هو أساس استنتاجك بأن الحزم "أفضل" ومقارنة بالبدائل؟

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub https://github.com/JuliaLang/julia/issues/4774#issuecomment -69501771.

هذا بسيط للغاية. تنتمي الوظائف المهمة لمعظم مستخدمي Julia إلى Base. الوظائف الأكثر خصوصية تنتمي إلى الحزمة.

لا أعتقد أن الأمر بهذه البساطة. على سبيل المثال ، توجد وظائف Bessel في Base ، ومن المستبعد جدًا أن تكون مهمة لمعظم مستخدمي Julia. السبب في إمكانية وجودهم في Base هو أن هناك معيارًا عالميًا واحدًا معقولًا لماهية وظائف Bessel ، ولا يحتمل أن يستخدم أي شخص هذه الأسماء لشيء آخر ، أو يتوقع منهم القيام بشيء مختلف.

من خلال اصطلاحات تسمية دقيقة (قد يقول البعض مطول) ، تستطيع Mathematica وضع أكثر من 4000 وظيفة في اللغة الأساسية ، وأجد أنه من الملائم للغاية ألا تضطر مطلقًا إلى تحميل حزمة. في المقابل ، عندما أستخدم Python / Sage ، ليس من غير المعتاد أن يقوم ملف / دفتر ملاحظات واحد باستيراد 200 وظيفة بشكل صريح في الجزء العلوي (تجنب ما لا يمكن تعقبه "من بناء الجملة ___ الاستيراد *"). في كل مرة أحتاج فيها إلى استخدام وظيفة ليست مضمنة ، يجب أن أخوض مجموعة من الخطوات الإضافية:

(1) حاول أن تتذكر ما إذا كنت قد استخدمته بالفعل في هذا الملف ، و / أو قم بإجراء بحث نصي للتأكيد (التقييد بكلمات كاملة إذا كان الاسم عبارة عن سلسلة فرعية لشيء آخر)
(2) إما: (أ) إضافة الاستيراد على الفور ، وفقدان قطار أفكاري وإيجاده مرة أخرى ؛ أو (ب) حاول تذكر إضافة الاستيراد بعد أن أفعل ما كنت أفعله ، مع الاحتفاظ بشيء آخر في الذاكرة
(3) بالنسبة للوظائف الأقل شيوعًا ، ربما يتعين عليك البحث عن الحزمة الموجودة فيها

يمكن أن يصبح هذا مزعجًا ومنهكًا. لذلك أعتقد أنه ، مثل وظائف Bessel ، أي شيء يعتبر قياسيًا - وبالتالي لن يتسبب في تضارب الأسماء أو التباس - يجب أن يكون في Base ، بغض النظر عما إذا كان يستخدمه الكثير من الأشخاص. الجبر الخطي بالتأكيد.


بالعودة إلى الموضوع ، كنا نتحدث عن عدة طبقات من الوظائف - الانتقال من المصفوفات باعتبارها حاويات عارية لغويًا (كما تم تنفيذها في Base.AbstractArray ) ، إلى كائنات الموتر الديكارتية ذات الدلالات لأعلى / لأسفل (كما هو موضح بواسطة AbstractTensorArray الاقتراح ، إلى كائنات أكثر موتر العام مع المؤشرات التي تم تعيينها إلى مساحات ناقلات (كما هو الحال فيJutho الصورة TensorToolbox ) --- زيادة عمومية وتقليل احتمالات الأمثل.

أعتقد أنه من المهم للمستخدمين أن يكونوا قادرين على الانتقال بسهولة بين هذه الطبقات ، لأسباب ليس أقلها أن المستخدمين _ قد لا يعرفون_ ما هو مستوى العمومية الذي يحتاجونه بالفعل عند البدء. كمثال بسيط ، أشار Jutho إلى أنه في مثال معالجة الصور jdbates ، قد يرغب المستخدمون جيدًا في ربط مجموعات فرعية مختلفة من المؤشرات بأشكال هندسية مميزة ، وذلك لمعالجة إحداثيات الصورة بطريقة ما ومساحة اللون بطريقة أخرى ؛ ولكن إذا كانوا قد بدأوا في استخدام واحد فقط من هذه هندسيًا ، فيجب أن يكون من الملائم استخدام عرض أكثر عمومية يسمح باستخدام كل منها بهندستها الخاصة. إذا كانت الوظائف الإضافية (أو أنماط استدعاء الوظيفة) التي تبدأ في كل مستوى من مستويات العمومية تستخدم الإعدادات الافتراضية المعقولة - على سبيل المثال ، مؤشرات أعلى / أسفل ومؤشرات محايدة في AbstractTensorArray s إلى مسافات متجهية ديكارتي افتراضية و مسافات "التسلسل" ، على التوالي --- ثم تصبح سلسة تقريبًا. لا يحتاج مستخدمو الطبقة السفلية من الوظائف إلى معرفة الطبقات العليا أو الاهتمام بها ، حتى يحتاجون إليها.

أي جزء من هذا يكون واضحًا ويمكن التنبؤ به - للمستخدمين المعنيين - ما يجب أن يكون عليه التسلسل الهرمي ، يمكن أن ينتقل بشكل معقول إلى Base. يجب أن يكون السؤال الحقيقي - سواء بالنسبة لعمليات المصفوفة أو الجبر الخطي أو جبر الموتر - ما مدى احتمالية أن يتوقع مستخدم هذا النوع من الوظائف أو يريدها بطريقة مختلفة؟

يكره الكثير من الناس التفاصيل الدقيقة السخيفة لعدد الواردات التي تحتاجها لإنجاز أي شيء في Python-land ، ولا أعتقد أن أي شخص يقترح الذهاب إلى هذه الأطوال.

ولكن هناك حجة مهمة مفادها أن الأعداد الكبيرة من التبعيات ونفخ المكتبة غير مرغوب فيها لبعض حالات الاستخدام ، جوليا اللغة لا ينبغي أن تتطلب تثبيت مكتبات وقت تشغيل فورتران على جهاز الكمبيوتر الخاص بك ولكن في الوقت الحالي مكتبة جوليا القياسية تفعل ذلك أم لا الكود الذي تريد تشغيله هو إجراء أي جبر خطي (أو وظائف Bessel ، أو FFT's ، إلخ). كل هذا مغطى جيدًا بواسطة # 5155 ومشكلات أخرى - "مثبت افتراضيًا" و "الحد الأدنى الضروري لأي وظيفة" يجب فصله في النهاية إلى مجموعات مختلفة من الوحدات.

شكرا توني ، أنا أؤيد ذلك. علاوة على ذلك ، مع نظام الحزم الخاص بنا ، لا توجد مشكلة في وجود "صندوق أدوات" مثل الحزم التي تجمع عدة حزم معًا. مع الماكرو @reexport هذا يعمل بشكل جيد.

لكن هناك نقطة أخرى. ضمن الحزمة ، من الأسهل بكثير دفع الفكرة إلى الأمام. إذا أراد المرء تغيير شيء ما ، فإنه يفعله ببساطة. داخل القاعدة الأولى مقيد أكثر بكثير.

يبدو أنه في حين أن وجود خليط من الحزم يسمح باستقلالية أكبر ، فإنه يخلق أيضًا نظامًا أساسيًا مجزأًا يصعب التنقل فيه. يبدو أن استخدام هيكل أكثر توحيدًا وتعميمًا من شأنه أن يبسط ويسهل التفاعل عبر التخصصات واستكشاف مجالات جديدة.

ما هي الطريقة الأكثر اصطلاحية حاليًا لعمل مصفوفة متجه؟
لنفترض مثلاً أنني حصلت على X بالشكل (K, N) و b بالشكل (K,) ، وأريد الضرب في b على ترك للحصول على متجه بطول (N,) .
هل أدعو BLAS.gemv('T',1.0,X,b)
أو reshape(b'*X,size(x,2))
كلاهما قبيح بعض الشيء.

أعتقد أنه يمكنك القيام بـ X'b

2015/03/13 17:15 GMT-04: 00 joschu [email protected] :

ما هي الطريقة الأكثر اصطلاحية حاليًا لعمل مصفوفة متجه؟
على سبيل المثال ، لنفترض أنني حصلت على X بالشكل (K ، N) و b بالشكل (K ،) ، وأريد
لضربه في b على اليسار للحصول على متجه الطول (N ،).
هل أتصل بـ BLAS.gemv ('T'، 1.0، X، b)
أو إعادة الشكل (ب '* س ، الحجم (س ، 2))
كلاهما قبيح بعض الشيء.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/4774#issuecomment -79405868.

نعم ، لقد اعتقدت أن ذلك سيؤدي إلى تشغيل نسخة من X.
ولكن يبدو أن الوقت @ يشير إلى عدم وجود نسخة ، بناءً على تخصيص الذاكرة

julia> X = rand(1000,1000); y = rand(1000);

julia> <strong i="8">@time</strong> y'X;
elapsed time: 0.00177384 seconds (15 kB allocated)

julia> <strong i="9">@time</strong> X'y;
elapsed time: 0.000528808 seconds (7 kB allocated)

نحن نقوم بتحليل خيالي لـ "حتى ينتهي الأمر بـ Ac_mul_B(X,y) X'y كـ Ac_mul_B(X,y) ويجعل
نفس مكالمة BLAS التي اقترحتها.

2015/03/13 17:28 GMT-04: 00 joschu [email protected] :

نعم ، على الرغم من أنني كنت أعتقد أن ذلك سيؤدي إلى تشغيل نسخة من X.
(ولكن يبدو أن time https://github.com/time يشير إلى أنه لا يوجد
نسخ ، بناءً على تخصيص الذاكرة

جوليا> X = راند (1000،1000) ؛ ص = راند (1000) ؛

جوليا> @ time y'X ؛
الوقت المنقضي: 0.00177384 ثانية (15 كيلو بايت مخصصة)

جوليا> @ time X'y ؛
الوقت المنقضي: 0.000528808 ثانية (7 كيلو بايت مخصصة)

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/4774#issuecomment -79421713.

صدق أو لا تصدق ، كتابة هذا الموضوع بأكمله تقترب من التحقق.

نقطة أخيرة: هل فكر أي شخص في ذلك. يمكن أن يكون في الواقع حيوانًا مختلفًا تمامًا عن "؟ هذا الأخير لديه الهيكل الصحيح لكونه ثنائيًا ، لكن. لا إذا كان الحقل الأساسي ليس الأرقام الحقيقية. هل من الجنون التخصيص. مفهوم "عكس جميع المؤشرات" الخاص بنقل كل مفاهيم الازدواجية والاحتفاظ بها في "، والذي ينتج" ناقل صف مضحك "/ مترافق هرميت؟

أعتقد أنه على أي حال ، يجب أن يكون conj(transpose(x)) معادلاً لـ ctranspose(x) .

كما ذكرنا سابقًا ، آمل أن يتم إعطاء اسم غير من أنواع الغلاف التي سيتم إنشاؤها بواسطة transpose و ctranspose يحتوي على مفهوم رياضي محدد مثل dual . يجب أن توفر لغة علمية مثل Julia مجموعة من هياكل البيانات المفيدة ويجب أن تنفذ عمليات مشتركة ، لكنني أعتقد أنه سيكون من الخطأ ربط بنية رياضية صارمة بها ، لأن هذا لن يكون مناسبًا لبعض التطبيقات ومعقدًا للغاية بالنسبة الآخرين. يعود الأمر للمستخدم لاستخدام هياكل البيانات والعمليات هذه لتنفيذ العمليات الحسابية في التطبيق الخاص به. هناك بالتأكيد تطبيقات لـ z.' * A * z تعيد عددًا قياسيًا حيث z متجه معقد و A بعض المصفوفة ، على الرغم من أن هذا لا علاقة له بمنتج داخلي و / أو ثنائي ثلاثة أبعاد.

jutho هل يمكنك إعطاء حالة استخدام z.' * A * z ؟

إذا z1 و z2 هي تمثيل متجهين معقدة Z1 و Z2 (مثل الظل ناقلات في الجزء holomorphic من مساحة الظل من مشعب كالر ) و a هو تمثيل المصفوفة لموتّر A بمؤشرين متغيرين (على سبيل المثال ، شكل مركب (2،0) لمشعب Kähler) ثم A(Z1,Z2) = z.' * a * z .

لاحظ أنني أؤكد هنا أن كائنات جوليا z1 ، z2 و a تشكل فقط _تقديم _ لبعض العناصر الرياضية (فيما يتعلق بالأساس / التنسيق المختار) وبالتالي لا يمكن ربط العمليات على هياكل البيانات بشكل فريد بالعمليات الرياضية دون معرفة ما تمثله هياكل البيانات هذه.

jutho شكرا. تم أخذ وجهة نظرك حول التمثيلات بشكل جيد ، وتم تمثيلها عدة مرات في هذه المناقشة. أحاول العثور على الحد الأدنى من واجهة المتجهات والمصفوفات ، ومعرفة ما إذا كان الحد الأدنى للواجهة على أي حال غير متوافق بشكل أساسي مع الحد الأدنى من واجهة المصفوفات ، وما يمكننا إلغاء تحميله لأنواع البيانات المجردة التي يحددها المستخدم.

في هذه المرحلة ، أنا أؤيد تمامًا اقتراح StefanKarpinski ، والذي ردده في الغالب andyferris أعلاه. خاصه

  1. فهرسة نمط APL
  2. v 'يعطي نوعًا من نوع Covector أو Transpose

كل شيء آخر هو التفاصيل. قد يكون من الجيد إضافة وظائف row(M,i) و col(M,i) . خلاف ذلك ، لاستخراج صف باعتباره covector أعتقد أنك ستحتاج M[i,:].' ؟ IIUC ، M[i,:]' شأنه أن يفعل conj غير مطلوب في هذه الحالة؟

نعم ، يجب أن أضيف أنني لم أقدر تمامًا الفهرسة اللطيفة على غرار APL في آخر مرة كتبت فيها ، لكنني الآن أؤيد تمامًا إجراء هذا التغيير. وهذا بدوره يجعل العناصر المتجهة المزدوجة أكثر إقناعًا ، ووظائف row / col .

منذ ذلك الحين حاولت التلاعب بتطبيق وكان الشيء الوحيد الأكثر إرباكًا هو ما إذا كان covector المستخرج من المصفوفة مترافقًا أم لا ...

أعتقد أنك تريد أن تأخذ القيم الحرفية للمصفوفة. باستخدام تدوين ديراك ، قم بتوسيع (أي) مصفوفة M = sum_i | i>على سبيل المثال [0،0،1 ، ... ، 0] ، نريد استخراجهانحصل على row(U,i)' = col(U’,i) وهو أمر منطقي تمامًا لاستخراج المتجهات الذاتية اليمنى واليسرى من تكوين eigendecomposition.

آندي

في 15 مارس 2015 ، الساعة 9:36 مساءً ، كتب Jeff Bezanson [email protected] :

في هذه المرحلة ، أنا أؤيد تمامًا اقتراح StefanKarpinski https://github.com/StefanKarpinski ، والذي يردده أيضًا في الغالب andyferris https://github.com/andyferris أعلاه. خاصه

فهرسة نمط APL
v 'يعطي نوعًا من نوع Covector أو Transpose
كل شيء آخر هو التفاصيل. قد يكون من الجيد إضافة وظائف الصف (M ، i) و col (M ، i). خلاف ذلك ، لاستخراج صف كمنشور أعتقد أنك ستحتاج M [i ،:]. ؟ IIUC، M [i ،:] 'هل سأفعل حرفًا غير مرغوب فيه في هذه الحالة؟

-
قم بالرد على هذه الرسالة الإلكترونية مباشرة أو اعرضها على GitHub https://github.com/JuliaLang/julia/issues/4774#issuecomment -81228816.

أي متطوعين لبدء العمل على هذا؟ على سبيل المثال ، mbauman ، jakebolewski الذي فوجئت برؤيته ليس في هذا الموضوع بالفعل :)

قد يكون العثور على كل ما يحتاج إلى تغيير أمرًا شاقًا ، ولكن التغيير الأساسي لسلوك الفهرسة لا ينبغي أن يكون سيئًا للغاية. ربما يستطيعjiahao و andreasnoack قول المزيد حول كيفية دمج Covectors ، على سبيل المثال ما الذي يجب أن يكون عليه النوع الفائق إن وجد.

نحتاج إلى 9 ، لا 8 تعليقات أخرى قبل أن نتمكن من المضي قدمًا في هذا.

يمكنني المساعدة في ذلك.

نحن قريبون جدا

كتعليق ذي صلة ، إذا كان هناك نوع غلاف Transpose و CTranspose ، يجب أن يكون أيضًا نوع غلاف عادي Conjugate ، مثل conj(A) أيضا كسول. لمضاعفة المصفوفات مع BLAS ، هذا ليس مفيدًا حقًا لأنه لا يوجد دعم خاص لذلك (و C في BLAS تعني اقتران hermitian) ، ولكن إذا كان هناك تطبيق Julia BLAS كامل ، فسيكون من الرائع دعمه أيضًا conj(A)*B بدون اقتران صريح.

أنا ، على سبيل المثال ، أشعر أنني الآن آخذ عمليات نقل المتجهات بجدية أكبر مما كنت أفعل من قبل.

ربما يستطيعandreasnoack و simonbyrne إخبارنا ما إذا كان يجب إعادة النظر في # 6837.

أتفق مع simonbyrne على أنه لا ينبغي أن يكون لدينا Transpose{Array} <: AbstractArray .

أفكار عامة أخرى:

  • أدركت أن حساب المنتج الخارجي يحتوي حاليًا على استثناء لقاعدة "عدم إضافة أبعاد مفردة لاحقة تلقائيًا". إذا كان حجم u هو (n,) ، فإن u * u' عبارة عن عملية حسابية تتضمن (n,) x (1, n) . لا يمكن حساب هذا المنتج باستخدام القواعد العادية لضرب المصفوفة _ ما لم يكن _ نعيد تلقائيًا تشكيل الوسيطة الأولى لتكون (n, 1) .
  • قاعدة "إضافة أبعاد مفردة لاحقة تلقائيًا" في دلالات فهرسة MATLAB غير متوافقة بشكل أساسي مع قاعدة "تبديل يعكس جميع الأبعاد". مع القاعدة السابقة ، تكون مصفوفات الشكل (n,) متطابقة من الناحية اللغوية مع المصفوفات المعاد تشكيلها من الشكل (n,1) والشكل (n,1,1) ، إلخ. لكن لاحظ أنه في حالة عكس كل الأبعاد ، فإن شكل المصفوفات الناتجة (n,) و (1, n) و (1,1,n) ، والتي _لا يمكن_ أن تكون مكافئة إذا كان مسموحًا لك فقط بإضافة أحرف مفردة لاحقة. بأخذ هذا إلى أقصى الحدود المنطقية ، يمكن أن يكون لتحويل المصفوفة عددًا عشوائيًا من الأحرف الفردية الرائدة وبالتالي يكون لها شكل غامض ، وهو أمر غير متسق منطقيًا.

قمت أيضًا بإجراء مسح للأدب وكشفت عن بعض تاريخ APL المثير للاهتمام. ما أشرنا إليه بقاعدة فهرسة APL لم يكن موجودًا في كتاب إيفرسون لعام 1962 ، ولكنه موجود بالفعل في APL \ 360 (1968 ؛ أول تطبيق لـ APL). ومع ذلك ، فقد دمجت APL \ 360 بين الحجميات والمتجهات 1 ، وهو تناقض لم يتم التعرف عليه في الأدبيات حتى (Haegi ، 1976). ظهرت مناقشة الدلالات الرسمية للمصفوفات متعددة الأبعاد لأول مرة في أطروحة الدكتوراه لبراون (1972 ؛ قام لاحقًا بتصميم APL2) ، وأثارت خطًا من العمل لإضفاء الطابع الرسمي على دلالاتها.

مسح ممتاز للتطورات التي أدت إلى APL2 هو:

  • كارل فريتز روهر. "مسح امتدادات APL." في وقائع المؤتمر الدولي حول APL ، APL '82 ، الصفحات 277-314 ، نيويورك ، نيويورك ، الولايات المتحدة الأمريكية ، 1982. ACM.

من الملحوظ في الأدبيات الانتباه إلى قواعد الفهرسة:

  • T. المزيد. "البديهيات والنظريات لنظرية المصفوفات." مجلة آي بي إم للبحث والتطوير ، 17 (مارس): 135 - 175 ، 1973.

    • كتاب ضخم يضفي الطابع الرسمي على دلالات المصفوفات متعددة الأبعاد باستخدام نظرية المجموعة البديهية كواين ، ويوضح كيف يمكن دمج المقاييس مع مصفوفات الرتبة 0 مع فكرة المجموعات الذاتية لتكوين ما يسميه أدبيات APL "المصفوفات العائمة". ([1] == 1 ، على النقيض من "المصفوفات الأرضية" حيث [1]! = 1. أظهر العمل اللاحق لشيلا إم سينجلتون في أطروحة الماجستير التي حصلت عليها عام 1980 أنه يمكن أيضًا تكييف نظرية مصفوفة مور لوصف المصفوفات الأرضية.)

    • يذكر المزيد أيضًا المنتج الداخلي الذي يعيد مقياسًا كقاعدة مهمة لتوجيه دلالات المصفوفة.

    • يلمح المزيد أيضًا إلى تعقيد معالجة "up / down-ness" للمصفوفات العامة متعددة الأبعاد:

      "لنفترض أن V فضاء متجه ذي أبعاد n فوق حقل. بغض النظر عن اعتبارات التناقض والتغاير ، فإن موتر التكافؤ q على V هو رسم خرائط متعدد الخطوط للمنتج الديكارتي لقائمة VV ... V للطول q إلى متجه إذا كان V يحتوي على قاعدة ، فيمكن تمثيل موتر التكافؤ q على V بواسطة موتر مكون ، وهو مصفوفة على محاور q ، كل منها بطول n. "

  • ج. لويس. "نظام فهرسة مصفوفة جديد لـ APL" ، وقائع المؤتمر الدولي السابع حول APL - APL '75 ، 234-239 ، 1975.

    • كانت هذه الورقة هي الأولى التي دعت إلى أن مجموعة الفهرس في عملية الفهرسة هي كائن من الدرجة الأولى في APL ، ولاحظت أنه يمكن تحقيق بناء متسق لنتيجة الفهرسة من خلال المنتجات الديكارتية المنتظمة على طول كل رتبة من مجموعة الفهرس.

  • هانز آر هيجي. "امتداد APL إلى هياكل البيانات الشبيهة بالشجرة." ACM SIGAPL APL ، اقتباس رباعي ، 7 (2): 8-18 ، 1976.

    • اشتكى هذا البحث من عدم الاتساق في APL \ 360 الكلاسيكي ، والذي يخلط بين العددية والمصفوفة 1 ، ويدافع عن أن قاعدة فهرسة APL تتطلب عدم استمرار هذا الخلط.

    • تحتوي هذه الورقة أيضًا على بنية مشابهة جدًا لـ Lewis، 1975؛ يبدو أن العمل مستقل.

  • جيه ايه جيرث ودل اورت. "الفهرسة والدمج في APL." في وقائع المؤتمر الدولي حول APL ، APL '88 ، الصفحات 156–161 ، نيويورك ، نيويورك ، الولايات المتحدة الأمريكية ، 1988. إيه سي إم.

    • لاحظ أنه يمكن تبرير قاعدة فهرسة APL من خلال التفكير في الفهرسة كعملية إذاعية تعين الفهرس المعين على مجموعة القيم. يقترح هذا التفسير الوظيفي بشكل طبيعي قاعدة الحفاظ على الرتبة والبناء الديكارتي للويس وهايجي.

أيضًا ، بدون قاعدة "يمكن إضافة أبعاد مفردة لاحقة" ، فإننا لا نطيع الهوية

image

نظرًا لأن الجانب الأيسر هو عدد (حسب تعريف التتبع) والجانب الأيمن له شكل (1, n) x (n, n) x (n,) = (1,) . على العكس من ذلك ، يمكننا أن نأخذ هذه الهوية كمبدأ إرشادي لاختيار دلالات نقل المتجهات. النقطة الرئيسية هي الخاصية الدورية لعملية التتبع التي تحدد الهوية الأولى. يجب أن تكون الكمية الموجودة داخل التتبع إما عددية أو مصفوفة (لم يتم تحديد تتبع المتجه). Avv' هو بالفعل مصفوفة لا لبس فيها: (Av)v' و A(vv') ينتجان نفس النتيجة. ولكن أيضًا من الكمية الثانية ، يجب أن يكون v'Av مصفوفة _ أو_ عددًا. (إذا كان الرقم القياسي ، فإن الهوية الثانية تحمل أيضًا.) يمكن أن يكون v'Av متجهًا واحدًا فقط إذا كانت قاعدة "يمكن إضافة أبعاد مفردة لاحقة" نشطة ، وفي هذه الحالة يمكن إعادة تشكيلها بشفافية إلى مصفوفة 1x1.

وبالتالي ، إذا أردنا تحديد التتبع ، فإنه يفرض بالضرورة قيودًا على الأشكال المسموح بها للمنتجات الخارجية vv' وللصيغ التربيعية v'Av .

jihao : لست متأكدًا تمامًا مما تدافع عنه

أعتقد أنه يمكن أخذ بعض الحجج الخاصة بك لتقوية الموقف الذي لا يمكننا التفكير فيه على أنه يعكس جميع الأبعاد (سيتم نقل متجه العمود إلى متجه عمود ، أو ربما مصفوفة ذات عدد تعسفي من الأبعاد المفردة البادئة). للبقاء متسقًا مع جبر المصفوفة ، أعتقد أنه يجب أن يؤخذ على أنه مبادلة البعدين الأولين بدلاً من ذلك. ثم أعتقد أن بعض التناقضات التي تذكرها تختفي. نأمل أن يختفي الباقي إذا لم نقم بإضافة أي أبعاد مفردة عند النقل (البعد الأول الغائب من covector لا يحتسب).

تعليقاتي العامة أعلاه ليست للدفاع عن هذه القواعد ، ولكن بدلاً من ذلك للمساعدة في تحديد مساحة تصميم قواعد فهرسة المصفوفة وتفاعلها مع هويات الجبر الخطي.

تستخدم قاعدة MATLAB قاعدة "يمكن إضافة أبعاد مفردة لاحقة" (وفقًا لـ @ alanedelman) لدعم المصفوفات متعددة الأبعاد. يتم تحديد حساب الفهرس للإزاحة المستخدم في مصفوفات MATLAB بواسطة sub2ind ، والذي يُرجع نفس الفهرس الخطي بغض النظر عن عدد 1s اللاحقة التي ترميها عليه. علاوة على ذلك ، تنص وثائق فهرسة مصفوفة MATLAB على أنه بالنسبة لعمليات الفهرسة:

لا يتجاوز عدد الأحرف المنخفضة المحددة لـ B ، باستثناء الأحرف المنخفضة اللاحقة التي تساوي 1 ، ndims (B).

بشكل أكثر رسمية ، أعتقد أنه يمكن ذكره على النحو التالي:

بالنسبة للعمليات التي تأخذ المصفوفات كمدخلات ، فإن المصفوفات (n,) -arrays ، (n,1) -arrays ، (n,1,1...) المصفوفات كلها في نفس فئة التكافؤ فيما يتعلق بكونها وسيطات صالحة لهذه العمليات. (إذا كان n=1 ، فإن فئة التكافؤ تتضمن أيضًا مقاسات.)

أمثلة:

  • A*b و A\b حيث A مصفوفة و b يمكن أن يكون متجهًا أو مصفوفة (دلالات متطابقة لمصفوفات n x 1 ) ،
  • hcat(A, b) حيث A مصفوفة و b يمكن أن يكون متجهًا أو مصفوفة

بالنسبة للجزء الأكبر ، لا تمتلك جوليا قاعدة "يمكن إضافة قاعدة أبعاد مفردة لاحقة" ، باستثناء مثال المنتج الخارجي. من المحتمل أن يكون هناك آخرون أيضًا ولكن لا يمكنني التفكير بهم الآن.

طالما أن Transpose{A<:AbstractArray} ليس نوعًا فرعيًا من AbstractArray أعتقد أنني لا أرى مشكلة (لكن ربما أتجاهل شيئًا ما لأنني لم أفكر في هذا كثيرًا مثلكم يا رفاق) :
مع

typealias AbstractVectorTranspose{A<:AbstractVector} Transpose{A}
typealias AbstractMatrixTranspose{A<:AbstractMatrix} Transpose{A}
typealias AbstractTMatrix Union(AbstractMatrix, AbstractMatrixTranspose} 

(وبالمثل مقابل CTranspose ) يمكننا الحصول عليها

AbstractVectorTranspose * AbstractVector = Number
AbstractVector * AbstractVectorTranspose = AbstractMatrix
AbstractVectorTranspose * AbstractTMatrix = AbstractVectorTranspose
AbstractTMatrix * AbstractVector = AbstractVector
AbstractTMatrix * AbstractTMatrix = AbstractTMatrix

السؤال الوحيد المطروح هو ما إذا كان يجب دعم AbstractVector * AbstractTMatrix عندما يكون AbstractTMatrix 1 كحجم أول ، أو ما إذا كان AbstractVector * AbstractVectorTranspose كافيًا.

أيضًا ، قد يساعد نظام النوع الجديد في التعبير عن بعض من هؤلاء typealias و union sa قليلاً.

أيضًا ، إذا تم احتساب v.'*A سبيل المثال (A.'*v).' ، فإن الحاجة إلى غلاف Conjugate تظهر إذا كان A نفسه على سبيل المثال A=B' .

أتفق مع simonbyrne على أنه لا ينبغي أن يكون لدينا Transpose{Array} <: AbstractArray .

هل يمكنك التفصيل هناك؟ اعتقدت أن الرأي في https://github.com/JuliaLang/julia/issues/4774#issuecomment -59428215 هو أن CoVector لا ينبغي أن يكون نوعًا فرعيًا من AbstractVector ، ولكن قد يبدو غريباً بعض الشيء بالنسبة لي ألا أملك Transpose{Matrix} <: AbstractArray .

بالنسبة لما يستحق ، أعتقد أن CoVector يجب أن يتصرف في الغالب مثل Vector باستثناء أن Vector يتحول إلى Matrix كمصفوفة عمود بينما CoVector يتحول Matrix كمصفوفة صف.

أعتقد أن هذا يعني أن الفهرسة في covector يجب أن تعمل بنفس الطريقة في مصفوفة الصف؟

هذه فكرة مثيرة للاهتمام. هل تصبح الأمور أسهل أو أكثر تعقيدًا إذا تم إسقاط أبعاد أحادية فقط في أنواع تبديل الموضع / المفرد؟

(لقد كنت أتابع هذه المشكلة باهتمام ولكن الجبر الخطي صدئ بدرجة كافية لدرجة أنني لم أشعر أنني مؤهل للمساهمة).

mbauman :

هل تصبح الأمور أسهل أو أكثر تعقيدًا إذا تم إسقاط الأبعاد المفردة الرائدة فقط في أنواع التبديل / covector؟

إذا سمحت بعدد عشوائي من الأبعاد المفردة الرائدة ، فلن تكون فهارس المصفوفة مرتبة جيدًا ولا يوجد شيء مثل "البعد الأول" ، وهو أمر غريب بما يكفي لدرجة أننا قد نأخذ الترتيب الجيد كبديهية.

tkelman :

اعتقدت أن الرأي الوارد في # 4774 (تعليق) هو أن CoVector لا ينبغي أن يكون نوعًا فرعيًا من AbstractVector ، ولكن قد يبدو غريبًا بعض الشيء بالنسبة لي ألا يكون لدينا Transpose {Matrix} <: AbstractArray.

لقد أصبح واضحًا بالنسبة لي أن هذه المشكلة تتعلق تمامًا بفصل دلالات المصفوفات (راجع # 10064) عن دلالات الجبر الخطي ، والبحث عن الأماكن التي تختلط فيها.

  • يتم تعريف دلالات المصفوفات بوظائف مثل الحجم والطول و getindex و setindex و hcat و vcat و reshape و rot90 ...
  • يتم تعريف دلالات الجبر الخطي من خلال وظائف مثل + ، - ، * ، / ، ، '، تتبع ...

إذا حددنا وظائف cat لتكون جزءًا من الواجهة الأساسية لـ AbstractArray ، فمن الواضح أن Transpose{<:AbstractArray} ليس AbstractArray لأن سلوكيات التسلسل مختلفة . إذا اعتبرنا الشكل والفهرسة فقط جزءًا من الواجهة الأساسية ، فسيكون الموقف أقل وضوحًا.

إذا طلبنا التسلسل كجزء من الواجهة الأساسية لـ AbstractArray ، فمن الأسهل أيضًا تبرير سبب عدم كون أنواع مثل SymTridiagonal ليست AbstractArray s ، نظرًا لأن عمليات التسلسل تزيد عن SymTridiagonal s مثل [SymTridiagonal(randn(5), randn(4)) randn(5)] غير معرّف حاليًا.

@ toivoh :

أعتقد أن هذا يعني أن الفهرسة في covector يجب أن تعمل بنفس الطريقة في مصفوفة الصف؟

هناك هويات تشير إلى أن سلوك الفهرسة Transpose{Vector} يجب أن يكون هو نفسه Vector s العادي. ضع في اعتبارك أنه بالنسبة للأنواع الرقمية ، ينتج عن v[1] نفس النتيجة مثل v' * e₁ = v ⋅ e₁ و v[1:2] ينتج نفس النتيجة مثل v' * [e₁ e₂] ، حيث e₁ الأساس المتعارف عليه Vector{Int} [1, 0, 0, ...] و e₂ هو [0, 1, 0, 0, ...] . إذا طلبنا هذه الهويات المتعلقة بالفهرسة والمنتجات الداخلية والتبديل ، فيمكن للمرء أن يدعي ذلك

(v')[1] == (e₁' * v'') == (v' * e₁)' == (v ⋅ e₁)' == conj(v ⋅ e₁)* = conj(v[1])

(حيث تكون الخطوة الأولى بديهية جديدة والرابعة تستفيد من حقيقة أن تحويل الحجم القياسي هو أمر غير عملي) بحيث تتجاهل الفهرسة إلى Transpose{Vector} التحويل بشكل أساسي ، والفهرسة إلى CTranspose{Vector} يقترن العناصر المفهرسة.

لي أن هذه المسألة تتعلق بالكامل بفصل دلالات المصفوفات (راجع # 10064) عن دلالات الجبر الخطي ، والبحث عن أماكن متداخلة.

  • يتم تعريف دلالات المصفوفات بوظائف مثل الحجم والطول و getindex و setindex و hcat و vcat و reshape و rot90 ...
  • يتم تعريف دلالات الجبر الخطي من خلال وظائف مثل + ، - ، * ، / ، ، '، تتبع ...

+1 إلى وجهة النظر هذه وليس لديك Transpose <: AbstractArray . أيضًا ، عند فهرسة covector ، يجب أن يكون بمؤشر واحد ، وإلا فإن نتيجة covector * vector (الانكماش على مؤشر واحد) لا يمكن أن تؤدي إلى رقم قياسي (كائن به مؤشرات صفرية).

jihao : لست متأكدًا من أنني أرى لماذا نحتاج أو نريد

(v')[1] == (e₁' * v'')

كبديهية جديدة. على الرغم من أنه حتى لو تم فهرسة covector كمصفوفة صف ، أعتقد أننا سنحصل على نفس النتيجة لما سبق بسبب الفهرسة الخطية.

و +1 لرؤية المشتركات باعتبارها معنية بالجبر الخطي.

ولكن لا يوجد سبب لعدم تحديد التسلسل بـ SymTridiagonal ، أليس كذلك؟

يتم تعريفtoivoh الفهرسة الخطية للمصفوفة بإعادة تشكيل المصفوفة أولاً إلى متجه ، ثم فهرسة المتجه الجديد. لذلك ، لكي تعطي الفهرسة الخطية نفس النتيجة للمصفوفات المنقولة ، يجب أولاً تحديد قواعد الفهرسة الخاصة بالمتجهات المنقولة حتى نتمكن من اشتقاق قواعد الفهرسة الخطية من ذلك. (أيضًا ، أنت تقوم باختبار اتصال شخص آخر.)

اعتقدت أن الفهرسة الخطية تتعلق بترتيب التخزين ، وليس هناك حقًا أي ترتيب معقول آخر للفهرسة الخطية للمتجه على أي حال ، أليس كذلك؟ (وآسف على الخطأ الإملائي.)

لا يوجد نظام اجتياز معقول فريد في الذاكرة. حتى بالنسبة لمصفوفات Fortran ، يمكنك اختيار تخزين العناصر في ترتيب العمود الرئيسي أو الصف الرئيسي أو حتى ترتيب العمود الرئيسي العكسي (وهو بالضبط ما فعله مترجم IBM Fortran I الأصلي). علاوة على ذلك ، هناك هياكل بيانات أخرى (انظر # 10064) مثل المحاولات التي يمكن استخدامها كمصفوفات ولديها المزيد من الخيارات لترتيب الاجتياز.

يمكن قول الشيء نفسه عن المتجهات والمصفوفات. بما أن الفهرسة الخطية تصل إلى العناصر بالترتيب نفسه لمصفوفة العمود وتبديلها (ونفس الأمر بالنسبة لمتجه العمود) ، فلماذا يجب أن يكون الفيكتور مختلفًا؟ إذا كان يجب أن يكون مختلفًا ، أعتقد أنه يجب ألا نحدد الفهرسة للمتعاملين على الإطلاق.

toivoh نعم نفس التعريفات

يمكن عدم السماح بفهرسة كائنات Transpose . أنا لا أقول أنه يجب أن تكون قابلة للفهرسة ، ولكن إذا كانت كذلك ، فلن يكون بالضرورة أن يكون لها نفس سلوك الفهرسة. لكي نكون متحفظين ، يمكننا ترك الفهرسة غير محددة في الوقت الحالي ومعرفة ما إذا كانت هناك أي حالات استخدام ستظهر.

سترغب العديد من تطبيقات جوليا النقية لوظائف الجبر الخطي في الفهرسة إلى تبديل ، أليس كذلك؟ تصبح كتابة ضرب مصفوفة جوليا الخالصة (لأنواع الأرقام التي لا تنتمي إلى BLAS) أمرًا سهلاً إذا لم يكن عليك التمييز بين أي حالة محتملة (عادية ، أو تبديل ، أو تحويل ، أو اقتران؟) للمصفوفتين المتضمنتين ولكن فقط تعاملهما كمصفوفات عادية. يمكن محاولة الأساليب التي لا تحتوي على ذاكرة التخزين المؤقت للحصول على نمط وصول إلى الذاكرة المحلية إلى حد ما.

صحيح ، دوه.

@ جوثو : أوافق. وللتناسب مع ذلك ، يجب على المتعاملين الفهرسة مثل مصفوفات الصف ، أليس كذلك؟

toivoh ، إذا كنت تقصد أنهم يجب أن يكون لديهم فهرس إضافي 1 في المقدمة ، فأنا لا أوافق ولا أرى كيف يعني ذلك بياني. كنت أتحدث فقط عن منتجات مصفوفة المصفوفة. المصفوفة * المتجه أو covector * المصفوفة هما طريقتان مختلفتان تتطلبان تعريفات مختلفة للوظائف ، ليس فقط لأن لديهم نمط وصول مختلف للذاكرة ، ولكن أيضًا لأن لديهم نوع إرجاع مختلف (Matrix_vector = vector أو covector_matrix = covector) ، لذلك هناك سبب عملي جدا في جوليا لعدم خلط هذه الأشياء.

بشكل عام ، لست من أشد المعجبين بالقدرة على إضافة مؤشرات إضافية 1 عند فهرسة مصفوفة ذات أبعاد N ، أو على سبيل المثال اسم مستعار من النوع VecOrMat . هذا يسمح بالبرمجة القذرة ، ولكن هذا أيضًا يجعل من السهل ارتكاب الأخطاء أو اكتشاف الأخطاء الأخرى بشكل أبطأ. لا أرى سوى طريقتين مفيدتين لإدخال مصفوفة ذات أبعاد N ، أي باستخدام مؤشرات N بالضبط ، في حال كنت تستخدمها ككائن متعدد الخطوط ، أو بمؤشر خطي ، عندما تتعامل معه كمتجه في منتج موتر الفضاء (على سبيل المثال لإضافة اثنين من هذه المصفوفات أو ضربها بعدد قياسي). في حين أن هذا كافٍ لاستعمالي ، يمكنني قبول أن هذا يقتصر على الآخرين.

Jutho : حسنًا ، أوافق على أنه ربما لا يهم لأن نوع الإرجاع يجب أن يكون مختلفًا على أي حال.

إليك محاولة لوصف ما نحاول القيام به وإعطاء بعض البديهيات:

أعتقد أننا وصلنا إلى إجماع واضح على أن نقطة البداية هي جبر المصفوفة (الذي يعتمد فقط على المصفوفات). بالنسبة لمعظم العمليات ، نعلم كيف يتصرفون في إعداد المصفوفة الصافية.

أعتقد أن ما نحاول القيام به هو توسيع وتنقيح إعداد المصفوفة النقية بطريقة متسقة للحصول على مقاييس ونواقل حقيقية أيضًا ، ولأنها تبدو ضرورية للاتساق ، فإن المتجهات.

هذه هي وجهة نظري للقياسات والمتجهات (كما رأينا من وجهة نظر المصفوفة الصافية): العدد القياسي هو مصفوفة ، بنوعها مقيدة لتكون 1 × 1. يكون nx 1. (سأجادل أدناه أن covector عبارة عن مصفوفة يتم تقييدها حسب نوعها لتكون 1 x n.) من وجهة النظر هذه ، يمكننا إعطاء بديهيتين: (غير موصوفين بشكل رسمي أدناه)

  • الامتداد: ضع في اعتبارك وظيفة من المصفوفات إلى المصفوفات. إذا كان سينتج دائمًا مصفوفة إخراج بحجم 1 في بُعد معين ، مع الأخذ في الاعتبار مدخلات من أنواع معينة ، فسيتم ترميز هذه الحقيقة في نوع المخرجات (مما يجعلها عدديًا / متجهًا / متجهًا).
  • التنقية: إذا كانت الوظيفة التي تتطلب وسيطة مصفوفة في إعداد المصفوفة الخالصة تتطلب أن يكون للمدخل حجم واحد في بُعد واحد أو أكثر ، فقد يرفض قبول إدخال حيث لم يتم تشفير هذه الحقيقة في النوع.

إذا اتفقنا مع ما سبق ، فيجب أن يكون تبديل المتجه من نوع covector الموصوف أعلاه: ينتج عن تبديل مصفوفة القلق 1 مصفوفة 1 × ن. إذا قمنا بترميز حقيقة أن الحجم على طول الأبعاد الأولى للنتيجة هو دائمًا واحد ، فإننا نحصل على covector كما هو موضح أعلاه.

إذا بدأت من وجهة نظر جبر المصفوفة ، فإن ما تقوله صحيح. هذا هو النموذج الذي ربما تطبقه MATlab بشكل مثالي. كل شيء عبارة عن مصفوفة. إنه نظام مغلق ، كل العمليات على المصفوفات تنتج مصفوفات جديدة.

كان لدي بالتأكيد انطباع بأن الهدف من هذه المشكلة (أخذ نقل المتجهات على محمل الجد ، نظرًا لأنها ليست مجرد مصفوفات) هو الابتعاد عن نموذج جبر المصفوفة ، لأنه يبدأ في إظهار التناقضات إذا كنت تريد فصل الأرقام عن المصفوفات 1 × 1 لأسباب من الكفاءة. البديل بعد ذلك هو اتباع نموذج الجبر الخطي ، حيث يوجد تمييز واضح بين المجال (الحجمي) ، والفضاء المتجه (والمزدوج المقابل له) ، ومساحة العوامل / التحويلات الخطية (المصفوفات).

أعتقد أن عمليات الجبر الخطي في جوليا متجذرة بقوة في تقليد matlab ، مع بعض الاستثناءات الملحوظة مثل وجود مقاييس ومتجهات ، وعدم محاولة تخمين المستخدم. أي شيء يتحرك بعيدًا جدًا عن ذلك من المحتمل أن يكون اضطرابًا كبيرًا جدًا.

أعتقد أن بديهياتي أعلاه يجب أن تمضي قدمًا في حل التناقضات التي تظهر عندما تريد فصل الحجميات والمتجهات عن المصفوفات (لأسباب تتعلق بالكفاءة والصحة). لكنني بالتأكيد منفتح لسماع أنظمة أخرى ممكنة.

أتفق مع Jutho هنا ؛ بيت القصيد من هذه القضية هو الابتعاد عن دلالات MATLAB "كل شيء هو مصفوفة". تعد قاعدة MATLAB "يمكن إضافة أبعاد مفردة لاحقة" ضرورية لإغلاق الكون في إطار عمليات الجبر الخطي ، ولكن هذه القاعدة تحدد فئات التكافؤ التي تحتوي على أعضاء من النوع T وأخرى من النوع Array{T,N} لـ الكل N ، وهو السبب الرئيسي الذي يجعل نظام MATLAB غير قابل للتقرير. (انظر النظرية 1 لجويشا وبانجي ، 2006 - على الرغم من أن النتيجة مذكورة من حيث الأشكال ، فإن المشكلة تتعلق حقًا بكيفية تغيير ترتيب المصفوفة في تغيير دلالات البرنامج.)

لكنني ما زلت أعتقد أن لدينا إجماعًا جيدًا على أن تكاثر العددية والمتجهات والمتجهات المشتركة والمصفوفات يجب أن يكون ترابطيًا (باستثناء أشياء مثل (v'*v)*v حيث يتضاعف اثنان غير عدديين لإنتاج عدد قياسي) ، وذلك على سبيل المثال v'*M*v يجب أن إنتاج العددية، M*v متجه و v'*M لcovector. لست متأكدًا إلى أي مدى يمكن الابتعاد عن دلالات كل شيء مصفوفة بينما لا تزال تستوفي هذه الشروط.
ما هو أكثر من ذلك الذي نحاول تجنبه ، وما الخصائص التي نريد الحصول عليها بدلاً من ذلك؟

ما مدى سوء الأمر إذا قمنا بدمج T و Array{T,0} في بعض الحالات؟ (على سبيل المثال ، الفهرسة: M[:,2] ينتج Array{T,1} ، لكن M[2,2] لا ينتج Array{T,0} )

لا يزال بإمكاننا الحفاظ على دلالات صالحة مع Transpose{Vector} .

أعدت قراءة جميع التعليقات حول الترابط وخلصت إلى أن معظم تلك المناقشة لا تتعلق في الواقع بالترابط في حد ذاتها ، بل بالأحرى عن دلالات المنتجات الداخلية والمنتجات الخارجية. إذا وجدت تعبيرًا لا يتعلق بأي منهما ، فيرجى الإشارة إليه.

تكمن مشكلة الدلالات من نوع Matlab في أن M*v' و v*M يعملان أحيانًا على الرغم من أنهما لا ينبغي. إذا كان M هو m x 1 فإن M*v' يكون صالحًا ويعيد كمية خارجية تشبه المنتج (نظرًا لأن v' هو 1 x n ) وبالمثل ، إذا كان M هو 1 x m ولدينا قاعدة "يمكن إضافة مفردة لاحقة" ، فيمكن تقييم v*M على أنه منتج n x 1 و 1 x m مصفوفات

أثيرت مسألة الخلط بين T و Array{T,0} أيضًا في أدبيات APL - في APL ، المصفوفات متعددة الأبعاد متداخلة بشكل متكرر ، مما يثير التساؤل حول ما إذا كان Array{T,0} و T يمكن تمييز T ) ، وإلا فهي "مصفوفات عائمة" (والتي تتكرر إلى Array{T,0} فقط). أعتقد أن عام 1973 أثبت بالفعل أن أي من الخيارين متسق بشكل بديهي. لست متأكدًا مما إذا كانت APL قد حلت يومًا ما السؤال الذي يجب استخدامه قبل أن يتقاعد معظم الممارسين أو ينتقلون إلى شيء آخر.

jiahao : لم أكن أدرك مدى أهمية

v[i] = e_i' * v

لربط الجبر الخطي ودلالات الفهرسة معًا. ولكن بعد ذلك يجب عليك أيضًا التفكير

M[i,j] = e_i' * M * e_j

مما يشير إلى أن المنتج الداخلي مع متجه الأساس من اليمين يتوافق مع الفهرسة على طول البعد الثاني. وبالتالي ، سأحتفظ بأنه يجب فهرسة الإدخال i th من covector v' على أنه

v' * e_i = v'[1, i]

أين نود بالطبع كتابة شيء آخر غير 1 كمؤشر أول ، لكن ماذا؟
على أي حال ، لأننا نسمح

e_i' * v = v[i] = v[i, 1]

ثم 1 يجب أن يُسمح به كعنصر نائب أيضًا في الحالة أعلاه.

على الرغم من ذلك ، فإن v' * e_i هو عدد قياسي ، لذا فإن e_1' * (v' * e_i) هو عامل مشترك ، وليس مقياسًا. لذلك لا تتطابق الأبعاد مع التفكير في v'[1, i] = e_1' * v' * e_i

تحرير: أعتقد أن هذا قد يكون حجة ضد السماح بتتبع الفردي في الفهرسة؟

نعم ، فهرسة المصفوفة هي الخطوة المنطقية التالية ، و e_i' * M * e_j هي في الواقع أحد التعبيرات التي تصبح فيها بديهية الترابط مفيدة ، حيث

(e_i' * M) * e_j = m_i' * e_j

e_i' * (M * e_j) = e_i' * m_j

يجب أن تكون متساوية. يمكن اشتقاق فهرسة المصفوفة من قاعدة فهرسة المتجهات وقاعدة فهرسة covector.

أعتقد أن الحل المتسق لهذه المشكلة قد يتطلب تعبيرات مثل v[i, 1] غير مسموح بها ، نظرًا لأن القاعدة التي تسمح بسلوك الفهرسة هذا
أ) يجب أن تتسبب في حالات زائفة لـ A*v' و v*A للعمل (الأول يعمل ولكن الأخير لا يفعل ذلك لأننا نطبق قاعدة المفرد اللاحقة بشكل غير متسق) ، و
ب) إذا أخذنا في الاعتبار المساواة v[i] = v[i, 1, 1, 1] فإن قاعدة الفهرسة covector المقابلة ستبدو مثل (v')[1, 1, 1, i] ويجب أن يكون لدى المرء قاعدة "السماح بعدد تعسفي من المفردات البادئة" للمشتركين من أجل الاتساق. أجد عدم وجود بُعد أول محدد بشكل فريد مزعجًا للغاية.

لا أعتقد أن منطق الفهرس هذا يذهب إلى أي مكان حقًا. الفهرسة هي خاصية عامة لمصفوفات أبعادها N ، ويمكن كتابتها كتعبيرات مصفوفة بسيطة لـ N=1 أو N=2 هي أمر تافه إلى حد ما ولا يحتوي على أي أساسي معلومات. لكن هذا لا يُعمم على المصفوفات ذات الرتبة الأعلى ، وبالتالي لا ينبغي استخدامه للتحفيز على ما إذا كان المشمول يحتاج إلى 1 أول أم لا عند فهرسته. هذا يؤدي بسرعة إلى تناقضات كما لوحظ في المشاركات السابقة.

كما هو مذكور أعلاه ، لم أكن أبدًا من المعجبين بالاعتماد على مؤشرات لاحقة ولم أستطع التفكير في موقف واحد يكون فيه ضروريًا أو حتى مفيدًا حقًا. لكن يمكنني قبول أن وجهة نظري محدودة للغاية.

لم أستوعب كل هذا بشكل كامل ولكن سؤالي الرئيسي هو ببساطة: هل size(covector) يساوي (n,) أم (1,n) ؟

إذا لم يكونوا جزءًا من عائلة AbstractArray ، فليس من الضروري تحديد size .

على الرغم من أنه لأسباب عملية أعتقد أنه سيتم تحديده (كما هو الحال بالنسبة للأرقام وما إلى ذلك) ، وتصويتي يذهب إلى (n,) . من وجهة نظر التخزين / الحاوية ، أود أن أقول أنه لا يوجد تمييز بين المتجهات والنواقل. لذلك ليست هناك حاجة أيضًا لاستخدام المتجهات كحاويات ، وبالتالي فهي لا تنتمي إلى التسلسل الهرمي AbstractArray . إنه مجرد نوع غلاف بسيط للتعبير عن أنهم يتصرفون بشكل مختلف عن المتجهات فيما يتعلق بعمليات الجبر الخطية.

"طالما تم الفصل بين الجبر والهندسة ، كان تقدمهما بطيئًا واستخداماتهما محدودة ؛ ولكن عندما تم توحيد هذين العلمين ، فقد أعار كل منهما قوى مشتركة ، وسارا معًا نحو الكمال." - جوزيف لويس لاجرانج

أتمنى أن أتمكن من المساهمة أكثر ، لكنني اعتقدت أنني سأقول فقط إنني أؤيد وجود نظام يفضل جعل الأدوات الرياضية المتطورة التي يستخدمها الفيزيائيون والمهندسون بديهية ودقيقة للاستخدام. ربما ، هذا المورد من MIT ، قد يكون مفيدًا ...

http://ocw.mit.edu/resources/res-8-001-applied-geometric-algebra-spring-2009/lecture-notes-contents/

في الواقع ، فكر في الأمر ، من العدل أن تقول ذلك

e_i' * x = x[i, :] # x is a vector or matrix
x * e_j  = x[:, j] # x is a covector or matrix

ثم من أجل فهرسة المصفوفة سيكون لدينا

e_i' * M * e_j = e_i' * (M * e_j) = e_i' * M[:, j] = M[:, j][i, :] = M[i, j]
e_i' * M * e_j = (e_i' * M) * e_j = M[i, :] * e_j  = M[i, :][:, j] = M[i, j]

حاليًا لا ينطبق هذا تمامًا في Julia ، على سبيل المثال ، ينتج v[i, :] حاليًا مصفوفة 1x1 وليست عددية. (لكن ربما لا ينبغي)
يتوافق ارتباط ضرب المصفوفة في e_i' * M * e_j مع تبادلية التقطيع على طول أبعاد مختلفة M[:, j][i, :] = M[i, :][:, j] ، والتي تبدو وكأنها ميزة مرغوب فيها.
من خلال سطر إعادة التفكير أعلاه ، يجب أن يكون لدينا

v'[:,i] = conj(v[i])

Jutho : أعتقد أن نموذج "الفهرسة e_i ، إلخ ، أيضًا بأي ترتيب (طالما أنك تتعقب الأبعاد المتطابقة).

أعتقد أن نموذج "الفهرسة كتقطيع متكرر" هذا يُعمم على المصفوفات / الموترات ذات الأبعاد الأعلى: يمكنك تطبيق تشريح واحد لكل بُعد للفهرسة ، بأي ترتيب. هذا يتوافق مع سلسلة من الانقباضات مع موترات من الدرجة الأولى تتوافق مع e_i ، وما إلى ذلك أيضًا بأي ترتيب (طالما أنك تتعقب الأبعاد المتطابقة).

نعم ، أنا على دراية تامة بتقلصات الموتر وما إلى ذلك ، وفي الواقع أن الحصول على عنصر مصفوفة / عنصر موتر يتوافق مع أخذ قيمة توقع في الأساس الحسابي القياسي ، أي التعاقد مع بعض المتجهات الأساسية (طالما لديك أساس متعامد على الأقل ) ، ولكن لا يوجد ارتباط فريد حول ما إذا كان الفهرس يتوافق مع انكماش e_i أو مع e_i' . يتوافق ذلك مع تحديد ما إذا كان المؤشر المقابل يظهر في موضع متغير أو مخالف ، ولا يوجد قرار فريد. جميع التركيبات الممكنة من المؤشرات العلوية والسفلية لها تطبيقات مفيدة. لكن التعاقد مع e_i و e_i' ليس حتى الطريقة الصحيحة لطرح هذا السؤال من وجهة نظر رياضية ، لأنه ، كما ذكرت أعلاه ، لا يوجد في الواقع مثل هذا التخطيط الرياضي مثل تبديل المتجه. التحويل هو عملية محددة للخرائط الخطية (المصفوفات) وحتى هناك تتوافق فقط مع تبديل المصفوفة إذا كتبت أيضًا متجهات مزدوجة كمتجهات عمود. إن تبديل المتجه هو مجرد خدعة ملائمة تم تقديمها في جبر المصفوفة (حيث تكون المتجهات بالفعل مصفوفات n x 1 ) وهي تعمل فقط لأنك في مساحة إقليدية حيث يوجد تخطيط أساسي من (المترافق) ) ناقلات الفضاء إلى الفضاء المزدوج.

على وجه الخصوص ، إذا كنت تريد الخصائص التي وصفتها أعلاه ، فيجب أن يكون لديك M[i,:] يُرجع كائنًا مختلفًا (إما مصفوفة 1xn أو مصفوفة) ثم M[:,i] (وهو ما يجب تكون مصفوفة أو متجهًا nx1 ). حقيقة أن هذا لا يعمم بشكل واضح على أبعاد أعلى هو بالضبط أحد نقاط المناقشة الرئيسية لهذه المشكلة ، ويبدو أن معظم الناس يفضلون فهرسة APL ، حيث يتم إسقاط الأبعاد المفهرسة برقم (أي كلاهما M[:,i] ينتج عن M[i,:] مصفوفة من المرتبة الأولى ، وبالتالي ، ناقل). الفهرسة هي إحدى خصائص المصفوفات ، وهذا الخلط بين سلوك الفهرسة وعمليات الجبر الخطي هو الذي ينتج عنه كل الالتباسات / التناقضات في المقام الأول. يمكن أن يكون متسقًا طالما بقيت داخل النظام البيئي المغلق للكائنات ذات الرتبة N=2 ، أي كل شيء عبارة عن مصفوفة ، وكذلك متجهات وأرقام ، ولا تفكر أبدًا في المصفوفات ذات الأبعاد الأعلى.

لقد أدركت أيضًا أن M[i,:] سيتعين عليه إنتاج covector من خلال المنطق أعلاه ، كما تقول. لذلك يبدو أن وجود متجهات في مستوى ما يتعارض بشكل أساسي مع فهرسة APL. إذا فضلنا فهرسة APL (وأنا أحب ذلك) يصبح السؤال هو أين نرسم الخط الفاصل بين ذلك العالم والعالم الذي يعيش فيه المتعاقدون. (كنت آمل أنه سيكون من الممكن التوفيق بين الاثنين ، ربما كان البقية منكم قد أدرك بالفعل أنه سيتعين علينا التخلي عن ذلك؟)

ربما لا يكون هذا الصراع مفاجئًا جدًا إذا فكرت في الأمر:

  • في فهرسة APL ، يتم الاحتفاظ فقط بالأبعاد ذات المعنى والقابلة للفهرسة في النتيجة ؛ يتم ضغط الباقي.
  • إذا فعلنا ذلك باستخدام v' فسنحصل على v' = conj(v) . بدلاً من ذلك ، يمكن النظر إلى covector على أنه تتبع البعد الأول المفقود.

أعتقد أن البداية الجيدة ستتمثل في تقييد العوامل المشتركة قدر الإمكان ، وذلك في الأساس فقط بتعريف الضرب والجمع / الطرح والقسمة اليسرى عليها.

يبدو أن الفكرة هي عدم جعلهم <: AbstractArray . هل من المنطقي أن تكون أنواعًا فرعية من نوع LinearOperator ؟ (أعلم أنه تم طرحه للمناقشة من قبل ، لكن لا تتذكر الاستنتاجات تمامًا).

أعتقد أن غياب الوراثة المتعددة أو بناء لغة للواجهات (وكلاهما قيد المناقشة) يتطلب مفاهيم معينة يتم تنفيذها فقط من خلال واجهة "ضمنية" ، أي مجموعة من الأساليب التي تحتاج إلى تعريف. التكرارات هي أحد هذه المفاهيم ، ومن المحتمل أن تكون العوامل الخطية أخرى تحتاج إلى تحديدها بواسطة مجموعة من الأساليب بدلاً من التسلسل الهرمي للنوع. سيكون من الغريب أن يكون لديك نوع مجردة LinearOperator ثم لا يكون لديك Matrix ليكون نوعًا فرعيًا منه.

toivoh هذا اعتبار مهم ، وهذا هو السبب في أنني اقترحت وظائف جديدة مثل row(M,i) و col(M,i) لاستخراج المتجه أو covector i th من مصفوفة. هذه الدوال ستكون فقط للمصفوفات ثنائية الأبعاد M وللأشخاص المهتمين بجبر المصفوفة. قد يبدو في البداية أقل وضوحًا قليلاً من فهرسة نمط MATLAB ، ولكن بشكل عام ، فإن الفصل المفاهيمي بين فكرة المتجه والثنائي / المنقول / المشترك يساعد في توضيح الأمور. في حالة ميكانيكا الكم ، قفز مجال كامل إلى تدوين ديراك bra-ket لمجرد أن هذا التمييز بين المتجه و covector مهم جدًا للناقلات المعقدة ، وتوضيح ديراك يجعل هذا واضحًا. آمل أن تقوم جوليا بذلك أيضًا ، فضلاً عن كونها أداة جيدة لصفائف تخزين ذات أبعاد أعلى وجبر خطي عالي الأبعاد! (لأننا جشعون ، أليس كذلك؟)

يجب أن أقول إن أي شخص قادم من ذوي الخبرة في MATLAB وبعض الإلمام بمصفوفات حقيقية في الغالب (لكنه ليس متعصبًا متشددًا في الجبر الخطي) قد لا يدرك في البداية سبب أهمية ما يناقش البعض منا بشأنه ، لكنني صدق ذلك.

لقد قلت هذا سابقًا ، لكنني سأكرره: من وجهة نظري ، لدينا قائمة الأولويات هذه ، مع تدفق الإصابات إلى أسفل:

(1) المصفوفات عبارة عن حاويات تخزين في الأساس يستخدمها جميع مستخدمي Julia ، ونريد أفضل دلالات لهذا الغرض. تبدو قواعد نمط APL ، بالنسبة لي على أي حال ، حلاً جيدًا للغاية. من ناحية أخرى ، فإن المصفوفات ثنائية الأبعاد على غرار MATLAB مع افتراضات مع مؤشرات لاحقة الأبعاد تبدو غير طبيعية ومربكة ، وكما قال Jutho فإنها يمكن أن تؤدي إلى برمجة قذرة حيث لا تتبع بشكل صحيح البعد من صفيفك. سأذهب بعيدًا لأقول أنه بالنسبة للمتجه v ، يجب أن يؤدي الرمز v[i,:] إلى خطأ نظرًا لأن v هو بعد واحد. تعتبر عمليات العناصر مثل + و .* مفيدة لأي فئة حاوية ، ليس فقط في المصفوفة أو الجبر متعدد الخطوط. حاوية تخزين الامتياز الوحيدة التي يقدمها الأشخاص للأشياء أدناه هي النقاط الإضافية على .* إلخ.

(2) سيستخدم معظم مستخدمي جوليا ، وليس كلهم ​​، جبر المصفوفة ، لذلك نضيف بعض السكر النحوي لبعض عمليات المتجهات والمصفوفات ، في الغالب برمز * (ولكن قد يكون لدينا تقسيم المصفوفة ، إلخ). في هذا النظام ، نأخذ المصفوفات ثنائية الأبعاد ومتجهات العمود والمصفوفات ، على التوالي. بالنسبة لنظام المصفوفة كامل الوظائف ، نحتاج أيضًا إلى متجهات الصف (المتجهات) وعملية تبديل ' . متجه الصف هو بكل معنى الكلمة مصفوفة ذات بعد واحد ، وأؤكد أنه يجب فهرستها على هذا النحو (وبالتأكيد ليس مثل covec[1,i] !!) مع قواعد APL ، نحن مضطرون لعمل بعض التمييز بين المتجهات والمتجهات ، ونظام الكتابة مثالي لهذا (تذكر أننا كنا محظوظين لأننا تمكنا بالفعل من إعادة استخدام المصفوفة والناقلات كنماذج لمصفوفات أحادية وثنائية الأبعاد بدلاً من نوع غلاف ... لفهم أيضًا ، لكنني لا أرى النقطة). باستخدام نظام الكتابة ، يمكن للمجمع معرفة أن CoVector * Vector هو عدد قياسي و Vector * CoVector مصفوفة ، وهكذا. كما قال toivoh ، _ من وجهة نظر MATLAB ، فإن CoVector يتتبع بالضبط البعد الأول "المفقود". لن يحتاج المستخدمون العاديون إلى إنشاء هذه الكائنات ؛ سيقومون فقط بإدخال المتجهات والمصفوفات واستخدام العمليات * و ' . الأشخاص الذين يهتمون سوف يلاحظون ويقدرون التمييز. تغيير _biggest_ للمستخدمين هو ضرورة تغيير M[i,:] لاستخدام وظيفة جديدة row(M,i) أو التحويل إلى فئة الغلاف بشيء مثل Transpose(M[i,:]) أو M[i,:]' - يمكن للمرء أن يفكر في هذا على أنه ميزة ، لأنه مثل تدوين ديراك ، لن تنسى

(3) بعضنا مهتم بالجبر متعدد الخطوط ، وكان عليه أن يتعلم الفرق بين المسافة المزدوجة والتبديل ، إلخ. وقد تطرق جوتو إلى هذا. تعد مصفوفات جوليا بالفعل أجهزة تخزين رائعة لموترات عالية الأبعاد ، وسيتم استخدام الحزم الإضافية (التي قد تجد أو لا تجد طريقًا إلى Base) بواسطة أشخاص مثلنا. لا نحتاج ولا نريد عمليات مثل ' أو * معرّفة على مصفوفات ذات أبعاد أكبر من اثنين. لا يمكنني رؤية حالة استخدام للتخزين مقابل ' لا يمكن القيام بها بشكل أكثر نظافة عن طريق إعادة ترتيب المؤشرات بشكل صريح. إن الفكرة الكاملة لتتبع المؤشرات أحادية البعد تجعل المفهوم أقل جاذبية ... لذا يرجى الاحتفاظ بـ ' لمصفوفات أحادية وثنائية الأبعاد فقط - مثل MATLAB :) (انظر ، لدي أشياء لطيفة قل عن MATLAB ...)

بالنسبة لنظام مصفوفة يعمل بكامل طاقته ، نحتاج أيضًا إلى متجهات الصف (المتجهات) وعملية تبديل '.

هذا البيان يقترب حقًا من قلب المشكلة. الفهرسة والتبديل والمنتجات * كلها مختلطة. علاوة على ذلك ، ليس من الممكن التوفيق بين الدلالات الكاملة لمتجهات الصف مع تلك الخاصة بالمتجهات دون تقديم دالة مثل row(A, i) لإرجاع الصف i th من A كـ a covector بدلاً من مصفوفة أحادية البعد. يريد حاليًا A[1, :] أن يعني كلاً من "أخذ الصف الأول من A" و "أخذ الشريحة الأولى على طول البعد الثاني من A" ، لكن هذه المفاهيم غير متوافقة بشكل أساسي في اقتراح covector.

متجه الصف هو بكل معنى الكلمة مصفوفة أحادية البعد ، وأؤكد أنه يجب فهرستها على هذا النحو.

أعتقد أنك تتصرف ببراعة مع هذا البيان. لقد أوضحت المناقشة السابقة تمامًا أنه إذا كنت تريد دلالات الجبر الخطي الكاملة (مع المنتجات والعلامات الصحيحة) ، فلا يمكن أن يكون لمتجه الصف نفس نوع المصفوفة أحادية البعد. أولاً ، يجب أن تُرجع الفهرسة في covector قيمًا مترافقة معقدة ، (v')[1] = conj(v[1]) ، للتناسق في المنتج الداخلي dot . ثانيًا ، النواقل ليست نواقل ، فهي وظائف خطية تنتظر إنتاج منتج داخلي مع ناقل. ثالثًا ، المتجهات والمتجهات لها سلوكيات مختلفة لسلسلة المصفوفات تحت hcat و vcat . لكل هذه الأسباب ، لا يمكن أن يكون متجه الصف "بكل معنى الكلمة مصفوفة أحادية البعد".

سأؤيد التخلص من العزاب الزائدة: لا أعتقد أنني رأيت رمز جوليا الذي استفاد منه. كنت سأقول في الأصل أننا سنحتاجها لمصفوفات ذات أبعاد 0 ، لكني أرى أن X[] يعمل بشكل جيد.

أعتقد أن فهرسة APL ، جنبًا إلى جنب مع الوظيفة row(M,i) لمتجهات الصفوف هي الأكثر منطقية ، ويبدو أنها حل وسط جيد. لست متأكدًا من فهرسة متجه الصفوف ، لكني لا أحب (v')[1,i] .

القرار الكبير الآخر ، الذي لم نتطرق إليه بعد ، هو أنواع. ما توصلت إليه من تجربة في هذا سابقًا هو أنه من الصعب حقًا أن يكون v' AbstractVector ، لأنه يجعل الإرسال في حالة من الفوضى.

خياران محتملان:

  1. نستخدم أنواع منفصلة للمصفوفة والمتجه:

    • Transpose <: AbstractMatrix

    • CoVector <: Any

    • نوع من تبديل العناصر للكائنات Factorization .

  2. نحن نستخدم نفس النوع لجميع التحويلات ، ولكن لدينا X' _not_ AbstractMatrix

    • Transpose <: Any

بالنسبة للاقتران ، يمكننا إما

أ. حدد ConjugateTranspose (مع ConjugateCoVector إذا ذهبنا مع الخيار 1 أعلاه)

ب. استخدم نوع غلاف Conjugate ، وعش مناسب: سنحتاج إلى بعض الاصطلاحات حول ما إذا كنا نستخدم Transpose{Conjugate{T}} أو Conjugate{Transpose{T}} .

أحب امتلاك Transpose{Matrix} وليس نوعًا فرعيًا من AbstractMatrix . أعتقد أن أقرب نظير لدينا في الأساس هو نوع مصفوفة خاصة مثل Symmetric ، والتي تتصرف جبريًا مثل المصفوفة ولكن ليس في دلالات الفهرسة الخاصة بها. (أثبت رقم 987 أنه بدون تعدد الميراث أو السمات المقدسة ، يجب أن يحترم التسلسل الهرمي للنوع دلالات الحاوية على دلالات الجبر.)

مشكلة تأليف الأنواع التي هي أساسًا "علامات دلالية" ظهرت أيضًا في # 8240. أعتقد أن Transpose{Conjugate{T}} سيكون مفضلاً ، لأن الاقتران مفهوم يقع في المجال الأساسي للعناصر.

فيما يلي أمثلة تتبع أحيانًا نفس قاعدة المنفرد الزائدة مثل MATLAB ، وفي أحيان أخرى لا تتبع:

  • يُسمح بالأحرف المفردة الزائدة في عمليات الفهرسة. (مثل MATLAB)
julia> (1:5)[5,1,1,1,1,1,1]
5
  • الشرائح الزائدة غير مسموح بها في عمليات الفهرسة. (على عكس MATLAB ، الذي يسمح لهم بذلك).
julia> (1:5)[5,:]
ERROR: BoundsError()
 in getindex at abstractarray.jl:451
  • بالنسبة إلى المصفوفات رتبة> = 3 ، تتم إضافة المفردات اللاحقة الضمنية إلى عملية تعيين مفهرسة عندما يكون هناك عدد أقل من الفهارس من رتبة المصفوفة ويكون المؤشر الأخير عددًا (مثل MATLAB):
julia> A=zeros(2,2,2); A[1,2]=5; A #Same as A[1,2,1]=5
2x2x2 Array{Float64,3}:
[:, :, 1] =
 0.0  5.0
 0.0  0.0

[:, :, 2] =
 0.0  0.0
 0.0  0.0
  • بالنسبة إلى المصفوفات ذات الترتيب> = 3 ، تتم إضافة _slices_ الزائدة الضمنية إلى عملية تعيين مفهرسة عندما يكون هناك عدد أقل من الفهارس من رتبة المصفوفة ويكون الفهرس الأخير _ ليس رقميًا_ (مثل MATLAB):
julia> A[:,:]=3; A
2x2x2 Array{Float64,3}:
[:, :, 1] =
 3.0  3.0
 3.0  3.0

[:, :, 2] =
 3.0  3.0
 3.0  3.0
  • بالنسبة إلى المصفوفات رتبة> = 3 ، تتم إضافة المفردات اللاحقة الضمنية إلى عملية الفهرسة عندما يكون هناك عدد أقل من الفهارس من رتبة المصفوفة ويكون المؤشر الأخير عددًا (مثل MATLAB):
julia> A=reshape(1:8,2,2,2); A[:,1]
2-element Array{Int64,1}:
 1
 2

julia> A[:,1,1]
2-element Array{Int64,1}:
 1
 2
  • بالنسبة لمصفوفات الرتبة r> = 3 ، فإن عملية الفهرسة عندما يكون هناك فهارس k <r من رتبة المصفوفة والفهرس الأخير عبارة عن شريحة خطيًا ضمنيًا المصفوفة المتبقية من رتبة rk. (مثل MATLAB):
julia> A=reshape(1:8,2,2,2); A[1,:]
1x4 Array{Int64,2}:
 1  3  5  7

julia> A=reshape(1:8,2,2,2); A[1,:,:]
1x2x2 Array{Int64,3}:
[:, :, 1] =
 1  3

[:, :, 2] =
 5  7
  • لا يتم إسقاط الأحرف المفردة الزائدة في عمليات التعيين. (على عكس MATLAB)
julia> A=zeros(1); A[1] = randn(1,1)
ERROR: `convert` has no method matching convert(::Type{Float64}, ::Array{Float64,2})

You might have used a 2d row vector where a 1d column vector was required.
Note the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].
You can convert to a column vector with the vec() function.
 in setindex! at array.jl:307

julia> A=zeros(1,1); A[1,1] = randn(1)
ERROR: `convert` has no method matching convert(::Type{Float64}, ::Array{Float64,1})
 in setindex! at array.jl:308
  • لا تُلحق Julia تلقائيًا بُعدًا لاحقًا فرديًا عندما يسمح ذلك بإجراء عملية صحيحة. (على عكس ماتلاب ، الذي يفعل)
julia> 1/[1.0,] #In MATLAB, interpreted as the inverse of a 1x1 matrix
ERROR: `/` has no method matching /(::Int64, ::Array{Float64,1})
  • تعمل المنتجات الخارجية وهي استثناء من القاعدة السابقة ؛ دلالاتهم تستخدم ضمنيًا مفردة لاحقة في الحجة الأولى. (مثل ماتلاب)
julia> [1:5]*[1:5]' # Shapes are (5,) and (1,5) - promoting to (5,1) x (1,5) works
5x5 Array{Int64,2}:
 1   2   3   4   5
 2   4   6   8  10
 3   6   9  12  15
 4   8  12  16  20
 5  10  15  20  25

يبدو أن هذه الأشياء قد تستحق القليل من التنظيف ، بمجرد أن ننتهي من الطريقة التي نريدها أن تتصرف بها. يبدو السلوك الحالي عند الفهرسة باستخدام عدد قليل جدًا من المؤشرات حيث تكون الشريحة الأخيرة مريبة بشكل خاص.

نجاح باهر. الأمثلة التي يطرحها Jiahao مزعجة بشكل غير عادي ... لا أحب تتبع عمليات الفردي في عمليات الفهرسة وفهرسة عمليات التخصيص بسبب ملاءمتها وغموضها. إذا لم تكن على دراية بهذه السلوكيات مسبقًا ، فقد ينتهي بك الأمر بفعل شيء ما بينما تحاول فعلًا فعل شيء آخر. أنا أؤيد الالتزام باستخدام دقيق وواضح للغة وتجنب الاختصارات الغامضة.

لتنفيذ هذا فعليًا ، سنحتاج إلى نوع من الإرسال المثلثي ، وإلا فأنا لست متأكدًا من كيفية التعبير عن أشياء مثل "مصفوفة بإدخالات Complex64 أو Complex128 ، تبديلها ، أو تبديله المقترن ". خاصة إذا استخدمنا الخيار 2 + ب أعلاه.

@ esd100 ، أي منها غامض أو خطير؟ هذه كلها إما مريحة - عندما يتم تخيل "مفردات افتراضية" من أجلك وتريدها - أو غير مريحة - عندما تريدها ولم تكن كذلك. ليس لأي من هذين معنيين معقولين بسلوكيات مختلفة.

متجه الصف هو بكل معنى الكلمة مصفوفة أحادية البعد ، وأؤكد أنه يجب فهرستها على هذا النحو.

أعتقد أنك تتصرف ببراعة مع هذا البيان.

صحيح! آسف jiahao ، [] . أنت محق في أن التسلسل يعتبر اعتبارًا مهمًا ، وأعتقد أن الطريقة الطبيعية للقيام بذلك (لإنشاء مصفوفة) واضحة بشكل معقول (من خلال اعتبارها بحجم 1 xn في هذه الحالة). من الواضح أن covector ليس "بكل معنى الكلمة" صفيف جوليا 1D ... هذا هو بيت القصيد ...

أمثلة jiahao تزعجني أيضًا. سوف أؤيد إزالة أي سلوك لاحق محتمل. قد يكون تخطيط الأبعاد اللاحقة مفيدًا ، ولكن يمكن أيضًا أن يشجع على نوع من الكسل حيث تنسى عدد أبعاد المصفوفة الخاصة بك ... (أعتقد أن هذا هو ما يعنيه "غامض" و "خطير" ... أريد حقًا Julia لإلقاء خطأ عندما أعامل مصفوفة ذات 16 بعدًا مثل مصفوفة 15 بعدًا ، على سبيل المثال).

أي منها غامض أم خطير؟

الرابع يبدو غامضًا وخطيرًا بالنسبة لي.

julia> A=zeros(2,2,2); A[:,:]=3; A
2x2x2 Array{Float64,3}:
[:, :, 1] =
 3.0  3.0
 3.0  3.0

[:, :, 2] =
 3.0  3.0
 3.0  3.0

من الواضح (بالنسبة لي) أن هذا يجب أن يكون خطأ في بناء الجملة. A هي المرتبة 3 ولم تتم الإشارة إلى البعد الثالث على الإطلاق. من المرجح أن البعد الثالث قد تم تركه عن طريق الخطأ وتم الآن إدخال خطأ يصعب العثور عليه في الكود. سأكون ممتنا لو تلقيت خطأ في وجهة نظره (كما هو الحال في كل من IDL و fortran).

أعتقد أنه من الأفضل أن تسمح المصفوفات فقط بالفهرسة بالعدد الصحيح من المؤشرات أو الحالة الخاصة للفهرسة الخطية 1D (لأنها سهلة للغاية). وقد يشمل ذلك عدم السماح بأحرف مفردة لاحقة أيضًا.

أو الحالة الخاصة للفهرسة الخطية 1D (لأنها مفيدة للغاية)

كيف يتم بيع مبادئنا بسهولة! :)

لم أحب الفهرسة الخطية كثيرًا ؛ يبدو لي نوعًا من الاختراق. غالبًا ما نريد أسرع طريقة للتكرار عبر مصفوفة. ويمكن أن تكون الفهرسة الخطية بطيئة حقًا بالنسبة إلى جميع المصفوفات الكثيفة البسيطة. ومع ذلك ، قد لا نتمكن من استبعاد الفهرسة الخطية تمامًا (لأسباب تتعلق بالأداء ولكسر الكثير من التعليمات البرمجية).

نعم ، هذا صحيح بما فيه الكفاية. لكن الفهرسة 1D على الأقل مميزة بصريًا. في حين أن فهرسة مصفوفة 6D مع 5D أقل بكثير. على أي حال ، أفضل وجود قواعد فهرسة أكثر صرامة والتخلي عن الفهرسة الخطية 1D بدلاً من الذهاب في الاتجاه الآخر. خاصة وأن المرء يمكنه بسهولة الحصول على مرجع معاد تشكيله للمصفوفة التي تشترك في الذاكرة.

هل يمكننا استخدام الأقواس {} (أو غيرها) للفهرسة الخطية ، والاحتفاظ بـ [] للفهرسة متعددة الأبعاد؟ مجرد فكرة...

في 23 مارس 2015 ، في الساعة 2:36 مساءً ، كتب بوب بورتمان [email protected] :

نعم ، هذا صحيح بما فيه الكفاية. لكن الفهرسة 1D على الأقل مميزة بصريًا. في حين أن فهرسة مصفوفة 6D مع 5D أقل بكثير. على أي حال ، أفضل وجود قواعد فهرسة أكثر صرامة والتخلي عن الفهرسة الخطية 1D بدلاً من الذهاب في الاتجاه الآخر. خاصة وأن المرء يمكنه بسهولة الحصول على مرجع معاد تشكيله للمصفوفة التي تشترك في الذاكرة.

-
قم بالرد على هذه الرسالة الإلكترونية مباشرة أو قم بعرضها على GitHub https://github.com/JuliaLang/julia/issues/4774#issuecomment -84805310.

أعتقد أيضًا أنه سيكون من الجيد لو تمكنا من فصل بناء الجملة
للفهرسة الخطية من صيغة الفهرسة العادية ، لكنني أوافق على ذلك
قد يكون تغييرًا هائلًا.

بينما يبدو أن هذه المشكلة تجذب الكثير من الجدل ، فإن معظم العمل الفعلي في تحسين الفهرسة قد حدث في عدد كبير جدًا من طلبات السحب خلال دورة 0.4. على سبيل المثال ، الآن لدينا CartesianIndex والأصدقاء ، لا أرى لماذا يحتاج المرء إلى فصل بناء الجملة عن الفهرسة الخطية والديكارتي - في الواقع يمكنك الآن الجمع بينهما (# 10524). أرغب في التخلص من الفهرسة الخطية أيضًا ، لكن في بعض الأحيان تكون أكثر أداءً (ربما يرجع ذلك إلى حد كبير إلى # 9080 ؛ يعاني enumerate و zip من نفس المشكلة) ربما يجب أن نطبق fastindex كغلاف حول eachindex ، كما في # 10507.

إذا كنت مهتمًا بفهرسة القواعد ، فبدلاً من ضرب هذه المشكلة حتى الموت ، دعنا نركز على الحدود الأكثر إثارة للاهتمام. في هذه اللحظة ، هذا بلا شك # 10525. على وجه الخصوص https://github.com/JuliaLang/julia/pull/10525#issuecomment -84597488 يحتاج إلى نوع من الدقة.

timholy لم أتابع حقًا جميع التطورات في الفهرسة الديكارتية السريعة ، وبعد إلقاء نظرة على base / multidimensional.jl ، أرى أن هناك الكثير من البرمجة الوصفية. هل هناك أي فرصة لكتابة الوقت (أو إلقاء خطاب JuliaCon) حول كيفية عمل كل هذا؟

في بعض النواحي ، لا يوجد الكثير لتعرفه: في حين أن هناك قدرًا لا بأس به من المعلومات التي تحدث تحت غطاء المحرك ، فإن الفكرة هي جعله سهل الاستخدام. حتى حرفيا تماما

k = 0
for I in eachindex(A)
     B[k+=1] = A[I]   # B is being linearly-indexed, A is being cartesian-indexed
end

قد يكون كل ما تحتاج إلى معرفته. (بعبارة أخرى ، قد تكون المساعدة على eachindex هي كل الوثائق المطلوبة.) ومع ذلك ، اتضح أنه يمكنك كتابة عدد كبير جدًا من الخوارزميات باستخدام بعض الامتدادات لهذا النموذج الأساسي ؛ ما هي هذه الإضافات ولماذا تكون قوية ، قد تكون في الواقع أقل وضوحًا.

أخطط لكتابة هذا في وقت ما في الأشهر المقبلة ، ولكن إذا أراد الناس حقًا معرفة التفاصيل ، فربما يكون حديث JuliaCon معقولًا. Jutho أو mbauman يمكن أن يقدم هذا الحديث تمامًا مثل أنا.

أود أن أضيف المزيد حول الغموض ، ولكن أعتقد أن بعض المناقشة اللاحقة لخصت بعض النقاط الرئيسية. ربما أكون أكثر حساسية تجاه هذا النوع من الغموض بصفتي غريبًا أو بدافع الخوف ، وفي خطر أن أبدو دراميًا للغاية. في رأيي المتواضع ، فإن أي عدد من التمارين البسيطة والحاسمة والمهمة يمكن أن تقودك إلى طريق لا يستحق فيه تحليل التكلفة / الفائدة لخطأ بسيط ذلك.

ربما يتعين علينا تنفيذ fastindex كغلاف حول كل مؤشر ، كما في # 10507

timholy هل هناك أي سبب لعدم قيام eachindex بإرجاع UnitRange للمصفوفات الخطية السريعة؟ سيظل نوعًا مستقرًا ، وإذا أراد المتصل في أي وقت التأكد من حصوله على مؤشر CartesianIndex ، فيمكنه يدويًا إنشاء CartesianRange (يمكننا أيضًا إضافة طريقة لـ eachindex(size(A)) نظرًا لعدم تصدير CartesianRange ).

هذا ما فعلته في البداية ، لكنني أعتقد أن Jutho غيره. (إذا لم يكن هذا صحيحًا ، فمن المحتمل أنني قمت بتغييره دون إدراك.) أفترض أن التغيير كان مدفوعًا من أجل الاتساق (لذا يمكنك الاعتماد على الحصول على CartesianIndex ) ، وهو أمر له قدر معين من المعنى . ولكن كما أشرت ، هناك وسائل بديلة لضمان ذلك.

Jutho ، أي أفكار؟

لا أتذكر تغيير eachindex ، لكن قد يكون كذلك. أنا بالتأكيد لا أتذكر سببًا جيدًا لذلك ، بخلاف الحصول على نتيجة متسقة مستقلة عن نوع المصفوفة. ولكن إذا تم شرح الفرق بين المصفوفات التي تحتوي على فهرسة خطية فعالة أو بدونها بوضوح في المستندات ، فلا أرى أي سبب لعدم تمكن eachindex إرجاع نطاق خطي في حالة المصفوفات ذات الفهرسة الخطية الفعالة.

timholy ، ردًا على مشاركتك السابقة ، لا يمكنني حضور JuliaCon ، لذا لا تتردد في التحدث عن الأشياء CartesianIndex (لقد ساهمت فقط ببعض اللمسات الأخيرة) إنني أتطلع إلى التقارير ومقاطع الفيديو الخاصة بالمؤتمر بالفعل.

فكرة غريبة: بالنسبة إلى مصفوفة A لأي بُعد (بما في ذلك البعد> 2) ، يمكن أن يكون لدى المرء A' دوريا تبدل مؤشرات A . إذن ، A'[i, j, k] == A[j, k, i] . سيختزل هذا إلى تبديل المصفوفة المعتاد للمصفوفات ثنائية الأبعاد ، بالإضافة إلى التحويل المعتاد لـ "متجهات" الصفوف والعمود عند تفسيره على أنه في MATLAB (مثل [n ، 1] و [1 ، n] 2d المصفوفات على التوالي). وبالتالي فإنه لن يقوم أبدًا بتعيين "متجه" لعمود ثنائي الأبعاد إلى متجه حقيقي أو "متجه" صف ثنائي الأبعاد إلى متجه حقيقي. (أعتقد أن هذه الخاصية جيدة ، لكن قد يختلف الآخرون.) ستعطي الهويات A'' == A' و v'' == v _ للمصفوفات والمتجهات التي يتم تفسيرها على أنها كائنات مصفوفة_. بالنظر إلى نوع التسلسل الهرمي للنوع كما نوقش أعلاه (حيث يتم تمييز المتجهات الحقيقية والمتجهات بشكل كافٍ عن المصفوفات المجردة) ، لا يزال من الممكن إعطاء ' طريقة مختلفة تمامًا للمتجهات الحقيقية والمتجهات المشتركة حيث تتوافق مع المفهوم الجبر الخطي ولا تحتاج إلى إرضاء v'' == v (ولكن يمكن أن يكون هذا ما قرر الناس أنهم يريدون).

لكي أكون واضحًا: لا أعتقد لثانية واحدة أن ' _ يحتاج إلى أي طريقة لمصفوفات الأبعاد> 2 ، لكنني لم أر هذا الاقتراح أعلاه (ما لم يكن هذا هو المقصود بـ "عكس المؤشرات ") واعتقدت أنني سأذكرها فقط. أكثر ضرر أراه يحدث (للوهلة الأولى) هو مفاهيمي: خلط عملية اندماجية (تعسفية بعض الشيء) مع عامل يؤخذ عادة في مجال الجبر الخطي. قد يجيب المرء على هذا بأن درجة معينة على الأقل من هذا الخلط أمر لا مفر منه عندما نحاول توسيع المفاهيم الجبرية الخطية إلى مفاهيم تتمحور حول البيانات فقط (كما يتضح من هذه المناقشة بأكملها). على هذا النحو ، قد نحصد أيضًا اختصارًا مناسبًا للتبديلات الدورية للمصفوفات متعددة الأبعاد كمنتج ثانوي لتحديد ما يجب أن يفعله ' بشكل عام لأبعاد المصفوفة متعددة الأبعاد طالما أنه يقلل إلى الحالة المتوقعة في 2 أبعاد. يمكن للمرء أيضًا إضافة طريقة تأخذ وسيطة عدد صحيح بحيث يبدل A'(k)[I] دوري مؤشرات A[I] k مرة ، مما يعطي A'(ndims(A))[I] == A[I] و A'(-k)[I] يبدل المؤشرات في الاتجاه المعاكس.

مجرد فكرة.

إذا تم تعريف transpose للمصفوفات متعددة الأبعاد ، فإنني أفضل أن يظل يرضي A''=A ، أي أنه معكوسه الخاص. هذا يتعارض بشكل مباشر مع الاقتراح السابق.

هذا عادل. كما قلت ، فإن اقتراحي يكون جذابًا (محتملًا) فقط إذا كان المرء مرتاحًا لترك صدع ينمو بين الأهمية الجبرية الخطية للتبديل وأي أهمية مركزية مركزية يفرضها المرء في حالة d> 2. كان تفكيري هو أنه طالما أن هذا الصدع يحدث بالفعل (نوعًا ما) ، وإذا كانت الطرق غير مستخدمة تمامًا بخلاف ذلك ، فقد يكون من الرائع أن يكون لديك اختصار لتبديل المؤشرات - طالما أنها لا تتطلب أيًا معاملة خاصة لجعل الحالة d = 2 تعمل. كما ذكرت (Jutho) ، إنها مصادفة ملائمة أن تبديل الأبعاد في الحالة ثنائية الأبعاد له أهمية جبرية خطية (وفقط بعد تحديد المتجهات (co) كمصفوفات ثنائية الأبعاد ، لهذا الأمر) ، لذلك ربما لا نفعل ذلك لا داعي لأن تكون صعب الإرضاء بشأن الخصائص الرياضية transpose (على سبيل المثال تتطلب A'' == A ) لـ d> 2. إذا رغب المرء في السير في هذا الطريق ، فهناك الكثير من الطرق المفيدة التي يمكن أن يتم تعيينه ، على سبيل المثال: A' يتحول دوريًا مرة واحدة ، A'(k) يتناوب بشكل دوري k مرة ، A'(I) لـ I::Array{Int, 1} بطول <= ndims(A) دوري تبدل المؤشرات المدرجة في I ، و A'(p) لـ p::Permutation بطول <= ndims(A) تتعارض مع المؤشرات وفقًا لـ p . لكنني أفترض أن أفضل ما يجب فعله هو إنشاء حزمة ومعرفة ما إذا كانت مفيدة بما يكفي للاستفادة منها.

أؤيد تغييرين / توضيحيين تم ذكرهما ، على سبيل المثال ، بواسطة StefanKarpinski في 16 أكتوبر 2014 ، و simonbyrne في 22 مارس 2015 ، ولكن بشرط واحد:

  1. transpose للمتجهات والمصفوفات ثنائية الأبعاد فقط ، وليس الموترات العامة.
  2. يجب أن تحذف عوامل التشغيل * و transpose أبعاد مفردة لاحقة في نهاية الحساب. خلاف ذلك ، قد يتم الاحتفاظ بأبعاد مفردة لاحقة.

سيوفر هذان التغييران العديد من وسائل الراحة ويحلان العديد من الغموض في عمل الجبر الخطي التقليدي. إنهم لا يقولون شيئًا عن قصد حول فهرسة المصفوفة العامة أو جبر الموتر ، والتي يمكن اعتبارها منفصلة. (على وجه الخصوص ، يجب اعتبار تبديل الموتر على أنه عملية منفصلة تمامًا عن تبديل المصفوفة / المتجه.)

بموجب هذا الاقتراح ، عند العمل مع ضرب المصفوفة وتبديلها ، لن يكون هناك أساسًا أي تمييز بين متجه ومصفوفة ذات عمود واحد ، ولن يكون هناك أي اختلافات ذات مغزى بين العددي والمتجه بطول 1 و 1 في -1 مصفوفة. ومع ذلك ، فإن x' سيكون مصفوفة 1 × n ، وليس متجهًا.

من ناحية أخرى ، لغرض الاحتفاظ بالبيانات ، يمكن إنشاء مصفوفة من أي حجم. لن يتم حذف أي أبعاد مفردة لأن مفاهيم الجبر الخطي للضرب والتبديل لن يتم تضمينها.

يوجد أدناه نسخة افتراضية من جلسة جوليا مع التغييرات المقترحة.

أولاً ، نحدد العدد القياسي والمتجهين والمصفوفة.

julia> alpha = 2.0
2.0

julia> x = [1.0; 2.0; 3.0]
3-element Array{Float64,1}:
 1.0
 2.0
 3.0

julia> y = [4.0; 5.0; 6.0]
3-element Array{Float64,1}:
 4.0
 5.0
 6.0

julia> A = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0]
3x3 Array{Float64,2}:
 1.0  2.0  3.0
 4.0  5.0  6.0
 7.0  8.0  9.0

يعمل الضرب المتجه عدديًا حتى في حالة وجود أبعاد خارجية ، وتكون النتيجة دائمًا متجهًا.

julia> alpha*x
3-element Array{Float64,1}:
 2.0
 4.0
 6.0

julia> alpha*x[:,[1]]
3-element Array{Float64,1}:
 2.0
 4.0
 6.0

التحويل هو ارتداد.

julia> x'
1x3 Array{Float64,2}:
 1.0  2.0  3.0

julia> x''
3-element Array{Float64,1}:
 1.0
 2.0
 3.0

julia> x==x''
true

julia> x'''
1x3 Array{Float64,2}:
 1.0  2.0  3.0

ينتج عن ضرب مصفوفة في مصفوفة ذات عمود واحد نتيجة مماثلة لمنتج متجه المصفوفة.

julia> A*x
3-element Array{Float64,1}:
 14.0
 32.0
 50.0

julia> A*x[:,[1]]
3-element Array{Float64,1}:
 14.0
 32.0
 50.0

مصفوفة من صف واحد في مصفوفة تساوي مصفوفة من صف واحد.

julia> x'*A
1x3 Array{Float64,2}:
 30.0  36.0  42.0

المنتج الداخلي عبارة عن عددية ويتم إنتاجه بواسطة القواعد العامة لمتجه المصفوفة ومنتجات المصفوفة.

julia> x'*y
32.0

julia> x'*y[:,[1]]
32.0

المنتج الخارجي ليس شيئًا مميزًا.

julia> x*y'
3x3 Array{Float64,2}:
  4.0   5.0   6.0
  8.0  10.0  12.0
 12.0  15.0  18.0

julia> x[:,[1]]*y'
3x3 Array{Float64,2}:
  4.0   5.0   6.0
  8.0  10.0  12.0
 12.0  15.0  18.0

المتجه مضروبًا في المتجه هو خطأ.

julia> x*y
ERROR: `*` has no method matching *(::Array{Float64,1}, ::Array{Float64,1})

المتجه مضروبًا في المصفوفة خطأ.

julia> x*A
ERROR: DimensionMismatch("*")
 in gemm_wrapper! at linalg/matmul.jl:270
 in * at linalg/matmul.jl:74

إن عملية ضرب المصفوفة ترابطية.

julia> (x*x')*y
3-element Array{Float64,1}:
 32.0
 64.0
 96.0

julia> x'*y
32.0

julia> x*(x'*y)
3-element Array{Float64,1}:
 32.0
 64.0
 96.0

julia> norm((x*x')*y-x*(x'*y))
0.0

تحرير: تم حذف مثالين يتضمنان خفض ترتيب البعد الداخلي في أحد المنتجات. لم يكن لديهم تأثير كبير على المناقشة الحالية.

أخشى أن هذا قد يفقد الاستقرار النوعي للعمليات المعنية ، نظرًا لأن تجاهل الأبعاد المفردة الزائدة ليس عملية مستقرة من النوع.

بالطريقة التي أراها ، فإن عمل covector بأكمله يتعلق بالحصول على بُعد فردي وهو معروف بناءً على النوع الذي سيتم إزالته. أيضًا ، كنا نحاول جاهدًا الحفاظ على التمييز بين المتجه والمصفوفة التي تصادف وجود عمود واحد ، ولكن هذا الاقتراح سيزيل هذا التمييز في بعض الحالات ، مثل x'' .

اقتراح هرطقة: ماذا لو أسقطنا الأبعاد من معلمات النوع ، وقمنا بفحص الأبعاد / الحجم في وقت التشغيل؟ (ينتهي بنا الأمر إلى القيام بقدر لا بأس به من ذلك على أي حال.) وترك معلمة الأبعاد للأنواع التي تشفر الحجم أيضًا كمعامل نوع. (البط ، يختبئ لمدة أسبوعين ، ويغير حسابه على github إلىSomeoneWhoCertainlyIsntTimHolyUhUhNoWay.)

(بالطبع ، سأشتكي من نفسي على حساب # 10525 وحده.)

FWIW ، أود أن أقول أن هذه ليست فكرة مجنونة: إنها طريقة عمل Torch ، على سبيل المثال ، وقد أعرب مطورو Torch عن عدم رضاهم عن ترميز Julia للأبعاد داخل نظام الكتابة.

timholy السؤال: هل يمكننا استخدام هذا تحسين الدلالات فيما يتعلق بالجبر الخطي

إذا كان الشخص لا يزال مهتمًا باستخدام CoVector / DualVector / TransposeVector فلا يزال يتعين علينا إنهاء TimHolyArray{DataType} _ و_ سيتعين علينا أن نفهم تبديل مصفوفة ذات أبعاد أكبر من اثنين (أو واحد) ، أو منع البناء TransposeVector(tharray) عندما يكون tharray بعدًا أكبر من اثنين (أو واحد) ... في الواقع ، كل أنواع سيتعين على الأشياء إعطاء أخطاء على مستوى وقت التشغيل والتي تعد حاليًا أخطاء وقت الترجمة (مثل عمليات الضرب غير المحددة حاليًا وبالتالي ممنوعة بواسطة نظام الكتابة).

من ناحية أخرى ، قد يكون تنفيذ علامة تبديل داخل هذه الفئة الجديدة أمرًا سيئًا ... فهو يضيف مزيدًا من التعقيد لما يجب أن يكون حاوية فعالة وخفيفة الوزن. كنت أميل إلى استبعاد هذا الخيار ، وترك العمل الشاق لنظام المترجم / النوع.

أنا لست بالضرورة ضد فكرتك - ولكن يبدو أنها مشكلة إضافية يمكن القيام بها بالتوازي مع عمليات النقل الموجهة.

timholy : أنا متأكد حقًا مما إذا كان هذا هو السبيل للذهاب أم لا. هناك حالات أجد فيها أنه من المفيد جدًا نشر البعد.

كان الاقتراح هو جعل هذا ينطبق على جميع المصفوفات. ولكن أنا ضد اقتراح بلدي الآن، لأنه ببساطة لكثير من الحالات متعددة الأبعاد تحتاج إلى توليد N الحلقات ل N صفائف الأبعاد. لا يمكننا فعل ذلك أكثر من ذلك إذا لم يكن N معلمة نوع.

نعم ، أليست هذه هي النقطة الكاملة لوحدات الماكرو الديكارتية (أو الوظيفة المرحلية التي ما زلت غير معتاد على :-))؟
لقد فعلت أشياء مماثلة في C ++ حيث إنه لأمر حقيقي أن يكون لديك البعد كمعلمة قالب. لكن كان لدي مواقف كان فيها المتغير الديناميكي مقيدًا لأن المرء يحتاج إلى عبارات كبيرة لتخصص أبعاد الصفيف المختلفة.

اقتراح:

  1. أعد تسمية سلوك ضرب المصفوفة الحالي إلى timesfast وسلوك التحويل الحالي إلى transposefast .
  2. قم بتعديل (*) و transpose لاقتطاع أبعاد مفردة لاحقة كما في التعليق السابق . على سبيل المثال ، سيصبح u'*v رقمًا قياسيًا ، وسيصبح v'' ناقلًا ، وسيتم تعريف (v*v')/(v'*v) .

السلوك الموجود هو نوع مستقر. يتبع السلوك المقترح اصطلاحات العديد من نصوص الجبر الخطية. كلاهما ذو قيمة. ربما يجب أن تمتلك جوليا كليهما.

أريد استخدام جوليا في الفصل الدراسي ، لذلك أصوت للسلوك الافتراضي لتقييم الراحة على الكفاءة.

شكرًا للعديد من المساهمين الذين ساعدوني على إضفاء السرعة على هذا الموضوع الطويل جدًا!

briansutton : أعتقد أنه يجب عليك حقًا إعادة النظر في ما تطلبه. أود أن أشجعك على الانتظار حتى يكون لديك فهم أعمق لكيفية عمل جوليا قبل اقتراح إعادة تعريف معنى الضرب.

كانت هذه المشكلة تتعلق بكيفية تجنب أكبر عدد ممكن من الحالات الخاصة.

القواعد التي تسمح بالتلاعب بالأبعاد المفردة تكسر اللحظة التي يهتم بها أحد الأبعاد الفردية. باستخدام قاعدة "اقتطاع [الكل] أبعاد مفردة لاحقة" ، إذا كان v متجهًا مكونًا من عنصر واحد ، فإن v' هو عددية ، وبالتالي فإن v'' هو أيضًا العددية. لذا حتى في هذا الاقتراح فإن الخاصية التي لا تحمل دائمًا v == v'' .

يمكنك محاولة تعديل القاعدة "لاقتطاع آخر بعد مفرد لاحقة فقط إذا كان للمصفوفة أبعاد 2". ولكن حتى مع هذه القاعدة المعدلة ، فإن المنتج الخارجي v * w' لا يتبع تلقائيًا من تعريف ضرب المصفوفة ، ولكن بدلاً من ذلك يجب أن يكون تعريفه الخاص بغلاف خاص وهو Vector * Matrix ، ويجب أن يكون التعريف يكون "طرح خطأ ما لم تكن الأشكال (N) x (1، M)".

@ jiahao :

عند إجراء الجبر الخطي باستخدام المتجهات والمصفوفات ، لا أرغب في رسم أي فروق بين العددية والمتجه المكون من عنصر واحد والمصفوفة 1 × 1. حاليًا ، تنتج عمليات مختلفة أيًا من العناصر الثلاثة. اقتراحي هو ، لعمليات ضرب المصفوفة وتبديلها ، اختيار واحد من الثلاثة ليكون التمثيل المفضل.

فيما يتعلق بمثالك الأول ( v==v'' ) ، أود تجنب إنشاء متجه مكون من عنصر واحد v في المقام الأول.

فيما يتعلق بمثالك الثاني ، نعم ، أعتقد أنه يجب التعامل مع v*w' تمامًا كما تصف. عند العمل مع ضرب المصفوفة وتبديلها ، أريد المتجه v والمصفوفة N-by-1 v[:,[1]] للدلالة على نفس الكائن الرياضي ، حتى لو كان لديهم تمثيلات داخلية مختلفة. قد يتطلب هذا رمزًا خاصًا للتعامل مع المصفوفة N مرات 1 × M.

أعتقد أنك ما زلت غير مقتنع بأن استقرار النوع مهم.

briansutton : أعتقد أنك ستجد أنه من المفيد جدًا محاولة تنفيذ الآلية المطلوبة لجعل عرضك يعمل بالسرعة التي يسمح بها نظام الكتابة الحالي لجوليا للعمل. أنا ، على سبيل المثال ، أعتقد أن أهدافك المعلنة غير قابلة للتحقيق نظرًا لأهداف جوليان المتمثلة في تقديم أداء يمكن التنبؤ به وتوافق تخطيط ذاكرة C.

لست متأكدًا مما إذا كنت أفهم الحجج ذهابًا وإيابًا ، ولكن شيئًا واحدًا لفت انتباهي. ربما يكون هذا تفكيرًا أمنيًا ، لكن سيكون من الجيد أن يكون الكمبيوتر قادرًا على التفكير بسرعة الدماغ البشري. ما أعنيه هو أنه عندما يتحدث برايان سوتون عن برنامج "اختيار التمثيل المفضل" ، أتخيل برنامجًا يمكنه التفكير ، تمامًا كما نستطيع ، عندما نفعل الرياضيات. ربما لا يكون ذلك ممكنًا مع تكنولوجيا اليوم وسيؤدي إلى إبطاء الأمور كثيرًا. لكن ، أليس من الجميل ...

أنا فيزيائي ومستخدم نشط لجوليا.

لم يعد لدي تفضيل قوي في الحفاظ على الطقس أو إسقاط جميع الأبعاد المفردة الزائدة

ولكن هنا أود أن أثير مسألة وثيقة الصلة بالموضوع.

تطبيق Julia الحالي:

لنفترض أن V يكون موترًا ثلاثي الأبعاد من رتبة 1 (متجه)
سوف تعطينا V [1] قشارة وليس موتر 1-خافت من الرتبة 1

دع A يكون موتر 3x4x5 من الرتبة 3
B = A [1،:،:] سوف يعطينا موتر 1x4x5 من رتبة 3.

السلوكان أعلاه غير متسقين تمامًا.

أفضّل بشدة ميزة الفهرسة / الانزلاق التالية:

دع A يكون موتر 3x4x5 من الرتبة 3
B = A [1،:،:] سوف يعطينا موتر 4x5 من رتبة 2.
C = A [1: 1،:،:] سوف يعطينا موتر 1x4x5 من الرتبة 2.
(حاليا أعلاه تعطي نفس النتيجة)

لنفترض أن V يكون موترًا من المرتبة الأولى
B = V [1] سوف يعطينا قشارة
C = V [1: 1] سيعطينا موتر 1-خافت من رتبة 1.

ستساعدنا هذه الميزة في تغيير شكل الموتر بسهولة أكبر ، وستكون مفيدة عندما نسمح بتتبع المؤشرات المفردة.

الأفضل

شياو جانج


من: esd100 [[email protected]]
تاريخ الإرسال: الثلاثاء ، 09 يونيو 2015 الساعة 9:46 مساءً
إلى: JuliaLang / julia
نسخة إلى: شياو قانغ ون
الموضوع: Re: [جوليا] التعامل بجدية مع النقل المتجه (# 4774)

لست متأكدًا مما إذا كنت أفهم الحجج ذهابًا وإيابًا ، ولكن شيئًا واحدًا لفت انتباهي. ربما يكون هذا تفكيرًا أمنيًا ، لكن سيكون من الجيد أن يكون الكمبيوتر قادرًا على التفكير بسرعة الدماغ البشري. ما أعنيه هو أنه عندما يتحدث برايان سوتون عن برنامج "اختيار التمثيل المفضل" ، أتخيل برنامجًا يمكنه التفكير ، تمامًا كما نستطيع ، عندما نفعل الرياضيات. ربما لا يكون ذلك ممكنًا مع تكنولوجيا اليوم وسيؤدي إلى إبطاء الأمور كثيرًا. لكن ، أليس من الجميل ...

-
يمكنك الرد على هذه الرسالة الإلكترونية مباشرةً أو عرضها على Gi tHubhttps: //github.com/JuliaLang/julia/issues/4774#issuecomment -110554622.

أعني: C = A [1: 1،:،:] سوف يعطينا موتر 1x4x5 من الرتبة 3.

شياو جانج


من: Xiao-Gang Wen [[email protected]]
تاريخ الإرسال: الاثنين 22 يونيو 2015 الساعة 12:01 مساءً
إلى: JuliaLang / julia ؛ جوليا لانج / جوليا
نسخة إلى: شياو قانغ ون
الموضوع: RE: [جوليا] التعامل بجدية مع نقل المتجهات (# 4774)

أنا فيزيائي ومستخدم نشط لجوليا.

لم يعد لدي تفضيل قوي في الحفاظ على الطقس أو إسقاط جميع الأبعاد المفردة الزائدة

ولكن هنا أود أن أثير مسألة وثيقة الصلة بالموضوع.

تطبيق Julia الحالي:

لنفترض أن V يكون موترًا ثلاثي الأبعاد من رتبة 1 (متجه)
سوف تعطينا V [1] قشارة وليس موتر 1-خافت من الرتبة 1

دع A يكون موتر 3x4x5 من الرتبة 3
B = A [1،:،:] سوف يعطينا موتر 1x4x5 من رتبة 3.

السلوكان أعلاه غير متسقين تمامًا.

أفضّل بشدة ميزة الفهرسة / الانزلاق التالية:

دع A يكون موتر 3x4x5 من الرتبة 3
B = A [1،:،:] سوف يعطينا موتر 4x5 من رتبة 2.
C = A [1: 1،:،:] سوف يعطينا موتر 1x4x5 من الرتبة 2.
(حاليا أعلاه تعطي نفس النتيجة)

لنفترض أن V يكون موترًا من المرتبة الأولى
B = V [1] سوف يعطينا قشارة
C = V [1: 1] سيعطينا موتر 1-خافت من رتبة 1.

ستساعدنا هذه الميزة في تغيير شكل الموتر بسهولة أكبر ، وستكون مفيدة عندما نسمح بتتبع المؤشرات المفردة.

الأفضل

شياو جانج


من: esd100 [[email protected]]
تاريخ الإرسال: الثلاثاء ، 09 يونيو 2015 الساعة 9:46 مساءً
إلى: JuliaLang / julia
نسخة إلى: شياو قانغ ون
الموضوع: Re: [جوليا] التعامل بجدية مع النقل المتجه (# 4774)

لست متأكدًا مما إذا كنت أفهم الحجج ذهابًا وإيابًا ، ولكن شيئًا واحدًا لفت انتباهي. ربما يكون هذا تفكيرًا أمنيًا ، لكن سيكون من الجيد أن يكون الكمبيوتر قادرًا على التفكير بسرعة الدماغ البشري. ما أعنيه هو أنه عندما يتحدث برايان سوتون عن برنامج "اختيار التمثيل المفضل" ، أتخيل برنامجًا يمكنه التفكير ، تمامًا كما نستطيع ، عندما نفعل الرياضيات. ربما لا يكون ذلك ممكنًا مع تكنولوجيا اليوم وسيؤدي إلى إبطاء الأمور كثيرًا. لكن ، أليس من الجميل ...

-
يمكنك الرد على هذه الرسالة الإلكترونية مباشرةً أو عرضها على Gi tHubhttps: //github.com/JuliaLang/julia/issues/4774#issuecomment -110554622.

ما تطلبه هو كيف يعمل slice حاليًا. إحساسي أن A[stuff] سيصبح مرادفًا لـ slice(A, stuff) ، وبالتالي ستحصل على رغبتك على الأرجح.

عزيزي تيم:

شكرا على البقشيش. لقد جربت شريحة. لا تناسب احتياجاتي. تنتج شريحة نوع بيانات جديد "subarray" لا يمكنني استخدامه في التعليمات البرمجية الأخرى التي تستخدم :: Array data type.

ربما يمكنني تغيير الكود الآخر الخاص بي بحيث يسمح بنوع البيانات "subarray".

شياو جانج


من: Tim Holy [[email protected]]
تاريخ الإرسال: الاثنين 22 يونيو 2015 5:32 مساءً
إلى: JuliaLang / julia
نسخة إلى: شياو قانغ ون
الموضوع: Re: [جوليا] التعامل بجدية مع النقل المتجه (# 4774)

ما تطلبه هو كيف تعمل الشريحة حاليًا. إحساسي هو أن [الأشياء] ستصبح مرادفًا للشريحة (أ ، أشياء) ، وبالتالي ستحصل على رغبتك على الأرجح.

-
يمكنك الرد على هذه الرسالة الإلكترونية مباشرةً أو عرضها على Gi tHubhttps: //github.com/JuliaLang/julia/issues/4774#issuecomment -114268796.

هل هناك أي شيء يعتمد حقًا على استخدام أنواع Array بدلاً من AbstractArray في شفرتك؟ قد لا يتطلب الأمر أكثر من بحث / استبدال Array بـ AbstractArray لجعل الأشياء تعمل.

عزيزي سكوت

شكرا جزيلا على النصيحة لك.

شياو جانج


من: Scott P. Jones [[email protected]]
تاريخ الإرسال: الخميس 25 حزيران (يونيو) 2015 الساعة 9:55 صباحًا
إلى: JuliaLang / julia
نسخة إلى: شياو قانغ ون
الموضوع: Re: [جوليا] التعامل بجدية مع النقل المتجه (# 4774)

هل هناك أي شيء يعتمد حقًا على استخدام أنواع المصفوفة الملموسة بدلاً من AbstractArray في التعليمات البرمجية الخاصة بك؟ قد لا يتطلب الأمر أكثر من بحث / استبدال Array مع AbstractArray لجعل الأشياء تعمل.

-
قم بالرد على هذه الرسالة الإلكترونية مباشرة أو tHubhttps: //github.com/JuliaLang/julia/issues/4774#issuecomment -115265047.

هل فعل ذلك الحيلة بالنسبة لك؟ أنا سعيد للمساعدة!

wenxgwen ، بدلاً من ذلك ، يمكنك استدعاء copy(slice(A,...)) أجل الحصول على نسخة من الشريحة في Array والتي يجب أن تعمل في الأصل مع وظائفك الموجودة بالفعل.

أصبح إصلاح هذه المشكلة الآن مسعىً مربحًا

نظرًا لأن إصلاح هذه المشكلة أصبح الآن أمرًا بالغ الأهمية في طريقي إلى 3 فواصل ...
image

ولكن بكل جدية. حاولت قراءة المناقشة بالكامل ولكن لا يمكنني ضمان عدم اقتراح هذا من قبل:

هل يمكننا توسيع تعريف AbstractArray للحصول على سمة إضافية (على غرار LinearIndexing؟) والتي تحدد ما إذا كانت البيانات الأساسية هي التخزين على أساس الصف أو العمود؟ ستفتح هذه الإضافة الخصائص التالية (من فضلك لا تركز على الأسماء ... فقط المفاهيم):

v --> length-2 Vector{Col}
  [ 1
    2 ]

v'  --> length-2 Vector{Row}
  [ 1 2 ]

m --> 2x2 Matrix{Col}
  [ 1 3 
    2 4 ]

m' --> 2x2 Matrix{Row}
  [ 1 2 
    3 4 ]

Some operations:
v'  --> length-2 Vector{Col}
v'' == v
v*v or v'*v'  --> either error, or do element-wise multiplication
v' * v --> scalar
v * v' --> 2x2 Matrix  (could be Row or Col??)
v' * m --> 2-length Vector{Row}
v * m --> either error or broadcasting operation
m * v --> either error or broadcasting operation
m * v' --> 2-length Vector{Col}

Indexing:
v[2] --> 2
v[1,2] --> error
v'[1,2] --> 2
m[1,2]  --> 3
m'[1,2]  --> 2

Size:
length(v)  --> 2
length(v')  --> 2
size(v)  --> (2,)
size(v')  --> (2,)
length(m)  --> 4
size(m)  --> (2,2)

من الواضح أن هذا الاقتراح يفتقد إلى الكثير من التعريفات ، ولكن ربما يمكن أن يبدأ المناقشة. هل يمكننا دعم تخزين فهرس العمود وفهرس الصف في نفس الوقت ، و "إصلاح" بعض المشكلات على طول الطريق؟

أتمنى بشدة أن تكون جوليا عبارة عن تخزين قائم على الصفوف ، لأن هذا هو بطبيعة الحال كيف أفكر في الحلقات والعديد من العمليات الأخرى. (ولا أعتقد أنني الوحيد الذي يفكر بهذه الطريقة) تعليقات من فضلك!

إنها فكرة مثيرة للاهتمام ، حيث يأخذ المُنشئ أيضًا في الصف أو العمود. أعتقد أنه تمت مناقشته من قبل في مكان ما عميقًا في نظام مشكلات GitHub. قد أكون مخطئا!

أنا شخصياً أفضل التخزين المستند إلى الأعمدة لأن معظم كتبي المدرسية تستخدم أعمدة في الرياضيات الخاصة بهم ، ثم في Julia لا أحتاج إلى تغيير كل شيء لاستخدام الصفوف بدلاً من ذلك. كما أنني وجدت الأمر غريبًا في البداية ولكنه سرعان ما أصبح مشكلة لعملي. هناك خوارزميات يسهل التعبير عنها في الصفوف ، ولكن هذا هو السبب في أنه قد يكون من الجيد أن تكون قادرًا على استخدام تخزين غير قياسي عند الحاجة. أتمنى أن تكون الاتفاقية على الرغم من أنها تُرجع دائمًا مصفوفة رئيسية للعمود أو متجه عمود عندما يكون لديك وظيفة يتم تصديرها بحيث لا يكون هناك أبدًا سؤال حول النوع الذي لديك عند استدعاء دالة. وإلا فقد يصبح الأمر فوضويًا جدًا ويصبح استخدامًا مزعجًا عندما تضطر إلى البحث دائمًا عن النوع الذي يتم إرجاعه.

المستندة إلى العمود في مقابل الصفوف ليست ضمن نطاق هذه المشكلة.

tbreloff تعجبني الفكرة كثيرًا. سيكون من الرائع أن تكون قادرًا على التفاعل بسهولة أكبر مع اللغات / المكتبات المتخصصة في الصفوف.

Jiahao محق في أن تفضيل الصف الرئيسي مقابل العمود الرئيسي هو خارج الموضوع. انها
مجرد أثر جانبي لطيف يحل مشكلة تبديل الموضوع بطريقة "جوليان"
(الأنواع البارامترية والوظائف المرحلية) تمنح الأشخاص مزيدًا من المرونة في
تنسيق التخزين.

إذا لم تعجبك فكرة إضافة سمة صف / عمود إلى المصفوفات ، فعندئذٍ
يمكن تحقيق الشيء نفسه بالضبط باستخدام TransposeView {T، N} ، لكن أنا
تشك في أن التنفيذ الجيد سيكون أكثر تعقيدًا.

أكبر عيب في السمة الإضافية هو ارتباك المستخدمين الجدد ،
وهذا شيء أجد صعوبة في التوفيق معه.

في يوم السبت الموافق 26 سبتمبر 2015 ، أرسل Scott P. Jones [email protected]
كتب:

tbreloff https://github.com/tbreloff تعجبني الفكرة كثيرًا. ذلك
سيكون من الرائع أن تكون قادرًا على التفاعل بسهولة أكبر مع اللغات / المكتبات
هذا الصف الرئيسي.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/4774#issuecomment -143436947.

هل يؤدي التحميل الزائد للمكالمات إلى تغيير مساحة التصميم على الإطلاق؟ في بعض الأحيان ، يبدو أن هناك نوعًا من الغموض في معنى * . على وجه الخصوص ، عندما نريد v::Covector * w::Vector لإرجاع رقم قياسي ، فهل نأخذ * الواقع ليكون "map w تحت v " بدلاً من مضاعفة المصفوفة؟ إذا كان الأمر كذلك ، فلا يمكن لأحد أن يطالب بالمثل أن يقوم w::Vector * v::Covector بإرجاع عدد قياسي ، نظرًا لأن المتجهات هي نفسها خرائط خطية فوق المتجهات؟

ربما سيكون من المفيد بدلاً من ذلك زيادة التحميل على call وكتابة v(w) للإشارة إلى عملية "الخريطة تحت v " على w ، وبالمثل w(v) - كلاهما سيعيد الحجميات. هل سيسمح هذا بمزيد من الفسحة في استيعاب الدلالات التي تشترك فيها عمليات الصفيف والعمليات الجبرية الخطية في حالة المصفوفات ثنائية الأبعاد؟

إذا كان الأمر كذلك ، فلا يمكن لأحد أن يطالب بالمثل أن يعيد w :: Vector * v :: Covector عددًا قياسيًا ، نظرًا لأن المتجهات هي نفسها خرائط خطية فوق المتجهات؟

أعتقد أننا نحاول اتباع المصفوفة واتفاقيات المتجهات التي يراها العديد من الأشخاص في جامعة السنة الأولى ، وهي غير تبادلية ولديها ناقل * ناقل متجه -> مصفوفة (من الرتبة 1 ، أي وجود مفرد واحد (ليس صفري) القيمة). ما كتبته يبدو أشبه بمفهوم الجبر الخطي المجرد ، حيث يكون المتجه والمتجهات المزدوجة / المتجهات عبارة عن خرائط من بعضها البعض إلى بعض الحجمي ، وهو أمر جيد ولكنه يختلف قليلاً عما تمت تجربته (IMHO) في Julia و MATLAB. أعتقد أننا يمكن أن نفسر ما كتبته على أنه المنتج الداخلي ، أو dot() أو يعمل على اثنين من المتغيرات (التي يجب أن نحددها على الأرجح للمشتركين ، كما أشعر) ، لكن في بعض الأحيان نريد أيضًا المظهر الخارجي -المنتج ، وحالياً يسمح لنا * غير المجمل بالكتابة والتعبير عن كلا السلوكين.

بالنسبة إلى اصطلاح الاستدعاء v(w) ، يمكننا أن نقول بالتساوي بالنسبة للمنتج النقطي أننا نريد مبلغ v في اتجاه w مما يوحي بأننا نستخدم عامل الفهرسة v[w] . (راجع للشغل ، أنا لا أقول أن هذا خيار تصميم لغة جيد - مجرد ملاحظة!)

يمكننا أن نقول بنفس القدر بالنسبة للمنتج النقطي أننا نريد مبلغ v في اتجاه w مما يوحي بأننا نستخدم عامل الفهرسة v[w] .

يتوافق هذا الاقتراح تقريبًا مع دلالات الفهرسة ، ولكنه لا يتوافق معها. يتعارض أيضًا مع دعمنا الحالي لفهرسة المتجهات إذا كان v هو Vector{<:Integer} .

ضع في اعتبارك أنه بالنسبة إلى v :: Vector{T<:Real} ، فإن v[1] يعادل المنتج النقطي v⋅e₁ ، حيث e₁ هو متجه الأساس الأساسي على طول المحور الأول. لذلك ، الفهرسة البسيطة هي في الحقيقة الوظيفة

   v[n] : n :: Integer --> y = (v ⋅ eₙ) :: T

بالنسبة لفهرسة المتجهات ، ينتج v[[1, 2]] [v⋅e₁, v⋅e₂] وهو نتيجة إسقاط v في الفضاء الفرعي الممتد بـ {e₁, e₂} ، أو ما يعادله هو نتيجة v' * [e₁ e₂] .

لذا فإن فهرسة المتجهات هي الوظيفة

   v[I] : I :: Vector{<:Integer} --> y = v' * [eₙ for n in I] :: Vector{T}

اقتراح جعل v[w] = (w ⋅ v) v غير متسق مع هذا التعريف لأنه يلغي التعيين الضمني من مجموعة من المؤشرات n (كما هو محدد بواسطة w ) لمجموعة من متجه الأساس المتعارف عليه eₙ ، وهو أمر ضروري حتى تعمل قواعد الفهرسة الحالية لدينا.

تحديد النطاق لمجرد تبديل المتجه في الوقت الحالي ، أعتقد أن لدينا خيارين. يمكننا إما أن نخطئ أو يمكننا تقديم نوع covector الخاص. نظرًا لطبيعة المتجه من الدرجة الأولى في جوليا ، أعتقد أن الأول سيكون بيعًا صعبًا للغاية ... وللقيام بذلك باستمرار ، يجب أن نمنع المتجهات تمامًا من المشاركة في جبر المصفوفات تمامًا.

لذلك أخذت رصاصة على كوفكتور. إنه عمل كثير ، وللأسف لن أتمكن من قضاء المزيد من الوقت فيه. أنشره هنا على أمل أن يركض شخص ما معه أو أن نتعلم من الصعوبات ونقرر الهروب. لكن لدي مبنى فرعي مع تحويلات كوجهات نظر ، وضرب المصفوفة مطبق مع المتجهات. تنجح بعض الاختبارات المحددة ، ولكن فقط بدون depwarn=error (على سبيل المثال ، ./julia -e 'using Base.Test; include("test/matmul.jl")' ). https://github.com/JuliaLang/julia/compare/mb/transpose

لقد حددت نوعين جديدين من طرق العرض لاستخدامهما في transpose و ctranspose من المصفوفات والمتجهات:

immutable MatrixTranspose{C,T,A} <: AbstractArray{T,2}
    data::A # A <: AbstractMatrix{T}
end
immutable Covector{C,T,V} 
    data::V # V <: AbstractVector{T}
end

المعلمة C هي قيمة منطقية بسيطة لتمثيل ما إذا كان التحويل هو تبديل أم لا. لاحظ أن Covector هو _not_ نوع فرعي من AbstractArray ؛ هذا مطلب قوي جدًا للحصول على إيفاد للعمل بشكل معقول.

بعض العيوب:

  • إن Covectors معقدة بالتأكيد ، وسيكون من الصعب توثيقها بطريقة سهلة الوصول وصارمة. قد تساعد اللغة هنا - يمكننا ببساطة تسميتها RowVector s. بغض النظر ، فإن الصعوبة الأولى التي تواجهها عند محاولة شرح هذا السلوك هي كيف تتحدث عن شكل covector ( size غير محدد). إذا كان (m,n) هو شكل مصفوفة ، فإن (m,) يمكن أن يمثل شكل متجه ... وإذا أساءنا استخدام تدوين tuple ، فيمكننا وصف covector بشكل عام ليحصل على الشكل (,n) . هذا يسمح لنا بالتعبير عن قواعد الجبر المتجه / المصفوفة المختلطة ذات البعد "المفقود" الذي يجمع وينتشر بشكل معقول إلى حد ما:

    • المصفوفة * المتجه هو (m,n) × (n,) → (m,)

    • مصفوفة Covector * هي (,m) × (m,n) → (,n)

    • Vector * Covector هو (n,) × (,n) → (n,n)

    • Covector * Vector هو (,n) × (n,) → α (سلمي)

  • يؤدي عدد العمليات الثنائية والأنواع هنا إلى انفجار اندماجي ضخم في عدد الأساليب التي يجب تحديدها ... لمجرد الضرب لدينا:

    • الطفرة: (متحولة ، غير متغيرة)
    • تبديل: (A ، Aᵀ ، Aᴴ) × (B ، Bᵀ ، Bᴴ).
    • الشكل: (Mat × Mat؛ Vec × Mat؛ Mat × Vec، Vec × Vec). لاحظ أنه ليست كل هذه العناصر مدعومة عبر جميع مجموعات عمليات النقل ، ولكن معظمها مدعوم.
    • التنفيذ: (BLAS ، Strided ، عام ، بالإضافة إلى تخصصات المصفوفات الهيكلية)

    في حين أن بعض هذه العمليات تتوافق بشكل جيد مع العديد من سلوكيات الإرسال والاحتياطية ، إلا أنها لا تزال تمثل عددًا ضخمًا من الأساليب لكل مشغل. من المؤكد أن إزالة دعم المصفوفة / المتجه المختلط هنا سيساعد بالتأكيد في تبسيط الأمور.


  • إنهم لا يحلون على الفور أيًا من الصعوبات المتعلقة بإسقاط جميع الأبعاد العددية. إن دعم أي نوع من تبديل المتجهات عند إسقاط أبعاد قياسية يضعنا في منطقة غامضة فيما يتعلق بالاتحاد المعقد (انظر https://github.com/JuliaLang/julia/pull/13612). ربما يمكننا الحصول على A[1,:] لإرجاع covector ، لكنه لا يتم تعميمه جيدًا وسيكون من الغريب تمامًا إرجاع مصفوفة غير مجردة من شريحة. سيكون أمرًا رائعًا إذا كان بإمكان الأشخاص تجربة # 13612 والبحث على وجه التحديد عن الحالات التي يتسبب فيها التحويل المقترن للمتجه في حدوث مشكلة - فسيكون ذلك سيئًا بنفس القدر مع دلالات تبديل المتجه الحالية ولا يتطلب من Covectors الكشف عنها.

بعض المزايا:

  • يعد استخدام الإرسال مباشرة بدلاً من التحليل الخاص إلى Ax_mul_Bx فوزًا كبيرًا. يتألف بشكل جيد للغاية مع واجهة برمجة تطبيقات BLAS. بشكل عام ، تريد إجراء الاقتران في المستويات الأعمق من الخوارزميات ، لذلك من المنطقي الاحتفاظ بهذه المعلومات مع الحجج. بالنسبة لاستدعاءات BLAS ، يمكن استخدام وظيفة بسيطة للبحث عن حرف التحويل ( ntc ).
  • الضرب بين المتجهات والمتجهات المشتركة أصبح الآن ترابطيًا لأن v'v يُرجع مقياسًا. يمكنك الآن تقييم v'v*v من اليسار إلى اليمين وتجنب تكوين المصفوفة.
  • يسمح هذا بإزالة Vector * Matrix ، والتي لا تعمل إلا إذا تعاملت مع جميع المتجهات كما لو كانت لها أبعاد مفردة متتالية ... وهي خطوة رائعة نحو إزالة الدعم بالكامل للأبعاد المفردة اللاحقة بشكل عام.

الملاحظات الأخرى:

  • إن وجود تعقيد التحويل الذي يمثله معلمة النوع المنطقي يعمل بشكل جيد ، لكنني غالبًا ما شعرت أنني قد حددت المعلمات بترتيب خاطئ. نادرًا ما كنت أرغب في تقييد أو التقاط كل من T و C . لست متأكدًا مما إذا كان القيام بذلك بالطريقة الأخرى سيكون أفضل من حيث عدد أنواع العناصر النائبة التي تحتاج إلى تحديدها ، ولكن على الأقل سيتطابق مع AbstractArray{T} .
  • يؤدي هذا حقًا إلى تفاقم صعوبات StridedArray. تعد قراءة جدول الطريقة مقابل * تحديًا كبيرًا لأنواع مثل ::Union{DenseArray{T<:Union{Complex{Float32},Complex{Float64},Float32,Float64},2},MatrixTranspose{C,T<:Union{Complex{Float32},Complex{Float64},Float32,Float64},A<:Union{DenseArray{T,1},DenseArray{T,2},SubArray{T,1,A<:DenseArray{T,N},I<:Tuple{Vararg{Union{Colon,Int64,Range{Int64}}}},LD},SubArray{T,2,A<:DenseArray{T,N},I<:Tuple{Vararg{Union{Colon,Int64,Range{Int64}}}},LD}}},SubArray{T<:Union{Complex{Float32},Complex{Float64},Float32,Float64},2,A<:DenseArray{T,N},I<:Tuple{Vararg{Union{Colon,Int64,Range{Int64}}}},LD}} . بالتأكيد ، لقد كتبته على أنه نوع من أنواع الأسماء المستعارة ، ولكن حتى مجرد إدارة كل هذه الأنواع المختلفة من الأسماء المستعارة يمثل ألمًا ( StridedMatOrTrans ، QRCompactWYQorTranspose ، إلخ).
  • لم تتح لي الفرصة لدمج هذا مع SparseVector ، لكن هذا سيكون فوزًا كبيرًا لأنه سيمثل النقل بكفاءة دون الحاجة إلى CSR.
  • هل نحتاج إلى تعريف الفهرسة العددية و / أو غير العددية على Covectors؟ إذا كان الأمر كذلك ، فما هي نتيجة r[:] أو r[1:end] ؟ هل هو ناقل أم مصحح؟ أعتقد أنني سأحاول الابتعاد دون تحديد هذا إذا استطعنا. ومن المثير للاهتمام ، أن Matlab لديها قواعد خاصة جدًا لفهرسة متجهات الصف مع متجهات أخرى - فهم يحاولون جاهدين الحفاظ على صفهم على حساب بعض الحالات الغريبة ( r((1:end)') هو r(1:end) هو r(:)' ). لدي فهرسة رقمية محددة في الفرع الخاص بي في الوقت الحالي ، ولكن ربما يجب إزالتها أيضًا. من شأن ذلك أن يوضح أن Covector يستخدم فقط مع عمليات الجبر الخطية التي تعرف عنها.

أخيرًا ، أريد فقط أن أشير إلى أن معظم المزايا التي أراها هنا تنطبق تمامًا على النوع MatrixTranspose حد ذاته. أعتقد أن هذا يوضح أن Covector يمكن أن تعمل بشكل جيد دون الخوض في الجبر المجرد لتمكين عمليات Vector / Matrix المختلطة. إنها تضيف بالتأكيد ميزة لطيفة (القدرة على استخدام المتجهات باستمرار مع الجبر الخطي) ، لكنني لست متأكدًا من أنها تستحق التعقيد الإضافي.

بدافع الفضول ، إذا كنت لا تزال تتذكر mbauman ، فما الذي دفعك لتقديم المعامل المنطقي C ؟ لا يمكن أن يكون لديك فقط (في pseudotraits)

transpose(::Matrix) -> MatrixTranspose
transpose(::MatrixTranspose) -> Matrix

؟ أنا لا أشكك في حكمك (الاستثنائي) هنا ، فقط أريد أن أفهم ما الذي أجبرتك على القيام بذلك.

من المفترض أنه يمكن للمرء تعميم هذا على نوع PermutedDimensionArray ، باستخدام معلمة tuple ترميز التقليب. من الواضح أن النوع Covector له غرض مختلف ويجب أن يكون شيئًا منفصلاً.

تحتاج إلى طريقة ما للتعامل مع عمليات النقل المقترنة (وأيضًا المصفوفات المترافقة غير المنقولة مقابل (A').' ). أرى ثلاث طرق واضحة للقيام بذلك:

  • قم بتخزين الاقتران كحقل منطقي داخل نوع MatrixTranspose واحد فقط. عند التفكير ، أعتقد أن هذا هو بالتأكيد أفضل خيار للتفاعل مع BLAS الخارجي. فيما يتعلق بـ JuliaBLAS الأصلي ، على الرغم من ذلك ، أود التأكد من أن Julia / LLVM قادرة على رفع T.isconjugate ? conj(T[i,j]) : T[i,j] خارج الحلقات.
  • نوع واحد مع معلمة اقتران. هذا ما اخترته ، وأعتقد أنني تأثرت بحقيقة أننا نقوم حاليًا بإرسال زائف على الاتحاد عن طريق Ac_mul_Bt والأصدقاء. كما أن لديها ضمانات أقوى حول تحسينات إزالة الفروع التي تستطيع جوليا القيام بها. لكنني لم أفكر مليًا في ذلك ... أردت فقط أن أبدأ في تنفيذ الرسم التخطيطي ، وكنت أكثر قلقًا بشأن Covector.
  • نوعان منفصلان ، MatrixTranspose و MatrixCTranspose . متشابه مع معلمة نوع ، لكنني أجد نوعين منفصلين من الأغلفة مزعجين. يمكن أن تساعد الأنواع الكبيرة المجردة والأسماء المستعارة للاتحاد ، لكنني ما زلت أختار المعلمة فوق هذا الخيار.

أفترض أن هناك الآن خيارًا رابعًا بوظائف مكتوبة ، وتخزين أي وظيفة تحويل داخل نوع التحويل ... ولكن هذا يتطلب أيضًا معلمة نوع للوظيفة لتكون سريعة ، ومن ثم فهي معلمة نوع لا يمكن إرسالها بسهولة أيضًا.

أتساءل عما إذا كان بإمكاننا الحصول على غلاف ConjugateView ، مع القاعدة conj و transpose ضمان وضع ConjugateView داخل غلاف MatrixTranspose . أي ، مقابل A a Matrix ،
ينتج كل من A' = conj(transpose(A)) = transpose(conj(A)) MatrixTranspose{ConjugateView{Matrix}} (مع استبعاد معلمات النوع غير المفيدة).

آه ، نعم ، هذا معقول أيضًا. أميل إلى التفكير في التحويل المترافق على أنه "شيء" ذري واحد ، لذلك فاتني هذا الخيار. كنت أفكر في كيفية تمثيل عمليات النقل غير المقترنة بنوع فهرس مصفوفة فرعية خاصة ، تمامًا مثل إعادة التشكيل.

أنا سعيد لأنكم ما زلتم تعملون على هذا! هذا خيط ملحمي! ثلاث هتافات !!!

هل هذا مخطط لـ 1.0؟

في مشكلتين (# 18056 ، # 18136) أشرت إلى هذا الموضوع العملاق.
لذلك أعطيها محاولة.

الآن لدى جوليا متجهات حقيقية أحادية الأبعاد ، _e.g._ mx[row,:] لم تعد مصفوفة 1xn بعد الآن.
هذا تغيير مرحب به!

ولكن كأثر جانبي ، أصبحت بعض المشاكل القائمة أكثر وضوحًا.
لقد شعرت بالعض من حقيقة أن v*mx لا يعمل مع المتجهات أحادية البعد.
رياضيًا يجب أن يعمل بشكل طبيعي ويعيد متجهًا ثلاثي الأبعاد ،
عندما يتم تحديد المنتج العام a*b بالتعاقد
الفهرس الأخير للحد الأول والفهرس الأول من المصطلح الثاني.

في الوقت الحالي ، يكون توقيع الأسلوب لمنتج Vector-Matrix هو:
(*)(A::AbstractVector, B::AbstractMatrix) = reshape(A,length(A),1)*B
ويتم استخدام هذه الطريقة في حالة v*v' وليس لحالة v*mx .
(شكرا andreasnoack للإشارة إلى هذا.)
من الواضح أنه لا يمكن استخدام طريقة واحدة لكليهما.

يبدو أن جوليا تكافح مع بعض الاختراعات الشبيهة بماتلاب.
لكن في Matlab لا توجد متجهات 1-d ، فقط مصفوفات 1xn و nx1 ،
الكثير من الأشياء الطبيعية يمكن أن تكون مشكلة هنا.
تمتلك جوليا متجهات حقيقية أحادية الأبعاد والتي يجب أن تكون ميزة كبيرة.
سيكون من الجيد الوصول إلى حالة متسقة حقًا خاصة بها.

فورتران هو مثال أفضل وأكثر اتساقًا يجب اتباعه في هذه الحالة.
تم تحديد العملية transpose للمصفوفات في Fortran فقط ،
إن إنشاء مصفوفة 1xn من متجه حقيقي 1-d ليس ببساطة تبديلًا.
للحصول على matmul انظر مقتطف من كتاب Metcalf المقتبس في # 18056.

أعتقد أن معظم نقاطalanedelman الأصلية كانت صحيحة.

إذن إليك اقتراح من شأنه أن يعالج ببساطة بعض المشكلات الحالية ،
مع احترام الوضع الحالي قدر الإمكان:

  • احتفظ ب v' كما هو الحال لإنشاء مصفوفة 1xn من متجه حقيقي 1-d v
  • ستكون وظائف rowmx و colmx أفضل ، لكن v' منتشر جدًا لتغييره
  • لدينا بالفعل الدالة vec لإنشاء متجه حقيقي ثلاثي الأبعاد
  • على الرغم من أن معكوس v' ليس v'' ولكن vec(v') ، يمكننا التعايش معه
  • يجب أن يتعاقد المنتج a*b دائمًا مع المؤشر الأخير a والفهرس الأول b
  • لا يجب استخدام عامل التشغيل * سواء للمنتجات الداخلية أو الخارجية
  • بالنسبة للمنتجات الداخلية ، لدينا بالفعل وظيفة dot
  • بالنسبة للمنتجات الخارجية ، يجب التخلص من استخدام * (_أي. __ بناء الجملة v*v' )
  • بالنسبة للمنتجات الخارجية ، يجب استخدام وظيفة جديدة
  • يمكن أن يحافظ عامل infix المقابل على ضوء بناء الجملة

سيكون فقدان [بناء جملة رياضي موجز] للمنتجات الخارجية أمرًا مؤسفًا. أفضل التخلي عن حصيرة vec * شخصيًا.

هل يمكن لـ PernutedDimsArray الموجودة بالفعل التعامل مع الحالة التي يكون فيها للأصل والمشاهدة أعداد مختلفة من الأبعاد؟ إذا كان الأمر كذلك ، فربما يكون هذا قابلاً للاستخدام بالفعل كنوع غلاف غير مترافق حتى بالنسبة للآباء المتجهين.

لم أجد PermutedDimsArray في الوثائق.

لكني أشعر أنه بدلاً من اختراع المزيد من أنواع البيانات ،
يجب فصل الأنواع الثلاثة فقط من منتجات المصفوفات بوضوح.
المنتجات الداخلية منفصلة بالفعل.
نحن بحاجة فقط لفصل المنتجات العادية والخارجية.
لن تضيع المنتجات الخارجية ، بل سيتغير تركيبها فقط.
يُرجى اعتبار حالة v*mx مجرد عرض لمشكلة أعمق.

بصرف النظر عن "مشكلة الطرق المفقودة" ، فلن يكون من النوع الذي يجب أن تقلق بشأنه ، بل سيكون أحد تفاصيل التنفيذ أن .' يُرجع نوع غلاف كسول (و ' نسخة مترافقة منه). وإلا لا أعتقد أنه يمكننا استخدام كل من vec*mat و vec*vec' باستخدام نفس عامل التشغيل * . إذا رأيت vec*mat في الورقة ، فسيبدو هذا خطأ بالنسبة لي ، لكني أرى vec*vec' كثيرًا.

بالتفكير في الأمر أكثر ، أعتقد أن PermutedDimsArray لا ينقل عناصره بشكل متكرر لمصفوفات من المصفوفات ، لذلك فهو ليس مناسبًا تمامًا كنوع الغلاف لاستخدامه هنا.

البديل الآخر هو عدم السماح بنقل المتجهات تمامًا. أعتقد أن المناقشة هنا كانت شاملة للغاية بالفعل ، ونحن ننتظر فقط تنفيذًا شاملاً لأحد الخيارين أو كلاهما لتقييم الشكل الذي سيبدو عليه التأثير.

أنا أقدر أنك كنت مستعدًا للمناقشة بينما اقترب هذا الموضوع من نهايته.

بينما قد يبدو v*mx غريبًا بالنسبة لك ، إلا أنه يُستخدم بكثرة في الشفرة البلورية.
يتم التعامل معها جيدًا أيضًا بواسطة Fortran matmul . (انظر # 18056)

العودة إلى المنتج u*v' .
عندما يكون u و v كلاهما مصفوفتان nx1 ، فهذا منتج مصفوفة عادي ،
التي تبين أنها تقدم نفس نتيجة المنتج الخارجي.
لكن هذا مجرد استخدام حاصل ضرب المصفوفة لمحاكاة الضرب الخارجي.
هذا سلس في عالم ماتلاب حيث كل شيء هو مصفوفة.

في جوليا لدينا نواقل حقيقية أحادية البعد أقرب إلى عالم فورتران.
في Julia ، يمثل المتجه المنقول v' مشكلة بالفعل ،
خيار فورتران هو منعه ، كما اقترحه آخرون لجوليا.

ليس لدى Fortran وظيفة جوهرية للمنتجات الخارجية.
جوليا تحوّل بسهولة v' إلى مصفوفة 1xn ،
وينفذ العملية * على متجه 1-d ومصفوفة 1xn.
نظرًا للإرسال المتعدد ، يمكنه القيام بذلك ،
ولكن هنا * بالتأكيد لم يعد منتج مصفوفة بعد الآن.

النقطة التي يتصرف فيها فورتران وجوليا بالمثل
هو أن كلاهما يستخدم وظيفة dot منفصلة للمنتجات الداخلية.
كان هناك نقاش حول تجميع dot أيضًا في عامل التشغيل * ،
لكن لحسن الحظ لم يحدث ذلك.

لذلك علينا التعامل مع المنتجات الثلاثة للجبر الخطي:
منتج المصفوفة العادي والمنتج الداخلي والمنتج الخارجي.
في الوقت الحاضر ، عامل التشغيل * عبارة عن صيغة مجمعة للمنتجات العادية والخارجية.
كل ما اقترحته هو فصلهما والوصول إلى حالة أكثر اتساقًا.

(أوه ، لقد تركت المنتج المتقاطع ، لكنه منفصل جيدًا بالفعل)

لا أعتقد أن المنتج الداخلي ، والمنتجات الخارجية ، ومضاعفة المصفوفة هي طريقة رياضية سليمة لتقسيم / تصنيف المنتجات. ما يلي هو بالتأكيد تكرار للأشياء التي ذكرها العديد من الأشخاص أعلاه ، ولكن بالنظر إلى طول هذا الموضوع ، آمل أن يكون من الجيد تضمين ملخص بين الحين والآخر. هذا هو ملخصي الشخصي ، وأنا بالتأكيد لست خبيرًا ، لذا صحح لي أين أكون مخطئًا.

في بيئة الجبر الخطي المجرد، واللاعبين الرئيسيين هم ناقلات v (الذين يعيشون في مساحة ناقلات V )، والخرائط الخطية (يتصرف على مساحة ناقلات واحدة V ورسم الخرائط ل ربما مساحة مختلفة W ) وتكوين هذه الخرائط أو الأشكال الخطية أو المتجهات (تعيش في مساحة مزدوجة V* وتعيين من V إلى الحجميات) ، المنتجات الداخلية (من V × V للكميات) ، منتجات موتر بين المتجهات (أي kron ). المنتج الخارجي الذي أفضل أن أفكر فيه على أنه منتج موتر بين متجه و covector.

من الأمور ذات الأهمية الخاصة لهذه المشكلة التشابه بين المتجهات والأشكال الخطية إذا تم تعريف منتج داخلي ، أي لكل f متجهات تعيين الحجم v إلى الحجميات ، يوجد w مثل f(v) = dot(w,v) لأي v . ومع ذلك ، يمكن أن توجد المتجهات دون الرجوع إلى المنتجات الداخلية (مثل التدرج اللوني لوظيفة متعددة الأبعاد).

لتمثيل كل هذه الكائنات على جهاز كمبيوتر ، عادة ما تختار أساسًا ويمكنك بعد ذلك تمثيل معظم هذه الأشياء باستخدام جبر المصفوفة. أي أنك تحتاج فقط إلى ضرب المصفوفة والتبديل إذا كنت على استعداد للتحلي بالمرونة مع أبعاد مفردة لاحقة (المتجهات مثل المصفوفات nx1 ، والقياسات كمصفوفات 1x1 ، إلخ). كان هذا هو رأي Matlab ، بالإضافة إلى طريقة كتابة العديد من الكتب والأوراق ، خاصة في الجبر الخطي العددي.

في هذه الحالة ، فإن التماثل المذكور أعلاه من المتجهات إلى المتجهات (بافتراض ضمنيًا المنتج الداخلي الإقليدي) يتوافق مع أخذ التحويل (اقتران Hermitian في الحالة المعقدة) لتمثيل المصفوفة لمتجه. ومع ذلك ، بالمعنى المجرد ، لا توجد فكرة عن تبديل المتجه ، وهذا على الأرجح سبب عدم تعريفه في Fortran ، كما ذكر GaborOszlanyi . يتم تحديد تبديل الخريطة الخطية فقط (هذا لا يتطلب منتجًا داخليًا ويتوافق تمثيل المصفوفة الخاص بها مع المصفوفة المنقولة حتى في الحالة المعقدة) ، بالإضافة إلى معايرة الخريطة الخطية (هذا يتطلب منتجًا داخليًا) .

نظرًا لأهمية ثبات النوع في كود جوليا ، فإن نهج ماتلاب "المصفوفات الوحيدة" (مع أبعاد مفردة مفردة مرنة) لا يعمل بشكل جيد. لكننا لا نريد أيضًا الانتقال إلى الإعداد المجرد تمامًا والاستمرار في العمل في الإعداد النموذجي (المنتجات الداخلية الإقليدية ، رسم الخرائط التافهة من المتجهات إلى المتجهات ، ...). نظرًا لأننا في النهاية نكتب رمزًا ونريد استخدام أحرف ASCII ، فنحن بحاجة إلى الضغط قدر الإمكان من الرموز * ، ' و .' . لحسن الحظ ، هذا هو المكان الذي يكون فيه الإرسال المتعدد مفيدًا ويؤدي إلى المقترحات المختلفة المذكورة أعلاه. لقد وضعت جدولًا حول هذا الموضوع ، أي كيف يمكن ترجمة عمليات الجبر الخطية المجردة إلى طرق جوليا محددة (وليس وظائف).

كملاحظة أخيرة لـ GaborOszlanyi ، ما زلت لا أجد مكانًا لـ v*A في كل هذا. قد يكون هذا قياسيًا في الحقول حيث يتم الإشارة إلى المتجهات بشكل افتراضي كمصفوفات صف ، لكنني شخصياً أعتقد أن هذا اختيار غريب. إذا كانت الخرائط الخطية f و g تعمل كـ f(v) = v*A و g(v) = v*B ، فهذا يعني أن g(f(v)) = (g ◦ f)(v) = v*A*B وهو أمر غريب منذ أمر التركيب متبادل. إن وجد ، يمكنني تفسير هذا على أنه منتج داخلي غير مكتمل ، كما هو الحال في الصف الثاني إلى الأخير من الجدول المرتبط.

ملخصك عميق ومقنع.
شكرا لشرح ذلك بشكل جيد.

لدي سؤالان متبقيان فقط:

  • ما هي التغييرات التي ستحدث بالفعل في جوليا نتيجة لهذه المناقشة الشاملة؟
  • لماذا نفذت Fortran v*mx في matmul ؟

هناك مشكلتان كشفتهما هذه المشكلة:

أ. علماء الرياضيات التطبيقية ملتزمون بتدوين Householder ، والذي يستخدم ضمنيًا شكلين طبيعيين:

  1. لا يمكن تمييز متجه الطول N عن مصفوفة العمود Nx1 ، نظرًا لأن مصفوفات Nx1 تشكل مساحة متجه. ("عمود"، ▯)
  2. لا يمكن تمييز المصفوفة 1 × 1 عن العدد القياسي ، حيث يمكن تعريف المصفوفات 1 × 1 بجميع الخصائص الجبرية للعدادات. ("تحجيم"، ■)

تكمن المشكلة في أنه لا يمكن التعبير عن أي من هذه التماثلات بشكل طبيعي في أنواع جوليا وكلاهما يتضمن عمليات فحص وقت التشغيل لشكل الصفيف. يمكن اعتبار قواعد البعد الفردي اللاحقة في MATLAB بمثابة تنفيذ لكل من هذه التماثلات.

يمكن تعريف المصفوفة ثنائية الأبعاد بشكل متكرر كمصفوفة من المصفوفات. ومع ذلك ، فإن المصفوفة هي صف من الأعمدة أو عمود من الصفوف ، ولكنها ليست صف صفوف أو عمود من الأعمدة. حقيقة أن المصفوفات لا يمكن تعريفها بشكل متكرر تسلط الضوء على بنية الموتر المختلفة للمصفوفات والمصفوفات ذات الأبعاد n. بشكل صحيح ، المصفوفات متعددة الأبعاد هي نوع محدود جدًا من الموتر وتفتقر إلى الآلية الكاملة اللازمة لتنفيذ هذا الأخير. نظرًا لأن الانكماش بالمعنى الدقيق للكلمة هو عملية على إقران فضاء متجه مع ثنائيته ، فمن الخطأ أن نتحدث عن التعاقد مع مؤشرات المصفوفات متعددة الأبعاد ، والتي لا تستدعي أبدًا مفهوم الفضاء المتجه المزدوج. معظم الناس لا يريدون الآلات الكاملة ، الأمر الذي يتطلب القلق بشأن الفهارس المشتركة / المتناقضة أو الفهارس الأعلى / السفلي مع طبيعة الصف / العمود. بدلاً من ذلك ، يرغب معظم الناس في أن تكون المصفوفات عبارة عن حاويات قديمة بسيطة ، ومخالفة تمامًا لجميع الأبعاد ، _ باستثناء البعدين_ ، حيث يرغب معظم المستخدمين في التفكير في المصفوفات ثنائية الأبعاد على أنها تحتوي على جبر المصفوفات (التي تكون موترات أسفل لأعلى) ، وليس أبدًا موتر لأسفل أو لأعلى أو لأعلى لأسفل. بمعنى آخر ، المصفوفات ثنائية الأبعاد تريد أن تكون ذات غلاف خاص.


لا يزال بإمكاني إقناعي بخلاف ذلك ، ولكن هذا هو اقتراحي الحالي المكون من 3 أجزاء:

أ) عدم السماح بنقل المتجهات تمامًا ، مما يتطلب من المستخدمين تحويل المتجهات صراحةً إلى مصفوفات أعمدة من أجل كتابة تعبيرات على غرار Householder مثل u'v ، u*v' ، u'*A*v و u'*A*v/u'v . يمكن بناء كل هذه التعبيرات من ثلاثة عوامل أولية أحادية وثنائية: matmul ، ومبدل المصفوفة ، وقسمة المصفوفة. في المقابل ، إذا كان u و v متجهين حقيقيين ، فلا يمكن إذن إعطاء تعبيرات فرعية مثل u' أو u'*A بمعنى بدون تقديم TransposedVector خاص

يتمثل أحد القيود في (أ) في أن جميع التعبيرات ذات النمط المنزلي ستولد مصفوفات 1 × 1 بدلاً من الحجميات الحقيقية (والتي لا تزال تمثل تحسنًا كبيرًا على u'v إرجاع متجه واحد) ، لذلك تعبير مثل (u'*v)*w ما زال لا يعمل. من الناحية العملية ، لا أعتقد أن تعبيرات "المنتج الثلاثي" مثل هذه تحدث كثيرًا.

ب) إدخال ترميز بديل للعمليات المماثلة على المتجهات ، مثل

  • u ⋅ v = scalarize(columnify(u)'*columnify(v)) للمنتج الداخلي (نقطة)
  • u ⊗ v = columnify(u)*columnify(v)' لمنتج (Kronecker) الخارجي
  • A(u, v) = scalarize(columnify(u)'*A*columnify(v)) ، رمز قديم للصيغة ثنائية الخطوط
  • A(u) = A(u, u) للصيغة التربيعية

تختلف التعبيرات الموجودة في (ب) عن نظيراتها في (أ) عن طريق التحجيم التلقائي للتعبيرات الخاصة بالمنتج الداخلي والأشكال الثنائية / التربيعية ، وبالتالي تجنب تشكيل مصفوفات 1 × 1.

ج) جعل مصفوفات 1 × 1 قابلة للتحويل إلى أحجام حقيقية ، بحيث يكون الرمز مثل

M = Array(Int, 1, 1, 1)
a::Int = M

يمكن أن تعمل. كل ما هو مطلوب هو إجراء فحص وقت التشغيل لحجم الصفيف بشيء مثل:

function convert{T}(::Type{T}, A::Array{T,N})
    if length(A) == 1
        return A[1]
    else
        error()
    end
end

هذا الاقتراح هو تعديل صغير لما اقترحه فولكمار بورنمان قبل حوالي عامين. عندما جربناها ، لم تكن تكلفة فحص وقت التشغيل كبيرة جدًا ، ولن يتم استدعاؤها إلا عند التعيين القسري من النوع (وهو في الواقع مكالمة مقنعة convert ) ، وليس التعيين العام.

jiahao ، قابلية قراءة هذا

jiahao ، يمكنني بالتأكيد أن أتفق مع معظم / كل ذلك ، على الرغم من أنني أود تحدي نقطتين:

دون تقديم نوع خاص من TransposedVector ، والذي كنتيجة منطقية يتطلب مصفوفات متعددة الأبعاد للقلق بشأن مؤشرات الصعود / الهبوط في هيكل الموتر الخاص بهم ، والذي يبدو أنه ثمن باهظ للغاية لدفعه.

يبدو هذا مجرد نتيجة منطقية بالنسبة لي إذا كنت تريد أن تجعل TransposedVector نوعًا فرعيًا من التسلسل الهرمي AbstractArray ، والذي افترضت أنه لم يكن الخطة (على عكس بعض LazyTranspose النوع الذي حقًا هو مجرد نوع آخر من AbstractMatrix ).

u ⊗ v لمنتج (Kronecker) الخارجي

إذا كان الهدف هو عدم الاعتماد على التماثل الضمني وفصل عمليات المصفوفة بشكل واضح عن العمليات المتجهة والمزيد من المنتجات المجردة ، فأنا أعتقد أن هذا فشل للسبب التالي (لست متأكدًا من الاتفاق العالمي على التعاريف الرياضية التالية):

  • منتج Kronecker A ⊗ B هو عملية محددة في المصفوفات ، وليس في المتجهات.
  • وبالتالي ، بدلاً من قراءة u ⊗ v كمنتج موتر لمتجهين ، سيؤدي ذلك إلى ظهور موتر ثنائي الأبعاد من النوع السفلي. الطريقة الوحيدة للحصول على "مصفوفة" مناسبة هي أخذ حاصل الضرب الموتر لمتجه مع covector. ولكن نظرًا لأنك تريد تجنب إدخال هذه الكائنات ، فيبدو أنه من المستحيل الحصول على نتيجة هذه العملية قبل تصنيف المتجهين المعنيين.
  • الاسم الثالث لـ u ⊗ v هو المنتج الخارجي الذي عادة ما يتم تعريفه بطريقة قذرة ، ولست متأكدًا مما إذا كان هناك تعريف صارم مقبول من حيث الأعلى والأسفل. تشير بعض المصادر إلى أنه مكافئ لمنتج موتر لمتجهين ، ومن هنا جاءت النقطة السابقة. إذا قبلت بدلاً من ذلك تعريفًا حيث يعني أيضًا "المنتج الخارجي" ضمنيًا تعيين المتجه الثاني إلى covector للحصول على موتر سفلي ، فلا توجد مشكلة.

بدلاً من ذلك ، يرغب معظم الأشخاص في أن تكون المصفوفات عبارة عن حاويات قديمة بسيطة ، ومخالفة تمامًا لجميع الأبعاد ، باستثناء بعدين ،

هل نظرنا في الخيار النووي؟ نبدأ الجبر الخطي من جديد ، ونزيل تمامًا أنماط الجبر لـ AbstractVector و AbstractMatrix واستبدلها بـ:

abstract AbstractVector{T} <: AbstractArray{T,1}
abstract AbstractMatrix{T} <: AbstractArray{T,2}

# and we could introduce:
abstract AbstractCoVector{T} <: AbstractArray{T,1}

أنا أفهم أن هناك الكثير من التداعيات ، لكن قد ينتهي بنا الأمر بفصل واضح بين مصفوفات التخزين متعددة الأبعاد والجبر الخطي. نحن لا نلتزم بتنفيذ جبر الموتر متعدد الأبعاد الكامل ، ومساحات المتجهات المزدوجة ، وما إلى ذلك. علينا فقط تنفيذ البتات التي يريدها كثير من الناس: المتجهات ، والمصفوفات والمصفوفات. نحصل على المنتجات الداخلية ، والمنتجات الخارجية ، ومنتجات مصفوفة covector ، ومنتجات ناقلات المصفوفة ومنتجات مصفوفة المصفوفة. تم تعريف التحويل على كل ما سبق. يمكن أن يكون لدينا تطبيقات AbstractMatrix والتي تستخدم بالفعل مصفوفة 1D من المصفوفات 1D (وليس التنفيذ الافتراضي بالطبع). لا يتعين علينا استخدام تدوين Householder (والذي يعد IMHO أحد نقاط ضعف MATLABs!) ولكن لا يزال بإمكاننا الحصول على جميع وسائل الراحة في الجبر الخطي.

أنا متوترة بعض الشيء لاقتراح هذا ، لكنني أعتقد أنه سيسمح لجوليا بتقليد النموذج "الصحيح" لما يتعلمه معظم الناس في الجبر الخطي على مستوى السنة الأولى بالجامعة ، دون الحاجة إلى الرجوع إلى اصطلاحات Householder. قد يؤدي التمييز الواضح أيضًا إلى تسهيل نقل Base.LinAlg إلى حزمة "مكتبة قياسية" ، والتي أعتقد أنها هدف طويل المدى لجوليا؟ كما أنه يتماشى جيدًا مع فكرة أنه سيكون هناك شيء جديد يشبه القائمة 1D يمكن تغيير حجمه والذي سيأتي مع التغييرات الجديدة Buffer والتنفيذ الأصلي لـ Array ، لذلك نوع "القائمة" العام يمكن أن تحل محل Vector للعديد من الأجزاء الأساسية لـ Julia ودعنا نحمّل الحزمة LinAlg متأخرًا جدًا مع تحديد Array و "list" مبكرًا.

توجد العديد من الخوارزميات التي تم "إهمالها" بالفعل ، والتي يتم التعبير عنها من خلال مصفوفات فورتران وليس من حيث الجبر الخطي المناسب. تحتاج جوليا إلى أن تكون قادرة على تنفيذ هذه الخوارزميات دون أن يضطر الناس إلى إعادة اكتشاف (أو إكراه) بنية الجبر الخطي فوق المصفوفات متعددة الأبعاد.

في مجال عملي ، من المحتمل أن يكون الجبر الخطي المناسب الذي يرسم الموترات والمؤشرات المشتركة / المتناقضة وما إلى ذلك على مصفوفات فورتران هو الأفضل. لإنجاز هذا العمل - وعدم إرباك الناس - سأترك المصطلحات "متجه" و "مصفوفة" و "مصفوفة" بمفردها ، مع الاحتفاظ بها في المستوى المنخفض ، واستخدام مصطلحات أخرى (مربي الحيوانات؟) لكل شيء أعلى مستوى . يجب أن يجرد المستوى الأعلى المذكور أيضًا خيارات التخزين ، إما عبر أنواع مجردة أو عبر تحديد معلمات. ربما تكون البادئة LA هي الطريقة المثلى للتعبير عن هذا:

LA.Vector
LA.CoVector
LA.Tensor{... describing co/contravariance of indices ...}

يتم بعد ذلك استخدام المتجهات والمصفوفات للتخزين البحت. في المستوى المنخفض ، تتم إدارة التحويل يدويًا (كما هو الحال في BLAS) ؛ على المستوى العالي ، يتم التعامل معها تلقائيًا.

هذا قريب من اقتراح andyferris ، إلا أنه لا يكسر التوافق مع الإصدارات السابقة ولا يكسر توقعات Matlab / Fortran / numpy convert.

eschnett أعتقد في وقت سابق في هذا الموضوع أنه تقرر ترك الجبر متعدد

بالنسبة لترك Matrix و Vector بمفردهما - حسنًا ، ربما تكون التعريفات الحالية مثالية ، أو ربما يكون هناك شيء أفضل يمكننا فعله للأشخاص الذين يرغبون في مضاعفة المصفوفات ونقل المتجهات ، باستخدام الرياضيات القياسية الرموز. أعتقد أنه قد يضيف منحنى تعليميًا صغيرًا للمستخدمين الجدد ، على الرغم من أنني كنت آمل إذا كان النظام واضحًا وبليغًا و _تحسينًا _ على اللغات الأخرى ، فيجب أن يكون التعلم سهلاً.

لاحظ أن مساحة المتجه المعقدة العامة غير الإقليدية V بها 4 مسافات مرتبطة: V ، conj(V) ، dual(V) و conj(dual(V)) . لذا فإن الموتر العام يحتوي على 4 أنواع من المؤشرات (يُشار إليها عادةً على أنها أعلى أو أسفل ، أو ممنوعة أو غير محظورة) في مساحة إقليدية معقدة (مثل ميكانيكا الكم) ، dual(V) ≡ conj(V) و conj(dual(V)) = V . في مساحة حقيقية (غير إقليدية) (مثل النسبية العامة) ، V ≡ conj(V) . في كلتا الحالتين الأخيرتين ، هناك حاجة فقط للمؤشرات الصعودية والهبوطية.

في الفضاء الإقليدي الحقيقي (معظم التطبيقات؟) ، كلهم ​​متساوون ، ومصفوفات جوليا العادية تكفي لتمثيل الموترات. لذلك على الأقل للأرقام الحقيقية ، تسمح العمليتان التاليتان ببناء جبر موتر كامل ومتسق.

  • عقد / منتج داخلي ، والذي يمكن تعميمه على مصفوفات عشوائية من المرتبة N باستخدام القاعدة: عقد الفهرس الأخير للمصفوفة الأولى مع الفهرس الأول من الثاني (أو numpy's dot اصطلاح A ∙ B مصفوفة من الرتبة M+N-2 إذا كان A و B قد حصل على المرتبة M و المرتبة N .
  • منتج tensor : A ⊗ B يُرجع مصفوفة من المرتبة N+M

متخصص وصولاً إلى المتجهات v ، w والمصفوفات A ، B ، وهذا يسمح لكتابة كل ما يلي:

  • المتجه الداخلي للمنتج v ∙ w -> يعرض بشكل استثنائي عددًا قياسيًا بدلاً من مصفوفة من الرتبة 0
  • ضرب متجه المصفوفة A ∙ v
  • ضرب مصفوفة المصفوفة A ∙ B
  • موتر / منتج خارجي v ⊗ w
  • covector (=== vector) ضرب المصفوفة v ∙ A

على الرغم من أن المرء قد يرغب في استخدام * مقابل ، فإن المشكلة تكمن في أن التعريف أعلاه لـ ليس ارتباطًا: (A ∙ v) ∙ w ≠ A ∙ (v ∙ w) لأن الأخير لن يكون كذلك يمكن تعريف.

ولكن مرة أخرى ، هذا فقط إذا كنت على استعداد لتجاهل المصفوفات المعقدة.

بالنسبة إلى التنفيذ العام تمامًا للتنسورات ، فقد بدأت (وتخليت) عن هذا منذ وقت طويل ، قبل أن يكون هناك مجموعات مكدس مخصصة ، ووظائف مُنشأة وكل هذه الأشياء الجيدة الأخرى التي من المحتمل أن تجعلها أكثر جدوى اليوم.

نهج مثير للاهتمام ،Jutho. يبدو بديهيًا بدرجة كافية. أظن أن هذه التعريفات يمكن إضافتها بغض النظر عما نفعله بـ * و ' ، وأنا أؤيد ذلك.

ولكن مرة أخرى ، هذا فقط إذا كنت على استعداد لتجاهل المصفوفات المعقدة.

تم إدراج conj() يدويًا لإصلاح ذلك. ولا أعتقد أن جوليا تريد تجاهل المصفوفات المعقدة ، أليس كذلك؟

لقد لاحظت أمرين آخرين حول استخدام AbstractMatrix كنوع فرعي خاص بدلاً من اسم مستعار من النوع:

matrix[:,i] -> AbstractVector{T}
matrix[i,:] -> AbstractCoVector{T}
array_2d[:,i] -> AbstractArray{T,1}
array_2d[i,:] -> AbstractArray{T,1}

هذا رائع جدًا - يمكننا الحصول على متجهات العمود والصف من فهرسة مصفوفة. إذا كانت مجرد حاوية تخزين ثنائية الأبعاد ، فسنحصل على مجموعة تخزين 1D. يجب أن تغطي جميع حالات الاستخدام! ولا يزال يخضع لواجهة AbstractArray مع قواعد APL للتقسيم نظرًا لأن كلا من AbstractVector{T} <: AbstractArray{T,1} و AbstractCoVector{T} <: AbstractArray{T,1} .

حقيقة واحدة "مثيرة للاهتمام" هي

array_3d[:,:,i] -> AbstractArray{T,2}
matrix(array_3d[:,:,i]) -> `AbstractMatrix {T}

لذلك يجب عليك لفها يدويًا كمصفوفة إذا كنت تريد القيام بضرب المصفوفة بالنتيجة. هل هذا زائد أم ناقص ، لا أعرف؟ ولكن يبدو أن هذا أحد المضاعفات المحتملة ولمسات لما ذكره eschnett حول تسهيل الأمر على المستخدمين من اللغات الأخرى التي تدمج التخزين والجبر الخطي.

قد يكون هذا سؤالًا سخيفًا ، لكن jutho ذكر سابقًا أن رمز الكتابة كان مقيدًا بواسطة ASCII. لماذا في العالم ما زلنا نقتصر على مجموعة من الشخصيات المكونة من 7 بتات تم تطويرها في عام 1963 ، وآخر تحديث لها في عام 1986 (قبل 30 عامًا)؟ كان هذا حقبة عندما كان 640 كيلو بايت الشهير هو الحد الأقصى لذاكرة الوصول العشوائي المتاحة على جهاز الكمبيوتر في عام 1981. في سوق الكمبيوتر اليوم ، لدينا الآن معالجات 64 بت مع 32 جيجابايت من ذاكرة الوصول العشوائي معروضة للبيع (50000 ضعف الحد الأقصى السابق) ونحن لا نقترب من أي مكان. الحد النظري لمعالجات 64 بت. إذن ، لماذا ما زلنا نقتصر على مجموعة الشخصيات التي تم تطويرها منذ 40 عامًا؟

يمكننا استخدام يونيكود ، فقط ضع في اعتبارك أنه لسوء الحظ ، لم ينمو حجم لوحة المفاتيح بعامل مماثل في الأربعين عامًا الماضية ولا عدد أصابع الشخص العادي (في ما يزيد عن 10000 عام الماضية).

يجب وضع IMHO و ASCII للراحة. لوحة مفاتيح رياضية خاصة لبرمجة الرموز الرياضية السريعة هي في الواقع فكرة جيدة! هل هناك سبب وجيه لعدم استخدام المزيد من الرموز التي تأتي مع UTF؟ هل يمكنك تبرير آلام محاولة استخلاص كل ما يمكنك الخروج به من ASCII؟

@ esd100 : من فضلك لا تستخدم قضية GitHub هذه في مثل هذه المناقشات التخمينية للغاية.

تضمين التغريدة لست متأكدًا مما تعنيه ب "المضاربة". هل أنت متأكد من أن هذه هي الكلمة التي قصدت استخدامها؟ اعتقدت أن استخدام ASCII مقابل شيء آخر كان ذا صلة بالمناقشة ، حيث يبدو أن اللغة والمشغلين والوظائف مرتبطة بالرموز المستخدمة. أنا لست خبيرًا بأي وسيلة ، لكن يبدو أنها مشكلة تتعلق بالمناقشة ، أو على الأقل توضيحها ، فيما يتعلق بالوظيفة التي تتم معالجتها.

أعني هل هناك أي سبب يمنعنا من تحديد اللغة بالطريقة التي نريدها (مع وضع الأهداف الأساسية في الاعتبار: سهولة الاستخدام والسرعة)؟ ألن يجعل استخدام الرموز / الكلمات الخاصة اللغة أكثر ثراءً وجمالاً؟

@ esd100 يرجى ملاحظة أن أحدث تعليق على سبيل المثال Jutho (باستخدام رمزين يونيكود) تم استقباله بشكل جيد و yuyichao يوافق على أنه يمكننا استخدام يونيكود. هناك مقترحات أخرى حول إدخال المزيد من عوامل التشغيل أحادية الرمز فقط (مثل رمز الإنشاء لتكوين الوظائف ، # 17184). لا أعتقد أن الناس يختلفون معك (على الرغم من أن لدينا اعتبارات عملية يجب وضعها في الاعتبار) ولكن إذا كانت لديك اقتراحات _محددة_ حول الموضوع ، فيرجى إخبارنا بذلك.

أنا مرتبك قليلاً بهذا السلوك الجديد في v0.5 والذي أعتقد أنه نشأ عن هذه المناقشة:

julia> [ x for x in 1:4 ]' # this is fine
1×4 Array{Int64,2}:
 1  2  3  4

julia> [ Symbol(x) for x in 1:4 ]' # bit this isn't? What is special about symbols?
WARNING: the no-op `transpose` fallback is deprecated, and no more specific
`transpose` method for Symbol exists. Consider `permutedims(x, [2, 1])` or writing
a specific `transpose(x::Symbol)` method if appropriate.

كيف أجعل متجه صف (غير رقمي) من قائمة الفهم؟ يجب أن يكون ناقل صف. (هل سيكون هذا أفضل كقضية منفصلة أم تتم مناقشته في مكان آخر؟ لست متأكدًا من مكان النشر ...)

يمكنك استخدام إعادة الشكل: reshape(v, 1, length(v)) . ربما يجب ذكر ذلك أيضًا في تحذير الإيقاف؟ أعتقد أن الفكرة هي أن التحويل هو عملية رياضية وبالتالي يجب تعريفه فقط للمتجهات / المصفوفات الرياضية.

تم ذكره في depwarn: permutedims(x, [2, 1]) .

permutedims لا يعمل مع المتجهات. راجع هذا الإصدار الجديد تمامًا: # 18320

أعتقد أن الفكرة هي أن التحويل هو عملية رياضية وبالتالي يجب تعريفه فقط للمتجهات / المصفوفات الرياضية.

هذا لا معنى لي بالنسبة لي. هل هذا للمناقشة؟ أنا أفضل حقًا التحويل للعمل على المصفوفات غير الرقمية ما لم يكن هناك مبرر جيد حقًا.

أعتقد أن الفكرة هي أن التحويل هو عملية رياضية وبالتالي يجب تعريفه فقط للمتجهات / المصفوفات الرياضية.

هذا لا معنى لي بالنسبة لي. هل هذا للمناقشة؟ أنا أفضل حقًا التحويل للعمل على المصفوفات غير الرقمية ما لم يكن هناك مبرر جيد حقًا.

أعتقد أنه من المعقد نسبيًا أن ترضي ما تريد _ و_ يكون منطقيًا للرياضيات. بالمعنى الرياضي ، غالبًا ما يتم تعريف التبديل عن طريق تبديل مسافات المتجهات ومسافاتها المزدوجة لمتجه أو مصفوفة (حسنًا ، هناك بعض التعقيد مع تبديل مقابل تبديل مقترن أيضًا). بالنسبة لمصفوفة M للأرقام العادية ، لدينا المنقول كـ permutedims(M, (2,1)) ، ولكن بشكل عام يمكنك تحديد مصفوفة "كتلة" من حيث المصفوفات الفرعية مثل هذا:

M = [A B;
     C D]

حيث A إلخ هي المصفوفات نفسها. ما أفهمه هو أن جوليا تحب ذلك

M' = [A' C';
      B' D']

وهو ما ستفعله باستخدام رياضيات الورق والقلم وبالتالي فهو "بناء جملة مرغوب فيه".

هذا يعني أن عناصر المصفوفة يجب أن تقبل ' و .' . بالنسبة للأرقام ، يتم تعريفها على أنها اقتران معقد وعدم وجود عمليات على التوالي. IMHO أعتقد أن هذا هو التورية الملاءمة ، لكنه يعمل ، والأهم من ذلك ، أنه يتم تنفيذه بقواعد _simple_ ("التحويل هو تكراري" - على عكس الحاجة إلى فئات BlockMatrix وما إلى ذلك). ولكن تمت إزالة التورية عند التبديل من الأنواع غير الرقمية في 0.5 ، لأنه لا معنى له. ما هو تحويل Symbol ؟

إذا كان لديك _data_ ، وليس أرقامًا ، فإن استخدام permutedims محدد تمامًا في معناه وسلوكه: فهو غير تكراري. قد يوفر لك استخدام تورية رياضية مثل .' بضعة أحرف في الكتابة - لكنه سيجعل _lot_ أكثر منطقية لشخص آخر (قد لا يكون على دراية بالرياضيات أو MATLAB) لقراءة الكود الخاص بك إذا كنت تستخدم reshape و permutedims حسب الضرورة. _بالنسبة لي ، هذه هي النقطة الأكثر أهمية.

IMHO هذه المسألة الطويلة جدًا تدور حول إنشاء واجهة متسقة رياضيًا للجبر الخطي ، ويبدو من الطبيعي بالنسبة لي أن النتيجة ستكون أقل تورية رياضية لمصفوفات البيانات.

شكرا للاستجابة مدروسة. ما زلت أعارض بشدة

ولكن تمت إزالة التورية عند التبديل من الأنواع غير الرقمية في 0.5 ، لأنه لا معنى له. ما هو تبديل الرمز؟

لست متأكدًا من تحديد تحويل Symbol أنه no-op أقل منطقية من تحديد التحويل على رقم حقيقي. أدركت أن "التورية" مناسبة ، ولكن يبدو أن الشيء "المناسب" الذي يجب فعله هو أن يكون التحويل محددًا فقط للمتجهات والمصفوفات وأن يكون لديك transpose(A::Matrix{Complex}) تطبيق conj كجزء من تنفيذه.

قد يوفر لك استخدام تورية رياضية مثل .' بضعة أحرف من الكتابة - ولكن سيكون الأمر أكثر منطقية بالنسبة لشخص آخر (قد لا يكون على دراية بالرياضيات أو MATLAB) لقراءة الكود الخاص بك إذا كنت تستخدم إعادة تشكيل و permutedims حسب الضرورة. بالنسبة لي ، هذه هي النقطة الأكثر أهمية.

أوافق على أنه يجب استخدام .' بحكمة وأن الاتصال الأكثر وضوحًا بـ transpose هو الأفضل غالبًا. أعتقد أن reshape و permutedims يمكن أن يتطلبوا قدرًا غير بسيط من النفقات المعرفية للقراءة والترميز في المقام الأول. كن صريحًا ، وهو أسرع في التحليل:

transpose([ f(x) for x = 1:length(A) ])
reshape([ f(x) for x = 1:length(A) ], 1, length(A))

حتى في الحالات البسيطة مثل هذه ، تحتاج إلى الارتداد من بداية السطر (لقراءة reshape ) وصولاً إلى النهاية (لقراءة length(A) ) لفهم ما يجري. (من المحتمل أن تعود إلى الوسط لفهم سبب وجود length(A) في المقام الأول.)

بالنسبة لي ، المشكلة الأكبر هي أنني إذا كنت جوليا جديدة (مما يعني أنني ربما استخدمت numpy و MATLAB من قبل) وأرى أن هذا يعمل:

[ x for x = 1:10 ]'

سأفترض بطبيعة الحال أن نفس الشيء سيعمل مع مصفوفات من السلاسل والرموز وما إلى ذلك. لن أقرأ من خلال المناقشات الطويلة عبر الإنترنت لمعرفة دلالات .' - أنا سنقوم بتجربة بعض الأشياء والتعميم / الاستدلال بالتجربة السابقة. ربما يساعد وجود رسالة خطأ أفضل هنا.

بشكل عام ، لا أرى كيف يتداخل الاحتفاظ بـ no-op transpos على Symbol وغيرها من المدخلات غير الرقمية مع الإطار الرياضي الجميل المقترح هنا (هدف يستحق!). لكن الحفاظ على عدم التشغيل يبدو غير ضار.

لكن الحفاظ على عدم التشغيل يبدو غير ضار.

لا يمكنك تحديد أي شيء بشكل هادف لـ Any لأن كل شيء هو نوع فرعي من Any . التعريف transpose(x)=x خطأ واضح لأي نوع من المصفوفات ولتجنب بعض الأخطاء الصامتة كان علينا إضافة هذه التعريفات . لذا فهي مقايضة بين ملاءمة السماح للصيغة الغريبة النسبية ' لعملية غير رياضية تمامًا وتجنب الأخطاء الصامتة.

لست متأكدًا من أن تحديد تبديل الرمز على أنه عدم وجود عملية يكون أقل منطقية من تحديد التحويل على رقم حقيقي. أدركت أن "التورية" مناسبة ، ولكن يبدو أن الشيء "المناسب" الذي يجب القيام به هو تغيير موضع محدد فقط للمتجهات والمصفوفات واستخدام transpose(A::Matrix{Complex}) تطبيق conj كجزء من تنفيذه.

لا أعارض تمامًا ، لكننا سنحتاج إلى تنفيذ نوع من BlockMatrix أو أن يكون لدينا طرق خاصة محددة لـ Matrix{M<:Matrix} . لست متأكدًا مما إذا كانت فكرة شائعة أم لا؟ (هذا سؤال جاد لمن يتابعونه لأنه يمكن أن يبسط بعض هذه القضايا ذات الصلة).

كن صريحًا ، وهو أسرع في التحليل:

transpose([ f(x) for x = 1:length(A) ])
reshape([ f(x) for x = 1:length(A) ], 1, length(A))

والثاني، لأنني لا تتصل / مثل تبديل جوليا الحالي من ناقلات (بشكل واضح، _I ناقلات اتخاذ transposes_ جدا _seriously_ :)) إذا كان علي أن أفعل ثاني أود أن أكتب verbosely rowvec = reshape(colvec, (1, n)) ، أو ربما فقط [f(x) for _ = 1:1, x = 1:n] لفرض الفهم لجعل الشكل الصحيح يبدأ به ، أو إذا كنت تحب .' فإن map(f, (1:n).') و f.((1:n).') يعملان حاليًا أيضًا.

إنها مقايضة بين راحة السماح للصيغة الغريبة النسبية "لعملية غير رياضية تمامًا وتجنب الأخطاء الصامتة

إذا كان هذا يتسبب في أخطاء صامتة ومشاكل أخرى ، فأعتقد أنني سأفقد هذه الحجة على الأرجح. (لا أفهم لماذا قد يتسبب ذلك في أخطاء - لكنني أصدقك.) من ناحية أخرى ....

سنحتاج إلى تنفيذ نوع من BlockMatrix أو لدينا طرق خاصة محددة للمصفوفة {M <: Matrix}

قد أكون مخطئًا ، لكنني أعتقد أنك تحتاج فقط إلى القيام بالثاني ، والذي يبدو أنه خيار معقول بالنسبة لي. ولكن هذا بدأ يتخطى راتبي.

[f (x) لـ _ = 1: 1 ، x = 1: n]

لقد نسيت هذا! ربما هذا ما سأفعله في النهاية. بشكل عام ، ما زلت أختلف مع ذوقك بخصوص الكود المقروء ، ولكن مع كل ذوق خاص به! ¯\_(ツ)_/¯

من الواضح أنني آخذ نقل المتجهات على محمل الجد

نعم. اعتقد ذلك. 😉

هذا (https://github.com/JuliaLang/julia/issues/16790) سيجعل استخدام reshape بدلاً من transpose أكثر استساغة قليلاً بالنسبة لي.

قد أكون مخطئًا ، لكنني أعتقد أنك تحتاج فقط إلى القيام بالثاني (تعديل: حدد طرق تبديل خاصة لـ Matrix{M<:Matrix} ) ، والتي تبدو كخيار معقول بالنسبة لي.

لسوء الحظ نعود الآن إلى التمييز بين البيانات والجبر الخطي مرة أخرى. تريد أن تحتوي مصفوفات كتل الجبر الخطي على تبديل تعاودي ولكن مصفوفات بيانات ثنائية الأبعاد عامة لمصفوفات بيانات ثنائية الأبعاد لا تحتوي على تبديل متكرر ... ولكن بينما Matrix{T} و Array{T,2} هما نفس الشيء لا يمكننا ذلك إفعل ذلك.

هذا (# 16790) سيجعل أيضًا استخدام إعادة التشكيل بدلاً من التبديل أكثر قبولا بالنسبة لي.

صحيح!!

تريد أن تحتوي مصفوفات كتل الجبر الخطي على تبديل تكراري ولكن مصفوفات بيانات عامة ثنائية الأبعاد لمصفوفات بيانات ثنائية الأبعاد لا تحتوي على تبديل تكراري

هذا لا يبدو شيئًا أريده بوضوح ... لماذا لا يكون لديك وظيفتان مختلفتان للتعامل مع هذه الأنواع المختلفة من عمليات النقل؟ أعتقد أنني فاتني المذكرة حول وجود تمييز صارم للغاية بين كائنات الجبر الخطي وكائنات البيانات.

تبدو القراءة خلال هذا الموضوع بأكمله مهمة شاقة ، لكن ربما ينبغي علي فعل ذلك قبل التعليق أكثر. لا أريد إضافة ضوضاء غير مدروسة.

أعتقد أنني فاتني المذكرة حول وجود تمييز صارم للغاية بين كائنات الجبر الخطي وكائنات البيانات.

لا يوجد تمييز صارم بين كائنات الجبر الخطي وكائن البيانات.
ليس في التنفيذ الحالي ، ولا في الاستخدام المثالي.

إذا كان الأمر كذلك ، فلن يتم دعم تعديل الحجم (باستخدام push! ) أو حتى قيم كائنات الجبر الخطي (وسيستخدم هؤلاء المستخدمون StaticArrays.jl وما إلى ذلك) ، و broadcast فقط تكون مدعومة على كائنات الجبر الخطي.
ستكون كائنات البيانات قابلة للتعديل والتوسيع وستدعم map ، (و reduce ، و filter ) ولكن ليس broadcast .

لكننا لا نعيش في العالم حيث يفكر الناس إما في ثنائي كائن البيانات ، مقابل كائنات الجبر الخطي.
وهكذا هذا العام 2.5 ، 340 تعليق الموضوع.


إعادة تحويل no-op .
يمكننا أن نضيف ، أعلى التسلسل الهرمي للنوع ، نوع الملخص Scalar و Nonscalar .
Scalars كل الرجوع إلى تبديل عدم الرجوع.
Nonscalars لا يتراجع ، (لكن الآن تراجع إلى تحذير الإيقاف)

الأرقام والأحرف والسلاسل وربما حتى Tuples ستكون Scalar ولن يتم تحديد تبديل no-op. بعض المقاييس ، مثل الأعداد المركبة تفرط في كتابة هذا التعريف للتبديل.

المصفوفات (المصفوفة والمتجهات وغيرها) ستكون أنواعًا فرعية من Nonscalar وسيكون لها تبديل متكرر.

لست متأكدًا مما إذا كنت أحب ذلك أم لا.

تعيد المجموعة الأخيرة من المنشورات صياغة المناقشات حول أنواع تبديل المصفوفة و "العددية" في # 18320 # 13171 # 13157 # 8974.

أنا حقا ترغب في تبديد فكرة أن transpose(x)=x احتياطي عدم المرجع غير مؤذية. في رأيي ، لا يزال من المفترض أن يؤدي الرجوع إلى النتيجة الصحيحة ، ببطء أكثر من الخوارزمية المحسّنة. إنه أمر خطير عندما تحسب الطريقة الاحتياطية الإجابة الخاطئة بصمت ، لأنها تعني أن الرجوع لا يحتوي على دلالات صحيحة: transpose(x) يعني أشياء مختلفة اعتمادًا على نوع x .

لا يعد الخيار البديل no-op غير خاطئ لمصفوفات المصفوفات فحسب ، ولكنه خاطئ أيضًا لجميع الكائنات التي تشبه المصفوفة التي ليست أنواعًا فرعية لـ AbstractMatrix (والتي تعني بواسطة # 987 أنها خزنت إدخالات صريحة ، _ لا_ أن لديهم جبر المصفوفات). إليك مثال طفل ملصق واحد (لدينا عدد قليل جدًا منه):

julia> A = rand(5,5); F = qrfact(A); R = F[:R]; Q = F[:Q] #Q is an example of a matrix-like object
5x5 Base.LinAlg.QRCompactWYQ{Float64,Array{Float64,2}}:
 -0.518817    0.0315127   0.749223    0.410014  -0.0197446
 -0.613422   -0.16763    -0.609716    0.33472   -0.3344   
 -0.0675866   0.686142    0.0724006  -0.302066  -0.654336 
 -0.582362   -0.0570904   0.010695   -0.735632   0.341065 
 -0.104062    0.704881   -0.248103    0.295724   0.585923 

julia> norm(A - Q*R) #Check an identity of the QR factorization
8.576118402884728e-16

julia> norm(Q'A - R) #Q'A is actually an Ac_mul_B in disguise
8.516860792899701e-16

julia> Base.ctranspose(Q::Base.LinAlg.QRCompactWYQ)=Q; #Reintroduce no-op fallback

julia> norm(ctranspose(Q)*A - R) #silently wrong 
4.554067975428161

يوضح هذا المثال أنه لمجرد أن شيئًا ما نوعًا فرعيًا من Any لا يعني أنه يمكنك افتراض أنه عددى وله تبديل no-op. كما يوضح سبب صعوبة حل المشكلة الرئيسية في البروتوكول الاختياري. بالنسبة للعنصر غير المصفوف الذي يشبه المصفوفة Q ، فإن Q' ليس له معنى حقيقي كعملية مصفوفة ولكن له معنى جبري واضح: التعبيرات مثل Q'A محددة جيدًا. الأشخاص الآخرون الذين يعملون مع المصفوفات وليس الجبر الخطي يريدون ببساطة عناصر متغيرة غير متكررة ولا يهتمون بالمصفوفات التي لا تشبه المصفوفات. ومع ذلك ، تظل الحقيقة أنه لا يمكنك الحصول على تهجئة متسقة لكل من الدلالات الجبرية ومبادلة المحور لجميع الأنواع.

ربما أكون كثيفًا ، لكنني كنت أعتقد أن المقارنة ستكون كما يلي:

julia> A = rand(5,5); F = qrfact(A); R = F[:R]; Q = F[:Q]
julia> Base.ctranspose(Q::Any) = Q;
WARNING: Method definition ctranspose(Any) in module Base at operators.jl:300 overwritten in module Main at REPL[6]:1.
julia> norm(ctranspose(Q)*A - R) # still works fine
4.369698239720409e-16

يبدو أن الكتابة فوق transpose بهذه الطريقة تسمح لـ transpose([ :x _=1:4 ]) - أي ما قمت بنشره. كنت أعتقد أنه طالما أنك تنفذ transpose / ctranspose بشكل صحيح لكل ما يحتاجه (على سبيل المثال ، QRCompactWYQ ) فلن يتم استدعاء الرجوع (منذ إجراء مكالمة أكثر تحديدًا) يمكن صنعه).

لا يستدعي الرمز الخاص بك طريقة ctranspose التي كتبتها (يمكنك التحقق من ذلك باستخدام @which ). إنها تستدعي طريقة احتياطية مختلفة في إصدار Julia v0.5 (وهو غير موجود في الإصدار 0.4) والذي يقوم بشكل أساسي بعمل ctranspose(full(Q)) . هذا التراجع الآخر صحيح ، لكنه يهزم السبب الحقيقي وراء امتلاكنا لهذا النوع الرائع من النوع Q (بحيث يمكن الضرب به بدقة). تعليقي بأن الاحتياطيات يجب أن تكون صحيحة لا يزال قائما.

نعم ، طالما أنك تنفذ التحويل بشكل صحيح لكل شيء
يحتاج إليها ، فإن التراجع بالطبع لا يضر. الضرر هو أنك لا تفعل
تحصل على خطأ في الأسلوب إذا نسيت القيام بذلك ، ولكن الخطأ بصمت
نتيجة.

شكرا toivoh الذي جعله انقر لي. أنا حقا أقدر التفسيرات.

ولكن إذا قمت بتعريف دالتين احتياطيتين transpose(X::AbstractMatrix) و transpose(X::AbstractVector) فمن المفترض أنك ستحصل دائمًا على النتيجة الصحيحة (حتى لو كانت بطيئة ... استدعاء full على سبيل المثال) لا؟ ويمكنك دائمًا كتابة وظيفة أكثر تخصصًا للقيام بها بشكل أفضل / أسرع. إذن ، لا ينبغي أن يتسبب transpose(::Any) حدوث أخطاء صامتة بخلاف "التورية" المذكورة سابقًا (على سبيل المثال عند التعامل مع أرقام Complex ... ربما حالات استخدام أخرى لا أعرف عنها؟)

لأسباب تاريخية ، QRCompactWYQ <: AbstractMatrix ، لكن وفقًا لـ # 987 # 10064 علاقة التصنيف الفرعي هذه غير صحيحة ويجب إزالتها.

مثال آخر على مصفوفة ليست مثل المصفوفة هو IterativeSolvers.AbstractMatrixFcn ، وهو ليس نوعًا فرعيًا من AbstractMatrix . بالنسبة لهذا النوع ، لن يتم إرسال الاحتياطيات التي تشير إليها أبدًا ، والتي كانت وجهة نظري الرئيسية مرة أخرى.

يجب أن نواصل هذه المناقشة في https://github.com/JuliaLang/julia/issues/13171. تدور المشكلة في الواقع بشكل أساسي حول المتجهات التي تحتوي على عناصر تشبه الأرقام.

شخص ما من فريق "الجبر الخطي لفريق" يحتاج إلى تصعيد والالتزام بعمل شيء حيال هذا لـ 0.6 أو سوف يصطدم مرة أخرى.

إذن لإعادة التشغيل ، ما هي الخطة الفعلية؟

يقودني خط تفكيري إلى: transpose(v::AbstractVector) = TransposedVector(v) حيث TransposedVector <: AbstractVector . الشيء الدلالي الوحيد الذي سيميز TransposedVector من AbstractVector سيكون كيف يتصرف تحت * (وجميع A_mul_B s ، \ ، / ، ...). أي أنه مصمم لتحديد المؤشرات التي سيتم التعاقد عليها بأقل من * (إلخ ...). سيكون التحويل مفهومًا للجبر الخطي وإذا كنت تريد إعادة ترتيب مجموعة من "البيانات" ، فيجب تشجيع reshape و permutedims .

الشيء الدلالي الوحيد الذي سيميز TransposedVector عن AbstractVector سيكون كيف يتصرف تحت *

إذن ، v'==v لكن v'*v != v*v' ؟ في حين أن هذا قد يكون منطقيًا ، إلا أنه قد يبدو محيرًا أيضًا.

إذن ، v'==v لكن v'*v != v*v' ؟ في حين أن هذا قد يكون منطقيًا ، إلا أنه قد يبدو محيرًا أيضًا.

IMO هذا أمر لا مفر منه (رغم أنه قد يكون مؤسفًا).

ثنائي المتجه هو أيضًا متجه. لا يزال النقل أيضًا عبارة عن بنية بيانات أحادية البعد مع عناصر محددة جيدًا والتي يجب أن تكون قادرة على الحصول على ، وتغيير ، وتخطيط ، وتقليل ، إلخ.

ما لم نفصل الجبر الخطي عن المصفوفات (على سبيل المثال ، اجعل Matrix{T} نوعًا فرعيًا ومغلفًا غير قابل للتغيير من Array{T,2} ، مع تحديد طرق أكثر (خاصة بالجبر الخطي)) ، فأنا لست متأكدًا من ذلك هو الكثير من الخيارات التي تتوافق مع كل من صفيفها وخصائص الجبر الخطي.

السؤال المربك الوحيد (بالنسبة لي) هو ما إذا كان يبث مثل المتجه ، أو بعده الثاني. إذا كان الحجم هو (1, n) فإن هذا التغيير بالكامل لا يفعل الكثير حقًا باستثناء التأكيد على أنه يشبه المصفوفة حيث يُعرف البعد الأول بطول 1 . يجب أن يظل تحويل Vector{T} Array{T,2} (على سبيل المثال Matrix ...) ، ومع ذلك يمكن أن يكون تبديل ذلك Vector مرة أخرى ( على سبيل المثال ، يمكن أن يكون لدينا v'' === v ).

هل هذه فكرة أفضل؟ سيكون أقل كسرًا وسيظل يحسن الدلالات من الجبر الخطي. تحرير: ويتصرف بشكل مختلف wrt == كما يحضر martinholters ).

بالنسبة لي ، يبدو أن وجود TransposedVector{T <: AbstractVector{Tv}} <: AbstractMatrix{Tv} *) مع size(::TransposedVector, 1)==1 ولكن transpose(::TransposedVector{T})::T هو الأسلوب الأكثر عقلانية ، ولكن كان هناك الكثير من الجدل لدرجة أنه من المحتمل وجود بعض الحجج الجيدة ضد هذا؟

*) أعلم أن هذا غير صحيح من الناحية النحوية ، لكنني آمل أن تكون الدلالات المقصودة واضحة.

نعم ، عند اللعب بالأفكار في الكود أجد أنني أتفق معك @ مارتينهولترز.

لقد بدأت على https://github.com/andyferris/TransposedVectors.jl. يمكن تحقيق كل هذا باستخدام قدر صغير فقط من قرصنة النوع وتجاوزات الطرق من حزمة خارج القاعدة ، وقد صنعت حزمة متوافقة مع Julia 0.5. إذا اتضح جيدًا ، فربما يمكننا نقله إلى Base؟ (أو تعلم بعض الدروس).

أحد الأسئلة الكبيرة هو ما إذا كان بإمكاننا العيش بدون نوع CTransposedVector للاقتران المعقد ، أو أنه سيتم التعامل مع ذلك.

لن أستخدم CTransposedVector منفصلًا ، لأن ذلك يجمع بين مفهومين (الاقتران وإعادة التشكيل) في كائن واحد. إنه أكثر قابلية للتركيب للحفاظ على هذين المفهومين منفذين ككيانات منفصلة. على سبيل المثال ، مع MappedArrays.jl يكون الأمر سهلاً مثل

conjview(A) = mappedarray((conj,conj), A)

وتحصل على أداء رائع أيضًا.

حسنًا ، شكرًا تيم. كنت أفكر / آمل في شيء من هذا القبيل - كان شاغلي الوحيد هو كيفية ضمان ظهور الغلافين دائمًا بالترتيب "الصحيح" ، لكنني أعتقد أن ما نفذته حتى الآن يمكنه التعامل مع ذلك. سنحتاج أيضًا إلى دعم BLAS لجميع هذه المجموعات ، والتي تمكنت من تجنب لمسها حتى الآن.

شيء جميل واحد هو أن التغيير المنفصل الذي يتخلف عن conj إلى conjview سيكون مستقلاً عن هذا التغيير (أعتقد أنه يمكن العبث بهما في حزم مستقلة وأن يتم تكوينهما معًا بشكل صحيح) هل هناك أي رغبة في عرض conj ؟ هل ننتظر العناصر غير المتغيرة المضمنة لجعل هذه الآراء مجانية؟ أو لا داعي للانتظار؟

andyferris : أعتقد أن https://github.com/JuliaLang/julia/issues/5332. ما وراء الأبعاد 1 و 2 ، لا أعتقد أن عمليات النقل منطقية ، لذا فهي مجموعة محدودة من الأنواع.

الآن بعد أن أكملنا التحويل ، سأذكر مرة أخرى أنه يجب علينا محاولة تجنب نوع المتجه المنقول. لقد تم ذكره مرتين أعلاه ولكني أشك في أن أي شخص سيتمكن مرة أخرى من قراءة جميع التعليقات الخاصة بهذه المشكلة. إن تقديم نوع تبديل للناقلات يعقد الأمور حقًا دون فائدة تقريبًا. إذا كنت تعتقد حقًا أن المتجه له اتجاه ، فاجعله مصفوفة وستعمل الأشياء. ليس من المنطقي أن يكون لديك متجهات الجبر الخطية التي تختلف عن المصفوفات ثم تقديم نوع غلاف جديد لجعل المتجهات تتصرف مثل مصفوفات 1xn .

عدم التناسق الآن هو أن x' يروج x إلى مصفوفة بينما A*x لا يقوم بترقية x إلى مصفوفة. إذا كانت عمليات الجبر الخطي للعملية ثنائية الأبعاد فقط ، فيجب أن يتم ترقية A*x و x'x ستكون مصفوفة 1x1 . بدلاً من ذلك ، يمكن أن نسمح للناقلات بأن تكون متجهات ، وبالتالي يكون أيضًا A*x متجهًا ، ولكن بعد ذلك ، يجب أن يكون x' خطأ أو خطأ. سيتطلب إدخال متجه محوّل الكثير من تعريفات الطرق الجديدة ويبدو أن الفائدة الوحيدة هي أن يصبح x'x رقمًا قياسيًا.

أعتقد أن تبديل المصفوفة مختلف تمامًا. سيسمح لنا ذلك بالتخلص من جميع أساليب Ax_mul_Bx والسلوك غير قابل للنقاش بنفس الطريقة التي يكون بها سلوك ناقل الحركة.

لا أرى حقًا كيف يتسبب إدخال نوع TransposedVector في حدوث مشاكل أكثر من إدخال نوع TransposedMatrix.

نعم ، كان الإجماع القوي في مكان ما في منتصف هذا التأليف هو أن تبديل المتجه غريب ، وأنه إذا تم تنفيذه ، فلن يكون بالتأكيد نوعًا فرعيًا من AbstractArray - حتى أنني لن أسمح بـ size بالكامل. يعدد ملخصي أعلاه بعض تحديات الصواميل والمسامير لتضمين covector - وليس أقلها تدوينًا (لاحظ أنني أوصي باتباع نهج Tim في تعيين conj فوق المصفوفة بدلاً من تضمينها كنوع معامل).

ولكن كانت هناك دعوة أقوى لتحويل المتجه ليكون مجرد خطأ. إذا كان هذا هو الحال ، فأعتقد أنه يمكن أن يعيش بالفعل في حزمة.

يبدو أن نقل المتجهات خطأ يشبه رمي الطفل بماء الحمام. عدم القدرة على كتابة v' لنقل متجه سيكون أمرًا مزعجًا حقًا. لا أفهم حقًا ما هو السيئ جدًا في وجود نوع TransposedVector الذي يتصرف مثل مصفوفة الصف بصرف النظر عن كيفية تضاعفها مع المتجهات والمصفوفات.

يعتمد ذلك على عدد السلوكيات التي تريد معالجتها باستخدام ناقل ناقل. إذا كنت تريد ببساطة v'' == v ، فلا بأس من typeof(v') <: AbstractMatrix . ولكن إذا كنت تريد الأشياء الأخرى التي تحدثنا عنها في هذا الموضوع مثل typeof(v'v) <: Scalar أو typeof(v'A) <: AbstractVector ، فيجب أن تكون وحشًا مختلفًا وأكثر تعقيدًا.

يبدو أن فكرة أن يكون TransposedVector نوعًا من Vector هي أصل العديد من المشكلات. يبدو أنه سيكون أقل إزعاجًا أن يكون نوعًا من المصفوفة ثم يكون لديك size(v.') == (1,length(v)) تمامًا كما نفعل الآن. الاختلاف الوحيد هو أن التحويل المزدوج يعطيك متجهًا للخلف وأن v'v سينتج عددًا قياسيًا. إذا أراد المرء أن يتعامل مع المنقول باعتباره متجهًا ، فيمكنه لأن length(v') يعطي الإجابة الصحيحة وتعمل الفهرسة الخطية كما هو متوقع.

أوافق معStefanKarpinski 110٪. لقد تلاعبت بجعله نوعًا من المتجهات ولكنه لا معنى له كثيرًا بل إنه كسر ، لأنواع الأسباب التي نوقشت سابقًا في هذا الموضوع.

أسلوب جعله بحجم (1, n) يعني من حيث سلوك Array أنه يتصرف تمامًا كما هو عليه الآن. العمليات _only_ التي ستميزها عن 1-by-N Matrix هي سلوك أقل من ' ، .' ، * ، \ . و / .

لا أحد من هؤلاء هم عوامل "مصفوفة مثل". إنها موجودة فقط لتنفيذ الجبر الخطي بين المصفوفات والمتجهات ، وتأتي مباشرة من MATLAB ("مختبر المصفوفة"). هذا التحسين النهائي يقول ببساطة أن size(tvec, 1) = 1 ثابتًا للمترجم _ و_ أريد v'' ليكون v . (أعتقد أنه نوعًا ما يشبه إلى حد ما StaticArray حيث يتم إصلاح أحد الأبعاد والآخر ديناميكي الحجم).

إذا كنت تريد v '' == v ، فلا بأس من typeof (v ') <: AbstractMatrix.

حق.

ولكن إذا كنت تريد الأشياء الأخرى التي تحدثنا عنها في هذا الموضوع مثل typeof (v'v) <: Scalar أو typeof (v'A) <: AbstractVector ، فيجب أن يكون وحشًا مختلفًا وأكثر تعقيدًا.

لماذا ا؟ نحن لا نكسر أيًا من خصائصها الشبيهة بالمصفوفة ، لذلك يمكن أن تظل مصفوفة. ستعمل أي مكالمة نقطية تمامًا كما كان من قبل ، وستتم إزالة العمليات الموجهة الأخرى. أعتقد أن * "متخصص" في معرفة الأشكال المختلفة من Vector و Matrix وهذا لأننا نحاول محاكاة سلوك الجبر الخطي المكتوب. جعل v' * v رقمًا قياسيًا هو _very_ رياضيات معيارية ، وتفسيري هو أن السبب الوحيد وراء عدم حدوث ذلك منذ البداية هو أنه ليس من التافه التنفيذ بطريقة متسقة (والإلهام الذي تأخذه جوليا من MATLAB) ، ولكن يمكن لستيفان توضيح ذلك. إن جعل المنتج الداخلي حجمًا هو التغيير الوحيد الذي يمكن التحدث عنه هنا (هناك أشياء أخرى ثانوية جدًا) - لا أرى سببًا يجعل هذا وحده غير مناسب أن يكون Array (هناك العديد من الأنواع من Array التي لا تحتوي على ' ، .' ، * ، \ و / محدد _ على الإطلاق_ ، المرتبة 3+ بشكل ملحوظ)

إحدى القضايا التي واجهتها العام الماضي كانت الغموض. IIRC كان حلها أسهل بكثير عندما لم يكن تبديل المتجه مصفوفة.

نعم ، أنا قلقة قليلاً من مدى عمق ذلك قبل أن أنتهي ... :)

كملاحظة عامة ، سيكون من الرائع أن نجعل / عندما نجعل أقل من Base مترابطًا ونقوم بتجميعها في المكتبات القياسية. إن وجود حزمة أو وحدة قائمة بذاتها تحدد فقط AbstractArray و Array سيجعل هذا النوع من التطوير أبسط.

ما هي بالضبط مشكلة اقتراح Jutho ؟ ألا يمكن أن ينقل * تلقائيًا (مترافق) المتجه إلى اليسار؟

إذا كان لدينا * ضرب المصفوفة ، و ' تبديل المصفوفة (المترافق) (يترك المتجهات دون تغيير) ، وعاملين promote يضيفان مفردة لاحقة و demote الذي يزيل مفردة لاحقة ، ثم يمكننا إنشاء تطبيق صحيح *: (n,m) -> (m,) -> (n,) ، تطبيق يسار *: (n,) -> (n,m) -> (m,) ، منتج قياسي *: (n,) -> (m,) -> (,) ومنتج خارجي ×: (n,) -> (m,) -> (n,m) مثل:

(*)(A::AbstractMatrix, v::AbstractVector) = demote(A*promote(v))
(*)(u::AbstractVector, A::AbstractMatrix) = demote((promote(u)'*A)')
(*)(u::AbstractVector, v::AbstractVector) = demote(demote(promote(u)'*promote(v)))
(×)(u::AbstractVector, v::AbstractVector) = promote(u)*promote(v)'

لست متأكدًا من أنني سأحتاج أبدًا إلى تبديل ناقل مع هؤلاء المشغلين. هل فاتني شيء؟

تحرير: ليس بالضبط اقتراح Jutho .

Armavica ، لست متأكدًا تمامًا من أنه كان اقتراحي تحديدًا لتعيين هذا المعنى إلى * ولكن بدلاً من ذلك لمشغل (unicode) جديد ، وهو ما يعادل حاليًا dot . علاوة على ذلك ، لا أعتقد أنك ستكون قادرًا على تنفيذ نهج promote و demote بطريقة مستقرة.

يتفق الأصولي بداخلي مع dot(v,w) على v'w أو v'*w أي وقت) ، لكن يمكنني أيضًا أن أقدر مرونة العمل بالطريقة التي اقترحها andyferris . لذلك لن أضيف أي شيء آخر إلى هذه المناقشة وأؤيد أي محاولة عاقلة لتشغيل التنفيذ الفعلي.

صحيح ،Jutho. من المثير للاهتمام أن الاثنين ليسا منفصلين: عدم وجود تبديل في المتجه المحدد افتراضيًا يعني أن هذه الوظيفة يمكن أن تعيش بشكل شرعي في حزمة منفصلة أو وحدة نمطية أو "مكتبة قياسية" (أي بدون "نوع القرصنة").

(أنا شخصياً أفضل كتابة النقطة (v ، w) على v'w أو v '* w في أي وقت)

Jutho - من ناحية أخرى ، أراهن أنك لا تكتب | ψ> ⋅ | ψ> على قطعة من الورق أو السبورة ، ولكن بالأحرى <ψ | ψ> (ونفس القياس ينطبق على كيفية رسم المنتجات الداخلية مع مخططات شبكة الموتر).

بالطبع أود أن أرى تدوين ديراك Braket باعتباره الصيغة المعيارية للجبر الخطي في كل الرياضيات أو حتى العلوم ، وبالتالي في جوليا ، لكن ربما لن يحدث ذلك.

الآن تجبرني على الاستطراد ، وهو ما لن أفعله بعد الآن. أنا أوافق بالتأكيد على تفضيل <ψ | ψ> للمنتج الداخلي ، لكن هذا مستقل عن حقيقة أنني لا أفكر في <| كمقارن Hermitian لـ | ψ>. يتم تعريف الاقتران Hermitian للمشغلين. والتماثل الطبيعي بين ناقلات وما يرتبط بها من ناقلاتها المزدوجة (covectors، functionals الخطية، ...) كما هو معروف Riesz تمثيل نظرية ، على الرغم من أن الأول هو بالطبع ما يعادل الهرميتي التصريف عند تفسير طول n ناقلات على شكل خرائط الخطية من C إلى C ^ n ، مثل مصفوفات بحجم (n,1) .

بالطبع أود أن أرى تدوين ديراك Braket باعتباره الصيغة المعيارية للجبر الخطي في كل الرياضيات أو حتى العلوم ، وبالتالي في جوليا ، لكن ربما لن يحدث ذلك.

هههه

الآن تجبرني على الاستطراد ، وهو ما لن أفعله بعد الآن.

آسف ... لم يكن علي أن أذكر ذلك ... :)

لا أفكر في <ψ | كمقارن Hermitian لـ | ψ>. يتم تعريف الاقتران Hermitian للمشغلين.

صحيح ، لم أفكر في ذلك.

يُعرف التماثل الطبيعي بين المتجهات والمتجهات المزدوجة المرتبطة بها (المتجهات ، والوظائف الخطية ، ...) باسم نظرية تمثيل Riesz ، على الرغم من أن السابق يعادل بالطبع الاقتران الهرمي عند تفسير الطول n المتجهات كخرائط خطية من C إلى C ^ ن ، مثل مصفوفات الحجم (ن ، 1).

أحاول ألا أستطرد (لكنني سيئ في ذلك) ، لكنني أعتقد أننا حصلنا على القليل من هذا الجزء الأخير نظرًا لأننا نربط بين AbstractVector مع 1D Array . بعبارة أخرى ، لا يعني AbstractVector "المتجه المجرد" بالمعنى الرياضي ، ولكنه يعني بدلاً من ذلك "العناصر العددية للمتجه التي تم تحديد أساس محدد مسبقًا". خرج MATLAB من هذا بسهولة لأن المتجهات كانت بحجم (n,1) .

كغذاء للفكر ، ما الذي تسميه عامل التشغيل (المضاد للخطوط) الذي يأخذ جميع الموترات من النموذج |a>|b><c| وتعيينها إلى |c><a|<b| ؟ لقد جمعت هذا دائمًا مع اقتران المشغل الثنائي والمتجه القياسي ، باسم "الاقتران Hermitian" ولكن ربما يكون هذا بلا معنى.

أجريت محادثة مع

  • تقديم نوع Covector أو RowVector ؛
  • للعمليات الجبرية الخطية ( * ، ' ، .' ، / ، \ ، ربما norm ؟ آخرون؟ ) هذا النوع بمثابة عامل مشترك في الجبر الخطي ؛
  • بالنسبة لعمليات المصفوفة (كل شيء آخر) ، يعمل هذا النوع كمصفوفة ثنائية الأبعاد 1 × n ؛
  • على وجه الخصوص ، size(v') من covector هو (1, length(v)) .

يتطلب هذا النهج تصنيف جميع الوظائف العامة في Base على أنها جبرية خطية أم لا. على وجه الخصوص ، size هي دالة مصفوفة ولا معنى لها في مجال الجبر الخطي ، الذي لا يحتوي إلا على متجهات (التي ليس لها "شكل" ، فقط مجموعة من الأبعاد) ، التحويلات الخطية قد يتم تمثيلها بواسطة مصفوفات ثنائية الأبعاد) ، وعدادات. أحد الأمثلة المحددة التي ظهرت هو cumsum ، والذي يعمل حاليًا على مصفوفات ثنائية الأبعاد كما لو تم توفير وسيطة البعد 1. هذا غير متسق مع sum ، والذي بدلاً من التعيين الافتراضي إلى وسيطة بعد 1 تُرجع مجموع الصفيف بأكمله. كما أنه يمنع cumsum من العمل على المتجهات بطريقة مقابلة لكيفية عملها على المتجهات. أعتقد أن cumsum يجب أن يعمل على المصفوفات العامة عن طريق التجميع التراكمي بترتيب العمود الرئيسي ذي الأبعاد N. بشكل عام ، يجب ألا تكون وسيطات الأبعاد الافتراضية على 1.

سأكون قلقة بعض الشيء إذا لم تكن هناك واجهة لتحديد المتعهدين. قد تقول معظم العمليات ، مثل الحجم والحجم ndims ، إنها تشبه المصفوفات ثنائية الأبعاد أو الأحادية الأبعاد تمامًا. فقط بمحاولة منتج نقطي هل ترى فرقًا. يجب على AFAICT التحقق مما إذا كان الكائن هو RowVector ، ولكن من النادر جدًا طلب كائن من نوع معين من أجل الحصول على خاصية عامة معينة.

StefanKarpinski أتفق مع كل ذلك. خاصة أن الوظائف إما عمليات "مصفوفة" أو عمليات "جبر خطي".

لقد بدأت بحجم = (1، n) TransposedVector هنا وهو بالضبط كما قلت. لقد استغرقت بعض الوقت للحصول على تغطية جيدة للاختبارات وجميع التركيبات * ، \ ، / لكل ممكن c و t الطريقة وطرق التحوير ، مع تجنب الغموض مع الطرق الأخرى في الأساس. إنه عمل بطيء ولكنه منهجي ، ومن ذلك أعتقد أنه يمكننا سحبها إلى القاعدة عندما تكون جاهزة (ربما إعادة تسمية الأشياء).

إنه تمييز مع Covector حيث يجب أن يكون في الحقيقة منقول اقتران (أو حتى تحول أكثر عمومية ، في الحالة العامة!) ، بينما RowVector أو TransposedVector أبسط من الناحية المفاهيمية.

JeffBezanson هل هناك شيء يمكننا فعله باستخدام indices() للحصول على بُعد "مفرد"؟

ولكن من النادر جدًا طلب أن يكون للكائن نوع معين من أجل الحصول على خاصية عامة معينة.

حسنًا ، سيكون رائعًا إذا كانت هذه سمة أو شيء من هذا القبيل. كنت آمل أن نتمكن من فصل الجبر الخطي عن المصفوفات بشكل عام ، لكن هذا تغيير كبير. وربما لا يمكن أن يكون أنيقًا بدون تطبيق سمة لطيفة في جوليا. أعتقد أن المشكلة هنا هي أننا نرسم خرائط لثلاثة أشياء (المتجهات ، المتجهات والمصفوفات) على نوعين ( AbstractArray{1} و AbstractArray{2} ) ، وهكذا يصبح أحدهم (المتجهات) نوعًا فرعيًا خاصًا من جهة أخرى.

كنت سأضع AbstractTransposedVector في الحزمة إذا كان بإمكاني التفكير في مكان يحتاج فيه شخص ما إلى أي شيء آخر غير تطبيق "المجمع" الأساسي.

JeffBezanson : أنا لا

تحديث لمحاولاتي في معالجة هذا:

TransposedVectors.jl الآن ، على ما أعتقد ، "ميزة كاملة". يحتوي على جميع الآليات اللازمة للقيام بما تحدث عنه @ StefanKarpinski هنا - إن تبديل المتجه هو غلاف لمتجه يتصرف كمصفوفة مجردة ثنائية الأبعاد بحجم 1xn - ولكن لعمليات الجبر الخطي ( * ، / ، \ ، ' ، .' و norm ) يتصرف كمتجه صف (أو متجه مزدوج).

يمكنك التحقق من ذلك على النحو التالي:

julia> Pkg.clone("https://github.com/andyferris/TransposedVectors.jl")
...

julia> using TransposedVectors
WARNING: Method definition transpose(AbstractArray{T<:Any, 1}) in module Base at arraymath.jl:416 overwritten in module TransposedVectors at /home/ferris/.julia/v0.5/TransposedVectors/src/TransposedVector.jl:28.
WARNING: Method definition ctranspose(AbstractArray{#T<:Any, 1}) in module Base at arraymath.jl:417 overwritten in module TransposedVectors at /home/ferris/.julia/v0.5/TransposedVectors/src/TransposedVector.jl:29.
WARNING: Method definition *(AbstractArray{T<:Any, 1}, AbstractArray{T<:Any, 2}) in module LinAlg at linalg/matmul.jl:86 overwritten in module TransposedVectors at /home/ferris/.julia/v0.5/TransposedVectors/src/mul.jl:9.
WARNING: Method definition At_mul_B(AbstractArray{#T<:Real, 1}, AbstractArray{#T<:Real, 1}) in module LinAlg at linalg/matmul.jl:74 overwritten in module TransposedVectors at /home/ferris/.julia/v0.5/TransposedVectors/src/mul.jl:37.
WARNING: Method definition Ac_mul_B(AbstractArray{T<:Any, 1}, AbstractArray{T<:Any, 1}) in module LinAlg at linalg/matmul.jl:73 overwritten in module TransposedVectors at /home/ferris/.julia/v0.5/TransposedVectors/src/mul.jl:64.

julia> v = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

julia> vt = v'
1×3 TransposedVectors.TransposedVector{Int64,Array{Int64,1}}:
 1  2  3

julia> vt*v
14

julia> vt*eye(3)
1×3 TransposedVectors.TransposedVector{Float64,Array{Float64,1}}:
 1.0  2.0  3.0

قد يكون هناك بعض تدهور الأداء - قد يكون قياس الأداء مفيدًا. في بعض الحالات ، سوف تقوم بعمل نسخ أقل (التحويل كسول) وفي حالات أخرى تقوم بعمل نسخ أكثر (في بعض الأحيان يتم إنشاء نسخة مترافقة من ناقل (ليس مصفوفة أبدًا) في Ac_mul_Bc على سبيل المثال). والغلاف نفسه له تكلفة طفيفة حتى نقوم بتضمين الحقول القابلة للتغيير في العناصر الثابتة (لحسن الحظ بالنسبة لي ، هذا يعمل بالفعل بشكل جيد مع StridedArray عند الاقتضاء.

إذا أعجب الأشخاص بهذه الطريقة ، فيمكننا أن نرى كيفية إنشاء علاقات عامة قريبًا لترحيل الرمز إلى Base (تحتوي الحزمة بالفعل على اختبارات وحدة وتم حل جميع جوانب الغموض). (أيضًا ، ذكر jiahao الرغبة في تجربة إصدار مصفوفة مجردة أحادية الأبعاد لمتجه مزدوج ، لست متأكدًا مما إذا كان قد تم إحراز أي تقدم؟)

هل يعتقد الناس أن مثل هذا العلاقات العامة سيكون منطقيًا في الإصدار 0.6 بدون نوع غلاف للمصفوفات المنقولة؟ في حين أن المتجهات المنقولة هي تغيير دلالي ، فإن المصفوفات المنقولة هي أكثر من تحسين ، لذلك أفترض أنها يمكن أن تدخل بشكل منفصل. بالطبع ، قد يبدو الأمر "غريبًا" إذا كانت بعض التحولات آراء وبعضها نسخ - آراء؟ هناك نقطة أخرى يجب مراعاتها وهي أنه بمجرد إدخال كل من المصفوفات والمتجهات المنقولة ، يجب القيام بالكثير من العمل لإزالة جميع وظائف At_mul_Bt ، واستبدالها بالطرق الموجودة على * ، لإكمال الانتقال (على الرغم من أن التبسيط سيكون مجزيًا!) - أشك في أن أي شخص قادر أو مستعد للقيام بكل ذلك بحلول نهاية هذا الشهر ...

عمل رائع ،andyferris! هل جربت استخدام غلاف عام كاذب Conjugate على الإطلاق؟

andyferris لقد ركلت الإطارات ، ومثل هذا قليلاً. يبدو تحسنًا صارمًا ، وآمل أن يتم التعامل مع مشكلات الأداء كما نجدها. دعونا نرى ما يقوله الآخرون.

شكرا يا شباب :)

هل جربت استخدام غلاف عام كاذب Conjugate على الإطلاق؟

ليس بعد ، على الرغم من أنه قد يكون ممكنًا دون بذل الكثير من الجهد ، ولكن لأكون صريحًا كنت قلقًا بشأن عدم إنهاء هذا كثيرًا بحلول نهاية ديسمبر. بالنظر إلى المستقبل ، كنت أفكر في أنه في النهاية قد يكون لدينا أنواع "unionall" التالية للإرسال إليها من أجل الجبر الخطي:

  • AbstractVector
  • Conjugate{V where V <: AbstractVector} (أو Conj{V} ، ربما حتى ConjArray ؟ بالطبع سيقبل مصفوفات من أي بُعد)
  • TransposedVector (أو RowVector ؟)
  • TransposedVector{Conjugate{V where V <: AbstractVector}}
  • AbstractMatrix
  • Conjugate{M where M <: AbstractMatrix}
  • TransposedMatrix (أو ببساطة Transpose{M} ؟)
  • TransposedMatrix{Conjugate{M where M<:AbstractMatrix}}

(بالإضافة إلى كل السمات المعطاة للتخزين الأساسي ، مثل ما نسميه الآن DenseArray و StridedArray - آمل أن # 18457 قد يجعل الأمر أسهل قليلاً للتعبير عنها أيضًا).

بصرف النظر عن التسمية ، هل يبدو ذلك كخطة معقولة؟

بالنسبة إلى الزفاف الفوري للدراجات ، بالنسبة للعلاقات العامة على أساس ما هو موجود حاليًا في الحزمة ، هل نفضل TransposedVector ، RowVector ، غلاف عام Transpose لكل من المتجهات والمصفوفات ، أو أي شيء آخر؟

أعتقد أن السلوك الذي قدمه تطبيق

تكمن المشكلة في تحديد أنواع مصفوفة جديدة. على سبيل المثال ، DArray هو نوع فرعي من AbstractArray ، لذلك يمكن أن يكون DArray أيضًا AbstractVector أو AbstractMatrix . من الناحية المثالية ، سنقوم فقط بتوسيع تمييز المتجه / المصفوفة إلى الصف / العمود / المصفوفة ، لذلك يمكن أن يكون DArray AbstractRow أو AbstractCol أو AbstractMatrix . سيكون التسلسل الهرمي للنوع شيئًا مثل

AbstractArray
    AbstractVector
        AbstractRowVector
        AbstractColumnVector
    AbstractMatrix
    ...

كان يتحدث مع jiahao عن هذا بالأمس.

قد تكون هناك بعض الأسبقية هنا ، حيث لا يمكن استخدام جميع AbstractVector s كأعمدة ، على سبيل المثال:

julia> isa(1.0:10.0, AbstractVector)
true

julia> randn(10,10) * 1.0:10.0
ERROR: MethodError: no method matching colon(::Array{Float64,2}, ::Float64)

والتي يمكن أن تعالج المشكلات التي عادت إليها في https://github.com/JuliaLang/julia/issues/4774#issuecomment -59428215

هذا فقط ينقص الأقواس حول النطاق؟

هذه مجرد مسألة أسبقية:

julia> randn(10,10) * (1.0:10.0)
10-element Array{Float64,1}:
 -22.4311
  ⋮

أوافق على أن الحل الأمثل هنا يبدو أنه يتطلب سمات ، لكنني لا أعتقد أن هذا يجب أن يعيق عمل

آه ، نقطة جيدة. أحب أن تكون الأولوية غير الصحيحة للمسافات البيضاء خطأ نحويًا ، على غرار Fortress.

أشارت مجموعة MIT إلى أن إحدى الطرق لتنفيذ التسلسل الهرمي للنوع الذي وصفته أعلاه هي إضافة معلمة نوع إلى التسلسل الهرمي للصفيف:

abstract AbstractArray{T,N,row}

type Array{T,N,row} <: AbstractArray{T,N,row}
end

typealias AbstractVector{T} AbstractArray{T,1}
typealias AbstractRowVector{T} AbstractArray{T,1,true}
typealias AbstractColVector{T} AbstractArray{T,1,false}
typealias AbstractMatrix{T} AbstractMatrix{T,2}

typealias Vector{T} Array{T,1,false}
typealias Matrix{T} Array{T,2,false}

لم أفهم جميع الآثار المترتبة على هذا - ربما يكون أسوأ ما في الأمر هو أن Array{Int,1} يصبح نوعًا مجردًا - ولكن يبدو أن هذا هو نوع التسلسل الهرمي وأن التجريدات المطلوبة صحيحة تمامًا.

لما يستحق ، هذا هو بالضبط حالة استخدام للأنماط الفوقية غير المكتملة المعلمات ؛ يمكن أن تصبح معلمات افتراضية ضمنية.

abstract AbstractArray{T,N,row}

type Array{T,N} <: AbstractArray{T,N}
end

isrow{T,N,row}(::AbstractArray{T,N,row}) = row
isrow{T,N}(::AbstractArray{T,N}) = false

julia> isrow(Array{Int,2}())
false

بالطبع ، هذا يجعل الإرسال فوضويًا قليلاً ... وقد لا يستحق الدعم. إنها مجرد كرة مبصقة.

بالنسبة لي هذا يبدو مكافئًا للتعريف

type Array{T,N} <: AbstractArray{T,N,false}
end

ما قد نريده هنا هو نوع من "معلمات النوع الافتراضية" على الرغم من ذلك ، مثل جعل النوع Array{X,Y} حيث لا توجد متغيرات مجانية X و Y يعطي في الواقع Array{X,Y,false} .

فكرة أخرى: الحفاظ على تدوين Householder للمنتجات الداخلية v'v و covector الأيسر يضرب v'A بجعل infix ' عامل التشغيل الخاص به بدلاً من تحليلها كـ v'*v و v'*A . إلى جانب جعل الهوية v' ، و v*v خطأ ، و v*A خطأ ، قد يعطي هذا الكثير مما هو مطلوب. سيكون عليك كتابة المنتجات الخارجية كـ outer(v,v) .

في مثل هذا المخطط ، سيكون v' خطأ أو حتى خطأ - نظرًا لعدم وجود سبب لتغيير المتجه في مثل هذا المخطط ، سيكون من المنطقي فقط للمصفوفة.

JeffBezanson أوافق على أن الحصول على AbstractRowVector سيكون الأفضل (لكنني بصراحة لا أستطيع التفكير في حالة استخدام ، لذلك لم أقم بتطبيقها في الحزمة). أود أيضًا أن أشير إلى أن هذا يمكن أن يعيش كنوع فرعي من AbstractMatrix . السبب الذي جعلني أتحرك في هذا الاتجاه هو أن broadcast يبدو مفهومًا أساسيًا لجوليا أكثر من الجبر الخطي ، ويتوقع الناس أن يكون متجه الصف ، حسنًا ، صفًا!

بالطبع استخدام RowVector <: AbstractMatrix هو استخدام مؤسف للمصطلحات! أعتقد أن هذا ناتج عن إعطاء مصفوفات ثنائية الأبعاد ومصفوفات مجردة نفس الاسم.

لقد قلت هذا من قبل ، بعيدًا جدًا ، ولكن نظرًا لأن هذه المشكلة طويلة جدًا ، فسوف أعيد تأكيدها: في لغة عامة مثل جوليا ، يجب أن تكون خاصية "مصفوفة البيانات" الاعتبار الأساسي لـ AbstractArray . الرد على الطريقة التي تريد أن يتصرف بها broadcast مع متجه "محوّل" يخبرك ما إذا كان 1D أو 2D. إذا كنت تريد التفكير من حيث الصفوف والأعمدة ، فإن متجهات الصف 1 x n ستكون أكثر منطقية. إذا كنت تريد التفكير في نواقل مزدوجة ، فإن 1D منطقي للغاية - وأنا سعيد بذلك أيضًا! لكن أخذ ثنائي المتجه أكثر تعقيدًا من إعادة تشكيل البيانات (على سبيل المثال ، يتعين علينا دعم الاقتران على الأقل).

أعتقد أن الصورة "الصفية" ستطابق توقعات المبرمجين "النموذجيين" ، في حين أن الأشخاص الذين لديهم تدريب رياضي متقدم قد يستفيدون بشكل أفضل من المتجهات المزدوجة لأنها تجريد أفضل (على الرغم من أنني متأكد من أنهم سيكونون قادرين على ذلك نتعاطف مع أولئك الذين لديهم معرفة أساسية بالجبر الخطي فقط). إذن - ما الجمهور الذي تستهدفه جوليا - الأشخاص الذين يتمتعون ببراعة رياضية أكثر من العديد من مستخدمي MATLAB النموذجيين ، أو الأشخاص الذين لديهم قدر أقل من ذلك؟

(كان رأيي أنه نظرًا لأن جوليا كانت تهدف إلى أن تكون لغة برمجة "عامة" ، كان الجمهور الأخير هو الهدف).

نظرًا لأننا نناقش أنواع الأشجار الممكنة - في المستقبل ، مع Buffer و "قوائم" قابلة لتغيير الحجم ، أتخيل شجرة مجردة من الواجهات التي تتماشى مع شيء ما على غرار

AbstractArray{T,N} # interface includes broadcast, Cartesian, getindex, setindex!, etc.
    AbstractArray{T,1}
        AbstractList{T} # resizeable, overloaded with `push!` and so-on
        AbstractVector{T} # non-resizeable, overloaded for *, /, \, ', .', etc
    AbstractArray{T,2}
        AbstractRowVector{T} # non-resizeable, overloaded for *, /, \, ', .', etc
        AbstractMatrix{T} # non-resizeable, overloaded for *, /, \, ', .', etc

بالطبع ، يمكننا أيضًا الحصول على AbstractDualVector{T} <: AbstractArray{T,1} بدلاً من AbstractRowVector .

سيكون من الصعب الحصول على نوع مرن وملموس من النوع Array يناسب كل هذه الأشياء (وربما غير ضروري). ستتيح لنا السمات بالتأكيد التعبير عن هذه الاختلافات في الواجهات المدعومة بسهولة أكبر.

يبدو أن امتلاك AbstractVector كلاً من C ++ std::vector ومتجه الجبر الخطي أمر صعب بعض الشيء بالنسبة لي :) (خاصة وأن واجهة المصفوفة تعني أنه لا يمكن أن يكون "متجهًا مجردًا" في حس الجبر الخطي (على سبيل المثال ، الأساس الحر))

نعم ، سيكون من الجيد فصل سلوك تغيير الحجم. أنا على متن الطائرة لذلك.

يبدو أن هذا النوع من التسلسل الهرمي يعني أنه سيكون لدينا "مصفوفة" و "مصفوفة ثنائية الأبعاد" منفصلة في القاعدة. يمكننا محاولة الالتفاف حوله ، على سبيل المثال من خلال جعل المُنشئ مقابل Array{T,2} يعيد فعليًا نوعًا آخر من المصفوفات ، لكنه يبدو قبيحًا جدًا. ربما أنا أسوء الفهم رغم ذلك.

يبدو أن هذا النوع من التسلسل الهرمي يعني أنه سيكون لدينا "مصفوفة" و "مصفوفة ثنائية الأبعاد" منفصلة في القاعدة.

صحيح ... أعتقد أنه للقيام بذلك بشكل جيد ، سنحتاج إلى سمات. ضع في اعتبارك أنني أطلقت عليها اسم "شجرة مجردة للواجهات". إن محاولة ذلك في الوقت الحالي تتطلب شيئًا قبيحًا كما قلته. ولكن ربما يمكننا إدخال AbstractList <: AbstractVector (ونقل الطرق المرتبطة) بمجرد الانتهاء من Buffer .

في الوقت الحالي ، يكون الاتصال بين الواجهات المدعومة وشجرة الكتابة ضعيفًا جدًا. من الصعب معرفة ما إذا كانت مصفوفة (مجردة) قابلة للتغيير (أي تدعم setindex! ) عند الإرسال ، وما إذا كانت قابلة لتغيير الحجم أم لا ، لا تعمل إلا مع الأنواع المحددة في Base ، إلخ. هذا يجعلها من الصعب على المستخدمين توفير وظيفة بأساليب تعمل وتتسم بالكفاءة مع مجموعة واسعة من المدخلات (هذه هي تجربتي من StaticArrays ).

فكرة للمحادثة حول مناطق الرياضيات في التسلسل الهرمي للنوع والأدوار المعقولة للتجريدات ذات المعلمات. عندما يكون ذلك ممكنًا ، من الجيد أن تقوم جوليا بتبسيط وتخفيف أي فصل عن كيفية كتابة التعليمات البرمجية للقيام بما تنوي الخبرة من النية المعبر عنها بخبرة.

هناك اتفاقية واحدة قد نختار استخدامها تجعل الممارسة الشائعة باستخدام نوع مجرد غير أي لتكوين منطقة وجودية وسط الأنواع الملموسة المصاحبة التي تجد الراحة المشتركة سهلة. من شأن ذلك أن يجلب ، بتكلفة قليلة جدًا ، حساسية أكبر متعددة السياقات - فهم جزء من التسلسل الهرمي للنوع يساعد المرء على الاقتراب من الأجزاء الأخرى.

كما أرى هذا ، فهو صاحب علاقة معممة. يضيء تجريد إيضاحي كجوار يربط بين الأحجار الخرسانية ، والأشكال المولدة التي تبني. مع المعلمات التي تحمل الوضوح البسيط للحدس ، تحصل جوليا على الكثير من الإنجازات في وقت أقل من الهراء.

حسنًا ، سيكون موضع تقدير أي تعليقات أخرى على TransposedVectors . أشعر أنها أصبحت قوية جدًا وجاهزة للتحول إلى علاقات عامة ، ولكن هناك بعض المشكلات ذات الصلة التي ذكرتها هنا .

(على سبيل المثال: هل اسم RowVector أفضل من TransposedVector ؟ هل [1 2 3] a RowVector أو Matrix ؟ ما هو indices(row, 1) ؟)

+1 لـ RowVector

في 20 كانون الأول (ديسمبر) 2016 ، الساعة 7:01 صباحًا ، كتب "Andy Ferris" [email protected] :

حسنًا ، سيكون موضع تقدير أي تعليقات أخرى على TransposedVectors . انا اشعر
لقد أصبحت صلبة جدًا وجاهزة للتحول إلى علاقات عامة ، ولكن هناك
بعض القضايا ذات الصلة التي ذكرتها هنا
https://github.com/andyferris/TransposedVectors.jl/issues .

(على سبيل المثال: هل RowVector اسم أفضل من TransposedVector؟ هل [1 2
3] RowVector أم المصفوفة؟ ما هي المؤشرات (الصف 1)؟)

-
أنت تتلقى هذا لأنك علقت.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/4774#issuecomment-268170323 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AAm20YYqsXmprI23GgI5PYyWStpTOq5qks5rJ309gaJpZM4BMOXs
.

أود حقًا إبقاء اصطلاح الصف / العمود بعيدًا عنه ، وأعتقد أنه يبدو غريبًا أن يكون لديك Vector و RowVector (أو حتى ColVector و RowVector ). +1 لـ TransposedVector أو DualVector

felixrehren أشعر أن DualVector يجب أن يكون له دلالات مختلفة عما قمت بتطبيقه ، بشكل أساسي كونه أحادي البعد (رياضيا ، ثنائي المتجه هو ناقل) وله خصائص ثنائية أخرى (مثل الاقتران المعقد) . هذا جيد ، لكنني وجدت أنه أصعب قليلاً في التنفيذ وأقل توافقًا مع الإصدارات السابقة.

الاسم TransposedVector مقبول. لكنها طويلة بعض الشيء. أيضًا ، يشير نوعًا ما إلى أنه لا يمكن الحصول على كائن من هذا النوع إلا من خلال نقل Vector . لكنني أفترض أنه يمكنك كسب TransposedVector بوسائل أخرى أيضًا ، على سبيل المثال ، عن طريق استخراج صف واحد من المصفوفة؟

أعتقد أن RowVector سيكون اسمًا جيدًا - فهو موجز ودقيق وبديهي. felixrehren ، أعتقد أن صورة الصف / العمود مفيدة. من المحتمل أن يكون هذا أمرًا لا مفر منه ، لأنه كلما قمت بإجراء تسلسل أو عمليات مصفوفة أخرى شائعة (بخلاف الضرب) ، فأنت بحاجة إلى التفكير في الطريقة التي يتم بها توجيه المتجه.

DualVector ليس سيئًا أيضًا ، لكن CoVector قد يبدو أقل رسمية.

تم تقديم PR الذي هددته سابقًا في # 19670. ذهبت مع RowVector الآن.

لكنني أفترض أنه يمكنك عمل TransposedVector بوسائل أخرى أيضًا ، على سبيل المثال ، عن طريق استخراج صف واحد من المصفوفة؟

هذه في الواقع نقطة شائكة - لم أفكر في بناء جملة رائع لذلك حتى الآن. أيه أفكار؟

لكنني أفترض أنه يمكنك عمل TransposedVector بوسائل أخرى أيضًا ، على سبيل المثال ، عن طريق استخراج صف واحد من المصفوفة؟

هذه في الواقع نقطة شائكة - لم أفكر في بناء جملة رائع لذلك حتى الآن. أيه أفكار؟

على الرغم من أنه يبدو في البداية أنه من الجذاب أن يكون لديك matrix[scalar,range] (وبنى أخرى مماثلة) ينتج عنه متجه للصفوف ، فإن ذلك سيكون خروجًا كبيرًا عن دلالات الفهرسة الحالية للصفائف متعددة الأبعاد ، والحالات الخاصة تجعلني حذرة.

بدلاً من ذلك ، أود أن أرى RowVectorVector لهذه المسألة) يحول أي نوع متكرر إلى النوع المناسب من المتجه. ثم يمكنك القيام بشيء مثل RowVector(matrix[scalar,range]) والذي سيكون واضحًا تمامًا ولا يزعج السلوك الحالي لفهرسة المصفوفة.

على اليمين ، يمكن استخراج الصف i th في شكل صف بواسطة A[i,:].' ، حاليًا في الإصدار 0.5 وسيستمر في القيام بذلك في المستقبل (للحصول على RowVector أو Transpose{V<:AbstractVector} أو أي شيء نتوصل إليه في النهاية (انظر هنا للمناقشة المستمرة)). ربما هذا هو الجواب.

ماذا عن مجرد إضافة وظيفتين جديدتين إلى Base؟
row(A,i) و col(A,i)
هذا الأخير ليس ضروريًا ، ولكن فقط للتماثل. إنها موجزة وواضحة ولها العديد من الأحرف مثل A[i,:].'

benninkrs هذا منطقي. على النقيض من ذلك ، فإن تفسيري الحدسي هو الجبر الخطي ، حيث لا يوجد اتجاه على الإطلاق للمتجه. جميع وجهات النظر حول هذا الموضوع معقولة ، أنا فقط لا أحب Vector و RowVector معًا لأن التسمية تبدو وكأنها تمزج بين نموذج مجردة وملموسة.

في هذه المرحلة ، أعتقد أننا بحاجة إما إلى الذهاب مع شيء ما بناءً على تنفيذ andyferris أو أن نقرر عدم التعامل مع عمليات النقل المتجه على محمل الجد. كمثال على بديل ، إليك طريقة تعالج أسوأ الأعراض: اترك v' كما هو حاليًا - أي إنتاج مصفوفة صف - ولكن حلل a'b كمعامل infix مع الأسبقية أدناه مباشرة عمليه الضرب. بمعنى آخر ، سيكون لدينا السلوكيات التالية:

  1. v' مصفوفة صف (التحويل ctranspose)
  2. v'v هو (منتج نقطي)
  3. v'*v متجه مكون من عنصر واحد (مصفوفة الصف * متجه)
  4. v*v' مصفوفة منتج خارجية (مصفوفة صف متجه *)
  5. v'A عبارة عن مصفوفة صف ("vecmat")
  6. v'*A مصفوفة صف (matmat)
  7. v'A*v هو (matvec A * v ثم منتج نقطي)
  8. (v'A)*v متجه مكون من عنصر واحد (vecmat ثم matvec)
  9. v'*A*v متجه مكون من عنصر واحد (matmat ثم matvec)
  10. v'' مصفوفة عمود (ناقل ctranspose ، ثم مصفوفة ctranspose)

في الإعداد الحالي 2 و 3 متكافئان و 7 و 8 و 9 متكافئان ، وهذا التغيير يكسر. لكن الأهم من ذلك ، أن العناصر الجريئة هي الأشياء التي سيصل إليها الأشخاص عادةً لأنها الأقصر والأكثر ملاءمة من الأشكال المماثلة - وكلهم يفعلون ما نرغب فيه. لا توجد أنواع جديدة ، فقط مشغل واحد جديد. العيب الرئيسي هو 10 - v'' لا يزال مصفوفة عمود. يمكن القول إن هذا يمكن اعتباره فائدة لأن postfix '' هو المشغل لتحويل المتجه إلى مصفوفة عمود.

بأخذ خطوة إلى الوراء ، أعتقد أن ما تعلمناه هو أنه بدون وظائف إضافية لتصنيف الأبعاد أو تحديد الأبعاد أو معالجة أبعاد ≤ 2 على أنها قابلة للاستبدال مثل Matlab ، لا يمكن جعل المصفوفات متعددة الأبعاد تتوافق بسلاسة مع الجبر الخطي. إذن ما تبقى لنا هو مسألة ملاءمة - هل يمكننا السماح للأشخاص بالتعبير عن عمليات الجبر الخطية الشائعة على المتجهات والمصفوفات بشكل ملائم دون تعقيد المصفوفات بشكل مفرط؟ أنا لست ميتًا على هذا النهج ، لكنني أعتقد أنه يجب علينا التفكير بجدية في هذا النهج وغيره من الأساليب التي تتناول الراحة النحوية دون إفساد التسلسل الهرمي لنوع المصفوفة لدينا كثيرًا.

هناك طريقة أخرى تتمثل في تحليل infix a'b بشكل خاص (أقل بقليل من * ) وإرجاع متجه مترافق v' . بشكل عام ، يمكن لـ postfix A' أن يقترن مصفوفة ويعكس أبعادها بشكل كسول بينما يقوم A.' بعكس أبعاد المصفوفة بشكل كسول ، وبالتالي يكون بمثابة هوية في المتجهات. في هذا المخطط ، يمكن أن تكون قائمة الخصائص كما يلي:

  1. v' هو ناقل (مترافق)
  2. v'v هو (منتج نقطي)
  3. v'*v خطأ (أوصي بـ v'v للمنتج الداخلي و outer(v,v) للمنتج الخارجي) †
  4. v*v' خطأ (أوصي بـ v'v للمنتج الداخلي و outer(v,v) للمنتج الخارجي) †
  5. v'A هو ناقل (vecmat)
  6. v'*A خطأ (أوصي بـ v'A لـ vecmat)
  7. v'A*v هو (matvec A * v ثم منتج نقطي)
  8. (v'A)*v خطأ (أوصي بـ v'v للمنتج الداخلي و outer(v,v) للمنتج الخارجي) †
  9. v'A'v هو ( v'(A'v) - matvec مقترن ثم منتج داخلي)
  10. v'' هو ناقل ( v'' === v و v.' === v )

الآن بعد أن كتبت كل هذه الخصائص ، قد يكون هذا هو الخيار المفضل: تعمل جميع حالات الخطأ في الواقع على مساعدة الأشخاص في اكتشاف واستخدام الصيغ المحققة ، وبالطبع تحتوي على الخاصية المرغوبة v'' === v (وتتوافق بشكل جيد مع .' كونه عامل انعكاس بُعد عام). ربما يكون وجود تراكيب متشابهة جدًا ومختلفة تمامًا أمرًا محيرًا.

† من المحتمل أن نلاحظ هذه الأخطاء في وقت التحليل بحثًا عن أخطاء أكثر دقة مع المخاطرة بإعطاء أخطاء للحالات التي زاد فيها تحميل رمز المستخدم على ' و * حتى تعمل هذه العمليات. أعتقد أن وجود غلاف متقارن كسول قد يكون ضروريًا لتصحيح هذه التوصيات ، لكننا نحتاج إلى ذلك على أي حال لـ # 5332.

بأخذ خطوة إلى الوراء ، أعتقد أن ما تعلمناه هو أنه بدون وظائف إضافية لتصنيف الأبعاد أو تحديد الأبعاد أو معالجة أبعاد ≤ 2 على أنها قابلة للاستبدال مثل Matlab ، لا يمكن جعل المصفوفات متعددة الأبعاد تتوافق بسلاسة مع الجبر الخطي. إذن ما تبقى لنا هو مسألة ملاءمة - هل يمكننا السماح للأشخاص بالتعبير عن عمليات الجبر الخطية الشائعة على المتجهات والمصفوفات بشكل ملائم دون تعقيد المصفوفات بشكل مفرط؟ أنا لست ميتًا على هذا النهج ، لكنني أعتقد أنه يجب علينا التفكير بجدية في هذا النهج وغيره من الأساليب التي تتناول الراحة النحوية دون إفساد التسلسل الهرمي لنوع المصفوفة لدينا كثيرًا.

: 100:

صراحة إجراء عمليات postfix ' و .' مصفوفة عامة (بدلاً من الجبر الخطي) تتجنب بشكل جيد مضاعفة دمج التخزين وأنواع الجبر الخطي ، وتترك الباب مفتوحًا لأطر العمل التي تتضمن تنازلات أقل. في غضون ذلك ، يجب أن توفر قدرة هذه العمليات على محاكاة تدوين صاحب المنزل في معظم الحالات الشائعة معظم الراحة المطلوبة. أيضا أقل كود وتعقيد. الأفضل!

إحدى المشكلات المتعلقة بعدم وجود v.' هي أن A .+ v.' قد يغير المعنى من إضافة قيم v إلى كل عمود من A لإضافة القيم إلى صفوف A . هذا من شأنه أن يجعل من الصعب بشكل عام القيام بعمليات شبيهة بالصف مع المتجهات وسيحتاج بالتأكيد إلى دورة إهمال كاملة لتجنب جعل الكود يفعل الشيء الخطأ بصمت (في مثل هذه الحالات حيث يكون A مربعًا).

في هذه المرحلة ، أعتقد أننا بحاجة إما إلى الذهاب مع شيء ما بناءً على تنفيذ andyferris أو أن نقرر عدم التعامل مع عمليات النقل المتجه على محمل الجد.

أدرك أن الموعد النهائي لـ v0.6 اقترب منا ، لكنني سأحذر من رمي الطفل بماء الحمام. في هذه المرحلة ، يبدو أن طرق عرض RowVector plus المذكورة لنقل المصفوفة واقتران المصفوفة ستسمح لنا بالحصول على:

  • IMO ، أنواع الجبر الخطي الأكثر منطقية إلى حد ما (نحن لا ننكر وجود متجهات مزدوجة كما هو الحال الآن ، على الرغم من أن متجه الصف قد يُنظر إليه على أنه حالة خاصة من المتجه المزدوج إلى حد ما)
  • v'' === v
  • بعض الأشياء في قائمة ستيفان مثل v1'v2 عبارة عن منتج نقطي
  • دلالات المصفوفات المتوافقة مع الإصدارات السابقة تقريبًا - على سبيل المثال ، لم تتغير نتيجة size(v') ، لكن لدينا v'' كأحد الأبعاد
  • قد تؤدي أغلفة الاقتران الكسولة والتبديل إلى زيادة الأداء في ظروف معينة وتكون مفيدة على أي حال
  • إزالة جميع وظائف Ac_mul_Bc لصالح * و A_mul_B! فقط (وبالمثل لـ \ و / ).

إن الحصول على كل هذا العمل مقابل Array بصراحة لن يتطلب الكثير من الجهد (بالنسبة لي المشكلة هي إيجاد الوقت في هذا الوقت من العام ، ومطاردة جميع الأنواع الأخرى لدينا في مجموعة الجبر الخطي). وستكون النقطة الأخيرة هي الصعداء.

على الجانب الآخر - يبدو أن هذه القواعد IMHO تعقد عملية التحليل بشكل طفيف وقد تكون مربكة بعض الشيء و / أو مفاجئة في كيفية تكوينها ' مع * (3 و 4 و 6 و 8 ستعمل مع RowVector ).

ونعم ، سيتعين علينا إهمال v.' أو شيء ما من أجل تسليط الضوء على الأخطاء المحتملة ، وعند هذه النقطة يبدو من الأفضل تقريبًا جعل v.' خطأ في الطريقة المفقودة (نحن ببساطة لن ندعم الصف) / متجهات مزدوجة ، ولكن لن توقف الحزمة عن القيام بذلك إذا رغبوا في ذلك)

19670 يبدو جاهزًا أو قريبًا منه ، إذا كانت هناك رغبة في التسلل إلى الإصدار v0.6.

بام

ووت.

هل كان هذا الموضوع الأطول لدينا؟

لا ، # 11004 لديه المزيد

آسف. أنت على حق ، كان يجب أن أحدد موضوع مفتوح .

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات