public Row(Row r2) { diag = r2.diag; diagCol = r2.diagCol; val = new List<double>(r2.val); col = new List<int>(r2.col); }
//adding r2 to r1, so diagonal element follow r2 //assuming r2[r1.diagCol] is zero. This is true in our //pivoting calculation/elimination in general public static Row Addition(Row r1, Row r2, int denseNcol) { var r3 = new Row { diag = r1.diag, diagCol = r1.diagCol, col= new List<int>(), val = new List<double>() }; //auxiliary dense vector helps to record position info bool[] auxiDense = new bool[denseNcol]; //register location of nonzeros of r2. For zeros, take value as -1 for(int i=0; i<r2.col.Count;i++) { auxiDense[r2.col[i]] = true; } //add matching nonzeros of r2 and r1 into r3; bool flag = false;//to detect diagnal position matching for (int i = 0; i < r1.col.Count;i++) { int j = r1.col[i]; if(auxiDense[j]) { r3.col.Add(r1.col[i]); r3.val.Add(r1.val[i]+r2.val[i]); } auxiDense[j] = false; if((!flag) && r1.col[i]==r2.diagCol) { r3.col.Add(r1.col[i]); r3.val.Add(r1.val[i] + r2.val[i]); flag = true; } } //if diagonal element of r2 doesnot matching if(!flag) { r3.col.Add(r2.diagCol); r3.val.Add(r2.diag); } for (int i = 0; i < r2.col.Count;i++) { int j = r2.col[i]; if(auxiDense[j]) { r3.col.Add(r2.diagCol); r3.val.Add(r2.diag); } auxiDense[j] = false; } return r3; }
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 SparseMatrixMDP GaussianJordenElimination(SparseMatrixMDP smatrixMdp) { var r = smatrixMdp.Ngroup; var groups = smatrixMdp.Groups; for (int i = 0; i < r; i++) //operating on each group, i can take as pivot position { var currentGroup = groups[i]; //rows in ith group should normalized according to the element in its pivot position (ith group, ith column) Debug.Assert(groups != null, "groups != null"); foreach (Row currentRow1 in currentGroup.RowsInSameGroup) { if (currentRow1.col[0] == i) //TODO:I think this info is redundant { if (Math.Abs(currentRow1.val[0] - 1) > EPSILON) { for (int k = 1; k < currentRow1.val.Count; k++) { currentRow1.val[k] = currentRow1.val[k]/currentRow1.val[0]; } } currentRow1.col.RemoveAt(0); currentRow1.val.RemoveAt(0); } } //currentRow1.colIndexCurrentRow = currentRow1.col.BinarySearch(i); //using current row to deduct every rows in other group if corresponding element (column i in dense matrix) is not zero //follow upper triangular form. for (int j = 0; j < r; j++) //scan all groups { if (j == i) { continue; } //update rows in group j var pivotGroup = groups[j]; var removeCollection = new HashSet<Row>(); var addCollection = new HashSet<Row>(); foreach (Row pivotRow in pivotGroup.RowsInSameGroup) { if (pivotRow.col[0] == i) //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]; //var hashset1 = new HashSet<int>(pivotRow.col); //hashset1.UnionWith(new HashSet<int>(currentRow.col)); pivotRow.col.RemoveAt(0); pivotRow.val.RemoveAt(0); foreach (Row currentRow in currentGroup.RowsInSameGroup) { // bool flag; if (!CheckDictionarySubset(pivotRow.SelectionMemoryInGroups, currentRow.SelectionMemoryInGroups)) { continue; } var r3 = new Row { diag = pivotRow.diag, diagCol = pivotRow.diagCol, // val = new List<double>(hashset1.Count), // col = hashset1.ToList(), Index = pivotRow.Index, }; //add elements in colValuePair var hashset1 = new HashSet<int>(currentRow.col); hashset1.UnionWith(new HashSet<int>(pivotRow.col)); var colValuePair = new Dictionary<int, double>(hashset1.ToDictionary(item => item, item => 0.0)); for (int inneri = 0; inneri < currentRow.col.Count; inneri++) { if (Math.Abs(currentRow.val[inneri]) > EPSILON) { colValuePair[currentRow.col[inneri]] += currentRow.val[inneri]*t; } } //add workingRow to r3 //var hashset2 = new HashSet<int>(); for (int inneri = 0; inneri < pivotRow.col.Count; inneri++) { double m = colValuePair[pivotRow.col[inneri]] + pivotRow.val[inneri]; if (Math.Abs(m) > EPSILON) { colValuePair[pivotRow.col[inneri]] = m; } } r3.col = new List<int>(colValuePair.Keys); r3.val = new List<double>(colValuePair.Values); // r3.SelectionMemoryInGroups = new Dictionary<Group, Row>(pivotRow.SelectionMemoryInGroups); // r3.SelectionMemoryInGroups[currentGroup] = currentRow; r3.SelectionMemoryInGroups = new Dictionary<int,int>(pivotRow.SelectionMemoryInGroups); r3.SelectionMemoryInGroups[currentGroup.Index] = currentRow.Index; //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; //pivotGroup.RowsInSameGroup.Add(r3); addCollection.Add(r3); if(pivotRow.SelectionMemoryInGroups.ContainsKey(currentGroup.Index)) { break; } //If pivotRow contains currentGroup index, and currentRow can work with pivotRow, //that means the rest of rows in the group are not that useful. } removeCollection.Add(pivotRow); } } //update rows in current group foreach (Row row in removeCollection) { pivotGroup.RowsInSameGroup.Remove(row); } foreach (Row row in addCollection) { pivotGroup.RowsInSameGroup.Add(row); } } Debug.WriteLine(smatrixMdp); } return smatrixMdp; }
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; }
public Row DeepCopy(Row r2) { var r = new Row { diag = r2.diag, diagCol = r2.diagCol, val = new List<double>(r2.val), col = new List<int>(r2.col) }; return r; }
public static Row Addition2(Row r1, Row r2) { var hashset1 = new HashSet<int>(r1.col); hashset1.UnionWith(new HashSet<int>(r2.col)); var r3 = new Row { diag = r1.diag, diagCol = r1.diagCol, //col = hashset1.ToList(), //val = new List<double>(hashset1.Count) }; var mapCol2ValIndex = new SortedDictionary<int, double>(); foreach (int i in hashset1) { mapCol2ValIndex.Add(i,0); } //copy r2 to r3 for (int i = 0; i < r2.col.Count; i++) { mapCol2ValIndex[r2.col[i]]+=r2.val[i]; } //copy r1 to r3 for (int i = 0; i < r1.col.Count; i++) { mapCol2ValIndex[r1.col[i]] += r1.val[i]; } r3.col = new List<int>(mapCol2ValIndex.Keys); r3.val = new List<double>(mapCol2ValIndex.Values); r3.diag = r3.col.Contains(r3.diagCol) ? mapCol2ValIndex[r3.diagCol] : 0; return r3; //var hashset1 = new HashSet<int> (r1.col); //hashset1.UnionWith(new HashSet<int>(r2.col)); //var r3 = new Row //{ // diag = r1.diag, // diagCol = r1.diagCol, // col = hashset1.ToList(), // val = new List<double>(hashset1.Count) //}; //var mapCol2ValIndex = new SortedDictionary<int, int>(); //for (int i = 0; i < r3.col.Count;i++) //{ // mapCol2ValIndex.Add(r3.col[i],i); // r3.val.Add(0); //initialization //} ////copy r2 to r3 //for (int i = 0; i < r2.col.Count;i++) //{ // int j = r2.col[i]; // int k = mapCol2ValIndex[j]; // r3.val[k] += r2.val[i]; //} ////copy r1 to r3 //for (int i = 0; i < r1.col.Count; i++) //{ // int j = r1.col[i]; // r3.val[mapCol2ValIndex[j]] += r1.val[i]; //} //r3.diag = r3.col.Contains(r3.diagCol) ? r3.val[mapCol2ValIndex[r3.diagCol]] : 0; //return r3; }