مسیریابی بهینه شده برای مکوری Zwift 🥖 تصادفی های جان مولر

Zwift اخیرا مجموعه جدیدی از مسیرها را در یک جزیره ساخته شده به نام Makuri منتشر کرده است. متفاوت از برخی از نقشه های دیگر، این نقشه دارای تعداد زیادی چهارراه است و چیزهای زیادی برای دیدن وجود دارد. زیباست. بنابراین، البته، به جای دوچرخه سواری در آنجا، فکر کردم این یک تمرین سرگرم کننده است که کوتاه ترین مسیری را پیدا کنم که به شما امکان می دهد حداقل یک بار همه چیز را ببینید.

بدون هیچ مقدمه ای، مسیر بهینه در اینجا آمده است:

مسیریابی بهینه شده برای مکوری Zwift 🥖 تصادفی های جان مولر

  • مسافت کل: 33.4 کیلومتر (تکرار: 5.6 کیلومتر)
  • مسیرهای استفاده شده: 33 (یک بار استفاده شده: 25)

مسیر بهینه از تعداد زیادی پیچ استفاده می کند، بنابراین چندان کاربردی نیست. این یک جزیره کوچک است، پس فقط به دوچرخه سواری ادامه دهید و به آن خواهید رسید. h را بزنید تا HUD خاموش شود :-).

بررسی اجمالی

این جزیره به شکل زیر است:

(منبع: Zwift)

چگونه به آنجا برسیم

از نظر فنی، نقشه در نندو، در جزایر سانتا کروز / جزایر سلیمان، جنوب اقیانوس آرام واقع شده است. شما می توانید در Zwift نیز به آنجا بروید – تصور می کنم شخصاً متفاوت به نظر می رسد.

کار

پس از نگاه کردن به اطراف، این یک تغییر از “مشکل فروشنده دوره گرد” (TSP) کلاسیک است. در مشکل اصلی، شما فقط به هر ترتیبی از مکان ها بازدید می کنید، مسیرهای انتخاب شده اهمیتی ندارند. در مورد ما، ما به آن اهمیت می دهیم مسیرها (همه مناظر را ببینید!)، بنابراین مشکل ما با «مشکل بازرسی مسیر (همچنین به عنوان «مشکل پستچی چینی» شناخته می‌شود، مطابقت دارد.»

خوشبختانه، یک اونس گوگل باعث صرفه جویی در مصرف نودل می شود، و راه حل های زیادی برای این کار کدگذاری شده است. من از کتابخانه Python “Postman Problems” توسط اندرو بروکس استفاده کردم که نمونه “هفت پل” را دارد که برای کپی و چسباندن عالی است. احتمالاً یک بعدازظهر تمام خواهم شد (توجه سردبیران: خیر).

مشکل را ساده کنید

پس از مدتی سواری در منطقه، همه مسیرها را از Strava گرفتم، آنها را به عنوان GPX صادر کردم، آنها را نقشه برداری کردم و آنها را با “گره ها” (تقاطع) و “لبه ها” (مسیرها) حاشیه نویسی کردم. من برای این کار از GPX Studio استفاده کردم و اسکرین شات را در Google Docs حاشیه نویسی کردم.

من زمان زیادی را صرف استخراج خودکار لبه‌ها و گره‌ها از فایل‌های GPX کردم. من این کار را به صورت دستی انجام دادم: بخش هایی را در Strava ایجاد کردم و فایل های GPX را با استفاده از My GPS Files تقسیم کردم. برای آخرین مسیر، Strava تصمیم گرفت که نمی‌توانم بخش‌های بیشتری ایجاد کنم، pffft. طول ها از مسافت های کیلومتری استراوا بودند، بنابراین به طور بالقوه کمی فاصله دارند. من می توانم آنها را بر اساس فایل های GPX دوباره محاسبه کنم، اما چه کسی برای دقت در یک بازی دوچرخه سواری مجازی وقت دارد؟ (من می توانم همین را برای بهینه سازی برای آن بگویم، اما هر چه باشد.)

حل کننده را اجرا کنید

این کاملاً بدون اتفاق بود.

python3 cpp_makuri.py

INFO:__main__:Solve CPP
(..)
Solution (from, to, path) - copy into draw_*.py:
(('A', 'Q', 'Q1'), ('Q', 'O', 'O2'), ('O', 'Q', 'O2'), ('Q', 'P', 'P1'), ('P', 'L', 'L1'), ('L', 'P', 'L1'), ('P', 'O', 'O1'), ('O', 'M', 'M1'), ('M', 'L', 'L2'), ('L', 'K', 'K1'), ('K', 'L', 'K1'), ('L', 'M', 'L2'), ('M', 'H', 'H2'), ('H', 'I', 'H1'), ('I', 'K', 'I2'), ('K', 'J', 'J1'), ('J', 'G', 'G1'), ('G', 'F', 'F2'), ('F', 'D', 'D2'), ('D', 'F', 'D2'), ('F', 'G', 'F1'), ('G', 'J', 'G1'), ('J', 'I', 'I1'), ('I', 'H', 'H1'), ('H', 'E', 'E1'), ('E', 'C', 'C2'), ('C', 'E', 'C2'), ('E', 'D', 'D1'), ('D', 'C', 'C1'), ('C', 'B', 'B1'), ('B', 'A', 'A3'), ('A', 'B', 'A2'), ('B', 'A', 'A1'))
INFO:__main__:Solution summary stats:
INFO:__main__:distance_walked : 33410
INFO:__main__:distance_doublebacked : 5650
INFO:__main__:distance_walked_once : 27760
INFO:__main__:distance_walked_optional : 0
INFO:__main__:distance_walked_required : 33410
INFO:__main__:edges_walked : 33
INFO:__main__:edges_doublebacked : 8
INFO:__main__:edges_walked_once : 25
INFO:__main__:edges_walked_optional : 0
INFO:__main__:edges_walked_required : 33
(...)

تصویر متحرک بسازید

هنگامی که همه چیز انجام شد، وقت آن است که زمان بیشتری را غرق کنید. من از MatPlotLib + ImageMagick برای ترسیم قطعات GPX به ترتیب استفاده کردم. انیمیشن های MatPlotLib به طور شگفت انگیزی ساده و ساده هستند.

#!/usr/bin/python3

# Draws animation of optimal trail for new Zwift island, saves as output/animated-map.gif
# by John Mueller - github.com/softplus
# License: Apache 2

import matplotlib.pyplot as plt
import matplotlib.animation as animation

# from cpp_makuri.py
solution = (('A', 'Q', 'Q1'), ('Q', 'O', 'O2'), ('O', 'Q', 'O2'), ('Q', 'P', 'P1'), ('P', 'L', 'L1'), ('L', 'P', 'L1'), ('P', 'O', 'O1'), ('O', 'M', 'M1'), ('M', 'L', 'L2'), ('L', 'K', 'K1'), ('K', 'L', 'K1'), ('L', 'M', 'L2'), ('M', 'H', 'H2'), ('H', 'I', 'H1'), ('I', 'K', 'I2'), ('K', 'J', 'J1'), ('J', 'G', 'G1'), ('G', 'F', 'F2'), ('F', 'D', 'D2'), ('D', 'F', 'D2'), ('F', 'G', 'F1'), ('G', 'J', 'G1'), ('J', 'I', 'I1'), ('I', 'H', 'H1'), ('H', 'E', 'E1'), ('E', 'C', 'C2'), ('C', 'E', 'C2'), ('E', 'D', 'D1'), ('D', 'C', 'C1'), ('C', 'B', 'B1'), ('B', 'A', 'A3'), ('A', 'B', 'A2'), ('B', 'A', 'A1'))

# reads all data points from CSV file
def get_data(trail):
    points = ()
    with open("tracks/" + trail + ".csv") as f:
        lines = f.readlines()
        for line in lines(1:):
            items = line.strip().split(",")
            points.append((float(x) for x in items))
    return points


# initialize figure, get sub-plot
fig = plt.figure(dpi=150)
ax1 = fig.add_subplot(1,1,1)

# draw the full map as background
def plot_all(solution):
    for trail in solution:
        pts = get_data(trail(2))
        ax1.plot( (d(1) for d in pts), (d(0) for d in pts), color="#77a")

# track previously visited trails to highlight extras
previously_seen = ()

# animation; i=index of trails so far
def animate(i):
    ax1.clear()
    plt.title('Makuri', size=10)
    plt.axis('off')
    plot_all(solution) # draw background, scale image

    # draw trails visited so far
    for trail in solution(:i):
        pts = get_data(trail(2))
        ax1.plot( (d(1) for d in pts), (d(0) for d in pts), color="#f00")

    # draw this trail, highlight if revisited    
    this_trail = solution(i)(2)
    pts = get_data(this_trail)
    if this_trail in previously_seen and i>0:
        ax1.plot( (d(1) for d in pts), (d(0) for d in pts), color="#faa", linewidth=5)
        ax1.plot( (d(1) for d in pts), (d(0) for d in pts), color="#333", linestyle=":", linewidth=3)
    else:
        ax1.plot( (d(1) for d in pts), (d(0) for d in pts), color="#faa", linewidth=5)
    previously_seen.append(this_trail)

# animate 
ani = animation.FuncAnimation(fig, animate, interval=1000, frames=len(solution), repeat_delay=10000) 

print("Animate and save...")
plt.show()
ani.save("output/animated-map.gif", writer="imagemagick") 
print("Done")

(در برخی مواقع در Github حذف خواهد شد.)

مسیریابی بهینه شده برای مکوری Zwift 🥖 تصادفی های جان مولر

اسکرین شات های تصادفی

نظرات / سوالات

در حال حاضر هیچ قابلیت نظر دادن در اینجا وجود ندارد. اگر می‌خواهید نظر بدهید، لطفاً از Mastodon استفاده کنید و من را (@[email protected]) در آنجا ذکر کنید. با تشکر!

صفحات مرتبط

Source link