ผู้ใช้:Archnat
ลิงก์ข้ามภาษาในบทความนี้ มีไว้ให้ผู้อ่านและผู้ร่วมแก้ไขบทความศึกษาเพิ่มเติมโดยสะดวก เนื่องจากวิกิพีเดียภาษาไทยยังไม่มีบทความดังกล่าว กระนั้น ควรรีบสร้างเป็นบทความโดยเร็วที่สุด |
การค้นหาแบบสองทิศทาง (อังกฤษ: Bidirectional Search) คือวิธีหนึ่งที่ใช้สำหรับการค้นหาข้อมูลภายในกราฟที่มีการระบุทิศทาง โดยมีจุดประสงค์เป็นการหาระยะทางสั้นสุดจากจุดเริ่มต้นไปยังจุดสิ้นสุดบนกราฟ หลักการค้นหาที่เป็นเอกลักษณ์ของวิธีการนี้ก็คือเราจะทำการค้นหาจากจุดเริ่มไปยังจุดสิ้นสุดและจากจุดสิ้นสุดกลับมายังจุดเริ่มต้นไปพร้อมๆกัน และเมื่อการค้นหามาบรรจบพร้อมกันที่จุดๆหนึ่งระหว่างกลางก็จะถือเป็นอันสิ้นสุด นอกจากนี้การค้นหาแบบสองทิศทางนี้ยังสามารถนำเอาไปประยุกต์รวมเข้ากับการค้นหาแบบอื่นๆเพื่อให้ได้ประสิทธิภาพที่ดียิ่งขึ้นได้ ตัวอย่างของวิธีการค้นหาที่สามารถนำเอามาประยุกต์กับการค้นหาแบบสองทิศทางเช่น Breadth-first search, Best-first search, ขั้นตอนวิธีเอสตาร์เป็นต้น ทั้งนี้ก็เพื่อที่จะเพิ่มประสิทธิภาพในการค้นหาให้ดีที่สุดนั่นเอง
นิยาม
[แก้]การค้นหาแบบสองทิศทางนั้นโดยนิยามแล้วก็คือขั้นตอนวิธีที่ใช้หลักการซึ่งคล้ายกับขั้นตอนวิธีแบ่งแยกเพื่อเอาชนะ(อังกฤษ: Divide and conquer)ในกรณีที่เราทราบตำแหน่งของเป้าหมายที่จะค้นหาแล้ว แทนที่จะค่อยๆเริ่มจากจุดเริ่มต้นไปยังจุดปลายเราจะทำการค้นหาจากจุดปลายย้อนกลับมาหาจุดเริ่มต้นไปพร้อมๆกันแทน ด้วยวิธีนี้ความเร็วในการค้นหาของแต่ละเส้นทางจะอยู่ที O (bd/2) เมื่อ คือจำนวนการแตกกิ่งก้าน (Branching factor) และ คือระยะทางทั้งหมดจากจุดเริ่มต้นไปยังจุดสิ้นสุด ซึ่งเมื่อนำระยะเวลาการค้นหามารวมกันแล้วก็ยังถือว่าได้ลดเวลาในการค้นหาลงไปอย่างมากหากเทียบกับการค้นหาแบบปกติ O (bd)
อย่างไรก็ตามแม้ว่าวิธีการนี้จะดูเหมือนว่าสามารถที่จะลดเวลาการค้นหาไปได้อย่างมากก็ตาม ข้อเสียของมันก็ยังมีอยู่หลายข้อด้วยกันคือ
- วิธีการค้นหาแบบสองทิศทางมีลักษณะที่เป็นศึกษาสำนึกหรือก็คือไม่สามารถบอกได้อย่างแน่นอนว่าเส้นทางที่หาได้เป็นเส้นทางที่ดีที่สุดหรือไม่
- ในการออกแบบขั้นตอนวิธีจำเป็นที่จะต้องคิดหาวิธีการที่จะทำให้สามารถค้นหาจากจุดปลายให้ย้อนกลับมายังจุดเริ่มต้นได้
- ต้องออกแบบวิธีการหาจุดเชื่อมต่อที่มาจากการค้นของทั้งสองทิศทาง
- ต้องมีการกำหนดเป้าหมายว่าอยู่ที่ใดบนกราฟ
ด้วยสาเหตุทั้งปวงที่กล่าวมาทำให้การนำเอาวิธีการค้นหาแบบสองทิศทางไปใช้งานจริงนั้นจึงยุ่งยากพอสมควร
ประวัติ
[แก้]Ira Pohlคือบุคคลแรกที่ออกแบบและนำเอาการค้นหาแบบสองทิศทางมาใช้ในปีค.ศ.1971 เริ่มแรกนั้นขั้นตอนวิธีดังกล่าวไม่มีประสิทธิภาพมากนักคือการค้นหาจากสองทางมักจะพลาดไม่ได้มาบรรจบกันทำให้ได้ผลลัพธ์ที่ผิดพลาด ต่อมาในปีค.ศ.1983 Des Champeaux ได้ออกแบบขั้นตอนวิธีใหม่เพื่อเข้ามาใช้แก้ปัญหาดังกล่าวด้วยวิธีแบบBHFFA(Bidirectional heuristic front to front algorithm)แต่ก็ทำให้เกิดปัญหาในเรื่องพื้นที่หน่วยความจำ ต่อมาในปีค.ศ.1984 PohlและPolitowiskyได้นำเสนอทางออกอีกแบบที่เขาเรียกว่า D-node retargetingขึ้นมาซึ่งสามารถช่วยแก้ปัญหาที่มีมาแต่เดิมรวมถึงเรื่องของหน่วยความจำได้อย่างมีประสิทธิภาพกว่าเก่า
หลังจากนั้นวิธีการค้นหาแบบสองทิศทางก็ได้ผ่านการปรับปรุงเรื่อยมาอีกหลายครั้งจนถึงล่าสุดคือปีค.ศ.2009โดยWimและHenk ซึ่งได้คิดค้นออกแบบการค้นหาแบบสองทิศทางของเอสตาร์ที่ได้รับการปรังปรุงให้ค้นหาได้อย่างมีประสิทธิภาพยิ่งขึ้น
การทำงาน
[แก้]
จากกราฟด้านบนเราจะสามารถมองเห็นการทำงานคร่าวๆได้โดย หากเราสมมติให้ วงกลมแต่ละวงคือปมของกราฟโดยที่แต่ละปมจะเก็บค่าตำแหน่งของปมนั้นๆเอาไว้ เส้นเชื่อมที่หนาจะหมายถึงค่าใช้จ่ายที่มากกว่าในการเดินทางผ่าน ส่วนปมที่ถูกทาด้วยสีฟ้าจะหมายถึงเป็นปมที่ถูกเลือกและปมสีแดงคือจุดที่คาดว่าการค้นหาจากสองทิศทางมาบรรจบกัน เส้นประใช้แสดงขอบเขตของการค้นหาแยกแต่ละฝั่งเอาไว้
ในแง่ของการนำเอาไปใช้งานจริงนั้น การค้นหาแบบสองทิศทางมักจะถูกนำไปรวมเข้ากับขั้นตอนวิธีแบบอื่นเสียมากกว่า ทั้งนี้ก็เพื่อที่จะให้ได้ผลลัพธ์ออกมาตามแต่ที่ต้องการ
รหัสเทียม
[แก้]ขั้นตอนวิธีสามารถแสดงโดยสังเขปด้วยรหัสเทียมได้ดังนี้
function BiderectionalSearch(xs,xg)
define Qs,Qg as priority queue //กำหนดแถวคอยแบบลำดับความสำคัญ ให้Qsคือแถวคอยที่ใช้เก็บเริ่มจากปมเริ่มต้น และQgคือแถวคอยที่ใช้เก็บเริ่มจากปมเป้าหมาย
Qs.insert(xs) and mark xs as visited //นำปมเริ่มต้น xsใส่ลงในQs และเปลี่ยนสถานะของxsให้เป็นปมที่ถูกพิจารณาแล้ว
Qg.insert(xg) and mark xg as visited //นำปมเป้าหมาย xgใส่ลงในQg และเปลี่ยนสถานะของxgให้เป็นปมที่ถูกพิจารณาแล้ว
while Qs not empty and Qg not empty
if(Qs not empty)
x:=Qs.getFirst()
if x = xg or x ɛ Qg //ถ้าหากว่าปมที่กำลังดูเป็นปมเป้าหมายหรือว่าเป็นปมที่อยู่ในแถวคอยของเป้าหมายแล้วก็ให้แสดงออกไปว่าหาพบและเลิกทำ
return SUCCESS
for each v ɛ adj(x) //สำหรับทุกๆปมที่มีเส้นเชื่อมต่อออกx หากปมๆนั้นยังไม่เคยถูกพิจารณาก็ให้เอาเข้าแถวคอยไป
if v is not visited
Mark v status as visited
Qs.insert(v)
if(Qg not empty)
xr:=Qg.getFirst()
if xr = xs or xr ɛ Qs //ถ้าหากว่าปมที่กำลังดูเป็นปมเริ่มต้นหรือว่าเป็นปมที่อยู่ในแถวคอยของปมเริ่มต้นแล้วก็ให้แสดงออกไปว่าหาพบและเลิกทำ
return SUCCESS
for each vr ɛ inversed_adj(xr) //สำหรับทุกๆปมที่มีเส้นเชื่อมมายังxr หากปมๆนั้นยังไม่เคยถูกพิจารณาก็ให้เอาเข้าแถวคอยไป
if vr is not visited
Mark vr status as visited
Qs.insert(vr)
return FAILURE //ถ้าทำจนหมดแล้วยังเชื่อมเส้นกันไม่ได้ก็คือไม่มีเส้นเชื่อมระหว่างxsกับxg
อ้างอิง
[แก้]- de Champeaux, Dennis; Sint, Lenie (1977), "An improved bidirectional heuristic search algorithm", Journal of the ACM, 24 (2): 177–191, doi:10.1145/322003.322004.
- de Champeaux, Dennis (1983), "Bidirectional heuristic search again", Journal of the ACM, 30 (1): 22–32, doi:10.1145/322358.322360.
- Ghosh, Subrata; Mahanti, Ambuj (1991), "Bidirectional Heuristic Search with Limited Resources", Inf. Process. Lett.: 335–340.
- Pohl, Ira (1971), "Bi-directional Search", ใน Meltzer, Bernard; Michie, Donald (บ.ก.), Machine Intelligence, vol. 6, Edinburgh University Press, pp. 127–140.
- Russell, Stuart J.; Norvig, Peter (2002), "3.4 Uninformed search strategies", Artificial Intelligence: A Modern Approach (2nd ed.), Prentice Hall.
- Davis, Henry W.; Pollack, Randy B.; Sudkamp, Thomas (1984), "Towards a better understanding of Bidirectional search", AAAI'84: 68–72.
- Pijls, Wim; Post, Henk (2009), "A new bidirectional search algorithm with shortened postprocessing", European Journal of Operational Research: 363–369.