Skip to content

Commit 63af5ac

Browse files
ravenbluedragonleios
authored andcommitted
Added implementation of Gaussian Elimination in Go (#552)
1 parent 7d15d3b commit 63af5ac

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed

CONTRIBUTORS.md

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ This file lists everyone, who contributed to this repo and wanted to show up her
4141
- crafter312
4242
- Christopher Milan
4343
- Vexatos
44+
- Raven-Blue Dragon
4445
- Björn Heinrichs
4546
- Olav Sundfør
4647
- dovisutu
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Package demonstrates Gaussian Elimination
2+
package main
3+
4+
import (
5+
"fmt"
6+
"math"
7+
)
8+
9+
func gaussianElimination(a [][]float64) {
10+
singular := false
11+
rows := len(a)
12+
cols := len(a[0])
13+
14+
for c, r := 0, 0; c < cols && r < rows; c++ {
15+
// 1. find highest value in column below row to be pivot
16+
p, highest := r, 0.
17+
for i, row := range a[r:] {
18+
if abs := math.Abs(row[c]); abs > highest {
19+
p = r + i
20+
highest = abs
21+
}
22+
}
23+
highest = a[p][c] // correct sign
24+
25+
if highest == 0. {
26+
if !singular {
27+
singular = true
28+
fmt.Println("This matrix is singular.")
29+
}
30+
continue
31+
}
32+
33+
// 2. swap pivot with current row
34+
if p != r {
35+
a[r], a[p] = a[p], a[r]
36+
}
37+
38+
for _, row := range a[r+1:] {
39+
// 3. find fraction from pivot value
40+
frac := row[c] / highest
41+
42+
// 4. subtract row to set rest of column to zero
43+
for j := range row {
44+
row[j] -= frac * a[r][j]
45+
}
46+
47+
// 5. ensure col goes to zero (no float rounding)
48+
row[c] = 0.
49+
}
50+
51+
r++
52+
}
53+
}
54+
55+
func gaussJordan(a [][]float64) {
56+
for r := len(a) - 1; r >= 0; r-- {
57+
// Find pivot col
58+
p := -1
59+
for c, cell := range a[r] {
60+
if cell != 0. {
61+
p = c
62+
break
63+
}
64+
}
65+
if p < 0 {
66+
continue
67+
}
68+
69+
// Scale pivot r to 1.
70+
scale := a[r][p]
71+
for c := range a[r][p:] {
72+
a[r][p+c] /= scale
73+
}
74+
// Subtract pivot row from each row above
75+
for _, row := range a[:r] {
76+
scale = row[p]
77+
for c, cell := range a[r][p:] {
78+
row[p+c] -= cell * scale
79+
}
80+
}
81+
}
82+
}
83+
84+
func backSubstitution(a [][]float64) []float64 {
85+
rows := len(a)
86+
cols := len(a[0])
87+
x := make([]float64, rows)
88+
for r := rows - 1; r >= 0; r-- {
89+
sum := 0.
90+
91+
for c := cols - 2; c > r; c-- {
92+
sum += x[c] * a[r][c]
93+
}
94+
95+
x[r] = (a[r][cols-1] - sum) / a[r][r]
96+
}
97+
return x
98+
}
99+
100+
func printMatrixRow(row []float64) {
101+
fmt.Print("[")
102+
for _, cell := range row {
103+
fmt.Printf("%9.4f ", cell)
104+
}
105+
fmt.Println("]")
106+
}
107+
108+
func printMatrix(a [][]float64) {
109+
for _, row := range a {
110+
printMatrixRow(row)
111+
}
112+
fmt.Println()
113+
}
114+
115+
func main() {
116+
a := [][]float64{
117+
{2, 3, 4, 6},
118+
{1, 2, 3, 4},
119+
{3, -4, 0, 10},
120+
}
121+
fmt.Println("Original Matrix:")
122+
printMatrix(a)
123+
124+
fmt.Println("Gaussian elimination:")
125+
gaussianElimination(a)
126+
printMatrix(a)
127+
128+
gaussJordan(a)
129+
fmt.Println("Gauss-Jordan:")
130+
printMatrix(a)
131+
132+
fmt.Println("Solutions are:")
133+
x := backSubstitution(a)
134+
printMatrixRow(x)
135+
}

contents/gaussian_elimination/gaussian_elimination.md

+8
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,8 @@ When we put everything together, it looks like this:
419419
[import:5-47, lang:"java"](code/java/GaussianElimination.java)
420420
{% sample lang="js" %}
421421
[import:1-38, lang:"javascript"](code/javascript/gaussian_elimination.js)
422+
{% sample lang="go" %}
423+
[import:9-53, lang:"go"](code/go/gaussian_elimination.go)
422424
{% endmethod %}
423425

424426
To be clear: if the matrix is found to be singular during this process, the system of equations is either over- or under-determined and no general solution exists.
@@ -459,6 +461,8 @@ This code does not exist yet in rust, so here's Julia code (sorry for the inconv
459461
[import:49-70, lang:"java"](code/java/GaussianElimination.java)
460462
{% sample lang="js" %}
461463
[import:57-76, lang:"javascript"](code/javascript/gaussian_elimination.js)
464+
{% sample lang="go" %}
465+
[import:55-82, lang:"go"](code/go/gaussian_elimination.go)
462466
{% endmethod %}
463467

464468
As a note: Gauss-Jordan elimination can also be used to find the inverse of a matrix by following the same procedure to generate a reduced row echelon matrix, but with an identity matrix on the other side instead of the right-hand side of each equation.
@@ -501,6 +505,8 @@ In code, it looks like this:
501505
[import:72-87, lang:"java"](code/java/GaussianElimination.java)
502506
{% sample lang="js" %}
503507
[import:40-55, lang:"javascript"](code/javascript/gaussian_elimination.js)
508+
{% sample lang="go" %}
509+
[import:84-98, lang:"go"](code/go/gaussian_elimination.go)
504510
{% endmethod %}
505511

506512
## Visual Representation
@@ -569,6 +575,8 @@ Here's a video describing Gaussian elimination:
569575
[import, lang:"java"](code/java/GaussianElimination.java)
570576
{% sample lang="js" %}
571577
[import, lang:"javascript"](code/javascript/gaussian_elimination.js)
578+
{% sample lang="go" %}
579+
[import, lang:"go"](code/go/gaussian_elimination.go)
572580
{% endmethod %}
573581

574582

0 commit comments

Comments
 (0)