xpflow 0.1b → 0.1c

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/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: