Resistance network calculator: Difference between revisions
(→{{header|zkl}}: added code) |
(→{{header|Go}}: Updated in line with the Python 'reference' entry and simplified by replacing *big.Rat with float64 throughout.) |
||
Line 65: | Line 65: | ||
import ( |
import ( |
||
"fmt" |
"fmt" |
||
"math |
"math" |
||
"strconv" |
"strconv" |
||
"strings" |
"strings" |
||
) |
) |
||
func |
func argmax(m [][]float64, i int) int { |
||
col := make([]float64, len(m)) |
|||
max, maxx := -1.0, -1 |
|||
for x := 0; x < len(m); x++ { |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
|||
func gauss(m [][]float64) []float64 { |
|||
n, p := len(m), len(m[0]) |
|||
for i := 0; i < n; i++ { |
for i := 0; i < n; i++ { |
||
k := i + argmax(m[i:n], i) |
|||
k |
m[i], m[k] = m[k], m[i] |
||
t := 1 / m[i][i] |
|||
for j := i + 1; j < p; j++ { |
|||
m[i][j] *= t |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
u.Set(a[i][j]) |
|||
a[i][j].Set(a[k][j]) |
|||
a[k][j].Set(u) |
|||
} |
|||
u.Set(b[i]) |
|||
b[i].Set(b[k]) |
|||
b[k].Set(u) |
|||
} |
} |
||
t.Set(u.Inv(a[i][i])) |
|||
for j := i + 1; j < n; j++ { |
for j := i + 1; j < n; j++ { |
||
t = m[j][i] |
|||
⚫ | |||
} |
|||
m[j][l] -= t * m[i][l] |
|||
⚫ | |||
⚫ | |||
for k := i + 1; k < n; k++ { |
|||
u.Mul(t, a[i][k]) |
|||
a[j][k].Sub(a[j][k], u) |
|||
} |
} |
||
u.Mul(t, b[i]) |
|||
b[j].Sub(b[j], u) |
|||
} |
} |
||
} |
} |
||
for i := n - 1; i >= 0; i-- { |
for i := n - 1; i >= 0; i-- { |
||
for j := 0; j < i; j++ { |
for j := 0; j < i; j++ { |
||
m[j][p-1] -= m[j][i] * m[i][p-1] |
|||
b[j].Sub(b[j], u) |
|||
} |
} |
||
} |
} |
||
col := make([]float64, len(m)) |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
} |
||
func network(n, k0, k1 int, s string) |
func network(n, k0, k1 int, s string) float64 { |
||
m := make([][]float64, n) |
|||
for i := 0; i < n; i++ { |
for i := 0; i < n; i++ { |
||
m[i] = make([]float64, n+1) |
|||
for j := 0; j < n; j++ { |
|||
a[i][j] = new(big.Rat) |
|||
} |
|||
} |
} |
||
for _, resistor := range strings.Split(s, "|") { |
|||
for _, resistor := range arr { |
|||
rarr := strings.Fields(resistor) |
rarr := strings.Fields(resistor) |
||
a, _ := strconv.Atoi(rarr[0]) |
|||
b, _ := strconv.Atoi(rarr[1]) |
|||
ri, _ := strconv.Atoi(rarr[2]) |
ri, _ := strconv.Atoi(rarr[2]) |
||
r := |
r := 1.0 / float64(ri) |
||
a |
m[a][a] += r |
||
m[b][b] += r |
|||
if |
if a > 0 { |
||
m[a][b] -= r |
|||
} |
} |
||
if |
if b > 0 { |
||
m[b][a] -= r |
|||
} |
} |
||
} |
} |
||
m[k0][k0] = 1 |
|||
m[k1][n] = 1 |
|||
return gauss(m)[k1] |
|||
for i := 0; i < n; i++ { |
|||
⚫ | |||
⚫ | |||
b[k1].SetInt64(1) |
|||
⚫ | |||
} |
} |
||
func main() { |
func main() { |
||
var |
var fa [4]float64 |
||
fa[0] = network(7, 0, 1, "0 2 6|2 3 4|3 4 10|4 5 2|5 6 8|6 1 4|3 5 6|3 6 6|3 1 8|2 1 8") |
|||
fa[1] = network(9, 0, 8, "0 1 1|1 2 1|3 4 1|4 5 1|6 7 1|7 8 1|0 3 1|3 6 1|1 4 1|4 7 1|2 5 1|5 8 1") |
|||
fa[2] = network(16, 0, 15, "0 1 1|1 2 1|2 3 1|4 5 1|5 6 1|6 7 1|8 9 1|9 10 1|10 11 1|12 13 1|13 14 1|14 15 1|0 4 1|4 8 1|8 12 1|1 5 1|5 9 1|9 13 1|2 6 1|6 10 1|10 14 1|3 7 1|7 11 1|11 15 1") |
|||
fa[3] = network(4, 0, 3, "0 1 150|0 2 50|1 3 300|2 3 250") |
|||
for _, |
for _, f := range fa { |
||
fmt.Printf("%.6g\n", f) |
|||
if strings.HasSuffix(s, "/1") { |
|||
fmt.Println(s[0 : len(s)-2]) |
|||
} else { |
|||
fmt.Println(s) |
|||
} |
|||
} |
} |
||
}</lang> |
}</lang> |
||
Line 169: | Line 150: | ||
<pre> |
<pre> |
||
10 |
10 |
||
1.5 |
|||
3/2 |
|||
1.85714 |
|||
13/7 |
|||
180 |
180 |
||
</pre> |
</pre> |
Revision as of 15:38, 23 March 2019
- Introduction
Calculate the resistance of any resistor network.
- The network is stated with a string.
- The resistors are separated by a vertical dash.
- Each resistor has
- a starting node
- an ending node
- a resistance
- Background
- Regular 3x3 mesh, using twelve one ohm resistors
0 - 1 - 2 | | | 3 - 4 - 5 | | | 6 - 7 - 8
Battery connection nodes: 0 and 8
assert 3/2 == network(9,0,8,"0 1 1|1 2 1|3 4 1|4 5 1|6 7 1|7 8 1|0 3 1|3 6 1|1 4 1|4 7 1|2 5 1|5 8 1")
- Regular 4x4 mesh, using 24 one ohm resistors
0 - 1 - 2 - 3 | | | | 4 - 5 - 6 - 7 | | | | 8 - 9 -10 -11 | | | | 12 -13 -14 -15
Battery connection nodes: 0 and 15
assert 13/7 == network(16,0,15,"0 1 1|1 2 1|2 3 1|4 5 1|5 6 1|6 7 1|8 9 1|9 10 1|10 11 1|12 13 1|13 14 1|14 15 1|0 4 1|4 8 1|8 12 1|1 5 1|5 9 1|9 13 1|2 6 1|6 10 1|10 14 1|3 7 1|7 11 1|11 15 1")
- Ten resistor network
Battery connection nodes: 0 and 1
assert 10 == network(7,0,1,"0 2 6|2 3 4|3 4 10|4 5 2|5 6 8|6 1 4|3 5 6|3 6 6|3 1 8|2 1 8")
- Wheatstone network
This network is not possible to solve using the previous Resistance Calculator as there is no natural starting point.
assert 180 == network(4,0,3,"0 1 150|0 2 50|1 3 300|2 3 250")
Go
<lang go>package main
import (
"fmt" "math" "strconv" "strings"
)
func argmax(m [][]float64, i int) int {
col := make([]float64, len(m)) max, maxx := -1.0, -1 for x := 0; x < len(m); x++ { col[x] = math.Abs(m[x][i]) if col[x] > max { max = col[x] maxx = x } } return maxx
}
func gauss(m [][]float64) []float64 {
n, p := len(m), len(m[0]) for i := 0; i < n; i++ { k := i + argmax(m[i:n], i) m[i], m[k] = m[k], m[i] t := 1 / m[i][i] for j := i + 1; j < p; j++ { m[i][j] *= t } for j := i + 1; j < n; j++ { t = m[j][i] for l := i + 1; l < p; l++ { m[j][l] -= t * m[i][l] } } } for i := n - 1; i >= 0; i-- { for j := 0; j < i; j++ { m[j][p-1] -= m[j][i] * m[i][p-1] } } col := make([]float64, len(m)) for x := 0; x < len(m); x++ { col[x] = m[x][p-1] } return col
}
func network(n, k0, k1 int, s string) float64 {
m := make([][]float64, n) for i := 0; i < n; i++ { m[i] = make([]float64, n+1) } for _, resistor := range strings.Split(s, "|") { rarr := strings.Fields(resistor) a, _ := strconv.Atoi(rarr[0]) b, _ := strconv.Atoi(rarr[1]) ri, _ := strconv.Atoi(rarr[2]) r := 1.0 / float64(ri) m[a][a] += r m[b][b] += r if a > 0 { m[a][b] -= r } if b > 0 { m[b][a] -= r } } m[k0][k0] = 1 m[k1][n] = 1 return gauss(m)[k1]
}
func main() {
var fa [4]float64 fa[0] = network(7, 0, 1, "0 2 6|2 3 4|3 4 10|4 5 2|5 6 8|6 1 4|3 5 6|3 6 6|3 1 8|2 1 8") fa[1] = network(9, 0, 8, "0 1 1|1 2 1|3 4 1|4 5 1|6 7 1|7 8 1|0 3 1|3 6 1|1 4 1|4 7 1|2 5 1|5 8 1") fa[2] = network(16, 0, 15, "0 1 1|1 2 1|2 3 1|4 5 1|5 6 1|6 7 1|8 9 1|9 10 1|10 11 1|12 13 1|13 14 1|14 15 1|0 4 1|4 8 1|8 12 1|1 5 1|5 9 1|9 13 1|2 6 1|6 10 1|10 14 1|3 7 1|7 11 1|11 15 1") fa[3] = network(4, 0, 3, "0 1 150|0 2 50|1 3 300|2 3 250") for _, f := range fa { fmt.Printf("%.6g\n", f) }
}</lang>
- Output:
10 1.5 1.85714 180
Python
<lang python>from fractions import Fraction
def argmax(m,i): col = [abs(row[i]) for row in m] return col.index(max(col))
def gauss(m): n, p = len(m), len(m[0]) for i in range(n): k = i + argmax(m[i:n],i) m[i], m[k] = m[k], m[i] t = 1 / m[i][i] for j in range(i + 1, p): m[i][j] *= t for j in range(i + 1, n): t = m[j][i] for k in range(i + 1, p): m[j][k] -= t * m[i][k] for i in range(n - 1, -1, -1): for j in range(i): m[j][-1] -= m[j][i] * m[i][-1] return [row[-1] for row in m]
def network(n,k0,k1,s): m = [[0] * (n+1) for i in range(n)] resistors = s.split('|') for resistor in resistors: a,b,r = resistor.split(' ') a,b,r = int(a), int(b), Fraction(1,int(r)) m[a][a] += r m[b][b] += r if a > 0: m[a][b] -= r if b > 0: m[b][a] -= r m[k0][k0] = Fraction(1, 1) m[k1][-1] = Fraction(1, 1) return gauss(m)[k1]
assert 10 == network(7,0,1,"0 2 6|2 3 4|3 4 10|4 5 2|5 6 8|6 1 4|3 5 6|3 6 6|3 1 8|2 1 8") assert 3/2 == network(3*3,0,3*3-1,"0 1 1|1 2 1|3 4 1|4 5 1|6 7 1|7 8 1|0 3 1|3 6 1|1 4 1|4 7 1|2 5 1|5 8 1") assert Fraction(13,7) == network(4*4,0,4*4-1,"0 1 1|1 2 1|2 3 1|4 5 1|5 6 1|6 7 1|8 9 1|9 10 1|10 11 1|12 13 1|13 14 1|14 15 1|0 4 1|4 8 1|8 12 1|1 5 1|5 9 1|9 13 1|2 6 1|6 10 1|10 14 1|3 7 1|7 11 1|11 15 1") assert 180 == network(4,0,3,"0 1 150|0 2 50|1 3 300|2 3 250")</lang>
zkl
GNU Scientific Library
This a tweak of Resistor_mesh#zkl <lang zkl>var [const] GSL=Import.lib("zklGSL"); // libGSL (GNU Scientific Library)
fcn network(n,k0,k1,mesh){
A:=GSL.Matrix(n,n); // zero filled foreach resistor in (mesh.split("|")){ a,b,r := resistor.split().apply("toInt"); r=1.0/r; A[a,a]=A[a,a] + r; A[b,b]=A[b,b] + r; if(a>0) A[a,b]=A[a,b] - r; if(b>0) A[b,a]=A[b,a] - r; } b:=GSL.Vector(n); // zero filled b[k1]=1; A.AxEQb(b)[k1];
}</lang> <lang zkl>network(7,0,1,"0 2 6|2 3 4|3 4 10|4 5 2|5 6 8|6 1 4|3 5 6|3 6 6|3 1 8|2 1 8") .println();
network(3*3,0,3*3-1,"0 1 1|1 2 1|3 4 1|4 5 1|6 7 1|7 8 1|0 3 1|3 6 1|1 4 1|4 7 1|2 5 1|5 8 1") .println();
network(4*4,0,4*4-1,"0 1 1|1 2 1|2 3 1|4 5 1|5 6 1|6 7 1|8 9 1|9 10 1|10 11 1|12 13 1|13 14 1|14 15 1|0 4 1|4 8 1|8 12 1|1 5 1|5 9 1|9 13 1|2 6 1|6 10 1|10 14 1|3 7 1|7 11 1|11 15 1") .println();
network(4,0,3,"0 1 150|0 2 50|1 3 300|2 3 250") .println();</lang>
- Output:
10 1.5 1.85714 180