public static SparseMatrix Read2MatrixToSparseMatrix(List<DTMCState> scc, List<DTMCState> output) { int inputSize = scc.Count; int outputSize = output.Count; int column = inputSize + outputSize; var matrix = new SparseMatrix(inputSize,column); var dtmcState2Number = new Dictionary<DTMCState, int>(column); //var number2dtmcState = new Dictionary<int, DTMCState>(column); //assign coordination first int i = 0; foreach (DTMCState mdpState in scc) { dtmcState2Number.Add(mdpState, i); i++; } foreach (DTMCState mdpState in output) { dtmcState2Number.Add(mdpState, i); i++; } //assign rows to matrix foreach (DTMCState dtmcState in scc) { int rowCoord = dtmcState2Number[dtmcState]; //update every valued rows elements var compressedRow = new SortedDictionary<int, double> {{rowCoord, 1}}; foreach (KeyValuePair<double, DTMCState> pair in dtmcState.Transitions) { int colCoord = dtmcState2Number[pair.Value]; if(colCoord==rowCoord) { compressedRow[rowCoord] += -pair.Key; }else { compressedRow.Add(colCoord, -pair.Key); } } var row = new Row(new List<double>(compressedRow.Values), new List<int>(compressedRow.Keys)) { diag = compressedRow[rowCoord], diagCol = rowCoord }; matrix.Rows.Add(row); //update diagnoal elements } return matrix; }
public static SparseMatrix GaussianJordenElimination(SparseMatrix smatrix) { //int r = smatrix.Nrows; //for (int i = 0; i < r; i++) //{ // //row value divide pivot element // var currentRow = smatrix.Rows[i]; // if (Math.Abs(currentRow.diag) > EPSILON) // { // if (Math.Abs(currentRow.diag - 1) > EPSILON) // { // for (int k = 0; k < currentRow.val.Count; k++) // { // currentRow.val[k] = currentRow.val[k]/currentRow.diag; // } // } // var colIndexCurrentRow = currentRow.col.BinarySearch(i); // //using current row to deduct every other rows in smatrix if corresponding element in row i is not zero // for (int j = 0; j < r; j++) // { // if(j==i) // { // continue; // } // var pivotRow = smatrix.Rows[j]; // int colIndexPivot = pivotRow.col.BinarySearch(i); // if (colIndexPivot >= 0 && Math.Abs(pivotRow.val[colIndexPivot] - 0) > EPSILON) // //index of col for column value in dense matrix equal to pivot element. if value is zero, it will not be found // { // double t = -pivotRow.val[colIndexPivot]; // //var hashset1 = new HashSet<int>(pivotRow.col); // //hashset1.UnionWith(new HashSet<int>(currentRow.col)); // var r3 = new Row // { // diag = pivotRow.diag, // diagCol = pivotRow.diagCol, // // val = new List<double>(hashset1.Count), // // col = hashset1.ToList(), // }; // //foreach (int i1 in hashset1) // //{ // // colValuePair.Add(i1,0); // //} // //add elements in colValuePair // var hashset1 = new HashSet<int>(); // for (int inneri = colIndexCurrentRow; inneri < currentRow.col.Count; inneri++) // { // hashset1.Add(currentRow.col[inneri]); // } // //add workingRow to r3 // var hashset2 = new HashSet<int>(); // for (int inneri =colIndexPivot; inneri < pivotRow.col.Count; inneri++) // { // hashset2.Add(pivotRow.col[inneri]); // } // hashset2.UnionWith(hashset1); // var colValuePair = new SortedDictionary<int, double>(); // foreach (int i1 in hashset2) // { // colValuePair.Add(i1,0); // } // //add currentRow*t to r3 // //inneri starts from colValue as it only needs to update elements after colValue // for (int inneri = colIndexCurrentRow; inneri < currentRow.col.Count; inneri++) // { // colValuePair[currentRow.col[inneri]] += currentRow.val[inneri]*t; // } // //add workingRow to r3 // for (int inneri = colIndexPivot; inneri < pivotRow.col.Count; inneri++) // { // colValuePair[pivotRow.col[inneri]] += pivotRow.val[inneri]; // } // //remove new introduced zeros //Comments: this is not productive. // //var hashsetZeros = new HashSet<int>(); // //foreach (KeyValuePair<int, double> keyValuePair in colValuePair) // //{ // // if (Math.Abs(keyValuePair.Value) < EPSILON) // // { // // hashsetZeros.Add(keyValuePair.Key); // // } // //} // //foreach (int hashsetZero in hashsetZeros) // //{ // // colValuePair.Remove(hashsetZero); // //} // r3.col = new List<int>(colValuePair.Keys); // r3.val = new List<double>(colValuePair.Values); // //update diag elements in that row. After row adding, the pivot element/diag info is redundant. // // r3.diag = r3.col.Contains(r3.diagCol) ? colValuePair[r3.diagCol] : 0; // smatrix.Rows[j] = r3; // Debug.WriteLine(smatrix); // } // } // } //} //return smatrix; //the algo can be simplified because of the property for this matrix. The pivot position is positive and nozero. //we also assume the first element in the column gives the right index (pivot colum index) //for each elimiantion operation //there will no redundant row, therefore, after elimiantion, there will no be the case for all elements in a row being //zeros int r = smatrix.Nrows; for (int i = 0; i < r; i++) { //row value divide pivot element var currentRow = smatrix.Rows[i]; //if (Math.Abs(currentRow.diag) > EPSILON) if(currentRow.col[0]==i) //assert current.Row.col.count>0; { if (Math.Abs(currentRow.val[0] - 1) > EPSILON) { for (int k = 1; k < currentRow.val.Count; k++) { currentRow.val[k] = currentRow.val[k] / currentRow.val[0]; } } //remove the pivot position element, dia, diacol is redundant now and remove them currentRow.col.RemoveAt(0); currentRow.val.RemoveAt(0); // var colIndexCurrentRow = currentRow.col.BinarySearch(i); //by right, this should always be the first element in the row // var colIndexCurrentRow = currentRow.col[0]; //using current row to deduct every other rows in smatrix if corresponding element in row i is not zero for (int j = 0; j < r; j++) { if (j == i) { continue; } var pivotRow = smatrix.Rows[j]; //int colIndexPivot = pivotRow.col.BinarySearch(i); //int colIndexPivot = pivotRow.col[0]; // if (colIndexPivot >= 0 && Math.Abs(pivotRow.val[colIndexPivot] - 0) > EPSILON) if(pivotRow.col[0]==i) //this actually guarantees the value nonzero, //index of col for column value in dense matrix equal to pivot element. if value is zero, it will not be found { double t = -pivotRow.val[0]; pivotRow.col.RemoveAt(0); pivotRow.val.RemoveAt(0); //diag, diagcol are also redundant. //var hashset1 = new HashSet<int>(pivotRow.col); //hashset1.UnionWith(new HashSet<int>(currentRow.col)); var r3 = new Row { diag = pivotRow.diag, diagCol = pivotRow.diagCol, // val = new List<double>(hashset1.Count), // col = hashset1.ToList(), }; //add elements in colValuePair var hashset1 = new HashSet<int>(currentRow.col); hashset1.UnionWith(new HashSet<int>(pivotRow.col)); var colValuePair = new SortedDictionary<int, double>(); foreach (int i1 in hashset1) { colValuePair.Add(i1,0); } //add currentRow*t to r3 //inneri starts from colValue as it only needs to update elements after colValue for (int inneri = 0; inneri < currentRow.col.Count; inneri++) { if (Math.Abs(currentRow.val[inneri]) > EPSILON) //make sure zero is not added { colValuePair[currentRow.col[inneri]] += currentRow.val[inneri] * t; } } //add workingRow to r3 for (int inneri = 0; inneri < pivotRow.col.Count; inneri++) { double m = colValuePair[pivotRow.col[inneri]] + pivotRow.val[inneri]; if (Math.Abs(m) > EPSILON) //make sure zero is not added { colValuePair[pivotRow.col[inneri]] = m; } } r3.col = new List<int>(colValuePair.Keys); r3.val = new List<double>(colValuePair.Values); //update diag elements in that row. After row adding, the pivot element/diag info is redundant. // r3.diag = r3.col.Contains(r3.diagCol) ? colValuePair[r3.diagCol] : 0; smatrix.Rows[j] = r3; Debug.WriteLine(smatrix); } } } } return smatrix; }