🏋️ პრაქტიკა: პროექტები¶
წინა გვერდებზე ალგორითმები ცალ-ცალკე განვიხილეთ. რეალურ ამოცანაში კი ისინი ერთმანეთს ერწყმის: ტაილები ინდექსს, გრაფი გეომეტრიას. ქვემოთ ოთხი მინი-პროექტია, თითოეული რამდენიმე ალგორითმს აერთიანებს. ყველა კოდი სუფთა Python-ია (მხოლოდ სტანდარტული ბიბლიოთეკა) და მონაცემები თავად იქმნება, ამიტომ არაფრის ჩამოტვირთვა არ გჭირდებათ.
როგორ ვიმუშაოთ
- წაიკითხეთ პროექტის აღწერა და ნაბიჯები.
- სცადეთ თავად, დახმარებისთვის გახსენით შესაბამისი თემის გვერდი.
- მხოლოდ ამის შემდეგ გახსენით „ამოხსნა". ის სრული, გასაშვები პროგრამაა.
თუ თქვენი შედეგი რიცხვებში განსხვავდება, პირველ რიგში შეამოწმეთ random.seed(...): ის განსაზღვრავს, რომ მონაცემები ყოველ ჯერზე ერთნაირი იყოს.
| პროექტი | ალგორითმები | გვერდები |
|---|---|---|
| 1. შენობების სიმჭიდროვის რუკა | XYZ ტაილები, quadkey, იერარქია | ტაილები, Quadtree |
| 2. უახლოესი სადგური | k-d tree, brute force | ინდექსები |
| 3. მინი-ნავიგატორი | A*, Douglas–Peucker | გრაფები, გეომეტრია |
| 4. მისაწვდომობის ზონა | Dijkstra, Convex hull, ფართობი | გრაფები, გეომეტრია |
🗺️ პროექტი 1. შენობების სიმჭიდროვის რუკა¶
ამოცანა. გვაქვს 3 500 წერტილი (შენობა) საქართველოს ტერიტორიაზე, სამ ქალაქთან დაჯგუფებული, და ფონური გაფანტული წერტილები. ვებ-რუკისთვის სიმჭიდროვე ტაილებად უნდა დავთვალოთ ყველა zoom-ზე.
ნაბიჯები
- ყოველი წერტილი გადაიყვანეთ z=12 ტაილის quadkey-ად.
- quadkey-ის პრეფიქსებით დათვალეთ წერტილები z=8, 10 და 12 დონეზე (
Counter). რომელია ყველაზე დატვირთული ტაილი თითოეულ დონეზე? - შეამოწმეთ, რომ ყოველი z=8 ტაილის მნიშვნელობა მისი z=10 შვილების ჯამის ტოლია.
- გაიგეთ, რამდენი პროცენტია დაკავებული z=12 ტაილი ტერიტორიის ბადეში.
ამოხსნა
გაგრძელება
დაამატეთ ფუნქცია, რომელიც მოცემული ტაილისთვის (მაგ. 12033323) აბრუნებს 4 შვილისა და მშობლის quadkey-ს, და გამოიყენეთ ის „ყველაზე დატვირთული ტაილის" ირგვლივ მეზობელი ტაილების სიმჭიდროვის გამოსაჩენად.
📍 პროექტი 2. უახლოესი სადგური¶
ამოცანა. 2 000 სადგურია და 2 000 მისამართისთვის უნდა ვიპოვოთ უახლოესი სადგური. პირდაპირი ძებნა თითო მოთხოვნაზე ყველა სადგურს ამოწმებს; k-d tree ამას უმეტეს ტოტს არ სწავლობს.
ნაბიჯები
- დაწერეთ
brute(q):minყველა სადგურზე. - ააგეთ k-d tree და
nearest(ინდექსები). - დარწმუნდით, რომ ორივე მეთოდი ყველა მისამართისთვის ერთსა და იმავე სადგურს აბრუნებს.
- გაზომეთ დრო
time.perf_counter()-ით და გამოთვალეთ დაჩქარება.
ამოხსნა
გაგრძელება
გაზარდეთ სადგურების რიცხვი 200-დან 20 000-მდე და ააგეთ დაჩქარების დამოკიდებულება n-ზე. რატომ იზრდება დაჩქარება n-თან ერთად? (მინიშნება: O(n) vs O(log n).)
🧭 პროექტი 3. მინი-ნავიგატორი¶
ამოცანა. 40×60 უჯრის რუკაზე დაბრკოლებებია (შენობები, კედლები). უნდა ვიპოვოთ უმოკლესი გზა (2,2)-დან (37,57)-მდე და ის გავამარტივოთ, რომ მხოლოდ მთავარი შემობრუნების წერტილები დარჩეს.
ნაბიჯები
- ააგეთ 8-მეზობლიანი გრაფი ისე, რომ დიაგონალზე კუთხის გადაჭრა დაბრკოლებას გვერდით არ შეიძლებოდეს.
- იპოვეთ გზა A*-ით ოქტილური ევრისტიკით. რამდენი უჯრა გაიხსნა?
- გაამარტივეთ გზა Douglas–Peucker-ით
ε=1-ზე. - შეამოწმეთ, არ კვეთს თუ არა გამარტივებული ხაზი დაბრკოლებას. სცადეთ
ε = 0.5, 1, 2, 3.
ამოხსნა
გზა: 82 უჯრა, სიგრძე 86.38, გახსნილია 580 უჯრა
ε=0.5: 24 წერტილი, დაბრკოლებას კვეთს 0 სეგმენტი
ε=1: 10 წერტილი, დაბრკოლებას კვეთს 1 სეგმენტი
ε=2: 6 წერტილი, დაბრკოლებას კვეთს 3 სეგმენტი
ε=3: 6 წერტილი, დაბრკოლებას კვეთს 3 სეგმენტი
ε=1-ზე გამარტივებული ხაზი უკვე კედელს კვეთს. ნავიგაციაში გამარტივება ან უნდა შეჩერდეს პირველ დარღვევაზე (ზრდის ε-ს მანამ, სანამ გზა სუფთაა), ან მის შემდეგ ისევ უნდა შემოწმდეს. ეს ტიპური შემთხვევაა, როცა ორი სწორი ალგორითმი ერთად არასწორ შედეგს იძლევა.
გაგრძელება
დაწერეთ ფუნქცია simplify_safe(path, cost), რომელიც ε-ს 0.25-ის ბიჯით ზრდის და აბრუნებს ყველაზე გამარტივებულ ხაზს, რომელიც არცერთ დაბრკოლებას არ კვეთს. შეადარეთ Dijkstra-ს გახსნილი უჯრების რაოდენობას იმავე წყვილზე.
⏱️ პროექტი 4. მისაწვდომობის ზონა¶
ამოცანა. იმავე რუკაზე გვინდა ვიცოდეთ, სად მივალთ (10,20) უჯრიდან T ხარჯით. ზონა უნდა შემოვხაზოთ პოლიგონით და ვიპოვოთ მისი ფართობი.
ნაბიჯები
- შეცვალეთ Dijkstra ისე, რომ ხარჯი
T-ს გადაცილებისას გაჩერდეს (ყველა უჯრაd ≤ T). - აიღეთ ამ უჯრების
(x, y) = (სვეტი, მწკრივი)კოორდინატები და ააგეთ Convex hull. - გამოთვალეთ ჰალის ფართობი შულეისის ფორმულით.
T = 5, 10, 15-ისთვის შეადარეთ ჰალის ფართობი მიღწეულ უჯრათა რაოდენობას. რას ნიშნავს ეს წილი?
ამოხსნა
დაამატეთ ეს კოდი წინა პროექტის navigator.py-ის ბოლოს (იგივე cost, neighbors):
გაგრძელება
ჰალის მაგივრად გამოთვალეთ ზონის ფართობი უჯრების რაოდენობით და შეადარეთ. შემდეგ დაამატეთ მეორე სასტარტო წერტილი და იპოვეთ უჯრები, რომლებზეც ორივე წერტილიდან T-ში მივდივართ (გადაკვეთა).
🏁 დასკვნითი პროექტი: ააგეთ საკუთარი¶
აირჩიეთ ერთ-ერთი და შეაერთეთ სულ მცირე სამი ალგორითმი:
| იდეა | რა გჭირდებათ |
|---|---|
| უახლოესი სასწრაფო დახმარება | k-d tree უახლოესი სადგურისთვის → A* გზისთვის → ზონა Voronoi-ს უჯრებით (Voronoi) |
| რელიეფის გზა | სიმაღლეების ბადე (TIN) → დახრილობა როგორც ხარჯი → A* → კონტურები (კონტურები) გზის ირგვლივ |
| ტაილ-სერვერი | წერტილების quadkey-ებად ჩაწერა → R-tree bbox მოთხოვნისთვის (ინდექსები) → ტაილების მიცემა z/x/y-ის მიხედვით |
შეფასების კრიტერიუმები:
- ✅ პროგრამა მეორედ გაშვებისას იგივე შედეგს იძლევა (
random.seed) - ✅ ყოველი ალგორითმი შემოწმებულია ნელი, მაგრამ აშკარად სწორი მეთოდის წინააღმდეგ (როგორც პროექტი 2-ში)
- ✅ ერთი განსაკუთრებული შემთხვევა მაინც გაანალიზებულია (როგორც პროექტი 3-ში, კედლის გადაკვეთა)