xpflow 0.1b → 0.1c

Sign up to get free protection for your applications and to get access to all the features.
data/bin/xpflow CHANGED
@@ -47,12 +47,26 @@ def usage
47
47
  end
48
48
 
49
49
  def use(*args)
50
-
51
- # TODO: this should be more sophisticated
52
- # for now it's so so
50
+ # obsolete, but backwards compatible 'use'
51
+ return import(*args)
52
+ end
53
+
54
+ def import_via_name(name)
55
+ # TODO: it should be more sophisticated
56
+ name = name.to_s
57
+ begin
58
+ Kernel.load("./#{name}")
59
+ rescue LoadError
60
+ Kernel.require("xpflow/exts/#{name}_use")
61
+ end
62
+ end
53
63
 
54
- args.each do |lib|
55
- require "xpflow/exts/#{lib.to_s}_use"
64
+ def import(*args)
65
+ if args.length == 0
66
+ raise "Import requires a file or a library"
67
+ end
68
+ args.each do |it|
69
+ import_via_name(it)
56
70
  end
57
71
  end
58
72
 
@@ -131,12 +131,12 @@ module XPFlow
131
131
  @config[:labels] += labels.split(',').map { |x| x.downcase.to_sym }
132
132
  end
133
133
 
134
- opts.on("-I", "--ignore-checkpoints", "Ignore automatically saved checkpoints") do
134
+ opts.on("-i", "--ignore-checkpoints", "Ignore automatically saved checkpoints") do
135
135
  @config[:ignore_checkpoints] = true
136
136
  end
137
- # opts.on("-C", "--checkpoint NAME", "Jump to checkpoint NAME (if exists)") do |name|
138
- # @config[:checkpoint] = name
139
- # end
137
+ opts.on("-c", "--checkpoint NAME", "Jump to checkpoint NAME (if exists)") do |name|
138
+ @config[:checkpoint] = name
139
+ end
140
140
  # opts.on("-c", "--list-checkpoints", "List available checkpoints") do
141
141
  # @config[:instead] += [ RunInfo.new(:list_checkpoints) ]
142
142
  # end
data/lib/xpflow/data.rb CHANGED
@@ -48,58 +48,87 @@ module XPFlow
48
48
  return average_stddev().last
49
49
  end
50
50
 
51
- #Credit for cdf_inverse : http://home.online.no/~pjacklam/notes/invnorm/
51
+ # START OF DISTRIBUTIONS
52
+
53
+ # Credit for cdf_inverse : http://home.online.no/~pjacklam/notes/invnorm/
52
54
  # inverse standard normal cumulative distribution function
53
- def cdf_inverse(p)
54
- a = [0, -3.969683028665376e+01, 2.209460984245205e+02, -2.759285104469687e+02, 1.383577518672690e+02, -3.066479806614716e+01, 2.506628277459239e+00]
55
- b = [0, -5.447609879822406e+01, 1.615858368580409e+02, -1.556989798598866e+02, 6.680131188771972e+01, -1.328068155288572e+01]
56
- c = [0, -7.784894002430293e-03, -3.223964580411365e-01, -2.400758277161838e+00, -2.549732539343734e+00, 4.374664141464968e+00, 2.938163982698783e+00]
57
- d = [0, 7.784695709041462e-03, 3.224671290700398e-01, 2.445134137142996e+00, 3.754408661907416e+00]
58
- #Define break-points.
59
- p_low = 0.02425
60
- p_high = 1.0 - p_low
61
-
62
- x = 0.0
63
- q = 0.0
64
- #Rational approximation for lower region.
65
- if 0.0 < p && p < p_low
66
- q = Math.sqrt(-2.0*Math.log(p))
67
- x = (((((c[1]*q+c[2])*q+c[3])*q+c[4])*q+c[5])*q+c[6]) / ((((d[1]*q+d[2])*q+d[3])*q+d[4])*q+1.0)
68
-
69
- #Rational approximation for central region.
70
- elsif p_low <= p && p <= p_high
71
- q = p - 0.5
72
- r = q*q
73
- x = (((((a[1]*r+a[2])*r+a[3])*r+a[4])*r+a[5])*r+a[6])*q / (((((b[1]*r+b[2])*r+b[3])*r+b[4])*r+b[5])*r+1.0)
74
-
75
- #Rational approximation for upper region.
76
- elsif p_high < p && p < 1.0
77
- q = Math.sqrt(-2.0*Math.log(1.0-p))
78
- x = -(((((c[1]*q+c[2])*q+c[3])*q+c[4])*q+c[5])*q+c[6]) / ((((d[1]*q+d[2])*q+d[3])*q+d[4])*q+1.0)
79
- end
80
-
81
- #The relative error of the approximation has
82
- #absolute value less than 1.15 × 10−9. One iteration of
83
- #Halley’s rational method (third order) gives full machine precision.
84
- if 0 < p && p < 1
85
- e = 0.5 * Math.erfc(-x/Math.sqrt(2.0)) - p
86
- u = e * Math.sqrt(2.0*Math::PI) * Math.exp((x**2.0)/2.0)
87
- x = x - u/(1.0 + x*u/2.0)
88
- end
89
- x
90
- end
91
- def minimal_sample_prel(prec,confidance)
92
- minimal_sample_both(prec,nil,confidance)
93
- end
94
- def minimal_sample_pabs(prec,confidance)
95
- minimal_sample_both(nil,prec,condidance)
96
- end
97
- #vectors is values and prec and confidence is in percentage
98
- def minimal_sample_both(prec_rel,prec,confidence)
99
- avg = average
100
- prec = prec_rel.nil? ? prec : avg*prec_rel
101
- critical_value=cdf_inverse((1-confidence)/2)
102
- ((critical_value*stddev() / prec) ** 2).to_i + 1
55
+ def self.cdf_inverse(p)
56
+ a = [0, -3.969683028665376e+01, 2.209460984245205e+02, -2.759285104469687e+02, 1.383577518672690e+02, -3.066479806614716e+01, 2.506628277459239e+00]
57
+ b = [0, -5.447609879822406e+01, 1.615858368580409e+02, -1.556989798598866e+02, 6.680131188771972e+01, -1.328068155288572e+01]
58
+ c = [0, -7.784894002430293e-03, -3.223964580411365e-01, -2.400758277161838e+00, -2.549732539343734e+00, 4.374664141464968e+00, 2.938163982698783e+00]
59
+ d = [0, 7.784695709041462e-03, 3.224671290700398e-01, 2.445134137142996e+00, 3.754408661907416e+00]
60
+ #Define break-points.
61
+ p_low = 0.02425
62
+ p_high = 1.0 - p_low
63
+
64
+ x = 0.0
65
+ q = 0.0
66
+ #Rational approximation for lower region.
67
+ if 0.0 < p && p < p_low
68
+ q = Math.sqrt(-2.0*Math.log(p))
69
+ x = (((((c[1]*q+c[2])*q+c[3])*q+c[4])*q+c[5])*q+c[6]) / ((((d[1]*q+d[2])*q+d[3])*q+d[4])*q+1.0)
70
+
71
+ #Rational approximation for central region.
72
+ elsif p_low <= p && p <= p_high
73
+ q = p - 0.5
74
+ r = q*q
75
+ x = (((((a[1]*r+a[2])*r+a[3])*r+a[4])*r+a[5])*r+a[6])*q / (((((b[1]*r+b[2])*r+b[3])*r+b[4])*r+b[5])*r+1.0)
76
+
77
+ #Rational approximation for upper region.
78
+ elsif p_high < p && p < 1.0
79
+ q = Math.sqrt(-2.0*Math.log(1.0-p))
80
+ x = -(((((c[1]*q+c[2])*q+c[3])*q+c[4])*q+c[5])*q+c[6]) / ((((d[1]*q+d[2])*q+d[3])*q+d[4])*q+1.0)
81
+ end
82
+
83
+ #The relative error of the approximation has
84
+ #absolute value less than 1.15 × 10−9. One iteration of
85
+ #Halley’s rational method (third order) gives full machine precision.
86
+ if 0 < p && p < 1
87
+ e = 0.5 * Math.erfc(-x/Math.sqrt(2.0)) - p
88
+ u = e * Math.sqrt(2.0*Math::PI) * Math.exp((x**2.0)/2.0)
89
+ x = x - u/(1.0 + x*u/2.0)
90
+ end
91
+ return x
92
+ end
93
+
94
+ # computes confidence interval, assuming that
95
+ # the number of measures is large enough
96
+ # to be approximated with CLT
97
+ # prec is ABSOLUTE (here and below)
98
+
99
+ def _compute_dist(prec, conf, cvalue)
100
+ m, s = average_stddev()
101
+ d = (cvalue * s).to_f / (@values.length ** 0.5)
102
+ sample = ((cvalue * s / prec) ** 2).to_i + 1
103
+ return {
104
+ :interval => [ m - d, m + d ],
105
+ :d => d,
106
+ :sample => sample
107
+ }
108
+ end
109
+
110
+ def _dist(name, prec, conf)
111
+ r = case name
112
+ when :n then _dist_n(prec, conf)
113
+ when :t then _dist_t(prec, conf)
114
+ else
115
+ raise "Unknown distribution: #{name}"
116
+ end
117
+ return r
118
+ end
119
+
120
+ def _dist_n(prec, conf)
121
+ cvalue = ValueData.cdf_inverse((1 + conf) * 0.5)
122
+ return _compute_dist(prec, conf, cvalue)
123
+ end
124
+
125
+ def confidence_interval_n(conf)
126
+ return _dist_n(1.0, conf)[:interval]
127
+ end
128
+
129
+ # computes the minimal sample size
130
+ def minimal_sample_n(prec, conf)
131
+ return _dist_n(prec, conf)[:sample]
103
132
  end
104
133
 
105
134
  TSTUDENT = [
@@ -108,33 +137,31 @@ module XPFlow
108
137
  2.074, 2.069, 2.064, 2.060, 2.056, 2.052, 2.048, 2.045, 2.042, 2.021, 2.009,
109
138
  2.000, 1.990, 1.984, 1.980, 1.960 ]
110
139
 
111
- def confidence_interval
112
- if size() >= TSTUDENT.length
113
- factor = TSTUDENT[-1]
114
- else
115
- factor = TSTUDENT[size()]
116
- end
117
- m, s = average_stddev()
118
- d = (factor * s).to_f / (@values.length ** 0.5)
119
- return [m - d, m + d]
140
+ def _get_tstudent_factor
141
+ n = size()
142
+ raise "size of sample must be positive" if n <= 0
143
+ return (n < TSTUDENT.length) ? TSTUDENT[n] : TSTUDENT[-1]
120
144
  end
121
145
 
122
- def confidence_precision
123
- a, b = confidence_interval()
124
- return (b - a) * 0.5
146
+ def _dist_t(prec, conf)
147
+ cvalue = _get_tstudent_factor()
148
+ return _compute_dist(prec, conf, cvalue)
125
149
  end
126
150
 
127
- def confidence_ratio
128
- # provides conf. as a percentage around the estimated mean value
129
- prec = confidence_precision()
130
- mean = average().abs
131
- return (prec / mean)
151
+ # computes confidence interval, assuming that
152
+ # each measure is normal; therefore their
153
+ # average is t-student
154
+ def confidence_interval_t(conf)
155
+ # TODO: confidence is ignored
156
+ return _dist_t(1.0, conf)[:interval]
132
157
  end
133
158
 
134
- def conf_ratio
135
- return confidence_ratio
159
+ def minimal_sample_t(prec, conf)
160
+ return _dist_t(prec, conf)[:sample]
136
161
  end
137
162
 
163
+ # END OF DISTRIBUTIONS
164
+
138
165
  def map(&block)
139
166
  arr = @values.map(&block)
140
167
  return ValueData.new(arr)
@@ -204,8 +204,6 @@ module XPFlow; module G5K
204
204
 
205
205
  def get_sites
206
206
  sites = get_items('sites').list
207
- # TODO: temporary fix for two sites
208
- sites = sites.select { |x| ! [ "Bordeaux", "Reims" ].include?(x['name']) }
209
207
  return sites
210
208
  end
211
209
 
data/lib/xpflow/nodes.rb CHANGED
@@ -458,7 +458,8 @@ module XPFlow
458
458
  :bootstrap_taktuk, :simple_node, :node_range, :taktuk_raw, :test_connectivity,
459
459
  :nodes_from_file, :nodes_from_result, :distribute, :chain_copy, :ssh_key,
460
460
  :nodes_from_machinefile, :g5k_deploy_keys, :localhost, :file_consistency,
461
- :ping_localhost, :ping_node, :g5k_reserve_nodes
461
+ :ping_localhost, :ping_node, :g5k_reserve_nodes,
462
+ :g5k_sites
462
463
 
463
464
  def setup
464
465
  nil
@@ -975,21 +976,30 @@ module XPFlow
975
976
  return true
976
977
  end
977
978
 
978
- def g5k_reserve_nodes(*args)
979
- p = proxy()
979
+ def with_g5k_lib(p)
980
980
  lib = G5K::Library.new
981
981
  lib.logging = proc { |x| p.engine.log(x) }
982
- lib.proxy = proxy
983
- return lib.reserve_nodes(*args)
982
+ lib.proxy = p
983
+ return yield(lib)
984
+
985
+ end
986
+
987
+ def g5k_reserve_nodes(*args)
988
+ with_g5k_lib(proxy) do |lib|
989
+ lib.reserve_nodes(*args)
990
+ end
991
+ end
992
+
993
+ def g5k_sites(*args)
994
+ with_g5k_lib(proxy) do |lib|
995
+ lib.sites()
996
+ end
984
997
  end
985
998
 
986
999
  def g5k_get_avail(opts = {})
987
- p = proxy()
988
- lib = G5K::Library.new
989
- lib.logging = proc { |x| p.engine.log(x) }
990
- lib.proxy = proxy
991
- job = lib.pick_reservation(opts)
992
- return job
1000
+ with_g5k_lib(proxy) do |lib|
1001
+ lib.pick_reservation(opts)
1002
+ end
993
1003
  end
994
1004
 
995
1005
  def nodes_file(user, filepath)
data/lib/xpflow/stdlib.rb CHANGED
@@ -84,8 +84,9 @@ module XPFlow
84
84
  return result
85
85
  end
86
86
 
87
- def value(v)
88
- return v
87
+ def value(*args)
88
+ return args.first if args.length == 1
89
+ return args
89
90
  end
90
91
 
91
92
  def code(*args)
@@ -249,9 +250,9 @@ module XPFlow
249
250
  class DataLibrary < SyncedActivityLibrary
250
251
 
251
252
  activities :store, :data, :avg, :sum, :stddev, :gauss,
252
- :confidence_precision, :confidence_interval, :save_yaml,
253
- :data_vector, :conf_precision, :data_append, :data_push,
254
- :run_later, :get_of, :minimal_sample, :minimal_sample_enough
253
+ :conf_interval, :save_yaml,
254
+ :data_vector, :data_push,
255
+ :run_later, :get_of, :minimal_sample, :sample_enough
255
256
 
256
257
  def data_vector(values = nil)
257
258
  return ValueData.new(values)
@@ -318,10 +319,6 @@ module XPFlow
318
319
  return m + s * Math.cos(2*Math::PI*x) * p
319
320
  end
320
321
 
321
- def data_append(data, x)
322
- return data.append(x)
323
- end
324
-
325
322
  def data_push(data, x)
326
323
  data.push(x)
327
324
  end
@@ -353,13 +350,54 @@ module XPFlow
353
350
  def save_yaml(filename, obj)
354
351
  IO.write(filename, obj.to_yaml)
355
352
  end
356
- def minimal_sample_enough(name,opts={})
357
- minimal_sample(name,opts)<name.size
353
+
354
+ # opts:
355
+ # :dist => distribution type (default: :normal, also: :n, :t, :tstudent)
356
+ # :conf => confidence (default: 0.95)
357
+ # :rel => relative precision in percents (default: 0.1)
358
+ # :abs => absolute precision (e.g., 5)
359
+
360
+ def _parse_sample_opts(v, _opts)
361
+ opts = { :conf => 0.95, :rel => 0.1, :abs => nil, :dist => :n }.merge(_opts)
362
+ dists = { :n => :n, :normal => :n, :t => :t, :tstudent => :t }
363
+ opts[:dist] = dists[opts[:dist]]
364
+ raise "Wrong confidence" if (opts[:conf] <= 0.0 or opts[:conf] >= 1.0)
365
+ if opts[:abs].nil?
366
+ opts[:abs] = v.average() * opts[:rel]
367
+ end
368
+ opts[:info] = v._dist(opts[:dist], opts[:abs], opts[:conf])
369
+ return opts
358
370
  end
359
- def minimal_sample(name,opts={})
360
- opts.merge({:conf=>0.95,:abs=>1})
361
- name.minimal_sample_both(opts[:rel],opts[:abs],opts[:conf])
371
+
372
+ def flatten_data(x)
373
+ if x.is_a?(Array)
374
+ return ValueData.new(x)
375
+ elsif x.is_a?(ValueData)
376
+ return x
377
+ else
378
+ raise "Wrong data type: #{x.class}"
379
+ end
362
380
  end
381
+
382
+ def sample_enough(v, opts = {})
383
+ v = flatten_data(v)
384
+ opts = _parse_sample_opts(v, opts)
385
+ info = opts[:info]
386
+ return info[:d] <= opts[:abs]
387
+ end
388
+
389
+ def minimal_sample(v, opts = {})
390
+ v = flatten_data(v)
391
+ opts = _parse_sample_opts(v, opts)
392
+ return opts[:info][:sample]
393
+ end
394
+
395
+ def conf_interval(v, opts = {})
396
+ v = flatten_data(v)
397
+ opts = _parse_sample_opts(v, opts)
398
+ return opts[:info][:interval]
399
+ end
400
+
363
401
  end
364
402
 
365
403
  class TestLibrary < SyncedActivityLibrary
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xpflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1b
4
+ version: 0.1c
5
5
  prerelease: 3
6
6
  platform: ruby
7
7
  authors: