/// <summary>
        ///   Construct an eigenvalue decomposition.</summary>
        /// <param name="value">
        ///   The matrix to be decomposed.</param>
        /// <param name="assumeSymmetric">
        ///   Defines if the matrix should be assumed as being symmetric
        ///   regardless if it is or not. Default is <see langword="false"/>.</param>
        /// <param name="inPlace">
        ///   Pass <see langword="true"/> to perform the decomposition in place. The matrix
        ///   <paramref name="value"/> will be destroyed in the process, resulting in less
        ///   memory comsumption.</param>
        public EigenvalueDecomposition(Double[,] value, bool assumeSymmetric, bool inPlace)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value", "Matrix cannot be null.");
            }

            if (value.GetLength(0) != value.GetLength(1))
            {
                throw new ArgumentException("Matrix is not a square matrix.", "value");
            }

            n = value.GetLength(1);
            V = new Double[n, n];
            d = new Double[n];
            e = new Double[n];


            this.symmetric = assumeSymmetric;

            if (this.symmetric)
            {
                V = inPlace ? value : (Double[,])value.Clone();

                // Tridiagonalize.
                this.tred2();

                // Diagonalize.
                this.tql2();
            }
            else
            {
                H = inPlace ? value : (Double[,])value.Clone();

                ort = new Double[n];

                // Reduce to Hessenberg form.
                this.orthes();

                // Reduce Hessenberg to real Schur form.
                this.hqr2();
            }
        }
        /// <summary>
        ///   Construct an eigenvalue decomposition.</summary>
        ///
        /// <param name="value">
        ///   The matrix to be decomposed.</param>
        /// <param name="assumeSymmetric">
        ///   Defines if the matrix should be assumed as being symmetric
        ///   regardless if it is or not. Default is <see langword="false"/>.</param>
        /// <param name="inPlace">
        ///   Pass <see langword="true"/> to perform the decomposition in place. The matrix
        ///   <paramref name="value"/> will be destroyed in the process, resulting in less
        ///   memory comsumption.</param>
        /// <param name="sort">
        ///   Pass <see langword="true"/> to sort the eigenvalues and eigenvectors at the end
        ///   of the decomposition.</param>
        ///
        public EigenvalueDecomposition(Double[,] value, bool assumeSymmetric,
            bool inPlace = false, bool sort = false)
        {
            if (value == null)
                throw new ArgumentNullException("value", "Matrix cannot be null.");

            if (value.GetLength(0) != value.GetLength(1))
                throw new ArgumentException("Matrix is not a square matrix.", "value");

            n = value.GetLength(1);
            V = new Double[n, n];
            d = new Double[n];
            e = new Double[n];


            this.symmetric = assumeSymmetric;

            if (this.symmetric)
            {
                V = inPlace ? value : (Double[,])value.Clone();

                // Tridiagonalize.
                this.tred2();

                // Diagonalize.
                this.tql2();
            }
            else
            {
                H = inPlace ? value : (Double[,])value.Clone();

                ort = new Double[n];

                // Reduce to Hessenberg form.
                this.orthes();

                // Reduce Hessenberg to real Schur form.
                this.hqr2();
            }

            if (sort)
            {
                // Sort eigenvalues and vectors in descending order
                var idx = Vector.Range(n);
                Array.Sort(idx, (i, j) => 
                {
                    if (Math.Abs(d[i]) == Math.Abs(d[j]))
                        return -Math.Abs(e[i]).CompareTo(Math.Abs(e[j]));
                    return -Math.Abs(d[i]).CompareTo(Math.Abs(d[j]));
                });

                this.d = this.d.Get(idx);
                this.e = this.e.Get(idx);
                this.V = this.V.Get(null, idx);
            }
        }
        private Double[,] v; // right singular vectors

        #endregion Fields

        #region Constructors

        /// <summary>Constructs a new singular value decomposition.</summary>
        /// <param name="value">
        ///   The matrix to be decomposed.</param>
        public SingularValueDecomposition(Double[,] value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value", "Matrix cannot be null.");
            }

            //m should not less than n
            Double[,] a;
            m = value.GetLength(0); // rows
            n = value.GetLength(1); // cols

            if (m < n)
            {
                throw new System.Exception("rows should not less than cols in value matrix");
            }

            // Proceed anyway
            a = (Double[,])value.Clone();

            int nu = System.Math.Min(m, n);
            int ni = System.Math.Min(m + 1, n);
            s = new Double[ni];
            u = new Double[m, nu];
            v = new Double[n, n];
            Double[] e = new Double[n];
            Double[] work = new Double[m];

            // Will store ordered sequence of indices after sorting.
            si = new int[ni]; for (int i = 0; i < ni; i++) si[i] = i;

            // Reduce A to bidiagonal form, storing the diagonal elements in s and the super-diagonal elements in e.
            int nct = System.Math.Min(m - 1, n);
            int nrt = System.Math.Max(0, System.Math.Min(n - 2, m));
            for (int k = 0; k < System.Math.Max(nct, nrt); k++)
            {
                if (k < nct)
                {
                    // Compute the transformation for the k-th column and place the k-th diagonal in s[k].
                    // Compute 2-norm of k-th column without under/overflow.
                    s[k] = 0;
                    for (int i = k; i < m; i++)
                    {
                        s[k] = Hypotenuse(s[k], a[i, k]);
                    }

                    if (s[k] != 0)
                    {
                        if (a[k, k] < 0)
                            s[k] = -s[k];

                        for (int i = k; i < m; i++)
                            a[i, k] /= s[k];

                        a[k, k] += 1;
                    }

                    s[k] = -s[k];
                }

                for (int j = k + 1; j < n; j++)
                {
                    if ((k < nct) & (s[k] != 0))
                    {
                        // Apply the transformation.
                        Double t = 0;
                        for (int i = k; i < m; i++)
                        {
                            t += a[i, k] * a[i, j];
                        }

                        t = -t / a[k, k];

                        for (int i = k; i < m; i++)
                        {
                            a[i, j] += t * a[i, k];
                        }
                    }

                    // Place the k-th row of A into e for the subsequent calculation of the row transformation.
                    e[j] = a[k, j];
                }

                if (k < nct)
                {
                    // Place the transformation in U for subsequent back
                    // multiplication.
                    for (int i = k; i < m; i++)
                        u[i, k] = a[i, k];
                }

                if (k < nrt)
                {
                    // Compute the k-th row transformation and place the k-th super-diagonal in e[k].
                    // Compute 2-norm without under/overflow.
                    e[k] = 0;
                    for (int i = k + 1; i < n; i++)
                        e[k] = Hypotenuse(e[k], e[i]);

                    if (e[k] != 0)
                    {
                        if (e[k + 1] < 0)
                            e[k] = -e[k];

                        for (int i = k + 1; i < n; i++)
                            e[i] /= e[k];

                        e[k + 1] += 1;
                    }

                    e[k] = -e[k];
                    if ((k + 1 < m) & (e[k] != 0))
                    {
                        // Apply the transformation.
                        for (int i = k + 1; i < m; i++)
                            work[i] = 0;

                        int k1 = k + 1;
                        for (int i = k1; i < m; i++)
                        {
                            for (int j = k1; j < n; j++)
                            {
                                work[i] += e[j] * a[i, j];
                            }
                        }

                        for (int j = k1; j < n; j++)
                        {
                            Double t = -e[j] / e[k1];
                            for (int i = k1; i < m; i++)
                            {
                                a[i, j] += t * work[i];
                            }
                        }
                    }

                    // Place the transformation in V for subsequent back multiplication.
                    for (int i = k + 1; i < n; i++)
                        v[i, k] = e[i];
                }
            }

            // Set up the final bidiagonal matrix or order p.
            int p = System.Math.Min(n, m + 1);
            if (nct < n) s[nct] = a[nct, nct];
            if (m < p) s[p - 1] = 0;
            if (nrt + 1 < p) e[nrt] = a[nrt, p - 1];
            e[p - 1] = 0;

            //generate U.
            for (int j = nct; j < nu; j++)
            {
                for (int i = 0; i < m; i++)
                    u[i, j] = 0;
                u[j, j] = 1;
            }

            for (int k = nct - 1; k >= 0; k--)
            {
                if (s[k] != 0)
                {
                    for (int j = k + 1; j < nu; j++)
                    {
                        Double t = 0;
                        for (int i = k; i < m; i++)
                        {
                            t += u[i, k] * u[i, j];
                        }

                        t = -t / u[k, k];

                        for (int i = k; i < m; i++)
                        {
                            u[i, j] += t * u[i, k];
                        }
                    }

                    for (int i = k; i < m; i++)
                    {
                        u[i, k] = -1.0 * u[i, k];
                    }

                    u[k, k] = 1 + u[k, k];
                    for (int i = 0; i < k - 1; i++)
                        u[i, k] = 0;
                }
                else
                {
                    for (int i = 0; i < m; i++)
                        u[i, k] = 0;
                    u[k, k] = 1;
                }
            }

            //generate V.
            for (int k = n - 1; k >= 0; k--)
            {
                if ((k < nrt) & (e[k] != 0))
                {
                    // TODO: The following is a pseudo correction to make SVD
                    //  work on matrices with n > m (less rows than columns).

                    // For the proper correction, compute the decomposition of the
                    //  transpose of A and swap the left and right eigenvectors

                    // Original line:
                    //   for (int j = k + 1; j < nu; j++)
                    // Pseudo correction:
                    //   for (int j = k + 1; j < n; j++)

                    for (int j = k + 1; j < n; j++) // pseudo-correction
                    {
                        Double t = 0;
                        for (int i = k + 1; i < n; i++)
                        {
                            t += v[i, k] * v[i, j];
                        }

                        t = -t / v[k + 1, k];

                        for (int i = k + 1; i < n; i++)
                        {
                            v[i, j] += t * v[i, k];
                        }
                    }
                }

                for (int i = 0; i < n; i++)
                {
                    v[i, k] = 0;
                }
                v[k, k] = 1;
            }

            // Main iteration loop for the singular values.
            int pp = p - 1;
            int iter = 0;
            while (p > 0)
            {
                int k, kase;

                // Here is where a test for too many iterations would go.

                // This section of the program inspects for
                // negligible elements in the s and e arrays.  On
                // completion the variables kase and k are set as follows.

                // kase = 1     if s(p) and e[k-1] are negligible and k<p
                // kase = 2     if s(k) is negligible and k<p
                // kase = 3     if e[k-1] is negligible, k<p, and
                //              s(k), ..., s(p) are not negligible (qr step).
                // kase = 4     if e(p-1) is negligible (convergence).

                for (k = p - 2; k >= -1; k--)
                {
                    if (k == -1)
                        break;

                    if (System.Math.Abs(e[k]) <=
                       tiny + eps * (System.Math.Abs(s[k]) + System.Math.Abs(s[k + 1])))
                    {
                        e[k] = 0;
                        break;
                    }
                }

                if (k == p - 2)
                {
                    kase = 4;
                }
                else
                {
                    int ks;
                    for (ks = p - 1; ks >= k; ks--)
                    {
                        if (ks == k)
                            break;

                        Double t = (ks != p ? System.Math.Abs(e[ks]) : 0) +
                                   (ks != k + 1 ? System.Math.Abs(e[ks - 1]) : 0);
                        if (System.Math.Abs(s[ks]) <= tiny + eps * t)
                        {
                            s[ks] = 0;
                            break;
                        }
                    }

                    if (ks == k)
                        kase = 3;
                    else if (ks == p - 1)
                        kase = 1;
                    else
                    {
                        kase = 2;
                        k = ks;
                    }
                }

                k++;

                // Perform the task indicated by kase.
                switch (kase)
                {
                    // Deflate negligible s(p).
                    case 1:
                        {
                            Double f = e[p - 2];
                            e[p - 2] = 0;
                            for (int j = p - 2; j >= k; j--)
                            {
                                Double t = Hypotenuse(s[j], f);
                                Double cs = s[j] / t;
                                Double sn = f / t;
                                s[j] = t;
                                if (j != k)
                                {
                                    f = -sn * e[j - 1];
                                    e[j - 1] = cs * e[j - 1];
                                }

                                for (int i = 0; i < n; i++)
                                {
                                    t = cs * v[i, j] + sn * v[i, p - 1];
                                    v[i, p - 1] = -sn * v[i, j] + cs * v[i, p - 1];
                                    v[i, j] = t;
                                }
                            }
                        }
                        break;

                    // Split at negligible s(k).
                    case 2:
                        {
                            Double f = e[k - 1];
                            e[k - 1] = 0;
                            for (int j = k; j < p; j++)
                            {
                                Double t = Hypotenuse(s[j], f);
                                Double cs = s[j] / t;
                                Double sn = f / t;
                                s[j] = t;
                                f = -sn * e[j];
                                e[j] = cs * e[j];

                                for (int i = 0; i < m; i++)
                                {
                                    t = cs * u[i, j] + sn * u[i, k - 1];
                                    u[i, k - 1] = -sn * u[i, j] + cs * u[i, k - 1];
                                    u[i, j] = t;
                                }
                            }
                        }
                        break;

                    // Perform one qr step.
                    case 3:
                        {
                            // Calculate the shift.
                            Double scale = System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Abs(s[p - 1]), System.Math.Abs(s[p - 2])), System.Math.Abs(e[p - 2])), System.Math.Abs(s[k])), System.Math.Abs(e[k]));
                            Double sp = s[p - 1] / scale;
                            Double spm1 = s[p - 2] / scale;
                            Double epm1 = e[p - 2] / scale;
                            Double sk = s[k] / scale;
                            Double ek = e[k] / scale;
                            Double b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2;
                            Double c = (sp * epm1) * (sp * epm1);
                            double shift = 0;

                            if ((b != 0) | (c != 0))
                            {
                                if (b < 0)
                                    shift = -System.Math.Sqrt(b * b + c);
                                else
                                    shift = System.Math.Sqrt(b * b + c);

                                shift = c / (b + shift);
                            }

                            Double f = (sk + sp) * (sk - sp) + (Double)shift;
                            Double g = sk * ek;

                            // Chase zeros.
                            for (int j = k; j < p - 1; j++)
                            {
                                Double t = Hypotenuse(f, g);
                                Double cs = f / t;
                                Double sn = g / t;
                                if (j != k) e[j - 1] = t;
                                f = cs * s[j] + sn * e[j];
                                e[j] = cs * e[j] - sn * s[j];
                                g = sn * s[j + 1];
                                s[j + 1] = cs * s[j + 1];

                                for (int i = 0; i < n; i++)
                                {
                                    /*t = cs * v[i, j] + sn * v[i, j + 1];
                                    v[i, j + 1] = -sn * v[i, j] + cs * v[i, j + 1];
                                    v[i, j] = t;*/

                                    Double vij = v[i, j]; // *vj;
                                    Double vij1 = v[i, j + 1]; // *vj1;

                                    t = cs * vij + sn * vij1;
                                    v[i, j + 1] = -sn * vij + cs * vij1;
                                    v[i, j] = t;
                                }

                                t = Hypotenuse(f, g);
                                cs = f / t;
                                sn = g / t;
                                s[j] = t;
                                f = cs * e[j] + sn * s[j + 1];
                                s[j + 1] = -sn * e[j] + cs * s[j + 1];
                                g = sn * e[j + 1];
                                e[j + 1] = cs * e[j + 1];

                                if (j < m - 1)
                                {
                                    for (int i = 0; i < m; i++)
                                    {
                                        /* t = cs * u[i, j] + sn * u[i, j + 1];
                                         u[i, j + 1] = -sn * u[i, j] + cs * u[i, j + 1];
                                         u[i, j] = t;*/

                                        Double uij = u[i, j]; // *uj;
                                        Double uij1 = u[i, j + 1]; // *uj1;

                                        t = cs * uij + sn * uij1;

                                        u[i, j + 1] = -sn * uij + cs * uij1;
                                        u[i, j] = t;
                                    }
                                }

                            }

                            e[p - 2] = f;
                            iter = iter + 1;
                        }
                        break;

                    // Convergence.
                    case 4:
                        {
                            // Make the singular values positive.
                            if (s[k] <= 0)
                            {
                                s[k] = (s[k] < 0 ? -s[k] : 0);

                                for (int i = 0; i <= pp; i++)
                                    v[i, k] = -v[i, k];

                            }

                            // Order the singular values.
                            while (k < pp)
                            {
                                if (s[k] >= s[k + 1])
                                    break;

                                Double t = s[k];
                                s[k] = s[k + 1];
                                s[k + 1] = t;

                                int ti = si[k];
                                si[k] = si[k + 1];
                                si[k + 1] = ti;

                                if (k < n - 1)
                                {
                                    for (int i = 0; i < n; i++)
                                    {
                                        t = v[i, k + 1];
                                        v[i, k + 1] = v[i, k];
                                        v[i, k] = t;
                                    }
                                }

                                if (k < m - 1)
                                {
                                    for (int i = 0; i < m; i++)
                                    {
                                        t = u[i, k + 1];
                                        u[i, k + 1] = u[i, k];
                                        u[i, k] = t;
                                    }
                                }

                                k++;
                            }

                            iter = 0;
                            p--;
                        }
                        break;
                }
            }
        }
Пример #4
0
            public void AddResult(ResultData r)
            {
                Boolean match = false;
                int indx = -1;
                foreach (MainResults MaRe in results)
                {
                    //match = (MaRe.Latitude == r.Latitude && MaRe.Longitude == r.Longitude);
                    match = (MaRe.OrganizationLocationID == r.OrganizationLocationID);
                    if (match)
                    {
                        indx = results.IndexOf(MaRe);
                        break;
                    }
                }
                if (!match)
                {
                    MainResults mr = new MainResults();
                    mr.TaxID = new String[] { r.TaxID };
                    mr.NPI = new String[] { r.NPI };
                    mr.PracticeName = r.PracticeName;
                    mr.ProviderName = new String[] { r.ProviderName };
                    mr.PracticeRangeMin = String.Format("{0:c0}", decimal.Parse(r.RangeMin));
                    mr.RangeMin = new String[] { r.RangeMin };
                    mr.PracticeRangeMax = String.Format("{0:c0}", decimal.Parse(r.RangeMax));
                    mr.RangeMax = new String[] { r.RangeMax };
                    mr.PracticeYourCostMin = String.Format("{0:c0}", decimal.Parse(r.YourCostMin));
                    mr.YourCostMin = new String[] { r.YourCostMin };
                    mr.PracticeYourCostMax = String.Format("{0:c0}", decimal.Parse(r.YourCostMax));
                    mr.YourCostMax = new String[] { r.YourCostMax };
                    mr.Latitude = r.Latitude;
                    mr.Longitude = r.Longitude;
                    mr.OrganizationLocationID = r.OrganizationLocationID;
                    mr.LocationAddress1 = r.LocationAddress1;
                    mr.LocationCity = r.LocationCity;
                    mr.LocationState = r.LocationState;
                    mr.LocationZip = r.LocationZip;
                    mr.Distance = r.Distance;
                    mr.NumericDistance = r.NumericDistance;
                    mr.PracticeFairPrice = r.FairPrice;
                    mr.FairPrice = new Boolean[] { r.FairPrice };
                    mr.HGRecognized = new Int32[] { r.HGRecognized };
                    switch (r.HGRecognized)
                    {
                        case -1:
                            mr.PracticeHGRecognized = "N/A";
                            break;
                        case 0:
                            mr.PracticeHGRecognized = "0/1 Physicians";
                            break;
                        case 1:
                            mr.PracticeHGRecognized = "1/1 Physicians";
                            break;
                        default:
                            mr.PracticeHGRecognized = "N/A";
                            break;
                    }
                    mr.PracticeAvgRating = r.HGOverallRating;
                    mr.HGOverallRating = new Double[] { r.HGOverallRating };
                    mr.HGPatientCount = new int[] { r.HGPatientCount };
                    results.Add(mr);
                }
                else
                {
                    MainResults mr = results[indx];

                    String[] s = new String[mr.TaxID.Length + 1];
                    mr.TaxID.CopyTo(s, 0);
                    s[s.Length - 1] = r.TaxID;
                    mr.TaxID = (String[])s.Clone();
                    mr.NPI.CopyTo(s, 0);
                    s[s.Length - 1] = r.NPI;
                    mr.NPI = (String[])s.Clone();
                    mr.ProviderName.CopyTo(s, 0);
                    s[s.Length - 1] = r.ProviderName;
                    mr.ProviderName = (String[])s.Clone();

                    mr.RangeMin.CopyTo(s, 0);
                    s[s.Length - 1] = r.RangeMin;
                    mr.RangeMin = (String[])s.Clone();
                    mr.PracticeRangeMin = String.Format("{0:c0}", ((double.Parse(mr.PracticeRangeMin.Replace("$", "")) + double.Parse(r.RangeMin)) / 2.0));
                    mr.RangeMax.CopyTo(s, 0);
                    s[s.Length - 1] = r.RangeMax;
                    mr.RangeMax = (String[])s.Clone();
                    mr.PracticeRangeMax = String.Format("{0:c0}", ((double.Parse(mr.PracticeRangeMax.Replace("$", "")) + double.Parse(r.RangeMax)) / 2.0));

                    mr.YourCostMin.CopyTo(s, 0);
                    s[s.Length - 1] = r.YourCostMin;
                    mr.YourCostMin = (String[])s.Clone();
                    mr.PracticeYourCostMin = String.Format("{0:c0}", ((double.Parse(mr.PracticeYourCostMin.Replace("$", "")) + double.Parse(r.YourCostMin)) / 2.0));
                    mr.YourCostMax.CopyTo(s, 0);
                    s[s.Length - 1] = r.YourCostMax;
                    mr.YourCostMax = (String[])s.Clone();
                    mr.PracticeYourCostMax = String.Format("{0:c0}", ((double.Parse(mr.PracticeYourCostMax.Replace("$", "")) + double.Parse(r.YourCostMax)) / 2.0));

                    Boolean[] b = new Boolean[mr.FairPrice.Length + 1];
                    mr.FairPrice.CopyTo(b, 0);
                    b[b.Length - 1] = r.FairPrice;
                    mr.FairPrice = (Boolean[])b.Clone();
                    if (!mr.PracticeFairPrice && r.FairPrice) { mr.PracticeFairPrice = r.FairPrice; }

                    Int32[] i32 = new Int32[mr.HGRecognized.Length + 1];
                    mr.HGRecognized.CopyTo(i32, 0);
                    i32[i32.Length - 1] = r.HGRecognized;
                    mr.HGRecognized = (Int32[])i32.Clone();
                    switch (r.HGRecognized)
                    {
                        case -1:
                            //Do Nothing
                            break;
                        case 0:
                            if (mr.PracticeHGRecognized == "N/A") { mr.PracticeHGRecognized = "0/0 Physicians"; }
                            String[] str0 = mr.PracticeHGRecognized.Replace("Physicians", "").Trim().Split('/');
                            mr.PracticeHGRecognized = String.Format("{0}/{1} Physicians",
                                str0[0],
                                (Convert.ToInt32(str0[1]) + 1).ToString());
                            break;
                        case 1:
                            if (mr.PracticeHGRecognized == "N/A") { mr.PracticeHGRecognized = "0/0 Physicians"; }
                            String[] str1 = mr.PracticeHGRecognized.Replace("Physicians", "").Trim().Split('/');
                            mr.PracticeHGRecognized = String.Format("{0}/{1} Physicians",
                                (Convert.ToInt32(str1[0]) + 1).ToString(),
                                (Convert.ToInt32(str1[1]) + 1).ToString());
                            break;
                        default:
                            break;
                    }

                    Double[] d = new Double[mr.HGOverallRating.Length + 1];
                    mr.HGOverallRating.CopyTo(d, 0);
                    d[d.Length - 1] = r.HGOverallRating;
                    mr.HGOverallRating = (Double[])d.Clone();
                    mr.PracticeAvgRating = ((mr.PracticeAvgRating + r.HGOverallRating) / 2.0);

                    int[] i = new int[mr.HGPatientCount.Length + 1];
                    mr.HGPatientCount.CopyTo(i, 0);
                    i[i.Length - 1] = r.HGPatientCount;
                    mr.HGPatientCount = (int[])i.Clone();

                    results[indx] = mr;
                }
            }
Пример #5
0
 /// <summary>
 /// Konstruktor.
 /// </summary>
 /// <param name="costMatrix">Macierz kosztu przejścia.</param>
 public TSPFitness(Double[,] costMatrix)
 {
     this.costMatrix = (Double[,])costMatrix.Clone();
 }
        public void ServiceHost_ClientInputRecieved(object sender, ClientInputMessage e)
        {
            Trace.WriteLine("ClientInputRecieved Recieved User Id : " + e.idUsuario, "Warning");
            try
            {
                /*Crear Blob desde un Stream*/
                // Se obtiene la cuenta de almacenamiento
                storageAccount = CloudStorageAccount.Parse(
                    CloudConfigurationManager.GetSetting("StorageConnectionString"));

                // Se crea el cliente de blobs
                blobClient = storageAccount.CreateCloudBlobClient();

                // Obtencion del container
                container = blobClient.GetContainerReference(VariablesConfiguracion.containerName);

                Int64 subid = 1;

                String mustacheTemplateStr = File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "/App_Data/mustacheCloud.txt");

                //Template para generar los MDL
                FormatCompiler compiler = new FormatCompiler();
                Generator generatorMDL = compiler.Compile(mustacheTemplateStr);

                //Obtener parametros del cliente
                SimulacionParameters parametros = JsonConvert.DeserializeObject<SimulacionParameters>(e.message);

                //Barrido paramétrico
                //Especificar número de parámetros, n
                Int32 n = parametros.reacciones.Count(r => r.rate != null);
                if (n > 0)
                {
                    //Inicializo vector de inicios, fines y steps
                    LinkedList<Double> inicios = new LinkedList<Double>();
                    LinkedList<Double> fines = new LinkedList<Double>();
                    LinkedList<Double> steps = new LinkedList<Double>();
                    foreach (var reaccion in parametros.reacciones.FindAll(r => r.rate != null))
                    {
                        var inicio = reaccion.rate.rateInicio;
                        var fin = reaccion.rate.rateFin;
                        var step = reaccion.rate.rateStep;
                        inicios.AddLast(inicio);
                        fines.AddLast(fin);
                        steps.AddLast(step);
                    }

                    var iniciosArray = inicios.ToArray();
                    var finesArray = fines.ToArray();
                    var stepsArray = steps.ToArray();

                    //Defino vector lógico L para hacer barrido selectivo
                    Int32[] vectorLogico = new Int32[n];
                    for (int i = 0; i < n; i++)
                    {
                        //vectorLogico[i] = i < 5 ? 1 : 100;
                        vectorLogico[i] = 1000;
                    }

                    // Inicialización del vector j
                    Double[] j = new Double[n];
                    for (var k = 0; k < n; k++)
                    {
                        if (k == vectorLogico[k])
                        {
                            iniciosArray[k] += stepsArray[k];
                        }
                        j[k] = iniciosArray[k];
                    }

                    LinkedList<Double[]> jotas = new LinkedList<double[]>();
                    //Barrido parametrico
                    Int32 z = n - 1;
                    while (z >= 0)
                    {
                        if ((j[z] - finesArray[z]) * stepsArray[z] > 0)
                        {
                            j[z] = iniciosArray[z];
                            z--;
                        }
                        else
                        {
                            jotas.AddLast((double[])j.Clone()); //Para ver las combinaciones que creo
                            var auxId = subid;
                            Thread thread = new Thread(() => CrearMDL(e, auxId, (double[])j.Clone(), parametros, generatorMDL));
                            thread.Start();
                            //CrearMDL(e, subid, (double[])j.Clone(), parametros, generatorMDL);
                            z = n - 1;
                            subid++;
                        }
                        if (z >= 0)
                        {
                            j[z] += stepsArray[z];
                            if (z == vectorLogico[z])
                            {
                                j[z] += stepsArray[z];
                            }
                        }
                    }

                }
                else {
                    List<Double> valores = new List<double>();
                    CrearMDL(e, 0, valores.ToArray(), parametros, generatorMDL);
                }

            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.Message);
                throw;
            }
        }