การค้นหาเส้นทางที่คำนวณล่วงหน้าแล้วยังมีความเกี่ยวข้องหรือไม่


12

บริบท

Old Lucas Arts (ScummVM era) ชี้และคลิกเกมผจญภัยกราฟิกที่ใช้การคำนวณเส้นทางก่อน นี่คือคร่าวๆของเทคนิค

ขั้นตอนที่ 1

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

 ______ _____ _________ _____
\   A  |  B  |    C    |  D   \
 \_____|     |         |_______\
       |_____|         |
             |_________|

ขั้นตอนที่ 2

อัลกอริทึมออฟไลน์ (เช่น Dijkstra หรือ A *) จะคำนวณเส้นทางที่สั้นที่สุดระหว่างแต่ละโหนดและทุกคู่ของโหนดและเก็บขั้นตอนแรกของเส้นทางในเมทริกซ์ 2D โดยสร้างดัชนีในแต่ละมิติโดยใช้โหนดเริ่มต้นและสิ้นสุด เช่นใช้กล่องเดินด้านบน:

      ___ ___ ___ ___
     | A | B | C | D | <- Start Node
  ___|___|___|___|___|
 | A | A | A | B | C |  ---
 |___|___|___|___|___|     |
 | B | B | B | B | C |     |
 |___|___|___|___|___|     |-- Next node in shortest path
 | C | B | C | C | C |     |   from Start to End
 |___|___|___|___|___|     | 
 | D | B | C | D | D |  ---
 |___|___|___|___|___| 
   ^
   |
End Node

ในขณะที่คุณอาจเดาว่าความต้องการหน่วยความจำเพิ่มขึ้นอย่างรวดเร็วเมื่อจำนวนโหนดเพิ่มขึ้น (N ^ 2) เนื่องจากสั้นมักจะมีขนาดใหญ่พอที่จะเก็บแต่ละรายการในเมทริกซ์ด้วยแผนที่ที่ซับซ้อนของ 300 โหนดที่จะส่งผลในการจัดเก็บพิเศษ:

300^2 * sizeof(short) = 176 kilobytes

ขั้นตอนที่ 3

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

// Find shortest path from Start to End
Path = {Start}
Current = Start
WHILE Current != End
    Current = LookUp[Current, End]
    Path.Add(Current)
ENDWHILE

ใช้อัลกอริทึมง่าย ๆ นี้เพื่อค้นหาเส้นทางที่สั้นที่สุดจาก C ถึง A:

1) Path = { C }, Current = C
2) Path = { C, B }, Current = B
3) Path = { C, B, A }, Current = A, Exit

คำถาม

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

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

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

ในเครื่องยนต์ของฉันฉันยังต้องการความสามารถในการเพิ่มและลบโหนดในกราฟแบบไดนามิก ( ดูที่นี่ ) ดังนั้นเส้นทางที่กำหนดไว้ล่วงหน้าทำให้สิ่งที่ซับซ้อนมากขึ้นเท่านั้นดังนั้นฉันจึงทิ้งมันไว้ ) ถึงกระนั้นฉันก็ยังสงสัยว่า ...

บรรทัดล่างเทคนิคนี้ยังคงมีความเกี่ยวข้องในทุกสถานการณ์หรือไม่?


2
ฉันคิดว่ามันยังเกี่ยวข้องถ้าคุณใช้งบประมาณของ CPU ที่ จำกัด แต่เมื่อคุณต้องการเส้นทางแบบไดนามิกมันก็ไม่มีประโยชน์อีกต่อไป Btw ฉันดูที่คุณได้อัลกอริธึม A * ของคุณจากและคุณสามารถเพิ่มประสิทธิภาพได้ยิ่งขึ้นโดยใช้ minheap และเทคนิคอื่น ๆ ฉันได้ทำซ้ำการปรับปรุง A * ใน C # ซึ่งคุณสามารถดูได้ที่นี่: roy-t.nl/index.php/2011/09/24/…อาจเป็นประโยชน์
Roy T.

1
ขอบคุณฉันได้ทำบุ๊กมาร์กแล้วและจะตรวจดูเมื่อฉันเริ่มปรับใบสมัครให้เหมาะสม ฉันค่อนข้างใช้โซลูชันของ Eric Lippert ด้วยการปรับเปลี่ยนเล็กน้อยเพราะมันสะอาดและง่ายต่อการติดตาม ... และสำหรับกรณีทดสอบทั้งหมดของฉันมันวิ่งได้ค่อนข้าง "ทันที" ดังนั้นฉันจึงไม่ต้องกังวลกับการปรับให้เหมาะสม
David Gouveia

1
BTW ถ้าคุณตัดสินใจที่จะไล่ตาม precomputation คุณอาจต้องการที่จะมองไปที่ขั้นตอนวิธี Floyd-Warshall มันสร้างเมทริกซ์“ ขั้นตอนต่อไป” มีประสิทธิภาพมากกว่าการใช้ Dijkstra / A ซ้ำ ๆ
amitp

@amitp ขอบคุณสำหรับเคล็ดลับมันเป็นเรื่องดีเสมอที่จะรู้เกี่ยวกับทางเลือกเหล่านี้! แม้ว่าในกรณีส่วนใหญ่การคำนวณล่วงหน้าจะทำแบบออฟไลน์ แต่ก็ไม่ได้ประโยชน์มากนักที่จะทำให้มีประสิทธิภาพมากขึ้น นอกเสียจากว่าคุณจะใจร้อนจริงๆ :-)
David Gouveia

เห็นด้วยแม้ว่า Floyd-Warshall นั้นง่ายกว่าการใช้งานมากกว่าอัลกอริทึมของ Dijkstra ดังนั้นหากคุณยังไม่ได้นำ Dijkstra มาใช้มันก็คุ้มค่าที่จะดู :)
amitp

คำตอบ:


3

ในเครื่องยนต์ของฉันฉันยังต้องการความสามารถในการเพิ่มและลบโหนดในกราฟแบบไดนามิก (ดูที่นี่) ดังนั้นเส้นทางที่กำหนดไว้ล่วงหน้าทำให้สิ่งที่ซับซ้อนมากขึ้นเท่านั้นดังนั้นฉันจึงทิ้งมันไว้ (ไม่พูดถึง runtime A * ของฉัน ) ถึงกระนั้นฉันก็ยังสงสัยว่า ...

บรรทัดล่างเทคนิคนี้ยังคงมีความเกี่ยวข้องในทุกสถานการณ์หรือไม่?

ฉันไม่เห็นประโยชน์จากการใช้เทคนิคดังกล่าว

ฉันไม่มีความยืดหยุ่นของกราฟ (คุณสามารถมี LOD ที่แตกต่างกันพวกเขาไม่จำเป็นต้องมีรูปร่างที่เฉพาะเจาะจงใด ๆ , ect ... ) ผู้ใช้เครื่องยนต์ของคุณจะรู้ว่ากราฟคืออะไรและใช้อย่างไร ดังนั้นหากพวกเขาต้องการเพิ่มฟังก์ชันการทำงานพิเศษพวกเขาจะต้องเรียนรู้วิธีการใช้ส่วนขยายโดยใช้สถานการณ์ที่แปลกใหม่สำหรับพวกเขา

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

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

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

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

ยังตระหนักว่ามีหลายเกมที่มีการแยกลูปสำหรับอัปเดต AI ฉันเชื่อว่าเขาตั้งค่าโปรเจคของฉันคือมีลูปการอัปเดตสำหรับผู้ใช้ที่ 60Hz AI มีเพียง 20 เฮิร์ตและเกมวาดเร็วที่สุด

นอกจากนี้ฉันยังได้เขียนโปรแกรม GBA เพื่อความสนุกสนานและไม่มีการถ่ายโอนใด ๆ ไปยังอุปกรณ์ที่ทันสมัย สำหรับ GBA ทุกอย่างเกี่ยวกับการลดปริมาณงานของโปรเซสเซอร์ (เพราะมันน่าสงสาร) คุณต้องตระหนักว่าภาษาระดับสูงส่วนใหญ่ C # และ Java (ไม่มาก C ++ หรือ C) ทำสิ่งต่าง ๆ ให้เกิดประโยชน์สูงสุดสำหรับคุณ สำหรับการปรับแต่งรหัสคุณไม่ได้ทำอะไรนอกจากการเข้าถึงหน่วยความจำน้อยที่สุดเท่าที่จะเป็นไปได้และเมื่อคุณทำการคำนวณให้มากที่สุดเท่าที่จะทำได้ก่อนที่จะนำหน่วยความจำใหม่ที่จะชนออกจากแคชและทำให้แน่ใจว่าคุณ ทำสิ่งเดียวครั้งเดียว

แก้ไข: นอกจากนี้ยังตอบคำถามของคุณใช่ การคำนวณเส้นทางล่วงหน้าที่ใช้บ่อยเป็นแนวคิดที่ยอดเยี่ยมและสามารถทำได้ด้วย A * ที่ใดก็ได้นอกวงเกมของคุณ ตัวอย่างเช่นจากคุณฐานไปยังทรัพยากรใน RTS เพื่อให้การรวบรวมไม่จำเป็นต้องคำนวณใหม่ทุกครั้งที่ต้องการออกหรือส่งคืน


เกี่ยวกับการแก้ไขของคุณผมไม่ได้จริงๆพูดคุยเกี่ยวกับ precomputing เส้นทางที่ใช้บ่อย แต่อย่างเคร่งครัดเกี่ยวกับเทคนิคที่ระบุไว้ของ precomputing ทุกเส้นทางที่เป็นไปได้เพียงครั้งเดียว ฉันก็สับสนเล็กน้อยว่าคำตอบส่วนใหญ่ของคุณขัดกับการใช้การบอกเส้นทางแบบ precomputed แต่ท้ายที่สุดคุณก็บอกว่ามันเป็นแนวคิดที่ยอดเยี่ยม ดังนั้นมันจะมีประโยชน์กับสภาพแวดล้อมที่ จำกัด ของ CPU เช่น GBA หรือไม่
David Gouveia

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

2
@ClassicThunder: เทคนิคการคำนวณล่วงหน้าเส้นทางทั้งหมดจากสถานที่สำคัญบางแห่งมักจะถูกเรียกว่าALT : A-star ที่มี Landmarks & Triangle-inequality : cs.princeton.edu/courses/archive/spr06/cos423/Handouts/GW05 pdf
Pieter Geerkens
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.