Just to finish the job, I've had a go at baksub.
Here my efforts for both forward and backward substitution:
All 4 examples require the vector and matrix arguments to
have the same length.
NB. successively append new elements to new vector z
forsuba=: 4 : 0
a =. x%d=.x|:~<0 1
b =. y%d
z =. ''
for_i. i.#b do.
z =. z, (i{b) - +/ z * i{. i{ a
end.
)
NB. overwrite b in place
NB. saves no of variables but needs to keep indexed assignment
forsubb=: 4 : 0
a =. x%d=.x|:~<0 1
b =. y%d
for_i. i.#b do.
b =. ((i{b) - +/ i{. b * i { a) i } b
end.
)
NB. successively prepend new elements to new vector z
baksuba =: 4 : 0
B =. x%d=.x|:~<0 1
Y =. y%d
z =. ''
for_i. i. -#Y do.
z =.z,~ (i{Y) - +/ z * (i+1)}. i {B
end.
)
NB. overwrite Y in place
NB. saves no of variables but needs to keep indexed assignment
baksubb =: 4 : 0
B =. x%d=.x|:~<0 1
Y =. y%d
for_i. - >: i. #Y do.
Y =. ((i{Y) - +/ (i+1){. Y * i {B) i } Y
end.
)
I haven't benchmarked the latter two, and still haven't found
closed forms despite Raul's hints.
Mike
On 02/09/2015 20:17, Mike Day wrote:
I've had a look at forsub this afternoon. I've cribbed Raul's
pre-factoring by
the matrix-diagonal, but otherwise they're my own ideas. Nothing out of
the ordinary, but fairly concise. "J-like"? - perhaps.
NB. these both assume that #x = #y
NB. Thunderbird will probably spoil the appearance
NB. successively append new elements to new vector z
forsuba=: 4 : 0
a =. x%d=.(+=&0)x|:~<0 1
b =. y%d
z =. ''
for_i. i.#b do.
z =. z, (i{b) - +/ z * i{. i{ a
end.
)
NB. overwrite b in place
NB. saves no of variables but needs to keep indexed assignment
forsubb=: 4 : 0
a =. x%d=.(+=&0)x|:~<0 1
b =. y%d
for_i. i.#b do. NB. could keep }.i.#b
b =. ((i{b) - +/ i{. b * i { a) i } b
end.
)
They're both marginally faster than forsub though nothing to
get excited about! I didn't find much change in performance
with the +/ . * form of sum-product. But they are quite
nicely concise. I feel there's a closed form hiding in there
somewhere, to replace the explicit loop, but haven't found
it yet!
Mike
On 02/09/2015 04:42, Thomas McGuire wrote:
Thanks I will try out your changes. Though in my implementation I was
trying to avoid multiplying the zero entries and your routines ignore
that:
z1=. (i{b) - (i{a) +/ .* z
Here multiplying by all elements of a row and letting the zeros get
rid of the unnecessary data in z in that particular step. It's
certainly cleaner but I will have to try out a comparison to see if
it matters.
What I was hoping for was to pull out the triangular data above the
diagonal and operate on that but I can't find a nice terse J command
to do that like you would have if I was pulling out the diagonal with
oblique.
I haven't had a chance to completely work out the timing
efficiencies of the original routines. But a quick check using 7x7
binomial numbers matrix:
] A=: !/~ i.7x
1 1 1 1 1 1 1
0 1 2 3 4 5 6
0 0 1 3 6 10 15
0 0 0 1 4 10 20
0 0 0 0 1 5 15
0 0 0 0 0 1 6
0 0 0 0 0 0 1
The timing of the original algorithm
timespacex 'A baksub (1+i.7)'
9.6e_5 14848
timespacex '(|:)A forsub (1+i.7)'
8.9e_5 12416
9.6e_5 + 8.9e_5
0.000185
timespacex '(1+i.7) %. A'
0.00067 30976
There seems to be some divergence as the size of the matrix increases
(whether it is enough to worry about I haven't determined yet).
The real reason I am using it is I am trying to implement a
non-linear least squares(NLLS) algorithm from R in J (see )
They have a routine that uses CR algorithm to implement NLLS and then
because you end up with upper and lower triangular matrices uses the
forward substitution and back substitution to solve the intermediate
matrix equations.
Tom McGuire
On Sep 1, 2015, at 10:54 AM, Raul Miller <rauldmil...@gmail.com> wrote:
I'm not sure I'd get rid of the for loop.
That said, here's a rephrase to make it more "j-like":
forsub=: 4 :0
d=. (<0 1)|:x
a=. x%d
b=. y%d
z=. (#b){.{.b
for_i.}.i.#b do.
z1=. (i{b) - (i{a) +/ .* z
z=. z1 i} z
end.
)
NB. Back substitution - multiply lower triangular matrix by vector
NB. Usage: matrix baksub vector
baksub =: 4 : 0
D=. (<0 1)|:x
B =. x%D
Y =. y%D
z =. (-#Y){.{:Y
for_i. }. i.-#Y do.
z1 =. (i{Y) - (i{B)+/ .* z
z =. z1 i} z
end.
)
Note that I have changed the algorithm slightly from your
implementation. So try it out on some other test cases to make sure
that I have not introduced any errors...
And of course, note also:
U1 baksub L1 forsub b1
1 _1 2
(|."1 U1) forsub&.|. L1 forsub b1
1 _1 2
That said, if you are doing this purely for efficiency reasons, those
efficiencies don't show up in your test data. (Running each timing
test twice to hint at some of the timing variances which can come from
outside influences such as OS scheduling):
timespacex 'b1 %. A1'
2.3e_5 7168
timespacex 'b1 %. A1'
3.5e_5 7168
timespacex 'U1 baksub L1 forsub b1'
6.2e_5 9344
timespacex 'U1 baksub L1 forsub b1'
3e_5 9344
Or, using your original definitions for forsub and baksub:
timespacex 'U1 baksub L1 forsub b1'
5.3e_5 11392
timespacex 'U1 baksub L1 forsub b1'
9.3e_5 11392
Thanks,
--
Raul
On Tue, Sep 1, 2015 at 1:47 AM, Thomas McGuire
<tmcguir...@gmail.com> wrote:
Sorry I should have rerun the stuff rather than just pick through
my debugging session.
The original Matrix
]A1 =: 3 3$1 2 3 2 _4 6 3 _9 _3
1 2 3
2 _4 6
3 _9 _3
LU decomposition triangular matrix L1 and U1 are
L1
1 0 0
2 _8 0
3 _15 _12
U1
1 2 3
0 1 0
0 0 1
b1 =: 5 18 6 NB. this is the right hand side of a system of
equations of the for Ax = b
Matrix divide solution
b1 %. A1
1 _1 2
Solution using the LU decomposition matrices
]y1 =: L1 forsub b1
5 _1 2
U1 baksub y1
1 _1 2
Tom McGuire
On Aug 31, 2015, at 10:23 PM, Raul Miller <rauldmil...@gmail.com>
wrote:
Can you double check whether you have posted what you intended?
I get
b1 %. A1
4.15625 1.375 _0.635417
L1 forsub b1
5 1.375 _0.635417
U1 baksub L1 forsub b1
0.517014 0.941667 _0.0635417
which does not correspond to the result you displayed.
Thanks,
--
Raul
On Mon, Aug 31, 2015 at 9:54 PM, Thomas McGuire
<tmcguir...@gmail.com> wrote:
I have been playing around with creating forward substitution and
backward substitution J scripts to solve lower and upper
triangular matrices of the type you would get by performing LU
decomposition on a single square matrix. I could certainly just
use matrix divide but this starts to slow down as the size of the
matrix NxN gets bigger. I have come up with a partial J like
solution but the script requires a for loop. I was wondering if
someone has a mor J-ish solution? Here is what I have done so far.
BACKGROUND and SCRIPTS:
From the LU decomp paper on the J website:
http://www.jsoftware.com/jwiki/Essays/LU%20Decomposition
There is a routine to perform the LU decomposition of a matrix.
Rather than use this though I cheated and borrowed a worked
example from the web:
The original matrix before LU
]A1 =: 3 3$ 1 2 3 2 _4 6 3 _9 _3
1 2 3
2 _4 6
3 _9 _3
b1 =: 5 _1 2
]L1 =: 3 3$1 0 0 2 _8 0 3 _15 _12
1 0 0
2 _8 0
3 _15 _12
]U1 =: 3 3$3 4 5 0 2 8 0 0 10
3 4 5
0 2 8
0 0 10
The forward substitution and backward substitution routines are
as follows:
NB. Forward substitution - multiply upper triangular matrix by
vector
NB. Usage: matrix forsub vector
forsub =: 4 : 0
a =. x
b =. y
z =. (#b)$z =. 0 0 0
z =. ((0 {b)% (<0 0) {a) 0} z
for_i. 1 + i. (#b)-1 do.
z1 =.((<i,i ){a)%~ ( (i{b) - (+/ (i{. (i {a))*(i{. z) ) )
z =. z1 i}z
end.
z
)
NB. Back substitution - multiply lower triangular matrix by vector
NB. Usage: matrix baksub vector
baksub =: 4 : 0
B =. x
Y =. y
N =. _1 + #Y
z =. (N+1)$0
z =. ((N {Y)% (<N,N) {B) N} z
for_i. |. i. N do.
z1 =. ((<i,i){B)%~ ((i{Y) - (+/ ((i+1)}. (i {B))*((i+1)}. z)))
z =. z1 i} z
end.
z
)
Solving linear equations with just matrix divide.
b1 %. A1
1 _1 2
To solve this set of linear equations with the L and U decomps
you do the following:
]y1 =: L1 forsub b1
5 _1 2
]x1 =: U1 baksub y1
1 _1 2
which agrees with the matrix divide version
These matrices were taken from the internet paper found here:
https://www.utdallas.edu/dept/abp/PDF_Files/LinearAlgebra_Folder/LU_Decomposition.pdf
---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm