Deconvolution/2D+: Difference between revisions
Content added Content deleted
m (→{{header|Tcl}}: Add comments) |
Thundergnat (talk | contribs) (→{{header|Tcl}}: Added Perl 6 solution) |
||
Line 94: | Line 94: | ||
h3 -: g3 deconv3 f3 NB. h3 matches g3 deconv3 f3 |
h3 -: g3 deconv3 f3 NB. h3 matches g3 deconv3 f3 |
||
1</lang> |
1</lang> |
||
=={{header|Perl 6}}== |
|||
Translation of Tcl |
|||
<lang perl6># Deconvolution of N dimensional matricies. |
|||
sub deconv_ND ( @g, @f ) { |
|||
my @gsize = size_of @g; |
|||
my @fsize = size_of @f; |
|||
my @hsize = @gsize >>-<< @fsize >>+>> 1; |
|||
my @toSolve; |
|||
for loopcoords(@gsize) -> $coords { |
|||
@toSolve.push( [ row( @g, @f, @gsize, $coords, @fsize, @hsize ) ]); |
|||
} |
|||
my @solved = rref( @toSolve ); |
|||
# Uncomment if you want to see the rref system of equations. |
|||
# pretty_print( @solved ); |
|||
my @h; |
|||
my $index = 0; |
|||
for loopcoords(@hsize) -> @coords { |
|||
insert( @h, @coords, @solved[$index][*-1] ); |
|||
$index++; |
|||
} |
|||
return @h; |
|||
# Inserts a value in the correct spot in an N dimensional array. |
|||
sub insert ( $array is rw, @coords is copy, $value ) { |
|||
my $level = @coords.shift; |
|||
if +@coords { |
|||
insert( $array[$level], @coords, $value ); |
|||
} else { |
|||
$array[$level] = $value; |
|||
} |
|||
} |
|||
} |
|||
# Returns a list containing the number of elements in |
|||
# each level of an N dimensional array. |
|||
sub size_of ( $m is copy ) { |
|||
my @size; |
|||
while $m ~~ Array { @size.push(+$m); $m = $m[0]; } |
|||
return @size; |
|||
} |
|||
# Construct a row (equation) for each value in @g to be sent |
|||
# to the simultaneous equation solver. |
|||
# @Xsize = Dimensions of @X, # of elems per level. |
|||
# @Xcoords = Path to each element of @X given as a series of indicies. |
|||
sub row ( @g, @f, @gsize, @gcoords, @fsize, $hsize ) { |
|||
my @row; |
|||
for loopcoords( $hsize ) -> @hcoords { |
|||
my @fcoords; |
|||
for ^@hcoords -> $index { |
|||
my $window = @gcoords[$index] - @hcoords[$index]; |
|||
@fcoords.push($window) and next if 0 <= $window < @fsize[$index]; |
|||
last; |
|||
} |
|||
@row.push( +@fcoords == +@hcoords ?? fetch( @f, |@fcoords ) !! 0 ); |
|||
} |
|||
@row.push( fetch( @g, |@gcoords ) ); |
|||
return @row; |
|||
# Returns the value found in @array with the |
|||
# coordinates given in the list of @indicies. |
|||
sub fetch (@array, *@indicies) { |
|||
my $index = @indicies.shift; |
|||
return @array[*-1] ~~ Array |
|||
?? fetch( @array[$index], @indicies ) |
|||
!! @array[$index]; |
|||
} |
|||
} |
|||
# Constructs an array of arrays of coordinates to each |
|||
# element in an N dimensional array. |
|||
sub loopcoords ( @hsize ) { |
|||
my @hcoords; |
|||
for ^([*] @hsize) -> $index { |
|||
my @coords; |
|||
my $j = $index; |
|||
for @hsize -> $dim{ |
|||
@coords.push( $j % $dim ); |
|||
$j div= $dim; |
|||
} |
|||
@hcoords.push( [@coords] ); |
|||
} |
|||
return @hcoords; |
|||
} |
|||
# Reduced Row Echelon Form simultaneous equation solver. |
|||
# Can handle over-specified systems of equations. |
|||
# (n unknowns in n + m equations) |
|||
sub rref ($m is rw) { |
|||
return unless $m; |
|||
my ($lead, $rows, $cols) = 0, +$m, +$m[0]; |
|||
# Trim off over specified rows if they exist. |
|||
# Not strictly necessary, but can save a lot of |
|||
# redundant calculations. |
|||
if $rows >= $cols { |
|||
$m = trim_system($m); |
|||
$rows = +$m; |
|||
} |
|||
for ^$rows -> $r { |
|||
$lead < $cols or return $m; |
|||
my $i = $r; |
|||
until $m[$i][$lead] { |
|||
++$i == $rows or next; |
|||
$i = $r; |
|||
++$lead == $cols and return $m; |
|||
} |
|||
$m[$i, $r] = $m[$r, $i] if $r != $i; |
|||
my $lv = $m[$r][$lead]; |
|||
$m[$r] >>/=>> $lv; |
|||
for ^$rows -> $n { |
|||
next if $n == $r; |
|||
$m[$n] >>-=>> $m[$r] >>*>> $m[$n][$lead]; |
|||
} |
|||
++$lead; |
|||
} |
|||
return $m; |
|||
# Reduce a system of equations to n equations with n unknowns. |
|||
# Looks for an equation with a true value for each position. |
|||
# If it can't find one, assumes that it has already taken one |
|||
# and pushes in the first equation it sees. This assumtion |
|||
# will alway be successful except in some cases where an |
|||
# under-specified system has been supplied, in which case, |
|||
# it would not have been able to reduce the system anyway. |
|||
sub trim_system ($m is rw) { |
|||
my ($vars, @t) = +$m[0]-1, (); |
|||
for ^$vars -> $lead { |
|||
for ^$m -> $row { |
|||
@t.push( $m.splice( $row, 1 ) ) and last if $m[$row][$lead]; |
|||
} |
|||
} |
|||
while (+@t < $vars) and +$m { @t.push( $m.splice( 0, 1 ) ) }; |
|||
return @t; |
|||
} |
|||
}</lang> |
|||
Use with a pretty printer as follows: |
|||
<lang perl6># Pretty printer for N dimensional arrays. Assumes that |
|||
# if the FIRST element in any particular level is an array, |
|||
# then ALL the elements at that level are arrays. |
|||
sub pretty_print ( @array, $indent = 0 ) { |
|||
my $tab = 2; |
|||
if @array[0] ~~ Array { |
|||
say ' ' x $indent,"["; |
|||
pretty_print( $_, $indent + $tab ) for @array; |
|||
say ' ' x $indent, "]{$indent??','!!''}"; |
|||
} else { |
|||
say ' ' x $indent, "[{say_it(@array)} ]{$indent??','!!''}"; |
|||
} |
|||
sub say_it ( @array ) { |
|||
return join ",", @array>>.fmt("%4s"); |
|||
} |
|||
} |
|||
my @f = ( |
|||
[ |
|||
[ -9, 5, -8 ], [ 3, 5, 1 ], |
|||
], |
|||
[ |
|||
[ -1, -7, 2 ], [ -5, -6, 6 ], |
|||
], |
|||
[ |
|||
[ 8, 5, 8 ], [ -2, -6, -4 ], |
|||
] |
|||
); |
|||
my @g = ( |
|||
[ |
|||
[ 54, 42, 53, -42, 85, -72 ], |
|||
[ 45,-170, 94, -36, 48, 73 ], |
|||
[ -39, 65,-112, -16, -78, -72 ], |
|||
[ 6, -11, -6, 62, 49, 8 ], |
|||
], |
|||
[ |
|||
[ -57, 49, -23, 52,-135, 66 ], |
|||
[ -23, 127, -58, -5,-118, 64 ], |
|||
[ 87, -16, 121, 23, -41, -12 ], |
|||
[ -19, 29, 35,-148, -11, 45 ], |
|||
], |
|||
[ |
|||
[ -55,-147,-146, -31, 55, 60 ], |
|||
[ -88, -45, -28, 46, -26,-144 ], |
|||
[ -12,-107, -34, 150, 249, 66 ], |
|||
[ 11, -15, -34, 27, -78, -50 ], |
|||
], |
|||
[ |
|||
[ 56, 67, 108, 4, 2, -48 ], |
|||
[ 58, 67, 89, 32, 32, -8 ], |
|||
[ -42, -31,-103, -30, -23, -8 ], |
|||
[ 6, 4, -26, -10, 26, 12 ], |
|||
] |
|||
); |
|||
=begin skip_output |
|||
say "@g ="; |
|||
pretty_print( @g ); |
|||
say '-' x 79; |
|||
say "@f ="; |
|||
pretty_print( @f ); |
|||
say '-' x 79; |
|||
=end skip_output |
|||
say "# {+size_of(@f)}D array:"; |
|||
say "@h ="; |
|||
pretty_print( deconv_ND( @g, @f ) );</lang> |
|||
Output: |
|||
<pre># 3D array: |
|||
@h = |
|||
[ |
|||
[ |
|||
[ -6, -8, -5, 9 ], |
|||
[ -7, 9, -6, -8 ], |
|||
[ 2, -7, 9, 8 ], |
|||
], |
|||
[ |
|||
[ 7, 4, 4, -6 ], |
|||
[ 9, 9, 4, -4 ], |
|||
[ -3, 7, -2, -3 ], |
|||
], |
|||
]</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |