ฟิสิกส์ของเกมที่สมบูรณ์แบบ แม่นยำไม่สิ้นสุดใน Python (ตอนที่ 1)

Nov 26 2022
ด้วยความแม่นยำอย่างแท้จริง โปรแกรม “Newton's Cradle” “ลูกเทนนิสและลูกบาสเก็ตบอลหล่น” และอื่นๆ นี่คือบทความแรกจากทั้งหมดสี่บทความที่แสดงให้คุณเห็นถึงวิธีการตั้งโปรแกรมเครื่องมือทางฟิสิกส์ที่สมบูรณ์แบบใน Python เป็นก้าวเล็กๆ ในความทะเยอทะยานอันยิ่งใหญ่ของฉันที่จะเปลี่ยนฟิสิกส์ คณิตศาสตร์ และแม้แต่ปรัชญาทั้งหมดให้เป็นการเขียนโปรแกรม

ด้วยความแม่นยำอย่างแท้จริง โปรแกรม “Newton's Cradle” “ลูกเทนนิสและบาสเก็ตบอลหล่น” และอื่นๆ

Newton's Cradle กับ Python — ที่มา: แก้ไขแล้ว https://openai.com/dall-e-2/

นี่เป็นบทความแรกจากทั้งหมดสี่บทความที่แสดงให้คุณเห็นถึงวิธีการตั้งโปรแกรมเครื่องมือทางฟิสิกส์ที่สมบูรณ์แบบใน Python เป็นก้าวเล็กๆ ในความทะเยอทะยานอันยิ่งใหญ่ของฉันที่จะเปลี่ยนฟิสิกส์ คณิตศาสตร์ และแม้แต่ปรัชญาทั้งหมดให้เป็นการเขียนโปรแกรม เราจะค้นพบเรื่องน่าประหลาดใจ เพิ่มความเข้าใจ และ (ฉันหวังว่า) จะสนุกผ่านโครงการนี้ รหัสทั้งหมดมี อยู่ใน GitHub

เราจะจำกัดกลไกในหลายๆ วิธี ตัวอย่างเช่น การชนกันของนิวตันระหว่างวงกลมกับเส้น อย่างไรก็ตาม เราจะไม่จำกัดความแม่นยำของเครื่องยนต์ 8*sqrt(3)/3โดยจะแสดงเวลา ตำแหน่ง และความเร็วทั้งหมดด้วยนิพจน์ที่ แน่นอนเช่น กล่าวอีกนัยหนึ่ง มันหลีกเลี่ยงการประมาณตัวเลขทั้งหมด

ผลลัพธ์จะเป็นแบบจำลองที่สมบูรณ์แบบ เช่น ของเล่นเปลของนิวตัน (หากต้องการเล่นซ้ำ/หยุดวิดีโอชั่วคราว ให้กดปุ่มที่มุมซ้ายล่าง เสียงจะมีประโยชน์)

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

  • การ จำกัดความเร็วของลูกเทนนิส — ในการสาธิตฟิสิกส์ที่ได้รับความนิยม คุณจะโยนลูกเทนนิสด้วยลูกบาสเก็ตบอล ลูกเทนนิสเด้งขึ้นเร็วกว่าตกมาก เร็วขึ้นแค่ไหน? เราจะเห็นว่าความเร็ว "ขึ้น" ไม่เกินสามเท่าของความเร็ว "ลง" สิ่งนี้ถือได้แม้ว่าเราจะสร้างลูกบาสเก็ตบอลให้ใหญ่อย่างไม่มีที่สิ้นสุด
  • การ สั่นสะเทือนที่ดี — ลองนึกภาพลูกเทนนิสที่กำลังเคลื่อนที่ซึ่งติดอยู่ระหว่างแป้นบาสกับกำแพง ในช่วงเวลาสั้น ๆ ระหว่างสองเฟรมของวิดีโอ ลูกเทนนิสสามารถกระดอนได้ 80 ครั้ง เครื่องมือที่ใช้การประมาณอาจพลาดการตีกลับบางส่วนเหล่านี้ เครื่องยนต์ของเรานับทุกๆ
  • Billiards Broken — แม้จะมีความแม่นยำไม่สิ้นสุด การแตกของ Billiards ก็ไม่สามารถย้อนกลับได้ เราจะเห็นว่าแม้เราจะลบ "ผลบัตเตอร์ฟลาย" และความไม่แน่นอนของควอนตัมออกไปแล้ว โลกก็ยังเป็นไปโดยสุ่มและไม่สามารถกำหนดได้

สร้างเครื่องยนต์

สมมติว่าเรามีฟังก์ชัน Python สำหรับ:

  • ให้วัตถุสองชิ้น (อาจเคลื่อนที่ได้) ใดๆ ในโลก ให้กลับช่วงเวลาที่แน่นอนจนกว่าวัตถุเหล่านั้นจะสัมผัสกัน คำตอบอาจเป็น "ไม่เคย"
  • เมื่อพิจารณาจากวัตถุสองชิ้นที่ชนกัน การชนจะเปลี่ยนความเร็วและทิศทางอย่างไร

ลองใช้แนวทางโดยดูโลกฟิสิกส์สามโลก โดยเริ่มจาก Newton's Cradle

เปลของนิวตัน

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

สำหรับ Newton's Cradle เราสร้างวงกลมและกำแพงก่อน

from perfect_physics import World, Circle, Wall

circle_list = [Circle(x=1, y=0, r=1, vx=1, vy=0, m=1)]
for i in range(1, 6):
    circle_list.append(Circle(x=i * 2 + 4, y=0, r=1, vx=0, vy=0, m=1))
wall_list = [Wall(x0=0, y0=0, x1=0, y1=1), Wall(x0=20, y0=0, x1=20, y1=1)]
world = World(circle_list, wall_list, xlim=(-1, 21), ylim=(-2, 2))
world.show()

      
                

  • ระหว่างวัตถุแต่ละคู่ ให้หาช่วงเวลาที่วัตถุชนกัน (ถ้ามี) ไม่สนใจคู่อื่นและการชนกัน — ในกรณีนี้ วงกลมแรก (เคลื่อนที่) จะชนกับวงกลมที่สองในช่วงเวลา 3 โดยไม่คำนึงถึงการชนกันนั้น มันจะชนกับวงกลมที่สามในช่วงเวลา 5 เป็นต้น มันจะชนกับกำแพงที่อยู่ไกลออกไปในเวลา ช่วง 18.
  • ค้นหาช่วงเวลาของการชนกันครั้งแรกและเลื่อนนาฬิกาโลกให้เร็วขึ้นขนาดนั้น ในกรณีนี้3.
  • ปรับความเร็วของวัตถุทั้งหมดที่เกี่ยวข้องกับการชนเหล่านี้ ตามที่คาดไว้ใน Newton's Cradle วงกลมแรกจะหยุดนิ่ง และวงกลมที่สองจะเริ่มเคลื่อนที่
  • ทำซ้ำได้นานเท่าที่ต้องการ ในตัวอย่าง ลูกบอลลูกที่สองและสามจะชนกันในช่วงเวลา 0 วิดีโอนี้แสดงการกระทำ เหตุการณ์ต่อเหตุการณ์ ("เหตุการณ์" คือการเลื่อนเวลาไปสู่การชนหรือปรับความเร็วตามการชน)

โดยทั่วไปแล้ว สำหรับทุกเฟรม เรา:

  • ค้นหาค่านาฬิกาจำลองสำหรับเฟรมนั้น
  • ค้นหาเหตุการณ์การชนที่อยู่ก่อนหน้าค่านาฬิกานั้น
  • เริ่มจากโลกที่การชนก่อนหน้า เลื่อนวงกลมไปที่ค่านาฬิกาของเฟรม (โดยการออกแบบ วงกลมจะไม่ชนกับสิ่งใดระหว่างการเคลื่อนที่นี้)

วงกลม&สามเหลี่ยม

ฉันอ้างว่าเวลาและตำแหน่งนั้นแน่นอนทั้งหมด แต่คุณเชื่อฉันไหม นี่คือหลักฐานบางส่วนผ่านวงกลมที่จารึกด้วยรูปสามเหลี่ยม ขั้นแรก นี่คือวิดีโอที่แสดงเฉพาะเหตุการณ์ 8*sqrt(3)/3คุณสามารถดูนาฬิกาที่ตั้งค่า เป็นนิพจน์ เช่น

และนี่คือวิดีโอปกติสำหรับวงกลมในรูปสามเหลี่ยม:

ในกรณีนี้ การจำลองจะเป็นไปตามรูปแบบ หากไม่มีความแม่นยำที่ไม่สิ้นสุด รูปแบบอาจพลาดได้

ลูกเทนนิสและบาสเก็ตบอลหล่น

ลองดูที่โลกฟิสิกส์อีกแห่งหนึ่งเพื่อดูข้อดีอีกอย่างของความแม่นยำที่ไม่สิ้นสุด โลกนี้ประกอบด้วยลูกเทนนิสและบาสเก็ตบอลที่เคลื่อนที่เข้าหากำแพงด้วยความเร็ว 1 มวลของลูกบาสเก็ตบอลเป็น 1,000 เท่าของลูกเทนนิส (โลกของเราไม่มีแรงโน้มถ่วง)

from perfect_physics import World, Circle, Wall

big_radius = 10
world_width = 40
folder = root / f"part1/two_size{big_radius}"

big = Circle(x=world_width // 2, y=0, r=big_radius, vx=1, vy=0, m=big_radius**3)
little = Circle(x=big.x - big_radius - 1, y=0, r=1, vx=1, vy=0, m=1)
circle_list = [big, little]
wall_list = [Wall(x0=0, y0=0, x1=0, y1=1), Wall(x0=world_width, y0=0, x1=world_width, y1=1)]
world = World(circle_list, wall_list, xlim=(-1, world_width + 1), ylim=(-big_radius - 1, big_radius + 1))
world.run_in_place(2, show=True)
print([circle.vx for circle in world.circle_list])

อย่างที่คาดไว้ (ถ้าคุณเคยลองมาแล้วในโลกจริง) ลูกเทนนิสจะเร็วขึ้น อย่างไรก็ตาม มันทำให้ฉันประหลาดใจที่เร็วขึ้นเพียงสามเท่า

ข้ามไปสักครู่แล้วใช้เครื่องมือที่เราจะพัฒนาในส่วนที่ 3 โค้ด Python นี้แสดงผลต่อลูกเทนนิสของบาสเก็ตบอลที่มีมวลเป็นอนันต์ ลูกเทนนิสเข้าไปด้วยความเร็ว 1 และออกไปด้วยความเร็ว 3 เป๊ะๆ

from sympy import limit, simplify, oo
from perfect_physics import load
cc_velocity_solution = load("data/cc_velocity_solution.sympy")
a_vx, a_vy, b_vx, b_vy  = cc_velocity_solution.subs([("a_x", 10), ("a_y", 0), ("a_r", 10), ("a_vx", -1), ("a_vy", 0),
                            ("b_x", -1), ("b_y", 0), ("b_r", 1), ("b_vx", 1), ("b_vy", 0), ("b_m", 1)])
print(simplify(b_vx))
limit(b_vx, "a_m", oo)
# prints (1 - 3*a_m)/(a_m + 1)
# returns -3

เครื่องยนต์ทำให้ฉันประหลาดใจมากยิ่งขึ้นเมื่อฉันปล่อยให้มันทำงานนานขึ้น ดูสิ่งที่เกิดขึ้นในเวลาวิดีโอ 20 วินาที (เวลาจำลอง 200):

บาสเก็ตบอลบีบลูกเทนนิส ซึ่งจะทำให้ลูกเทนนิสกระเด้งไปมามากกว่า 80 ครั้งในวิดีโอเฟรมเดียว ลูกเทนนิสมีความเร็วสูงเกิน 31 ในแทร็กเสียงของวิดีโอ การสั่นของลูกเทนนิสทำให้เกิดเสียงมากกว่า 2,000 Hz (ครั้ง/วินาที)

หากเราสุ่มตัวอย่างเพียงครั้งเดียวต่อเฟรมแทนที่จะคำนวณแบบแม่นยำ เราจะพลาด (หรือคำนวณผิด) การกระทำที่รวดเร็วนี้

สรุปส่วนที่ 1

มันได้ผล! เรามีเครื่องมือทางฟิสิกส์ที่สมบูรณ์แบบ เราได้เปลี่ยนฟิสิกส์เป็นการเขียนโปรแกรม

เราสันนิษฐานว่าเราเริ่มต้นด้วยสองฟังก์ชัน Python ที่บอกเราว่า - สำหรับวัตถุคู่ใดก็ตาม - สองสิ่ง 1) เวลาจนกว่าจะเกิดการชนกันครั้งต่อไป (ถ้ามี) และ 2) ผลของการชนนั้นต่อความเร็ว เราได้เห็นวิธีเปลี่ยนฟังก์ชันทั้งสองนี้ให้เป็นกลไกทางฟิสิกส์ที่สมบูรณ์แบบโดยทำซ้ำๆ กัน: เคลื่อนไปข้างหน้าให้ทันเวลาจนกระทั่งเกิดการชนครั้งต่อไป และปรับความเร็วของวัตถุทั้งหมดที่เกี่ยวข้องกับการชน

เราสร้างวิดีโอโดยค้นหาการชนกันของเฟรมวิดีโอ จากนั้นเลื่อนเวลาไปข้างหน้า (โดยไม่ต้องกังวลเรื่องการชนกัน) ของเฟรมนั้น

Newton's Cradle โลกที่หนึ่ง ประพฤติตามที่คาดไว้ โลกใบที่ 2 วงกลมที่เขียนด้วยสามเหลี่ยม ใช้สำนวน เช่น8*sqrt(3)/3เวลา เป็นต้น พบรูปแบบ การโยนลูกเทนนิสและบาสเก็ตบอลทำให้ความเร็วของลูกเทนนิสเกินขีดจำกัดอย่างน่าประหลาดใจสำหรับฉัน นอกจากนี้ยังสร้างการตีกลับได้เร็วกว่าวิธีที่สมบูรณ์แบบน้อยกว่าที่สามารถคำนวณได้

บทความถัดไปตอนที่ 2จำลองการแตกของบิลเลียดด้วยผลลัพธ์ทางปรัชญาที่น่าประหลาดใจสำหรับฉัน ต่อไป ในตอนที่ 3 เราจะดูวิธีทำให้คอมพิวเตอร์สร้างฟังก์ชันเริ่มต้นทั้งสองนี้ สุดท้าย ในตอนที่ 4 เราจะเร่งเครื่องยนต์เล็กน้อย (แต่ยังไม่เพียงพอ) และหารือเกี่ยวกับข้อจำกัดต่างๆ

หากคุณมีไอเดียสำหรับการจำลองที่คุณต้องการให้ฉันดำเนินการ โปรดส่งมาให้ฉัน พวกเขาอาจกลายเป็นพื้นฐานของส่วนที่ 5

คุณสามารถดาวน์โหลดโค้ดนี้ได้จากCarlKCarlK/perfect-physics (github.com ) แจ้งให้เราทราบหากมีความสนใจและฉันจะสร้างตัวติดตั้งที่ดีกว่า

ติดตามCarl M. Kadie — สื่อสำหรับการแจ้งเตือนในส่วนต่อไป ทุกส่วนจะอ่านได้ฟรี สุดท้าย บน YouTube ฉันมีแบบจำลองทางฟิสิกส์ ที่เก่ากว่า (โดยประมาณ) และ วิดีโอเกี่ยวกับ ธรรมชาติที่พยายามจะตลกขบขัน