การเขียนโปรแกรมแบบไดนามิกแตกต่างจากแรงเดรัจฉานอย่างไร


19

ฉันอ่านเกี่ยวกับการเขียนโปรแกรมแบบไดนามิกเมื่อฉันเจอข้อความอ้างอิงต่อไปนี้

อัลกอริทึมการเขียนโปรแกรมแบบไดนามิกจะตรวจสอบวิธีที่เป็นไปได้ทั้งหมดในการแก้ปัญหาและจะเลือกทางออกที่ดีที่สุด ดังนั้นเราจึงสามารถคิดคร่าว ๆ ของการเขียนโปรแกรมแบบไดนามิกเป็นอัจฉริยะวิธีแรงเดรัจฉานที่ช่วยให้เราไปถึงการแก้ปัญหาที่เป็นไปได้ทั้งหมดในการเลือกที่ดีที่สุด หากขอบเขตของปัญหาเป็นเช่นนั้นที่จะผ่านการแก้ไขปัญหาที่เป็นไปได้ทั้งหมดและเป็นไปได้อย่างรวดเร็วพอการเขียนโปรแกรมแบบไดนามิกรับประกันการหาทางออกที่ดีที่สุด

ตัวอย่างต่อไปนี้ได้รับ

ตัวอย่างเช่นสมมติว่าคุณต้องได้รับจากจุด A ถึงจุด B โดยเร็วที่สุดในเมืองที่กำหนดในช่วงชั่วโมงเร่งด่วน อัลกอริทึมการเขียนโปรแกรมแบบไดนามิกจะตรวจสอบรายงานการจราจรทั้งหมดโดยดูจากชุดค่าผสมที่เป็นไปได้ทั้งหมดของถนนที่คุณอาจจะใช้แล้วจะบอกให้คุณทราบว่าวิธีใดเป็นวิธีที่เร็วที่สุด แน่นอนว่าคุณอาจต้องรอสักครู่จนกว่าอัลกอริทึมจะเสร็จสิ้นและจากนั้นจึงเริ่มขับรถเท่านั้น เส้นทางที่คุณจะใช้จะเป็นเส้นทางที่เร็วที่สุด (สมมติว่าไม่มีอะไรเปลี่ยนแปลงในสภาพแวดล้อมภายนอก)

Brute Force กำลังพยายามแก้ปัญหาที่เป็นไปได้ก่อนตัดสินใจเลือกทางออกที่ดีที่สุด

การเขียนโปรแกรมแบบไดนามิกแตกต่างจาก Brute Force อย่างไรหากผ่านโซลูชั่นที่เป็นไปได้ทั้งหมดก่อนที่จะเลือกสิ่งที่ดีที่สุดความแตกต่างเดียวที่ฉันเห็นคือการเขียนโปรแกรมแบบไดนามิกคำนึงถึงปัจจัยเพิ่มเติม (สภาพการจราจรในกรณีนี้)

ฉันถูกต้องหรือไม่ที่จะบอกว่า Dynamic Programming เป็นส่วนหนึ่งของวิธี Brute Force?


1
สภาพการจราจรเป็นปลาเฮอริ่งแดง คุณสามารถพิจารณาได้ในอัลกอริทึมใด ๆ
Yuval Filmus

คำตอบที่เกี่ยวข้อง
กราฟิลส์

คำพูดแรกของคุณไม่ได้กำหนดโปรแกรมแบบไดนามิก
reinierpost

@reierierpost ก็พยายามไปด้วยintelligent, brute forceแต่ก็ลืมอธิบายส่วน "ปัญญา"
Izkata

@Izkata ด้วยเหตุผลนั้นทุกอัลกอริทึมคือ "กำลังดุร้ายกำลังฉลาด" (ซึ่งเป็นรูปแบบ oxymoron อยู่ดี)
ราฟาเอล

คำตอบ:


17

อัลกอริทึมการเขียนโปรแกรมแบบไดนามิกจะตรวจสอบวิธีที่เป็นไปได้ทั้งหมดในการแก้ปัญหาและจะเลือกทางออกที่ดีที่สุด

คำสั่งนี้เป็นเพียงผิดธรรมดา

การเกิดซ้ำของการเขียนโปรแกรมแบบไดนามิกทำ (บ่อยครั้ง) พิจารณาวิธีที่เป็นไปได้ทั้งหมดเพื่อแยกอินสแตนซ์ปัญหาที่กำหนดเป็นอินสแตนซ์ขนาดเล็กตามรูปแบบบางอย่าง แต่ก็จะไม่ได้รวมทั้งหมดของการแก้ปัญหาบางส่วนทั้งหมดที่มีแต่ละอื่น ๆ และเลือกที่ดีที่สุด - มันรวมเท่านั้นที่ดีที่สุดการแก้ปัญหาบางส่วน (และหยิบสิ่งที่ดีที่สุดของคนเหล่านั้น)

ความจริงที่ว่าวิธีนี้ให้ผลที่ดีที่สุดสำหรับปัญหาดั้งเดิมนั้นไม่ได้เป็นเรื่องเล็กน้อยและในความเป็นจริงแล้วมีเพียงปัญหาบางอย่างเท่านั้น คือผู้ที่ปฏิบัติตามหลักการของการมองโลกในแง่ดีที่สุด (หนึ่งในคำจำกัดความ "คาว" ที่มีการกล่าวอ้างอย่างสม่ำเสมอ) ดูที่นี่สำหรับความคิดเพิ่มเติมเกี่ยวกับเรื่องนี้

ในฐานะที่เป็นตัวอย่างที่เป็นรูปธรรมให้พิจารณาขั้นตอนวิธีการ Bellman ฟอร์ดในกราฟสมบูรณ์ที่มีน้ำหนักหน่วย: มันเท่านั้นที่เคยพิจารณาเส้นทางที่หนึ่งและสองความยาว (เช่นΘ ( n 2 )อีกหลายคน) เพราะผู้ที่ใช้ขอบเป็นที่ดีที่สุดทั้งหมด แต่มีวิธีแก้ไขมากมายถ้าคุณไม่ จำกัด จำนวนขอบสูงสุดที่อนุญาตและยังคง( n - 1 ) ! มากถ้าคุณอนุญาตให้ทุกโหนดใช้เพียงครั้งเดียว อย่างชัดเจน Bellman-Ford - อัลกอริธึมการเขียนโปรแกรมแบบไดนามิก - ไม่ทำการค้นหาที่โหดเหี้ยมKnΘ(n2)»(n-1)!


"คำสั่งนี้เป็นเพียงผิดธรรมดา" - Fix มัน
nmclean

4
@nmclean ประสบการณ์ของฉันกับการแก้ไขบทความที่เกี่ยวข้องกับอัลกอริทึมใน Wikipedia นั้นน่าพอใจน้อยกว่ามาก ฉันควรลงทุนเวลาของฉันที่นี่
ราฟาเอล

ฉันลองเสี่ยงโชคและแก้ไขบทความ หวังว่าตอนนี้มันผิดน้อยไปหน่อย
C4stor

9

การเขียนโปรแกรมแบบไดนามิกนั้นฉลาดในขณะที่มันนำการคำนวณมาใช้ใหม่ สมมติว่าแก้, f (6), คุณต้องแก้ปัญหาย่อย 2 ข้อซึ่งทั้งคู่เรียก f (3) วิธีการบังคับเดรัจฉานจะคำนวณ f (3) สองครั้งจึงเป็นการสิ้นเปลืองในขณะที่การเขียนโปรแกรมแบบไดนามิกจะเรียกมันครั้งเดียวบันทึกผลลัพธ์ในกรณีที่การคำนวณในอนาคตจำเป็นต้องใช้มัน ในหลาย ๆ ปัญหาพลวัตช่วยเพิ่มความซับซ้อนแบบทวีคูณของกำลังดุร้ายกับความซับซ้อนแบบพหุนาม


9
นั่นคือการบันทึกความทรงจำซึ่งเป็นหนึ่งในหลายเทคนิคที่ DP ใช้
Ben Voigt

4
แรงเดรัจฉานกับ memoisation ยังไม่มีประสิทธิภาพ โครงสร้างเพิ่มเติม / การตัดแต่งกิ่งที่จัดทำโดยการเกิดซ้ำของ DP ทำให้การชำระหนี้มีผล
กราฟิลส์

3
ฉันไม่รู้อะไรเลยเกี่ยวกับการเขียนโปรแกรมแบบไดนามิก แต่ฉันค่อนข้างแน่ใจว่ามีมากกว่านั้นเพียงแค่เพิ่มแคชไปยังอัลกอริทึมแรงเดรัจฉาน ฉันคิดว่าการเขียนโปรแกรมแบบไดนามิกหลีกเลี่ยงการทดสอบชุดค่าผสมที่เป็นไปได้ทั้งหมดโดยแบ่งย่อยปัญหาพื้นที่ออกค้นหาวิธีแก้ปัญหาที่ดีที่สุดสำหรับการแบ่งย่อยย่อยแล้วรวมเข้าด้วยกันเพื่อสร้างโซลูชันที่ดีที่สุดโดยรวม (มันอาจทำแบบนี้ซ้ำ ๆ ย่อย ๆ ในส่วนย่อย) มันใช้งานได้ก็ต่อเมื่อคุณสามารถแสดงปัญหาในแบบที่ช่วยให้การรวมกันของการแก้ปัญหาเช่นนี้และยังได้รับที่เหมาะสมโดยรวม
Jonathan Hartley

1
คำตอบนี้ค่อนข้างแม่นยำจริง ๆ ฉันแนะนำให้อ่านหนังสือเช่น Cormen et al: "ความรู้เบื้องต้นเกี่ยวกับอัลกอริทึม" เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับการเขียนโปรแกรมแบบไดนามิกหนังสือเล่มนี้มีบทที่ดีพอสมควร สรุปการเขียนโปรแกรมแบบไดนามิกที่มีประสิทธิภาพใช้ประโยชน์จากคุณสมบัติสองประการของปัญหา (การปรับให้เหมาะสม) ที่คุณต้องการแก้ไข: วิธีการแก้ปัญหาที่ดีที่สุดสามารถสร้างได้จากการแก้ปัญหาที่ดีที่สุดของปัญหาย่อยที่มีขนาดเล็กลง เล็ก จากนั้นคุณสามารถสร้างการแก้ปัญหาย่อยทั้งหมดจากล่างขึ้นบนเร่งการคำนวณด้วยต้นทุนของหน่วยความจำ
MRA

หรือเพื่อให้ง่ายขึ้น: ถ้าคุณรู้วิธีคำนวณสัมประสิทธิ์ทวินามโดยใช้สามเหลี่ยมของปาสคาลคุณก็รู้ทุกอย่างที่คุณจำเป็นต้องรู้เกี่ยวกับการเขียนโปรแกรมแบบไดนามิก
MRA

3

ความแตกต่างที่บทความวิกิพีเดียอาจพยายามทำอยู่ระหว่างอัลกอริธึมสามประเภท:

  1. อัลกอริธึมที่ครอบคลุมโซลูชันที่เป็นไปได้ทั้งหมด

  2. อัลกอริธึมที่ผ่านชุดย่อยของโซลูชันที่เป็นไปได้ทั้งหมดเลือกเพื่อให้โซลูชันที่เหมาะสมเป็นของชุดย่อย

  3. อัลกอริธึมที่ผ่านชุดย่อยของโซลูชันที่เป็นไปได้ทั้งหมดโดยไม่มีการรับประกันว่าโซลูชันที่ดีที่สุดเป็นของชุดย่อย

อัลกอริทึมสองประเภทแรกสร้างโซลูชันที่ดีที่สุดในขณะที่ประเภทที่สามมีจุดมุ่งหมายเพื่อผลิตโซลูชันที่ "ดี" แทนที่จะเป็นโซลูชันที่ดีที่สุด ในความคิดของฉันความแตกต่างระหว่างสองชนิดแรกนั้นไม่ชัดเจนนัก

ฉันขอเริ่มด้วยการยกตัวอย่างง่ายๆสำหรับอัลกอริธึมทั้งสามประเภทในบริบทของเส้นทางที่สั้นที่สุด (ตัวอย่างที่คุณให้)

  1. ลองเส้นทางที่เป็นไปได้ทั้งหมด นี้เรียกว่าแรงเดรัจฉาน

  2. ลองเส้นทางที่เป็นไปได้ทั้งหมดติดตามการแก้ปัญหาขั้นต่ำจนถึงตอนนี้ เมื่อใดก็ตามที่เส้นทางปัจจุบันที่คุณกำลังสร้างมีราคาแพงกว่าวิธีการแก้ปัญหาขั้นต่ำสุดให้ละทิ้งมันและเลือกอีกเส้นทางหนึ่ง (เราจินตนาการว่าระยะทางนั้นคำนวณตามส่วนของแต่ละส่วน นี้เรียกว่าการตัดแต่งกิ่ง

  3. ดูแผนที่พิจารณาเส้นทางไม่กี่เส้นทางและเลือกเส้นทางที่ดีที่สุด นี่เป็นอัลกอริธึมสำหรับมนุษย์มากกว่าคอมพิวเตอร์

ตัวอย่างเหล่านี้ค่อนข้างหยาบและอาจไม่ได้วาดภาพที่แม่นยำมากนัก การตัดแต่งกิ่งมีความสำคัญในหลาย ๆ สถานการณ์เช่นในหมากรุกคอมพิวเตอร์ หากคุณสงสัยให้ค้นหาอัลกอริทึมA *ซึ่งใช้กับเส้นทางที่สั้นที่สุด

การเขียนโปรแกรมแบบไดนามิกเป็นเทคนิคสำหรับการเร่งความเร็วขั้นตอนวิธีกำลังดุร้าย อย่างไรก็ตามมันค่อนข้างทำให้เข้าใจผิดคิดว่าวิธีนี้ มันเป็นเทคนิคอัลกอริทึมสำหรับการแก้ปัญหาการเพิ่มประสิทธิภาพ คุณสามารถใช้การตัดแต่งกิ่งในบริบทของการเขียนโปรแกรมแบบไดนามิก

เสื้อเสื้อเสื้อ+1เสื้อ


แล้วก็มีการลบผู้สมัครออกจากการพิจารณาโดยไม่ต้องดำเนินการอย่างเต็มที่ ตัวอย่างเช่นการค้นหาชุดของตัวเลขที่ไม่เป็นลบด้วยผลรวมขั้นต่ำคุณไม่จำเป็นต้องรวมแต่ละชุดอย่างสมบูรณ์ให้ไปจนกว่าผลรวมจะเกินจำนวนที่ดีที่สุดในปัจจุบัน นี่คือความคิดที่คล้ายกันกับการตัดแต่งกิ่ง แต่มุมฉาก การรวมแนวคิดทั้งสองเข้าด้วยกันทำให้เกิด "สาขาและขอบเขต" ซึ่งปัญหาของความซับซ้อนที่ลดลงได้รับการแก้ไขและนำมาใช้เพื่อพิสูจน์ความถูกต้องของการตัดแต่งกิ่ง
Ben Voigt

0

การเขียนโปรแกรมแบบไดนามิกเร็วกว่าแรงเดรัจฉานมาก กำลังดุร้ายอาจใช้เวลาชี้แจงในขณะที่การเขียนโปรแกรมแบบไดนามิกมักจะเร็ว

การเปรียบเทียบกับกำลังดุร้ายนั้นเป็นสิ่งที่หลวมมาก การเขียนโปรแกรมแบบไดนามิกไม่ใช่กระสุนเงินเวทย์มนตร์ที่ให้คุณใช้อัลกอริทึมแรงเดรัจฉานใด ๆ ที่คุณต้องการและทำให้มีประสิทธิภาพ


5
นั่นเป็นผลไม่ใช่คำอธิบาย
กราฟิลส์

-2

ตรงไปตรงมานี้ การเขียนโปรแกรมแบบไดนามิกเป็น "กลยุทธ์การค้นหา" ซึ่งใช้ปัจจัยเพิ่มเติมเพื่อ จำกัด การค้นหาให้แคบลง หากมีการแก้ปัญหาในพื้นที่การค้นหาที่ไม่มีการเขียนโปรแกรมแบบไดนามิกจะ (ปกติ) จะค้นหาผ่านองค์ประกอบของพื้นที่ค้นหาทุก แต่นั่นไม่ได้หมายความว่าเป็นการค้นหาที่ดุร้าย


"หากไม่มีวิธีแก้ปัญหาในพื้นที่การค้นหาการเขียนโปรแกรมแบบไดนามิก (โดยทั่วไป) จะทำการค้นหาผ่านทุกองค์ประกอบของพื้นที่การค้นหา" - ผิดดูคำตอบของฉัน
ราฟาเอล

-2

คำแถลงว่าการตั้งโปรแกรมแบบไดนามิกเป็นแรงเดรัจฉานอัจฉริยะถูกต้อง แต่ยากที่จะเข้าใจด้วยการใช้ถ้อยคำนั้น จุดของการเขียนโปรแกรมแบบไดนามิกโดยทั่วไปจะมีปัญหาและแบ่งออกเป็นชิ้นเล็ก ๆ ในวิธีที่ชาญฉลาด หลังจากที่คุณทำเสร็จแล้วคุณจะใช้กำลังดุร้ายเพื่อแก้ปัญหาชิ้นส่วนเล็ก ๆ แต่ละชิ้นแล้วคุณจะใช้กำลังดุร้ายอีกครั้งเพื่อรวมชิ้นส่วนเข้าด้วยกันเป็นทางออกสุดท้าย ดังนั้นในขณะที่คุณสามารถพูดได้อย่างแน่นอนว่าการเขียนโปรแกรมแบบไดนามิกเป็นวิธีการแก้ปัญหากำลังดุร้ายชนิดหนึ่งเคล็ดลับอยู่ที่วิธีที่คุณใช้กำลังดุร้ายนั้น


1
"คุณจะใช้กำลังดุร้ายเพื่อแก้ปัญหาแต่ละชิ้นเล็ก ๆ " - ผิด โดยทั่วไปคุณจะใช้วิธีเดียวกันนี้ซ้ำ ๆ
FrankW
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.