outer تسطّح المصفوفتين قبل الضرب. [1]
اختر معنى المحاور
outer تسطّح المدخلين؛ multiply.outer تحتفظ بمحاورهما في الناتج. [1][2]
المقصود بالتسطيح هنا جمع عناصر المدخل في تسلسل ذي محور واحد. outer تضرب كل عنصر من التسلسل الأول في كل عنصر من الثاني؛ أما صيغة ufunc.outer فتجمع محاور المدخلين في وصف الناتج. [1][2]
نختار مدخلين لهما محوران، ثم نقرأ القيم والعناوين معًا. الأعداد مؤلفة بلا وحدة. لا نستخدم كلمة «خارجي» وحدها لتحديد شكل الاستدعاء الذي نريده.
ستة عشر ناتجًا بعناوين مختلفة
أنشأنا A=np.array([[3,-1],[-4,2]],dtype=np.int64) وB=np.array([[2,5],[-2,7]],dtype=np.int64)، في NumPy 2.3.5 على CPython 3.12.14. شكل كل منهما (2,2)، وفهارسنا تبدأ من 0.
نفذنا O=np.outer(A,B). سجلنا الشكل (4,4) والنوع int64، والقيم [[6,15,−6,21],[−2,−5,2,−7],[−8,−20,8,−28],[4,10,−4,14]].
في هذا التشغيل قرأنا عناصر A بالترتيب [3,−1,−4,2] وعناصر B بالترتيب [2,5,−2,7]. الصف الأول من O هو ضرب 3 في العناصر الأربعة للثاني؛ والصف الثالث ضرب −4 فيها. لا نجمع هذه النواتج في عدد واحد.
ثم نفذنا U=np.multiply.outer(A,B). سجلنا النوع int64 والشكل (2,2,2,2). لكل اختيار (i,j) من A لوحة صغيرة هي A[i,j] مضروبة في B: لوحة 3 هي [[6,15],[−6,21]]، ولوحة −1 هي [[−2,−5],[2,−7]]، ولوحة −4 هي [[−8,−20],[8,−28]]، ولوحة 2 هي [[4,10],[−4,14]].
كل ناتج يحتوي 16 عنصرًا. تختلف طريقة عنونة المنتجات؛ لم يفقد التشغيل أربعة منتجات لكي يحول أربعة محاور إلى محورين. لذلك نسجل شكل الناتج بجانب القيم، ولا نكتفي بعدد العناصر.
وصل الفهارس وتحكم بالتجميع
عقد ufunc.outer يجعل محاور A تسبق محاور B في عنوان الناتج. [2]
في مثالنا نكتب U[i,j,k,l]=A[i,j]×B[k,l]. حسب مرجعنا، العنوان الموافق في جدول O هو (2i+j,2k+l)، حيث الفهارس الأربعة بين 0 و1. اختبرنا المطابقة في الخانات الست عشرة، ولم نعتمد على تساوي خانة منفردة.
مثلًا A[1,0]=−4 وB[0,1]=5، لذلك U[1,0,0,1]=−20. فهرس صف O الموافق هو 2×1+0=2، وفهرس عموده 2×0+1=1؛ قرأنا O[2,1]=−20. أما O[1,2]=2 فهو ضرب −1 في −2؛ قلب الفهرسين يعطي منتجًا آخر في هذا المثال.
أنشأنا متجهين صريحين من int64: av=[3,−1,−4,2] وbv=[2,5,−2,7]. أعادت np.multiply.outer(av,bv) القيم نفسها التي سجلناها في O، بالنوع int64 والشكل (4,4). هذا تحكم يبدأ بمدخلين ذوي محور واحد.
وشغّلنا G=U.reshape((4,4),order="C"). سجلنا أيضًا جدول O نفسه من int64. جمع هذا الطلب أول فهرسين للصف وآخر فهرسين للعمود في مثالنا؛ لا نقول إن كل إعادة تشكيل ممكنة تحفظ العنوان المقصود.
هذه فحوص للقيم والفهارس. لم نكتب في G أو U ولم نفحص استقلال الذاكرة أو مشاركتها، فلا نستنتج منهما أن إعادة التشكيل صنعت نسخة مستقلة.

تحكم بالترتيب ونطاق الاختبار
نفذنا T=np.outer(A,B.T). قرأنا [[6,−6,15,21],[−2,2,−5,−7],[−8,8,−20,−28],[4,−4,10,14]] من int64 وشكل (4,4).
مرجع هذا التحكم قرأ B عمودًا كاملًا ثم العمود التالي: [2,−2,5,7]. لذلك انتقلت 15 في الصف الأول من العمود 1 إلى العمود 2، و−6 من العمود 2 إلى العمود 1. بقاء الشكل (4,4) لم يمنع تغير القيم التي نجدها عند عنوان ثابت.
قارنا بايتات A وB الأصليتين قبل جميع الاستدعاءات وبعدها فبقيت متطابقة. لا نخلط تطبيق منقول في مدخل استدعاء مع كتابة تغيّر قيم B الأصلية.
مرجعنا يبني القوائم من فهارس Python ويضرب أعدادًا صحيحة فقط. يجمع قائمة الصف الأول ثم الثاني للمرجع الأول، ويبني أربع قوائم متداخلة للمرجع الآخر. لا يستدعي outer أو multiply.outer أو ravel أو reshape أو transpose داخل حساب المرجع.
عددنا كل مدخل من أربعة عناصر تأخذ القيم من {−2,0,3}: لدينا 3**4=81 مدخلًا لكل طرف، أي 81×81=6561 زوجًا. الأعداد والنواتج صغيرة وتدخل int64 في النطاق المختبر.
لكل زوج ستة فحوص: قيم ونوع وشكل outer؛ وقيم ونوع وشكل multiply.outer مع المطابقة الرباعية؛ والتحكم بمتجهين صريحين؛ وتجميع U بترتيب C؛ والتحكم بمنقول B مقابل قراءة مرجعية حسب الأعمدة؛ وثبات بايتات المصدرين. أضفنا الستة نفسها للمثال المعروض، فالإجمالي 6561×6+6=39372، ومرت جميعها.
استبعدنا الأشكال والأنواع الأخرى، والمدخلات المفردة والفارغة، والتخطيطات والخطوات الأخرى عدا تحكم B.T المحدد، والعائمة والمركبة وNaN وتجاوز المجال وout والفئات المشتقة. لم نفحص الأداء أو حجم الذاكرة أو الكتابة عبر مخازن مشتركة.
اختر الاستدعاء وفق العناوين المطلوبة في الخطوة التالية. في هذا المثال المنتجات نفسها لها وصف ذو أربعة محاور أو جدول ذو محورين، ويظل ترتيب قراءة المدخل جزءًا من المقارنة.
| الاستدعاء | الشكل المسجل | خانة من المثال |
|---|---|---|
| O = np.outer(A,B) | (4,4) | O[2,1] = -20 |
| U = np.multiply.outer(A,B) | (2,2,2,2) | U[1,0,0,1] = -20 |
| U.reshape((4,4),order="C") | (4,4) | G[2,1] = -20 |
| T = np.outer(A,B.T) | (4,4) | T[2,1] = 8 |
للتوسع: المتجهات والمصفوفات.
المراجع
أُعدّ هذا المقال بمساعدة الذكاء الاصطناعي، وخضع لمراجعة ذاتية بالأداة نفسها. لا يُنسب إلى مراجع بشري أو خبير مستقل. منهجية المحتوى.
