อัลกอริทึมเพื่อค้นหาจุดที่ใกล้ที่สุด


18

ฉันมีรายชื่อเมืองสองสามร้อยแห่งที่มีละติจูด / ลองจิจูดของพวกเขา ได้รับตำแหน่งอื่น (เช่น lat / long) ฉันต้องการค้นหาเมืองที่ใกล้ที่สุด

ขณะที่ฉันไม่ได้ใช้ GIS ใด ๆ ตอนนี้อัลกอริทึมที่ชัดเจนคือการวนรอบเมืองทั้งหมดคำนวณระยะทางระหว่างจุด

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

หมายเหตุ : ฉันไม่ต้องการ / ต้องการโซลูชัน GIS ที่สมบูรณ์หรือไลบรารีที่หนัก / ซับซ้อน ฉันชอบโซลูชันที่ดีน้อยกว่า แต่ง่ายและเบากว่าเพราะนั่นเป็นสิ่งเดียวที่ฉันต้องแก้


ดังนั้นไม่สำคัญว่าระยะทางจะไม่ถูกต้องหรือไม่ และคุณไม่ต้องการบัญชีสำหรับถนนที่อาจทำให้เมืองไกลออกไปกว่าอีกเมืองหนึ่ง (เส้นทแยงมุมเทียบกับสี่เหลี่ยมจัตุรัส)?
แบรด Nesom

ใช่ถนนไม่สำคัญสำหรับฉัน ฉันต้องการเมืองที่ใกล้ที่สุดในระยะทางเชิงเส้นเพราะมันใช้สำหรับการพยากรณ์อากาศ
lujop

1
พยากรณ์อากาศ? ฉันหวังว่าคุณจะมีซูเปอร์คอมพิวเตอร์และพนักงานของนักอุตุนิยมวิทยาที่ผ่านการฝึกอบรมในการกำจัดของคุณ
Michael Todd

การคาดการณ์จะทำไมเคิลเดียวที่ฉันจะใช้อย่างใดอย่างหนึ่งที่ใกล้ที่สุด :)
lujop

คำตอบ:


24

ฉันตรวจสอบคำถามนี้เมื่อ 20 ปีก่อนเมื่อออกแบบ GIS เดสก์ท็อป เราจำเป็นต้องค้นหาระยะทางแบบจุดต่อจุดแบบโต้ตอบ; เป้าหมายของเราคือทำการคำนวณในเวลาน้อยกว่า 1/2 วินาทีสำหรับคะแนนนับพัน การทดสอบ (บน 25 MHz 486 PC!) แสดงให้เห็นว่าเราสามารถคำนวณระยะทางทั้งหมดตามที่คุณอธิบาย (ด้วยอัลกอริธึมที่ชัดเจนง่าย ๆ ) ดังนั้นอย่างรวดเร็วจนไม่เหมาะสมที่จะสร้างโซลูชันที่ซับซ้อนยิ่งขึ้นเช่นโครงสร้างควอดทรี .

สำหรับระยะทางที่คำนวณให้ "สอบสวน" เดี่ยวชี้ตัวเลือกของคุณ ได้แก่ (ก) การฉายทุกจุดใช้การฉายเท่ากันศูนย์กลางอยู่ที่จุดการสอบสวนหรือ (ข) การใช้รูปแบบการแผ่นดินทรงกลมและใช้สูตร Haversine สิ่งแรกมีความเหมาะสมหากคุณต้องการความแม่นยำของแบบจำลองวงรี ไม่ว่าในกรณีใดการคำนวณนั้นเร็วพอสมควรอาจจะน้อยกว่า 1,000 ติ๊ก: คุณสามารถค้นหาประมาณหนึ่งล้านคะแนนต่อวินาทีด้วยโปรเซสเซอร์เดียว

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

หากคุณต้องการที่จะไปเร็วขึ้นคุณสามารถใช้การประมาณต่าง ๆ เพื่อจุดหน้าจอ ตัวอย่างเช่นหากคุณอยู่ระหว่างละติจูด -88 ถึง +88 องศาและจุดที่ใกล้ที่สุดที่พบนั้นอยู่ห่างออกไป 200 กม. ดังนั้นจุดใดก็ตามที่ละติจูดแตกต่างจากละติจูดของจุดโพรบมากกว่า 2 องศาอาจไม่สามารถเข้าใกล้ได้มากขึ้น โลกละติจูดหนึ่งองศาเกินประมาณ 110 กม.) ในหลายกรณีการคัดกรองล่วงหน้าประเภทนี้อาจช่วยให้คุณสามารถประมวลผลคะแนนหลายร้อยล้านต่อวินาที


1
สำหรับการอภิปรายเกี่ยวกับสูตรแฮเวอรีน
whuber

4

ฉันเห็นด้วยกับคนอื่น ๆ ว่าการวนรอบแบบเรียบง่ายควรมีประสิทธิภาพสำหรับ "สองสามร้อยเมือง"

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

มันอาจจะง่ายกว่า (เช่นใช้ delta lat เป็น y และ delta lon * cos (lat) เป็น x และค้นหา x ขั้นต่ำ ^ 2 + y ^ 2) คุณกำลังใช้โคไซน์ของละติจูดเป้าหมายซึ่งคุณจะคำนวณเพียงครั้งเดียว สิ่งนี้จะไม่ถูกต้องมากขึ้นสำหรับเมืองที่อยู่ห่างไกล แต่พวกเขาจะถูกปฏิเสธอย่างไรก็ตามไม่สำคัญ สมมติว่าเมืองที่ใกล้ที่สุดของคุณโดยทั่วไปอยู่ในระยะสองสามร้อยกิโลเมตรโอกาสของผลลัพธ์ที่แตกต่างกัน (เมืองที่ใกล้ที่สุด) เมื่อเทียบกับการใช้สูตรที่แม่นยำยิ่งขึ้นนั้นมีขนาดค่อนข้างเล็กและจะเกิดขึ้นก็ต่อเมื่อความแตกต่างนั้นเล็กพอ ความถูกต้อง "อาจขึ้นอยู่กับปัจจัยอื่น ๆ อยู่ดี (เช่น: สูญเสียเสียง)

นอกจากว่าคุณกำลังใช้ระบบฝังตัวหรือล่ามที่ช้าคุณอาจจะสามารถใช้ formals ทรงกลมที่คนอื่นแนะนำให้ใช้


1

นี่คือสิ่งที่ได้พูดไปแล้ว แต่ฉันคิดว่าฉันจะสังเกตเห็นความสำคัญของการเลือกโครงสร้างข้อมูลที่เหมาะสม ฉันเขียนโค้ดของตัวเองสำหรับ K-Function ใน. NET และพบว่าการใช้คอลเลกชันที่มีประสิทธิภาพช่วยเร่งความเร็วของสิ่งต่าง ๆ อย่างมาก ขอโทษฉันไม่รู้จักสัญกรณ์ O สำหรับความเร็วที่แน่นอน ฉันใช้พจนานุกรมสองเล่มสำหรับพิกัด x และ y ด้วยรหัสจุดเป็นกุญแจสำคัญ ฉันไม่รู้ Java ดังนั้นจึงไม่สามารถแนะนำอะไรได้

ไชโยเดวิด

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