interleave matrix columns

21 views
Skip to first unread message

Thomas McGuire

unread,
Apr 17, 2026, 5:12:19 AM (3 days ago) Apr 17
to fo...@jsoftware.com
Some background before I get to my question: 
I have been playing with an old APL Quote Quad paper “Fuzzy Control of Technological Processes in APL2” by Skomorokhov, Reinhardt and Tielemann.
They have an interesting way of setting up Fuzzy sets to be used in a membership function and then using interpolation to come up with the final set membership. 

There are 2 parameters of concern N and D that map to variables in an automated mail room and for those they have created 2 fuzzy sets stored in a matrix:

MuN =: 6 9$ _200 _150 _100 _50 0 50 100 150 200 1 0.5 0 0 0 0 0 0 0 0 0.5 1 0.5 0 0 0 0 0 0 0 0 0.5 1 0.5 0 0 0 0 0 0 0 0 0.5 1 0.5 0 0 0 0 0 0 0 0 0.5 1

MuD =: _100 _75 _50 _25 0 25 50 75 100 (0)}MuN


MuN

_200 _150 _100 _50 0 50 100 150 200

1 0.5 0 0 0 0 0 0 0

0 0.5 1 0.5 0 0 0 0 0

0 0 0 0.5 1 0.5 0 0 0

0 0 0 0 0 0.5 1 0.5 0

0 0 0 0 0 0 0 0.5 1

MuD

_100 _75 _50 _25 0 25 50 75 100

1 0.5 0 0 0 0 0 0 0

0 0.5 1 0.5 0 0 0 0 0

0 0 0 0.5 1 0.5 0 0 0

0 0 0 0 0 0.5 1 0.5 0

0 0 0 0 0 0 0 0.5 1


The membership function clips the input parameters at the boundries of their respective domains. Finds the 2 columns that the parameter falls between and then does an interpolation to come up with the fuzzy membership of the input parameter.


member =: 4 : 0

v =: 0 { y NB. peal off the set boundries

m =: 1 }. y NB. pull out the fuzzy set matrix

l =: (0{v)>. x <. {:v NB. clip the input to the domain in v

i =: _1 + 1 >. +/v<x NB. find the beginning boundry where x is between

NB. Interpolate fuzzy membership by using the fuzzy sets that x lies between

NB. the index i tells the start set and i+1 0 gives us the indexes of the

NB. boundries between which x lies.

(i{"1 m)+(l - i{v)*(-/"1 (i+1 0){"1 m)%-/(i+1 0){v

)


So their example the find the membership for N=-25 that with the fuzzy sets MuN works as follows:


_25 member MuN

0 0.25 0.75 0 0


They then define fuzzy operations in APL2’s adverb style which translates directly into an adverb definition in J:


NB. adverb to turn a J verb into a fuzzy verb. Essentially perform

NB. an outer product with the J verb

fuzzy =: 1 : '(x member MuD) u/ (y member MuN)'


and now you can do fuzzy logic on input parameters as follows:


5 (* fuzzy) _50

0 0 0 0 0

0 0 0 0 0

0 0.45 0.45 0 0

0 0.05 0.05 0 0

0 0 0 0 0

5 (<. fuzzy) _50

0 0 0 0 0

0 0 0 0 0

0 0.5 0.5 0 0

0 0.1 0.1 0 0

0 0 0 0 0


They then go into control issues and develop a rule base for their application I won’t go into that. What becomes apparent in the J code above is that the fuzzy set definition is very regular. It can be built mechanically from J idioms as follows: The colums of MuN or MuD once the axis labels are removed are just and identity matrix and a lower diagonal matrix. The identity matrix values correspond to the peaks of the half triangle sets at the boundaries and 3 full triangles that span the inner part of the domain.


(i.5) =/ i.5

1 0 0 0 0

0 1 0 0 0

0 0 1 0 0

0 0 0 1 0

0 0 0 0 1


To create the 0.5 cross over columns of the set I just need to take the identity matrix and shift the columns down by 1 and add it back to the identity matrix and multiply by 0.5. I can do this with a fork as follows:


(] + |.!.0) (i.5) =/ i.5

1 0 0 0 0

1 1 0 0 0

0 1 1 0 0

0 0 1 1 0

0 0 0 1 1


Multiply this by 0.5 and drop the last column (if you look at MuN or MuD I just need the pattern of the first 4 columns to march the pattern), which I show below and save along with storing the identity matrix:


im=: (i.5) =/ i.5

im

1 0 0 0 0

0 1 0 0 0

0 0 1 0 0

0 0 0 1 0

0 0 0 0 1

xm=: _1}."1( 0.5*(] + |.!.0) (i.5) =/ i.5)

xm

0.5 0 0 0

0.5 0.5 0 0

0 0.5 0.5 0

0 0 0.5 0.5

0 0 0 0.5


and brings us to the question of how to interleave the columns of “xm" inbetween the columns of “im"? My first attempt was to splice the matrices together and build an index to place the columns where they belong. It works but it’s kind of ugly so I won’t show it. Doing a little search around Jsoftware.com I found the MRG verb in the phrases document. If I box columns of each matrix I can apply an easy to construct pattern and MRG will build the final fuzzy set matrix the way it is supposed to be (the catch is I have to transpose the matrix to capture the columns properly):


MRG=: /:@/:@[ { ]


|: >(9$0 1) MRG (;/ |:im),;/ |:xm

1 0.5 0 0 0 0 0 0 0

0 0.5 1 0.5 0 0 0 0 0

0 0 0 0.5 1 0.5 0 0 0

0 0 0 0 0 0.5 1 0.5 0

0 0 0 0 0 0 0 0.5 1


Which matches the set definitions originally stated in MuN and MuD. This isn’t bad in terms of the number of operators needed. But it does require that I calculate the 0 1 pattern ahead of time and there’s the boxing and unboxing that seem somewhat unnatural and minorly difficult to extend to problems where I may want more than just the 5 fuzzy set definitions.


So is there a way to interleave the columns of the 2 matrices in a more direct fashion?


Tom McGuire




Henry Rich

unread,
Apr 17, 2026, 5:59:49 AM (3 days ago) Apr 17
to forum
Away from my machine, but thinking of

_9 ]\ }: 46 $ 11 {. 0.5 1 0.5

Or

|: > }: , im ,:&:(<"1)&|: ix

Both untested.

Henry Rich

To unsubscribe from this group and stop receiving emails from it, send an email to forum+un...@jsoftware.com.

Igor Zhuravlov

unread,
Apr 17, 2026, 7:38:23 AM (3 days ago) Apr 17
to fo...@jsoftware.com
On Fri, Apr 17, 2026, 7:12 PM 'Thomas McGuire' via forum <
fo...@jsoftware.com> wrote:
> [...]
> So is there a way to interleave the columns of the 2 matrices in a more
> direct fashion?

NB. var. 1
(MRG"1~ 2 | i.@{:@$) im ,. xm
1 0.5 0 0 0 0 0 0 0
0 0.5 1 0.5 0 0 0 0 0
0 0 0 0.5 1 0.5 0 0 0
0 0 0 0 0 0.5 1 0.5 0
0 0 0 0 0 0 0 0.5 1

NB. var. 2
im ,/"2@:(,"0)&.(a:`(,"1&0 :. (}:"1))) xm
1 0.5 0 0 0 0 0 0 0
0 0.5 1 0.5 0 0 0 0 0
0 0 0 0.5 1 0.5 0 0 0
0 0 0 0 0 0.5 1 0.5 0
0 0 0 0 0 0 0 0.5 1

Tested with j9.7.0-beta14/j64/linux

--
Regards,
Igor



Igor Zhuravlov

unread,
Apr 17, 2026, 7:58:59 AM (3 days ago) Apr 17
to fo...@jsoftware.com
NB. var. 2 simplified
}:"1 ,/"2 ,"0/ im ,: xm
1 0.5 0 0 0 0 0 0 0
0 0.5 1 0.5 0 0 0 0 0
0 0 0 0.5 1 0.5 0 0 0
0 0 0 0 0 0.5 1 0.5 0
0 0 0 0 0 0 0 0.5 1

--
Regards,
Igor


Thomas McGuire

unread,
Apr 17, 2026, 9:47:07 AM (3 days ago) Apr 17
to fo...@jsoftware.com
Your first function needed a minor adjustment “}.” instead of “}:” we just want to get rid of the first 0.5 and then the pattern you set pushes everything to the proper location. I know you didn’t get time to test it but here it is corrected:

_9 ]\}.46 $ 11 {. 0.5 1 0.5


and then the second way you gave I had to add another transpose to get the merge to happen correctly:


|: >}:, |: im ,:&:(<"1)&|: xm


I like the first one in that it rethinks how to build the pattern over my build it in matrix form. 

Thanks for your response

Tom McGuire

Marcin Żołek

unread,
Apr 17, 2026, 10:24:18 AM (3 days ago) Apr 17
to fo...@jsoftware.com
If I understand correctly, Igor's var. 2 can be simplified even further by replacing ,/"2 with ,"2

   }:"1 ,"2 ,"0/ im ,: xm

I came up with this simplification because I think that, if both matrices had the same shape, the following would suffice:

   ,"2@:(,"0)

For example:

   ]a =: i. 3 4
0 1  2  3
4 5  6  7
8 9 10 11
   ]b =: 100 + a
100 101 102 103
104 105 106 107
108 109 110 111
   a ,"2@:(,"0) b
0 100 1 101  2 102  3 103
4 104 5 105  6 106  7 107
8 108 9 109 10 110 11 111

Thanks,
Marcin

P.S. I found a Vector article showing J in action where fuzzy logic is used for drawing fractals. Sample fractal from the article generated with up-to-date addon in Jqt:

load  '~addons/graphics/fvj4/raster.ijs'
NB. Probabilistic fuzzy logic.
por =: + - *
pand =: *
NB. Fractal.
m =: > ,/^:(_1: + #@$) { 3 # < (i. % <:) 8
b =: (por/ . pand |:) m
lin256 =: <.@(255.99&*)
view_image P256 ; lin256 b

Thomas McGuire

unread,
Apr 17, 2026, 11:05:49 AM (3 days ago) Apr 17
to fo...@jsoftware.com
I like var 1 since it fixes my box/unbox and calculates the size and still uses the MRG

Var 2 I was still trying to figure out until you sent out the simplification:

}:"1 ,/"2 ,"0/ im ,: xm

This one is nice since I can take it apart easily and see what each adverb is doing. 

Thanks Igor

Tom McGuire
Reply all
Reply to author
Forward
0 new messages