البرمجة الديناميكية

البرمجة الديناميكية ( DP ) هي طريقة رياضية للتحسين ونموذج خوارزمي في آن واحد . طُوّرت هذه الطريقة على يد ريتشارد بيلمان في خمسينيات القرن الماضي ، ووجدت تطبيقات في العديد من المجالات، مثل هندسة الطيران والاقتصاد .
في كلا السياقين، يشير المصطلح إلى تبسيط مشكلة معقدة بتقسيمها إلى مشاكل فرعية أبسط بطريقة تكرارية . وبينما لا يمكن تفكيك بعض مشاكل اتخاذ القرار بهذه الطريقة، فإن القرارات التي تمتد عبر عدة نقاط زمنية غالبًا ما تتفكك بشكل تكراري. وبالمثل، في علوم الحاسوب، إذا أمكن حل مشكلة ما على النحو الأمثل بتقسيمها إلى مشاكل فرعية ثم إيجاد الحلول المثلى لهذه المشاكل الفرعية بشكل تكراري، يُقال حينها إنها تمتلك بنية فرعية مثلى .
إذا أمكن تضمين المسائل الفرعية بشكل متكرر داخل مسائل أكبر، بحيث تصبح أساليب البرمجة الديناميكية قابلة للتطبيق، فإن هناك علاقة بين قيمة المسألة الأكبر وقيم المسائل الفرعية. [ 1 ] في أدبيات التحسين، تُسمى هذه العلاقة معادلة بيلمان .
ملخص
التحسين الرياضي
في مجال التحسين الرياضي، تشير البرمجة الديناميكية عادةً إلى تبسيط القرار عن طريق تقسيمه إلى سلسلة من خطوات القرار عبر الزمن. [ 2 ]
يتم ذلك عن طريق تحديد سلسلة من دوال القيمة V 1 ، V 2 ، ... ، V n مع أخذ y كوسيط يمثل حالة النظام في الأوقات i من 1 إلى n .
تعريف V n ( y ) هو القيمة التي تم الحصول عليها في الحالة y في آخر وقت n .
يمكن إيجاد قيم V i في الأوقات السابقة i = n − 1، n − 2، ...، 2، 1 من خلال العمل بشكل عكسي، باستخدام علاقة تكرارية تسمى معادلة بيلمان .
بالنسبة لـ i = 2، ...، n ، يتم حساب V i − 1 في أي حالة y من V i عن طريق تعظيم دالة بسيطة (عادةً ما تكون مجموع) المكسب من قرار في الوقت i − 1 والدالة V i في الحالة الجديدة للنظام إذا تم اتخاذ هذا القرار.
بما أن V i قد تم حسابها بالفعل للحالات المطلوبة، فإن العملية المذكورة أعلاه تعطي V i − 1 لتلك الحالات.
وأخيرًا، تمثل V1 في الحالة الابتدائية للنظام قيمة الحل الأمثل. ويمكن استعادة القيم المثلى لمتغيرات القرار، واحدًا تلو الآخر، من خلال تتبع الحسابات التي تم إجراؤها مسبقًا.
نظرية التحكم
في نظرية التحكم ، تتمثل إحدى المشكلات النموذجية في إيجاد تحكم مقبولمما يتسبب في النظاماتباع مسار مقبولعلى فترة زمنية مستمرةالذي يقلل دالة التكلفة
يتمثل حل هذه المشكلة في قانون أو سياسة تحكم مثلى، مما ينتج عنه مسار مثاليووظيفة تكلفة الوصولويخضع هذا الأخير للمعادلة الأساسية للبرمجة الديناميكية:
معادلة تفاضلية جزئية تُعرف باسم معادلة هاميلتون-جاكوبي-بيلمان ، والتيويجد المرء أن التقليل منمن ناحية،والدالة المجهولةثم يعوض النتيجة في معادلة هاميلتون-جاكوبي-بيلمان للحصول على المعادلة التفاضلية الجزئية التي يجب حلها مع شرط الحدود[ 3 ] من الناحية العملية، يتطلب هذا بشكل عام تقنيات عددية لبعض التقريب المنفصل لعلاقة التحسين الدقيقة.
بدلاً من ذلك، يمكن تقريب العملية المستمرة بنظام منفصل، مما يؤدي إلى علاقة تكرارية مماثلة لمعادلة هاميلتون-جاكوبي-بيلمان:
فيالمرحلة الثالثة منفترات زمنية منفصلة متساوية التباعد، وحيثوتشير إلى تقريبات منفصلة لـوتُعرف هذه المعادلة الوظيفية باسم معادلة بيلمان ، والتي يمكن حلها للحصول على حل دقيق للتقريب المتقطع لمعادلة التحسين. [ 4 ]
مثال من علم الاقتصاد: مشكلة رامزي في الادخار الأمثل
في علم الاقتصاد ، يتمثل الهدف عمومًا في تعظيم (بدلًا من تقليل) دالة الرفاه الاجتماعي الديناميكية . في مسألة رامزي، تربط هذه الدالة كميات الاستهلاك بمستويات المنفعة . بعبارة أخرى، يواجه المخطط المفاضلة بين الاستهلاك الحالي والاستهلاك المستقبلي (عبر الاستثمار في رأس المال المستخدم في الإنتاج)، وهو ما يُعرف بالاختيار بين الفترات الزمنية . ويتم خصم الاستهلاك المستقبلي بمعدل ثابت.يُعطى تقريب منفصل لمعادلة انتقال رأس المال بواسطة
أينهو الاستهلاك،رأس المال، وهي دالة إنتاج تحقق شروط إينادا . رأس مال ابتدائييفترض ذلك.
يتركلنفترض أن الاستهلاك في الفترة t ، وأن الاستهلاك يحقق منفعة.طالما أن المستهلك على قيد الحياة. افترض أن المستهلك غير صبور، بحيث يُقلل من قيمة المنفعة المستقبلية بمعامل b في كل فترة، حيث. يتركلنفترض أن رأس المال في الفترة t . بافتراض أن رأس المال الأولي هو مبلغ معينولنفترض أن رأس المال والاستهلاك في هذه الفترة يحددان رأس المال في الفترة التالية على النحو التالي:حيث A ثابت موجب وبافتراض أن رأس المال لا يمكن أن يكون سالباً، يمكن كتابة مشكلة قرار المستهلك على النحو التالي:
- رهناً بـللجميع
بهذه الطريقة، تبدو المسألة معقدة، لأنها تتضمن إيجاد حلول لجميع متغيرات الاختيار.(العاصمة)(ليس متغيرًا اختياريًا - رأس المال الأولي للمستهلك يُعتبر أمرًا معطى.)
تعتمد طريقة البرمجة الديناميكية لحل هذه المشكلة على تقسيمها إلى سلسلة من القرارات الأصغر. وللقيام بذلك، نُعرّف سلسلة من دوال القيمة.، لوالتي تمثل قيمة امتلاك أي مبلغ من رأس المال k في كل وقت t . (بافتراض) لا توجد منفعة من امتلاك رأس المال بعد الوفاة..
يمكن حساب قيمة أي كمية من رأس المال في أي وقت سابق عن طريق الاستقراء العكسي باستخدام معادلة بيلمان . في هذه المسألة، لكلمعادلة بيلمان هي
- رهناً بـ
هذه المسألة أبسط بكثير من تلك التي كتبناها سابقاً، لأنها لا تتضمن سوى متغيرين للقرار.وبشكل بديهي، بدلاً من اختيار خطة حياته الكاملة عند الولادة، يمكن للمستهلك أن يتخذ الأمور خطوة بخطوة. في الوقت t ، رأس ماله الحالييتم تحديد ذلك، وما عليه سوى اختيار الاستهلاك الحاليوالادخار.
لحل هذه المشكلة فعلياً، نعمل بطريقة عكسية. ولتبسيط الأمر، يُرمز إلى المستوى الحالي لرأس المال بالرمز k .وهو أمر معروف بالفعل، لذا باستخدام معادلة بيلمان بمجرد أن نتمكن من الحسابوهكذا دواليك حتى نصل إلىوهي قيمة مسألة القرار الأولية طوال فترة الحياة. بعبارة أخرى، بمجرد أن نعرفيمكننا حساب ذلك، وهو الحد الأقصى لـ، أينالمتغير المختار و.
بالعمل عكسيًا، يمكن إثبات أن دالة القيمة عند الزمنيكون
حيث كلهو ثابت، والكمية المثلى للاستهلاك في وقت معينيكون
والتي يمكن تبسيطها إلى
نرى أنه من الأمثل استهلاك جزء أكبر من الثروة الحالية مع تقدم العمر، وفي النهاية استهلاك كل الثروة المتبقية في الفترة T ، وهي الفترة الأخيرة من الحياة.
علوم الحاسوب
هناك سمتان أساسيتان يجب أن تتوافرا في أي مشكلة حتى يكون البرمجة الديناميكية قابلة للتطبيق: البنية الفرعية المثلى والمشكلات الفرعية المتداخلة . إذا أمكن حل مشكلة ما بدمج الحلول المثلى لمشكلات فرعية غير متداخلة ، تُسمى هذه الاستراتيجية " فرق تسد ". [ 1 ] ولهذا السبب، لا تُصنف خوارزميتا فرز الدمج والفرز السريع ضمن مسائل البرمجة الديناميكية.
تعني البنية الفرعية المثلى إمكانية الحصول على حل لمسألة تحسين معينة من خلال دمج الحلول المثلى لمسائلها الفرعية. وعادةً ما تُوصف هذه البنى الفرعية المثلى باستخدام الاستدعاء الذاتي . على سبيل المثال، إذا كان لدينا رسم بياني G=(V,E) ، فإن أقصر مسار p من الرأس u إلى الرأس v يُظهر بنية فرعية مثلى: خذ أي رأس وسيط w على هذا المسار p . إذا كان p هو أقصر مسار بالفعل، فيمكن تقسيمه إلى مسارين فرعيين p1 من u إلى w و p2 من w إلى v، بحيث يكون هذان المساران بدورهما أقصر مسارين بين الرأسين المتناظرين (باستخدام حجة القص واللصق البسيطة الموضحة في مقدمة الخوارزميات ). وبالتالي، يمكن صياغة حل إيجاد أقصر المسارات بسهولة بطريقة استدعائية، وهو ما تفعله خوارزمية بيلمان-فورد أو خوارزمية فلويد-وارشال .
يعني تداخل المسائل الفرعية أن فضاء المسائل الفرعية يجب أن يكون صغيرًا، أي أن أي خوارزمية تكرارية لحل المسألة يجب أن تحل نفس المسائل الفرعية مرارًا وتكرارًا، بدلًا من توليد مسائل فرعية جديدة. على سبيل المثال، لننظر إلى الصيغة التكرارية لتوليد متتالية فيبوناتشي: F <sub>i</sub> = F<sub> i - 1</sub> + F <sub>i - 2</sub> ، مع حالة الأساس F <sub>1</sub> = F <sub> 2</sub> = 1. عندئذٍ F <sub>43</sub> = F <sub>42</sub> + F <sub> 41 </sub> ، و F <sub>42 </sub> = F <sub> 41</sub> + F <sub> 40 </sub>. الآن، يتم حل F <sub>41</sub> في الأشجار الفرعية التكرارية لكل من F <sub>43</sub> و F <sub>42</sub> . على الرغم من أن العدد الإجمالي للمسائل الفرعية صغير فعليًا (43 مسألة فقط)، إلا أننا ننتهي بحل نفس المسائل مرارًا وتكرارًا إذا اعتمدنا حلًا تكراريًا بسيطًا كهذا. تأخذ البرمجة الديناميكية هذه الحقيقة في الحسبان، وتحل كل مسألة فرعية مرة واحدة فقط.

يمكن تحقيق ذلك بإحدى الطريقتين التاليتين: [ 5 ]
- النهج التنازلي : هذا النهج هو النتيجة المباشرة للصياغة التكرارية لأي مسألة. إذا أمكن صياغة حل أي مسألة بشكل تكراري باستخدام حلول مسائلها الفرعية، وكانت هذه المسائل الفرعية متداخلة، فيمكن بسهولة تخزين حلولها في جدول (غالبًا ما يكون مصفوفة أو جدول تجزئة عمليًا). عند محاولة حل مسألة فرعية جديدة، نتحقق أولًا من الجدول لمعرفة ما إذا كانت قد حُلت بالفعل. إذا كان الحل مسجلًا، يمكننا استخدامه مباشرةً، وإلا نحل المسألة الفرعية ونضيف حلها إلى الجدول.
- النهج التصاعدي : بعد صياغة حل المسألة بشكل تكراري بدلالة مسائلها الفرعية، يمكننا محاولة إعادة صياغة المسألة بطريقة تصاعدية: نبدأ بحل المسائل الفرعية ثم نستخدم حلولها للبناء عليها والوصول إلى حلول للمسائل الفرعية الأكبر. ويتم ذلك عادةً في شكل جدولي من خلال توليد حلول متكررة لمسائل فرعية أكبر فأكبر باستخدام حلول المسائل الفرعية الأصغر. على سبيل المثال، إذا كنا نعرف قيم F41 و F40 ، فيمكننا حسابقيمة F42 مباشرةً .
تستطيع بعض لغات البرمجة تخزين نتيجة استدعاء دالة تلقائيًا باستخدام مجموعة محددة من الوسائط، وذلك لتسريع عملية التقييم بالاسم (وتُعرف هذه الآلية بالتقييم عند الحاجة ). وتتيح بعض اللغات هذه الميزة بشكل قابل للنقل (مثل Scheme و Common Lisp و Perl و D ). كما تتضمن بعض اللغات خاصية التخزين التلقائي ، مثل Prolog و J ، التي تدعم التخزين باستخدام الظرف M. [ 6 ] . على أي حال، لا يُمكن تطبيق هذه الخاصية إلا على الدوال الشفافة مرجعيًا . ويُعدّ التخزين أيضًا نمط تصميم سهل الاستخدام في اللغات التي تعتمد على إعادة كتابة المصطلحات، مثل Wolfram Language .
المعلوماتية الحيوية
تُستخدم البرمجة الديناميكية على نطاق واسع في المعلوماتية الحيوية لمهام مثل محاذاة التسلسلات ، وطَيّ البروتينات ، والتنبؤ ببنية الحمض النووي الريبي (RNA)، وارتباط البروتين بالحمض النووي (DNA). طُوّرت أولى خوارزميات البرمجة الديناميكية لارتباط البروتين بالحمض النووي في سبعينيات القرن الماضي بشكل مستقل من قِبَل تشارلز ديليسي في الولايات المتحدة [ 7 ] ، وجورجي جورسكي وألكسندر زاسيداتيليف في الاتحاد السوفيتي [ 8 ] . وقد اكتسبت هذه الخوارزميات مؤخرًا شعبية كبيرة في المعلوماتية الحيوية وعلم الأحياء الحاسوبي ، لا سيما في دراسات تحديد مواقع النيوكليوسومات وارتباط عوامل النسخ .
أمثلة: خوارزميات الحاسوب
خوارزمية ديكسترا لحل مشكلة أقصر مسار
من منظور البرمجة الديناميكية، تُعد خوارزمية ديكسترا لمسألة أقصر مسار مخطط تقريبي متتابع يحل معادلة الدالة للبرمجة الديناميكية لمسألة أقصر مسار باستخدام طريقة الوصول . [ 9 ] [ 10 ] [ 11 ]
في الواقع، شرح ديكسترا للمنطق الكامن وراء الخوارزمية، [ 12 ] وهو
المسألة 2. أوجد المسار ذو أقصر طول إجمالي بين عقدتين معطيتينو.
نستفيد من حقيقة أنه، إذاهي عقدة على المسار الأدنى منلإن معرفة الأخير تستلزم معرفة المسار الأدنى منل.
هو إعادة صياغة لمبدأ بيلمان الشهير للأمثلية في سياق مشكلة أقصر مسار .
متتالية فيبوناتشي
يُحسّن استخدام البرمجة الديناميكية في حساب العنصر النوني من متتالية فيبوناتشي الأداء بشكل كبير. إليك تطبيقًا بسيطًا، يعتمد مباشرةً على التعريف الرياضي:
دالة fib(n) إذا كان n <= 1 تُرجع n تُرجع fib(n − 1) + fib(n − 2)
لاحظ أنه إذا قمنا باستدعاء، على سبيل المثال، ، fib(5)فإننا ننتج شجرة استدعاء تستدعي الدالة على نفس القيمة عدة مرات مختلفة:
fib(5)fib(4) + fib(3)(fib(3) + fib(2)) + (fib(2) + fib(1))((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))(((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
على وجه الخصوص، fib(2)تم حسابها ثلاث مرات من الصفر. في الأمثلة الأكبر، يتم إعادة حساب العديد من قيم fib، أو المسائل الفرعية ، مما يؤدي إلى خوارزمية ذات وقت أسي.
لنفترض الآن أن لدينا كائن خريطة بسيط ، m ، يربط كل قيمة من القيم fibالمحسوبة مسبقًا بنتيجتها، ونقوم بتعديل دالتنا لاستخدامها وتحديثها. تتطلب الدالة الناتجة وقتًا قدره O ( n ) فقط بدلًا من وقت أسي (لكنها تتطلب مساحة قدرها O( n )).
var m := map (0 → 0, 1 → 1) function fib(n) if key n is not in map m m[n] := fib(n − 1) + fib(n − 2) أعد m[n]
تُسمى هذه التقنية لحفظ القيم التي تم حسابها بالفعل بالتخزين المؤقت ؛ وهذا هو النهج من أعلى إلى أسفل، حيث نقوم أولاً بتقسيم المشكلة إلى مشاكل فرعية ثم نقوم بحساب القيم وتخزينها.
في المنهج التصاعدي ، نحسب القيم الأصغر fibأولاً، ثم نبني القيم الأكبر انطلاقاً منها. يستخدم هذا الأسلوب أيضاً زمناً قدره O( n ) لأنه يحتوي على حلقة تكرارية تتكرر n − 1 مرة، ولكنه لا يتطلب سوى مساحة ثابتة (O(1))، على عكس المنهج التنازلي الذي يتطلب مساحة O( n ) لتخزين الخريطة.
دالة fib(n) إذا كان n = 0، تُرجع 0، وإلا تُرجع 0. متغير previousFib := 0، متغير currentFib := 1. تُكرر هذه العملية n - 1 مرة // يتم تخطي الحلقة إذا كان n = 1. متغير newFib := previousFib + currentFib previousFib := currentFib currentFib := newFib إرجاع فيبوناتشي الحالية
في كلا المثالين، نقوم بالحساب fib(2)مرة واحدة فقط، ثم نستخدمه لحساب كل من fib(4)و fib(3)، بدلاً من حسابه في كل مرة يتم فيها تقييم أي منهما.
نوع من المصفوفات المتوازنة 0-1
لنفترض مسألة إسناد قيم، إما صفر أو واحد، إلى مواضع مصفوفة من الرتبة n × n ، حيث n عدد زوجي، بحيث يحتوي كل صف وكل عمود على n /2 من الأصفار و n /2 من الواحدات بالضبط. نسأل: كم عدد الإسنادات المختلفة الممكنة لقيمة n معينة ؟ على سبيل المثال، عندما n = 4 ، يكون هناك خمسة حلول ممكنة.
هناك ثلاثة مناهج محتملة على الأقل: القوة الغاشمة ، والتراجع ، والبرمجة الديناميكية.
تعتمد طريقة البحث الشامل على فحص جميع قيم الأصفار والآحاد، وحساب القيم التي تحتوي على صفوف وأعمدة متوازنة ( نصف عدد الأصفار ونصف عدد الآحاد ).المهام المحتملة وفي حالة التخصيصات المعقولة، فإن هذه الاستراتيجية غير عملية بالنسبة للقيم الكبيرة بشكل تعسفي لـ.
تعتمد طريقة التراجع في هذه المسألة على اختيار ترتيب معين لعناصر المصفوفة، ثم وضع القيم 1 أو 0 بشكل متكرر، مع التحقق من أن مجموع عدد العناصر غير المُخصصة وعدد القيم 1 أو 0 في كل صف وعمود يساوي على الأقل n /2 . ورغم أن هذه الطريقة أكثر تعقيدًا من طريقة البحث الشامل، إلا أنها ستزور كل حل مرة واحدة، مما يجعلها غير عملية عندما يكون n أكبر من ستة، لأن عدد الحلول يكون كبيرًا بالفعل.116 963 796 250 لـ n = 8، كما سنرى.
تُمكّن البرمجة الديناميكية من حساب عدد الحلول دون الحاجة إلى زيارتها جميعًا. تخيّل التراجع عن قيم الصف الأول - ما المعلومات التي نحتاجها حول الصفوف المتبقية، لكي نتمكن من حساب الحلول التي تم الحصول عليها لكل قيمة من قيم الصف الأول بدقة؟ لنفترض وجود لوحات k × n ، حيث 1 ≤ k ≤ n ، وتحتوي صفوفها k علىأصفار وتُطبَّق عملية التخزين المؤقت على الدالة f، التي تُحوِّل متجهاتٍ من n زوجًا من الأعداد الصحيحة إلى عدد الألواح (الحلول) الممكنة. يوجد زوج واحد لكل عمود، ويشير مُكوِّناه على التوالي إلى عدد الأصفار والآحاد التي لم تُضَف بعد إلى ذلك العمود. نبحث عن قيمة( عدد n من الوسائط أو متجه واحد مكون من n عنصرًا). تتضمن عملية إنشاء المسألة الفرعية التكرار على كل واحد من يتم تحديد القيم الممكنة للصف العلوي من اللوحة، ثم يتم المرور على كل عمود، وطرح واحد من العنصر المناسب في الزوج الخاص بذلك العمود، وذلك بناءً على ما إذا كانت القيمة المُحددة للصف العلوي تحتوي على صفر أو واحد في ذلك الموضع. إذا كانت أي من النتائج سالبة، فإن القيمة غير صالحة ولا تُساهم في مجموعة الحلول (يتوقف التكرار). وإلا، يتم تحديد قيمة للصف العلوي من اللوحة k × n ، ثم يتم حساب عدد الحلول للوحة المتبقية ( k - 1) × n بشكل تكراري ، وذلك بجمع أعداد الحلول لكل قيمة مقبولة للصف العلوي، وإرجاع المجموع الذي يتم تخزينه مؤقتًا. الحالة الأساسية هي المسألة الفرعية البسيطة، والتي تحدث للوحة 1 × n . عدد الحلول لهذه اللوحة إما صفر أو واحد، وذلك بناءً على ما إذا كان المتجه عبارة عن تبديل لأزواج n /2 (0, 1) و n /2 (1, 0) أم لا.
على سبيل المثال، في اللوحتين الأوليين الموضحتين أعلاه، ستكون تسلسلات المتجهات كالتالي:
((2, 2) (2, 2) (2, 2) (2, 2)) ((2, 2) (2, 2) (2, 2) (2, 2)) k = 4 0 1 0 1 0 0 1 1 ((1, 2) (2, 1) (1, 2) (2, 1)) ((1, 2) (1, 2) (2, 1) (2, 1)) k = 3 1 0 1 0 0 0 1 1 ((1, 1) (1, 1) (1, 1) (1, 1)) ((0, 2) (0, 2) (2, 0) (2, 0)) k = 2 0 1 0 1 1 1 0 0 ((0, 1) (1, 0) (0, 1) (1, 0)) ((0, 1) (0, 1) (1, 0) (1, 0)) k = 1 1 0 1 0 1 1 0 0 ((0, 0) (0, 0) (0, 0) (0, 0)) ((0, 0) (0, 0), (0, 0) (0, 0))
عدد الحلول (التسلسل A058527 في OEIS ) هو
- 1، 2، 90،297 200 ،116 963 796 250 ،6 736 218 287 430 460 752 ، ...
يمكن العثور على روابط لتطبيق MAPLE لنهج البرمجة الديناميكية ضمن الروابط الخارجية .
رقعة الشطرنج
لنفترض رقعة شطرنج مكونة من n × n مربعًا ودالة تكلفة c(i, j)تُعيد التكلفة المرتبطة بكل مربع (i,j)( iحيث n هو الصف، jوn هو العمود). على سبيل المثال (على رقعة شطرنج 5 × 5)،
| 5 | 6 | 7 | 4 | 7 | 8 |
|---|---|---|---|---|---|
| 4 | 7 | 6 | 1 | 1 | 4 |
| 3 | 3 | 5 | 7 | 8 | 2 |
| 2 | – | 6 | 7 | 0 | – |
| 1 | – | – | 5 | – | – |
| 1 | 2 | 3 | 4 | 5 |
هكذاc(1, 3) = 5
لنفترض أن هناك قطعة شطرنج يمكنها أن تبدأ من أي مربع في الصف الأول (أي الصف الأول)، وتريد معرفة أقصر مسار (مجموع أقل التكاليف عند كل صف تمت زيارته) للوصول إلى الصف الأخير؛ بافتراض أن قطعة الشطرنج لا يمكنها التحرك إلا قطريًا إلى اليسار للأمام، أو قطريًا إلى اليمين للأمام، أو بشكل مستقيم للأمام. أي أن قطعة الشطرنج في الصف الأول (1,3)يمكنها التحرك إلى أي من المربعات (2,2)الثلاثة .(2,3)(2,4)
| 5 | |||||
|---|---|---|---|---|---|
| 4 | |||||
| 3 | |||||
| 2 | x | x | x | ||
| 1 | o | ||||
| 1 | 2 | 3 | 4 | 5 |
تُظهر هذه المسألة بنيةً فرعيةً مثلى . أي أن حل المسألة بأكملها يعتمد على حلول المسائل الفرعية. لنُعرّف دالة q(i, j)على النحو التالي:
- q ( i , j ) = الحد الأدنى للتكلفة للوصول إلى المربع ( i , j ).
بدءًا من الرتبة الأولى nوصولًا إلى الرتبة الثانية 1، نحسب قيمة هذه الدالة لجميع المربعات في كل رتبة متتالية. باختيار المربع الذي يحمل أقل قيمة في كل رتبة، نحصل على أقصر مسار بين الرتبة الأولى nوالرتبة الثانية 1.
الدالة q(i, j)تساوي أقل تكلفة للوصول إلى أي من المربعات الثلاثة الموجودة أسفلها (لأنها المربعات الوحيدة التي يمكن الوصول إليها) زائد c(i, j). على سبيل المثال:
| 5 | |||||
|---|---|---|---|---|---|
| 4 | أ | ||||
| 3 | ب | ج | د | ||
| 2 | |||||
| 1 | |||||
| 1 | 2 | 3 | 4 | 5 |
والآن، دعونا نحدد ذلك q(i, j)بعبارات أكثر عمومية:
يتناول السطر الأول من هذه المعادلة لوحةً مُصممةً على شكل مربعات مُفهرسة 1عند الحد الأدنى والحد nالأعلى. يُحدد السطر الثاني ما يحدث عند الرتبة الأولى، مُوفراً حالةً أساسية. أما السطر الثالث، وهو الاستدعاء الذاتي، فهو الجزء المهم، إذ يُمثل الحدود A,B,C,Dفي المثال. من هذا التعريف، يُمكننا اشتقاق شيفرة استدعاء ذاتي مباشرة لـ . في الشيفرة الزائفة التالية، يُمثل حجم اللوحة، و دالة التكلفة، و تُعيد أصغر عدد من القيم.q(i, j)nc(i, j)min()
دالة minCost(i, j) إذا كان j < 1 أو j > n تُرجع قيمة لانهائية ، وإلا إذا كان i = 1 تُرجع c(i, j)، وإلا تُرجع القيمة الدنيا ( min (minCost(i-1, j-1), minCost(i-1, j), minCost(i-1, j+1)) + c(i, j)تحسب هذه الدالة تكلفة المسار فقط، وليس المسار نفسه. سنناقش المسار نفسه لاحقًا. وكما هو الحال في مثال أعداد فيبوناتشي، فإن هذه الطريقة بطيئة للغاية لأنها تُظهر أيضًا خاصية تداخل المسائل الفرعية . أي أنها تعيد حساب تكاليف المسار نفسها مرارًا وتكرارًا. مع ذلك، يمكننا حسابها بشكل أسرع بكثير بطريقة تصاعدية إذا خزّنا تكاليف المسار في مصفوفة ثنائية الأبعاد q[i, j]بدلًا من استخدام دالة. هذا يتجنب إعادة الحساب؛ إذ تُحسب جميع القيم اللازمة للمصفوفة q[i, j]مسبقًا مرة واحدة فقط. (i,j)ويتم ببساطة البحث عن القيم المحسوبة مسبقًا عند الحاجة.
نحتاج أيضًا إلى معرفة أقصر مسار فعلي. ولتحقيق ذلك، نستخدم مصفوفة أخرى p[i, j]؛ مصفوفة السوابق . تسجل هذه المصفوفة المسار إلى أي مربع s. يُنمذج سلف المربع الأول sكإزاحة نسبية إلى فهرس q[i, j]تكلفة المسار المحسوبة مسبقًا للمربع الأول s. لإعادة بناء المسار الكامل، نبحث عن سلف المربع الأول s، ثم سلف ذلك المربع، ثم سلف ذلك المربع، وهكذا بشكل متكرر، حتى نصل إلى مربع البداية. انظر إلى الشفرة الزائفة التالية:
دالة حساب أقصر مسار للمصفوفات () لـ x من 1 إلى n q[1, x] := c(1, x) لكل y من 1 إلى n q[y, 0] := ∞ q[y, n + 1] := ∞ لكل y من 2 إلى n، ولكل x من 1 إلى n m := min(q[y-1, x-1], q[y-1, x], q[y-1, x+1]) q[y, x] := m + c(y, x) إذا كان m = q[y-1, x-1] p[y, x] := -1 وإلا إذا كان m = q[y-1, x] p[y, x] := 0 وإلا فإن p[y, x] := 1
أما الباقي فهو مسألة بسيطة تتمثل في إيجاد الحد الأدنى وطباعته.
دالة حساب أقصر مسار computeShortestPathArrays() minIndex := 1 min := q[n, 1] لكل i من 2 إلى n إذا كان q[n, i] < min minIndex := i min := q[n, i] printpath(n, minIndex)دالة printPath(y, x) تطبع (x) تطبع (" < -") إذا كانت y = 2 تطبع (x + p[y, x]) وإلا تطبع printPath(y-1, x + p[y, x])محاذاة التسلسل
في علم الوراثة ، يُعدّ محاذاة التسلسل تطبيقًا هامًا حيث تُعدّ البرمجة الديناميكية أساسية. [ 13 ] عادةً، تتلخص المشكلة في تحويل تسلسل إلى آخر باستخدام عمليات التحرير التي تستبدل أو تُضيف أو تُزيل عنصرًا. لكل عملية تكلفة مُرتبطة بها، والهدف هو إيجاد تسلسل التحرير ذي أقل تكلفة إجمالية .
يمكن صياغة المشكلة بشكل طبيعي على أنها تكرار، حيث يتم تعديل التسلسل A بشكل أمثل إلى التسلسل B إما عن طريق:
- بإدخال الحرف الأول من B، وإجراء محاذاة مثالية بين A وذيل B
- حذف الحرف الأول من A، وإجراء المحاذاة المثلى لذيل A وB
- استبدال الحرف الأول من A بالحرف الأول من B، وإجراء عمليات محاذاة مثالية لذيول A و B.
يمكن جدولة عمليات المحاذاة الجزئية في مصفوفة، حيث تحتوي الخلية (i,j) على تكلفة المحاذاة المثلى لـ A[1..i] مع B[1..j]. ويمكن حساب التكلفة في الخلية (i,j) عن طريق جمع تكلفة العمليات ذات الصلة مع تكلفة الخلايا المجاورة لها، ثم اختيار القيمة المثلى.
توجد متغيرات مختلفة، انظر خوارزمية سميث-واترمان وخوارزمية نيدلمان-وونش .
لغز برج هانوي


برج هانوي أو أبراج هانوي هي لعبة أو لغز رياضي . تتكون من ثلاثة قضبان، وعدد من الأقراص بأحجام مختلفة يمكن انزلاقها على أي قضيب. يبدأ اللغز بوضع الأقراص في كومة مرتبة بشكل منظم تصاعديًا حسب الحجم على أحد القضبان، بحيث يكون أصغرها في الأعلى، مما يشكل شكلًا مخروطيًا.
الهدف من اللغز هو نقل المجموعة بأكملها إلى قضيب آخر، مع مراعاة القواعد التالية:
- لا يمكن نقل سوى قرص واحد في كل مرة.
- تتكون كل حركة من أخذ القرص العلوي من أحد القضبان وإدخاله على قضيب آخر، فوق الأقراص الأخرى التي قد تكون موجودة بالفعل على ذلك القضيب.
- لا يجوز وضع أي قرص فوق قرص أصغر منه.
يتكون حل البرمجة الديناميكية من حل المعادلة الوظيفية
- S(n,h,t) = S(n-1,h, not(h,t)) ; S(1,h,t) ; S(n-1,not(h,t),t)
حيث يرمز n إلى عدد الأقراص المراد نقلها، و h إلى قضيب البداية، و t إلى قضيب الهدف، و not(h,t) إلى القضيب الثالث (لا h ولا t)، و ; إلى الربط، و
- S(n, h, t) := حل لمسألة تتكون من n قرصًا يتم نقلها من القضيب h إلى القضيب t.
بالنسبة لـ n=1 تكون المشكلة تافهة، وهي S(1,h,t) = "نقل قرص من القضيب h إلى القضيب t" (لم يتبق سوى قرص واحد).
عدد الحركات المطلوبة لهذا الحل هو 2n - 1. إذا كان الهدف هو زيادة عدد الحركات إلى أقصى حد (دون تكرار)، فإن معادلة البرمجة الديناميكية تصبح أكثر تعقيدًا بعض الشيء، ويتطلب الأمر 3n - 1 حركة . [ 14 ]
لغز إسقاط البيض
تتعلق إحدى الألغاز الشهيرة بإسقاط بيض من مبنى لتحديد الارتفاع الذي يبدأ عنده البيض بالانكسار. فيما يلي وصف يتضمن بيضتين (N=2) ومبنى مكون من 36 طابقًا (H=36): [ 15 ]
- لنفترض أننا نريد معرفة أي الطوابق في مبنى مكون من 36 طابقًا آمنة لإسقاط البيض منها، وأيها سيؤدي إلى كسر البيض عند الهبوط (باستخدام المصطلحات الإنجليزية الأمريكية ، حيث يكون الطابق الأول هو مستوى الأرض). نفترض بعض الافتراضات:
- يمكن استخدام البيضة التي تنجو من السقوط مرة أخرى.
- يجب التخلص من البيضة المكسورة.
- يكون تأثير السقوط هو نفسه بالنسبة لجميع البيض.
- إذا انكسرت البيضة عند سقوطها، فإنها ستنكسر أيضاً إذا سقطت من نافذة أعلى.
- إذا نجت البيضة من السقوط، فستنجو من سقوط أقصر.
- لا يُستبعد أن تتسبب نوافذ الطابق الأول في كسر البيض، كما لا يُستبعد أن يتمكن البيض من البقاء على قيد الحياة من خلال نوافذ الطابق السادس والثلاثين.
- إذا توفرت بيضة واحدة فقط، وأردنا التأكد من الحصول على النتيجة الصحيحة، فلا يمكن إجراء التجربة إلا بطريقة واحدة. أسقط البيضة من نافذة الطابق الأول؛ إذا نجت، أسقطها من نافذة الطابق الثاني. استمر في الصعود حتى تنكسر. في أسوأ الأحوال، قد تتطلب هذه الطريقة 36 محاولة. لنفترض أن لدينا بيضتين. ما هو أقل عدد من محاولات إسقاط البيض التي تضمن نجاح التجربة في جميع الحالات؟
لاستنتاج معادلة وظيفية للبرمجة الديناميكية لهذا اللغز، لنفترض أن حالة نموذج البرمجة الديناميكية هي زوج s = (n,k)، حيث
- n = عدد بيض الاختبار المتاح، n = 0، 1، 2، 3، ...، N − 1.
- k = عدد الطوابق (المتتالية) التي لم يتم اختبارها بعد، k = 0، 1، 2، ...، H − 1.
على سبيل المثال، تشير s = (2,6) إلى توفر بيضتين للاختبار، وأن ستة طوابق (متتالية) لم تُختبر بعد. الحالة الابتدائية للعملية هي s = ( N , H )، حيث N يُمثل عدد بيض الاختبار المتاح عند بدء التجربة. تنتهي العملية إما عند نفاد بيض الاختبار ( n = 0) أو عند k = 0، أيهما يحدث أولاً. إذا انتهت العملية عند الحالة s = (0, k ) وكان k > 0، فإن الاختبار يكون قد فشل.
والآن، لنبدأ
- W ( n , k ) = الحد الأدنى لعدد التجارب المطلوبة لتحديد قيمة الحد الأدنى الحرج في أسوأ سيناريو مع الأخذ في الاعتبار أن العملية في الحالة s = ( n , k ).
ثم يمكن إثبات أن [ 16 ]
- W ( n , k ) = 1 + min{max( W ( n − 1, x − 1), W ( n , k − x )): x = 1, 2, ..., k }
حيث W ( n ,0) = 0 لجميع قيم n > 0 و W (1, k ) = k لجميع قيم k . من السهل حل هذه المعادلة تكراريًا عن طريق زيادة قيم n و k بشكل منهجي .
حل أسرع للبرمجة الديناميكية باستخدام معلمات مختلفة
لاحظ أن الحل أعلاه يأخذيمكن تحسين ذلك باستخدام حل البرمجة الديناميكية.الوقت عن طريق البحث الثنائي على الأمثلفي التكرار المذكور أعلاه، بما أنيتزايد فيبينمايتناقص فيوبالتالي، فإن الحد الأدنى المحلي لـيمثل الحد الأدنى العالمي. كذلك، من خلال تخزين القيمة المثلىلكل خلية في جدول البرمجة الديناميكية وبالرجوع إلى قيمتها في الخلية السابقة، يكون الحل الأمثليمكن إيجاد كل خلية في وقت ثابت، مما يحسنها إلىالوقت. ومع ذلك، هناك حل أسرع يتضمن تحديدًا مختلفًا لمعاملات المشكلة:
يتركليكن العدد الإجمالي للطوابق بحيث تنكسر البيضات عند إسقاطها منهاالطابق الثالث (المثال أعلاه يعادل أخذ).
يتركأن يكون هذا هو الحد الأدنى للأرضية التي يجب أن تسقط منها البيضة حتى تنكسر.
يتركليكن الحد الأقصى لعدد قيموالتي يمكن تمييزها باستخداميحاول وبيض.
ثمللجميع.
يترككن الأرضية التي تُسقط منها البيضة الأولى في الاستراتيجية المثلى.
إذا انكسرت البيضة الأولى،منلويمكن تمييزها باستخدام ما لا يزيد عنيحاول وبيض.
إذا لم تنكسر البيضة الأولى،منلويمكن تمييزها باستخداميحاول وبيض.
لذلك،.
عندئذٍ تصبح المسألة مكافئة لإيجاد الحد الأدنىبحيث.
وللقيام بذلك، يمكننا حساببالترتيب التصاعدي، الأمر الذي سيستغرقوقت.
وبالتالي، إذا تعاملنا بشكل منفصل مع حالة، ستأخذ الخوارزميةوقت.
لكن يمكن في الواقع حل علاقة التكرار، مما يعطيوالتي يمكن حسابها فيالوقت باستخدام الهويةللجميع.
منذللجميعيمكننا استخدام البحث الثنائي علىللعثور، مما يعطيالخوارزمية. [ 17 ]
ضرب المصفوفات المتسلسلة
يُعدّ ضرب سلسلة المصفوفات مثالًا معروفًا يُبيّن فائدة البرمجة الديناميكية. فعلى سبيل المثال، غالبًا ما تتطلب التطبيقات الهندسية ضرب سلسلة من المصفوفات. وليس من المستغرب وجود مصفوفات ذات أبعاد كبيرة، مثل 100×100. لذا، فإن مهمتنا هي ضرب المصفوفات .عملية ضرب المصفوفات ليست تبديلية، بل تجميعية؛ ولا يمكننا ضرب أكثر من مصفوفتين في الوقت نفسه. لذا ، يمكننا ضرب هذه السلسلة من المصفوفات بطرق عديدة ومختلفة، على سبيل المثال:
- ( ( A1 × A2 ) × A3 ) × ... أن
- A 1 × ((( A 2 × A 3 ) × ... ) × A n )
- ( A1 × A2 ) × ( A3 × ... An )
وهكذا دواليك. توجد طرق عديدة لضرب هذه السلسلة من المصفوفات. جميعها تُنتج نفس النتيجة النهائية، إلا أن وقت الحساب يختلف باختلاف المصفوفات المراد ضربها. فإذا كانت أبعاد المصفوفة A هي m×n وأبعاد المصفوفة B هي n×q، فإن أبعاد المصفوفة C=A×B ستكون m×q، وستتطلب m×n×q عملية ضرب عددية (باستخدام خوارزمية ضرب مصفوفات مبسطة لأغراض التوضيح).
على سبيل المثال، لنضرب المصفوفات A وB وC. ولنفترض أن أبعادها هي m×n وn×p وp×s على التوالي. ستكون المصفوفة A×B×C بحجم m×s ويمكن حسابها بالطريقتين الموضحتين أدناه:
- Ax(B×C) سيتطلب هذا الترتيب من ضرب المصفوفات nps + mns من عمليات الضرب القياسي.
- (A×B)×C سيتطلب هذا الترتيب من ضرب المصفوفات mnp + mps حسابات قياسية.
لنفترض أن m = 10، n = 100، p = 10، و s = 1000. إذن، تتطلب الطريقة الأولى لضرب السلسلة 1,000,000 + 1,000,000 عملية حسابية. أما الطريقة الثانية فتتطلب 10,000 + 100,000 عملية حسابية فقط. من الواضح أن الطريقة الثانية أسرع، لذا ينبغي ضرب المصفوفات باستخدام هذا الترتيب للأقواس.
لذلك، فإن استنتاجنا هو أن ترتيب الأقواس مهم، وأن مهمتنا هي إيجاد الترتيب الأمثل للأقواس.
في هذه المرحلة، لدينا عدة خيارات، أحدها تصميم خوارزمية برمجة ديناميكية تقسم المسألة إلى مسائل متداخلة وتحسب الترتيب الأمثل للأقواس. يُعرض حل البرمجة الديناميكية أدناه.
لنُسمِّي m[i,j] الحد الأدنى لعدد عمليات الضرب القياسي اللازمة لضرب سلسلة من المصفوفات من المصفوفة i إلى المصفوفة j (أي A i × .... × A j ، أي i ≤ j). نقسم السلسلة عند مصفوفة k، بحيث يكون i ≤ k < j، ونحاول إيجاد التركيبة التي تُنتج الحد الأدنى لـ m[i,j].
الصيغة هي:
إذا كان i = j، فإن m[i,j] = 0. إذا كان i < j، فإن m[i,j] = القيمة الصغرى لجميع القيم الممكنة لـ k (m[i,k] + m[k+1,j] +)حيث تتراوح قيمة k من i إلى j − 1.
- يمثل بُعد الصف للمصفوفة i،
- يمثل بُعد العمود للمصفوفة k،
- يمثل بُعد العمود للمصفوفة j.
يمكن ترميز هذه الصيغة كما هو موضح أدناه، حيث يمثل مُدخل "chain" سلسلة المصفوفات، أي :
دالة OptimalMatrixChainParenthesis(chain) n = طول (السلسلة) لـ i = 1، n m[i,i] = 0 // بما أنه لا يتطلب أي عمليات حسابية لضرب مصفوفة واحدة، وذلك لـ len = 2 و n، ولـ i = 1 و n - len + 1 j = i + len -1 m[i,j] = ∞ // بحيث يتم تحديث الحساب الأول لـ k = i, j-1 q = m[i, k] + m[k+1, j] +إذا كان q < m[i, j] // الترتيب الجديد للأقواس أفضل من السابق m[i, j] = q // تحديث s[i, j] = k // تسجيل قيمة k التي سيتم التقسيم بناءً عليها، أي مكان وضع الأقواسحتى الآن، قمنا بحساب قيم جميع القيم الممكنة لـ m [ i , j ] ، وهو الحد الأدنى لعدد العمليات الحسابية اللازمة لضرب سلسلة من المصفوفة i إلى المصفوفة j ، وسجلنا "نقطة الفصل" المقابلة s [ i , j ] . على سبيل المثال، إذا كنا نضرب السلسلة A1 × A2 × A3 × A4 ، وتبين أن m [1,3] = 100 و s [1,3] = 2 ، فهذا يعني أن الموضع الأمثل للأقواس للمصفوفات من 1 إلى 3 هووضرب تلك المصفوفات سيتطلب 100 عملية حسابية قياسية.
ستُنتج هذه الخوارزمية جدولين m [, ] و s [, ] يحتويان على مدخلات لجميع القيم الممكنة لـ i و j. الحل النهائي للسلسلة بأكملها هو m[1, n]، مع تقسيم مُقابل عند s[1, n]. سيكون فكّ الحل عملية تكرارية، تبدأ من الأعلى وتستمر حتى نصل إلى الحالة الأساسية، أي ضرب المصفوفات المفردة.
لذا، تتمثل الخطوة التالية في تقسيم السلسلة فعلياً، أي وضع الأقواس في مكانها الأمثل. ولتحقيق هذا الغرض، يمكننا استخدام الخوارزمية التالية:
دالة PrintOptimalParenthesis(s, i, j) إذا كان i = j اطبع "A"i آخر مطبعة "(" PrintOptimalParenthesis(s, i, s[i, j]) PrintOptimalParenthesis(s, s[i, j] + 1, j) مطبعة ")"بالطبع، هذه الخوارزمية غير مفيدة للضرب الفعلي. إنها مجرد طريقة سهلة الاستخدام لمعرفة شكل النتيجة.
لضرب المصفوفات فعلياً باستخدام التقسيمات المناسبة، نحتاج إلى الخوارزمية التالية:
دالة MatrixChainMultiply ( سلسلة من 1 إلى n ) // تُعيد المصفوفة النهائية، أي A1×A2×...×An OptimalMatrixChainParenthesis ( سلسلة من 1 إلى n ) // ستُنتج هذه الدالة "جداول" s[.] و m[.] OptimalMatrixMultiplication ( s , سلسلة من 1 إلى n ) // تُجري عملية الضرب فعليًادالة OptimalMatrixMultiplication ( s , i , j ) // تُعيد نتيجة ضرب سلسلة من المصفوفات من Ai إلى Aj بالطريقة المثلى إذا كان i < j // استمر في تقسيم السلسلة وضرب المصفوفات في الجانبين الأيسر والأيمن LeftSide = OptimalMatrixMultiplication ( s , i , s [ i , j ]) RightSide = OptimalMatrixMultiplication ( s , s [ i , j ] + 1 , j ) return MatrixMultiply ( LeftSide , RightSide ) else if i = j return Ai // المصفوفة في الموضع i else print "خطأ، يجب أن يكون i <= j صحيحًا"دالة MatrixMultiply ( A , B ) // دالة تضرب مصفوفتين إذا كانت أعمدة ( A ) = صفوف ( B ) for i = 1 , صفوف ( A ) for j = 1 , أعمدة ( B ) C [ i , j ] = 0 for k = 1 , أعمدة ( A ) C [ i , j ] = C [ i , j ] + A [ i , k ] * B [ k , j ] return C else print "خطأ، أبعاد غير متوافقة."تاريخ الاسم
استُخدم مصطلح البرمجة الديناميكية لأول مرة في أربعينيات القرن العشرين من قِبل ريتشارد بيلمان لوصف عملية حل المشكلات التي تتطلب إيجاد أفضل القرارات تباعًا. وبحلول عام ١٩٥٣، طوّر بيلمان هذا المصطلح إلى معناه الحديث، مشيرًا تحديدًا إلى تضمين مشكلات القرار الأصغر ضمن مشكلات القرار الأكبر، [ ١٨ ] ومنذ ذلك الحين ، اعترف معهد مهندسي الكهرباء والإلكترونيات (IEEE) بهذا المجال كأحد مواضيع تحليل النظم والهندسة . ويُخلّد اسم معادلة بيلمان إسهام بيلمان ، وهي نتيجة أساسية في البرمجة الديناميكية تُعيد صياغة مشكلة التحسين في شكل تكراري .
يشرح بيلمان المنطق الكامن وراء مصطلح البرمجة الديناميكية في سيرته الذاتية، عين الإعصار: سيرة ذاتية :
قضيتُ فصل الخريف (من عام ١٩٥٠) في مؤسسة راند . كانت مهمتي الأولى إيجاد اسم لعمليات اتخاذ القرار متعددة المراحل. والسؤال المثير للاهتمام هو: "من أين جاء اسم البرمجة الديناميكية؟" لم تكن الخمسينيات سنوات جيدة للبحث الرياضي. كان لدينا رجلٌ مميزٌ في واشنطن يُدعى ويلسون . كان وزيرًا للدفاع، وكان لديه في الواقع خوفٌ مرضيٌ وكراهيةٌ لكلمة "بحث". لا أستخدم هذا المصطلح باستخفاف، بل أستخدمه بدقة. كان وجهه يحمرّ بشدة، ويصبح عنيفًا إذا استخدم أحدٌ مصطلح "بحث" في حضوره. يمكنك أن تتخيل شعوره آنذاك تجاه مصطلح "رياضي". كانت مؤسسة راند تابعةً للقوات الجوية، وكان ويلسون رئيسًا للقوات الجوية، بشكلٍ أساسي. لذلك، شعرتُ أنه يجب عليّ فعل شيءٍ ما لحماية ويلسون والقوات الجوية من حقيقة أنني كنتُ في الواقع أمارس الرياضيات داخل مؤسسة راند. ما اللقب، ما الاسم، الذي يمكنني اختياره؟ في المقام الأول، كنتُ مهتمًا بالتخطيط، واتخاذ القرارات، والتفكير. لكن كلمة "تخطيط" ليست مناسبة لأسباب عديدة. لذلك قررت استخدام كلمة "برمجة". أردتُ إيصال فكرة أن هذا العمل ديناميكي، متعدد المراحل، ومتغير مع الزمن. فكرتُ، لنضرب عصفورين بحجر واحد. لنأخذ كلمة ذات معنى دقيق للغاية، ألا وهو "ديناميكي" بالمعنى الفيزيائي الكلاسيكي. كما أنها تتمتع بخاصية مثيرة للاهتمام كصفة، وهي أنه من المستحيل استخدام كلمة "ديناميكي" بمعنى سلبي. حاول أن تفكر في أي تركيبة قد تُعطيها معنى سلبيًا. هذا مستحيل. وهكذا، اعتقدتُ أن "البرمجة الديناميكية" اسم مناسب. اسم لا يمكن حتى لعضو في الكونغرس أن يعترض عليه. لذلك استخدمته كمصطلح شامل لأنشطتي.
— ريتشارد بيلمان، عين الإعصار: سيرة ذاتية (1984، صفحة 159)
اختار بيلمان كلمة "ديناميكي" للتعبير عن الجانب المتغير مع الزمن للمشكلات، ولأنها تبدو مثيرة للإعجاب. [ 13 ] تشير كلمة "برمجة" إلى استخدام هذه الطريقة لإيجاد برنامج أمثل ، كما هو الحال في الجدول الزمني العسكري للتدريب أو الخدمات اللوجستية. هذا الاستخدام هو نفسه المستخدم في عبارات "البرمجة الخطية" و "البرمجة الرياضية" ، وهما مرادفان للتحسين الرياضي . [ 19 ]
قد يكون التفسير المذكور أعلاه لأصل المصطلح غير دقيق: فبحسب راسل ونورفيج، لا يمكن أن تكون القصة المذكورة أعلاه صحيحة تمامًا، لأن أول ورقة بحثية استخدم فيها المصطلح (بيلمان، 1952) نُشرت قبل أن يصبح ويلسون وزيرًا للدفاع عام 1953. [ 20 ] كما صرّح هارولد ج. كوشنر في خطاب له: "من ناحية أخرى، عندما سألت [بيلمان] السؤال نفسه، أجاب بأنه كان يحاول التفوق على البرمجة الخطية لدانتزيج بإضافة الديناميكية. ربما كان كلا الدافعين صحيحًا." [ 21 ]
انظر أيضاً
- التحدب في علم الاقتصاد – موضوع هام في علم الاقتصاد
- الخوارزمية الجشعة – سلسلة من الخيارات المثلى محليًا
- عدم التحدب (في الاقتصاد) – انتهاكات افتراضات التحدب في مبادئ الاقتصاد الأساسية
- البرمجة العشوائية – إطار عمل لنمذجة مسائل التحسين التي تنطوي على عدم اليقين
- البرمجة الديناميكية العشوائية – تقنية عام 1957 لنمذجة مشاكل اتخاذ القرار في ظل عدم اليقين
- التعلم المعزز – مجال من مجالات تعلم الآلة
مراجع
- 1 2 كورمين، TH؛ ليسرسون، CE؛ ريفيست، ر.ل. Stein، C. (2001)، مقدمة للخوارزميات (الطبعة الثانية)، مطبعة معهد ماساتشوستس للتكنولوجيا وماكجرو هيل، ISBN 0-262-03293-7ص. 344.
- ↑ كورمن، توماس هـ. (2009). مقدمة في الخوارزميات ( الطبعة الثالثة). الولايات المتحدة الأمريكية: مطبعة معهد ماساتشوستس للتكنولوجيا . ص 359. ISBN 978-0262033848.
{{cite book}}: صيانة CS1: التاريخ والسنة ( رابط ) - ↑ كامين، إم آي ؛ شوارتز، إن إل (1991). التحسين الديناميكي: حساب التفاضل والتكامل والتحكم الأمثل في الاقتصاد والإدارة ( الطبعة الثانية). نيويورك: إلسيفير. ص 261. ISBN 978-0-444-01609-6.
- ↑ كيرك، دونالد إي. (1970). نظرية التحكم الأمثل: مقدمة . إنجلوود كليفس، نيوجيرسي: برنتيس هول. الصفحات 94-95 . ISBN 978-0-13-638098-6.
- ↑ "الخوارزميات من تأليف جيف إريكسون" . jeffe.cs.illinois.edu . تم الاطلاع عليه بتاريخ 2024-12-06 .
- ↑ "مذكرة" . مفردات مجلة . برمجيات مجلة . تم الاطلاع عليه بتاريخ 28 أكتوبر 2011 .
- ↑ ديليسي، تشارلز (يوليو 1974)، "الظواهر التعاونية في البوليمرات المتجانسة: صياغة بديلة لدالة التوزيع"، البوليمرات الحيوية ، 13 (7): 1511-1512 ، doi : 10.1002/bip.1974.360130719
- ↑ غورسكي، جي في؛ زاسيداتيليف، إيه إس (سبتمبر 1978)، "علاقات دقيقة لحساب ارتباط البروتينات التنظيمية وغيرها من روابط الشبكة في عديدات النوكليوتيدات المزدوجة"، بيوفيزيكا ، 23 (5): 932-946 ، PMID 698271
- ↑ Sniedovich, M. (2006), "إعادة النظر في خوارزمية Dijkstra: العلاقة بالبرمجة الديناميكية" (PDF) ، مجلة التحكم وعلم التحكم الآلي ، 35 (3): 599– 620.نسخة إلكترونية من الورقة البحثية مع وحدات حسابية تفاعلية.
- ↑ ديناردو، إي. في. (2003)، البرمجة الديناميكية: النماذج والتطبيقات ، مينولا، نيويورك: منشورات دوفر ، رقم ISBN 978-0-486-42810-9
- ↑ سنيدوفيتش، م. (2010)، البرمجة الديناميكية: الأسس والمبادئ ، تايلور وفرانسيس ، رقم ISBN 978-0-8247-4099-3
- ^ ديكسترا ، إي دبليو (ديسمبر 1959). “ملاحظة حول مشكلتين فيما يتعلق بالرسوم البيانية”. الرياضيات الرقمية . 1 (1): 269-271 . دوى : 10.1007 / BF01386390 .
- 1 2 إيدي، إس آر (2004). "ما هي البرمجة الديناميكية؟". مجلة نيتشر للتكنولوجيا الحيوية . 22 (7): 909-910 . doi : 10.1038/nbt0704-909 . PMID 15229554. S2CID 5352062 .
- ↑ موشيه سنيدوفيتش (2002)، "ألعاب OR/MS: 2. مشكلة أبراج هانوي"، معاملات INFORMS في التعليم ، 3 (1): 34-51 ، doi : 10.1287/ited.3.1.45 .
- ↑ كونهاوزر، جيه دي إي، فيلمان، دي، وواغون، إس (1996). في أي اتجاه سارت الدراجة؟ عروض دولسياني الرياضية - رقم 18. الجمعية الرياضية الأمريكية .
- ↑ سنيدوفيتش، موشيه (2003). "ألعاب بحوث العمليات/علوم الحاسوب: 4. متعة إسقاط البيض في براونشفايغ وهونغ كونغ" . معاملات INFORMS في التعليم . 4 (1): 48-64 . doi : 10.1287/ited.4.1.48 .
- ↑ دين كونابل ويلز، الروابط بين توافقية التباديل والخوارزميات والهندسة
- ↑ ستيوارت دريفوس. "ريتشارد بيلمان يتحدث عن نشأة البرمجة الديناميكية" .
- ↑ نوسيدال، ج.؛ رايت، إس. جيه . (2006). التحسين العددي . سبرينغر. ص 9. ISBN 9780387303031.
- ↑ راسل، س.؛ نورفيج، ب. (2009). الذكاء الاصطناعي: منهج حديث ( الطبعة الثالثة). برنتيس هول. ISBN 978-0-13-207148-2.
- ↑ كوشنر، هارولد ج. (2004-07-01). "جائزة ريتشارد إي. بيلمان للتراث في مجال التحكم" . مؤرشف من الأصل في 2014-10-19.
للمزيد من القراءة
- أدا، جيروم؛ كوبر، راسل (2003)، الاقتصاد الديناميكي ، مطبعة معهد ماساتشوستس للتكنولوجيا، رقم ISBN 9780262012010مقدمة مبسطة للبرمجة الديناميكية في الاقتصاد. كود MATLAB للكتاب. مؤرشف بتاريخ 9 أكتوبر 2020 في أرشيف Wayback Machine .
- بيلمان، ريتشارد (1954)، "نظرية البرمجة الديناميكية"، نشرة الجمعية الرياضية الأمريكية ، 60 (6): 503-516 ، doi : 10.1090/S0002-9904-1954-09848-8 ، MR 0067459 . يتضمن قائمة مراجع شاملة للأدبيات في هذا المجال، حتى عام 1954.
- بيلمان، ريتشارد (1957)، البرمجة الديناميكية ، مطبعة جامعة برينستونطبعة دوفر الورقية (2003)، رقم ISBN 0-486-42809-5.
- كورمين، توماس هـ . ليسرسون، تشارلز إي . ريفست، رونالد ل . شتاين ، كليفورد (2001)، مقدمة للخوارزميات ( الطبعة الثانية)، مطبعة معهد ماساتشوستس للتكنولوجيا وماكجرو هيل، ISBN 978-0-262-03293-3وخاصة الصفحات من 323 إلى 369.
- دريفوس، ستيوارت إي.؛ لو، أفيريل إم. (1977)، فن ونظرية البرمجة الديناميكية ، دار النشر الأكاديمية، رقم ISBN 978-0-12-221860-6.
- جيجيريش، ر.؛ ماير، س.؛ ستيفن، ب. (2004)، "منهج البرمجة الديناميكية على بيانات التسلسل" (ملف PDF) ، علم برمجة الحاسوب ، 51 (3): 215-263 ، doi : 10.1016/j.scico.2003.12.005.
- ماين، شون (2007)، تقنيات التحكم للشبكات المعقدة ، مطبعة جامعة كامبريدج، رقم ISBN 978-0-521-88441-9تمت أرشفة هذا النص من النسخة الأصلية بتاريخ 19 يونيو 2010..
- سريثاران، إس إس (1991). "البرمجة الديناميكية لمعادلات نافيير-ستوكس". رسائل الأنظمة والتحكم . 16 (4): 299-307 . doi : 10.1016/0167-6911(91)90020-f .
- ستوكي، نانسي ؛ لوكاس، روبرت إي .؛ بريسكوت، إدوارد (1989)، الأساليب التكرارية في الديناميات الاقتصادية ، مطبعة جامعة هارفارد، ISBN 978-0-674-75096-8.
روابط خارجية
- كينغ، إيان، 2002 (1987)، " مقدمة بسيطة للبرمجة الديناميكية في نماذج الاقتصاد الكلي ". مقدمة للبرمجة الديناميكية كأداة مهمة في النظرية الاقتصادية.
- البرمجة الديناميكية
- خوارزميات وأساليب التحسين
- المعادلات
- هندسة النظم
- التحكم الأمثل
