Number of linear independent subsets with cardinality 4 - sage

I have a list of vectors in the vector space Q with a dimension of 5, which I want to order in a list and use Combinations(list, 4) to get all sublists with 4 elements. I then want to
check how many of those sublists are linear independent in the Vector Space with V.linear dependence(vs) == [].
I'm running into an error when running my code:
V = VectorSpace(QQ,5)
V.list = ([2, 2, 2,-3,-3],[2, 2,-3,2,-3],[2,2,-3,-3,2],[2,-3,2,2,-3],[2,-3,2,-3,2],[2,-3,-3,2,2],[-3,2,2,2,-3],[-3,2,2,-3,2],[-3,2,-3,2,2],[-3,-3,2,2,2])
C = Combinations(list, 4)
V.linear_dependence(C) == []
"ValueError: vector [[2, 2, 2, -3, -3], [2, 2, -3, 2, -3], [2, 2, -3, -3, 2], [2, -3, 2, 2, -3]] is not an element of Vector space of dimension 5 over Rational Field"
Anyone got any clues as to what im missing?

You are asking it to just take a list (or actually, tuple) and put it in the vector space, but I think Sage doesn't do that automatically. Try this.
V = VectorSpace(QQ,5)
list = ([2, 2, 2,-3,-3],[2, 2,-3,2,-3],[2,2,-3,-3,2],[2,-3,2,2,-3],[2,-3,2,-3,2],[2,-3,-3,2,2],[-3,2,2,2,-3],[-3,2,2,-3,2],[-3,2,-3,2,2],[-3,-3,2,2,2])
C = Combinations(list, 4)
for c in C:
if V.linear_dependence([V(x) for x in c]) == []: print c
The reason for a double list is that neither of these things are inherently in a vector space.
A slight modification to this, replacing print c with z+=1 (having predefined z=0) says that 185 of your 210 combinations appear to be linearly independent.
By the way, comparing to the empty list might not be as efficient as other options.

Related

Apply custom pairwise function in PyTorch

I have two 1D tensors
a = tensor([1, 2])
b = tensor([3, 4, 5])
I want to compute custom operation pairwise matrix, for example
"a + b" - adds every element from a to every element from b
tensor([4, 5, 6], [5, 6, 7])
"a / b" - divides every element from a by every element from b
tensor([1/3, 1/4, 1/5], [2/3, 2/4, 2/5])
Can this be done efficiently, without for cycles?
Yes, you can do that element-wise in a vectorised form.
First bring the operands to broadcastable shapes (You can read about the pytorch broadcasting semantics here)
a = a.unsqueeze(-1) # a.shape == (2, 1)
b = b.unsqueeze(-2) # b.shape == (1, 3)
# the last line is redundant in fact, according to the semantics
Then apply the operation you want:
c = a / b # c.shape == (2, 3)

Julia - Repeat entries of a vector by another vector (inner)

I have an array x and I would like to repeat each entry of x a number of times specified by the corresponding entries of another array y, of the same length of x.
x = [1, 2, 3, 4, 5] # Array to be repeated
y = [3, 2, 1, 2, 3] # Repetitions for each element of x
# result should be [1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5]
Is there a way to do this in Julia?
Your x and y vectors constitute what is called a run-length encoding of the vector [1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5]. So if you take the inverse of the run-length encoding, you will get the vector you are looking for. The StatsBase.jl package contains the rle and inverse_rle functions. We can use inverse_rle like this:
julia> using StatsBase
julia> x = [1, 2, 3, 4, 5];
julia> y = [3, 2, 1, 2, 3];
julia> inverse_rle(x, y)
11-element Vector{Int64}:
1
1
1
2
2
3
4
4
5
5
5
You've given what I would have suggested as the answer already in your comment:
vcat(fill.(x, y)...)
How does this work? Start with fill:
help?> fill
fill(x, dims::Tuple)
fill(x, dims...)
Create an array filled with the value x. For example, fill(1.0, (5,5)) returns a 5×5 array of floats, with each element initialized to 1.0.
This is a bit more complicated than it needs to be for our case (where we only have one dimension to fill into), so let's look at a simple example:
julia> fill(1, 3)
3-element Vector{Int64}:
1
1
1
so fill(1, 3) just means "take the number one, and put this number into a one-dimensional array 3 times."
This of course is exactly what we want to do here: for every element in x, we want an array that holds this element multiple times, with the multiple given by the corresponding element in y. We could therefore loop over x and y and do something like:
julia> for (xᵢ, yᵢ) ∈ zip(x, y)
fill(xᵢ, yᵢ)
end
Now this loop doesn't return anything, so we'd have to preallocate some storage and assign to that within the loop. A more concise way of writing this while automatically returning an object would be a comprehension:
julia> [fill(xᵢ, yᵢ) for (xᵢ, yᵢ) ∈ zip(x, y)]
5-element Vector{Vector{Int64}}:
[1, 1, 1]
[2, 2]
[3]
[4, 4]
[5, 5, 5]
and even more concisely, we can just use broadcasting:
julia> fill.(x, y)
5-element Vector{Vector{Int64}}:
[1, 1, 1]
[2, 2]
[3]
[4, 4]
[5, 5, 5]
so from the comprehension or the broadcast we are getting a vector of vectors, each vector being an element of x repeated y times. Now all that remains is to put these together into a single vector by concatenating them vertically:
julia> vcat(fill.(x, y)...)
11-element Vector{Int64}:
1
1
1
2
2
3
4
4
5
5
5
Here we are using splatting to essentially do:
z = fill.(x, y)
vcat(z[1], z[2], z[3], z[4], z[5])
Note that splatting can have suboptimal performance for arrays of variable length, so a better way is to use reduce which is special cased for this and will give the same result:
reduce(vcat, fill.(x, y))
If performance is a priority, you can also do it the long, manual way:
function runlengthdecode(vals::Vector{T}, reps::Vector{<:Integer}) where T
length(vals) == length(reps) || throw(ArgumentError("Same number of values and counts expected"))
result = Vector{T}(undef, sum(reps))
resind = 1
for (valind, numrep) in enumerate(reps)
for i in 1:numrep
#inbounds result[resind] = vals[valind]
resind += 1
end
end
result
end
This runs about 12 times faster than the vcat/fill based method for the given data, likely because of avoiding creating all the intermediate filled vectors.
You can also instead use fill! on the preallocated result's #views, by replacing the loop in above code with:
for (val, numrep) in zip(vals, reps)
fill!(#view(result[resind:resind + numrep - 1]), val)
resind += numrep
end
which has comparable performance.
Also, for completeness, a comprehension can be quite handy for this. And it's faster than fill and vcat.
julia> [x[i] for i=1:length(x) for j=1:y[i]]
11-element Vector{Int64}:
1
1
1
2
2
3
4
4
5
5
5

How to pass an arbitrary number of arguments to R function without for loop?

My question is about getting rid of a for loop while retaining the functionality of the code.
I have a matrix of pairwise orderings of elements A_1, A_2, ... A_N. Each ordering is represented as a row of a matrix. The code below shows an example.
# Matrix representing the relations
# A1 < A2, A1 < A5, A2 < A4
(mat <- matrix(c(1, 2, 1, 5, 2, 4), ncol = 2, byrow = TRUE))
#> [,1] [,2]
#> [1,] 1 2
#> [2,] 1 5
#> [3,] 2 4
I want this whole matrix as a set of ordered pairs. The reason is that I later need to generate the transitive closure of these relations. I have been using the sets package and created the function below.
create_sets <- function(mat){
# Empty set
my_set <- sets::set()
# For loop for adding pair elements to the set, one at a time
for(i in seq(from = 1, to = nrow(mat), by = 1)){
my_set <- sets::set_union(my_set,
sets::pair(mat[[i, 1]], mat[[i, 2]]))
}
return(my_set)
}
create_sets(mat)
#> {(1, 2), (1, 5), (2, 4)}
This function works well, but I believe the for loop is unnecessary, and am not capable of replacing it. For the particular example matrix above with exactly three rows, I could instead have used to following code:
my_set2 <- sets::set(
sets::pair(mat[[1, 1]], mat[[1, 2]]),
sets::pair(mat[[2, 1]], mat[[2, 2]]),
sets::pair(mat[[3, 1]], mat[[3, 2]])
)
my_set2
#> {(1, 2), (1, 5), (2, 4)}
The reason why this works, is that sets::set takes any number of pairs.
args(sets::set)
#> function (...)
#> NULL
However, the matrix mat will have an arbitrary number of rows, and I want the function to be able to handle all possible cases. This is why I have not been able to get rid of the for loop.
My question is hence: Given a matrix mat in which each row represents an ordered pair, is there some generic way of passing the pairs in each row as separate arguments to sets::set, without looping?
The OP has asked
[...] is there some generic way of passing the pairs in each row as separate arguments to sets::set, without looping?
Yes, the do.call() function is probably what you are looking for. From help(do.call):
do.call constructs and executes a function call from a name or a function and a list of arguments to be passed to it.
So, OP's create_sets() function can be replaced by
do.call(sets::set, apply(mat, 1, function(x) sets::pair(x[1], x[2])))
{(1, 2), (1, 5), (2, 4)}
The second argument to do.call() requires a list. This is created by
apply(mat, 1, function(x) sets::pair(x[1], x[2]))
which returns the list
[[1]]
(1, 2)
[[2]]
(1, 5)
[[3]]
(2, 4)
apply(mat, 1, FUN) is a kind of implied for loop which loops over the rows of a matrix mat and takes the vector of row values as argument when calling function FUN.
Edit: as.tuple() instead of pair()
The pair() function requires exactly two arguments. This is why we were forced to define an anonymous function function(x) sets::pair(x[1], x[2]).
The as.tuple() function coerces the elements of an object into elements of a set. So, the code can be even more simplified :
do.call(sets::set, apply(mat, 1, sets::as.tuple))
{(1, 2), (1, 5), (2, 4)}
Here, as.tuple() takes the whole vector of row values and coerces it to a set.
Option 1: do nothing
for loops aren't always the end of the world, this doesn't look too bad if your matrices aren't enormous.
Option 2: the split, apply, combine way (by way of a new function)
Write a function that combines the row things (there is a shorter way to do this, but this makes your task explicit)
f <- function(x) {
sets::pair(x[1], x[2])
}
Reduce(sets::set_union, lapply(split(mat, 1:nrow(mat)), f))
## {(1, 2), (1, 5), (2, 4)}
The Reduce does the same thing as the for loop (repeatedly apply set_union), and the lapply turns the matrix into a list of pairs (also like a for loop would)

R-Common elements on all pairwise comparisons of elements of a vector

I have a vector in R, say c(2, 2, 3, 2, 3, 4, 4), and I want to build a square matrix of size n (the number of elements of the vector) that has a 1 if the element i of the vector has the same value of the element j , and 0 otherwise. In this example , the element [1,2] and [1,4] of the matrix must have a 1 because the first, second and fourth elements of the vector are the same.
Is there a way to do this ? A command or function to build ? Something with combinations ? I would like to avoid loops like for.
Thank you !
This just came to my mind... Is this what you want?
a <- c(2, 2, 3, 2, 3, 4, 4)
mat <- a%*%t(a)
apply(mat, 2, function(x){as.integer((x/a)==a)})
We can use outer to create a square matrix by comparing each element of the vector with the other elements
+(outer(v1, v1, `==`))
Or use sapply
+(sapply(v1, `==`, v1))

R - how to get a value of a multi-dimensional array by a vector of indices

Let's say I have a multi-dimensional array called pi, and its number of dimensions isn't known until the runtime:
dims <- rep(3, dim_count)
pi <- array(0, dims)
As you can see the dimension count depends on dim_count. How do I retrieve a value from the array when I have a vector of the indexes? For example when I have:
dim_count <- 5
indexes <- c(1, 2, 3, 3, 3)
I want to retrieve
pi[1, 2, 3, 3, 3]
Is there a short, effective and hopefully elegant way of doing this?
Making use of a little known usage of [:
When indexing arrays by [ a single argument i can be a matrix with as many columns as there are dimensions of x; the result is then a vector with elements corresponding to the sets of indices in each row of i.
you can simply do:
pi[matrix(indexes, 1)]
do.call("[",...) seems to work.
indexes <- c(1,2,3,3,3)
pi[1,2,3,3,3] <- 17 ## so we know if we succeeded or not
do.call("[",c(list(pi),as.list(indexes)))
Note that your example wouldn't work -- your dimensions were all 3, but some of your index elements were >3 ...
do.call() is an option:
dim_count <- 5
indexes <- c(1, 2, 2, 2, 3)
dims <- rep(3, dim_count)
pi <- array(seq_len(prod(dims)), dims)
do.call(`[`, c(list(x = pi), as.list(indexes)))
Which gives:
> do.call(`[`, c(list(x = pi), as.list(indexes)))
[1] 202
> pi[1, 2, 2, 2, 3]
[1] 202
The tricky bit is getting the list of arguments in the right format. pi should be the first argument to "[" (or named as argument x, see ?"["), whilst we want each element of indexes itself to be a component of the supplied list, not a vector within that list. Hence the convoluted c(list(x = pi), as.list(indexes)).
An alternative way to construct the argument list which might be easier to follow is:
ARGS <- vector("list", length = dim_count + 1)
ARGS[[1]] <- pi
ARGS[2:length(ARGS)] <- indexes
do.call("[", ARGS)
which gives
> do.call("[", ARGS)
[1] 202
> pi[1, 2, 2, 2, 3]
[1] 202

Resources