How to delete following columns from matrix in julia (specific case)

consider following matrix,

julia> b = [-1 1 0 0 0 0;1 -1 -1 1 0 0;0 0 1 -1 -1 1;0 0 0 0 1 -1]
4×6 Matrix{Int64}:
 -1   1   0   0   0   0
  1  -1  -1   1   0   0
  0   0   1  -1  -1   1 
  0   0   0   0   1  -1

how do i obtain following matrix from the b matrix


julia> bnew 
4×3 Matrix{Int64}:
 -1   0   0
  1  -1   0
  0   1  -1
  0   0   1

Basically, if [-1,1 ,0 ,0] is the column, then [1,-1,0,0] is called its reflection (and vice versa). What I want is… reflection, if at all present in the original matrix b to be deleted from the matrix while retaining the original column vector. Can we generalize this?

another example, if

julia> B=[-1 1 0 0;1 -1 -1 0;0 0 0 1]
3×4 Matrix{Int64}:
 -1   1   0  0
  1  -1  -1  0
  0   0   0  1

then output should be

julia> b=[-1 0 0;1 -1 0; 0 0 1]
3×3 Matrix{Int64}:
 -1   0  0
  1  -1  0
  0   0  1

Try this:

@views function remove_reflections(b)
    n = size(b,2)
    ix_drop = falses(n)
    for i = 1:n-1
        ix = i+1:n
        ix_drop[ix] .|= (Ref(-b[:,i]) .== eachcol(b[:,ix]))
    end
    return b[:, .!ix_drop]
end

For the provided examples it outputs:

b = [-1 1 0 0 0 0; 1 -1 -1 1 0 0; 0 0 1 -1 -1 1; 0 0 0 0 1 -1]
julia> remove_reflections(b)
 -1   0   0
  1  -1   0
  0   1  -1
  0   0   1

b = [-1 1 0 0; 1 -1 -1 0; 0 0 0 1]
julia> remove_reflections(b)
 -1   0  0
  1  -1  0
  0   0  1
2 Likes

@rafael.guerra
what is the following line doing ?

 ix_drop[ix] .= (ix_drop[ix] .| (Ref(-b[:,i]) .== eachcol(b[:,ix])))

It book keeps in the bitvector ix_drop the columns that are reflections of the column being analyzed in the loop. It does bitwise or not to erase (and to add) to previous entries.

NB: used now the simplified shorthand syntax .|=

1 Like

i think this works as a solution, but I will try to test more with other matrices(btw, input is incidence matrix from a directional graph, so -1,1,0 are the entries in such matrix)

Some other options for fun :slight_smile:

@views b[:, [i==1 || b[:,i] != -b[:,i-1] for i in 1:size(b,2)]]

@views b[:, [true; eachcol(b[:, 2:end]) .!= .-eachcol(b[:, 1:end-1])]]

@views b[:, [true
             map((c,prev) -> c != -prev, eachcol(b[:,2:end]), eachcol(b))]]

@views foldl(eachcol(b[:,2:end]), init=b[:,1]) do M, c
    c == -M[:,end] ? M : [M c]
end
2 Likes

@sudete, it’s amazing how much code you’ve managed to put into the matrix index. And it’s pretty damn fast!

2 Likes

yes uhm not sure if it’s great for readability but it’s fun :slight_smile:

2 Likes

@rafael.guerra @sudete
How did you learn Julia to begin with? I am surprised to little new syntax everytime I come here with some query

I think mostly by spending time here while procrastinating… But initially I put some time in reading the manual A-Z and experimenting with the concepts in each page.

2 Likes

I’m not in the best position to give advice because I’m really a beginner, but as a general rule, a good way to learn is to try to do small, useful personal projects, reading the manual and checking the forums for solutions and asking for help when you get stuck.

2 Likes

@rafael.guerra @sudete
Thanks for your kind replies. Both of your solution work for me. Thanks a lot

1 Like