From: Brian Warner
Date: Thu, 19 Feb 2009 20:55:15 +0000 (-0700)
Subject: reliability.py: fix the numpy conversion, it was completely broken. Thanks to Terrell...
X-Git-Tag: allmydata-tahoe-1.4.0~180
X-Git-Url: https://git.rkrishnan.org/?a=commitdiff_plain;h=790a10d1b2a8bc78ea4c81e12ec330a3e2d9a27e;p=tahoe-lafs%2Ftahoe-lafs.git
reliability.py: fix the numpy conversion, it was completely broken. Thanks to Terrell Russell for the help.
---
diff --git a/src/allmydata/reliability.py b/src/allmydata/reliability.py
index 2729692a..76d930f3 100644
--- a/src/allmydata/reliability.py
+++ b/src/allmydata/reliability.py
@@ -2,7 +2,7 @@
import math
from allmydata.util import statistics
-from numpy import array
+from numpy import array, matrix, dot
DAY=24*60*60
MONTH=31*DAY
@@ -78,14 +78,14 @@ class ReliabilityModel:
#print "REPAIR:", repair
#print "DIFF:", (old_post_repair - decay * repair)
- START = array([[0]*N + [1]])
- ALIVE = array([[0]*k + [1]*(1+N-k)])
- DEAD = array([[1]*k + [0]*(1+N-k)])
- REPAIRp = array([[0]*k + [1]*(R-k) + [0]*(1+N-R)])
- REPAIR_newshares = array([[0]*k +
- [N-i for i in range(k, R)] +
- [0]*(1+N-R)])
- assert REPAIR_newshares.shape[1] == N+1
+ START = array([0]*N + [1])
+ ALIVE = array([0]*k + [1]*(1+N-k))
+ DEAD = array([1]*k + [0]*(1+N-k))
+ REPAIRp = array([0]*k + [1]*(R-k) + [0]*(1+N-R))
+ REPAIR_newshares = array([0]*k +
+ [N-i for i in range(k, R)] +
+ [0]*(1+N-R))
+ assert REPAIR_newshares.shape[0] == N+1
#print "START", START
#print "ALIVE", ALIVE
#print "REPAIRp", REPAIRp
@@ -101,24 +101,25 @@ class ReliabilityModel:
report = ReliabilityReport()
for t in range(0, report_span+delta, delta):
- unmaintained_state = unmaintained_state * decay
- maintained_state = maintained_state * decay
+ # the .A[0] turns the one-row matrix back into an array
+ unmaintained_state = (unmaintained_state * decay).A[0]
+ maintained_state = (maintained_state * decay).A[0]
if (t-last_check) > check_period:
last_check = t
# we do a check-and-repair this frequently
- need_repair = (maintained_state * REPAIRp).sum()
+ need_repair = dot(maintained_state, REPAIRp)
P_repaired_last_check_period = need_repair
- new_shares = (maintained_state * REPAIR_newshares).sum()
+ new_shares = dot(maintained_state, REPAIR_newshares)
needed_repairs.append(need_repair)
needed_new_shares.append(new_shares)
- maintained_state = maintained_state * repair
+ maintained_state = (maintained_state * repair).A[0]
if (t-last_report) > report_period:
last_report = t
- P_dead_unmaintained = (unmaintained_state * DEAD).sum()
- P_dead_maintained = (maintained_state * DEAD).sum()
+ P_dead_unmaintained = dot(unmaintained_state, DEAD)
+ P_dead_maintained = dot(maintained_state, DEAD)
cumulative_number_of_repairs = sum(needed_repairs)
cumulative_number_of_new_shares = sum(needed_new_shares)
report.add_sample(t, unmaintained_state, maintained_state,
@@ -128,8 +129,8 @@ class ReliabilityModel:
P_dead_unmaintained, P_dead_maintained)
# record one more sample at the end of the run
- P_dead_unmaintained = (unmaintained_state * DEAD).sum()
- P_dead_maintained = (maintained_state * DEAD).sum()
+ P_dead_unmaintained = dot(unmaintained_state, DEAD)
+ P_dead_maintained = dot(maintained_state, DEAD)
cumulative_number_of_repairs = sum(needed_repairs)
cumulative_number_of_new_shares = sum(needed_new_shares)
report.add_sample(t, unmaintained_state, maintained_state,
@@ -174,7 +175,7 @@ class ReliabilityModel:
assert len(decay_row) == (N+1), len(decay_row)
decay_rows.append(decay_row)
- decay = array(decay_rows)
+ decay = matrix(decay_rows)
return decay
def build_decay_row(self, start_shares, P):
@@ -205,7 +206,7 @@ class ReliabilityModel:
new_repair_row[start_shares] = 1
new_repair_rows.append(new_repair_row)
- repair = array(new_repair_rows)
+ repair = matrix(new_repair_rows)
return repair
class ReliabilityReport:
diff --git a/src/allmydata/test/test_provisioning.py b/src/allmydata/test/test_provisioning.py
index 74c57c4a..7e1f9a2f 100644
--- a/src/allmydata/test/test_provisioning.py
+++ b/src/allmydata/test/test_provisioning.py
@@ -71,7 +71,41 @@ class Reliability(unittest.TestCase):
def test_basic(self):
if ReliabilityModel is None:
raise unittest.SkipTest("reliability model requires NumPy")
+
+ # test that numpy math works the way I think it does
+ import numpy
+ decay = numpy.matrix([[1,0,0],
+ [.1,.9,0],
+ [.01,.09,.9],
+ ])
+ start = numpy.array([0,0,1])
+ g2 = (start * decay).A[0]
+ self.failUnlessEqual(repr(g2), repr(numpy.array([.01,.09,.9])))
+ g3 = (g2 * decay).A[0]
+ self.failUnlessEqual(repr(g3), repr(numpy.array([.028,.162,.81])))
+
+ # and the dot product
+ recoverable = numpy.array([0,1,1])
+ P_recoverable_g2 = numpy.dot(g2, recoverable)
+ self.failUnlessAlmostEqual(P_recoverable_g2, .9 + .09)
+ P_recoverable_g3 = numpy.dot(g3, recoverable)
+ self.failUnlessAlmostEqual(P_recoverable_g3, .81 + .162)
+
r = ReliabilityModel.run(delta=100000,
report_period=3*MONTH,
report_span=5*YEAR)
self.failUnlessEqual(len(r.samples), 20)
+
+ last_row = r.samples[-1]
+ #print last_row
+ (when, unmaintained_shareprobs, maintained_shareprobs,
+ P_repaired_last_check_period,
+ cumulative_number_of_repairs,
+ cumulative_number_of_new_shares,
+ P_dead_unmaintained, P_dead_maintained) = last_row
+ self.failUnless(isinstance(P_repaired_last_check_period, float))
+ self.failUnless(isinstance(P_dead_unmaintained, float))
+ self.failUnless(isinstance(P_dead_maintained, float))
+ self.failUnlessAlmostEqual(P_dead_unmaintained, 0.033591004555395272)
+ self.failUnlessAlmostEqual(P_dead_maintained, 3.2983995819177542e-08)
+
diff --git a/src/allmydata/web/reliability.xhtml b/src/allmydata/web/reliability.xhtml
index d8502031..b01c7927 100644
--- a/src/allmydata/web/reliability.xhtml
+++ b/src/allmydata/web/reliability.xhtml
@@ -38,7 +38,7 @@ repair bandwidth to configure on a Tahoe grid.
check period.
P_dead (unmaintained): the chance that the file will be unrecoverable
without periodic check+repair
- P_dead (maintained): the chance that the file will be recoverable even
+ P_dead (maintained): the chance that the file will be unrecoverable even
with periodic check+repair