rubylabs 0.7.4 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.4
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 grams; posx, posy, and posz are the 3d position vector (in meters)
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
 
@@ -1,5 +1,5 @@
1
1
  # Two body system: a 6.6 pound watermelon and the earth. The melon is
2
2
  # initially stationary on the the earth's surface.
3
3
 
4
- melon 3000 0 6.371E6 0 0 0 0 10 pink
4
+ melon 3.0 0 6.371E6 0 0 0 0 10 pink
5
5
  earth 5.9736E+24 0 0 0 0 0 0 1000 darkgreen
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
- sprintf "<%s, %s, %s>", @x.to_s, @y.to_s, @z.to_s
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
- @mass = rand(10000) * 1e6
207
- @position = Vector.new(rand(300)-150, rand(300)-150, 0)
208
- @velocity = Vector.new(rand(20)-10, rand(10)-5, 0)
209
- @name = "b" + self.object_id.to_s
210
- elsif args[0].is_a?(Numeric) && args[1].is_a?(Numeric)
211
- @mass = args[0]
212
- @position = Vector.new(args[1], 0.0, 0.0)
213
- @velocity = Vector.new(0.0, 0.0, 0.0)
214
- @name = args[2]
215
- @linear = true
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
- s = ""
227
- s << @name + ": " if @name
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, moving)
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
- b = Body.new(mm*100/big, r, v)
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], args[3])
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, i, time)
563
- b = bodies[i]
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 0...bodies.length
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, time)
609
+ def step_system(bodies, dt)
588
610
  nb = bodies.length
589
611
 
590
- for i in 0...nb # compute all pairwise interactions
591
- for j in (i+1)...nb
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(time) # apply the accumulated forces
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 dt
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
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-02 00:00:00 -08:00
12
+ date: 2010-03-12 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15