Exemplo n.º 1
0
        public DiscreteTimeMarkovChain(ModelCapacity modelCapacity)
        {
            var modelSize = modelCapacity.DeriveModelByteSize(_sizeOfState, _sizeOfTransition);

            StateLabeling     = new LabelVector();
            ProbabilityMatrix = new SparseDoubleMatrix(modelSize.NumberOfStates + 1, modelSize.NumberOfTransitions);             // one additional row for row of initial distribution
        }
Exemplo n.º 2
0
 public SparseJacobianEvaluator(int N, Action <double, double[], double[]> f)
 {
     variatedX = new double[N];
     f_old     = new double[N];
     f_new     = new double[N];
     J         = new SparseDoubleMatrix(N, N);
     this.f    = f;
 }
        public MarkovDecisionProcess(ModelCapacity modelCapacity)
        {
            var modelSize = modelCapacity.DeriveModelByteSize(_sizeOfState, _sizeOfTransition);

            StateLabeling = new LabelVector();
            var numbersOfTransitionsPerState   = ((double)modelSize.NumberOfTransitions) / modelSize.NumberOfStates;
            var numbersOfDistributionsPerState = (long)Math.Ceiling(Math.Sqrt(numbersOfTransitionsPerState));
            var numberOfDistributions          = modelSize.NumberOfStates * numbersOfDistributionsPerState;

            RowsWithDistributions = new SparseDoubleMatrix(numberOfDistributions, modelSize.NumberOfTransitions); // need for every distribution one row
            StateToRowsL          = new int[modelSize.NumberOfStates + 1];                                        // one additional row for initial distributions
            StateToRowsRowCount   = new int[modelSize.NumberOfStates + 1];                                        // one additional row for initial distributions
            SetRowOfStateEntriesToInvalid();
        }
Exemplo n.º 4
0
        private SparseDoubleMatrix CreateDerivedMatrix(Dictionary <long, bool> exactlyOneStates, Dictionary <long, bool> exactlyZeroStates)
        {
            //Derived matrix is 0-based. Row i is equivalent to the probability distribution of state i (this is not the case for the Markov Chain).

            var derivedMatrix = new SparseDoubleMatrix(MarkovChain.States, MarkovChain.Transitions + MarkovChain.States);            //Transitions+States is a upper limit

            var enumerator = MarkovChain.GetEnumerator();

            for (var sourceState = 0; sourceState < MarkovChain.States; sourceState++)
            {
                enumerator.SelectSourceState(sourceState);
                derivedMatrix.SetRow(sourceState);
                if (exactlyOneStates.ContainsKey(sourceState) || exactlyZeroStates.ContainsKey(sourceState))
                {
                    // only add a self reference entry
                    derivedMatrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(sourceState, 1.0));
                }
                else
                {
                    // if state is neither exactlyOneStates nor exactlyZeroStates, it is a toCalculateState
                    var selfReferenceAdded = false;
                    while (enumerator.MoveNextTransition())
                    {
                        var columnValueEntry = enumerator.CurrentTransition;
                        var targetState      = columnValueEntry.Column;
                        if (targetState == sourceState)
                        {
                            //this implements the removal of the identity matrix
                            derivedMatrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(sourceState, columnValueEntry.Value - 1.0));
                            selfReferenceAdded = true;
                        }
                        else
                        {
                            derivedMatrix.AddColumnValueToCurrentRow(columnValueEntry);
                        }
                    }
                    if (!selfReferenceAdded)
                    {
                        //this implements the removal of the identity matrix (if not already done)
                        derivedMatrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(sourceState, -1.0));
                    }
                }
                derivedMatrix.FinishRow();
            }
            return(derivedMatrix);
        }
Exemplo n.º 5
0
 private void CreateExemplaryMatrix()
 {
     //_matrix = new SparseDoubleMatrix(6, 20);
     _matrix = new SparseDoubleMatrix(1024, 1024);
     _matrix.SetRow(0);
     _matrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(0, 1.0));
     _matrix.FinishRow();
     _matrix.SetRow(1);
     _matrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(1, 2.0));
     _matrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(2, 3.0));
     _matrix.FinishRow();
     _matrix.SetRow(2);
     _matrix.FinishRow();
     _matrix.SetRow(3);
     _matrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(0, 4.0));
     _matrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(4, 5.0));
     _matrix.FinishRow();
     _matrix.SetRow(4);
     _matrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(4, 6.0));
     _matrix.AddColumnValueToCurrentRow(new SparseDoubleMatrix.ColumnValue(3, 7.0));
     _matrix.FinishRow();
 }
Exemplo n.º 6
0
        private double[] GaussSeidel(SparseDoubleMatrix derivedMatrix, double[] derivedVector, int iterationsLeft)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            var stateCount      = MarkovChain.States;
            var resultVector    = new double[stateCount];
            var fixPointReached = iterationsLeft <= 0;
            var iterations      = 0;

            //Derived matrix is 0-based. Row i is equivalent to the probability distribution of state i (this is not the case for the Markov Chain).
            var enumerator = derivedMatrix.GetEnumerator();

            for (var i = 0; i < stateCount; i++)
            {
                resultVector[i] = 0.0;
            }
            while (!fixPointReached)
            {
                for (var i = 0; i < stateCount; i++)
                {
                    var reflexiveEntry = 0.0;
                    var temporaryValue = derivedVector[i];

                    enumerator.MoveRow(i);
                    while (enumerator.MoveNextColumn())
                    {
                        var currentEntry = enumerator.CurrentColumnValue.Value;
                        if (currentEntry.Column == i)
                        {
                            reflexiveEntry = currentEntry.Value;
                        }
                        else
                        {
                            temporaryValue -= currentEntry.Value * resultVector[currentEntry.Column];
                        }
                    }
                    Assert.That(reflexiveEntry != 0.0, "entry must not be 0.0");

                    resultVector[i] = temporaryValue / reflexiveEntry;
                }

                iterationsLeft--;
                iterations++;
                if (iterations % 10 == 0)
                {
                    stopwatch.Stop();
                    var currentProbability = CalculateFinalProbability(resultVector);
                    _output?.WriteLine($"Completed {iterations} Gauss-Seidel iterations in {stopwatch.Elapsed}.  Current probability={currentProbability.ToString(CultureInfo.InvariantCulture)}");
                    stopwatch.Start();
                }
                if (iterationsLeft <= 0)
                {
                    fixPointReached = true;
                }
            }
            stopwatch.Stop();

            return(resultVector);
        }
Exemplo n.º 7
0
            /// <summary>
            /// Execute predictor-corrector scheme for Nordsieck's method
            /// </summary>
            /// <param name="flag"></param>
            /// <param name="f">Evaluation of the deriatives. First argument is time, second arg are the state variables, and 3rd arg is the array to accomodate the derivatives.</param>
            /// <param name="denseJacobianEvaluation">Evaluation of the jacobian.</param>
            /// <param name="sparseJacobianEvaluation">Evaluation of the jacobian as a sparse matrix. Either this or the previous arg must be valid.</param>
            /// <param name="opts">current options</param>
            /// <returns>en - current error vector</returns>
            internal void PredictorCorrectorScheme(
                ref bool flag,
                Action <double, double[], double[]> f,
                Func <double, double[], IROMatrix <double> > denseJacobianEvaluation,
                Func <double, double[], SparseDoubleMatrix> sparseJacobianEvaluation,
                GearsBDFOptions opts
                )
            {
                NordsieckState currstate = this;
                NordsieckState newstate  = this;
                int            n         = currstate._xn.Length;

                VectorMath.Copy(currstate._en, ecurr);
                VectorMath.Copy(currstate._xn, xcurr);
                var x0 = currstate._xn;

                MatrixMath.Copy(currstate._zn, zcurr); // zcurr now is old nordsieck matrix
                var qcurr = currstate._qn;             // current degree
                var qmax  = currstate._qmax;           // max degree
                var dt    = currstate._dt;
                var t     = currstate._tn;

                MatrixMath.Copy(currstate._zn, z0); // save Nordsieck matrix

                //Tolerance computation factors
                double Cq  = Math.Pow(qcurr + 1, -1.0);
                double tau = 1.0 / (Cq * Factorial(qcurr) * l[qcurr - 1][qcurr]);

                int count = 0;

                double Dq = 0.0, DqUp = 0.0, DqDown = 0.0;
                double delta = 0.0;

                //Scaling factors for the step size changing
                //with new method order q' = q, q + 1, q - 1, respectively
                double rSame, rUp, rDown;

                if (null != denseJacobianEvaluation)
                {
                    var J = denseJacobianEvaluation(t + dt, xcurr);
                    if (J.GetType() != P?.GetType())
                    {
                        AllocatePMatrixForJacobian(J);
                    }

                    do
                    {
                        MatrixMath.MapIndexed(J, dt * b[qcurr - 1], (i, j, aij, factor) => (i == j ? 1 : 0) - aij * factor, P, Zeros.AllowSkip); // P = Identity - J*dt*b[qcurr-1]
                        VectorMath.Copy(xcurr, xprev);
                        f(t + dt, xcurr, ftdt);
                        MatrixMath.CopyColumn(z0, 1, colExtract);                                                       // 1st derivative/dt
                        VectorMath.Map(ftdt, colExtract, ecurr, dt, (ff, c, e, local_dt) => local_dt * ff - c - e, gm); // gm = dt * f(t + dt, xcurr) - z0.GetColumn(1) - ecurr;
                        gaussSolver.SolveDestructive(P, gm, tmpVec1);
                        VectorMath.Add(ecurr, tmpVec1, ecurr);                                                          //	ecurr = ecurr + P.SolveGE(gm);
                        VectorMath.Map(x0, ecurr, b[qcurr - 1], (x, e, local_b) => x + e * local_b, xcurr);             //	xcurr = x0 + b[qcurr - 1] * ecurr;

                        //Row dimension is smaller than zcurr has
                        int M_Rows    = ecurr.Length;
                        int M_Columns = l[qcurr - 1].Length;
                        //So, "expand" the matrix
                        MatrixMath.MapIndexed(z0, (i, j, z) => z + (i < M_Rows && j < M_Columns ? ecurr[i] * l[qcurr - 1][j] : 0.0d), zcurr);

                        Dq = ToleranceNorm(ecurr, opts.RelativeTolerance, opts.AbsoluteTolerance, xprev);
                        var factor_deltaE = (1.0 / (qcurr + 2) * l[qcurr - 1][qcurr - 1]);
                        VectorMath.Map(ecurr, currstate._en, factor_deltaE, (e, c, factor) => (e - c) * factor, deltaE); // deltaE = (ecurr - currstate.en)*(1.0 / (qcurr + 2) * l[qcurr - 1][qcurr - 1])

                        DqUp = ToleranceNorm(deltaE, opts.RelativeTolerance, opts.AbsoluteTolerance, xcurr);
                        zcurr.CopyColumn(qcurr - 1, colExtract);
                        DqDown = ToleranceNorm(colExtract, opts.RelativeTolerance, opts.AbsoluteTolerance, xcurr);
                        delta  = Dq / (tau / (2 * (qcurr + 2)));
                        count++;
                    } while (delta > 1.0d && count < opts.NumberOfIterations);
                }
                else if (null != sparseJacobianEvaluation)
                {
                    SparseDoubleMatrix J = sparseJacobianEvaluation(t + dt, xcurr);
                    var P = new SparseDoubleMatrix(J.RowCount, J.ColumnCount);

                    do
                    {
                        J.MapSparseIncludingDiagonal((x, i, j) => (i == j ? 1 : 0) - x * dt * b[qcurr - 1], P);
                        VectorMath.Copy(xcurr, xprev);
                        f(t + dt, xcurr, ftdt);
                        MatrixMath.CopyColumn(z0, 1, colExtract);
                        VectorMath.Map(ftdt, colExtract, ecurr, (ff, c, e) => dt * ff - c - e, gm); // gm = dt * f(t + dt, xcurr) - z0.GetColumn(1) - ecurr;
                        gaussSolver.SolveDestructive(P, gm, tmpVec1);
                        VectorMath.Add(ecurr, tmpVec1, ecurr);                                      //	ecurr = ecurr + P.SolveGE(gm);
                        VectorMath.Map(x0, ecurr, (x, e) => x + e * b[qcurr - 1], xcurr);           // xcurr = x0 + b[qcurr - 1] * ecurr;

                        //Row dimension is smaller than zcurr has
                        int M_Rows    = ecurr.Length;
                        int M_Columns = l[qcurr - 1].Length;
                        //So, "expand" the matrix
                        MatrixMath.MapIndexed(z0, (i, j, z) => z + (i < M_Rows && j < M_Columns ? ecurr[i] * l[qcurr - 1][j] : 0.0d), zcurr);

                        Dq = ToleranceNorm(ecurr, opts.RelativeTolerance, opts.AbsoluteTolerance, xprev);
                        var factor_deltaE = (1.0 / (qcurr + 2) * l[qcurr - 1][qcurr - 1]);
                        VectorMath.Map(ecurr, currstate._en, (e, c) => (e - c) * factor_deltaE, deltaE); // deltaE = (ecurr - currstate.en)*(1.0 / (qcurr + 2) * l[qcurr - 1][qcurr - 1])

                        DqUp   = ToleranceNorm(deltaE, opts.RelativeTolerance, opts.AbsoluteTolerance, xcurr);
                        DqDown = ToleranceNorm(zcurr.GetColumn(qcurr - 1), opts.RelativeTolerance, opts.AbsoluteTolerance, xcurr);
                        delta  = Dq / (tau / (2 * (qcurr + 2)));
                        count++;
                    } while (delta > 1.0d && count < opts.NumberOfIterations);
                }
                else // neither denseJacobianEvaluation nor sparseJacobianEvaluation valid
                {
                    throw new ArgumentNullException(nameof(denseJacobianEvaluation), "Either denseJacobianEvaluation or sparseJacobianEvaluation must be set!");
                }

                //======================================

                var nsuccess = count < opts.NumberOfIterations ? currstate._nsuccess + 1 : 0;

                if (count < opts.NumberOfIterations)
                {
                    flag = false;
                    MatrixMath.Copy(zcurr, newstate._zn);
                    zcurr.CopyColumn(0, newstate._xn);
                    VectorMath.Copy(ecurr, newstate._en);
                }
                else
                {
                    flag = true;
                    // MatrixMath.Copy(currstate.zn, newstate.zn); // null operation since currstate and newstate are identical
                    currstate._zn.CopyColumn(0, newstate._xn);
                    VectorMath.Copy(currstate._en, newstate._en); // null operation since currstate and newstate are identical
                }

                //Compute step size scaling factors
                rUp = 0.0;

                if (currstate._qn < currstate._qmax)
                {
                    rUp = rUp = 1.0 / 1.4 / (Math.Pow(DqUp, 1.0 / (qcurr + 2)) + 1e-6);
                }

                rSame = 1.0 / 1.2 / (Math.Pow(Dq, 1.0 / (qcurr + 1)) + 1e-6);

                rDown = 0.0;

                if (currstate._qn > 1)
                {
                    rDown = 1.0 / 1.3 / (Math.Pow(DqDown, 1.0 / (qcurr)) + 1e-6);
                }

                //======================================
                _nsuccess = nsuccess >= _qn ? 0 : nsuccess;
                //Step size scale operations

                if (rSame >= rUp)
                {
                    if (rSame <= rDown && nsuccess >= _qn && _qn > 1)
                    {
                        _qn = _qn - 1;
                        _Dq = DqDown;

                        for (int i = 0; i < n; i++)
                        {
                            for (int j = newstate._qn + 1; j < qmax + 1; j++)
                            {
                                _zn[i, j] = 0.0;
                            }
                        }
                        nsuccess = 0;
                        _rFactor = rDown;
                    }
                    else
                    {
                        // _qn = _qn;
                        _Dq      = Dq;
                        _rFactor = rSame;
                    }
                }
                else
                {
                    if (rUp >= rDown)
                    {
                        if (rUp >= rSame && nsuccess >= _qn && _qn < _qmax)
                        {
                            _qn      = _qn + 1;
                            _Dq      = DqUp;
                            _rFactor = rUp;
                            nsuccess = 0;
                        }
                        else
                        {
                            // _qn = _qn;
                            _Dq      = Dq;
                            _rFactor = rSame;
                        }
                    }
                    else
                    {
                        if (nsuccess >= _qn && _qn > 1)
                        {
                            _qn = _qn - 1;
                            _Dq = DqDown;

                            for (int i = 0; i < n; i++)
                            {
                                for (int j = newstate._qn + 1; j < qmax + 1; j++)
                                {
                                    _zn[i, j] = 0.0;
                                }
                            }
                            nsuccess = 0;
                            _rFactor = rDown;
                        }
                        else
                        {
                            // _qn = _qn;
                            _Dq      = Dq;
                            _rFactor = rSame;
                        }
                    }
                }

                _dt = dt;
                _tn = t;
            }