Please move this question to Code Review -area . This works better because I know that the code below is trash and I want to get critical feedback to complete the rewriting. I invent the wheel a lot.
[Update]
I will explain a little about theory here, perhaps the problem can be simplified in this way. The code above will try to build a chain of marks with a transition matrix A below. The corresponding pattern corresponds to 100 , which you can imagine as turning coins over.
>>> Q=numpy.matrix('0.5 0.5 0; 0 0.5 0.5; 0 0.5 0') >>> I=numpy.identity(3) >>> I array([[ 1., 0., 0.], [ 0., 1., 0.], [ 0., 0., 1.]]) >>> Q matrix([[ 0.5, 0.5, 0. ], [ 0. , 0.5, 0.5], [ 0. , 0.5, 0. ]]) >>> A=numpy.matrix('0.5 0.5 0 0; 0 0.5 0.5 0; 0 0.5 0 0.5; 0 0 0 1') >>> A matrix([[ 0.5, 0.5, 0. , 0. ], [ 0. , 0.5, 0.5, 0. ], [ 0. , 0.5, 0. , 0.5], [ 0. , 0. , 0. , 1. ]])
average 8 in the question becomes the sum of the values ββin the first row in the matrix N=(IQ)^-1 , where Q higher.
>>> (IQ)**-1 matrix([[ 2., 4., 2.], [ 0., 4., 2.], [ 0., 2., 2.]]) >>> numpy.sum(((IQ)**-1)[0]) 8.0
Now you will probably see that this problem with only a matching pattern visible becomes a chain of marks. I see no reason why you could not replace the messy conditions for-in-case with something similar to matrices or matrices. I donβt know how to implement them, but iterators may be able to go exploring, especially with a lot of states where you need to decompose.
But there was a problem with Numpy, what are -Inf and NaN things -Inf ? Check the values ββwith which they should converge from (IQ)**-1 . N is N=I+Q+Q^2+Q^3+...=\frac{IQ^{n}}{IQ} .
>>> (IQ**99)/(IQ) matrix([[ 2.00000000e+00, 1.80853571e-09, -Inf], [ NaN, 2.00000000e+00, 6.90799171e-10], [ NaN, 6.90799171e-10, 1.00000000e+00]]) >>> (IQ**10)/(IQ) matrix([[ 1.99804688, 0.27929688, -Inf], [ NaN, 1.82617188, 0.10742188], [ NaN, 0.10742188, 0.96679688]])