tasks a-s
This commit is contained in:
parent
47bf37c096
commit
b83f433714
12433 changed files with 156208 additions and 123 deletions
5
Task/Resistor-mesh/0DESCRIPTION
Normal file
5
Task/Resistor-mesh/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
[[image:resistor-mesh.svg]]
|
||||
|
||||
Given 10 × 10 grid nodes interconnected by 1Ω resistors as shown, find the resistance between point A and B.
|
||||
|
||||
See also [[http://xkcd.com/356/]]
|
||||
69
Task/Resistor-mesh/Ada/resistor-mesh.ada
Normal file
69
Task/Resistor-mesh/Ada/resistor-mesh.ada
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
procedure ResistMesh is
|
||||
H, W : constant Positive := 10;
|
||||
rowA, colA : constant Positive := 2; -- row/col indexed from 1
|
||||
rowB : constant Positive := 7;
|
||||
colB : constant Positive := 8;
|
||||
|
||||
type Ntype is (A, B, Free);
|
||||
type Vtype is digits 15;
|
||||
type Node is record
|
||||
volt : Vtype := 0.0;
|
||||
name : Ntype := Free;
|
||||
end record;
|
||||
type NodeMesh is array (Positive range <>, Positive range <>) of Node;
|
||||
package IIO is new Ada.Text_IO.Float_IO (Vtype);
|
||||
mesh, dmesh : NodeMesh (1 .. H, 1 .. W);
|
||||
curA, curB, diff : Vtype;
|
||||
|
||||
procedure set_AB (mesh : in out NodeMesh) is begin
|
||||
mesh (rowA, colA).volt := 1.0; mesh (rowA, colA).name := A;
|
||||
mesh (rowB, colB).volt := -1.0; mesh (rowB, colB).name := B;
|
||||
end set_AB;
|
||||
|
||||
function sides (i : Positive; j : Positive) return Vtype is
|
||||
s : Integer := 0;
|
||||
begin
|
||||
if i /= 1 and i /= H then s := s + 2; else s := s + 1; end if;
|
||||
if j /= 1 and j /= W then s := s + 2; else s := s + 1; end if;
|
||||
return Vtype (s);
|
||||
end sides;
|
||||
|
||||
procedure calc_diff (mesh : NodeMesh; dmesh : out NodeMesh;
|
||||
total : out Vtype) is
|
||||
n : Natural;
|
||||
v : Vtype := 0.0;
|
||||
begin
|
||||
total := 0.0;
|
||||
for i in Positive range 1 .. H loop
|
||||
for j in Positive range 1 .. W loop
|
||||
n := 0; v := 0.0;
|
||||
if i /= 1 then v := v + mesh (i - 1, j).volt; n := n + 1; end if;
|
||||
if j /= 1 then v := v + mesh (i, j - 1).volt; n := n + 1; end if;
|
||||
if i < H then v := v + mesh (i + 1, j).volt; n := n + 1; end if;
|
||||
if j < W then v := v + mesh (i, j + 1).volt; n := n + 1; end if;
|
||||
v := mesh (i, j).volt - v / Vtype (n);
|
||||
dmesh (i, j).volt := v;
|
||||
if mesh (i, j).name = Free then total := total + v ** 2; end if;
|
||||
end loop;
|
||||
end loop;
|
||||
end calc_diff;
|
||||
|
||||
begin
|
||||
|
||||
loop
|
||||
set_AB (mesh);
|
||||
calc_diff (mesh, dmesh, diff);
|
||||
exit when diff < 1.0e-40;
|
||||
for i in Positive range 1 .. H loop
|
||||
for j in Positive range 1 .. W loop
|
||||
mesh (i, j).volt := mesh (i, j).volt - dmesh (i, j).volt;
|
||||
end loop;
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
curA := dmesh (rowA, colA).volt * sides (rowA, colA);
|
||||
curB := dmesh (rowB, colB).volt * sides (rowB, colB);
|
||||
diff := 4.0 / (curA - curB);
|
||||
IIO.Put (diff, Exp => 0); New_Line;
|
||||
end ResistMesh;
|
||||
31
Task/Resistor-mesh/BBC-BASIC/resistor-mesh.bbc
Normal file
31
Task/Resistor-mesh/BBC-BASIC/resistor-mesh.bbc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
INSTALL @lib$+"ARRAYLIB"
|
||||
*FLOAT 64
|
||||
@% = &F0F
|
||||
|
||||
PRINT "Resistance = "; FNresistormesh(10, 10, 1, 1, 7, 6) " ohms"
|
||||
END
|
||||
|
||||
DEF FNresistormesh(ni%, nj%, ai%, aj%, bi%, bj%)
|
||||
LOCAL c%, i%, j%, k%, n%, A(), B()
|
||||
n% = ni% * nj%
|
||||
DIM A(n%-1, n%-1), B(n%-1, 0)
|
||||
FOR i% = 0 TO ni%-1
|
||||
FOR j% = 0 TO nj%-1
|
||||
k% = i% * nj% + j%
|
||||
IF i% = ai% AND j% = aj% THEN
|
||||
A(k%, k%) = 1
|
||||
ELSE
|
||||
c% = 0
|
||||
IF (i% + 1) < ni% c% += 1 : A(k%, k% + nj%) = -1
|
||||
IF i% > 0 c% += 1 : A(k%, k% - nj%) = -1
|
||||
IF (j% + 1) < nj% c% += 1 : A(k%, k% + 1) = -1
|
||||
IF j% > 0 c% += 1 : A(k%, k% - 1) = -1
|
||||
A(k%, k%) = c%
|
||||
ENDIF
|
||||
NEXT
|
||||
NEXT
|
||||
k% = bi% * nj% + bj%
|
||||
B(k%, 0) = 1
|
||||
PROC_invert(A())
|
||||
B() = A().B()
|
||||
= B(k%, 0)
|
||||
65
Task/Resistor-mesh/C/resistor-mesh.c
Normal file
65
Task/Resistor-mesh/C/resistor-mesh.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define S 10
|
||||
typedef struct { double v; int fixed; } node;
|
||||
|
||||
#define each(i, x) for(i = 0; i < x; i++)
|
||||
node **alloc2(int w, int h)
|
||||
{
|
||||
int i;
|
||||
node **a = calloc(1, sizeof(node*)*h + sizeof(node)*w*h);
|
||||
each(i, h) a[i] = i ? a[i-1] + w : (node*)(a + h);
|
||||
return a;
|
||||
}
|
||||
|
||||
void set_boundary(node **m)
|
||||
{
|
||||
m[1][1].fixed = 1; m[1][1].v = 1;
|
||||
m[6][7].fixed = -1; m[6][7].v = -1;
|
||||
}
|
||||
|
||||
double calc_diff(node **m, node **d, int w, int h)
|
||||
{
|
||||
int i, j, n;
|
||||
double v, total = 0;
|
||||
each(i, h) each(j, w) {
|
||||
v = 0; n = 0;
|
||||
if (i) v += m[i-1][j].v, n++;
|
||||
if (j) v += m[i][j-1].v, n++;
|
||||
if (i+1 < h) v += m[i+1][j].v, n++;
|
||||
if (j+1 < w) v += m[i][j+1].v, n++;
|
||||
|
||||
d[i][j].v = v = m[i][j].v - v / n;
|
||||
if (!m[i][j].fixed) total += v * v;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
double iter(node **m, int w, int h)
|
||||
{
|
||||
node **d = alloc2(w, h);
|
||||
int i, j;
|
||||
double diff = 1e10;
|
||||
double cur[] = {0, 0, 0};
|
||||
|
||||
while (diff > 1e-24) {
|
||||
set_boundary(m);
|
||||
diff = calc_diff(m, d, w, h);
|
||||
each(i,h) each(j, w) m[i][j].v -= d[i][j].v;
|
||||
}
|
||||
|
||||
each(i, h) each(j, w)
|
||||
cur[ m[i][j].fixed + 1 ] += d[i][j].v *
|
||||
(!!i + !!j + (i < h-1) + (j < w -1));
|
||||
|
||||
free(d);
|
||||
return (cur[2] - cur[0])/2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
node **mesh = alloc2(S, S);
|
||||
printf("R = %g\n", 2 / iter(mesh, S, S));
|
||||
return 0;
|
||||
}
|
||||
76
Task/Resistor-mesh/D/resistor-mesh.d
Normal file
76
Task/Resistor-mesh/D/resistor-mesh.d
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import std.stdio, std.traits;
|
||||
|
||||
enum Node.FP differenceThreshold = 1e-40;
|
||||
|
||||
struct Node {
|
||||
alias real FP;
|
||||
enum Kind : size_t { free, A, B }
|
||||
|
||||
FP voltage = 0.0;
|
||||
private Kind kind = Kind.free;
|
||||
|
||||
@property Kind fixed() const pure nothrow { return kind; }
|
||||
}
|
||||
|
||||
Node.FP iter(size_t w, size_t h)(ref Node[w][h] m) pure nothrow {
|
||||
static void enforceBoundaryConditions(ref Node[w][h] m)
|
||||
pure nothrow {
|
||||
m[1][1].voltage = 1.0;
|
||||
m[6][7].voltage = -1.0;
|
||||
}
|
||||
|
||||
static Node.FP calcDifference(in ref Node[w][h] m,
|
||||
ref Node[w][h] d) pure nothrow {
|
||||
Node.FP total = 0.0;
|
||||
|
||||
foreach (i; 0 .. h)
|
||||
foreach (j; 0 .. w) {
|
||||
Node.FP v = 0.0;
|
||||
{
|
||||
size_t n = 0;
|
||||
if (i != 0) { v += m[i - 1][j].voltage; n++; }
|
||||
if (j != 0) { v += m[i][j - 1].voltage; n++; }
|
||||
if (i < h-1) { v += m[i + 1][j].voltage; n++; }
|
||||
if (j < w-1) { v += m[i][j + 1].voltage; n++; }
|
||||
v = m[i][j].voltage - v / n;
|
||||
}
|
||||
|
||||
d[i][j].voltage = v;
|
||||
if (m[i][j].fixed == Node.Kind.free)
|
||||
total += v ^^ 2;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
Node[w][h] difference;
|
||||
|
||||
while (true) {
|
||||
enforceBoundaryConditions(m);
|
||||
if (calcDifference(m, difference) < differenceThreshold)
|
||||
break;
|
||||
foreach (i, const(Node[]) di; difference)
|
||||
foreach (j, ref const(Node) dij; di)
|
||||
m[i][j].voltage -= dij.voltage;
|
||||
}
|
||||
|
||||
Node.FP[EnumMembers!(Node.Kind).length] cur = 0.0;
|
||||
foreach (i, const(Node[]) di; difference)
|
||||
foreach (j, ref const(Node) dij; di)
|
||||
cur[m[i][j].fixed] += dij.voltage *
|
||||
(!!i + !!j + (i < h-1) + (j < w-1));
|
||||
|
||||
return (cur[Node.Kind.A] - cur[Node.Kind.B]) / 2.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
enum size_t w = 10,
|
||||
h = w;
|
||||
Node[w][h] mesh;
|
||||
|
||||
// Set A and B Nodes.
|
||||
mesh[1][1] = Node( 1.0, Node.Kind.A);
|
||||
mesh[6][7] = Node(-1.0, Node.Kind.B);
|
||||
|
||||
writefln("R = %.19f", 2 / iter(mesh));
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
>load incidence;
|
||||
>{u,r}=solvePotentialX(makeRectangleX(10,10),12,68); r,
|
||||
1.60899124173
|
||||
44
Task/Resistor-mesh/Euler-Math-Toolbox/resistor-mesh-2.euler
Normal file
44
Task/Resistor-mesh/Euler-Math-Toolbox/resistor-mesh-2.euler
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
function makeRectangleX (n:index,m:index)
|
||||
## Make the incidence matrix of a rectangle grid in compact form.
|
||||
## see: makeRectangleIncidence
|
||||
K=zeros(n*(m-1)+m*(n-1),3);
|
||||
k=1;
|
||||
for i=1 to n;
|
||||
for j=1 to m-1;
|
||||
K[k,1]=(i-1)*m+j; K[k,2]=(i-1)*m+j+1; K[k,3]=1;
|
||||
k=k+1;
|
||||
end;
|
||||
end;
|
||||
for i=1 to n-1;
|
||||
for j=1 to m;
|
||||
K[k,1]=(i-1)*m+j; K[k,2]=i*m+j; K[k,3]=1;
|
||||
k=k+1;
|
||||
end;
|
||||
end;
|
||||
H=cpxzeros([n*m,n*m]);
|
||||
H=cpxset(H,K);
|
||||
H=cpxset(H,K[:,[2,1,3]]);
|
||||
return H;
|
||||
endfunction
|
||||
|
||||
function solvePotentialX (A:cpx, i:index ,j:index)
|
||||
## Solve the potential problem of resistance in a graph.
|
||||
## This functions uses the conjugate gradient method.
|
||||
## A is a compressed incidence matrix.
|
||||
## Return the potential u for the nodes in A,
|
||||
## such that u[i]=1, u[j]=-1, and the flow
|
||||
## to each knot is equal to the flow from the knot,
|
||||
## and the flow from i to j is (u[i]-u[j])*A[i,j].
|
||||
## see: makeIncidence
|
||||
n=size(A)[1];
|
||||
b=ones(n,1); f=-cpxmult(A,b);
|
||||
h=1:n; B=cpxset(A,h'|h'|f);
|
||||
B=cpxset(B,i|h'|0);
|
||||
B=cpxset(B,[i,i,1]);
|
||||
B=cpxset(B,j|h'|0);
|
||||
B=cpxset(B,[j,j,1]);
|
||||
v=zeros(n,1); v[i]=1; v[j]=-1;
|
||||
u=cpxfit(B,v);
|
||||
f=(-f[i])*u[i]-cpxmult(A,u)[i];
|
||||
return {u,2/f}
|
||||
endfunction
|
||||
39
Task/Resistor-mesh/Euler-Math-Toolbox/resistor-mesh-3.euler
Normal file
39
Task/Resistor-mesh/Euler-Math-Toolbox/resistor-mesh-3.euler
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
function cgX (H:cpx, b:real column, x0:real column=none, f:index=10)
|
||||
## Conjugate gradient method to solve Hx=b for compressed H.
|
||||
##
|
||||
## This is the method of choice for large, sparse matrices. In most
|
||||
## cases, it will work well, fast, and accurate.
|
||||
##
|
||||
## H must be positive definite. Use cpxfit, if it is not.
|
||||
##
|
||||
## The accuarcy can be controlled with an additional parameter
|
||||
## eps. The algorithm stops, when the error gets smaller then eps, or
|
||||
## after f*n iterations, if the error gets larger. x0 is an optional
|
||||
## start vector.
|
||||
##
|
||||
## H : compressed matrix (nxm)
|
||||
## b : column vector (mx1)
|
||||
## x0 : optional start point (mx1)
|
||||
## f : number of steps, when the method should be restarted
|
||||
##
|
||||
## See: cpxfit, cg, cgXnormal
|
||||
if isvar("eps") then localepsilon(eps); endif;
|
||||
n=cols(H);
|
||||
if x0==none then x=zeros(size(b));
|
||||
else; x=x0;
|
||||
endif;
|
||||
loop 1 to 10
|
||||
r=b-cpxmult(H,x); p=r; fehler=r'.r;
|
||||
loop 1 to f*n
|
||||
if sqrt(fehler)~=0 then return x; endif;
|
||||
Hp=cpxmult(H,p);
|
||||
a=fehler/(p'.Hp);
|
||||
x=x+a*p;
|
||||
rn=r-a*Hp;
|
||||
fehlerneu=rn'.rn;
|
||||
p=rn+fehlerneu/fehler*p;
|
||||
r=rn; fehler=fehlerneu;
|
||||
end;
|
||||
end;
|
||||
return x;
|
||||
endfunction
|
||||
10
Task/Resistor-mesh/J/resistor-mesh-1.j
Normal file
10
Task/Resistor-mesh/J/resistor-mesh-1.j
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
nodes=: 10 10 #: i. 100
|
||||
nodeA=: 1 1
|
||||
nodeB=: 6 7
|
||||
|
||||
conn =: [: (#~ e.~/@|:~&0 2) ([ ,: +)"1
|
||||
ref =: ~. nodeA,nodes-.nodeB
|
||||
wiring=: /:~ ref i. ,/ nodes conn"2 1 (,-)=i.2
|
||||
Yii=: _1 _1 }. (* =@i.@#) #/.~ {."1 wiring
|
||||
Yij=: - _1 _1 }. 1:`(<"1@[)`]}&(+/~ 0*i.1+#ref) wiring
|
||||
Y=: Yii+Yij
|
||||
2
Task/Resistor-mesh/J/resistor-mesh-2.j
Normal file
2
Task/Resistor-mesh/J/resistor-mesh-2.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
{.{. %. Y
|
||||
1.60899
|
||||
2
Task/Resistor-mesh/J/resistor-mesh-3.j
Normal file
2
Task/Resistor-mesh/J/resistor-mesh-3.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
{.{.%. x:Y
|
||||
455859137025721r283319837425200
|
||||
12
Task/Resistor-mesh/Mathematica/resistor-mesh-1.math
Normal file
12
Task/Resistor-mesh/Mathematica/resistor-mesh-1.math
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
gridresistor[p_, q_, ai_, aj_, bi_, bj_] :=
|
||||
Block[{A, B, k, c, V}, A = ConstantArray[0, {p*q, p*q}];
|
||||
Do[k = (i - 1) q + j;
|
||||
If[{i, j} == {ai, aj}, A[[k, k]] = 1, c = 0;
|
||||
If[1 <= i + 1 <= p && 1 <= j <= q, c++; A[[k, k + q]] = -1];
|
||||
If[1 <= i - 1 <= p && 1 <= j <= q, c++; A[[k, k - q]] = -1];
|
||||
If[1 <= i <= p && 1 <= j + 1 <= q, c++; A[[k, k + 1]] = -1];
|
||||
If[1 <= i <= p && 1 <= j - 1 <= q, c++; A[[k, k - 1]] = -1];
|
||||
A[[k, k]] = c], {i, p}, {j, q}];
|
||||
B = SparseArray[(k = (bi - 1) q + bj) -> 1, p*q];
|
||||
LinearSolve[A, B][[k]]];
|
||||
N[gridresistor[10, 10, 2, 2, 8, 7], 40]
|
||||
7
Task/Resistor-mesh/Mathematica/resistor-mesh-2.math
Normal file
7
Task/Resistor-mesh/Mathematica/resistor-mesh-2.math
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
graphresistor[g_, a_, b_] :=
|
||||
LinearSolve[
|
||||
SparseArray[{{a, a} -> 1, {i_, i_} :> Length@AdjacencyList[g, i],
|
||||
Alternatives @@ Join[#, Reverse /@ #] &[
|
||||
List @@@ EdgeList[VertexDelete[g, a]]] -> -1}, {VertexCount[
|
||||
g], VertexCount[g]}], SparseArray[b -> 1, VertexCount[g]]][[b]];
|
||||
N[graphresistor[GridGraph[{10, 10}], 12, 77], 40]
|
||||
62
Task/Resistor-mesh/Maxima/resistor-mesh.maxima
Normal file
62
Task/Resistor-mesh/Maxima/resistor-mesh.maxima
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* Place a current souce between A and B, providing 1 A. Then we are really looking
|
||||
for the potential at A and B, since I = R (V(B) - V(A)) where I is given and we want R.
|
||||
|
||||
Atually, we will compute potential at each node, except A where we assume it's 0.
|
||||
Without with assumption, there would be infinitely many solutions since potential
|
||||
is known up to a constant. For A we will simply write the equation V(A) = 0, to
|
||||
keep the program simple.
|
||||
|
||||
Hence, for a general grid of p rows and q columns, there are n = p * q nodes,
|
||||
so n unknowns, and n equations. Write Kirchhoff's current law at each node.
|
||||
Be careful with the node A (equation A = 0) and the node B (there is a constant
|
||||
current to add, from the source, that will go in the constant terms of the system).
|
||||
|
||||
Finally, we have a n x n linear system of equations to solve. Simply use Maxima's
|
||||
builtin LU decomposition.
|
||||
|
||||
Since all computations are exact, the result will be also exact, written as a fraction.
|
||||
Also, the program can work with any grid, and any two nodes on the grid.
|
||||
|
||||
For those who want more speed and less space, notice the system is sparse and necessarily
|
||||
symmetric, so one can use conjugate gradient or any other sparse symmetric solver. */
|
||||
|
||||
|
||||
/* Auxiliary function to get rid of the borders */
|
||||
ongrid(i, j, p, q) := is(i >= 1 and i <= p and j >= 1 and j <= q)$
|
||||
|
||||
grid_resistor(p, q, ai, aj, bi, bj) := block(
|
||||
[n: p * q, A, B, M, k, c, V],
|
||||
A: zeromatrix(n, n),
|
||||
for i thru p do
|
||||
for j thru q do (
|
||||
k: (i - 1) * q + j,
|
||||
if i = ai and j = aj then
|
||||
A[k, k]: 1
|
||||
else (
|
||||
c: 0,
|
||||
if ongrid(i + 1, j, p, q) then (c: c + 1, A[k, k + q]: -1),
|
||||
if ongrid(i - 1, j, p, q) then (c: c + 1, A[k, k - q]: -1),
|
||||
if ongrid(i, j + 1, p, q) then (c: c + 1, A[k, k + 1]: -1),
|
||||
if ongrid(i, j - 1, p, q) then (c: c + 1, A[k, k - 1]: -1),
|
||||
A[k, k]: c
|
||||
)
|
||||
),
|
||||
B: zeromatrix(n, 1),
|
||||
B[k: (bi - 1) * q + bj, 1]: 1,
|
||||
M: lu_factor(A),
|
||||
V: lu_backsub(M, B),
|
||||
V[k, 1]
|
||||
)$
|
||||
|
||||
grid_resistor(10, 10, 2, 2, 8, 7);
|
||||
455859137025721 / 283319837425200
|
||||
|
||||
bfloat(%), fpprec = 40;
|
||||
1.608991241730729655954495520510088761201b0
|
||||
|
||||
/* Some larger example */
|
||||
grid_resistor(20, 20, 1, 1, 20, 20);
|
||||
129548954101732562831760781545158173626645023 / 33283688571680493510612137844679320717594861
|
||||
|
||||
bfloat(%), fpprec = 40;
|
||||
3.89226554090400912102670691601064387507b0
|
||||
58
Task/Resistor-mesh/Perl-6/resistor-mesh.pl6
Normal file
58
Task/Resistor-mesh/Perl-6/resistor-mesh.pl6
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
my $S = 10;
|
||||
|
||||
my @fixed;
|
||||
|
||||
sub allocmesh ($w, $h) {
|
||||
gather for ^$h {
|
||||
take [0 xx $w];
|
||||
}
|
||||
}
|
||||
|
||||
sub force-fixed(@f) {
|
||||
@f[1][1] = 1;
|
||||
@f[6][7] = -1;
|
||||
}
|
||||
|
||||
sub force-v(@v) {
|
||||
@v[1][1] = 1;
|
||||
@v[6][7] = -1;
|
||||
}
|
||||
|
||||
sub calc_diff(@v, @d, Int $w, Int $h) {
|
||||
my $total = 0;
|
||||
for ^$h X ^$w -> $i, $j {
|
||||
my @neighbors = grep *.defined, @v[$i-1][$j], @v[$i][$j-1], @v[$i+1][$j], @v[$i][$j+1];
|
||||
my $v = [+] @neighbors;
|
||||
@d[$i][$j] = $v = @v[$i][$j] - $v / +@neighbors;
|
||||
$total += $v * $v unless @fixed[$i][$j];
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
sub iter(@v, Int $w, Int $h) {
|
||||
my @d = allocmesh($w, $h);
|
||||
my $diff = 1e10;
|
||||
my @cur = 0, 0, 0;
|
||||
|
||||
while $diff > 1e-24 {
|
||||
force-v(@v);
|
||||
$diff = calc_diff(@v, @d, $w, $h);
|
||||
for ^$h X ^$w -> $i, $j {
|
||||
@v[$i][$j] -= @d[$i][$j];
|
||||
}
|
||||
}
|
||||
|
||||
for ^$h X ^$w -> $i, $j {
|
||||
@cur[ @fixed[$i][$j] + 1 ]
|
||||
+= @d[$i][$j] * (?$i + ?$j + ($i < $h - 1) + ($j < $w - 1));
|
||||
}
|
||||
|
||||
return (@cur[2] - @cur[0]) / 2;
|
||||
}
|
||||
|
||||
my @mesh = allocmesh($S, $S);
|
||||
|
||||
@fixed = allocmesh($S, $S);
|
||||
force-fixed(@fixed);
|
||||
|
||||
say 2 / iter(@mesh, $S, $S);
|
||||
60
Task/Resistor-mesh/Perl/resistor-mesh.pl
Normal file
60
Task/Resistor-mesh/Perl/resistor-mesh.pl
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use strict;
|
||||
|
||||
my ($w, $h) = (9, 9);
|
||||
my @v = map([ (0) x ($w + 1) ], 0 .. $h); # voltage
|
||||
my @f = map([ (0) x ($w + 1) ], 0 .. $h); # fixed condition
|
||||
my @d = map([ (0) x ($w + 1) ], 0 .. $h); # diff
|
||||
|
||||
my @n; # neighbors
|
||||
for my $i (0 .. $h) {
|
||||
push @{$n[$i][$_]}, [$i, $_ - 1] for 1 .. $w;
|
||||
push @{$n[$i][$_]}, [$i, $_ + 1] for 0 .. $w - 1;
|
||||
}
|
||||
for my $j (0 .. $w) {
|
||||
push @{$n[$_][$j]}, [$_ - 1, $j] for 1 .. $h;
|
||||
push @{$n[$_][$j]}, [$_ + 1, $j] for 0 .. $h - 1;
|
||||
}
|
||||
|
||||
sub set_boundary {
|
||||
$f[1][1] = 1; $f[6][7] = -1;
|
||||
$v[1][1] = 1; $v[6][7] = -1;
|
||||
}
|
||||
|
||||
sub calc_diff {
|
||||
my $total_diff;
|
||||
for my $i (0 .. $h) {
|
||||
for my $j (0 .. $w) {
|
||||
my ($p, $v) = $n[$i][$j];
|
||||
$v += $v[$_->[0]][$_->[1]] for @$p;
|
||||
$d[$i][$j] = $v = $v[$i][$j] - $v / scalar(@$p);
|
||||
$total_diff += $v * $v unless $f[$i][$j];
|
||||
}
|
||||
}
|
||||
$total_diff;
|
||||
}
|
||||
|
||||
sub iter {
|
||||
my $diff = 1;
|
||||
while ($diff > 1e-24) { # 1e-24 is overkill (12 digits of precision)
|
||||
set_boundary();
|
||||
$diff = calc_diff();
|
||||
print "error^2: $diff\r";
|
||||
for my $i (0 .. $h) {
|
||||
for my $j (0 .. $w) {
|
||||
$v[$i][$j] -= $d[$i][$j];
|
||||
}
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
|
||||
my @current = (0) x 3;
|
||||
for my $i (0 .. $h) {
|
||||
for my $j (0 .. $w) {
|
||||
$current[ $f[$i][$j] ] +=
|
||||
$d[$i][$j] * scalar(@{$n[$i][$j]});
|
||||
}
|
||||
}
|
||||
return ($current[1] - $current[-1]) / 2;
|
||||
}
|
||||
|
||||
print "R = @{[2 / iter()]}\n";
|
||||
64
Task/Resistor-mesh/Python/resistor-mesh.py
Normal file
64
Task/Resistor-mesh/Python/resistor-mesh.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
DIFF_THRESHOLD = 1e-40
|
||||
|
||||
class Fixed:
|
||||
FREE = 0
|
||||
A = 1
|
||||
B = 2
|
||||
|
||||
class Node:
|
||||
__slots__ = ["voltage", "fixed"]
|
||||
def __init__(self, v=0.0, f=Fixed.FREE):
|
||||
self.voltage = v
|
||||
self.fixed = f
|
||||
|
||||
def set_boundary(m):
|
||||
m[1][1] = Node( 1.0, Fixed.A)
|
||||
m[6][7] = Node(-1.0, Fixed.B)
|
||||
|
||||
def calc_difference(m, d):
|
||||
h = len(m)
|
||||
w = len(m[0])
|
||||
total = 0.0
|
||||
|
||||
for i in xrange(h):
|
||||
for j in xrange(w):
|
||||
v = 0.0
|
||||
n = 0
|
||||
if i != 0: v += m[i-1][j].voltage; n += 1
|
||||
if j != 0: v += m[i][j-1].voltage; n += 1
|
||||
if i < h-1: v += m[i+1][j].voltage; n += 1
|
||||
if j < w-1: v += m[i][j+1].voltage; n += 1
|
||||
v = m[i][j].voltage - v / n
|
||||
|
||||
d[i][j].voltage = v
|
||||
if m[i][j].fixed == Fixed.FREE:
|
||||
total += v ** 2
|
||||
return total
|
||||
|
||||
def iter(m):
|
||||
h = len(m)
|
||||
w = len(m[0])
|
||||
difference = [[Node() for j in xrange(w)] for i in xrange(h)]
|
||||
|
||||
while True:
|
||||
set_boundary(m) # Enforce boundary conditions.
|
||||
if calc_difference(m, difference) < DIFF_THRESHOLD:
|
||||
break
|
||||
for i, di in enumerate(difference):
|
||||
for j, dij in enumerate(di):
|
||||
m[i][j].voltage -= dij.voltage
|
||||
|
||||
cur = [0.0] * 3
|
||||
for i, di in enumerate(difference):
|
||||
for j, dij in enumerate(di):
|
||||
cur[m[i][j].fixed] += (dij.voltage *
|
||||
(bool(i) + bool(j) + (i < h-1) + (j < w-1)))
|
||||
|
||||
return (cur[Fixed.A] - cur[Fixed.B]) / 2.0
|
||||
|
||||
def main():
|
||||
w = h = 10
|
||||
mesh = [[Node() for j in xrange(w)] for i in xrange(h)]
|
||||
print "R = %.16f" % (2 / iter(mesh))
|
||||
|
||||
main()
|
||||
40
Task/Resistor-mesh/REXX/resistor-mesh.rexx
Normal file
40
Task/Resistor-mesh/REXX/resistor-mesh.rexx
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*REXX pgm calculates resistance between any 2 points on a resister grid*/
|
||||
numeric digits 20 /*use moderate digits (precision)*/
|
||||
minVal=(1'e-'||(digits()*2)) / 1 /*calculate the threshold min val*/
|
||||
if 1=='f1'x then ohms = 'ohms' /*EBCDIC machine? Use 'ohms'. */
|
||||
else ohms = 'ea'x /* ASCII machine? Use Greek Ω.*/
|
||||
parse arg wide high Arow Acol Brow Bcol .
|
||||
say 'minVal = ' format(minVal,,,,0) ; say
|
||||
say 'resistor mesh is of size: ' wide "wide, " high 'high.' ; say
|
||||
say 'point A is at (row,col): ' Arow","Acol
|
||||
say 'point B is at (row,col): ' Brow","Bcol
|
||||
@.=0; cell.=1
|
||||
do until $ <= minVal; $=0; v = 0
|
||||
@.Arow.Acol = +1 ; cell.Arow.Acol = 0
|
||||
@.Brow.Bcol = -1 ; cell.Brow.Bcol = 0
|
||||
|
||||
do i =1 for high; im=i-1; ip=i+1
|
||||
do j=1 for wide; jm=j-1; jp=j+1; n=0; v=0
|
||||
if i\==1 then do; v=v+@.im.j; n=n+1; end
|
||||
if j\==1 then do; v=v+@.i.jm; n=n+1; end
|
||||
if i<high then do; v=v+@.ip.j; n=n+1; end
|
||||
if j<wide then do; v=v+@.i.jp; n=n+1; end
|
||||
v=@.i.j-v/n; #.i.j=v; if cell.i.j then $=$+v*v
|
||||
end /*j*/
|
||||
end /*i*/
|
||||
do r=1 for High
|
||||
do c=1 for Wide; @.r.c=@.r.c-#.r.c
|
||||
end /*c*/
|
||||
end /*r*/
|
||||
end /*until*/
|
||||
say
|
||||
Acur = #.Arow.Acol * sides(Arow,Acol)
|
||||
Bcur = #.Brow.Bcol * sides(Brow,Bcol)
|
||||
say 'resistance between point A and point B is: ' 4/(Acur-Bcur) ohms
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────sides subroutine────────────────────*/
|
||||
sides: parse arg i,j; !=0; if i\==1 & i\==high then !=!+2
|
||||
else !=!+1
|
||||
if j\==1 & j\==wide then !=!+2
|
||||
else !=!+1
|
||||
return !
|
||||
95
Task/Resistor-mesh/Tcl/resistor-mesh-1.tcl
Normal file
95
Task/Resistor-mesh/Tcl/resistor-mesh-1.tcl
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
package require Tcl 8.6; # Or 8.5 with the TclOO package
|
||||
|
||||
# This code is structured as a class with a little trivial DSL parser so it is
|
||||
# easy to change what problem is being worked on.
|
||||
oo::class create ResistorMesh {
|
||||
variable forcePoints V fixed w h
|
||||
|
||||
constructor {boundaryConditions} {
|
||||
foreach {op condition} $boundaryConditions {
|
||||
switch $op {
|
||||
size {
|
||||
lassign $condition w h
|
||||
set fixed [lrepeat $h [lrepeat $w 0]]
|
||||
set V [lrepeat $h [lrepeat $w 0.0]]
|
||||
}
|
||||
fixed {
|
||||
lassign $condition j i v
|
||||
lset fixed $i $j [incr ctr]
|
||||
lappend forcePoints $j $i $v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
method CalculateDifferences {*dV} {
|
||||
upvar 1 ${*dV} dV
|
||||
set error 0.0
|
||||
for {set i 0} {$i < $h} {incr i} {
|
||||
for {set j 0} {$j < $w} {incr j} {
|
||||
set v 0.0
|
||||
set n 0
|
||||
if {$i} {
|
||||
set v [expr {$v + [lindex $V [expr {$i-1}] $j]}]
|
||||
incr n
|
||||
}
|
||||
if {$j} {
|
||||
set v [expr {$v + [lindex $V $i [expr {$j-1}]]}]
|
||||
incr n
|
||||
}
|
||||
if {$i+1 < $h} {
|
||||
set v [expr {$v + [lindex $V [expr {$i+1}] $j]}]
|
||||
incr n
|
||||
}
|
||||
if {$j+1 < $w} {
|
||||
set v [expr {$v + [lindex $V $i [expr {$j+1}]]}]
|
||||
incr n
|
||||
}
|
||||
lset dV $i $j [set v [expr {[lindex $V $i $j] - $v/$n}]]
|
||||
if {![lindex $fixed $i $j]} {
|
||||
set error [expr {$error + $v**2}]
|
||||
}
|
||||
}
|
||||
}
|
||||
return $error
|
||||
}
|
||||
|
||||
method FindCurrentFixpoint {epsilon} {
|
||||
set dV [lrepeat $h [lrepeat $w 0.0]]
|
||||
set current {0.0 0.0 0.0}
|
||||
while true {
|
||||
# Enforce the boundary conditions
|
||||
foreach {j i v} $forcePoints {
|
||||
lset V $i $j $v
|
||||
}
|
||||
# Compute the differences and the error
|
||||
set error [my CalculateDifferences dV]
|
||||
# Apply the differences
|
||||
for {set i 0} {$i < $h} {incr i} {
|
||||
for {set j 0} {$j < $w} {incr j} {
|
||||
lset V $i $j [expr {
|
||||
[lindex $V $i $j] - [lindex $dV $i $j]}]
|
||||
}
|
||||
}
|
||||
# Done if the error is small enough
|
||||
if {$error < $epsilon} break
|
||||
}
|
||||
# Compute the currents from the error
|
||||
for {set i 0} {$i < $h} {incr i} {
|
||||
for {set j 0} {$j < $w} {incr j} {
|
||||
lset current [lindex $fixed $i $j] [expr {
|
||||
[lindex $current [lindex $fixed $i $j]] +
|
||||
[lindex $dV $i $j] * (!!$i+!!$j+($i<$h-1)+($j<$w-1))}]
|
||||
}
|
||||
}
|
||||
# Compute the actual current flowing between source and sink
|
||||
return [expr {([lindex $current 1] - [lindex $current 2]) / 2.0}]
|
||||
}
|
||||
|
||||
# Public entry point
|
||||
method solveForResistance {{epsilon 1e-24}} {
|
||||
set voltageDifference [expr {
|
||||
[lindex $forcePoints 2] - [lindex $forcePoints 5]}]
|
||||
expr {$voltageDifference / [my FindCurrentFixpoint $epsilon]}
|
||||
}
|
||||
}
|
||||
6
Task/Resistor-mesh/Tcl/resistor-mesh-2.tcl
Normal file
6
Task/Resistor-mesh/Tcl/resistor-mesh-2.tcl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
ResistorMesh create mesh {
|
||||
size {10 10}
|
||||
fixed {1 1 1.0}
|
||||
fixed {6 7 -1.0}
|
||||
}
|
||||
puts [format "R = %.12g" [mesh solveForResistance]]
|
||||
49
Task/Resistor-mesh/XPL0/resistor-mesh.xpl0
Normal file
49
Task/Resistor-mesh/XPL0/resistor-mesh.xpl0
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
code real RlRes=46, RlOut=48;
|
||||
def S = 10;
|
||||
|
||||
proc SetBoundary(MV, MF);
|
||||
real MV; int MF;
|
||||
[MF(1,1):= 1; MV(1,1):= 1.0;
|
||||
MF(6,7):= -1; MV(6,7):= -1.0;
|
||||
];
|
||||
|
||||
func real CalcDiff(MV, MF, DV, W, H);
|
||||
real MV; int MF; real DV; int W, H;
|
||||
int I, J, N; real V, Total;
|
||||
[Total:= 0.0;
|
||||
for I:= 0 to H-1 do
|
||||
for J:= 0 to W-1 do
|
||||
[V:= 0.0; N:= 0;
|
||||
if I then [V:= V + MV(I-1,J); N:= N+1];
|
||||
if J then [V:= V + MV(I,J-1); N:= N+1];
|
||||
if I+1 < H then [V:= V + MV(I+1,J); N:= N+1];
|
||||
if J+1 < W then [V:= V + MV(I,J+1); N:= N+1];
|
||||
V:= MV(I,J) - V/float(N); DV(I,J):= V;
|
||||
if MF(I,J) = 0 then Total:= Total + V*V;
|
||||
];
|
||||
return Total;
|
||||
];
|
||||
|
||||
func real Iter(MV, MF, W, H);
|
||||
real MV; int MF, W, H;
|
||||
real DV, Diff, Cur; int I, J;
|
||||
[DV:= RlRes(W); for I:= 0 to W-1 do DV(I):= RlRes(H);
|
||||
Diff:= 1E10;
|
||||
Cur:= [0.0, 0.0, 0.0];
|
||||
while Diff > 1E-24 do
|
||||
[SetBoundary(MV, MF);
|
||||
Diff:= CalcDiff(MV, MF, DV, W, H);
|
||||
for I:= 0 to H-1 do
|
||||
for J:= 0 to W-1 do
|
||||
MV(I,J):= MV(I,J) - DV(I,J);
|
||||
];
|
||||
for I:= 0 to H-1 do
|
||||
for J:= 0 to W-1 do
|
||||
Cur(MF(I,J)+1):= Cur(MF(I,J)+1) +
|
||||
DV(I,J) * float(-(I>0) - (J>0) - (I<H-1) - (J<W-1));
|
||||
\middle=4; side=3; corner=2
|
||||
return (Cur(2)-Cur(0))/2.0;
|
||||
];
|
||||
|
||||
real MeshV(S,S); int MeshF(S,S);
|
||||
RlOut(0, 2.0 / Iter(MeshV, MeshF, S, S))
|
||||
Loading…
Add table
Add a link
Reference in a new issue