source: CIVL/examples/contracts/contractsMPI/gaussJordan_elimination_spec.c

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/* FILE: gaussJordan_elimination.c A gaussian-jordan elimination
2 * solver that converts a given matrix to a reduce row echelon form
3 * matrix
4 * RUN : mpicc gaussJordan_elimination.c; mpiexec -n 4 ./a.out numRow numCol m[0][0], m[0][1] ...
5 * VERIFY : civl verify gaussianJordan_elimination.c
6 */
7#include <mpi.h>
8#include <stdlib.h>
9#include <string.h>
10#include <civlc.cvh>
11
12$input int ROWB = 3; // upper bound of numRow
13$input int numRow; // number of rows in the matrix
14$assume(0 < numRow && numRow <= ROWB);
15$input int COLB = 4; // upper bound of numCol
16$input int numCol; // number of columns in the matrix
17$assume(0 < numCol && numCol <= COLB && numCol > numRow);
18$input long double data[numRow][numCol]; // input matrix
19
20/*@ requires \valid(a + (0 .. (numCol * numRow)));
21 @ requires \valid(rowLoc + (0 .. numRow));
22 @ requires numRow > 0 && numCol >0;
23 @ requires \forall int i; 0 <= i < numRow ==> rowLoc[i] = i; rowLoc has initial values
24 @ assigns a[0 .. numRow * numCol], rowLoc[0 .. numRow];
25 @ ensures \forall int i, j; 0 <= i < numRow && 0 <= j < i // Requires that the matrix a is already done
26 @ ==> a[numCol * i + i] == 1 && a[numCol * i + j] == 0; // gaussian elimination.
27 @ ensures \forall int i; 0 <= i < numRow ==>
28 @ \exists int j; 0 <= j < numRow ==> // rowLoc is valid, i.e. each cell in rowLoc has
29 @ rowLoc[j] == i; // a unique value in [0, numRow).
30 @
31*/
32void specElimination(long double *a, int * rowLoc) {
33 long double denom; // a temporary variable will be used to
34 //divide other variables
35
36 for(int i=0; i < numRow; i++) {
37 int leadCol = numCol; // the column where leading 1 be in
38 int rowOfLeadCol = i; // the row where leadCol be in
39
40 /* step 1: Find out the leftmost nonzero column, interchange it with
41 the current iterated row. */
42 for(int j=i; j < numCol; j++) {
43 for(int k=i; k < numRow; k++) {
44 if(a[rowLoc[k]*numCol + j] != 0.0) {
45 leadCol = j;
46 rowOfLeadCol = k;
47 break;
48 }
49 }
50 if(leadCol < numCol)
51 break;
52 }
53 /* If there is no leading 1 in all unprocessed rows, elimination
54 terminates. */
55 if(leadCol == numCol)
56 return;
57 /* step 2: Reducing the leading number to one */
58 denom = a[rowLoc[rowOfLeadCol]*numCol + leadCol];
59 /* If the denominator is zero (or extremely nearing zero), do
60 * nothing. The reason is the denominator is the left-most
61 * nonzero element in all unprocessed rows, if it's zero, all
62 * numbers at that column in all unprocessed rows are zeros. For
63 * such a case, it's no need to do anything in this iteration.
64 */
65 if(denom != 0.0) {
66 for(int j=leadCol; j < numCol; j++) {
67 long double tmp = a[rowLoc[rowOfLeadCol]*numCol + j] / denom;
68
69 a[rowLoc[rowOfLeadCol]*numCol + j] = tmp;
70 }
71 }
72 if(rowOfLeadCol != i) {
73 int tmp;
74
75 tmp = rowLoc[i];
76 rowLoc[i] = rowLoc[rowOfLeadCol];
77 rowLoc[rowOfLeadCol] = tmp;
78 }
79 /* step 3: Add a suitable value to each row below row i so that they have zero at column i */
80 for(int j=i+1; j < numRow; j++) {
81 long double factor = -a[rowLoc[j]*numCol + leadCol];
82
83 for(int k=leadCol; k < numCol; k++)
84 a[rowLoc[j]*numCol + k] += factor * a[rowLoc[i]*numCol + k];
85 }
86 }
87}
88
89/* Working upward to make each leading one the only nonzero number in
90 * which column it be .
91 * Parameters:
92 * a: the matrix in a row echelon form.
93 * rowLoc: a look-up table for rows' locations
94 */
95/*@ requires \valid(a + (0 .. (numCol * numRow)));
96 @ requires \valid(rowLoc + (0 .. numRow));
97 @ requires numRow > 0 && numCol >0;
98 @ requires \forall int i, j; 0 <= i < numRow && 0 <= j < i // Requires that the matrix a is already done
99 @ ==> a[numCol * i + i] == 1 && a[numCol * i + j] == 0; // gaussian elimination.
100 @ requires \forall int i; 0 <= i < numRow ==>
101 @ \exists int j; 0 <= j < numRow ==> // rowLoc is valid, i.e. each cell in rowLoc has
102 @ rowLoc[j] == i; // a unique value in [0, numRow).
103 @ assigns a[0 .. numRow * numCol];
104 @ ensures \forall int i,j; 0 <= i < numRow &&
105 @ 0 <= j < numCol-1 && i != j // Ensures the result is in row-echlon form
106 @ ==> a[numCol * i + i] == 1 && a[numCol * i + j] == 0;
107 @
108 @
109*/
110void specReduce(long double * a, int * rowLoc) {
111 int leadCol; // the column of the leading one in a row
112 int i;
113
114 i = (numRow > (numCol - 1))?(numCol-2):(numRow-1);
115 for(; i>=0; i--) {
116 //Find the leading 1, but if it's an all-zero row, skip it.
117 leadCol = -1;
118 for(int j=i; j<numCol; j++) {
119 if(a[rowLoc[i]*numCol + j] != 0.0) {
120 leadCol = j;
121 break;
122 }
123 }
124 // if it's not an all-zero row, reducing all other numbers in all
125 // rows above at the column at where the leading 1 be.
126 if(leadCol > -1) {
127 for(int j=i-1; j >=0; j--) {
128 long double factor = -a[rowLoc[j]*numCol + leadCol];
129
130 for(int k=leadCol; k < numCol; k++)
131 a[rowLoc[j]*numCol + k] += a[rowLoc[i]*numCol + k] * factor;
132 }
133 }
134 }
135}
Note: See TracBrowser for help on using the repository browser.