Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

ทฤษฎีกราฟเชิงปฏิบัติใน Ruby

นี่เป็นงวดถัดไปในซีรีส์ “วิทยาการคอมพิวเตอร์เชิงปฏิบัติ” ที่คุณจะได้เรียนรู้วิธีใช้แนวคิดวิทยาการคอมพิวเตอร์แบบคลาสสิกเพื่อแก้ปัญหาจริงโดยใช้ Ruby

วันนี้เราจะมาพูดถึง ทฤษฎีกราฟ .

คุณอาจเคยได้ยินเกี่ยวกับไบนารีทรี พวกมันมีลักษณะดังนี้:

ทฤษฎีกราฟเชิงปฏิบัติใน Ruby

ประเด็นก็คือ ต้นไม้ไบนารีเป็นเพียงกราฟรุ่นพิเศษ ดังนั้นควรให้แนวคิดแก่คุณว่ากราฟมีความกว้างเพียงใด

มาเริ่มกันที่ภาพรวมของพื้นฐานทฤษฎีกราฟกันก่อน จากนั้นเราจะมาดูกันว่าการใช้งานจริงมีอะไรบ้างและจะใช้งานสิ่งนี้ใน Ruby ได้อย่างไร

กราฟพื้นฐาน

กราฟประกอบด้วยสององค์ประกอบ:

  • โหนด (หรือจุดยอด)
  • ขอบ

โหนดหนึ่งแสดงถึงองค์ประกอบหนึ่งในกราฟ เช่น เมืองหรือถนน ในกราฟที่แสดงแผนที่ ในขณะที่ขอบแสดงถึงการเชื่อมต่อระหว่างโหนด

หากคุณดูหนังสือวิทยาศาสตร์คอมพิวเตอร์หรือคณิตศาสตร์ คุณจะเห็นกราฟที่กำหนดโดยสูตรนี้:G(V, E) .

โดยที่ G หมายถึงกราฟ V คือเซตของจุดยอด &E คือเซตของขอบ

กราฟสามารถกำหนดทิศทางหรือไม่มีทิศทางได้ หมายความว่าคุณสามารถไปได้เพียงทิศทางเดียว (กราฟบอกทิศทาง) หรือทั้งสองทิศทาง (กราฟแบบไม่บอกทิศทาง)

กราฟที่ได้รับความนิยมมากที่สุดคือ กราฟ Acyclic แบบกำกับทิศทาง (DAG). Acyclic หมายถึง ไม่มีการวนซ้ำ ไม่มีทางย้อนรอยได้

ใช้สำหรับกราฟ

ตอนนี้เราได้เห็นภาพรวมของปัจจัยพื้นฐานแล้ว มาดูการใช้งานทั่วไปของกราฟกัน

คุณสามารถใช้กราฟเพื่อทำสิ่งต่างๆ เช่น:

  • ค้นหาเส้นทางที่สั้นที่สุด (หรือยาวที่สุด) ระหว่างสองตำแหน่ง
  • ตรวจสอบว่าสองสิ่งเกี่ยวข้องกันหรือไม่
  • สร้างเครื่องมือแนะนำ
  • วิเคราะห์การพึ่งพา

อีกตัวอย่างหนึ่งรวมถึงการหาเส้นทางที่ดีที่สุดไปยังจุดหมายปลายทาง (นึกถึงอุปกรณ์ GPS)

วิธีการใช้และใช้กราฟ

คุณสามารถเขียนการใช้งานกราฟของคุณเองได้ แต่สำหรับบทความนี้ เราจะใช้ RGL gem ที่ได้ติดตั้งไว้สำหรับเราแล้ว

ในการสร้างกราฟพื้นฐานโดยใช้ RGL:

require 'rgl/adjacency'

graph = RGL::DirectedAdjacencyGraph.new

graph.add_edge 1,2
graph.add_edge 3,4
graph.add_edge 1,4
graph.add_edge 4,3

รหัสนี้สร้างกราฟต่อไปนี้:

ทฤษฎีกราฟเชิงปฏิบัติใน Ruby

คุณสามารถแสดงกราฟของคุณได้ดังนี้:

require 'rgl/dot'

graph.print_dotted_on

จากนั้นคัดลอกผลลัพธ์ของวิธีการนั้นบนไซต์ที่สามารถประมวลผลภาษาดอทได้ ชอบอันนี้

หรือคุณสามารถติดตั้ง Graphviz บนเครื่องของคุณเพื่อสร้างภาพในเครื่อง

ตอนนี้เรามีกราฟแล้ว เราอาจต้องการสำรวจเพื่อหาข้อมูลเกี่ยวกับกราฟ

มีอัลกอริธึมพื้นฐานสองแบบสำหรับการค้นหากราฟของคุณ :

  • การค้นหาแบบกว้างก่อน (BFS)
  • ค้นหาความลึกครั้งแรก (DFS)

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

อัญมณี RGL ได้ใช้อัลกอริทึมเหล่านั้นสำหรับคุณแล้ว:

require 'rgl/traversal'

graph.bfs_iterator.to_a
# [1, 2, 4, 3]

graph.dfs_iterator.to_a
# [1, 4, 3, 2]

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

กราฟแสดงน้ำหนัก

เราสามารถเพิ่มข้อมูลเพิ่มเติมลงในกราฟในรูปแบบของน้ำหนักเพื่อให้มีประโยชน์มากขึ้น

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

ตัวอย่างเช่น หากเรามีแผนที่ของประเทศในรูปของกราฟ &เราต้องการไปให้ถึงจุดหมายในเวลาที่สั้นที่สุดเท่าที่จะเป็นไปได้ น้ำหนักจะแสดงระยะทางระหว่างสองเมือง

ทฤษฎีกราฟเชิงปฏิบัติใน Ruby

หรือถ้าเรามีเครือข่ายคอมพิวเตอร์ น้ำหนักอาจแสดงถึงจำนวนฮ็อปที่ต้องใช้ในการเข้าถึงเครือข่ายใดเครือข่ายหนึ่ง

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

นี่คือตัวอย่างโค้ดสำหรับกราฟแบบถ่วงน้ำหนัก:

graph = RGL::DirectedAdjacencyGraph.new
graph.add_vertices "Los Angeles", "New York", "Chicago", "Houston", "Seattle"

edge_weights =
{
  ["New York", "Los Angeles"] => 2445,
  ["Los Angeles", "Chicago"] => 2015,
  ["Los Angeles", "Houston"] => 1547,
  ["Chicago", "Houston"] => 939,
  ["Seattle", "Los Angeles"] => 1548
}

edge_weights.each { |(city1, city2), w| graph.add_edge(city1, city2) }

ขณะนี้เราสามารถค้นหาเส้นทางที่สั้นที่สุดจากจุดหนึ่งไปยังอีกจุดหนึ่งได้ และนั่นคือหัวข้อของหัวข้อถัดไป!

ค้นหาเส้นทางที่สั้นที่สุด

อัลกอริทึมยอดนิยมสำหรับการค้นหาเส้นทางที่สั้นที่สุดในกราฟคืออัลกอริธึม "เส้นทางที่สั้นที่สุดของ Dijkstra"

จากกราฟถ่วงน้ำหนัก เราสามารถใช้อัลกอริทึมของ Dijkstra เพื่อแก้ปัญหานี้:

“วิธีที่เร็วที่สุดในการเดินทางจากจุด A ไปยังจุด B คืออะไร”

นี่คือตัวอย่างโค้ดโดยใช้ RGL gem:

p graph.dijkstra_shortest_path(edge_weights, "New York", "Houston")
# ["New York", "Los Angeles", "Houston"]

ซึ่งจะบอกเราถึงเส้นทางที่สั้นที่สุดจากนิวยอร์กไปยังฮูสตัน โดยใช้ข้อมูลที่มีอยู่ในกราฟ

สรุป

คุณได้เรียนรู้ว่าโครงสร้างข้อมูลกราฟคืออะไร &ใช้งานอย่างไรกับอัญมณี RGL

คุณยังได้เรียนรู้เกี่ยวกับอัลกอริทึมทั่วไปสำหรับการทำงานกับกราฟ เช่น DFS, BFS &Dijkstra

อย่าลืมแชร์โพสต์นี้ หากคุณพบว่ามีประโยชน์เพื่อให้คนอื่น ๆ สามารถเพลิดเพลินได้ 🙂