public void RectangularMatrixAccess() { // create a matrix via outer product ColumnVector cv = new ColumnVector(new double[] { 1, 2 }); RowVector rv = new RowVector(new double[] { 3, 4, 5 }); RectangularMatrix M = cv * rv; // check dimensions Assert.IsTrue(M.RowCount == cv.Dimension); Assert.IsTrue(M.ColumnCount == rv.Dimension); // check values for (int r = 0; r < M.RowCount; r++) { for (int c = 0; c < M.ColumnCount; c++) { Assert.IsTrue(M[r, c] == cv[r] * rv[c]); } } // extract a column ColumnVector mc = M.Column(1); Assert.IsTrue(mc.Dimension == M.RowCount); for (int i = 0; i < mc.Dimension; i++) { Assert.IsTrue(mc[i] == M[i, 1]); } // extract a row RowVector mr = M.Row(1); Assert.IsTrue(mr.Dimension == M.ColumnCount); for (int i = 0; i < mr.Dimension; i++) { Assert.IsTrue(mr[i] == M[1, i]); } // test clone RectangularMatrix MC = M.Copy(); Assert.IsTrue(MC.RowCount == M.RowCount); Assert.IsTrue(MC.ColumnCount == M.ColumnCount); // test equality of clone Assert.IsTrue(MC == M); Assert.IsFalse(MC != M); // test independence of clone MC[0, 0] += 1.0; Assert.IsFalse(MC == M); Assert.IsTrue(MC != M); }
/// <summary> /// Generates a resource consumption pattern matrix /// </summary> /// <param name="ip">The current InputParameters object</param> private RectangularMatrix GenResConsPat(InputParameters ip) { bool throwAway; int numThrows = 0; RectangularMatrix outputMatrix; do { throwAway = false; outputMatrix = new RectangularMatrix(ip.RCP, ip.CO); // Flowchart 5.1(a): Generate vector X RowVector X = GenRandNumbers.GenStdNormalVec(ip.CO); // The following code is used in both 5.1(b) and 5.1(c): RowVector[] Y = new RowVector[ip.RCP - 1]; RowVector[] Z = new RowVector[Y.Length]; for (int i = 0; i < Y.Length; ++i) { Y[i] = GenRandNumbers.GenStdNormalVec(ip.CO); } // Flowchart 5.1(b): Generate (DISP1 - 1) vectors Y // Then create Z vectors based on X and Y double COR1 = GenRandNumbers.GenUniformDbl(ip.COR1LB, ip.COR1UB); double sqrtConstant1 = Math.Sqrt(1 - COR1 * COR1); for (int i = 0; i < ip.DISP1 - 1; ++i) { Z[i] = (COR1 * X) + (sqrtConstant1 * Y[i]); } // Flowchart 5.1(c): Generate (RCP - DISP1) vectors Y // Then create the remaining Z vectors based on X and Y double COR2 = GenRandNumbers.GenUniformDbl(ip.COR2LB, ip.COR2UB); double sqrtConstant2 = Math.Sqrt(1 - COR2 * COR2); for (int i = ip.DISP1 - 1; i < Z.Length; ++i) { Z[i] = (COR2 * X) + (sqrtConstant2 * Y[i]); } // Flowchart 5.1(d): // Take the absolute values of X and the Z's and // scale both by 10.0. X = X.Map(x => 10.0 * Math.Abs(x)); for (int i = 0; i < Z.Length; ++i) { Z[i] = Z[i].Map(z => 10.0 * Math.Abs(z)); } // Round X and the Z's to integers X = X.Map(x => Math.Ceiling(x)); for (int i = 0; i < Z.Length; ++i) { Z[i] = Z[i].Map(z => Math.Ceiling(z)); } // Flowchart 5.1(e): // Now punch out values in the Z's at random to make // the matrix sparse for (int i = 0; i < Z.Length; ++i) { Z[i] = Z[i].Map(x => ((GenRandNumbers.GenUniformDbl() < D) ? x : 0.0)); } // Flowchart 5.1(f): // Copy X into first row of outputMatrix. outputMatrix.CopyRowInto(X, 0); // Copy the Z's into the remaining rows of outputMatrix. for (int i = 0; i < Z.Length; ++i) { outputMatrix.CopyRowInto(Z[i], i + 1); } // Ensure that the first row has no zeros // There is a very small probability of getting a zero with // the Ceiling function, but given that there are a finite // number of double-precision floating point numbers, it // is not impossible to get a 0.0. double[] firstRow = outputMatrix.Row(0).ToArray(); if (Array.Exists(firstRow, x => x == 0.0)) { throwAway = true; break; } // Ensure that each *row* has at least one non-zero entry for (int i = 0; i < outputMatrix.RowCount; ++i) { double[] nextRow = outputMatrix.Row(i).ToArray(); if (Array.TrueForAll(nextRow, x => x == 0.0)) { throwAway = true; break; } } // Ensure that each *column* has at least one non-zero entry // Technically, this check is redundant, as the first row, X, // is not supposed to have any zero entries. But just to be // on the safe side... for (int j = 0; j < outputMatrix.ColumnCount; ++j) { double[] nextCol = outputMatrix.Column(j).ToArray(); if (Array.TrueForAll(nextCol, x => x == 0.0)) { string s = "There is a column with all zeros. " + "That should not happen since the first row is " + "supposed to have no zeros."; throw new ApplicationException(s); } } if (throwAway) { ++numThrows; } } while (throwAway); Console.WriteLine("RES_CONS_PAT: {0} Throw aways\n", numThrows); return(outputMatrix); }
private void Solve(int iteration, ref CMAState cmaState, ref Solution solution, bool isOnce = false) { //ColumnVector xmean = new ColumnVector(parameters); double tolX = this.StandardDeviationToleranceMultiple * this.InitialVarianceEstimate; int stopeval = this.StopEvals; RectangularMatrix arx = new RectangularMatrix(cmaState.p.N, cmaState.p.Lambda); ColumnVector arfitness = new ColumnVector(cmaState.p.Lambda); bool isRestart = false; bool isGoodEnough = false; int counteval = 0; while (counteval < stopeval) { // Generate and evaluate lambda offspring for (int k = 0; k < cmaState.p.Lambda; k++) { double[] sample = cmaState.Sample(arx.Column(k)); for (int r = 0; r < cmaState.p.N; r++) { arx[r, k] = sample[r]; } arfitness[k] = this.ObjectiveFunction(arx.Column(k).ToArray(), this.UserData); counteval++; } // Sort by fitness and compute weighted mean into xmean // minimization int[] arindex; arfitness = Utilities.Sort(arfitness, out arindex); // one based index int mu = cmaState.p.Mu; cmaState.ReEstimate( (RectangularMatrix)Utilities.GetColumns(arx, arindex.Take(cmaState.p.Mu)), arfitness.First(), arfitness.SkipWhile((f, i) => i < (mu - 1)).First()); cmaState.UpdateEigenSystem(1, 0); if ((solution.StopReason == StopReason.NotSet) || (arfitness[0] < solution.MinimizedFitness)) { solution.StopReason = StopReason.Incomplete; solution.MinimizedFitness = arfitness[0]; solution.BestCMAState = cmaState; solution.BestNumEvals = counteval; solution.BestNumRestarts = iteration; solution.BestParameters = cmaState.mean.ToArray(); } if (arfitness[0] <= this.StopFitnessMinimization) { isGoodEnough = true; break; } if (IsRestart(ref solution, arfitness, tolX, cmaState)) { isRestart = true; break; } if (isOnce) { break; } } if ((isRestart) && (iteration > this.MaxRestarts)) { solution.StopReason = StopReason.MaxRestarts; } else if ((isRestart) && ((cmaState.p.Lambda * this.RestartPopulationMultiple) > MAX_POPULATIONSIZE)) { solution.StopReason = StopReason.MaxPopulation; } else if (isRestart) { solution.History = new Queue <double>(); solution.StopReason = StopReason.Restart; int previousLambda = cmaState.p.Lambda; cmaState = new CMAState(_initialCmaParams, new ColumnVector(this.InitialParameters), this.InitialVarianceEstimate); cmaState.p.UpdateLambda((int)(previousLambda * this.RestartPopulationMultiple)); } else if (isGoodEnough) { solution.StopReason = StopReason.GoodEnough; } else { solution.StopReason = StopReason.MaxIterations; } solution.LatestCMAState = cmaState; solution.LatestNumEvals = counteval; solution.LatestNumRestarts = iteration; solution.LatestParameters = cmaState.mean.ToArray(); }
/// <summary> /// /// </summary> /// <param name="pop"></param> /// <param name="muBest"></param> /// <param name="muWorst"></param> public void ReEstimate(RectangularMatrix pop, double muBest, double muWorst) { if (pop.ColumnCount != p.Mu) { throw new ApplicationException(""); } int n = p.N; fitnessHistory[gen % fitnessHistory.Count()] = muBest; // needed for divergence check ColumnVector oldmean = new ColumnVector(mean.Dimension); for (int i = 0; i < mean.Dimension; i++) { oldmean[i] = mean [i]; } double[] BDz = new double[n]; // valarray<double> /* calculate xmean and rgBDz~N(0,C) */ for (int i = 0; i < n; ++i) { mean[i] = 0.0; for (int j = 0; j < pop.ColumnCount; ++j) { mean[i] += p.Weights[j] * (pop.Column(j))[i]; } BDz[i] = Math.Sqrt(p.MuEff) * (mean[i] - oldmean[i]) / sigma; } ColumnVector tmp = new ColumnVector(n); // [vector<double>] /* calculate z := D^(-1) * B^(-1) * rgBDz into rgdTmp */ for (int i = 0; i < n; ++i) { double sum = 0.0; for (int j = 0; j < n; ++j) { sum += B[j, i] * BDz[j]; } tmp[i] = sum / d[i]; } /* cumulation for sigma (ps) using B*z */ for (int i = 0; i < n; ++i) { double sum = 0.0; for (int j = 0; j < n; ++j) { sum += B[i, j] * tmp[j]; } ps[i] = (1.0 - p.CCumSig) * ps[i] + Math.Sqrt(p.CCumSig * (2.0 - p.CCumSig)) * sum; } /* calculate norm(ps)^2 */ double psxps = ps.Sum(x => x * x); double chiN = Math.Sqrt((double)p.N) * (1.0 - 1.0 / (4.0 * p.N) + 1.0 / (21.0 * p.N * p.N)); /* cumulation for covariance matrix (pc) using B*D*z~N(0,C) */ bool isHsig = Math.Sqrt(psxps) / Math.Sqrt(1.0 - Math.Pow(1.0 - p.CCumSig, 2.0 * gen)) / chiN < 1.5 + 1.0 / (p.N - 0.5); double hsig = (isHsig) ? 1.0 : 0.0; //pc = (1.0 - p.ccumcov) * pc + hsig * Math.Sqrt(p.ccumcov * (2.0 - p.ccumcov)) * BDz; pc = pc.Select(x => x * (1.0 - p.CCumCov)).Zip(BDz.Select(x => x * Math.Sqrt(p.CCumCov * (2.0 - p.CCumCov)) * hsig), (lhs, rhs) => lhs + rhs).ToArray(); /* stop initial phase (MK, this was not reachable in the org code, deleted) */ /* remove momentum in ps, if ps is large and fitness is getting worse */ if (gen >= fitnessHistory.Count()) { // find direction from muBest and muWorst (muBest == muWorst handled seperately double direction = (muBest < muWorst) ? -1.0 : 1.0; int now = gen % fitnessHistory.Count(); int prev = (gen - 1) % fitnessHistory.Count(); int prevprev = (gen - 2) % fitnessHistory.Count(); bool fitnessWorsens = (muBest == muWorst) || // <- increase norm also when population has converged (this deviates from Hansen's scheme) ((direction * fitnessHistory[now] < direction * fitnessHistory[prev]) && (direction * fitnessHistory[now] < direction * fitnessHistory[prevprev])); if (psxps / p.N > 1.5 + 10.0 * Math.Sqrt(2.0 / p.N) && fitnessWorsens) { double tfac = Math.Sqrt((1 + Math.Max(0.0, Math.Log(psxps / p.N))) * p.N / psxps); ps = ps.Select(x => x * tfac).ToArray(); psxps *= tfac * tfac; } } /* update of C */ /* Adapt_C(t); not used anymore */ if (p.CCov != 0.0) { //flgEigensysIsUptodate = 0; /* update covariance matrix */ for (int i = 0; i < n; ++i) { for (int j = 0; j <= i; ++j) { C[i, j] = (1 - p.CCov) * C[i, j] + p.CCov * (1.0 / p.MuCov) * pc[i] * pc[j] + (1 - hsig) * p.CCumCov * (2.0 - p.CCumCov) * C[i, j]; /*C[i][j] = (1 - p.ccov) * C[i][j] + sp.ccov * (1./sp.mucov) * (rgpc[i] * rgpc[j] + (1-hsig)*sp.ccumcov*(2.-sp.ccumcov) * C[i][j]); */ for (int k = 0; k < p.Mu; ++k) { /* additional rank mu update */ C[i, j] += p.CCov * (1 - 1.0 / p.MuCov) * p.Weights[k] * ((pop.Column(k))[i] - oldmean[i]) * ((pop.Column(k))[j] - oldmean[j]) / sigma / sigma; // * (rgrgx[index[k]][i] - rgxold[i]) // * (rgrgx[index[k]][j] - rgxold[j]) // / sigma / sigma; } } } } /* update of sigma */ sigma *= Math.Exp(((Math.Sqrt(psxps) / chiN) - 1.0) / p.Damp); /* calculate eigensystem, must be done by caller */ //cmaes_UpdateEigensystem(0); /* treat minimal standard deviations and numeric problems * Note that in contrast with the original code, some numerical issues are treated *before* we * go into the eigenvalue calculation */ treatNumericalIssues(muBest, muWorst); gen++; // increase generation }