public FMatrix SumMatrix(FMatrix f1, int N) { FMatrix A = new FMatrix(M, N); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { A._M[i, j] = this._M[i, j] + f1._M[i, j]; } } return(A); }
public FMatrix Scale1(float S) { FMatrix A = new FMatrix(M, N); for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { A._M[i, j] = 1 / this._M[i, j]; } } return(A); }
/// <summary> /// CPU version of the GPU Row Sums /// </summary> /// <param name="M">The matrix to compute the row sums on</param> /// <returns>A vector of the row sums i.e. an Mx1 column vector from the matrix</returns> public static float[] cpuRowSums(ref FMatrix M) { float [] Result = new float[M.M]; for (int i = 0; i < M.M; i++) { float Sum = 0; for (int j = 0; j < M.N; j++) { Sum += M._M[i, j]; } Result[i] = Sum; } return(Result); }
/// <summary> /// Second version of correlate based on distance from mean and square distance from mean /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <returns></returns> public static double Correlate2(ref FMatrix A, ref FMatrix B) { //predcondition - check A.M==B.M && A.N==B.N double SumA = 0, SumB = 0; for (int i = 0; i < A.M; i++) { for (int j = 0; j < A.N; j++) { SumA += A._M[i, j]; SumB += B._M[i, j]; } } double MeanA = SumA / (A.M * A.N); double MeanB = SumB / (B.M * B.N); System.Diagnostics.Debug.WriteLine("MeanA: " + MeanA + " MeanB: " + MeanB + " SumA: " + SumA + " SumB: " + SumB); double C1 = 0, C2 = 0, C3 = 0, C4 = 0; for (int i = 0; i < A.M; i++) { for (int j = 0; j < A.N; j++) { //C1 += A._M[i, j] - MeanA; //C2 += B._M[i, j] - MeanB; C1 += (A._M[i, j] - MeanA) * (B._M[i, j] - MeanB); C3 += Math.Pow(A._M[i, j] - MeanA, 2); C4 += Math.Pow(B._M[i, j] - MeanB, 2); } } // //double D1 = 0, D2 = 0, D3 = 0, D4 = 0, D5 = 0; //double NM = 7201 * 7201; //for (int i = 0; i < A.M; i++) //{ // for (int j = 0; j < A.N; j++) // { // D1+= // } //} // //double r = C1*C2/(Math.Sqrt(C3)*Math.Sqrt(C4)); double r = C1 / (Math.Sqrt(C3) * Math.Sqrt(C4)); return(r); }
/// <summary> /// Mean trips calculation /// </summary> /// <param name="Tij"></param> /// <param name="dis"></param> /// <returns></returns> public float CalculateCBar(ref FMatrix Tij, ref FMatrix dis) { int N = Tij.N; float CNumerator = 0, CDenominator = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { CNumerator += Tij._M[i, j] * dis._M[i, j]; CDenominator += Tij._M[i, j]; } } float CBar = CNumerator / CDenominator; return(CBar); }
/// <summary> /// Deserialise a matrix using Buffer.BlockCopy to ensure it is FAST. This can deserialise an N=7200 matrix in around 15ms. /// Format is 4 byte integer containing the matrix order (N), LSB first. The following bytes are the float binary format /// with 4 bytes per float (single) for each array item in turn. /// NOTE: the static method returning an FMatrix might look bad, but it actually returns an object pointer into the global heap. /// DirtySerialise and DirtyDeserialise are opposite functions. /// </summary> /// <param name="Filename"></param> /// <returns></returns> public static FMatrix DirtyDeserialise(string Filename) { FMatrix Mat; using (Stream stream = File.OpenRead(Filename)) { //read the little endian value of M and N back from the stream a byte at a time int M = stream.ReadByte() | (stream.ReadByte() << 8) | (stream.ReadByte() << 16) | (stream.ReadByte() << 24); int N = stream.ReadByte() | (stream.ReadByte() << 8) | (stream.ReadByte() << 16) | (stream.ReadByte() << 24); //int N = M; //now create a new matrix of order MxN, along with the byte buffer to read the line Mat = new FMatrix(M, N); byte[] buf = new byte[N * sizeof(float)]; for (int i = 0; i < M; i++) { stream.Read(buf, 0, buf.Length); Buffer.BlockCopy(buf, 0, Mat._M, i * N * sizeof(float), buf.Length); } } return(Mat); }
private void TestMatrix(ref FMatrix M) { int N = M.N; int ZeroCount = 0, NaNCount = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (M._M[i, j] <= 0) { ++ZeroCount; } if (float.IsNaN(M._M[i, j])) { ++NaNCount; } } } System.Diagnostics.Debug.WriteLine("ZeroCount=" + ZeroCount + " NaNCount=" + NaNCount); }
private void button1_Click(object sender, EventArgs e) { using (var fbd = new FolderBrowserDialog()) { fbd.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); //fbd.SelectedPath = @"D:\desktopQuant\data\"; fbd.SelectedPath = @"D:\2020\grantBikes\data\tranus\"; DialogResult result = fbd.ShowDialog(); if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath)) { string[] files = Directory.GetFiles(fbd.SelectedPath); /*System.Windows.Forms.MessageBox.Show("Directory: " + fbd.SelectedPath.ToString(), "Message"); * System.Windows.Forms.MessageBox.Show("Files found: " + files.Length.ToString(), "Message"); * for (int i=0;i< files.Length;i++) * System.Windows.Forms.MessageBox.Show("Files found: " + files.ElementAt(i), "Message");*/ // Display the ProgressBar control. pBar1.Visible = true; pBar1.Minimum = 1; pBar1.Maximum = 100; pBar1.Value = 1; pBar1.Step = 10; FMatrix[] temp = new FMatrix[3]; //Data input to model. FMatrix[] mtotal = null; FMatrix[] mtemp = null; mtotal = new FMatrix[3]; mtemp = new FMatrix[3]; string[] OutTPred = { "TPred1.csv", "TPred2.csv", "TPred3.csv" }; string OutTPredCombined = "TPred.csv"; int N = 194; if (modelType == 3) { string dijprivate = "privateTimeCode.csv"; string dijprivateS = "dis_roads_min.bin"; string dijpublic = "publicTimeCode.csv"; string dijpublicS = "dis_bus_min.bin"; string tprivate = "viajesODprivadosM.csv"; string tpublicS = "TObs_1.bin"; string tpublic = "viajesODpublicosM.csv"; string tprivateS = "TObs_2.bin"; FMatrix dijPrivate = FMatrix.GenerateTripsLondon(fbd.SelectedPath + "\\" + dijprivate, N); dijPrivate.DirtySerialise(fbd.SelectedPath + "\\" + dijprivateS); FMatrix dijPublic = FMatrix.GenerateTripsLondon(fbd.SelectedPath + "\\" + dijpublic, N); dijPublic.DirtySerialise(fbd.SelectedPath + "\\" + dijpublicS); FMatrix tprivateM = FMatrix.GenerateTripsLondon(fbd.SelectedPath + "\\" + tprivate, N); tprivateM.DirtySerialise(fbd.SelectedPath + "\\" + tpublicS); FMatrix tpublicM = FMatrix.GenerateTripsLondon(fbd.SelectedPath + "\\" + tpublic, N); tpublicM.DirtySerialise(fbd.SelectedPath + "\\" + tprivateS); } int NumModes = 1; switch (this.modelType) { case 3: NumModes = 2; break; default: NumModes = 3; break; } QUANT3ModelProperties q = new QUANT3ModelProperties(); FMatrix[] TObs = new FMatrix[NumModes]; //Data input to model. for (int k = 0; k < NumModes; k++) { TObs[k] = FMatrix.DirtyDeserialise(fbd.SelectedPath + "\\" + q.InTObs[k]); } for (int k = 0; k < NumModes; k++) { mtotal[k] = new FMatrix(N, N); } for (int i = 0; i < nexperiments; i++) { QUANT3Model quant = new QUANT3Model(modelType); temp = quant.LoadAndRun(q, fbd, pBar1, i); //quant.LoadAndRun(q, fbd, pBar1); //mtemp = temp; for (int j = 0; j < NumModes; j++) { //mtemp[j] = temp[j]; //mtemp[j].DirtySerialise(fbd.SelectedPath + "\\" + OutTPred[j] + "_1"); temp[j].WriteCSVMatrix(fbd.SelectedPath + "\\" + OutTPred[j] + "_" + i.ToString() + ".csv"); } FMatrix TPredCombinedtmp = new FMatrix(N, N); float Sum = 0; for (int w = 0; w < TPredCombinedtmp.M; w++) { for (int j = 0; j < TPredCombinedtmp.N; j++) { for (int k = 0; k < NumModes; k++) { Sum += temp[k]._M[w, j]; } TPredCombinedtmp._M[w, j] = Sum; Sum = 0.0f; } } TPredCombinedtmp.WriteCSVMatrix(fbd.SelectedPath + "\\TPred_" + i.ToString() + ".csv"); for (int j = 0; j < NumModes; j++) { mtotal[j] = mtotal[j].SumMatrix(temp[j], N); } System.Diagnostics.Debug.WriteLine("run = " + i); } for (int j = 0; j < NumModes; j++) { mtotal[j] = mtotal[j].Scale(1.0f / nexperiments); } for (int k = 0; k < NumModes; k++) { //mtotal[k].DirtySerialise(fbd.SelectedPath + "\\" + OutTPred[k]); mtotal[k].WriteCSVMatrix(fbd.SelectedPath + "\\" + OutTPred[k]); } FMatrix TPredCombined = new FMatrix(N, N); for (int i = 0; i < TPredCombined.M; i++) { for (int j = 0; j < TPredCombined.N; j++) { float Sum = 0; for (int k = 0; k < NumModes; k++) { Sum += mtotal[k]._M[i, j]; } TPredCombined._M[i, j] = Sum; } } //TPredCombined.DirtySerialise(fbd.SelectedPath + "\\" + OutTPredCombined); TPredCombined.WriteCSVMatrix(fbd.SelectedPath + "\\" + OutTPredCombined); } button2.Enabled = true; } /*int size = -1; * DialogResult result = openFileDialog1.ShowDialog(); // Show the dialog. * if (result == DialogResult.OK) // Test result. * { * string file = openFileDialog1.FileName; * try * { * string text = File.ReadAllText(file); * size = text.Length; * } * catch (IOException) * { * } * } * Console.WriteLine(size); // <-- Shows file size in debugging mode. * Console.WriteLine(result); // <-- For debugging use.*/ }
/// <summary> /// NOTE: this was copied directly from the Quant 1 model /// Run the quant model with different values for the Oi and Dj zones. /// Uses a guid to store the user defined model run data /// PRE: needs TObs, dis and beta /// TODO: need to instrument this /// TODO: writes out one file, which is the sum of the three predicted matrices produced /// </summary> /// <param name="OiDjHash">Hashmap of zonei index and Oi, Dj values for that area. A value of -1 for Oi or Dj means no change.</param> /// <param name="hasConstraints">Run with random values added to the Dj values.</param> /// <param name="OutFilename">Filename of where to store the resulting matrix, probably includes the GUID of the user directory to store the results</param> public void RunWithChanges(Dictionary <int, float[]> OiDjHash, bool hasConstraints, string OutFilename) { Stopwatch timer = Stopwatch.StartNew(); int N = TObs[0].N; float[] DjObs = new float[N]; float[] OiObs = new float[N]; float Sum; //OiObs for (int i = 0; i < N; i++) { Sum = 0; for (int j = 0; j < N; j++) { for (int k = 0; k < NumModes; k++) { Sum += TObs[k]._M[i, j]; } } OiObs[i] = Sum; } //DjObs for (int j = 0; j < N; j++) { Sum = 0; for (int i = 0; i < N; i++) { for (int k = 0; k < NumModes; k++) { Sum += TObs[k]._M[i, j]; } } DjObs[j] = Sum; } FMatrix[] TPredCons = new FMatrix[NumModes]; for (int k = 0; k < NumModes; k++) //mode loop { TPredCons[k] = new FMatrix(N, N); for (int i = 0; i < N; i++) { //denominator calculation which is sum of all modes double denom = 0; for (int kk = 0; kk < NumModes; kk++) //second mode loop { for (int j = 0; j < N; j++) { denom += DjObs[j] * Math.Exp(-Beta[kk] * dis[kk]._M[i, j]); } } //numerator calculation for this mode (k) for (int j = 0; j < N; j++) { TPredCons[k]._M[i, j] = (float)(B[j] * OiObs[i] * DjObs[j] * Math.Exp(-Beta[k] * dis[k]._M[i, j]) / denom); } } } //now the DjCons - you could just set Zj here? float[] DjCons = new float[N]; for (int j = 0; j < N; j++) { Sum = 0; for (int i = 0; i < N; i++) { for (int k = 0; k < NumModes; k++) { Sum += TPredCons[k]._M[i, j]; } } DjCons[j] = Sum; } // // //constraints initialisation - this is the same as the calibration, except that the B[j] values are initially taken from the calibration, while Z[j] is initialised from Dj[j] as before. float[] Z = new float[N]; for (int j = 0; j < N; j++) { Z[j] = float.MaxValue; if (IsUsingConstraints) { if (Constraints[j] >= 1.0f) //constraints array taking place of Gj (Green Belt) in documentation { //Gj=1 means a high enough percentage of MSOA land is green belt, so can't be built on //set constraint to original Dj //Z[j] = DjObs[j]; Z[j] = DjCons[j]; } } } //end of constraints initialisation - have now set B[] and Z[] based on IsUsingConstraints, Constraints[] and DObs[] //apply changes here from the hashmap foreach (KeyValuePair <int, float[]> KVP in OiDjHash) { int i = KVP.Key; if (KVP.Value[0] >= 0) { OiObs[i] = KVP.Value[0]; } if (KVP.Value[1] >= 0) { DjObs[i] = KVP.Value[1]; } } bool ConstraintsMet = false; do { //residential constraints ConstraintsMet = true; //unless violated one or more times below int FailedConstraintsCount = 0; //run 3 model System.Diagnostics.Debug.WriteLine("Run 3 model"); for (int k = 0; k < NumModes; k++) //mode loop { TPred[k] = new FMatrix(N, N); Parallel.For(0, N, i => //for (int i = 0; i < N; i++) { //denominator calculation which is sum of all modes double denom = 0; for (int kk = 0; kk < NumModes; kk++) //second mode loop { for (int j = 0; j < N; j++) { denom += B[j] * DjObs[j] * Math.Exp(-Beta[kk] * dis[kk]._M[i, j]); } } //numerator calculation for this mode (k) for (int j = 0; j < N; j++) { TPred[k]._M[i, j] = (float)(B[j] * OiObs[i] * DjObs[j] * Math.Exp(-Beta[k] * dis[k]._M[i, j]) / denom); } } ); } //constraints check if (IsUsingConstraints) { System.Diagnostics.Debug.WriteLine("Constraints test"); for (int j = 0; j < N; j++) { float Dj = 0; for (int i = 0; i < N; i++) { Dj += TPred[0]._M[i, j] + TPred[1]._M[i, j] + TPred[2]._M[i, j]; } if (Constraints[j] >= 1.0f) //Constraints is taking the place of Gj in the documentation { //System.Diagnostics.Debug.WriteLine("Test: " + Dj + ", " + Z[j] + "," + B[j]); if ((Dj - Z[j]) >= 0.5) //was >1.0 threshold { B[j] = B[j] * Z[j] / Dj; ConstraintsMet = false; ++FailedConstraintsCount; // System.Diagnostics.Debug.WriteLine("Constraints violated on " + FailedConstraintsCount + " MSOA zones"); // System.Diagnostics.Debug.WriteLine("Dj=" + Dj + " Zj=" + Z[j] + " Bj=" + B[j]); } } } } } while (!ConstraintsMet); //add all three TPred together FMatrix TPredAll = new FMatrix(N, N); //Parallel.For(0, N, i => for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { Sum = 0; for (int k = 0; k < NumModes; k++) { Sum += TPred[k]._M[i, j]; } TPredAll._M[i, j] = Sum; } } //); //and store the result somewhere TPredAll.DirtySerialise(OutFilename); System.Diagnostics.Debug.WriteLine("QUANT3Model::RunWithChanges: " + timer.ElapsedMilliseconds + " ms"); }
//this is runwithconstraints public void Run(ProgressBar pb, String SelectedPath) { int N = TObs[0].M; //hopefully [0] and [1] and [2] are the same if (nexp > 1) { float total = 345214.0f; float target = 0.9f * total; float rndvaluet = 0.0f; Random rnd = new Random(); /// int col = 1; int row = 1; while (rndvaluet <= target) { col = rnd.Next(0, N); row = rnd.Next(0, N); if (TObs[0]._M[col, row] != 0 || TObs[1]._M[col, row] != 0 || TObs[2]._M[col, row] != 0) { // countZero += 1; TObs[0]._M[col, row] = 0.0f; TObs[1]._M[col, row] = 0.0f; TObs[2]._M[col, row] = 0.0f; positions.Add(new List <int> { col, row }); rndvaluet += 1; } } } //set up Beta for modes 0, 1 and 2 to 1.0f Beta = new float[NumModes]; for (int k = 0; k < NumModes; k++) { Beta[k] = 1.0f; } //work out Dobs and Tobs from rows and columns of TObs matrix //These don't ever change so they need to be outside the convergence loop float[] DjObs = new float[N]; float[] OiObs = new float[N]; float Sum; // System.Diagnostics.Debug.WriteLine("End while " + rndvaluet); //// //OiObs for (int i = 0; i < N; i++) { Sum = 0; for (int j = 0; j < N; j++) { for (int k = 0; k < NumModes; k++) { Sum += TObs[k]._M[i, j]; } } OiObs[i] = Sum; // System.Diagnostics.Debug.WriteLine(OiObs[i]); } //DjObs for (int j = 0; j < N; j++) { Sum = 0; for (int i = 0; i < N; i++) { for (int k = 0; k < NumModes; k++) { Sum += TObs[k]._M[i, j]; } } DjObs[j] = Sum; } //constraints initialisation B = new float[N]; for (int i = 0; i < N; i++) { B[i] = 1.0f; //hack } float[] Z = new float[N]; for (int j = 0; j < N; j++) { Z[j] = float.MaxValue; if (IsUsingConstraints) { if (Constraints[j] >= 1.0f) //constraints array taking place of Gj (Green Belt) in documentation { //Gj=1 means 0.8 of MSOA land is green belt, so can't be built on //set constraint to original Dj Z[j] = DjObs[j]; } } } FMatrix[] Tij = null; bool Converged = false; int countR = 0; Tij = new FMatrix[NumModes]; for (int k = 0; k < NumModes; k++) { Tij[k] = new FMatrix(N, N); } while (!Converged) { pb.PerformStep(); bool ConstraintsMet = false; do { //residential constraints ConstraintsMet = true; //unless violated one or more times below int FailedConstraintsCount = 0; //model run for (int k = 0; k < NumModes; k++) //mode loop { //Parallel.For(0, N, i => for (int i = 0; i < N; i++) { //denominator calculation which is sum of all modes double denom = 0; for (int kk = 0; kk < NumModes; kk++) //second mode loop { for (int j = 0; j < N; j++) { denom += DjObs[j] * Math.Exp(-Beta[kk] * dis[kk]._M[i, j]); } } //numerator calculation for this mode (k) for (int j = 0; j < N; j++) { Tij[k]._M[i, j] = (float)(B[j] * OiObs[i] * DjObs[j] * Math.Exp(-Beta[k] * dis[k]._M[i, j]) / denom); } } //); } //constraints check if (IsUsingConstraints) { System.Diagnostics.Debug.WriteLine("Constraints test"); // InstrumentStatusText = "Constraints test"; for (int j = 0; j < N; j++) { float Dj = 0; for (int i = 0; i < N; i++) { Dj += Tij[0]._M[i, j] + Tij[1]._M[i, j] + Tij[2]._M[i, j]; } if (Constraints[j] >= 1.0f) //Constraints is taking the place of Gj in the documentation { if ((Dj - Z[j]) >= 0.5) //was >1.0 { B[j] = B[j] * Z[j] / Dj; ConstraintsMet = false; ++FailedConstraintsCount; System.Diagnostics.Debug.WriteLine("Dj=" + Dj + " Zj=" + Z[j] + " Bj=" + B[j]); } } } } } while (!ConstraintsMet); //calculate mean predicted trips and mean observed trips (this is CBar) float[] CBarPred = new float[NumModes]; float[] CBarObs = new float[NumModes]; float[] delta = new float[NumModes]; for (int k = 0; k < NumModes; k++) { CBarPred[k] = CalculateCBar(ref Tij[k], ref dis[k]); CBarObs[k] = CalculateCBar(ref TObs[k], ref dis[k]); delta[k] = Math.Abs(CBarPred[k] - CBarObs[k]); //the aim is to minimise delta[0]+delta[1]+... } //delta check on all betas (Beta0, Beta1, Beta2) stopping condition for convergence //double gradient descent search on Beta0 and Beta1 and Beta2 Converged = true; countR++; //System.Diagnostics.Debug.WriteLine("count = " + countR); for (int k = 0; k < NumModes; k++) { System.Diagnostics.Debug.WriteLine("k=" + k + " - value= " + delta[k] / CBarObs[k]); //if (delta[k] / CBarObs[k] > factor) if (delta[k] / CBarObs[k] > 0.001) //if (delta[k] / CBarObs[k] > 0.52) { Beta[k] = Beta[k] * CBarPred[k] / CBarObs[k]; System.Diagnostics.Debug.WriteLine("Beta " + Beta[k]); Converged = false; } } float deltat = 0.0f; for (int k = 0; k < NumModes; k++) { deltat += delta[k]; } } //Set the output, TPred[] for (int k = 0; k < NumModes; k++) { TPred[k] = Tij[k]; } if (nexp > 1) { //save Betas if (!File.Exists(SelectedPath + "\\" + "betas.csv")) { using (StreamWriter r = File.CreateText(SelectedPath + "\\" + "betas.csv")) r.Write(Beta[0] + "," + Beta[1] + "," + Beta[2] + "\n"); } else { using (StreamWriter r = File.AppendText(SelectedPath + "\\" + "betas.csv")) r.Write(Beta[0] + "," + Beta[1] + "," + Beta[2] + "\n"); } //RMSE /*FMatrix TPredCombinedp = new FMatrix(N, N); * FMatrix TObsCombined = new FMatrix(N, N); * float Sump = 0.0f; * float Sumo=0.0f; * for (int w = 0; w < TPredCombinedp.M; w++) * { * for (int j = 0; j < TPredCombinedp.N; j++) * { * * for (int k = 0; k < 3; k++) * { * Sump += TPred[k]._M[w, j]; * Sumo += TObsCopy[k]._M[w, j]; * } * TPredCombinedp._M[w, j] = Sump; * TObsCombined._M[w, j] = Sumo; * Sump = 0.0f; * Sumo = 0.0f; * } * }*/ double[] sumT = { 0.0f, 0.0f, 0.0f }; double[] difsq = { 0.0f, 0.0f, 0.0f }; double[] sumV = { 0.0f, 0.0f, 0.0f }; foreach (List <int> subList in positions) { for (int k = 0; k < NumModes; k++) { difsq[k] = (TPred[k]._M[subList[0], subList[1]] - TObsCopy[k]._M[subList[0], subList[1]]) * (TPred[k]._M[subList[0], subList[1]] - TObsCopy[k]._M[subList[0], subList[1]]); sumT[k] = sumT[k] + difsq[k]; sumV[k] = sumV[k] + TPred[k]._M[subList[0], subList[1]]; } if (!File.Exists(SelectedPath + "\\" + "removed_" + nexp + ".csv")) { using (StreamWriter f = File.CreateText(SelectedPath + "\\" + "removed_" + nexp + ".csv")) f.Write(subList[0] + "," + subList[1] + "\n"); } else { using (StreamWriter f = File.AppendText(SelectedPath + "\\" + "removed_" + nexp + ".csv")) f.Write(subList[0] + "," + subList[1] + "\n"); } } double sumAllV = sumV[0] + sumV[1] + sumV[2]; double avg = sumAllV / (3 * positions.Count); double[] sumOfSquares = { 0.0f, 0.0f, 0.0f }; foreach (List <int> subList in positions) { for (int k = 0; k < NumModes; k++) { sumOfSquares[k] += Math.Pow((TPred[k]._M[subList[0], subList[1]] - avg), 2.0); } } double sumOfSquaresT = sumOfSquares[0] + sumOfSquares[1] + sumOfSquares[2]; double sigma = sumOfSquaresT / (3 * (positions.Count - 1)); double sd = Math.Sqrt(sigma); double sumAllT = sumT[0] + sumT[1] + sumT[2]; double rmse = Math.Sqrt(sumAllT / (3 * positions.Count)); if (!File.Exists(SelectedPath + "\\" + "rmse.csv")) { using (StreamWriter sw = File.CreateText(SelectedPath + "\\" + "rmse.csv")) sw.Write(rmse + "," + sigma + "," + sd + "\n"); } else { using (StreamWriter sw = File.AppendText(SelectedPath + "\\" + "rmse.csv")) sw.Write(rmse + "," + sigma + "," + sd + "\n"); } //END RMSE } }
//this is runwithconstraints public void Run(ProgressBar pb) { int N = TObs[0].M; //hopefully [0] and [1] and [2] are the same //set up Beta for modes 0, 1 and 2 to 1.0f Beta = new float[NumModes]; for (int k = 0; k < NumModes; k++) { Beta[k] = 1.0f; } //work out Dobs and Tobs from rows and columns of TObs matrix //These don't ever change so they need to be outside the convergence loop float[] DjObs = new float[N]; float[] OiObs = new float[N]; float Sum; //OiObs for (int i = 0; i < N; i++) { Sum = 0; for (int j = 0; j < N; j++) { for (int k = 0; k < NumModes; k++) { Sum += TObs[k]._M[i, j]; } } OiObs[i] = Sum; } //DjObs for (int j = 0; j < N; j++) { Sum = 0; for (int i = 0; i < N; i++) { for (int k = 0; k < NumModes; k++) { Sum += TObs[k]._M[i, j]; } } DjObs[j] = Sum; } //constraints initialisation B = new float[N]; for (int i = 0; i < N; i++) { B[i] = 1.0f; //hack } float[] Z = new float[N]; for (int j = 0; j < N; j++) { Z[j] = float.MaxValue; if (IsUsingConstraints) { if (Constraints[j] >= 1.0f) //constraints array taking place of Gj (Green Belt) in documentation { //Gj=1 means 0.8 of MSOA land is green belt, so can't be built on //set constraint to original Dj Z[j] = DjObs[j]; } } } //end of constraints initialisation - have now set B[] and Z[] based on IsUsingConstraints, Constraints[] and DObs[] //Instrumentation block - mainly to start off the graph so you have something to look at while the next bit happens /*for (int k = 0; k < NumModes; k++) * InstrumentSetVariable("Beta" + k, Beta[k]); * InstrumentSetVariable("delta", 0); * InstrumentTimeInterval();*/ //end of Instrumentation block FMatrix[] Tij = null; bool Converged = false; int countR = 0; Tij = new FMatrix[NumModes]; for (int k = 0; k < NumModes; k++) { Tij[k] = new FMatrix(N, N); } while (!Converged) { pb.PerformStep(); //Instrumentation block /* for (int k = 0; k < NumModes; k++) * { * InstrumentSetVariable("Beta" + k, Beta[k]); * InstrumentSetVariable("delta" + k, 100); * InstrumentSetVariable("delta", 100); * }*/ //end of instrumentation block bool ConstraintsMet = false; do { //residential constraints ConstraintsMet = true; //unless violated one or more times below int FailedConstraintsCount = 0; //model run //Tij = new FMatrix[NumModes]; for (int k = 0; k < NumModes; k++) //mode loop { //InstrumentStatusText = "Running model for mode " + k; //Tij[k] = new FMatrix(N, N); Parallel.For(0, N, i => //for (int i = 0; i < N; i++) { //denominator calculation which is sum of all modes double denom = 0; for (int kk = 0; kk < NumModes; kk++) //second mode loop { for (int j = 0; j < N; j++) { denom += DjObs[j] * Math.Exp(-Beta[kk] * dis[kk]._M[i, j]); } } //numerator calculation for this mode (k) for (int j = 0; j < N; j++) { Tij[k]._M[i, j] = (float)(B[j] * OiObs[i] * DjObs[j] * Math.Exp(-Beta[k] * dis[k]._M[i, j]) / denom); } } ); } //constraints check if (IsUsingConstraints) { System.Diagnostics.Debug.WriteLine("Constraints test"); // InstrumentStatusText = "Constraints test"; for (int j = 0; j < N; j++) { float Dj = 0; for (int i = 0; i < N; i++) { Dj += Tij[0]._M[i, j] + Tij[1]._M[i, j] + Tij[2]._M[i, j]; } if (Constraints[j] >= 1.0f) //Constraints is taking the place of Gj in the documentation { if ((Dj - Z[j]) >= 0.5) //was >1.0 { B[j] = B[j] * Z[j] / Dj; ConstraintsMet = false; ++FailedConstraintsCount; // InstrumentStatusText = "Constraints violated on " + FailedConstraintsCount + " MSOA zones"; System.Diagnostics.Debug.WriteLine("Dj=" + Dj + " Zj=" + Z[j] + " Bj=" + B[j]); } } } //copy B2 into B ready for the next round //for (int j = 0; j < N; j++) B[j] = B2[j]; } //System.Diagnostics.Debug.WriteLine("FailedConstraintsCount=" + FailedConstraintsCount); //Instrumentation block //for (int k = 0; k < NumModes; k++) // InstrumentSetVariable("Beta" + k, Beta[k]); //InstrumentSetVariable("delta", FailedConstraintsCount); //not technically delta, but I want to see it for testing //InstrumentTimeInterval(); //end of instrumentation block } while (!ConstraintsMet); //calculate mean predicted trips and mean observed trips (this is CBar) float[] CBarPred = new float[NumModes]; float[] CBarObs = new float[NumModes]; float[] delta = new float[NumModes]; for (int k = 0; k < NumModes; k++) { CBarPred[k] = CalculateCBar(ref Tij[k], ref dis[k]); CBarObs[k] = CalculateCBar(ref TObs[k], ref dis[k]); delta[k] = Math.Abs(CBarPred[k] - CBarObs[k]); //the aim is to minimise delta[0]+delta[1]+... } //delta check on all betas (Beta0, Beta1, Beta2) stopping condition for convergence //double gradient descent search on Beta0 and Beta1 and Beta2 Converged = true; countR++; System.Diagnostics.Debug.WriteLine("count = " + countR); for (int k = 0; k < NumModes; k++) { System.Diagnostics.Debug.WriteLine("k=" + k + " - value= " + delta[k] / CBarObs[k]); //if (delta[k] / CBarObs[k] > factor) if (delta[k] / CBarObs[k] > 0.001) { Beta[k] = Beta[k] * CBarPred[k] / CBarObs[k]; Converged = false; } } System.Diagnostics.Debug.WriteLine("Converged = " + Converged); //if (countR == 100) //Converged = true; //Instrumentation block /* for (int k = 0; k < NumModes; k++) * { * InstrumentSetVariable("Beta" + k, Beta[k]); * InstrumentSetVariable("delta" + k, delta[k]); * }*/ float deltat = 0.0f; for (int k = 0; k < NumModes; k++) { deltat += delta[k]; } //InstrumentSetVariable("delta", delta[] + delta[NumModes - 2] + delta[NumModes-1]); //should be a k loop //InstrumentSetVariable("delta", deltat); //InstrumentTimeInterval(); //end of instrumentation block } //Set the output, TPred[] for (int k = 0; k < NumModes; k++) { TPred[k] = Tij[k]; } //debugging: //for (int i = 0; i < N; i++) // System.Diagnostics.Debug.WriteLine("Quant3Model::Run::ConstraintsB," + i + "," + B[i]); }
/// <summary> /// Initialise the model from the Quant2ModelProperties data and run it. /// </summary> /// <param name="ConnectionId"></param> /// <param name="q3mp"></param> public void LoadAndRun(QUANT3ModelProperties q3mp, FolderBrowserDialog f, ProgressBar pb) { // HubConnectionId = ConnectionId; //deserialise the distance and TObs matrices // InstrumentStatusText = "Loading matrices"; /*string[] files = Directory.GetFiles(f.SelectedPath); * System.Windows.Forms.MessageBox.Show("Files found: " + files.Length.ToString(), "Message");*/ /*for (int i=0;i< files.Length;i++) * System.Windows.Forms.MessageBox.Show("Files found: " + files.ElementAt(i), "Message");*/ for (int k = 0; k < NumModes; k++) { dis[k] = FMatrix.DirtyDeserialise(f.SelectedPath + "\\" + q3mp.Indis[k]); TObs[k] = FMatrix.DirtyDeserialise(f.SelectedPath + "\\" + q3mp.InTObs[k]); } ////IsUsingConstraints = q3mp.IsUsingConstraints; if (IsUsingConstraints) { //set up the constraints input data from the green belt and land use data table Constraints = new float[TObs[0].N]; //load constraints file here - convert data table to array based on zonei code DataTable dt = (DataTable)Serialiser.Get(q3mp.InConstraints); int ConstraintCount = 0; foreach (DataRow row in dt.Rows) //this does assume that there is a zonei value for every slot in Constraints[] { int ZoneI = (int)row["zonei"]; float Gj = (float)row["Gj"]; Constraints[ZoneI] = Gj; if (Gj >= 1.0) { ++ConstraintCount; } } System.Diagnostics.Debug.WriteLine("ConstraintCount=" + ConstraintCount); } // InstrumentStatusText = "Starting model run"; pb.PerformStep(); Run(pb); pb.PerformStep(); //write out 3 modes of predicted matrix for (int k = 0; k < NumModes; k++) { TPred[k].DirtySerialise(f.SelectedPath + "\\" + q3mp.OutTPred[k]); } //and a combined mode so the visualisation can see the data //TODO: this block needs to change once the GUI is able to visualise the different modes separately FMatrix TPredCombined = new FMatrix(TPred[0].M, TPred[0].N); for (int i = 0; i < TPredCombined.M; i++) { for (int j = 0; j < TPredCombined.N; j++) { float Sum = 0; for (int k = 0; k < NumModes; k++) { Sum += TPred[k]._M[i, j]; } TPredCombined._M[i, j] = Sum; } } TPredCombined.DirtySerialise(f.SelectedPath + "\\" + q3mp.OutTPredCombined); //end combination block //constraints B weights if we're doing that if (IsUsingConstraints) { Serialiser.Put(q3mp.OutConstraintsB, B); } System.Diagnostics.Debug.WriteLine("DONE"); /*InstrumentStatusText = "Computing model statistics"; * StatisticsDataQ3 sd = new StatisticsDataQ3(); * DataTable PopulationTable = (DataTable)Serialiser.Get(q3mp.InPopulationFilename); * sd.ComputeFromModel(this, ref PopulationTable); * sd.SerialiseToXML(q3mp.InOutStatisticsFilename); * InstrumentStatusText = "Finished"; * InstrumentFinished();*/ }