Julia: إيقاف (ثم إزالة) الفهرسة الخطية المعممة

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

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

في الأساس ، أود أن أقول إن هذا السلوك مفاجئ:

julia> x = reshape(1:3^3, (3,3,3));

julia> size(x)
(3,3,3)

julia> x[3,4]
12

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

تحرير: المناقشة الأكثر تشابهًا: https://github.com/JuliaLang/julia/issues/5396

arrays breaking help wanted

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

أنا أقدر مخاوفك وأنك تخصص وقتًا للتعبير عنها هنا. يمكن أن يكون نقل الأشياء إلى الأمام مؤلمًا بالتأكيد.

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

ال 109 كومينتر

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

الكود ذو الصلة:
LinearFast (يحول الكل إلى فهرس خطي): https://github.com/JuliaLang/julia/blob/0c20e64ab2697302b419042b9a043e967ed3db53/base/abstractarray.jl#L508
LinearSlow (يتوسع إلى الأبعاد الكاملة): https://github.com/JuliaLang/julia/blob/0c20e64ab2697302b419042b9a043e967ed3db53/base/abstractarray.jl#L525 -L551

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

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

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

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

julia> x = reshape(1:3^3, (3,3,3));
julia> x[3,3]
9

في بعض النواحي ، أجد ذلك أكثر إثارة للدهشة من المثال الآخر (ولكني أجد أنه يعود x[3,3,:] أقل من

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

ربما تكون حالة الفهرسة الخطية 1-D جيدة لأن الفهرسة كمصفوفة أحادية الأبعاد مميزة بصريًا (مقارنة ، على سبيل المثال ، بفهرسة صفيف 8-D كـ 7-D). ومع ذلك ، نظرًا لأنه من السهل جدًا استخدام vec لست متأكدًا من أن هذا ضروري.

تمت مناقشة هذا قليلاً في https://github.com/JuliaLang/julia/issues/4774 لكني لا أعرف كيفية الربط بتعليقات محددة وهذه مشكلة طويلة.

BobPortmann يمكنك الارتباط بتعليقات محددة بالنقر بزر الماوس الأيمن على الطابع الزمني (بجوار اسم المؤلف في رأس التعليق) ، واختيار "نسخ موقع الرابط" أو ما يعادله.

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

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

أنا أحب فكرة إعطاء الفهرسة الخطية طريقة خاصة.

ماذا عن A[i, LinearIndex(j)] ؟

سأكون على ما يرام مع ذلك.

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

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

على وجه التحديد. دعونا نتخلى عن هذا بالتأكيد.

-1 لإسقاط الإصدار 1D. من الطبيعي جدًا أن تدور حول جميع العناصر في مصفوفة متعددة الأبعاد باستخدام

for n=1:length(x)
  x[n] = ...
end

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

JeffBezanson ، أنا لا أتفق مع العبارة حول الإفراط في تعميم تحسين سابق لأوانه.

الفهرسة الخطية هي نظام الفهرسة _الطبيعي_ وأي شيء يوفر وصولاً متعدد الأبعاد هو في الواقع بعض البنية التحتية لتسهيل كتابة الكود أو تصميم خوارزمية على الشخص.
يبدو أن إزالة الفهرسة الخطية بعيدًا تمامًا أمر خاطئ بالنسبة لي ، وإدخال بناء جملة إضافي (مما يعني بالنسبة لي ، يجب أن أضرب المزيد من المفاتيح على REPL قبل الحصول على الإخراج) يبدو لي عبئًا إضافيًا ؛ a [i] خطي فقط ، [i ، j] هو بعد ؛ أين المشكلة؟

الآن ننتقل إلى المشكلة المثيرة التي بدأت هذا: امتلاك وصول aa [i، j] عندما يتم تعريف a في الواقع ثلاثي الأبعاد. لم أكن أدرك أن هذا موجود ، لكن في الواقع هذا شيء أود أن يكون في لغة ما.

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

بالطريقة التي أراها ، فإن الفهرسة الخطية هي مخطط الفهرسة الطبيعي بنفس المعنى الذي يجعل رمز الآلة هو لغة البرمجة الطبيعية: إنه اللغة الأساسية.

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

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

مجرد التفكير بصوت عالٍ: بالإضافة إلى eachindex ، يمكن أن تكون هناك أيضًا دالة eachelement تعرض مرجعًا لعنصر مصفوفة ، كما في

for xn in eachelement(x)
    xn = ...
end

يمكن أن يكون هذا المرجع شيئًا مثل مصفوفة فرعية صفرية الأبعاد.

ألا يجب أن يكون هذا xn[] = ... ؟

للوصول إلى القيمة فقط ، لدينا ذلك بالفعل من for x in X... .

صحيح ، كان يجب أن يكون xn[] .

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

يمكن أن يكون مفيدا.

: +1: إهمال هذا. لقد سميت هذه الفهرسة الخطية "الجزئية" من قبل - لست متأكدًا من أين التقطت تلك المصطلحات. تمت مناقشته في https://github.com/JuliaLang/julia/issues/13015 و https://github.com/JuliaLang/julia/issues/5396 ، وهي نقطة قمت بإدراجها كاحتمال في # 13157 .

سيكون هذا النوع من المكرر مفيدًا جدًا للمصفوفات المتفرقة حيث لا يُسمح بالوصول إلى المواقع غير الهيكلية (على سبيل المثال ، مصفوفات PETSc).

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

ربما أكون متحيزًا لأن ترميز matlab الخاص بي يتضمن في كثير من الأحيان فهرسة خطية على الرغم من أن البيانات منظمة في 2or3D ولدي نموذج عقلي للتعامل معها.

-1 آخر لإسقاط الإصدار 1D لنفس السبب مثل https://github.com/JuliaLang/julia/issues/14770#issuecomment -174262352.

ما عليك سوى الاحتفاظ بالإصدار 1D من الفهرسة الخطية وإزالة الفهرسة الخطية "الجزئية" imo.

أنا أيضا أحب أن أحصل على نسخة الفهرسة الخطية 1d والتخلص من الفهرسة الخطية الجزئية. هذا حل عاقل تماما.

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

toivoh ، لا ، لست من أجل التخلص من هذه الفهرسة الخطية الجزئية.

لهذا السبب قلت للجميع تقريبًا :)
هل هناك أي شخص آخر يريد الاحتفاظ بالفهرسة الخطية الجزئية؟

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

ق / خطي / جزئي خطي / في الجملة الأخيرة.

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

c[:,:,k]

حيث k هو رقم الشريحة. أواجه الآن بيانات رباعية الأبعاد (ثلاثية الأبعاد + الوقت) وأود إعادة استخدام بنيتي التحتية الحالية. في الوقت الحالي ، عندما يتم كتابة كل شيء بشكل بطة ، سيكون من السهل جدًا دفع مجموعة بيانات 4D والسماح بتجاوز k size(c,3) .

لدي شيء مشابه لما يلي في بعض كود matlab. نقوم بتقييم (لكل خطوة زمنية للمحاكاة / التكرار) علاقة AB في مصفوفة 2D NxN ونسجل (لـ postpro) مصفوفات NxN هذه في متجر TxNxN 3D. نظرًا لأن عملية النسخ تستند إلى find (الإبلاغ عن الفهرس الخطي) ، في جوليا يمكنني إجراء Tnn [time_step ، find (ABrelation)> = cell_limit)] = 1 ؛ ونعم ، أنا أعلم أنه يمكنني كتابة هذا كحلقة صريحة ولا ينبغي التفكير باستخدام كود matlab لبناء بيانات جوليا ...

tknopp ، مثال صالح مع توسيع الأبعاد ومحاولة الحفاظ على البنية التحتية.

بالنسبة لي ، يبدو أن مصفوفات NxN Vector ستكون بنية بيانات أفضل لحالة الاستخدام هذه.

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

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

باستخدام مصفوفة فرعية ، يمكن كتابة الرمز الخاص بك بالشكل sub(Tnn, time_step)[find(ABrelation) >= cell_limit] = 1 . هذا قصير تقريبًا ، وربما أوضح. عندما تصبح المشاهدات الافتراضية ، ستكون أقصر.

+1 مني آخر للسماح بالفهرسة الخطية للحالة 1D فقط.

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

ومن المثير للاهتمام ، أنه بمجرد أن تبدأ في استخدام المصفوفات الفرعية ، فلن تحتاج إلى العثور على الإطلاق (على افتراض أنك تعني في الواقع find(ABrelation .>= cell_limit) ):

sub(Tnn, time_step, :, :)[ABrelation .>= cell_limit] = 1

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

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

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

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

arr[:linear, i]
arr[Linear(i)]
linind(arr, i)

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

قد يكون من المنطقي أن يكون لديك عملية إعادة تشكيل مدمجة + getindex لتجنب تخصيص غلاف مُعاد تشكيله على الكومة

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

في # 5396 اكتشفت بنفسي أن استخدام الفهرسة الخطية الجزئية في matlab هو أن أكون قادرًا على السماح لـ setindex! إضافة أبعاد إلى المصفوفات بصمت. نظرًا لأن جوليا لا تسمح بذلك (phew!) ، فليس هناك سبب كبير لترك فهرسة خطية جزئية.

ما زلت أتساءل ، لماذا كان هذا هنا في المقام الأول (لم يكن لديك الوقت للبحث في سجلات git)؟

أنا مقتنع (من المناقشة أعلاه):
-1 للفهرسة الخطية الجزئية
+1 لإتاحة فهرسة خطية بدون بناء جملة إضافي (يجب أن يروي إدخال واحد في [v] القصة)

أنا أسمح فقط بالفهرسة باستخدام فهرس لكل بُعد أو فهرس واحد بالضبط.

أنا أيضا مؤيد.

carnaval يمكن اشتقاق تدوين لذلك من التعليق التوضيحي لمعلمات نوع البعد كما في A{3,3}[i,j] وربما A{}[i] للفهرسة الخطية

أفترض أن الفهرسة الخطية ستستخدم دائمًا النطاق 1:length(A) .

كيف سيعمل هذا ، على سبيل المثال ، مع النواقل المتفرقة؟ لا توجد طريقة بديهية للتمييز بين A[regular_index] و A[linear_index] . وبالمثل بالنسبة للمتجهات حيث لا يكون الحد الأدنى 1 . قد تكون هناك حاجة إلى صيغة خاصة (مثل A[:linear, i] ).

ما هي المشكلة التي تحاول حلها باستخدام بناء جملة إضافي للفهرسة الخطية؟

هناك ثلاثة:
(1) باستخدام مصفوفة M ، كتابة M[i] بطريق الخطأ بدلاً من M[i,j] ، أي ترك فهرس ؛ مع بناء جملة خاص للفهرسة الخطية ، فسيتم اكتشاف ذلك.
(2) إذا كان لديك متجه صفري (غير موجود في Base ، ولكنه مناسب في بعض الحالات) ، فإن الفهرسة العادية تبدأ من 0 ، بينما يتوقع الأشخاص أن تبدأ الفهرسة الخطية دائمًا من 1. بدون صيغة خاصة ، لا توجد وسيلة للتمييز بين هذين. وينطبق الشيء نفسه على أي مصفوفة أحادية البعد تتصرف بشكل مختلف عن Vector ؛ يمكنك أيضًا التفكير في عرض "نافذة" في متجه حيث لا تبدأ الفهرسة عند 1.
(3) إن استخدام فهرس خطي واحد بدلاً من نطاقات الفهرس المعلنة مع المصفوفة ليس شيئًا متاحًا بشكل شائع في العديد من اللغات (دون إنشاء مثل هذا العرض بشكل صريح) ، وبالتالي سيكون مربكًا للمبتدئين.

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

(2) هو افتراض افتراضي. أي مصفوفة M يمكن اعتبارها حاوية وبالتالي يمكن اجتيازها باستخدام M[1:length(M)] . هذا هو سبب وجود length في المقام الأول.

(3) ما هي اللغات التي لا تملك هذه الميزة في ذهنك؟ بالطبع لا يتم احتساب هنا سوى اللغات ذات المصفوفات المتعددة المضمنة.

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

بالنسبة إلى (2) ، راجع على سبيل المثال https://github.com/eschnett/FlexibleArrays.jl. إذا قمت بتعريف مصفوفة 1d بنطاق فهرس 0:9 ، فلن تعمل فهرستها بـ M[1:length(M)] . (بالطبع ما زلت تريد أن تكون قادرًا على فهرستها بهذه الطريقة ، ولهذا السبب تحتاج إلى بناء جملة خاص.)

بالنسبة إلى (3) ، كانت وجهة نظري "بدون تقديم وجهة نظر صراحة". لا يهم ما إذا كانت المصفوفات مضمنة أو محددة في مكتبة. أفكر على سبيل المثال في Fortran و C و C ++ و Mathematica و Python. كلها تسمح بالفهرسة الخطية ، وكلها تتطلب إما بناء جملة خاص أو بناء لاستخدام الفهرسة الخطية مع مصفوفة متعددة الأبعاد.

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

(3) حسنًا ، لقد رأيت للتو أن Python / Numpy تتعامل مع هذا بشكل مختلف. لا تحتوي C / C ++ على مصفوفات خافتة متعددة بالمعنى الذي نستخدمه في Julia.

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

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

لذلك ، يستخدم المرء الأعداد الصحيحة كعلامات مجردة لجميع عناصر المصفوفة.

بخصوص C و C ++: يمنحك double array[2][2] مصفوفة ثنائية الأبعاد. للحصول على عرض أحادي الأبعاد ، اكتب (double*)&array[0][0] : هذا ممكن ، لكن ليس بشكل ضمني.

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

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

لقد لعبت مع بعض الحاويات من هذا القبيل بنفسي ... وتوصلت إلى استنتاج مفاده أنه من الخطير جدًا ببساطة تصنيف AbstractArray إذا كانت الفهرسة بالأعداد الصحيحة تعني أي شيء بخلاف الوصول إلى عنصر داخل 1:size(A,d) . هناك عدد كبير جدًا من طرق المصفوفات المجردة التي تفترض أن هذه الوصول واردة ، وبالتالي تقوم بإيقاف فحص الحدود. يساعد eachindex البعض ، لكنه لا يقودنا إلى هناك.

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


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

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

لنبدأ بإهمال الفهرسة الخطية الجزئية وأبعاد الأحادية المفردة

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

function sumcolumns(A::AbstractVecOrMat)
    m, n = size(A, 1), size(A, 2)
    s = zeros(accum(eltype(A)), 1, n)
    for j = 1:n
        z = s[1,j]
        for i = 1:m
            z += A[i,j]
        end
        s[1,j] = z
    end
    s
end

والتي قد تنكسر لمدخلات Vector إذا تخلصنا من الزائدة المفردة.

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

لذلك يبدو أن بعض الناس مغرمون حقًا بهذه الميزة (خلفية Matlab) ، بينما لم يعتاد عليها الآخرون ويجدونها غريبة (خلفية Python / C / Fortran).

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

لقد قمت مؤخرًا بتطبيق موجهات SIMD كنوع بيانات https://github.com/eschnett/SIMD.jl ، ثم كانت لدي فكرة لجعلها أنواعًا فرعية من DenseArray{T,1} . لدهشتي ، هذا كسر الأمثلة الموجودة في الملف التمهيدي الخاص بي - يحاول REPL متجهات الإخراج كمصفوفات (بالطريقة نفسها التي تصفها أعلاه) ، مما أجبرني على دعم معالجة متجهات SIMD كمصفوفات ثنائية الأبعاد. نواقل SIMD بطبيعتها ليست متعددة الأبعاد ؛ في الواقع ، فإن فهرستها عادةً ما تكون باهظة الثمن ، ولن يكون دعم العرض متعدد الأبعاد مفيدًا لأي مستخدم فعلي.

إذن - ما المقصود بـ "المصفوفة المجردة أحادية البعد" AbstractVector في جوليا؟ هل هو تعميم لجميع أنواع المصفوفات أحادية الأبعاد أم أنها مصفوفة متعددة الأبعاد دائمًا؟ إذا كان الأمر كذلك ، فهل يجب أن يكون هناك نوع مجردة آخر في Julia للحالات التي تظل فيها المصفوفات 1d دائمًا 1d

يمكنك حاليًا معالجة النطاقات كمصفوفات: (1:10)[4,1] .

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

غالبًا ما يكون هذا صحيحًا ، ولكن في هذه الأيام أجد أنه يمكنني القيام بمعظم الأشياء متعددة الأبعاد الآن فقط باستخدام التكرارات الديكارتية. إذا لم تكن معتادًا على هذا ، فإن AxisAlgorithms و base/reducedim.jl نماذج جيدة.

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

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

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

الآن بعد أن فكرت في هذا ، لدي شعور بأن هذا من شأنه أن يبسط شفرتى بشكل كبير.

أعتقد أنك تخلط بين Base.Cartesian وبين مؤشر CartesianIndex / CartesianRange. لا توجد وحدات ماكرو إذا كنت تستخدم الأخير. في الكود الذي قمت بربطه ، لا توجد وحدات ماكرو ، ولا يزال بإمكانك القيام بأشياء مذهلة: ابتسم:.

شكرا للمؤشر. لم أكن على علم بالفرق.

هل هناك طريقة لسرد جميع الدوال في REPL التي تحتوي على CartesianIndex أو CartesianRange كمدخلات أو مخرجات؟

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

هل هناك طريقة لسرد في REPL جميع الوظائف التي لها مؤشر ديكارتي أو CartesianRange كمدخل أو إخراج؟

هل methodswith(CartesianIndex) ما تبحث عنه؟ الأفضل!

D'oh. شكر.

eschnett ، لم تكن أول شخص يبدو أنه مرتبك بهذا الاختلاف. كان ذلك كافيًا لدفعني أخيرًا إلى كتابة منشور مدونة:
https://github.com/JuliaLang/julialang.github.com/pull/324

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

JeffBezanson ، بناء على ماذا؟

lobingera ، إذا قرأت هذا الموضوع ، فهناك رأي أغلبية واضح جدًا. لا أعرف أي خطط لاستبعاد _ all_ الفهرسة الخطية ، هذا يتعلق فقط بالحالة "الجزئية" أو "العامة". ويبدو أن AFAICT لا توجد مقاومة للخطة في https://github.com/JuliaLang/julia/issues/14770#issuecomment -174212684 ، لذا إذا تم تبنيها فلن تخسر شيئًا.

بالنظر إلى ذلك ، هل يمكنك توضيح مخاوفك؟

هل هناك خطة أو اقتراح لفهرسة خطية للمصفوفات حيث لا تكون الحدود السفلية 1 ؟ أود تطبيق هذا لـ https://github.com/eschnett/FlexibleArrays.jl.

فكرتي الحالية هي تحديد نوع immutable LinearIndex i::Int end ، واستخدامه للفهرسة الخطية ، بافتراض أن الفهرس الخطي i=1 يجب أن يكون أول عنصر مصفوفة.

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

إذا كان لدي مصفوفة 1D بها نطاق فهرس 0:9 ، كيف يمكنني استخدام فهرس ديكارت لتمثيل فهرس خطي؟ يمثل CartesianIndex((1,)) الواضح بالفعل فهرسًا عاديًا يشير إلى العنصر الثاني ، و CartesianIndex((10,)) هو بالفعل خطأ خارج الحدود.

فقط تخصص getindex(A::FlexibleArray, ::CartesianIndex) لتحصل على الترجمة الفورية التي تريدها.

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

getindex(A::FlexibleVector, i::CartesianIndex{1}) = … # interpretation of index as 1:end
getindex(A::FlexibleArray, i::CartesianIndex{1}) = A[CartesianIndex(ind2sub(size(A), i[1]))]

؟

أرغب بالفعل في تفسير الفهرس الديكارتي على أنه مؤشر عادي (يعتمد على الشكل) لأن المؤشرات الديكارتية ملائمة جدًا لحسابات الفهرس.

آها ، نحن نتحدث عن بعضنا البعض. عندما كنت أتحدث عن الفهرسة الديكارتية أعلاه ، لم أكن أعني فقط مؤشرًا واحدًا أو أكثر ، ولكن كل مؤشر يبدأ من 1:size(A, d) . إذا كنت تريد دعم الفهرسة الخطية ، فستحتاج إلى استخدام نوع خاص وتنفيذ قواعد فهرسة خاصة ، بغض النظر عن أي شيء. إذا كنت تستخدم CartesianIndex لتعني عالميًا الفهرسة القائمة على 1 ، فلن تحتاج بعد الآن إلى تخصيص كل فهرس ، وسيظل الرمز الذي يستخدم CartesianRanges صريحًا يعمل. أعتقد أنه طريق أقل إيلامًا شخصيًا.

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

أقترح تفسيرًا لـ CartesianIndex نفترضه بالفعل في Base: أن المؤشرات هي دائمًا على أساس 1. من خلال الموافقة على هذا التفسير ، تصبح المصفوفات المرنة الخاصة بك فجأة مثل أي مصفوفة LinearSlow أخرى ... ولا تتطلب أنواعًا أو مصطلحات جديدة. أعتقد أنه سوف يتحسن عندما نقوم بتنقيح مصطلحات تكرار الفهرس. أعتقد أن هذا يجعل توحيد المعايير جيدًا.

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

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

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

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

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

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

lobingera ، هذا التغيير آمن تمامًا ، على حد

نقوم بتشغيل PkgEval بانتظام على النظام البيئي للحزمة بالكامل لقياس تأثير التغييرات. بالنسبة لتغيير وظائف jb / ، على سبيل المثال ، بذلJeffBezanson جهودًا كبيرة للتأكد من أن معظم الحزم ستكون قادرة على مواصلة العمل ، بما في ذلك تقديم طلبات سحب لإصلاحها. لم يكن بالطبع 100٪ ، لكن هذا شيء ندركه ونهتم به.

بالنسبة للأسباب الفنية للتخلص من الفهرسة الخطية الجزئية:

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

كل هذه النقاط مجتمعة مع الإجماع العام هنا على أنه يجب أن تذهب ، تبدو كافية لإيقاف الفهرسة الخطية الجزئية في 0.5 وإزالتها في 0.6.

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

إذا كنتم (جميعًا) ترى هذا ضروريًا لتبسيط الإصدار 0.5 ، فمن أنا لا أوافق؟

أنا أقدر مخاوفك وأنك تخصص وقتًا للتعبير عنها هنا. يمكن أن يكون نقل الأشياء إلى الأمام مؤلمًا بالتأكيد.

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

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

هل لدينا خطة تنفيذ مقترحة لكيفية القيام بذلك؟

مع # 11242 أعتقد أنه يجب أن يكون واضحًا ومباشرًا. قد نرغب في تقديم طريقة sub2sub تشبه ind2sub ولكنها تأخذ مجموعة فهرس خطي جزئي بدلاً من فهرس خطي عددي للسماح باستبدال بسيط في طريقة الإهلاك.

getindex(::AbstractArray, ::Int) = # linear
getindex{T,N}(::AbstractArray{T,N}, ::Vararg{Int, N}) = # cartesian
<strong i="8">@deprecate</strong> getindex(A::AbstractArray, I::Int...) getindex(A, sub2sub(size(A), I)...)

لاحظ ، مع ذلك ، أن هذا من شأنه _ أيضًا_ إهمال أبعاد الزائدة المفردة.

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

سيكون من الجيد التفكير في الرمز الذي سيحل محل هذا.

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

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

mbauman هل لديك بدايات فرع أو شيء يمكننا أن نبدأ منه؟ إذا كان الأمر يتعلق فقط بحل تحذيرات الإهمال (ولكن الكثير منها) ، فسيبدو من السهل توزيعها ، ولكن من يعرف أيضًا كيف يبدأ هذا؟

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

هذا غير متوقع ... فضولي لمعرفة أين / ما هم ، ربما أغفلت هذه المناقشة شيئًا ما

قد نتمكن من التعامل مع الإهمالات عن طريق إضافة LinearIndex(i) المسموح به فقط في الخانة الأخيرة. بشكل ساذج يبدو أنه يتطلب Vararg في منتصف قائمة الوسيطات ، ولكن في هذه الأيام يمكننا ترتيبها إما مع الدوال المُنشأة أو مجموعة هشة من Base.front و @inline ( للأداء).

أعتقد أنني أفضل استخدام reshape على المصفوفة التي تتم فهرستها. بهذه الطريقة سيكون أكثر أداءً للمصفوفات البطيئة الخطية أيضًا. ربما نحتاج إلى طريقة مختصرة للتعبير عن reshape A to have N dimensions عن طريق إضافة أبعاد مفردة لاحقة أو طي الأبعاد الأخيرة.

إنها أيضًا طريقة لطيفة للتعبير عن الخوارزمية في DSP.jl التي أشار إليها ستيفن أعلاه.

ما هو موقفنا من هذا الآن مع دمج # 16251؟ هل هي النقطة التي يكون فيها الجزء الأساسي من التغيير سهلاً والباقي مسألة مطاردة إهمال يمكن للعديد من الأشخاص المشاركة فيها؟

نعم ، يجب أن يكون الأمر بسيطًا إلى حد ما الآن.

  • انقل الأساليب التي حددتها للإهمال ، وأضف تحذيرات الإيقاف. في بلدي اختبار سريع أعلاه، لاحظت بعض التصرفات متزعزع مع depwarn في REPL لأنها تعتمد على كومة ... و getindex inlines مثل مجنون، لذلك هناك ببساطة ليس كثيرا من كومة. لذلك قد يأخذ هذا بعض الاعتبار.
  • احترس من الإرسال المفاجئ بين الطرق من النموذج getindex(A::Array, I::Int…) و getindex{T,N}(A::Array{T,N}, I::Vararg{Int, N}) . قد تحتاج إلى إضافة بعض الوظائف الصريحة غير المهملة من أجل الحفاظ على السلوك الذي نريده غير مهمل. ما زلت أضعها في deprecations.jl ، رغم ذلك ، لأنها ستكون ضرورية فقط طالما كانت الإهمالات موجودة. مزعج بعض الشيء ، لكنه ليس صعبًا للغاية.
  • قم بالمرور عبر القاعدة والاختبارات ، مضيفًا إعادة تشكيل في كل مكان لتتناسب مع عدد المؤشرات وتجعل جوليا سعيدة: reshape(A, Val{3})[i, j, k] .

ما هو مطلوب هنا هو أن يبدأ شخص ما ( mbauman ، حتى لو فشلت الاختبارات. يمكن للآخرين بعد ذلك المتابعة عن طريق تحديد الاختبارات المختلفة والاستخدامات الأخرى للفهرسة الخطية المعممة.

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

بالنسبة لما يستحق ، يتطلب التطبيق الأكثر مباشرة هنا # 18457 لأنه يعمل على إصلاح طريقة فرز الخلل باستخدام Varargs بطول محدد.

نظرًا لأن # 18457 جاهز تقريبًا (هل يمكننا دمجه بعد؟) ، دعنا ننتظر ذلك ثم نفعل ذلك.

التحديث بالترتيب هنا. لقد تحدثنا عن شيئين مختلفين تمامًا في هذا الموضوع ، مع تشعبات مختلفة:

  1. استنكر الخطية لأي بعد يتجاوز الأول. هذا ما فعلته في # 20079. ملاحظة أنه لا يزال يسمح فهرسة إلى N صفيف الأبعاد مع أقل من N المؤشرات. بمجرد إجراء هذا التغيير ، سنكون قادرين على تبسيط تخفيض A[i, end] ببساطة لاستخدام size(A, 2) - وأعتقد أنه يمكننا التخلي عن Base.trailingsize تمامًا. وبالمثل ، لن نحتاج بعد الآن إلى الاهتمام بالحالات الخاصة لتخلف : s وراء الحالة المفردة A[:] . والجدير بالذكر أن هذا أثر فقط على رمز الاختبار الذي تم تصميمه خصيصًا لاختبار هذا السلوك.
  2. توقف عن الفهرسة في المصفوفات ذات الأبعاد N مع أي شيء عدا المؤشرات 1 أو N . هذا ما جربته في # 20040 ، وهو أمر مزعج للغاية لأنه يزيل القدرة على الفهرسة في متجهات مع زائدة 1 s. يتطلب هذا التغيير الانحناء للخلف للتأكد من أننا نحدد فقط الفهرسة بأبعاد 1 أو N. بينما أفترض أنه يمكننا نظريًا إهمال الفهرسة بمؤشرات 1 < n < N ولكن مع الاستمرار في تتبع الأبعاد المفردة ، فإن تحديد ذلك مع الإرسال سيتطلب دعمًا لتوقيع جديد: getindex{N}(A::AbstractArray{T,N} where T, I::Vararg{Int, N}, trailing_singletons::Int…) .

أنا مع التغيير الأول ، ولكن ضد التغيير الثاني.

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

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

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

إن ترددي بشأن مؤشرات only-1-or-N-ليس فقط أنه يتطلب الكثير من التغييرات على الكود الحالي ، بل إنه _أيضًا_صعوبة في التنفيذ والتنفيذ. هل كان هذا تبسيطًا صافياً بشكل أكثر اتساقًا (على كلا الجانبين) ، فأعتقد أنني سأجده أكثر جاذبية.

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

لا يمكنني التحدث عن صعوبة التنفيذ ، ولكن إذا كنا نعطي الأولوية لتجربة المستخدم ، فإن تقديم عدد خاطئ من المؤشرات عن غير قصد يعد فخًا مؤسفًا حاليًا. نتلقى شكاوى حول هذا في JuMP: https://github.com/JuliaOpt/JuMP.jl/issues/937

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

الانتقال إلى معلم الآن بعد دمج # 20079.

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

أحتاج إلى قضاء بعض الوقت للحصول على https://github.com/JuliaLang/julia/pull/21750 . ثم يمكننا التحدث عن الخطوات التالية هنا. أؤيد تشديد جولة أخيرة لفحص الحدود هنا ، بحيث لا نسمح إلا بأبعاد زائدة محذوفة عندما يكون حجم هذه الأبعاد المحذوفة هو 1 .

مع دمج https://github.com/JuliaLang/julia/pull/21750 ، أعتقد أنه لا يوجد سوى عدد قليل من حالات الفهرسة الصغيرة التي لا تزال بحاجة إلى إهمالها هنا.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات