সঠিক ফিনিশিং পয়েন্ট এবং শূন্য টার্মিনাল বেগ সহ রেসট্র্যাকের বৈকল্পিক


9

ভূমিকা

চ্যালেঞ্জটি গেম রেসট্র্যাক এবং সেই দুটি চ্যালেঞ্জের একটি খুব আকর্ষণীয় বৈকল্পিক :

এই চ্যালেঞ্জের উত্স এখানে (জার্মান ভাষায়): সিটি-রেসট্র্যাক ck

এই চ্যালেঞ্জটি বিশেষত আকর্ষণীয় (এবং উপরে বর্ণিত দুটি চ্যালেঞ্জ থেকে পৃথক) কারণ এটি একটি বিশাল অনুসন্ধান-স্থানকে কিছু সঠিক অবস্থার সাথে সম্মিলিত করে যা পূরণ করতে হয়। কারণ বিশাল অনুসন্ধান-স্থানের বিস্তৃত অনুসন্ধান কৌশলগুলি ব্যবহার করা শক্ত, কারণ সঠিক অবস্থার কারণে আনুমানিক পদ্ধতিগুলি সহজে ব্যবহারযোগ্য হয় না। এই অনন্য সংমিশ্রণের কারণে (প্লিজ পদার্থবিজ্ঞানের অন্তর্নিহিত অন্তর্নিহিততা) সমস্যাটি আকর্ষণীয় (এবং রেসিং গাড়িগুলির সাথে সংযুক্ত সমস্ত কিছু যাই হোক না কেন আকর্ষণীয় ;-)

চ্যালেঞ্জ

নিম্নলিখিত রেসট্র্যাক ( উত্স ) একবার দেখুন:

এখানে চিত্র বর্ণনা লিখুন

আপনাকে প্রাচীরের কোনও একটি স্পর্শ না করেই শুরু করতে হবে (120,180)এবং (320,220)(জার্মান ভাষায় "জিয়েল") শেষ করতে হবে।

গাড়িটি ফর্মটির ত্বক ভেক্টর দ্বারা নিয়ন্ত্রিত (a_x,a_y)- উদাহরণ হিসাবে:

(8,-6)
(10,0)
(1,9)

প্রথম সংখ্যাটি এক্স-ভেক্টরের ত্বরণ, দ্বিতীয়টি ওয়াই-ভেক্টরের জন্য। তাদের পূর্ণসংখ্যা হতে হবে কারণ আপনি কেবল গ্রিডে পূর্ণসংখ্যা পয়েন্ট ব্যবহার করার অনুমতি পেয়েছেন। অতিরিক্তভাবে নিম্নলিখিত শর্তটি পূরণ করতে হবে:

a_x^2 + a_y^2 <= 100,

যার অর্থ যে কোনও দিকের ত্বরণ নীচের বা সমান হতে হবে 10

এটি কীভাবে কাজ করে তা দেখতে নীচের চিত্রটি ( উত্স ) দেখুন:

এখানে চিত্র বর্ণনা লিখুন

উদাহরণ হিসাবে: (120,180)আপনার কাছ থেকে শুরু করে 8এক্স-দিক দিয়ে এবং -6ওয়াই-দিক দিয়ে গতি বাড়ান। পরবর্তী পদক্ষেপের জন্য এটি আপনার বেগ যেখানে আপনি (10,0)আপনার পরবর্তী ফলাফল পরিবর্তন (শারীরিকভাবে সঠিক) পেতে আপনার ত্বরণ যোগ করেছেন (নির্দেশ করুন (146,168)। আপনি প্রাচীরের কোনও একটি স্পর্শ করেছেন কিনা তা যাচাই করার সময় এটির ফলাফলটি কী গণনা করে তা পরবর্তী পদক্ষেপে আপনি আবার আপনার পরবর্তী গতিবেগ ভেক্টরটিকে পরবর্তী চলন এবং তার জন্য আপনার বর্তমান গতিতে যুক্ত করতে পারেন So সুতরাং প্রতিটি পদক্ষেপে আপনার গাড়ীটির একটি অবস্থান এবং একটি বেগ রয়েছে ((নীল তীরের উপরে চিত্রিত চিত্রে নীল কমলাগুলির জন্য ত্বরণ এবং ফলাফলের আন্দোলনের জন্য গা red় লাল তীরগুলির জন্য))

অতিরিক্ত শর্ত হিসাবে আপনি (0,0)যখন সমাপ্তির পয়েন্টে থাকবেন তখন আপনাকে টার্মিনাল বেগ রাখতে হবে (320,220)

আউটপুটটি উপরে বর্ণিত আকারে ত্বরণ ভেক্টরগুলির একটি তালিকা হতে হবে।

বিজয়ী হলেন তিনি এমন একটি প্রোগ্রাম যা খুব কম ত্বরণের ভেক্টরগুলির সাথে সমাধান খুঁজে পায় provides

টাইব্রেকার
অতিরিক্ত হিসাবে এটি দুর্দান্ত হবে যদি আপনি দেখান যে এটি একটি সর্বোত্তম সমাধান এবং এটিই কেবলমাত্র সর্বোত্তম সমাধান কিনা বা বেশ কয়েকটি অনুকূল সমাধান (এবং সেগুলি কী)।

আপনার অ্যালগরিদম কীভাবে কাজ করে তার একটি সাধারণ রূপরেখা দিতে এবং কোডটিতে মন্তব্য করতে যাতে আমরা এটি বুঝতে পারি তবে এটিও ভাল।

আমার একটি প্রোগ্রাম রয়েছে যা প্রদত্ত যে কোনও সমাধান বৈধ কিনা তা পরীক্ষা করে আমি প্রতিক্রিয়া জানাব।

সংযোজন
আপনি যে কোনও প্রোগ্রামিংয়ের ভাষা ব্যবহার করতে পারেন তবে কেউ বিশেষত আর ব্যবহার করলে আমি বিশেষভাবে আনন্দিত হব কারণ আমি আমার দিনের চাকরিতে এটি প্রচুর ব্যবহার করি এবং কোনওভাবে এটি অভ্যস্ত হয়ে পড়ে :-)

সংযোজন দ্বিতীয়
প্রথমবারের জন্য আমি একটি অনুগ্রহ শুরু করলাম - আশা করি এটি বলটি ঘূর্ণায়মান হবে (বা আরও ভাল: গাড়িটি চালাবেন :-)


@ মেগো: তবুও ... এটি সম্পর্কে চিন্তাভাবনা করা: আমি কমপক্ষে দুটি কারণে প্রোগ্রামটি যুক্ত করব কিনা তা নিশ্চিত নই: প্রথমত, মূল চ্যালেঞ্জের মধ্যে এটি অন্তর্ভুক্ত ছিল না, দ্বিতীয়ত: উদাহরণস্বরূপ এর রুটিন রয়েছে যা এর অংশ চ্যালেঞ্জ (যেমন সংঘর্ষ সনাক্তকরণ) যাতে মজাদার অংশটি নষ্ট করে দেয় ... আমাকে এতে ঘুমাতে হবে ...
vonjd

1
প্রোগ্রামটির কি আসলে পাথ গণনা করা দরকার, বা আমি কেবল আগেই সর্বোত্তম পথটি গণনা করতে পারি এবং তারপরে এর মতো কিছু পোস্ট করতে print "(10,42)\n(62,64)..."পারি?
লুভজো

@ লভজো: না, প্রোগ্রামটি নিজেই পাথটি গণনা করতে হবে, সুতরাং বুদ্ধি অবশ্যই প্রোগ্রামে অন্তর্ভুক্ত করা উচিত, কেবলমাত্র একটি আউটপুট রুটিন নয়।
vonjd

উত্তর:


4

পাইথন, ২৪ টি পদক্ষেপ (কাজ চলছে)

ধারণাটি ছিল প্রথমে অবিচ্ছিন্ন সমস্যা সমাধানের জন্য, অনুসন্ধানের স্থানটি ব্যাপকভাবে হ্রাস করা এবং তারপরে ফলাফলটিকে গ্রিডে পরিমাণমুক্ত করা (কেবলমাত্র নিকটস্থ গ্রিডপয়েন্টে গোল করে এবং আশেপাশের 8 স্কোয়ারটি অনুসন্ধান করে)

আমি ট্রাইগনোমেট্রিক ফাংশনের সমষ্টি হিসাবে পথটিকে প্যারাম্যাট্রাইজ করি (বহুবচনগুলির বিপরীতে এগুলি বিচ্ছিন্ন করে না এবং চেক রাখা সহজ হয়)। আমি ত্বরণের পরিবর্তে সরাসরি গতিও নিয়ন্ত্রণ করি, কারণ শেষের দিকে 0-তে থাকে এমন একটি ওজনযুক্ত ফাংশন কেবলমাত্র গুণ করে বাউন্ডারি শর্তটি কার্যকর করা সহজ।
আমার উদ্দেশ্য ফাংশনটি
ত্বরণের জন্য এক্সফোনালিয়াল স্কোর নিয়ে > 10
শেষের পয়েন্ট এবং টার্গেটের মধ্যে ইউক্লিডিয়ান দূরত্বের জন্য পলিনোমোনাল স্কোর
- প্রাচীরের প্রতিটি প্রান্তের জন্য প্রতিটি চৌরাস্তার জন্য দীর্ঘ ধ্রুবক স্কোর, প্রাচীরের কিনার দিকে কমতে

স্কোর কমানোর জন্য, আমি এটি সবই ফেলেছি নেল্ডার-মিড অপটিমাইজেশনে ফেলেছি এবং কয়েক সেকেন্ড অপেক্ষা করি। অ্যালগরিদম সর্বদা শেষের দিকে যেতে সফল হয়, সেখানে থামে এবং সর্বাধিক ত্বরণ ছাড়িয়ে যায় না, তবে এতে দেয়ালগুলির সাথে ঝামেলা রয়েছে। পাথটি হয় কোণা দিয়ে টেলিপোর্ট করে এবং সেখানে আটকে যায়, বা দেয়ালের পাশ দিয়ে থামবে কেবল লক্ষ্য জুড়ে (বাম চিত্র)
এখানে চিত্র বর্ণনা লিখুন

পরীক্ষার সময় আমি ভাগ্যবান হয়েছি এবং এমন একটি পথ পেয়েছি যা একটি প্রতিশ্রুতিবদ্ধ উপায়ে (ডান চিত্র) ফাঁসানো হয়েছিল এবং পরামিতিগুলি টুইট করার পরে আরও একটি সফল অপ্টিমাইজেশনের জন্য এটি প্রাথমিক অনুমান হিসাবে ব্যবহার করতে পারলাম।

Quantization
প্যারামিট্রিক পাথ সন্ধানের পরে দশমিক পয়েন্টগুলি সরিয়ে ফেলার সময় হয়েছিল। 3x3 এর আশেপাশে অনুসন্ধান অনুসন্ধানের স্থানটি প্রায় 300 ^ N থেকে 9 ^ N পর্যন্ত হ্রাস করে, তবে এটি প্রয়োগ করা এখনও খুব বড় এবং বিরক্তিকর। আমি এই রাস্তায় নামার আগে আমি উদ্দেশ্যমূলক ক্রিয়ায় (মন্তব্য করা অংশগুলি) একটি "স্ন্যাপ টু গ্রিড" শব্দ যুক্ত করার চেষ্টা করেছি। সমাধানের জন্য আপডেট করা উদ্দেশ্য এবং কেবল বৃত্তাকারের সাথে অপ্টিমাইজেশনের আরও একশটি পদক্ষেপ যথেষ্ট ছিল।

[(9, -1), (4, 0), (1, 1), (2, 2), (-1, 2), (-3, 4), (-3, 3), (-2 , 3), (-2, 2), (-1, 1), (0, 0), (1, -2), (2, -3), (2, -2), (3, -5) ), (2, -4), (1, -5), (-2, -3), (-2, -4), (-3, -9), (-4, -4), (- 5, 8), (-4, 8), (5, 8)]

পদক্ষেপের সংখ্যা নির্ধারণ করা হয়েছিল এবং অপ্টিমাইজেশনের অংশ নয়, তবে যেহেতু আমাদের কাছে পথটির বিশ্লেষণাত্মক বিবরণ রয়েছে, (এবং যেহেতু সর্বাধিক ত্বরণটি 10 ​​এর নিচে রয়েছে) আমরা এটি আরও কম সংখ্যক সহ আরও অপ্টিমাইজেশনের জন্য একটি প্রাথমিক পয়েন্ট হিসাবে পুনরায় ব্যবহার করতে পারি timesteps

from numpy import *
from scipy.optimize import fmin
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection as LC

walls = array([[[0,0],[500,0]],   # [[x0,y0],[x1,y1]]
        [[500,0],[500,400]],
        [[500,400],[0,400]],
        [[0,400],[0,0]],

        [[200,200],[100,200]],
        [[100,200],[100,100]],
        [[100,100],[200,100]],

        [[250,300],[250,200]],

        [[300,300],[300,100]],
        [[300,200],[400,200]],
        [[300,100],[400,100]],

        [[100,180],[120, 200]], #debug walls
        [[100,120],[120, 100]],
        [[300,220],[320, 200]],
        #[[320,100],[300, 120]],
])

start = array([120,180])
goal = array([320,220])

###################################
# Boring stuff below, scroll down #
###################################
def weightedintersection2D(L1, L2):
    # http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
    p = L1[0]
    q = L2[0]
    r = L1[1]-L1[0]
    s = L2[1]-L2[0]
    d = cross(r,s)
    if d==0: # parallel
        if cross(q-p,r)==0: return 1 # overlap
    else:
        t = cross(q-p,s)*1.0/d
        u = cross(q-p,r)*1.0/d
        if 0<=t<=1 and 0<=u<=1: return 1-0*abs(t-.5)-1*abs(u-.5) # intersect at p+tr=q+us
    return 0

def sinsum(coeff, tt):
    '''input: list of length 2(2k+1), 
    first half for X-movement, second for Y-movement.
    Of each, the first k elements are sin-coefficients
    the next k+1 elements are cos-coefficients'''
    N = len(coeff)/2
    XS = [0]+list(coeff[:N][:N/2])
    XC =     coeff[:N][N/2:]
    YS = [0]+list(coeff[N:][:N/2])
    YC =     coeff[N:][N/2:]
    VX = sum([XS[i]*sin(tt*ww[i]) + XC[i]*cos(tt*ww[i]) for i in range(N/2+1)], 0)
    VY = sum([YS[i]*sin(tt*ww[i]) + YC[i]*cos(tt*ww[i]) for i in range(N/2+1)], 0)
    return VX*weightfunc, VY*weightfunc

def makepath(vx, vy):
    # turn coordinates into line segments, to check for intersections
    xx = cumsum(vx)+start[0]
    yy = cumsum(vy)+start[1]
    path = []
    for i in range(1,len(xx)):
        path.append([[xx[i-1], yy[i-1]],[xx[i], yy[i]]])
    return path

def checkpath(path):
    intersections = 0
    for line1 in path[:-1]: # last two elements are equal, and thus wrongly intersect each wall
        for line2 in walls:
            intersections += weightedintersection2D(array(line1), array(line2))
    return intersections

def eval_score(coeff):
    # tweak everything for better convergence
    vx, vy = sinsum(coeff, tt)
    path = makepath(vx, vy)
    score_int = checkpath(path)
    dist = hypot(*(path[-1][1]-goal))
    score_pos = abs(dist)**3
    acc = hypot(diff(vx), diff(vy))
    score_acc = sum(exp(clip(3*(acc-10), -10,20)))
    #score_snap = sum(abs(diff(vx)-diff(vx).round())) + sum(abs(diff(vy)-diff(vy).round()))
    print score_int, score_pos, score_acc#, score_snap
    return score_int*100 + score_pos*.5 + score_acc #+ score_snap

######################################
# Boring stuff above, scroll to here #
######################################
Nw = 4 # <3: paths not squiggly enough, >6: too many dimensions, slow
ww = [1*pi*k for k in range(Nw)]
Nt = 30 # find a solution with tis many steps
tt = linspace(0,1,Nt)
weightfunc = tanh(tt*30)*tanh(30*(1-tt)) # makes sure end velocity is 0

guess = random.random(4*Nw-2)*10-5
guess = array([ 5.72255365, -0.02720178,  8.09631272,  1.88852287, -2.28175362,
        2.915817  ,  8.29529905,  8.46535503,  5.32069444, -1.7422171 ,
       -3.87486437,  1.35836498, -1.28681144,  2.20784655])  # this is a good start...
array([ 10.50877078,  -0.1177561 ,   4.63897574,  -0.79066986,
         3.08680958,  -0.66848585,   4.34140494,   6.80129358,
         5.13853914,  -7.02747384,  -1.80208349,   1.91870184,
        -4.21784737,   0.17727804]) # ...and it returns this solution      

optimsettings = dict(
    xtol = 1e-6,
    ftol = 1e-6,
    disp = 1,
    maxiter = 1000, # better restart if not even close after 300
    full_output = 1,
    retall = 1)

plt.ion()
plt.axes().add_collection(LC(walls))
plt.xlim(-10,510)
plt.ylim(-10,410)
path = makepath(*sinsum(guess, tt))
plt.axes().add_collection(LC(path, color='red'))
plt.plot(*start, marker='o')
plt.plot(*goal, marker='o')
plt.show()

optres = fmin(eval_score, guess, **optimsettings)
optcoeff = optres[0]    

#for c in optres[-1][::optimsettings['maxiter']/10]:
for c in array(optres[-1])[logspace(1,log10(optimsettings['maxiter']-1), 10).astype(int)]:
    vx, vy = sinsum(c, tt)
    path = makepath(vx,vy)
    plt.axes().add_collection(LC(path, color='green'))
    plt.show()

করণীয়: জিইউআই যা আপনাকে মোটামুটি দিকনির্দেশনার জন্য প্রাথমিক পথ আঁকতে দেয়। 14-মাত্রিক স্থান থেকে এলোমেলোভাবে নমুনা দেওয়ার চেয়ে যে কোনও কিছুই ভাল


সাবাশ! দেখে মনে হচ্ছে 17 টি পদক্ষেপ সর্বনিম্ন - এই অতিরিক্ত তথ্যের সাহায্যে সমাধানের জন্য আপনি কীভাবে আপনার প্রোগ্রামটি পরিবর্তন করবেন?
ভনজড

ওহে প্রিয়: আমার প্রোগ্রামটি দেখায় যে আপনি (320,220) এ শেষ না হয়ে (320,240) এ গিয়েছেন - আপনি কি দয়া করে এটি পরীক্ষা করে দেখুন
ভনজড

1
ওফস, সমাধানটি আপডেট করেছে এবং এটিকে 24 টি ধাপে পুনর্নির্মাণ করেছে। হাত দিয়ে ফাইন টিউনিং ছবিটি দেখে তুচ্ছভাবে সহজ, এটিকে স্বয়ংক্রিয়ভাবে কোনও সাধারণ কেসের সাথে কাজ করার জন্য - এত বেশি নয়
ডেনডেনডো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.