This topic was tackled before, but only qualitatively. Hence this more quantitative approach.
How to we measure these probabilities?
According to the classical definition of probability, all we need to measure the probability of method m's changing is to measure the ratio of the number of times m actually changes to the number of revisions in the limit as the numbers of changes and revisions approach infinity. Few programs on github, however, have yet reached an infinite number of revisions, so we'll make an approximation: the probability that m changes is the large number of times it changes during a large number of revisions divided by that number of revisions. This is why we need to analyze large numbers of changes and large numbers of consecutive revisions.
Given this, we can calculate the conditional probability:
P(δ(m) ∩ δ(C_{m}))  
P(δ(m)  δ(C_{m})) = 

P(δ(C_{m})) 
P(δ(m) ∩ δ(C_{m})) is the number of revisions in which method m changes simultaneously with any one of its children (divided by the total number of revisions). P(δ(C_{m})) is the total number of times than any child of m changes (divided by the total number of revisions).
Let's take the example shown in figure 3, in which a program of just 3 methods evolves over 4 revisions, where the amateurish, unantialiased, irregular blue "circles" indicate code update to a method.
Figure 3: A system of 3 methods evolving over 4 revisions.
All 3 methods are created in revision 1; this is not considered a change. In revision 2, both m and c1 change. In revision 3, both m and c2 change. In revision 4, only c2 changes.
Let's calculate the change probabilities of each method.
The probability of a change in method m given a change to any child is 2/3 because it changes twice simultaneously with any of its children's changes, and the number of revisions in which any child changes is 3. The probability of a change in m given a change to any antecedent is 0 because it has no antecedents.
The probability of a change in method c1 given a change to any of its children is 0 because it has no children. The probability of a change in c1 given a change to any of its antecedents is 1/2 because it changes only once simultaneously with its antecedent, and that antecedent changes a total of 2 times.
Method c2 has the same probabilities as c1.
The system's ripple bias is the sum of all childrelated probabilities divided by the sum of all antecedentrelated probabilities. So the ripple bias for this system is: (2/3) / (1/2 + 1/2) = 2/3.
The Java programs were taken randomly from github, though certain criteria had to be met. The programs had to be nontrivial (with more than 1000 methods) and had to have enough commits for the program to have evolved at least 1000 method changes. The programs also had to be easy to compile: if it didn't compile with ant, maven or gradle, it was dismissed with unimaginable revulsion.
Spoklin Soice analyzed the programs and produced raw data which was then fed into a grotesque parser poorly written by the author to calculate the ripple bias.
Program  #Revs  #Changes  #LOC  CDR  Child corr.  Ante. corr.  Ripple bias 
ant  1504  1975  4812610  1.85  0.41  0.05  1.36 
atmosphere  1149  3834  4679350  1.36  0.52  0.06  1.12 
bitcoinj  596  1652  3547778  1.92  0.36  0.03  0.97 
commafeed  1294  1933  604825  2.81  0.33  0.07  1.21 
gitblit  1890  2906  10779729  4.63  0.44  0.19  2.08 
jackson  1598  4104  4985775  2.77  0.35  0.03  1.1 
javadvr  353  5695  613573  1.24  0.04  0  1.3 
jedis  1222  7371  1331930  1.4  0.17  0.18  1.95 
jsoup  499  3445  628246  0.76  0.06  0.06  1.32 
mapdb  1946  8441  4506846  2  0.3  0.04  1.37 
mina  780  1533  2075634  1.21  0.32  0.03  1.47 
mockito  1432  1874  768854  1.52  0.18  0.02  1.52 
nutch  468  1152  1126970  1.01  0.26  0.01  0.93 
OpenGrok  634  2515  3086448  2.46  0.31  0.05  1.75 
RxJava  1357  9465  7009369  2.82  0.08  0.07  1.65 
scouter  1543  1076  4436123  1.48  0.19  0.13  1.05 
sonatype  1028  2128  1543476  1  0.4  0.08  1.08 
swagger  1181  4143  2816018  0.7  0.2  0.04  0.98 
traccar  651  2652  1369662  3.48  0.51  0.53  3.3 
traccar  1550  3201  3686489  1.98  0.36  0.14  2.58 
Total  22675  71095  64409705  38.38  5.67  0.15  30.09 
Average  1133.75  3554.75  3220485.25  1.92  0.28  0.01  1.5 
Table 1: Data over all revisions.
In the table above, the columns are as follows:
To keep analysis times reasonable (processing a program over its lifetime can easily take 24 hours), programs were not analyzed in their entirety: usually only part of the program was analyzed (so long as the part had > 1000 methods). Also, as bytecode was analyzed, the analysis divided program histories into series compiled with the same version of Java, so as to avoid falsepositive changes stemming from merely moving to a newer JVM at some point in the program's lifetime. Traccar appears twice as it happens that two ranges of its consecutive updates, each on a different Java version, met the criteria (>1000 method changes) to earn it double candidacy.
This is probably a lower bound.
If we have two methods, a() and b(), where a() depends solely on b() and b() is dependedon solely by a(), then a change analysis may identify that both methods change in a particular revision, but no algorithm can decide whether the change was made to a() and then rippled down to b(), or the change was made to b() and rippled up to a(). It is entirely symmetrical. The only way to answer this would be to ask the original programmer, and ... just no.
Ripple bias can only expose itself where a() has multiple children or antecedents.
Yet there is little reason to suppose that ripple effects behave differently in singledependency cases than multiple. Given that the ripple bias is clearly nonunity, then perhaps interviews with all those programmers would also reveal that ripple effects go from dependedon to dependedfrom in singledependency cases and that the ripple bias is actually higher than we can determine with algorithm alone.
Of course, this post is just an idea and threats to validity are legion.
One particular difficulty lies in how this analysis identifies change: by measuring bycode. Abstract and interface methods have no bytecode, so this analysis detect changes only in concrete methods.
A common way that an interface method, say, might change is that a new argument is added to its method signature, so a(String) might change to a(String, int). It is, however, impossible for an algorithm to distinguish such a change from the introduction of a new method that just happens to have the same name but a different argument list.
We could simply make that assumption: that all (unique) methods distinguished by classname and methodname are the same method across revisions if differing only by argument list, and indeed such an attempt was made in the early life of the parser used, but it felt a little ... uncertain.
Perhaps capturing interface changes deserves more attention. Again, however, there is little reason to presume that ripple effects behave different for interface methods than concrete, so including interface changes may increase ripple bias further.
An on unrelated point, it's not even certain that expressing the ripple bias as a ratio is a better description of events than, say, expressing it as the subtraction: P(δ(m)  δ(C_{m}))  P(δ(m)  δ(A_{m})). Some configurations of changes can occur where small numbers of antecedent changes can flatter the ripple bias as the antecedent changes appear in the denominator; these would surely not be present in the subtractive form. More analysis is required, though note that, whatever proves to be the best way to measure ripple effects, data show that dependent methods change almost twice as often as independent methods and this motivates the structural imperative of the post as much as any theoretical framework.
Just for information, if we drop the requirement for analyzed programs to generate 1000 changed methods and allow series with merely 200 changed methods, then we get the table below, with the average ripple bias falling to 1.35, though the CDR stays relatively unchanged at 1.93.
Program  #Revs  #Changes  #LOC  CDR  Child corr.  Ante. corr.  Ripple bias 
Aeron  285  379  373366  1.19  0.22  0.14  0.77 
ant  1504  1975  4812610  1.85  0.41  0.05  1.36 
atmosphere  1149  3834  4679350  1.36  0.52  0.06  1.12 
bitcoinj  596  1652  3547778  1.92  0.36  0.03  0.97 
commafeed  1294  1933  604825  2.81  0.33  0.07  1.21 
commons  261  480  780177  0.49  0.37  0  0.99 
commons  403  266  1219548  0.77  0.14  0.2  1.09 
gitblit  1890  2906  10779729  4.63  0.44  0.19  2.08 
jackson  1598  4104  4985775  2.77  0.35  0.03  1.1 
java  353  5695  613573  1.24  0.04  0  1.3 
jedis  1222  7371  1331930  1.4  0.17  0.18  1.95 
jsoup  499  3445  628246  0.76  0.06  0.06  1.32 
logstash  269  223  228332  4.7  0.35  0.24  1.34 
mapdb  1946  8441  4506846  2  0.3  0.04  1.37 
mina  780  1533  2075634  1.21  0.32  0.03  1.47 
mockito  1432  1874  768854  1.52  0.18  0.02  1.52 
nutch  300  537  532338  2.25  0.31  0.03  0.8 
nutch  468  1152  1126970  1.01  0.26  0.01  0.93 
nutch  542  713  1170171  1.05  0.31  0.01  0.9 
OpenGrok  577  239  2299176  3.85  0.16  0.58  0.9 
OpenGrok  634  2515  3086448  2.46  0.31  0.05  1.75 
RxJava  1357  9465  7009369  2.82  0.08  0.07  1.65 
scouter  1543  1076  4436123  1.48  0.19  0.13  1.05 
sonatype  1028  2128  1543476  1  0.4  0.08  1.08 
spring  412  226  1556514  1.41  0.11  0.09  0.92 
swagger  1181  4143  2816018  0.7  0.2  0.04  0.98 
traccar  651  2652  1369662  3.48  0.51  0.53  3.3 
traccar  1550  3201  3686489  1.98  0.36  0.14  2.58 
Total  25724  74158  72569327  54.07  7.36  0.22  37.79 
Average  918.71  2648.5  2591761.68  1.93  0.26  0.01  1.35 