Changeset 5648 for branches/QAP/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/MultidimensionalScaling.cs
- Timestamp:
- 03/10/11 01:49:10 (13 years ago)
- Location:
- branches/QAP
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/QAP
- Property svn:ignore
-
old new 1 1 *.suo 2 TestResults
-
- Property svn:ignore
-
branches/QAP/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/MultidimensionalScaling.cs
r5641 r5648 23 23 using HeuristicLab.Data; 24 24 25 namespace HeuristicLab.Problems.QuadraticAssignment {25 namespace HeuristicLab.Problems.QuadraticAssignment.Views { 26 26 public static class MultidimensionalScaling { 27 28 public static DoubleMatrix Classic(DoubleMatrix distances, out double error) {29 if (distances == null) throw new ArgumentNullException("distances");30 if (distances.Rows != distances.Columns) throw new ArgumentException("Distance matrix must be a square matrix.", "distances");31 error = 0.0;32 33 int dimension = distances.Rows;34 if (dimension == 1) return new DoubleMatrix(new double[,] { { 0, 0 } });35 else if (dimension == 2) return new DoubleMatrix(new double[,] { { 0, distances[0, 1] } });36 37 double[,] A = new double[dimension + 1, dimension + 1];38 for (int i = 1; i < dimension; i++) {39 for (int j = i + 1; j < dimension + 1; j++) {40 A[i, j] = -0.5 * distances[i - 1, j - 1] * distances[i - 1, j - 1];41 A[j, i] = A[i, j];42 A[0, 0] += A[i, j] / (dimension * dimension);43 double avg = A[i, j] / (double)dimension;44 A[0, j] += avg;45 A[0, i] += avg;46 A[i, 0] += avg;47 A[j, 0] += avg;48 }49 }50 double[,] B = new double[dimension, dimension];51 for (int i = 0; i < dimension - 1; i++) {52 for (int j = i + 1; j < dimension; j++) {53 B[i, j] = A[i + 1, j + 1] - A[0, j + 1] - A[i + 1, 0] + A[0, 0];54 }55 }56 double[] eigenvalues;57 double[,] eigenvectors;58 alglib.smatrixevd(B, dimension, 1, true, out eigenvalues, out eigenvectors);59 60 DoubleMatrix coordinates = new DoubleMatrix(dimension, 2);61 for (int i = 0; i < dimension; i++) {62 for (int j = 0; j < dimension; j++) {63 coordinates[i, 0] += eigenvectors[eigenvectors.GetLength(0) - 1, j]64 * distances[i, j];65 coordinates[i, 1] += eigenvectors[eigenvectors.GetLength(0) - 2, j]66 * distances[i, j];67 }68 }69 70 return coordinates;71 }72 27 73 28 /// <summary> … … 77 32 /// </summary> 78 33 /// <param name="distances">A symmetric NxN matrix that specifies the distances between each element i and j. Diagonal elements are ignored.</param> 79 /// <param name=" error">Returns the errorbetween the fit distances and the actual distances.</param>34 /// <param name="stress">Returns the stress between the fit distances and the actual distances.</param> 80 35 /// <returns>A Nx2 matrix where the first column represents the x- and the second column the y coordinates.</returns> 81 public static DoubleMatrix Metric (DoubleMatrix distances, out double error) {36 public static DoubleMatrix MetricByDistance(DoubleMatrix distances, out double stress) { 82 37 if (distances == null) throw new ArgumentNullException("distances"); 83 38 if (distances.Rows != distances.Columns) throw new ArgumentException("Distance matrix must be a square matrix.", "distances"); 84 error= 0.0;39 stress = 0.0; 85 40 86 41 int dimension = distances.Rows; … … 94 49 coordinates[i, 1] = 10 * Math.Sin(rad * i); 95 50 } 96 double epsg = 0.0000000001; 51 52 double epsg = 1e-7; 97 53 double epsf = 0; 98 54 double epsx = 0; 99 int maxits = 1000;55 int maxits = 0; 100 56 alglib.mincgstate state = null; 101 57 alglib.mincgreport rep; 102 58 103 for (int iterations = 0; iterations < 200; iterations++) {59 for (int iterations = 0; iterations < 10; iterations++) { 104 60 for (int i = 0; i < dimension; i++) { 105 61 double[] c = new double[] { coordinates[i, 0], coordinates[i, 1] }; … … 111 67 alglib.mincgrestartfrom(state, c); 112 68 } 113 alglib.mincgoptimize(state, func, null, new Info(coordinates, distances, i));69 alglib.mincgoptimize(state, StressGradient, null, new Info(coordinates, distances, i)); 114 70 alglib.mincgresults(state, out c, out rep); 115 71 … … 118 74 } 119 75 } 120 error = 0; 76 stress = CalculateNormalizedStress(dimension, distances, coordinates); 77 return coordinates; 78 } 79 80 private static void StressGradient(double[] x, ref double func, double[] grad, object obj) { 81 func = 0; grad[0] = 0; grad[1] = 0; 82 Info info = (obj as Info); 83 for (int i = 0; i < info.Coordinates.Rows; i++) { 84 double c = info.Distances[info.Row, i]; 85 if (i != info.Row) { 86 double a = info.Coordinates[i, 0]; 87 double b = info.Coordinates[i, 1]; 88 func += Stress(x, c, a, b); 89 grad[0] += ((2 * x[0] - 2 * a) * Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a) - 2 * c * x[0] + 2 * a * c) / Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a); 90 grad[1] += ((2 * x[1] - 2 * b) * Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a) - 2 * c * x[1] + 2 * b * c) / Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a); 91 } 92 } 93 } 94 95 private static double Stress(double[] x, double distance, double xCoord, double yCoord) { 96 return Stress(x[0], x[1], distance, xCoord, yCoord); 97 } 98 99 private static double Stress(double x, double y, double distance, double otherX, double otherY) { 100 double d = Math.Sqrt((x - otherX) * (x - otherX) 101 + (y - otherY) * (y - otherY)); 102 return (d - distance) * (d - distance); 103 } 104 105 public static double CalculateNormalizedStress(int dimension, DoubleMatrix distances, DoubleMatrix coordinates) { 106 double stress = 0; 121 107 for (int i = 0; i < dimension - 1; i++) { 122 108 for (int j = i + 1; j < dimension; j++) { 123 109 if (distances[i, j] != 0) { 124 double dx = coordinates[i, 0] - coordinates[j, 0]; 125 double dy = coordinates[i, 1] - coordinates[j, 1]; 126 double d = Math.Sqrt(dx * dx + dy * dy); 127 error += ((distances[i, j] - d) * (distances[i, j] - d)) / (distances[i, j] * distances[i, j]); 110 stress += Stress(coordinates[i, 0], coordinates[i, 1], distances[i, j], coordinates[j, 0], coordinates[j, 1]) 111 / (distances[i, j] * distances[i, j]); 128 112 } 129 113 } 130 114 } 131 return coordinates; 132 } 133 134 public static void func(double[] x, ref double func, double[] grad, object obj) { 135 func = 0; grad[0] = 0; grad[1] = 0; 136 Info info = (obj as Info); 137 for (int i = 0; i < x.Length; i++) { 138 if (i != info.Row) { 139 double d = (x[0] - info.Coordinates[i, 0]) 140 * (x[0] - info.Coordinates[i, 0]) 141 + (x[1] - info.Coordinates[i, 1]) 142 * (x[1] - info.Coordinates[i, 1]); 143 func += (d - info.Distances[info.Row, i]) * (d - info.Distances[info.Row, i]); 144 grad[0] += 2 * x[0] - 2 * info.Coordinates[i, 0]; 145 grad[1] += 2 * x[1] - 2 * info.Coordinates[i, 1]; 146 } 147 } 115 return stress; 148 116 } 149 117
Note: See TracChangeset
for help on using the changeset viewer.