SAGE + right_kernel() + basis matrix - sage

I executed the right_kernel() instruction for any binary matrix H. Why always I get a basis matrix in this form [I|A] (Where I:identity matrix)?

In general it is not the case that the basis matrix has the form [I|A].
According to the sage documentation the basis matrix is in echelon form by default.
For example
sage: H
[1 0 0 1 1]
[1 0 1 0 1]
[1 0 0 0 0]
sage: H.right_kernel()
Vector space of degree 5 and dimension 2 over Finite Field of size 2
Basis matrix:
[0 1 0 0 0]
[0 0 1 1 1]

Related

Create a mask array, where `1` are at max value index of given array

Given a matrix A = [1 5 3; 4 2 6]. How to create a new mask matrix where 1 values are at column-wise maximum value index mask = [0 1 0; 1 0 1]. How to do this in julia without mutating any created arrays.
With mutation I'm doing it the following way.
maxval, maxind = findmax(A, dims=1)
mask = zeros(size(A))
mask[maxind] .= 1
There's really nothing wrong with what you have (although I'd probably use falses instead of zeros). You could alternatively use broadcast, but I'd expect it to have similar performance:
julia> A = [1 5 3; 4 2 6]
2×3 Array{Int64,2}:
1 5 3
4 2 6
julia> A .== maximum(A, dims=1)
2×3 BitArray{2}:
0 1 0
1 0 1
(Note that unlike Python, we differentiate between matrices and vectors of vectors; you wrote them like the latter)

Repetitively taking XOR of consecutive elements

Given a binary array of size N
e.g. A[1:N] = 1 0 0 1 0 1 1 1
A new array of size N-1 will be created by taking XOR of 2 consecutive elements.
A'[1:N-1] = 1 0 1 1 1 0 0
Repeat this operation until one element is left.
1 0 0 1 0 1 1 1
1 0 1 1 1 0 0
1 1 0 0 1 0
0 1 0 1 1
1 1 1 0
0 0 1
0 1
1
I want to find the last element left (0 or 1)
One can find the answer by repetitively performing the operation. This approach will take O(N*N) time. Is there a way to solve the problem more efficiently?
There's a very efficient solution to this problem, which needs just a few lines of code, but it's rather complicated to explain. I'll have a go, anyway.
Suppose you need to reduce a list of, say, 6 numbers that are all zero except for one element. By symmetry, there are just three cases to consider:
1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0
1 0 0 0 0 1 1 0 0 0 0 1 1 0 0
1 0 0 0 0 1 0 0 1 0 1 0
1 0 0 1 1 0 1 1 1
1 0 0 1 0 0
1 1 0
In the first case, a single '1' at the edge doesn't really do anything much. It basically just stays put. But in the other two cases, more elements of the list get involved and the situation is more complex. A '1' in the second element of the list produces a result of '1', but a '1' in the third element produces a result of '0'. Is there a simple rule that explains this behaviour?
Yes, there is. Take a look at this:
Row 0: 1
Row 1: 1 1
Row 2: 1 2 1
Row 3: 1 3 3 1
Row 4: 1 4 6 4 1
Row 5: 1 5 10 10 5 1
I'm sure you've seen this before. It's Pascal's triangle, where each row is obtained by adding adjacent elements taken from the row above. The larger numbers in the middle of the triangle reflect the fact that these numbers are obtained by adding together values drawn from a broader subset of the preceding rows.
Notice that in Row 5, the two numbers in the middle are both even, while the other numbers are all odd. This exactly matches the behaviour of the three examples shown above; the XOR product of an even number of '1's is zero, and the XOR product of an odd number of '1's is '1'.
To make things clearer, let's just consider the parity of the numbers in this triangle (i.e., '1' for odd numbers, '0' for even numbers):
Row 0: 1
Row 1: 1 1
Row 2: 1 0 1
Row 3: 1 1 1 1
Row 4: 1 0 0 0 1
Row 5: 1 1 0 0 1 1
This is actually called a Sierpinski triangle. Where a zero appears in this triangle, it tells us that it doesn't matter if your list has a '1' or a '0' in this position; it will have no effect on the resulting value because if you wrote out the expression showing the value of the final result in terms of all the initial values in your list, this element would appear an even number of times.
Take a look at Row 4, for example. Every element is zero except at the extreme edges. That means if your list has 5 elements, the end result depends only on the first and last elements in the list. (The same applies to any list where the number of elements is one more than a power of 2.)
The rows of the Sierpinski triangle are easy to calculate. As mentioned in oeis.org/A047999:
Lucas's Theorem is that T(n,k) = 1 if and only if the 1's in the binary expansion of k are a subset of the 1's in the binary expansion of n; or equivalently, k AND NOT n is zero, where AND and NOT are bitwise operators.
So, after that long-winded explanation, here's my code:
def xor_reduction(a):
n, r = len(a), 0
for k in range(n):
b = 0 if k & -n > 0 else 1
r ^= b & a.pop()
return r
assert xor_reduction([1, 0, 0, 1, 0, 1, 1, 1]) == 1
I said it was short. In case you're wondering, the 4th line has k & -n (k AND minus n) instead of k & ~n (k AND not n) because n in this function is the number of elements in the list, which is one more than the row number, and ~(n-1) is the same thing as -n (in Python, at least).

How to find the index of the column of the minimum nonzero element across rows in Julia?

I have an nxm Array{Int64,2} in Julia. I would like to find for each row, the index of the column of the minimum element that is not zero. If the row is zero then return 0.
For example, for n=10 and m=2 and
julia> A
10×2 Array{Int64,2}:
2 0
1 1
8 7
0 0
3 8
0 0
0 0
2 4
5 1
6 0
I would like to return
julia> B
10-element Array{Int64,1}:
1
1
2
1
1
1
1
1
2
1
What I did is this:
B = zeros(Int64, n);
for i in 1:n
B[i] = findmin(A[i, :])[2];
end
but this does not work when there is a zero in some row...
You can also use mapslices and specify your function that works for a single row.
First, set up a matrix:
julia> A = [2 1; 1 2; -1 -2; 0 0; 0 5; 10 0]
6×2 Array{Int64,2}:
2 1
1 2
-1 -2
0 0
0 5
10 0
Create a function that finds the index of the minimal non-zero elements per row:
function findmincol(row)
# handle the special case when all elements are 0
if all(row .== 0)
return 0
end
# check the number of zero elements
length_zero = sum(row .== 0)
# find the min among non-zero elements
filter!(x -> x != 0, row)
return findmin(row)[2] + length_zero
end
Then you can use mapslices to map the the findmincol function to each row of A:
mapslices(findmincol, A, dims=2)
This gives you (what I think is) the correct solution:
6×1 Array{Int64,2}:
2
1
2
0
2
1
Most functions (sum, minimum, find, findmin, etc) take a dims keyword argument to specify the axis along which to do said operation:
Ex
findmin(rand(3, 4), dims=1)
([0.15952 0.0289172 0.409214 0.195433], CartesianIndex{2}[CartesianIndex(3, 1)
CartesianIndex(2, 2) CartesianIndex(3, 3) CartesianIndex(3, 4)])
returns the actual minima and the locations, as Cartesian Indices, as two separate arrays
So:
v, i = findmin(randn(10, 2), dims=2)
i = map(t -> t[2], i)
i[v .== 0] .= 0
The Cartesian Index is a little weird, but apparently used frequently for multi-dimensional indexing

How to define a matrix using if and for loops in sagemath?

I am using sagemath for my computations.
Now, from R I have the codes to generate a matrix of size $2r\times 2r$ from the following codes..
n=10
k=10
r=5
x=matrix(data=NA, nrow=n, ncol=k)
for(j in 1:k){
for(i in 1:n){
if (i==j){x[i,j]=0}
if ((i<=r)&(i<j)&(j<=r)) {x[i,j]=2}
if ((i<=r)&(i>j)&(j<=r)) {x[i,j]=2}
if ((i<=r)&(j>r)){x[i,j]=1}
if ((i>r)&(j<=r)) {x[i,j]=1}
if ((i>r)&(j>r)){x[i,j]=0}
if ((i>r)& (i<j) &(j>r)){x[i,j]=2}
if ((i>r)& (i>j) &(j>r)){x[i,j]=2}
}
}
x
How can I do the same in SageMath?
When constructing a matrix in Sagemath, you can pass in a function that computes its entries, which eliminates the need for explicit (and generally inefficient) loops. This function is defined below as xentries: I used the same conditionals as in your post, but grouped them for readability.
def xentries(i, j, r):
if i == j or (i > r and j > r):
return 0
if (i <= r and j > r) or (i > r and j <= r):
return 1
return 2
n = 10
k = 10
r = 5
x = matrix(ZZ, n, k, lambda i, j: xentries(i, j, r))
Here, ZZ means the integers, and is used to indicate that the matrix has integer entries. It could be rational QQ or real RR. The other arguments are the size of the matrix, and the function that constructs its entries. The matrix x is now the following:
[0 2 2 2 2 2 1 1 1 1]
[2 0 2 2 2 2 1 1 1 1]
[2 2 0 2 2 2 1 1 1 1]
[2 2 2 0 2 2 1 1 1 1]
[2 2 2 2 0 2 1 1 1 1]
[2 2 2 2 2 0 1 1 1 1]
[1 1 1 1 1 1 0 0 0 0]
[1 1 1 1 1 1 0 0 0 0]
[1 1 1 1 1 1 0 0 0 0]
[1 1 1 1 1 1 0 0 0 0]

R: Generate a list of canonical matrix

Here is my question.
I'm trying to create a list with all the symmetric canonical matrix of size nxn with a diagonal of 1,..,1 and k element equal to one in each triangle.
For instance if n=3 and k=2, I want to generate all 3x3 matrix symmetric with 1,1,1 diagonal and 2 element equal to 1 up and below the diagonale:
1 1 1
1 1 0
1 0 1
And
1 1 0
1 1 1
0 1 1
And
1 1 0
1 1 1
0 1 1
And
1 0 1
0 1 1
1 1 1
Can you help me ?
Regards
I don't understand why you generate the second matrix twice. So the solution below just creates all unique symmetric matrices with the desired properties. If you want some of them twice, you will have to tweak the code a bit.
# load required packages
require(plyr)
# function to generate a list of "canonical matrices"
generate.canonical.matrix <- function(n, k){
# initialize
m <- matrix(0, nrow=n, ncol=n)
# number of positions in the upper triangle
K <- n*(n-1)/2
if (K<k) stop("k cannot be larger than n*(n-1)/2")
# upper triangle matrix
upper <- which(upper.tri(m))
# for all combinations of k elements
alply(combn(K, k), 2, function(index){ # CHANGE combn(K, k) TO GET NON-UNIQUE MATRICES
# set upper tirangle matrix
m[upper[index]] <- 1
# combine upper, lower and diagonal matrices
m+t(m)+diag(n)
})
}
# function call
generate.canonical.matrix(3, 2)

Resources