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 +19 -5
- data/lib/xpflow/cmdline.rb +4 -4
- data/lib/xpflow/data.rb +97 -70
- data/lib/xpflow/exts/g5k.rb +0 -2
- data/lib/xpflow/nodes.rb +21 -11
- data/lib/xpflow/stdlib.rb +52 -14
- metadata +1 -1
data/bin/xpflow
CHANGED
@@ -47,12 +47,26 @@ def usage
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def use(*args)
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
55
|
-
|
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
|
|
data/lib/xpflow/cmdline.rb
CHANGED
@@ -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("-
|
134
|
+
opts.on("-i", "--ignore-checkpoints", "Ignore automatically saved checkpoints") do
|
135
135
|
@config[:ignore_checkpoints] = true
|
136
136
|
end
|
137
|
-
|
138
|
-
|
139
|
-
|
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
|
-
#
|
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
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
123
|
-
|
124
|
-
return (
|
146
|
+
def _dist_t(prec, conf)
|
147
|
+
cvalue = _get_tstudent_factor()
|
148
|
+
return _compute_dist(prec, conf, cvalue)
|
125
149
|
end
|
126
150
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
135
|
-
return
|
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)
|
data/lib/xpflow/exts/g5k.rb
CHANGED
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
|
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 =
|
983
|
-
return lib
|
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
|
-
|
988
|
-
|
989
|
-
|
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(
|
88
|
-
return
|
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
|
-
:
|
253
|
-
:data_vector, :
|
254
|
-
:run_later, :get_of, :minimal_sample, :
|
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
|
-
|
357
|
-
|
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
|
-
|
360
|
-
|
361
|
-
|
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
|