Author Topic: Re: Finding PI using Collisions  (Read 901 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Finding PI using Collisions
« on: March 20, 2019, 12:47:24 pm »

I've not seen this before, interesting.

I have seen Pi calculations from throwing random line segment "toothpick" over a grid of equally spaced vertical or horizontal lines. Tons of tests for very slow climb to accuracy to a given limit.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Finding PI using Collisions
« Reply #1 on: March 28, 2019, 09:32:34 am »
It would be nice if someone could help repair this to get it working.  This would be a fun way to get different digits of _PI.  So far all my efforts has been useless.

By removing the animations, you probably could get the digits even faster.

I think there is a precision problem. You have to start the bounce at the precise moment of collision, not when one block is part way (no matter how little) into the other block or the wall.

You can't just say when blockSmall.x < wall.x or blockSmall.x + blockSmall.width > blockBig.x start the bounce.

Maybe if you back up the blockSmall.x when it has gone too far into wall or blockBig.x, you would also have to adjust the "bounce" of the blockBig.x from exact point in time of collision.

Append: But what if those two adjustments result in another bounce!
« Last Edit: March 28, 2019, 09:45:03 am by bplus »

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: Finding PI using Collisions
« Reply #2 on: March 28, 2019, 09:39:33 am »

I've not seen this before, interesting.

I have seen Pi calculations from throwing random line segment "toothpick" over a grid of equally spaced vertical or horizontal lines. Tons of tests for very slow climb to accuracy to a given limit.

That would be a fun simulation to code, Buffon's needles it's called?  Someone has proposed that challenge on the n54 (not Steve's which happens to look like the JB forum) forum but after it was closed for unregistered users so no responses.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Finding PI using Collisions
« Reply #3 on: March 28, 2019, 12:19:03 pm »
Could you post the link to Shiffman's lesson?

Wait, this!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Finding PI using Collisions
« Reply #4 on: March 28, 2019, 07:40:58 pm »
OK got it working for up to 4 digits:
Code: QB64: [Select]
  1. _TITLE "Block PI" ' B+ mod  [banned user] Post 2019-03-20
  2.  
  3. SCREEN _NEWIMAGE(1300, 200, 32)
  4. _SCREENMOVE 80, 200
  5. CONST true = -1
  6. CONST false = NOT true
  7.  
  8. count = 0
  9.  
  10.  
  11. digits = 4 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< works up to 4  then 5 completely fails but if move farther away... almost!
  12.  
  13.  
  14. timeSteps = 10 ^ (digits)
  15.  
  16. TYPE newBlock
  17.     x AS DOUBLE
  18.     y AS DOUBLE
  19.     w AS INTEGER
  20.     v AS DOUBLE
  21.     m AS _INTEGER64
  22.     xc AS INTEGER 'constraint block x can't go left of
  23.  
  24. DIM SHARED Block(2) AS newBlock
  25. Block(1).x = 100 'for 5 digits try 1100
  26. Block(1).w = 20
  27. Block(1).m = 1
  28. Block(1).v = 0
  29. Block(1).xc = 0
  30.  
  31. Block(2).x = 200 'for 5 digits try 1200
  32. Block(2).w = 100
  33. Block(2).m = 100 ^ (digits - 1)
  34. Block(2).v = -1 / (timeSteps + 1)
  35. Block(2).xc = 20
  36.  
  37. WHILE NOT Done
  38.     CLS
  39.     FOR t = 1 TO timeSteps
  40.         Block(1).x = Block(1).x + Block(1).v
  41.         Block(2).x = Block(2).x + Block(2).v
  42.         checkCollide
  43.     NEXT
  44.     DrawBlocks
  45.     PRINT "Block 1 v ="; Block(1).v
  46.     PRINT "Block 2 v ="; Block(2).v
  47.     _PRINTSTRING (300, 8), "digits =" + STR$(digits)
  48.     _PRINTSTRING (650, 8), "Count:" + STR$(count)
  49.     _DISPLAY
  50.     _LIMIT 60
  51.  
  52.     IF Block(2).x > _WIDTH THEN Done = true
  53.  
  54. SUB checkCollide
  55.     DIM sm AS DOUBLE
  56.     DIM v1 AS DOUBLE
  57.     DIM v2 AS DOUBLE
  58.  
  59.     IF Block(2).x < Block(1).x + Block(1).w THEN 'collision
  60.         sm = Block(1).m + Block(2).m
  61.         v1 = Block(1).v: v2 = Block(2).v  '<<<<<<<<<<<<<<<<<<<<< make new values from the old ones!!!
  62.         Block(1).v = v1 * (Block(1).m - Block(2).m) / sm + v2 * 2 * Block(2).m / sm
  63.         Block(2).v = v2 * (Block(2).m - Block(1).m) / sm + v1 * 2 * Block(1).m / sm
  64.         count = count + 1
  65.     END IF
  66.     IF Block(1).x < Block(1).xc THEN Block(1).x = Block(1).xc: count = count + 1: Block(1).v = -Block(1).v
  67.     IF Block(2).x < Block(2).xc THEN Block(2).x = Block(2).xc: count = count + 1: Block(2).v = -Block(2).v
  68.  
  69. SUB DrawBlocks
  70.     LINE (Block(1).x, 200 - Block(1).w)-STEP(Block(1).w, Block(1).w), _RGB32(127, 63, 63), BF
  71.     LINE (Block(2).x, 200 - Block(2).w)-STEP(Block(2).w, Block(2).w), _RGB32(63, 63, 127), BF
  72.  
  73.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Finding PI using Collisions
« Reply #5 on: March 30, 2019, 09:16:32 pm »
OK I got 7 digits. It took so long, I'm not interested in trying 8 unless I can make some serious cuts in time.

It only took about 3 main changes to get the code to run correctly (noted in code) compared to previous post.

Code: QB64: [Select]
  1. _TITLE "PI Calc from Block Collision Counts" ' B+ mod  Post 2019-03-30
  2.  
  3. SCREEN _NEWIMAGE(1200, 200, 32)
  4. _SCREENMOVE 80, 200
  5. CONST true = -1
  6. CONST false = NOT true
  7.  
  8. count = 0
  9.  
  10.  
  11. digits = 7 '<<< got 6 but took half hour, so I closed the gaps between wall, block1 and block2 now it takes 15.5 mins
  12.  
  13.  
  14. DIM SHARED timeSteps AS _FLOAT
  15. timeSteps = 10 ^ (digits + 1) 'fix #1, from (digits) to (digits + 1) got me to 5 digits easy!
  16.  
  17. TYPE newBlock 'all _floats to match [banned user]
  18.     x AS _FLOAT
  19.     y AS _FLOAT
  20.     w AS _FLOAT
  21.     v AS _FLOAT
  22.     m AS _FLOAT
  23.     xc AS _FLOAT 'constraint block x can't go left of
  24.  
  25. DIM SHARED Block1 AS newBlock, Block2 AS newBlock 'cut the array and use block1 and block2 to copy [banned user] approach
  26. Block1.x = 1
  27. Block1.w = 20
  28. Block1.m = 1
  29. Block1.v = 0
  30. Block1.xc = 0
  31.  
  32. Block2.x = 22
  33. Block2.w = 100
  34. Block2.m = 100 ^ (digits - 1)
  35. Block2.v = -1 / timeSteps
  36. Block2.xc = Block1.w
  37. startT$ = TIME$
  38. WHILE NOT Done
  39.     CLS
  40.     FOR t = 1 TO timeSteps
  41.         Block1.x = Block1.x + Block1.v
  42.         Block2.x = Block2.x + Block2.v
  43.         checkCollide
  44.     NEXT
  45.  
  46.     DrawBlocks
  47.     PRINT "Block 1 v ="; Block1.v
  48.     PRINT "Block 2 v ="; Block2.v
  49.     _PRINTSTRING (300, 8), "Digits =" + STR$(digits)
  50.     _PRINTSTRING (550, 8), "Count:" + STR$(count)
  51.     _PRINTSTRING (750, 8), "Start: " + startT$
  52.     _DISPLAY
  53.     _LIMIT 60
  54.  
  55.     'the follwing is excellent stop condition because 6 finishes off screen!!!!!!
  56.     'thanks [banned user]
  57.     IF Block1.v > 0 AND Block2.v > Block1.v THEN Done = true
  58. _PRINTSTRING (950, 8), "Done: " + TIME$
  59.  
  60. SUB checkCollide
  61.     DIM sm AS _FLOAT
  62.     DIM v1 AS _FLOAT
  63.     DIM v2 AS _FLOAT
  64.     IF Block2.x < Block1.x + Block1.w THEN 'collision
  65.         sm = Block1.m + Block2.m
  66.         v1 = Block1.v: v2 = Block2.v '<<<<<<<<<<<<<<<<<<<<< make new values from the old ones!!!
  67.         Block1.v = v1 * (Block1.m - Block2.m) / sm + v2 * 2 * Block2.m / sm
  68.         Block2.v = v2 * (Block2.m - Block1.m) / sm + v1 * 2 * Block1.m / sm
  69.         count = count + 1
  70.     END IF
  71.  
  72.     IF Block2.x < Block2.xc THEN Block2.x = Block2.xc 'Fix #2 comment out >> : count = count + 1 ': Block2.v = -Block2.v
  73.     'this stopped the count inflation for digits = 6
  74.  
  75.     IF Block1.x < Block1.xc THEN Block1.x = Block1.xc: count = count + 1: Block1.v = -Block1.v
  76.  
  77.  
  78. SUB DrawBlocks
  79.     LINE (Block1.x, 200 - Block1.w)-STEP(Block1.w, Block1.w), _RGB32(127, 63, 63), BF
  80.     LINE (Block2.x, 200 - Block2.w)-STEP(Block2.w, Block2.w), _RGB32(63, 63, 127), BF
  81.  
  82.  

Here is a record of the last few clicks:
Quote
Started at 10:46 AM
By 12:04 PM it was 5 clicks away
BY 12:18 PM it was 4 clicks away
By 12:45 PM it was 3 clicks away
By 13:31 PM it was 2 clicks away
By 14:59 PM it was 1 click away
By 21:05 PM it finally finished

7 Digits Pi Clac from Block Collision Count.PNG
* 7 Digits Pi Clac from Block Collision Count.PNG (Filesize: 22.81 KB, Dimensions: 1165x618, Views: 46)
« Last Edit: March 31, 2019, 09:12:54 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Finding PI using Collisions
« Reply #6 on: March 31, 2019, 09:11:41 am »
Got the time cut by less than half but still afraid to take a run on 8 digits, though I am curious if the code holds up for 8.
Code: QB64: [Select]
  1. _TITLE "mod 2 PI Calc from Block Collision Counts" ' B+ mod  Post 2019-03-30
  2. '2019-03-30 can I serious cut time for 6 digits from 15.5 mins? 4:34 now
  3. '2019-03-31 7 digit run took 3 hrs 2 mins down from 10 hrs 50 mins (while using computer for other things at same time).
  4.  
  5. DIM digits AS INTEGER
  6. digits = 7 '<<< got 6 but took half hour, so I closed the gaps between wall, block1 and block2 now it takes 15.5 mins
  7.  
  8. SCREEN _NEWIMAGE(1200, 200, 32)
  9. _SCREENMOVE 80, 200
  10. TYPE newBlock
  11.     x AS _FLOAT
  12.     w AS INTEGER
  13.     v AS _FLOAT
  14.     m AS _INTEGER64
  15.     xc AS INTEGER 'constraint block x can't go left of
  16. DIM timeSteps AS _INTEGER64
  17. timeSteps = 10 ^ (digits + 1)
  18. DIM Block1 AS newBlock, Block2 AS newBlock
  19. Block1.x = 1
  20. Block1.w = 20
  21. Block1.m = 1
  22. Block1.v = 0
  23. Block1.xc = 0
  24. Block2.x = Block1.x + Block1.w + 10
  25. Block2.w = 100
  26. Block2.m = 100 ^ (digits - 1)
  27. Block2.v = -.5 / timeSteps
  28. Block2.xc = Block1.w
  29. startT$ = TIME$
  30.     t = 0
  31.     WHILE t < timeSteps
  32.         Block1.x = Block1.x + Block1.v
  33.         Block2.x = Block2.x + Block2.v
  34.         IF Block2.x < Block1.x + Block1.w THEN 'collision
  35.             sm = Block1.m + Block2.m
  36.             v1 = Block1.v: v2 = Block2.v
  37.             Block1.v = v1 * (Block1.m - Block2.m) / sm + v2 * 2 * Block2.m / sm
  38.             Block2.v = v2 * (Block2.m - Block1.m) / sm + v1 * 2 * Block1.m / sm
  39.             count = count + 1
  40.         END IF
  41.         IF Block2.x < Block2.xc THEN Block2.x = Block2.xc
  42.         IF Block1.x < Block1.xc THEN Block1.x = Block1.xc: count = count + 1: Block1.v = -Block1.v
  43.         t = t + 1
  44.     WEND
  45.     CLS
  46.     LINE (Block1.x, 200 - Block1.w)-STEP(Block1.w, Block1.w), _RGB32(127, 63, 63), BF
  47.     LINE (Block2.x, 200 - Block2.w)-STEP(Block2.w, Block2.w), _RGB32(63, 63, 127), BF
  48.     PRINT "Block 1 v ="; Block1.v
  49.     PRINT "Block 2 v ="; Block2.v
  50.     PRINT
  51.     PRINT "Block 1 x ="; Block1.x + Block1.w
  52.     PRINT "Block 2 x ="; Block2.x
  53.     PRINT "X Difference ="; Block2.x - Block1.x - Block1.w
  54.     _PRINTSTRING (300, 8), "Digits =" + STR$(digits)
  55.     _PRINTSTRING (550, 8), "Count:" + STR$(count)
  56.     _PRINTSTRING (750, 8), "Start: " + startT$
  57.     _DISPLAY
  58. LOOP UNTIL Block1.v > 0 AND Block2.v > Block1.v
  59. _PRINTSTRING (950, 8), "Done: " + TIME$
  60.  
  61.  

Shiffman makes it look so easy with JS, he doesn't get bogged down until running 11 digits.

So I am really interested if anyone can cut the time in QB64 code for times comparable to JS.
« Last Edit: March 31, 2019, 09:13:55 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Finding PI using Collisions
« Reply #7 on: April 02, 2019, 03:21:11 pm »
Interesting code changes:

When there is a collision, the code backs up the x value to pre-collision spot, counts a bump and changes velocity.
Eliminated the bogging down by TimeSteps and the constraint checks on the blocks.
Does not bother with visual model but just counts bumps.

Sweet!!!  7 digit instantly! 8 in 1 sec, 9 in 10 secs, 10 in 1 min 38 secs!!!
Code: QB64: [Select]
  1. _TITLE "mod 3 PI Calc from Block Collision Counts" ' B+ mod  Post 2019-04-02
  2. '2019-03-30 can I serious cut time for 6 digits from 15.5 mins? 4:34 now
  3. '2019-03-31 7 digit run took 3 hrs 2 mins down from 10 hrs 50 mins (while using computer for other things at same time).
  4.  
  5. '2019-04-02 [banned user]'s PI Pool changes code thus:
  6. '  1. When there is a collision, the code backs up the x value to pre-collision spot, counts a bump and changes velocity.
  7. '  2. Eliminated the bogging down by TimeSteps and the constraint checks on the blocks.
  8. '  3. Does not bother with visual model but just counts bumps.
  9.  
  10. DIM digits AS INTEGER
  11. digits = 10 ' 7 digit instantly! 8 in 1 sec, 9 in 10 secs, 10 in 1 min 38 secs!!!
  12.  
  13. SCREEN _NEWIMAGE(800, 200, 32)
  14. _SCREENMOVE 300, 200
  15. TYPE newBlock
  16.     x AS _FLOAT
  17.     w AS INTEGER
  18.     v AS _FLOAT
  19.     m AS _INTEGER64
  20.  
  21. DIM Block1 AS newBlock, Block2 AS newBlock
  22. Block1.x = 100
  23. Block1.w = 40
  24. Block1.m = 1
  25. Block1.v = 0
  26.  
  27. Block2.x = 300
  28. Block2.w = 40
  29. Block2.m = 100 ^ (digits - 1)
  30. Block2.v = -5
  31.  
  32. startT$ = TIME$
  33.     Block1.x = Block1.x + Block1.v
  34.     Block2.x = Block2.x + Block2.v
  35.     IF Block2.x < Block1.x + Block1.w THEN 'collision backup and change velocities
  36.         Block1.x = Block1.x - Block1.v
  37.         Block2.x = Block2.x - Block2.v
  38.         sm = Block1.m + Block2.m
  39.         v1 = Block1.v: v2 = Block2.v '<<<<<<<<<<<<<<<<<<<<< make new values from the old ones!!!
  40.         Block1.v = v1 * (Block1.m - Block2.m) / sm + v2 * 2 * Block2.m / sm
  41.         Block2.v = v2 * (Block2.m - Block1.m) / sm + v1 * 2 * Block1.m / sm
  42.         count = count + 1
  43.     END IF
  44.     IF Block1.x <= 0 THEN 'back up and change velocity
  45.         Block1.x = Block1.x - Block1.v
  46.         Block2.x = Block2.x - Block2.v
  47.         count = count + 1: Block1.v = -Block1.v
  48.     END IF
  49. LOOP UNTIL Block1.v > 0 AND Block2.v > Block1.v
  50. _PRINTSTRING (10, 8), "Digits =" + STR$(digits)
  51. _PRINTSTRING (250, 8), "Start: " + startT$
  52. _PRINTSTRING (450, 8), "Done: " + TIME$
  53. _PRINTSTRING (10, 28), _TRIM$(STR$(count)) + " Collisions Counted"
  54. _PRINTSTRING (10, 48), "314159265358979323846264338327950288419716939937510  [banned user]'s PI reference"
  55.  
  56.  

mod  3 PI Calc from collisions 10 digits!.PNG
* mod 3 PI Calc from collisions 10 digits!.PNG (Filesize: 25.16 KB, Dimensions: 832x333, Views: 40)
« Last Edit: April 02, 2019, 03:24:40 pm by bplus »