cat_engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,65 @@
1
+ 
2
+ namespace CORE.Engines
3
+ {
4
+ using System;
5
+ using System.Xml;
6
+
7
+ public interface IEngine
8
+ {
9
+
10
+ XmlDocument getCurrentItem();
11
+ XmlDocument getPreviousItem();
12
+ XmlDocument getNextItem();
13
+ XmlDocument getForm();
14
+
15
+
16
+ void updateNode(XmlNode node);
17
+ bool loadItems(XmlDocument doc, XmlDocument FormParams, bool WithHeader);
18
+
19
+ void decrementPosition();
20
+ void incrementPosition();
21
+ void rollbackPosition();
22
+
23
+ bool finished
24
+ {
25
+ get;
26
+ }
27
+ bool IsCompleted
28
+ {
29
+ get;
30
+ }
31
+ bool IsResume
32
+ {
33
+ get;
34
+ }
35
+ int currentPosition
36
+ {
37
+ get;
38
+ set;
39
+ }
40
+ int previousPosition
41
+ {
42
+ get;
43
+ set;
44
+ }
45
+
46
+ int TotalItems
47
+ {
48
+ get;
49
+ }
50
+
51
+ string message
52
+ {
53
+ get;
54
+ set;
55
+ }
56
+
57
+ string paramPROC
58
+ {
59
+ get;
60
+ }
61
+
62
+
63
+ }
64
+
65
+ }
@@ -0,0 +1,44 @@
1
+ namespace CORE.Engines
2
+ {
3
+ using System;
4
+ using System.Xml;
5
+
6
+ public class ShellWrapper
7
+ {
8
+ static void Main(string[] args)
9
+ {
10
+ // get form id from command line args
11
+ string formID = args[0];
12
+
13
+ XmlDocument doc = new XmlDocument();
14
+ doc.Load("forms/" + formID + ".xml");
15
+
16
+ XmlDocument formParams = new XmlDocument();
17
+ formParams.Load("parameters/" + formID + ".xml");
18
+
19
+ CATEngine3 e = new CATEngine3();
20
+ e.loadItems(doc, formParams, true);
21
+
22
+ // get answers from command line args if they exist
23
+ string responseID = "";
24
+ for(int i = 1; i < args.Length; i++) {
25
+ responseID = args[i];
26
+ XmlDocument nextItem = e.getNextItem();
27
+ XmlElement item = (XmlElement)nextItem.GetElementsByTagName("Item")[0];
28
+ item.SetAttribute("ItemResponseOID", responseID);
29
+ // item.Attributes["Response"].Value = responseID;
30
+ // item.Attributes["ResponseTime"].Value = "10";
31
+ e.updateNode(item);
32
+ }
33
+
34
+ if(e.finished) {
35
+ double theta = e.ThetaHistory[e.ThetaHistory.Length - 1];
36
+ double stdError = e.StdErrorHistory[e.StdErrorHistory.Length - 1];
37
+ Console.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Results Theta=\"" + theta + "\" StdError=\"" + stdError + "\" />");
38
+
39
+ } else {
40
+ e.getCurrentItem().Save(Console.Out);
41
+ }
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,825 @@
1
+ namespace CORE.Engines
2
+ {
3
+ using System;
4
+ using System.Collections;
5
+ using System.Collections.Generic;
6
+ using System.IO;
7
+ using System.Linq;
8
+ using System.Text;
9
+
10
+
11
+ /// <summary>
12
+ /// A set of general utilities.
13
+ /// </summary>
14
+ public class Util
15
+ {
16
+ /// <summary>
17
+ /// Enumerator for the dimension type. These are dimension names for a matrix.
18
+ /// </summary>
19
+ public enum DimensionType
20
+ {
21
+ /// <summary>Dimension 0</summary>
22
+ Row,
23
+ /// <summary>Dimension 1</summary>
24
+ Column,
25
+ /// <summary>Dimension 2</summary>
26
+ Depth
27
+ };
28
+
29
+ /// <summary>
30
+ /// Reads a two-dimensional table of numbers from a text file.
31
+ /// </summary>
32
+ /// <param name="SourceFilename">The source filename.</param>
33
+ /// <param name="Delimiter">The delimiter separating the numeric values.</param>
34
+ /// <returns>A two-dimensional array of numbers (double data type).</returns>
35
+ /// <remarks>Assumes carriage return/line feed at the end of every row.
36
+ /// Assumes no delimiter at the end of every row.</remarks>
37
+ public static double[][] Read2DNumericTable(string SourceFilename, string Delimiter)
38
+ {
39
+ double[][] data;
40
+ FileInfo SourceFile;
41
+ StreamReader Reader;
42
+ ArrayList ar1d;
43
+ ArrayList ar2d;
44
+ int start;
45
+ int end;
46
+
47
+ ar2d = new ArrayList();
48
+ SourceFile = new FileInfo(SourceFilename);
49
+ Reader = SourceFile.OpenText();
50
+ string TextLine;
51
+ do {
52
+ TextLine = Reader.ReadLine();
53
+ if ( TextLine != null ) {
54
+ TextLine = TextLine.Trim();
55
+ ar1d = new ArrayList();
56
+ start = 0;
57
+ end = 0;
58
+ while ( end != -1 ) {
59
+ end = TextLine.IndexOf(Delimiter, start);
60
+ if ( start != end ) {
61
+ //if start == end then delimiter is the next character so skip it
62
+ if ( end == -1 && TextLine.Length != 0 ) {
63
+ //Last number in the line with no delimiter at the end
64
+ ar1d.Add(Convert.ToDouble(TextLine.Substring(start).Trim()));
65
+ }
66
+ else {
67
+ ar1d.Add(Convert.ToDouble(TextLine.Substring(start, (end - start)).Trim()));
68
+ }
69
+ }
70
+ start = end + 1;
71
+ }
72
+ ar2d.Add(ar1d.ToArray(typeof(double)));
73
+ }
74
+ } while ( TextLine != null );
75
+
76
+ data = (double[][])ar2d.ToArray(typeof(double[]));
77
+ Reader.Close();
78
+
79
+ return data;
80
+ }
81
+
82
+ /// <summary>
83
+ /// Reads a list of numbers from a text file
84
+ /// </summary>
85
+ /// <param name="SourceFilename">The source filename.</param>
86
+ /// <returns>An array of numbers (double data type)</returns>
87
+ /// <remarks>Assumes carriage return/line feed at the end of every line, with one number per line.
88
+ /// Lines that cannot be evaluated to valid numbers are skipped.</remarks>
89
+ public static double[] ReadNumericList(string SourceFilename)
90
+ {
91
+ double result;
92
+
93
+ List<double> liList = new List<double>();
94
+ FileInfo SourceFile = new FileInfo(SourceFilename);
95
+ StreamReader Reader = SourceFile.OpenText();
96
+ string TextLine;
97
+
98
+ do {
99
+ TextLine = Reader.ReadLine();
100
+ if (TextLine != null) {
101
+ TextLine = TextLine.Trim();
102
+ if (double.TryParse(TextLine, out result)) {
103
+ liList.Add(result);
104
+ }
105
+ }
106
+ } while (TextLine != null);
107
+
108
+ Reader.Close();
109
+
110
+ return liList.ToArray();
111
+ }
112
+
113
+
114
+ #region WriteNumericArrayToFile (overloaded)
115
+
116
+ /// <summary>
117
+ /// Writes a two-dimensional table of numbers to a text file.
118
+ /// </summary>
119
+ /// <param name="TargetFilename">The target filename.</param>
120
+ /// <param name="AppendToFile">If set to <c>true</c> append to the end of the file.</param>
121
+ /// <param name="Delimiter">The delimiter separating the numeric values.</param>
122
+ /// <param name="data">The data to be written.</param>
123
+ /// <remarks>Data is a 2D jagged array.</remarks>
124
+ public static void WriteNumericArrayToFile(string TargetFilename, bool AppendToFile, string Delimiter, double[][] data)
125
+ {
126
+ StreamWriter Writer;
127
+ int i;
128
+ int j;
129
+
130
+ Writer = new StreamWriter(TargetFilename, AppendToFile);
131
+ StringBuilder TextLine;
132
+ for ( i = 0; i < data.Length; i++ ) {
133
+ TextLine = new StringBuilder();
134
+ for ( j = 0; j < data[i].Length; j++ ) {
135
+ TextLine.Append(data[i][j]);
136
+ //no delimiter at the end
137
+ if ( j != data[i].Length - 1 ) {
138
+ TextLine.Append(Delimiter);
139
+ }
140
+ }
141
+ Writer.WriteLine(TextLine.ToString());
142
+ }
143
+ Writer.Close();
144
+ }
145
+
146
+ /// <summary>
147
+ /// Writes a two-dimensional table of numbers to a text file.
148
+ /// </summary>
149
+ /// <param name="TargetFilename">The target filename.</param>
150
+ /// <param name="AppendToFile">If set to <c>true</c> append to the end of the file.</param>
151
+ /// <param name="Delimiter">The delimiter separating the numeric values.</param>
152
+ /// <param name="data">The data to be written.</param>
153
+ /// <remarks>Data is a 2D rectangular array.</remarks>
154
+ public static void WriteNumericArrayToFile(string TargetFilename, bool AppendToFile, string Delimiter, double[,] data)
155
+ {
156
+ StreamWriter Writer;
157
+ int i;
158
+ int j;
159
+
160
+ Writer = new StreamWriter(TargetFilename, AppendToFile);
161
+ StringBuilder TextLine;
162
+ for ( i = 0; i < data.GetLength(0); i++ ) {
163
+ TextLine = new StringBuilder();
164
+ for ( j = 0; j < data.GetLength(1); j++ ) {
165
+ TextLine.Append(data[i, j]);
166
+ //no delimiter at the end
167
+ if ( j != data.GetLength(1) - 1 ) {
168
+ TextLine.Append(Delimiter);
169
+ }
170
+ }
171
+ Writer.WriteLine(TextLine.ToString());
172
+ }
173
+ Writer.Close();
174
+ }
175
+
176
+ /// <summary>
177
+ /// Writes an array of numbers to a text file.
178
+ /// </summary>
179
+ /// <param name="TargetFilename">The target filename.</param>
180
+ /// <param name="AppendToFile">If set to <c>true</c> append to the end of the file.</param>
181
+ /// <param name="Delimiter">The delimiter separating the numeric values.</param>
182
+ /// <param name="data">The data to be written.</param>
183
+ /// <remarks>Data is a 1D array.</remarks>
184
+ public static void WriteNumericArrayToFile(string TargetFilename, bool AppendToFile, string Delimiter, double[] data)
185
+ {
186
+ StreamWriter Writer;
187
+ int i;
188
+
189
+ Writer = new StreamWriter(TargetFilename, AppendToFile);
190
+ StringBuilder TextLine;
191
+ TextLine = new StringBuilder();
192
+ for ( i = 0; i < data.Length; i++ ) {
193
+ TextLine.Append(data[i]);
194
+ //no delimiter at the end
195
+ if ( i != data.Length - 1 ) {
196
+ TextLine.Append(Delimiter);
197
+ }
198
+ }
199
+ Writer.WriteLine(TextLine.ToString());
200
+ Writer.Close();
201
+ }
202
+
203
+ /// <summary>
204
+ /// Writes a two-dimensional table of numbers to a text file.
205
+ /// </summary>
206
+ /// <param name="TargetFilename">The target filename.</param>
207
+ /// <param name="AppendToFile">If set to <c>true</c> append to the end of the file.</param>
208
+ /// <param name="Delimiter">The delimiter separating the numeric values.</param>
209
+ /// <param name="data">The data to be written.</param>
210
+ /// <remarks>Data is a 2D jagged array.</remarks>
211
+ public static void WriteNumericArrayToFile(string TargetFilename, bool AppendToFile, string Delimiter, int[][] data)
212
+ {
213
+ StreamWriter Writer;
214
+ int i;
215
+ int j;
216
+
217
+ Writer = new StreamWriter(TargetFilename, AppendToFile);
218
+ StringBuilder TextLine;
219
+ for ( i = 0; i < data.Length; i++ ) {
220
+ TextLine = new StringBuilder();
221
+ for ( j = 0; j < data[i].Length; j++ ) {
222
+ TextLine.Append(data[i][j]);
223
+ //no delimiter at the end
224
+ if ( j != data[i].Length - 1 ) {
225
+ TextLine.Append(Delimiter);
226
+ }
227
+ }
228
+ Writer.WriteLine(TextLine.ToString());
229
+ }
230
+ Writer.Close();
231
+ }
232
+
233
+ /// <summary>
234
+ /// Writes a two-dimensional table of numbers to a text file.
235
+ /// </summary>
236
+ /// <param name="TargetFilename">The target filename.</param>
237
+ /// <param name="AppendToFile">If set to <c>true</c> append to the end of the file.</param>
238
+ /// <param name="Delimiter">The delimiter separating the numeric values.</param>
239
+ /// <param name="data">The data to be written.</param>
240
+ /// <remarks>Data is a 2D rectangular array.</remarks>
241
+ public static void WriteNumericArrayToFile(string TargetFilename, bool AppendToFile, string Delimiter, int[,] data)
242
+ {
243
+ StreamWriter Writer;
244
+ int i;
245
+ int j;
246
+
247
+ Writer = new StreamWriter(TargetFilename, AppendToFile);
248
+ StringBuilder TextLine;
249
+ for ( i = 0; i < data.GetLength(0); i++ ) {
250
+ TextLine = new StringBuilder();
251
+ for ( j = 0; j < data.GetLength(1); j++ ) {
252
+ TextLine.Append(data[i, j]);
253
+ //no delimiter at the end
254
+ if ( j != data.GetLength(1) - 1 ) {
255
+ TextLine.Append(Delimiter);
256
+ }
257
+ }
258
+ Writer.WriteLine(TextLine.ToString());
259
+ }
260
+ Writer.Close();
261
+ }
262
+
263
+ /// <summary>
264
+ /// Writes an array of numbers to a text file.
265
+ /// </summary>
266
+ /// <param name="TargetFilename">The target filename.</param>
267
+ /// <param name="AppendToFile">If set to <c>true</c> append to the end of the file.</param>
268
+ /// <param name="Delimiter">The delimiter separating the numeric values.</param>
269
+ /// <param name="data">The data to be written.</param>
270
+ /// <remarks>Data is a 1D array.</remarks>
271
+ public static void WriteNumericArrayToFile(string TargetFilename, bool AppendToFile, string Delimiter, int[] data)
272
+ {
273
+ StreamWriter Writer;
274
+ int i;
275
+
276
+ Writer = new StreamWriter(TargetFilename, AppendToFile);
277
+ StringBuilder TextLine;
278
+ TextLine = new StringBuilder();
279
+ for ( i = 0; i < data.Length; i++ ) {
280
+ TextLine.Append(data[i]);
281
+ //no delimiter at the end
282
+ if ( i != data.Length - 1 ) {
283
+ TextLine.Append(Delimiter);
284
+ }
285
+ }
286
+ Writer.WriteLine(TextLine.ToString());
287
+ Writer.Close();
288
+ }
289
+
290
+ #endregion
291
+
292
+ /// <summary>
293
+ /// Writes a text string to a file.
294
+ /// </summary>
295
+ /// <param name="TargetFilename">The target filename.</param>
296
+ /// <param name="AppendToFile">if set to <c>true</c> append to the end of the file.</param>
297
+ /// <param name="data">The text to write to the file.</param>
298
+ public static void WriteStringToFile(string TargetFilename, bool AppendToFile, string data)
299
+ {
300
+ StreamWriter Writer;
301
+
302
+ Writer = new StreamWriter(TargetFilename, AppendToFile);
303
+ Writer.WriteLine(data);
304
+ Writer.Close();
305
+ }
306
+
307
+ /// <summary>
308
+ /// Sets the normal distribution.
309
+ /// </summary>
310
+ /// <param name="DataArray">The input data array.</param>
311
+ /// <param name="Mean">The mean around which to set the distribution.</param>
312
+ /// <param name="StdDev">The standard deviation to use for the distribution.</param>
313
+ /// <returns>
314
+ /// An array with the normal distribution points around the given mean and standard deviation for the data array given.
315
+ /// If the mean is null then 0.0 is used. If the standard deviation is null or zero then 1.0 is used.
316
+ /// </returns>
317
+ public static double[] SetNormalDistribution(double[] DataArray, double Mean, double StdDev)
318
+ {
319
+ if ( DataArray == null ) {
320
+ return null;
321
+ }
322
+ if ( Mean.Equals(null) ) {
323
+ Mean = 0.0;
324
+ }
325
+ if ( StdDev.Equals(null) ) {
326
+ StdDev = 1.0;
327
+ }
328
+ else if ( StdDev <= 0.0 ) {
329
+ StdDev = 1.0;
330
+ }
331
+ ArrayList ar1d = new ArrayList();
332
+ double tmp;
333
+ for ( int i = 0; i < DataArray.Length; i++ ) {
334
+ tmp = (DataArray[i] - Mean) / StdDev;
335
+ ar1d.Add(1 / Math.Sqrt(2 * Math.PI) * Math.Exp(-0.5 * tmp * tmp));
336
+ }
337
+ return (double[])ar1d.ToArray(typeof(double));
338
+ }
339
+
340
+ #region MatrixMultiply (overloaded)
341
+
342
+ /// <summary>
343
+ /// Multiplies two matricies, item by item.
344
+ /// </summary>
345
+ /// <param name="a">The first matrix, 1D.</param>
346
+ /// <param name="b">The second matrix, 2D.</param>
347
+ /// <returns>The product of two matricies. Result will be the same size as the 2D matrix.</returns>
348
+ /// <remarks>
349
+ /// Each product is a(row) * b(row,col) with dimensions of b. "row" must be equal for both a and b,
350
+ /// or null value is returned.
351
+ /// </remarks>
352
+ public static double[,] MatrixMultiply(double[] a, double[,] b)
353
+ {
354
+ if ( a.Length != b.GetLength(0) ) {
355
+ return null;
356
+ }
357
+ double[,] Product = new double[b.GetLength(0), b.GetLength(1)];
358
+
359
+ for ( int row = 0; row < b.GetLength(0); row++ ) {
360
+ for ( int col = 0; col < b.GetLength(1); col++ ) {
361
+ Product[row, col] = b[row, col] * a[row];
362
+ }
363
+ }
364
+ return Product;
365
+ }
366
+
367
+ /// <summary>
368
+ /// Multiplies two matricies, item by item.
369
+ /// </summary>
370
+ /// <param name="a">The first matrix, 1D.</param>
371
+ /// <param name="b">The second matrix, 2D.</param>
372
+ /// <returns>The product of two matricies. Result will be the same size as the 2D matrix.</returns>
373
+ /// <remarks>
374
+ /// Each product is a(row) * b(row,col) with dimensions of b. "row" must be equal for both a and b,
375
+ /// or null value is returned.
376
+ /// </remarks>
377
+ public static double[,] MatrixMultiply(int[] a, double[,] b)
378
+ {
379
+ if ( a.Length != b.GetLength(0) ) {
380
+ return null;
381
+ }
382
+ double[,] Product = new double[b.GetLength(0), b.GetLength(1)];
383
+
384
+ for ( int row = 0; row < b.GetLength(0); row++ ) {
385
+ for ( int col = 0; col < b.GetLength(1); col++ ) {
386
+ Product[row, col] = b[row, col] * a[row];
387
+ }
388
+ }
389
+ return Product;
390
+ }
391
+
392
+ /// <summary>
393
+ /// Multiplies two matricies, item by item.
394
+ /// </summary>
395
+ /// <param name="a">The first matrix, 1D.</param>
396
+ /// <param name="b">The second matrix, 2D.</param>
397
+ /// <returns>The product of two matricies. Result will be the same size as the 2D matrix.</returns>
398
+ /// <remarks>
399
+ /// Each product is a(row) * b(row,col) with dimensions of b. "row" must be equal for both a and b,
400
+ /// or null value is returned.
401
+ /// </remarks>
402
+ public static double[,] MatrixMultiply(double[] a, int[,] b)
403
+ {
404
+ if ( a.Length != b.GetLength(0) ) {
405
+ return null;
406
+ }
407
+ double[,] Product = new double[b.GetLength(0), b.GetLength(1)];
408
+
409
+ for ( int row = 0; row < b.GetLength(0); row++ ) {
410
+ for ( int col = 0; col < b.GetLength(1); col++ ) {
411
+ Product[row, col] = b[row, col] * a[row];
412
+ }
413
+ }
414
+ return Product;
415
+ }
416
+
417
+ /// <summary>
418
+ /// Multiplies two matricies, item by item.
419
+ /// </summary>
420
+ /// <param name="a">The first matrix, 2D.</param>
421
+ /// <param name="b">The second matrix, 1D.</param>
422
+ /// <returns>The product of two matricies. Result will be the same size as the 2D matrix.</returns>
423
+ /// <remarks>
424
+ /// Each product is a(row,col) * b(row) with dimensions of a. "row" must be equal for both a and b,
425
+ /// or null value is returned.
426
+ /// </remarks>
427
+ public static double[,] MatrixMultiply(double[,] a, double[] b)
428
+ {
429
+ if ( b.Length != a.GetLength(0) ) {
430
+ return null;
431
+ }
432
+ double[,] Product = new double[a.GetLength(0), a.GetLength(1)];
433
+
434
+ for ( int row = 0; row < a.GetLength(0); row++ ) {
435
+ for ( int col = 0; col < a.GetLength(1); col++ ) {
436
+ Product[row, col] = a[row, col] * b[row];
437
+ }
438
+ }
439
+ return Product;
440
+ }
441
+
442
+ /// <summary>
443
+ /// Multiplies two matricies, item by item.
444
+ /// </summary>
445
+ /// <param name="a">The first matrix, 2D.</param>
446
+ /// <param name="b">The second matrix, 1D.</param>
447
+ /// <returns>The product of two matricies. Result will be the same size as the 2D matrix.</returns>
448
+ /// <remarks>
449
+ /// Each product is a(row,col) * b(row) with dimensions of a. "row" must be equal for both a and b,
450
+ /// or null value is returned.
451
+ /// </remarks>
452
+ public static double[,] MatrixMultiply(int[,] a, double[] b)
453
+ {
454
+ if ( b.Length != a.GetLength(0) ) {
455
+ return null;
456
+ }
457
+ double[,] Product = new double[a.GetLength(0), a.GetLength(1)];
458
+
459
+ for ( int row = 0; row < a.GetLength(0); row++ ) {
460
+ for ( int col = 0; col < a.GetLength(1); col++ ) {
461
+ Product[row, col] = a[row, col] * b[row];
462
+ }
463
+ }
464
+ return Product;
465
+ }
466
+
467
+ /// <summary>
468
+ /// Multiplies two matricies, item by item.
469
+ /// </summary>
470
+ /// <param name="a">The first matrix, 2D.</param>
471
+ /// <param name="b">The second matrix, 1D.</param>
472
+ /// <returns>The product of two matricies. Result will be the same size as the 2D matrix.</returns>
473
+ /// <remarks>
474
+ /// Each product is a(row,col) * b(row) with dimensions of a. "row" must be equal for both a and b,
475
+ /// or null value is returned.
476
+ /// </remarks>
477
+ public static double[,] MatrixMultiply(double[,] a, int[] b)
478
+ {
479
+ if ( b.Length != a.GetLength(0) ) {
480
+ return null;
481
+ }
482
+ double[,] Product = new double[a.GetLength(0), a.GetLength(1)];
483
+
484
+ for ( int row = 0; row < a.GetLength(0); row++ ) {
485
+ for ( int col = 0; col < a.GetLength(1); col++ ) {
486
+ Product[row, col] = a[row, col] * b[row];
487
+ }
488
+ }
489
+ return Product;
490
+ }
491
+
492
+ /// <summary>
493
+ /// Multiplies two matricies, item by item.
494
+ /// </summary>
495
+ /// <param name="a">The first matrix, 1D.</param>
496
+ /// <param name="b">The second matrix, 1D.</param>
497
+ /// <returns>The product of two matricies. Result will be a 1D matrix.</returns>
498
+ /// <remarks>
499
+ /// Each product is a(row) * b(row) with dimensions of a. a and b must be the same size
500
+ /// or null is returned.</remarks>
501
+ public static double[] MatrixMultiply(double[] a, double[] b)
502
+ {
503
+ if ( a.Length != b.Length ) {
504
+ return null;
505
+ }
506
+ double[] Product = new double[a.Length];
507
+
508
+ for ( int row = 0; row < a.Length; row++ ) {
509
+ Product[row] = a[row] * b[row];
510
+ }
511
+ return Product;
512
+ }
513
+
514
+ /// <summary>
515
+ /// Multiplies two matricies, item by item.
516
+ /// </summary>
517
+ /// <param name="a">The first matrix, 1D.</param>
518
+ /// <param name="b">The second matrix, 1D.</param>
519
+ /// <returns>The product of two matricies. Result will be a 1D matrix.</returns>
520
+ /// <remarks>
521
+ /// Each product is a(row) * b(row) with dimensions of a. a and b must be the same size
522
+ /// or null is returned.</remarks>
523
+ public static double[] MatrixMultiply(int[] a, double[] b)
524
+ {
525
+ if ( a.Length != b.Length ) {
526
+ return null;
527
+ }
528
+ double[] Product = new double[a.Length];
529
+
530
+ for ( int row = 0; row < a.Length; row++ ) {
531
+ Product[row] = a[row] * b[row];
532
+ }
533
+ return Product;
534
+ }
535
+
536
+ /// <summary>
537
+ /// Multiplies two matricies, item by item.
538
+ /// </summary>
539
+ /// <param name="a">The first matrix, 1D.</param>
540
+ /// <param name="b">The second matrix, 1D.</param>
541
+ /// <returns>The product of two matricies. Result will be a 1D matrix.</returns>
542
+ /// <remarks>
543
+ /// Each product is a(row) * b(row) with dimensions of a. a and b must be the same size
544
+ /// or null is returned.</remarks>
545
+ public static double[] MatrixMultiply(double[] a, int[] b)
546
+ {
547
+ if ( a.Length != b.Length ) {
548
+ return null;
549
+ }
550
+ double[] Product = new double[a.Length];
551
+
552
+ for ( int row = 0; row < a.Length; row++ ) {
553
+ Product[row] = a[row] * b[row];
554
+ }
555
+ return Product;
556
+ }
557
+
558
+ #endregion
559
+
560
+ /// <summary>
561
+ /// Reduces a 2D matrix to 1D by summing each column or row.
562
+ /// </summary>
563
+ /// <param name="a">The matrix.</param>
564
+ /// <param name="ByDim">Dimension to sum by.</param>
565
+ /// <returns>1D matrix with summed values, having same length as the dimension to sum by.</returns>
566
+ public static double[] MatrixReduceBySum(double[,] a, DimensionType ByDim)
567
+ {
568
+ double[] sum;
569
+ int row;
570
+ int col;
571
+ if ( ByDim == DimensionType.Row ) {
572
+ sum = new double[a.GetLength(0)];
573
+ for ( row = 0; row < a.GetLength(0); row++ ) {
574
+ for ( col = 0; col < a.GetLength(1); col++ ) {
575
+ sum[row] = sum[row] + a[row, col];
576
+ }
577
+ }
578
+ }
579
+ else {
580
+ sum = new double[a.GetLength(1)];
581
+ for ( col = 0; col < a.GetLength(1); col++ ) {
582
+ for ( row = 0; row < a.GetLength(0); row++ ) {
583
+ sum[col] = sum[col] + a[row, col];
584
+ }
585
+ }
586
+ }
587
+ return sum;
588
+ }
589
+
590
+ #region ArraySum (overloaded)
591
+
592
+ /// <summary>
593
+ /// Sums all elements of a 1D array.
594
+ /// </summary>
595
+ /// <param name="a">The array to sum.</param>
596
+ /// <returns>The sum of all elements in the array.</returns>
597
+ public static double ArraySum(double[] a)
598
+ {
599
+ double info = 0;
600
+ for ( int i = 0; i < a.Length; i++ ) {
601
+ info = info + a[i];
602
+ }
603
+ return info;
604
+ }
605
+
606
+ /// <summary>
607
+ /// Sums all elements of a 1D array.
608
+ /// </summary>
609
+ /// <param name="a">The array to sum.</param>
610
+ /// <returns>The sum of all elements in the array.</returns>
611
+ public static double ArraySum(int[] a)
612
+ {
613
+ int info = 0;
614
+ for ( int i = 0; i < a.Length; i++ ) {
615
+ info = info + a[i];
616
+ }
617
+ return (double)info;
618
+ }
619
+
620
+ #endregion
621
+
622
+ /// <summary>
623
+ /// Slices one dimension from a 3D matrix.
624
+ /// </summary>
625
+ /// <param name="a">The 3D matrix.</param>
626
+ /// <param name="ByDim">The dimension to slice.</param>
627
+ /// <param name="x">Index of the first dimension to hold constant.</param>
628
+ /// <param name="DimX">The first constant dimension.</param>
629
+ /// <param name="y">Index of the second dimension to hold constant.</param>
630
+ /// <param name="DimY">The second constant dimension.</param>
631
+ /// <returns>A one dimensional array from the 3D matrix.</returns>
632
+ public static double[] MatrixSlice1D(double[, ,] a, DimensionType ByDim, int x, DimensionType DimX, int y, DimensionType DimY)
633
+ {
634
+ int ArraySize = a.GetLength((int)ByDim);
635
+ double[] ar1d = new double[ArraySize];
636
+ switch ( ByDim ) {
637
+ case DimensionType.Row:
638
+ for ( int i = 0; i < ArraySize; i++ ) {
639
+ if ( DimX == DimensionType.Column ) {
640
+ ar1d[i] = a[i, x, y];
641
+ }
642
+ else {
643
+ ar1d[i] = a[i, y, x];
644
+ }
645
+ }
646
+ break;
647
+ case DimensionType.Column:
648
+ for ( int i = 0; i < ArraySize; i++ ) {
649
+ if ( DimX == DimensionType.Row ) {
650
+ ar1d[i] = a[x, i, y];
651
+ }
652
+ else {
653
+ ar1d[i] = a[y, i, x];
654
+ }
655
+ }
656
+ break;
657
+ case DimensionType.Depth:
658
+ for ( int i = 0; i < ArraySize; i++ ) {
659
+ if ( DimX == DimensionType.Row ) {
660
+ ar1d[i] = a[x, y, i];
661
+ }
662
+ else {
663
+ ar1d[i] = a[y, x, i];
664
+ }
665
+ }
666
+ break;
667
+ }
668
+ return ar1d;
669
+ }
670
+
671
+ /// <summary>
672
+ /// Calculate averages across categories. Mimics the "tapply" method in R. Assumes that <c>categories</c> and <c>items</c>
673
+ /// are in the proper order with respect to each other.
674
+ /// </summary>
675
+ /// <param name="categories"><c>List</c> of categories of items.</param>
676
+ /// <param name="items"><c>List</c> of items.</param>
677
+ /// <returns><c>SortedList</c> of categories with their averages.</returns>
678
+ public static SortedList<int, double> CategoryAverages (List<int> categories, List<double> items)
679
+ {
680
+ if (items.Count != categories.Count) {
681
+ throw new ApplicationException("CategoryAverages: item/category count mismatch. ");
682
+ }
683
+
684
+ SortedList<int, List<double>> slCat = new SortedList<int, List<double>>();
685
+
686
+ for (int i=0; i<items.Count; i++) {
687
+ if (!(slCat.ContainsKey(categories[i]))) {
688
+ List<double> Items = new List<double>();
689
+ Items.Add(items[i]);
690
+ slCat.Add(categories[i], Items);
691
+ }
692
+ else {
693
+ slCat[categories[i]].Add(items[i]);
694
+ }
695
+ }
696
+
697
+ SortedList<int,double> averages = new SortedList<int,double>();
698
+
699
+ foreach (int i in slCat.Keys) {
700
+ averages[i] = slCat[i].AsQueryable().Average();
701
+ }
702
+
703
+ return averages;
704
+ }
705
+
706
+ /// <summary>
707
+ /// Utility for random number selection. This can use the C# random number generator
708
+ /// or use an input list (used for QA to ensure the same random number sequence).
709
+ /// </summary>
710
+ public class RandomNumber
711
+ {
712
+ private static int _Index;
713
+ private static int _ListCount;
714
+ private static double[] _NumberList;
715
+ private static Random _RandomNumber;
716
+ private static bool _UseList;
717
+
718
+ /// <summary>
719
+ /// Private constructor
720
+ /// </summary>
721
+ private RandomNumber ()
722
+ {
723
+ Init();
724
+ }
725
+
726
+ public static void Init ()
727
+ {
728
+ _UseList = false;
729
+ _RandomNumber = new Random(unchecked((int)DateTime.Now.Ticks));
730
+ }
731
+
732
+ /// <summary>
733
+ /// Initialize the generator to use a predetermined list of random numbers.
734
+ /// </summary>
735
+ /// <param name="randomNumberList">The list of predetermined random numbers, type <c>double</c>,
736
+ /// with values from zero to one.</param>
737
+ public static void Init (double[] randomNumberList) {
738
+
739
+ if (randomNumberList.Count() == 0) {
740
+ throw new ApplicationException("QArandom error: input list is empty");
741
+ }
742
+
743
+ _UseList = true;
744
+ _NumberList = randomNumberList;
745
+ _ListCount = _NumberList.Count();
746
+ _Index = -1;
747
+ }
748
+
749
+ /// <summary>
750
+ /// Get the next random number.
751
+ /// </summary>
752
+ /// <returns>A <c>double</c> between zero and one.</returns>
753
+ public static double NextDouble()
754
+ {
755
+ if (_UseList) {
756
+ if (_Index == _ListCount-1) {
757
+ //If at the end of the list go back to the beginning
758
+ _Index = 0;
759
+ }
760
+ else {
761
+ _Index++;
762
+ }
763
+ return _NumberList[_Index];
764
+ }
765
+ else {
766
+ if (_RandomNumber == null) {
767
+ Init();
768
+ }
769
+ return _RandomNumber.NextDouble();
770
+ }
771
+ }
772
+
773
+ /// <summary>
774
+ /// Get the next random number and scale it to the integer <c>maxValue</c>.
775
+ /// </summary>
776
+ /// <param name="maxValue">The maximum <c>integer</c> value to return</param>
777
+ /// <returns>A random <c>integer</c> between zero and <c>maxValue</c>.</returns>
778
+ public static int Next(int maxValue)
779
+ {
780
+ if (_UseList) {
781
+ if (_Index == _ListCount-1) {
782
+ //If at the end of the list go back to the beginning
783
+ _Index = 0;
784
+ }
785
+ else {
786
+ _Index++;
787
+ }
788
+ return (int)Math.Round(_NumberList[_Index] * maxValue);
789
+ }
790
+ else {
791
+ if (_RandomNumber == null) {
792
+ Init();
793
+ }
794
+ return _RandomNumber.Next(maxValue);
795
+ }
796
+ }
797
+
798
+ }
799
+
800
+
801
+ /// <summary>
802
+ /// A comparer for a list of double-int key-value pairs. This is required to allow sorting of this type of list.
803
+ /// </summary>
804
+ public class KVPDoubleIntComparer : IComparer<KeyValuePair<double,int>>
805
+ {
806
+ public int Compare ( KeyValuePair<double, int> kvp1, KeyValuePair<double, int> kvp2 )
807
+ {
808
+ //Check for equalities: use the same method as the R programming language
809
+ if ((kvp1.Key == kvp2.Key) && (kvp1.Value != kvp2.Value)) {
810
+ if (kvp1.Value > kvp2.Value) {
811
+ return 1;
812
+ }
813
+ else {
814
+ return -1;
815
+ }
816
+ }
817
+ else {
818
+ return (kvp1.Key.CompareTo(kvp2.Key));
819
+ }
820
+ }
821
+ }
822
+
823
+ }
824
+
825
+ }