خوارزمية كاراتسوبا

عملية كاراتسوبا لضرب az+b و cz+d (المؤطرة)، و 1234 و 567 مع z=100. تشير الأسهم الأرجوانية إلى الضرب، والصفراء إلى الجمع، والفضية إلى الطرح، والسماوية إلى الإزاحة إلى اليسار. تُظهر الأشكال (أ) و(ب) و(ج) عملية التكرار مع z=10 للحصول على القيم الوسيطة.

خوارزمية كاراتسوبا هي خوارزمية ضرب سريعة للأعداد الصحيحة . اكتشفها أناتولي كاراتسوبا عام 1960 ونُشرت عام 1962. [ 1 ] [ 2 ] [ 3 ] وهي خوارزمية فرق تسد، تُختزل عملية ضرب عددين مكونين من n خانة إلى ثلاث عمليات ضرب لأعداد مكونة من n /2 خانة، وبتكرار هذا الاختزال، إلى عدد لا يتجاوز n /2 خانة.نسجل23ن1.58{\displaystyle n^{\log _{2}3}\approx n^{1.58}}عمليات الضرب المكونة من رقم واحد. ولذلك فهي أسرع بشكل تقاربي من الخوارزمية التقليدية ، التي تؤدين2{\displaystyle n^{2}}المنتجات ذات الرقم الواحد.

كانت خوارزمية كاراتسوبا أول خوارزمية ضرب أسرع تقاربياً من خوارزمية "المدرسة الابتدائية" التربيعية. وتُعد خوارزمية توم-كوك (1963) تعميماً أسرع لطريقة كاراتسوبا، بينما تُعد خوارزمية شونهاج-ستراسن (1971) أسرع منها، وذلك عند قيم n الكبيرة بما فيه الكفاية .

تاريخ

تتطلب الطريقة القياسية لضرب عددين مكونين من n خانة عددًا من العمليات الأولية يتناسب معن2{\displaystyle n^{2}\,\!}، أويا(ن2){\displaystyle O(n^{2})\,\!}باستخدام ترميز Big-O . افترض أندريه كولموغوروف أن الخوارزمية التقليدية هي الأمثل تقاربياً ، مما يعني أن أي خوارزمية لتلك المهمة ستتطلبΩ(ن2){\displaystyle \أوميغا (n^{2})\,\!}العمليات الحسابية الأساسية.

في عام 1960، نظم كولموغوروف ندوة حول المسائل الرياضية في علم التحكم الآلي في جامعة موسكو الحكومية ، حيث ذكرΩ(ن2){\displaystyle \أوميغا (n^{2})\,\!}التخمينات وغيرها من المشكلات في تعقيد الحساب . في غضون أسبوع، وجد كاراتسوبا، الذي كان طالبًا يبلغ من العمر 23 عامًا آنذاك، خوارزمية تضرب عددين مكونين من n رقمًا فييا(نسجل23){\displaystyle O(n^{\log _{2}3})}بخطوات أولية، دحض بذلك الفرضية. كان كولموغوروف متحمسًا للغاية لهذا الاكتشاف؛ فأعلن عنه في الاجتماع التالي للندوة، التي اختُتمت بعد ذلك. ألقى كولموغوروف بعض المحاضرات حول نتيجة كاراتسوبا في مؤتمرات حول العالم (انظر، على سبيل المثال، "وقائع المؤتمر الدولي للرياضيات 1962"، الصفحات 351-356، وأيضًا "6 محاضرات أُلقيت في المؤتمر الدولي للرياضيات في ستوكهولم، 1962")، ونشر الطريقة في عام 1962، في وقائع أكاديمية العلوم في الاتحاد السوفيتي . كان المقال من تأليف كولموغوروف، وتضمن نتيجتين في الضرب، خوارزمية كاراتسوبا ونتيجة منفصلة ليوري أوفمان ؛ وقد ذُكر فيه "أ. كاراتسوبا وي. أوفمان" كمؤلفين. لم يعلم كاراتسوبا بالورقة البحثية إلا عندما تلقى نسخًا منها من الناشر. [ 2 ]

الخوارزمية

الخطوة الأساسية

المبدأ الأساسي لخوارزمية كاراتسوبا هو فرق تسد ، باستخدام صيغة تسمح بحساب حاصل ضرب عددين كبيرينx{\displaystyle x}وy{\displaystyle y}باستخدام ثلاث عمليات ضرب لأعداد أصغر، كل منها يحتوي على نصف عدد الأرقام تقريبًاx{\displaystyle x}أوy{\displaystyle y}بالإضافة إلى بعض عمليات الجمع وإزاحة الأرقام. هذه الخطوة الأساسية هي في الواقع تعميم لخوارزمية ضرب الأعداد المركبة المماثلة ، حيث يتم استبدال الوحدة التخيلية i بقوة من قوى الأساس .

يتركx{\displaystyle x}وy{\displaystyle y}يتم تمثيله على النحو التالي:ن{\displaystyle n}سلاسل مكونة من - أرقام في نظام أساسي ماب{\displaystyle B}لأي عدد صحيح موجبم{\displaystyle m}أقل منن{\displaystyle n}يمكن كتابة الرقمين المعطاينين ​​على النحو التالي:

x=x1بم+x0،{\displaystyle x=x_{1}B^{m}+x_{0},}
y=y1بم+y0،{\displaystyle y=y_{1}B^{m}+y_{0},}

أينx0{\displaystyle x_{0}}وy0{\displaystyle y_{0}}أقل منبم{\displaystyle B^{m}}ثم يصبح المنتج

xy=(x1بم+x0)(y1بم+y0)=x1y1ب2م+(x1y0+x0y1)بم+x0y0=z2ب2م+z1بم+z0،{\displaystyle {\begin{aligned}xy&=(x_{1}B^{m}+x_{0})(y_{1}B^{m}+y_{0})\\&=x_{1}y_{1}B^{2m}+(x_{1}y_{0}+x_{0}y_{1})B^{m}+x_{0}y_{0}\\&=z_{2}B^{2m}+z_{1}B^{m}+z_{0},\\\end{aligned}}}

أين

z2=x1y1،{\displaystyle z_{2}=x_{1}y_{1},}
z1=x1y0+x0y1،{\displaystyle z_{1}=x_{1}y_{0}+x_{0}y_{1},}
z0=x0y0.{\displaystyle z_{0}=x_{0}y_{0}.}

تتطلب هذه الصيغ أربع عمليات ضرب، وكانت معروفة لتشارلز باباج . [ 4 ] لاحظ كاراتسوبا أنxy{\displaystyle xy}يمكن حسابها بثلاث عمليات ضرب فقط، مع إضافة بضع عمليات جمع إضافية.z0{\displaystyle z_{0}}وz2{\displaystyle z_{2}}كما كان من قبل وz3=(x1+x0)(y1+y0)،{\displaystyle z_{3}=(x_{1}+x_{0})(y_{1}+y_{0}),}يلاحظ المرء أن

z1=x1y0+x0y1=x1y0+x0y1+x1y1+x0y0-x1y1-x0y0=(x1+x0)(y1+y0)-x1y1-x0y0=z3-z2-z0.{\displaystyle {\begin{alignat}{2}z_{1}&=x_{1}y_{0}+x_{0}y_{1}\\&=x_{1}y_{0}+x_{0}y_{1}+x_{1}y_{1}+x_{0}y_{0}&&-x_{1}y_{ 1}-x_{0}y_{0}\\&=(x_{1}+x_{0})(y_{1}+y_{0})&&-x_{1}y_{1}-x_{0}y_{0}\\&=z_{3}-z_{2}-z_{0}.\\\end{alignat}}}

وبالتالي، لا يلزم سوى ثلاث عمليات ضرب لإجراء الحسابz0،z1{\displaystyle z_{0},z_{1}}وz2،{\displaystyle z_{2},}وبالتاليxy.{\displaystyle xy.}

يستخدم شكل بديلz4=(x1-x0)(y1-y0){\displaystyle z_{4}=(x_{1}-x_{0})(y_{1}-y_{0})}بدلاً من:

z1=x1y1+x0y0-(x1y1-x0y0+x1y0+x0y1=x1y1+x0y0-(x1y1-x0y0+x1y0+x0y1=x1y1+x0y0-(x1y1+x0y0-x1y0-x0y1)=x1y1+x0y0-(x1-x0)(y1-y0)=z2+z0-z4.{\displaystyle {\begin{align}z_{1}&={\phantom {x_{1}y_{1}+x_{0}y_{0}-(x_{1}y_{1}-x_{0}y_{0}+{}}}x_{1}y_{0}+x_{0}y_{1}\\&=x_{1}y_{1}+x_{0}y_{0}-{\phantom {(}}x_{1}y_{1}-x_{0}y_{0}+x_{1}y_{0}+x_{0}y_{1}\\&=x_{1}y_{1}+x_{0}y_{0}-(x_{1}y_{1}+x_{0}y_{0}-x_{1}y_{ 0}-x_{0}y_{1})\\&=x_{1}y_{1}+x_{0}y_{0}-(x_{1}-x_{0})(y_{1}-y_{0})\\&=z_{2}+z_{0}-z_{4}.\\\end{محاذاة}}}

مثال

لحساب حاصل ضرب 12345 و 6789، حيث B = 10، اختر m = 3. نستخدم m إزاحة لليمين لتحليل معاملات الإدخال باستخدام الأساس الناتج ( B m = 1000 )، كما يلي:

12345 = 12 × 1000 + 345
6789 = 6 × 1000 + 789

يتم استخدام ثلاث عمليات ضرب فقط، والتي تعمل على أعداد صحيحة أصغر، لحساب ثلاث نتائج جزئية:

z 2 = 12 × 6 = 72
z 0 = 345 × 789 = 272205
ض 1 = ( 12 + 345 ) × ( 6 + 789 ) − ض 2ض 0 = 357 × 795 − 72 − 272205 = 283815 − 72 − 272205 = 11538

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

النتيجة = · ( Bm ) ² + · ( Bm ) ¹ + z⁰ · ( Bm ) ، أي
النتيجة = 72 × 1000 2 + 11538 × 1000 + 272205 = 83810205 .

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

تطبيق متكرر

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

في حاسوب مزود بمضاعف كامل 32 بت × 32 بت ، على سبيل المثال، يمكن اختيار B = 2^ 31 وتخزين كل رقم ككلمة ثنائية منفصلة مكونة من 32 بت. عندئذٍ، لن تحتاج عمليتا الجمع x1 + x0 و y1 + y0 إلى كلمة ثنائية إضافية لتخزين رقم الترحيل (كما هو الحال في جامع حفظ الترحيل )، ويمكن تطبيق تكرار كاراتسوبا حتى يصبح طول الأرقام المراد ضربها رقمًا واحدًا فقط.

تحليل التعقيد الزمني

تُجدي الخطوة الأساسية في خوارزمية كاراتسوبا مع أي أساس B وأي قيمة لـ m ، لكن الخوارزمية التكرارية تكون أكثر كفاءة عندما تكون m مساوية لـ n /2، مُقرّبةً لأعلى. على وجه الخصوص، إذا كانت n تساوي 2k ، حيث k عدد صحيح ، ويتوقف التكرار فقط عندما تكون n تساوي 1، فإن عدد عمليات الضرب في خانة واحدة هو 3k ، وهو nc حيث c = log₂ 3 .

بما أنه يمكن تمديد أي مدخلات ذات أرقام صفرية حتى يصبح طولها قوة من قوى العدد اثنين، فإنه يترتب على ذلك أن عدد عمليات الضرب الأولية، لأي قيمة لـ n ، يكون على الأكثر3سجل2ن3نسجل23{\displaystyle 3^{\lceil \log _{2}n\rceil }\leq 3n^{\log _{2}3}\,\!}.

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

تي(ن)=3تي(ن/2)+جن+د{\displaystyle T(n)=3T(\lceil n/2\rceil )+cn+d}

لبعض الثوابت c و d . بالنسبة لعلاقة التكرار هذه ، تعطي النظرية الرئيسية لتكرارات فرق تسد الحد التقاربيتي(ن)=Θ(نسجل23){\displaystyle T(n)=\Theta (n^{\log _{2}3})\,\!}.

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

تطبيق

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

const BASE = 10/* حساب حجم العدد في النظام العشري. على سبيل المثال، العدد 12345 حجمه 5 في النظام العشري وحجمه 2 في النظام العشري 1024. */ function size_in_base ( num ) string_num = num . toString () return string_num . length ()/* تقسيم رقم إلى أرقامه الصغرى "d" وأرقامه الكبرى. على سبيل المثال، split_at(12345, 3) سيستخرج الأرقام الثلاثة الأخيرة، مما يعطي: high=12، low=345. */ function split_at ( num , d ) hi = num / ( BASE ^ d ) low = num % ( BASE ^ d ) /* باقي القسمة */ return hi , lowدالة كاراتسوبا ( العدد 1 ، العدد 2 ) إذا كان ( العدد 1 < الأساس أو العدد 2 < الأساس ) تُرجع حاصل ضرب العدد 1 × العدد 2 /* الرجوع إلى الضرب التقليدي */ /* حساب حجم العددين. */ m = max ( الحجم في الأساس ( العدد 1 الحجم في الأساس ( العدد 2 )) m2 = floor ( m / 2 ) /* m2 = ceil (m / 2) ستعمل أيضًا */ /* تقسيم تسلسلات الأرقام في المنتصف. */ high1 ، low1 = split_at ( العدد 1 ، m2 ) high2 ، low2 = split_at ( العدد 2 ، m2 ) /* 3 استدعاءات متكررة لأعداد نصف الحجم تقريبًا. */ z0 = كاراتسوبا ( منخفض 1 , منخفض 2 ) z3 = كاراتسوبا ( منخفض 1 + مرتفع 1 , منخفض 2 + مرتفع 2 ) z2 = كاراتسوبا ( مرتفع 1 , مرتفع 2 ) عودة ( z2 × BASE ^ ( m2 × 2 )) + (( z3 - z2 - z0 ) × BASE ^ m2 ) + z0

تتمثل إحدى المشكلات التي تحدث مع هذا التطبيق في أن كل عامل من العوامل(x1+x0){\displaystyle (x_{1}+x_{0})}و(y1+y0){\displaystyle (y_{1}+y_{0})}لz3{\displaystyle z_{3}}قد يتطلب الأمر أكثر من m2مجرد أرقام لتمثيلها، وz3{\displaystyle z_{3}}قد يحدث تجاوز في النطاق نفسه (ينتج عنه نتيجة في النطاقبمz3<2بم{\displaystyle B^{m}\leq z_{3}<2B^{m}}). يمكن تجنب الحاجة إلى مضاعف ذي بت إضافي واحد باستخدام الشكل البديل المذكور أعلاه:

z1=z2+z0-(x1-x0)(y1-y0).{\displaystyle z_{1}=z_{2}+z_{0}-(x_{1}-x_{0})(y_{1}-y_{0}).}

حسابz4=(x1-x0)(y1-y0){\displaystyle z_{4}=(x_{1}-x_{0})(y_{1}-y_{0})}سينتج عنه نتيجة في نطاق-بم<z4<بم{\displaystyle -B^{m}<z_{4}<B^{m}}تتطلب هذه الطريقة أيضًا بتًا إضافيًا واحدًا، لترميز إشارة الأرقام التي قد تكون سالبة، ولكن يمكن التعامل معها عن طريق حساب القيمة المطلقة.|z4|=|x1-x0||y1-y0|{\displaystyle \left|z_{4}\right|=\left|x_{1}-x_{0}\right|\left|y_{1}-y_{0}\right|}باستخدام مُضاعِف ذي عرض ثابت، يتم حساب إشارةz4{\displaystyle z_{4}}بشكل منفصل، وأخيراً جمعها

z1=z2+z0±|z4|.{\displaystyle z_{1}=z_{2}+z_{0}\pm \left|z_{4}\right|.}

مراجع

  1. كاراتسوبا، أ.أأوفمان، ي.ب. (1962). "ضرب الأعداد متعددة الأرقام بواسطة الحواسيب الآلية" . وقائع أكاديمية العلوم في الاتحاد السوفيتي (باللغة الروسية). 145 : 293-294 . ترجمة في المجلة الأكاديمية Physics-Doklady ، 7 (1963)، ص 595-596
  2. 1 2 كاراتسوبا، أ.أ. (1995). "تعقيد الحسابات" (ملف PDF) . وقائع معهد ستيكلوف للرياضيات . 211 : 169-183 . ترجمة من Trudy Mat. Inst. Steklova، 211، 186-202 (1995)
  3. كنوت، دونالد إي. (1969). فن برمجة الحاسوب . المجلد 2، الخوارزميات شبه العددية ( الطبعة الأولى). ريدينغ، ماساتشوستس: أديسون-ويسلي. الصفحات: 11+624. ISBN    978-0201038026.
  4. باباج، تشارلز (1864). "الفصل الثامن - من المحرك التحليلي، معالجة الأعداد الكبيرة". مقتطفات من حياة فيلسوف . لندن: لونجمان جرين. ص 125. 
  5. وايس، مارك أ. (2005). هياكل البيانات وتحليل الخوارزميات في لغة C++ ( الطبعة الثالثة). بوسطن: أديسون-ويسلي . ص 480. ISBN   0321375319.