rubylabs 0.7.4 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/bin/statistics2-0.53/statistics2.rb +0 -0
- data/bin/statistics2.rb +0 -0
- data/data/spheres/solarsystem.txt +1 -1
- data/data/spheres/urey.txt +1 -1
- data/lib/rubylabs.rb +1 -1
- data/lib/spherelab.rb +74 -58
- data/lib/tsplab.rb +33 -3
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.7.
|
1
|
+
0.7.5
|
File without changes
|
data/bin/statistics2.rb
CHANGED
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Solar system data, downloaded from JPL, from ephemeris created for Jan 1, 1970
|
2
2
|
# Format for each line:
|
3
3
|
# name, mass, posx, posy, posz, velx, vely, velz, dia, color
|
4
|
-
# where mass is in
|
4
|
+
# where mass is in kilograms; posx, posy, and posz are the 3d position vector (in meters)
|
5
5
|
# and velx, vely, and velz is the 3D velocity vector (m/sec). The last two items are
|
6
6
|
# for the visualization -- radius (in pixels) and color for drawing the body.
|
7
7
|
|
data/data/spheres/urey.txt
CHANGED
data/lib/rubylabs.rb
CHANGED
@@ -208,7 +208,7 @@ Similar to TestArray, but draws random words from a file.
|
|
208
208
|
|
209
209
|
class RandomArray < Array
|
210
210
|
|
211
|
-
data = File.join(File.dirname(__FILE__), '..', 'data')
|
211
|
+
data = File.join(File.dirname(__FILE__), '..', 'data', 'arrays')
|
212
212
|
|
213
213
|
@@sources = {
|
214
214
|
:cars => "#{data}/cars.txt",
|
data/lib/spherelab.rb
CHANGED
@@ -78,7 +78,8 @@ module SphereLab
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def inspect
|
81
|
-
|
81
|
+
pos = [@x,@y,@z].map { |x| sprintf "%.5g", x }
|
82
|
+
return "(" + pos.join(",") + ")"
|
82
83
|
end
|
83
84
|
|
84
85
|
=begin rdoc
|
@@ -187,32 +188,20 @@ module SphereLab
|
|
187
188
|
attr_accessor :mass, :position, :velocity, :force
|
188
189
|
attr_accessor :name, :size, :color, :prevx, :prevy, :graphic
|
189
190
|
|
190
|
-
=begin rdoc
|
191
|
-
The constructor can be called with a variety of different arguments:
|
192
|
-
* for the main n-body simulation, initial conditions are read from a data file,
|
193
|
-
and the constructor is passed three parameters: mass, position vector, and
|
194
|
-
velocity vector; an optional 4th parameter is a name string
|
195
|
-
* for interactive experiments, pass two floats, which become the mass and the
|
196
|
-
x component of the velocity; an optional 3rd parameter is the name
|
197
|
-
* also for interactive experiments pass :rand to make a body with random
|
198
|
-
mass, position, and velocity
|
199
|
-
* pass no parameters to get a body with all attributes set to 0
|
200
|
-
=end
|
201
|
-
|
202
191
|
def initialize(*args)
|
203
192
|
if args[1].class == Vector
|
204
193
|
@mass, @position, @velocity, @name = args
|
205
|
-
elsif args[0] == :random
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
elsif args[0].is_a?(Numeric) && args[1].is_a?(Numeric)
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
194
|
+
# elsif args[0] == :random
|
195
|
+
# @mass = rand(10000) * 1e6
|
196
|
+
# @position = Vector.new(rand(300)-150, rand(300)-150, 0)
|
197
|
+
# @velocity = Vector.new(rand(20)-10, rand(10)-5, 0)
|
198
|
+
# @name = "b" + self.object_id.to_s
|
199
|
+
# elsif args[0].is_a?(Numeric) && args[1].is_a?(Numeric)
|
200
|
+
# @mass = args[0]
|
201
|
+
# @position = Vector.new(args[1], 0.0, 0.0)
|
202
|
+
# @velocity = Vector.new(0.0, 0.0, 0.0)
|
203
|
+
# @name = args[2]
|
204
|
+
# @linear = true
|
216
205
|
else
|
217
206
|
@mass = 0.0
|
218
207
|
@position = Vector.new(0.0, 0.0, 0.0)
|
@@ -223,15 +212,8 @@ module SphereLab
|
|
223
212
|
end
|
224
213
|
|
225
214
|
def inspect
|
226
|
-
|
227
|
-
s
|
228
|
-
s << @mass.to_s + "g "
|
229
|
-
if @linear
|
230
|
-
s << "x: " + @position.x.to_s
|
231
|
-
else
|
232
|
-
s << @position.inspect + " " + @velocity.inspect
|
233
|
-
end
|
234
|
-
return s
|
215
|
+
name = @name ? @name : ""
|
216
|
+
return sprintf "%s: %.3g kg %s %s", name, @mass, @position.inspect, @velocity.inspect
|
235
217
|
end
|
236
218
|
|
237
219
|
=begin rdoc
|
@@ -447,7 +429,8 @@ module SphereLab
|
|
447
429
|
|
448
430
|
def random_vectors(r, i, n)
|
449
431
|
theta = (2 * PI / n) * i + (PI * rand / n)
|
450
|
-
radius = r + (r/3)*(rand-0.5)
|
432
|
+
# radius = r + (r/3)*(rand-0.5)
|
433
|
+
radius = r + r * (rand-0.5)
|
451
434
|
x = radius * cos(theta)
|
452
435
|
y = radius * sin(theta)
|
453
436
|
vtheta = (PI - theta) * -1 + PI * (rand-0.5)
|
@@ -459,19 +442,23 @@ module SphereLab
|
|
459
442
|
def random_velocity(v, r)
|
460
443
|
res = Vector.new(-r * cos)
|
461
444
|
end
|
445
|
+
|
446
|
+
# todo -- put mm, mr in global options
|
462
447
|
|
463
|
-
def random_bodies(n, big
|
448
|
+
def random_bodies(n, big)
|
464
449
|
big = 1 if big.nil?
|
465
450
|
moving = true if moving.nil?
|
466
451
|
res = []
|
467
452
|
mm = 1e12 # average mass
|
468
453
|
mr = 150 # average distance from origin
|
454
|
+
bigm = (mm * 100) / big
|
469
455
|
big.times do |i|
|
470
456
|
r, v = random_vectors(mr/2, i, big)
|
471
|
-
|
457
|
+
ms = (1 + (rand/2 - 0.25) )
|
458
|
+
b = Body.new(bigm*ms, r, v)
|
472
459
|
b.name = "b#{i}"
|
473
460
|
b.color = '#0080ff'
|
474
|
-
b.size = 10
|
461
|
+
b.size = 10*ms
|
475
462
|
res << b
|
476
463
|
end
|
477
464
|
(n-big).times do |i|
|
@@ -482,12 +469,24 @@ module SphereLab
|
|
482
469
|
b.size = 5
|
483
470
|
res << b
|
484
471
|
end
|
485
|
-
if !moving
|
486
|
-
res.each { |b| b.velocity.x = b.velocity.y = b.velocity.z = 0.0 }
|
487
|
-
end
|
488
472
|
return res
|
489
473
|
end
|
490
474
|
|
475
|
+
def falling_bodies(n)
|
476
|
+
raise "n must be 5 or more" unless n >= 5
|
477
|
+
a = random_bodies(n-1, n-1)
|
478
|
+
# b = Body.new(1e13, (a[0].position + a[1].position), Vector.new(0,0,0))
|
479
|
+
b = Body.new(1e13, (a[0].position + a[1].position)*0.85, Vector.new(0,0,0))
|
480
|
+
# pos = a[0].position
|
481
|
+
# (1..(n-2)).each { |i| pos.add( a[i].position ) }
|
482
|
+
# b = Body.new(1e14, pos * (1.0 / n), Vector.new(0,0,0))
|
483
|
+
b.name = "falling"
|
484
|
+
b.size = 5
|
485
|
+
b.color = 'red'
|
486
|
+
a.insert(0, b)
|
487
|
+
return a
|
488
|
+
end
|
489
|
+
|
491
490
|
=begin rdoc
|
492
491
|
Initialize a new n-body system, returning an array of body objects. The
|
493
492
|
parameter is the name of a predefined system, the name of a file, or the
|
@@ -500,7 +499,10 @@ module SphereLab
|
|
500
499
|
raise "usage: make_system(id)" unless args.length > 0
|
501
500
|
if args[0] == :random
|
502
501
|
raise "usage: make_system(:random, n, m)" unless args.length >= 2 && args[1].class == Fixnum
|
503
|
-
return random_bodies(args[1], args[2]
|
502
|
+
return random_bodies(args[1], args[2])
|
503
|
+
elsif args[0] == :falling
|
504
|
+
raise "usage: make_system(:falling, n)" unless args.length >= 1 && args[1].class == Fixnum
|
505
|
+
return falling_bodies(args[1])
|
504
506
|
end
|
505
507
|
filename = args[0]
|
506
508
|
if filename.class == Symbol
|
@@ -518,6 +520,16 @@ module SphereLab
|
|
518
520
|
b.size = a[-2].to_i
|
519
521
|
b.color = a[-1]
|
520
522
|
bodies << b
|
523
|
+
end
|
524
|
+
if args[0] == :urey
|
525
|
+
class <<bodies[0]
|
526
|
+
def height
|
527
|
+
return 0 if prevy.nil?
|
528
|
+
return position.y - prevy
|
529
|
+
end
|
530
|
+
# def height=(x)
|
531
|
+
# end
|
532
|
+
end
|
521
533
|
end
|
522
534
|
rescue
|
523
535
|
puts "error: #{$!}"
|
@@ -559,23 +571,33 @@ module SphereLab
|
|
559
571
|
Demonstrate adding force vectors by moving only one body
|
560
572
|
=end
|
561
573
|
|
562
|
-
def update_one(bodies,
|
563
|
-
b = bodies[
|
574
|
+
def update_one(bodies, time)
|
575
|
+
b = bodies[0]
|
564
576
|
if b.graphic.nil?
|
565
577
|
puts "display the system with view_system"
|
566
578
|
return nil
|
567
579
|
end
|
568
|
-
for j in
|
569
|
-
next if i == j
|
580
|
+
for j in 1...bodies.length
|
570
581
|
Body.interaction( b, bodies[j] )
|
571
582
|
end
|
572
583
|
b.move(time)
|
584
|
+
if @@drawing.options.has_key?(:dash)
|
585
|
+
@@drawing.options[:dashcount] = (@@drawing.options[:dashcount] + 1) % @@drawing.options[:dash]
|
586
|
+
if @@drawing.options[:dashcount] == 0
|
587
|
+
@@drawing.options[:pendown] = @@drawing.options[:pendown].nil? ? :track : nil
|
588
|
+
end
|
589
|
+
end
|
573
590
|
newx, newy = scale(b.position, @@drawing.origin, @@drawing.scale)
|
574
591
|
Canvas.move(b.graphic, newx-b.prevx, newy-b.prevy, @@drawing.options[:pendown])
|
575
592
|
b.prevx = newx
|
576
593
|
b.prevy = newy
|
577
594
|
b.clear_force
|
595
|
+
# puts b.velocity.norm
|
596
|
+
# if (speed = b.velocity.norm) > 7.5
|
597
|
+
# b.velocity.scale(7.5 / speed)
|
598
|
+
# end
|
578
599
|
Canvas.sync
|
600
|
+
return true
|
579
601
|
end
|
580
602
|
|
581
603
|
=begin rdoc
|
@@ -584,17 +606,17 @@ module SphereLab
|
|
584
606
|
=end
|
585
607
|
|
586
608
|
# :begin :step_system
|
587
|
-
def step_system(bodies,
|
609
|
+
def step_system(bodies, dt)
|
588
610
|
nb = bodies.length
|
589
611
|
|
590
|
-
for i in 0
|
591
|
-
for j in (i+1)
|
612
|
+
for i in 0..(nb-1) # compute all pairwise interactions
|
613
|
+
for j in (i+1)..(nb-1)
|
592
614
|
Body.interaction( bodies[i], bodies[j] )
|
593
615
|
end
|
594
616
|
end
|
595
617
|
|
596
618
|
bodies.each do |b|
|
597
|
-
b.move(
|
619
|
+
b.move(dt) # apply the accumulated forces
|
598
620
|
b.clear_force # reset force to 0 for next round
|
599
621
|
end
|
600
622
|
end
|
@@ -686,12 +708,6 @@ module SphereLab
|
|
686
708
|
mymax = earth.coords[1]
|
687
709
|
melon = Canvas.circle(mxmin, mymax, 5, :fill => blist[0].color)
|
688
710
|
blist[0].graphic = melon
|
689
|
-
class <<blist[0]
|
690
|
-
def height
|
691
|
-
return 0 if prevy.nil?
|
692
|
-
return position.y - prevy
|
693
|
-
end
|
694
|
-
end
|
695
711
|
scale = (mymax-mymin) / hmax.to_f
|
696
712
|
@@drawing = MelonView.new(blist, scale, blist[0].position.y, melon.coords, options)
|
697
713
|
Canvas.sync
|
@@ -706,7 +722,7 @@ module SphereLab
|
|
706
722
|
|
707
723
|
def position_melon(blist, height)
|
708
724
|
melon = blist[0]
|
709
|
-
if @@drawing
|
725
|
+
if @@drawing && blist[0].graphic
|
710
726
|
if height < 0 || height > @@drawing.options[:hmax]
|
711
727
|
puts "Height must be between 0 and #{@@drawing.options[:hmax]} meters"
|
712
728
|
return false
|
@@ -732,7 +748,7 @@ module SphereLab
|
|
732
748
|
my = melon.position.y
|
733
749
|
return "splat" if melon.prevy.nil? || my < melon.prevy
|
734
750
|
step_system(blist, dt)
|
735
|
-
if @@drawing
|
751
|
+
if @@drawing && blist[0].graphic
|
736
752
|
if @@drawing.options[:dash] > 0
|
737
753
|
@@drawing.options[:dashcount] = (@@drawing.options[:dashcount] + 1) % @@drawing.options[:dash]
|
738
754
|
if @@drawing.options[:dashcount] == 0
|
@@ -744,7 +760,7 @@ module SphereLab
|
|
744
760
|
Canvas.move(melon.graphic, dx, dy, @@drawing.options[:pendown])
|
745
761
|
Canvas.sync
|
746
762
|
end
|
747
|
-
return
|
763
|
+
return blist[0].height
|
748
764
|
end
|
749
765
|
|
750
766
|
# :begin :drop_melon
|
data/lib/tsplab.rb
CHANGED
@@ -126,7 +126,7 @@ minutes.
|
|
126
126
|
def coords(name)
|
127
127
|
return @coords[name]
|
128
128
|
end
|
129
|
-
|
129
|
+
|
130
130
|
# private methods -- return the key for a city (make a new one if necessary),
|
131
131
|
# get a time value from an input line, save a distance
|
132
132
|
|
@@ -247,6 +247,9 @@ inherited from a parent, and incremented whenever a mutation or crossover is app
|
|
247
247
|
|
248
248
|
=end
|
249
249
|
|
250
|
+
=begin
|
251
|
+
TODO don't give access to path (unless there's a way to make it read-only -- freeze it?)
|
252
|
+
=end
|
250
253
|
|
251
254
|
class Tour
|
252
255
|
attr_reader :id, :path, :cost, :matrix, :nm, :nx
|
@@ -292,6 +295,33 @@ inherited from a parent, and incremented whenever a mutation or crossover is app
|
|
292
295
|
end
|
293
296
|
end
|
294
297
|
|
298
|
+
# Another constructor -- return the next tour lexicographically
|
299
|
+
# following tour t
|
300
|
+
|
301
|
+
def Tour.next(t)
|
302
|
+
p = t.path.clone
|
303
|
+
n = p.length
|
304
|
+
# find largest j s.t. path[j] < path[j+1]
|
305
|
+
j = n-2
|
306
|
+
while j >= 0
|
307
|
+
break if p[j] < p[j+1]
|
308
|
+
j -= 1
|
309
|
+
end
|
310
|
+
return nil if j < 0
|
311
|
+
# find largest i s.t. path[j] < path[i]
|
312
|
+
i = n-1
|
313
|
+
loop do
|
314
|
+
break if p[j] < p[i]
|
315
|
+
i -= 1
|
316
|
+
end
|
317
|
+
# exchange path[j], path[i]
|
318
|
+
p[j], p[i] = p[i], p[j]
|
319
|
+
# reverse path from j+1 to end
|
320
|
+
tmp = p.slice!(j+1, n-1)
|
321
|
+
p += tmp.reverse
|
322
|
+
return Tour.new(t.matrix, p)
|
323
|
+
end
|
324
|
+
|
295
325
|
def to_s()
|
296
326
|
return "\##{@id}: #{@path} / #{@cost}"
|
297
327
|
end
|
@@ -342,12 +372,12 @@ inherited from a parent, and incremented whenever a mutation or crossover is app
|
|
342
372
|
@nm += t.nm
|
343
373
|
self
|
344
374
|
end
|
345
|
-
|
375
|
+
|
346
376
|
# private methods -- compute the cost of a path, given a matrix; apply
|
347
377
|
# mutations (point mutations, cross-overs)
|
348
378
|
|
349
379
|
private
|
350
|
-
|
380
|
+
|
351
381
|
def pathcost(m,s)
|
352
382
|
sum = m.distance(s[0],s[-1]) # link from end to start
|
353
383
|
for i in 0..s.length-2
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubylabs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- conery
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-03-
|
12
|
+
date: 2010-03-12 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|