Tôi là một nhà nghiên cứu khoa học hành tinh và một dự án tôi đang thực hiện là mô phỏng N -body về các vành đai của Sao Thổ. Mục tiêu của nghiên cứu đặc biệt này là xem các hạt kết tụ với nhau dưới trọng lực bản thân và đo khối lượng tổng hợp của các khối so với vận tốc trung bình của tất cả các hạt trong tế bào. Chúng tôi đang cố gắng tìm hiểu xem điều này có thể giải thích một số quan sát được thực hiện bởi tàu vũ trụ Cassini trong ngày hạ chí của Sao Thổ khi các cấu trúc lớn được nhìn thấy đổ bóng trên các vòng gần như cạnh. Dưới đây là một ảnh chụp màn hình của bất kỳ dấu thời gian nhất định trông như thế nào. (Mỗi hạt có đường kính 2 m và tế bào mô phỏng có chiều ngang khoảng 700 m.)
Mã tôi đang sử dụng đã tạo ra vận tốc trung bình ở mọi dấu thời gian. Những gì tôi cần làm là tìm ra một cách để xác định khối lượng của các hạt trong các khối và KHÔNG phải là các hạt đi lạc giữa chúng. Tôi biết vị trí, khối lượng, kích thước, v.v. của mọi hạt, nhưng tôi không dễ dàng biết rằng, các hạt 30.000-40.000 cùng với 102.000-105.000 tạo thành một sợi mà mắt người nhìn thấy rõ.
Vì vậy, thuật toán tôi cần viết sẽ cần phải là một mã có càng ít tham số do người dùng nhập vào càng tốt (về khả năng nhân rộng và tính khách quan) sẽ đi qua tất cả các vị trí hạt, tìm ra hạt nào thuộc cụm, và sau đó tính toán khối lượng. Sẽ thật tuyệt nếu nó có thể làm điều đó cho "từng" cụm / chuỗi trái ngược với mọi thứ trên tế bào, nhưng tôi không nghĩ rằng tôi thực sự cần nó để tách chúng ra.
Điều duy nhất tôi nghĩ đến là thực hiện một phép tính khoảng cách N 2 trong đó tôi tính khoảng cách giữa mỗi hạt và nếu, 100 hạt gần nhất nằm trong một khoảng cách nhất định, thì hạt đó sẽ được coi là một phần của cụm. Nhưng điều đó có vẻ khá cẩu thả và tôi đã hy vọng rằng các bạn và các lập trình viên CS có thể biết về một giải pháp thanh lịch hơn?
Được chỉnh sửa với Giải pháp của tôi: Những gì tôi đã làm là thực hiện một cách tiếp cận cụm / lân cận gần nhất và thực hiện N 2 nhanh chóng trước tiên. Vì vậy, lấy mọi hạt, tính khoảng cách cho tất cả các hạt khác và ngưỡng cho một cụm hay không là liệu có hạt N trong khoảng cách d hay không (hai tham số phải được đặt trước , nhưng như đã nói với một số Phản hồi / bình luận, tôi sẽ không thoát khỏi việc không có một vài trong số đó).
Sau đó, tôi đã tăng tốc nó bằng cách không sắp xếp khoảng cách mà chỉ đơn giản là thực hiện tìm kiếm N và tăng số lượt truy cập cho các hạt trong d , và điều đó tăng tốc theo hệ số 6. Sau đó, tôi đã thêm một "cây lập trình viên ngu ngốc" (vì tôi biết bên cạnh không có gì về mã cây). Tôi chia ô mô phỏng thành một số lưới đã đặt (kết quả tốt nhất khi kích thước lưới ≈7 d ) trong đó lưới chính nối với ô, một lưới được bù một nửa bằng x và y , và hai lưới còn lại được bù bởi 1/4 in ± x và ± y . Đoạn mã sau đó phân chia các hạt thành các lưới, sau đó mỗi hạt N chỉ phải có khoảng cách tính cho các hạt khác trong ô đó.
Về mặt lý thuyết, nếu đây là một cây thật, tôi sẽ nhận được thứ tự N * log ( N ) trái ngược với tốc độ N 2 . Tôi đã nhận được một nơi nào đó giữa hai người, trong đó với một tập hợp con 50.000 hạt, tôi đã tăng tốc độ 17 lần và đối với một tế bào 150.000 hạt, tôi đã tăng tốc độ 38 lần. 12 giây cho lần đầu tiên, 53 giây cho lần thứ hai, 460 giây cho một tế bào 500.000 hạt. Đó là những tốc độ tương đương với thời gian mã mất bao lâu để chạy mô phỏng 1 dấu thời gian về phía trước, vì vậy điều đó hợp lý tại thời điểm này. Ồ - và nó hoàn toàn được xâu chuỗi, vì vậy nó sẽ cần nhiều bộ xử lý nhất mà tôi có thể sử dụng.