SAGE returning wrong minimal polynomial? - sage

sage: A
[ t 1 1 0 t + 1 1]
[ t t 0 t + 1 t 1]
[ 0 1 t + 1 0 t 0]
[ t t 0 0 0 0]
[ 0 1 0 1 1 1]
[ t 1 t t t 1]
sage: A.base_ring()
Finite Field in t of size 2^2
sage: A.minpoly()
x^5 + (t + 1)*x^4 + t*x^3
sage: A.minpoly()(A)
[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]
[1 1 1 1 1 1]
The result of the last command should have been the zero matrix, of course. I have no idea why it failed. So the question is what went wrong.

I can't reproduce this on OS X 10.6.8:
sage: version()
'Sage Version 4.8, Release Date: 2012-01-20'
sage: R.<t> = GF(4)
sage: R
Finite Field in t of size 2^2
sage: A = Matrix(R, [[t, 1, 1, 0, t+1, 1], [t,t,0,t+1,t,1,],[0,1,t+1,0,t,0],[t,t,0,0,0,0,],[0,1,0,1,1,1,],[t,1,t,t,t,1]])
sage: A
[ t 1 1 0 t + 1 1]
[ t t 0 t + 1 t 1]
[ 0 1 t + 1 0 t 0]
[ t t 0 0 0 0]
[ 0 1 0 1 1 1]
[ t 1 t t t 1]
sage: s = """
....: [ t 1 1 0 t + 1 1]
....: [ t t 0 t + 1 t 1]
....: [ 0 1 t + 1 0 t 0]
....: [ t t 0 0 0 0]
....: [ 0 1 0 1 1 1]
....: [ t 1 t t t 1]"""
sage:
sage: str(A) == s.strip()
True
sage: A.minpoly()
x^6 + (t + 1)*x^5 + t*x^4
sage: A.minpoly()(A)
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
Note the extra factor of x. You didn't post your version number or any information about your architecture, so I don't know if it's an architecture-dependent linear algebra bug which is still present or one which has been fixed. Sage 5.0 will be coming out relatively soon (it's currently at beta12) and upgrading is highly recommended.
Two meta-notes: Please post code that can be copied and pasted to reproduce the problem. Also, you can always test your snippet on sagenb.org (or even test.sagenb.org) to see if your problem is still present in mainline and beyond. Both seem to give the right answer.

Related

Why doesn't PostScript have arcus cosinus, and how to fix it?

I found a formula for getting the angle between two 3D vectors (e.g. as shown in https://stackoverflow.com/a/12230083/6607497).
However when trying to implement it in PostScript I realized that PostScript lacks the arcus cosinus function needed to get the angle.
Why doesn't PostScript have that function and how would a work-around look like?
In Wikipedia I found the formula
$\arccos(x)={\frac {\pi }{2}}-\arctan \left({\frac {x}{\sqrt {1-x^{2}}}}\right)}$, but that looks a bit complicated; and if it's not: Why didn't they add acos (arcus cosinus) using that definition?
Did I miss something obvious?
As indicated in Wikipedia and done in pst-math, acos can be implemented rather easily using atan and sqrt (among other primitives) like this:
GS>% arcus cosinus, using degrees
GS>/acos { dup dup mul neg 1.0 add sqrt exch atan } bind def
GS>1 acos ==
0.0
GS>-1 acos ==
180.0
GS>0 acos ==
90.0
However this may be less efficient than a native implementation.
As the comments indicated, if the only purpose for arcus cosinus is to get the angle between two vectors, another approach using the two-parameter atan is preferable.
I ran some experiments in C and Kahan's formula 2 * atan2 (norm (x * norm (y) - norm (x) * y), norm (x * norm (y) + norm (x) * y)) works well, as does the more commonly used atan2 (norm (cross (x, y)), dot (x, y)). Best I can tell, C's atan2 is equivalent to Postscript's two-argument atan function. –
njuffa -Oct 23 at 23:21
So I tried to implement it (for 3D vectors (x y z)):
First the norm (length), named n3:
% norm 3D vector
%(x y z)
/n3 { dup mul exch dup mul add exch dup mul add sqrt } def
Then three helpers to multiply (v3m), add (v3a), and subtract (v3s) 3D vectors (for those not fearing stack rotations):
% multiply 3D vector with factor
%(x y z f)
/v3m {
dup 3 1 roll mul 4 1 roll %(z*f x y f)
dup 3 1 roll mul 3 1 roll %(z*f y*f x f)
mul exch 3 -1 roll %(x*f y*f z*f)
} def
% subtract 3D vectors
%(x1 y1 z1 x2 y2 z2)
/v3s {
6 -3 roll %(x2 y2 z2 x1 y1 z1)
4 -1 roll sub %(x2 y2 x1 y1 z1-z2)
5 1 roll 3 -1 roll sub %(z1-z2 x2 x1 y1-y2)
4 1 roll exch sub %(y1-y2 z1-z2 x1-x2)
3 1 roll %(x1-x2 y1-y2 z1-z2)
} def
% add 3D vectors
%(x1 y1 z1 x2 y2 z2)
/v3a {
4 -1 roll add %(x1 y1 x2 y2 z2+z1)
5 1 roll 3 -1 roll add %(z2+z1 x1 x2 y2+y1)
4 1 roll add %(y2+y1 z2+z1 x1+x2)
3 1 roll %(x1+x2 y2+y1 z2+z1)
} def
Eventually the angle function (a) is a bit different, because I wanted to avoid heavy stack shuffling, so converted the vectors to arrays and assigned the arrays to a name each.
I think it makes the code also a bit more readable, while a bit less efficient (you may try to use copy to duplicate the vectors' coordinates without using arrays and names (and the additional local dictionary):
% angle between two 3D vectors
%(x1 y1 z1 x2 y2 z2)
/a {
[ 4 1 roll ]
4 1 roll
[ 4 1 roll ]
%([v2] [v1])
2 dict begin
/v1 exch def
/v2 exch def
v1 aload pop n3 v2 aload pop
4 -1 roll v3m
%(|v1|*v2)
v2 aload pop n3 v1 aload pop
4 -1 roll v3m
%(|v1|*v2 |v2|*v1)
v3s n3
%(||v1|*v2-|v2|*v1|)
v1 aload pop n3 v2 aload pop
4 -1 roll v3m
%(|v1|*v2)
v2 aload pop n3 v1 aload pop
4 -1 roll v3m
%(|v1|*v2 |v2|*v1)
v3a n3
%(||v1|*v2-|v2|*v1| ||v1|*v2+|v2|*v1|)
atan
%(atan(||v1|*v2-|v2|*v1|,||v1|*v2+|v2|*v1|))
2.0 mul
end
} def
Finally here are some test cases:
GS>0 0 1 0 0 1 a ==
0.0
GS>0 0 1 0 1 0 a ==
90.0
GS>0 0 1 0 1 1 a ==
45.0
GS>0 0 1 1 0 0 a ==
90.0
GS>0 0 1 1 0 1 a ==
45.0
GS>0 0 1 1 1 0 a ==
90.0
GS>0 0 1 1 1 1 a ==
54.7356071
%
GS>0 1 0 0 0 1 a ==
90.0
GS>0 1 0 0 1 0 a ==
0.0
GS>0 1 0 0 1 1 a ==
45.0
GS>0 1 0 1 0 0 a ==
90.0
GS>0 1 0 1 0 1 a ==
90.0
GS>0 1 0 1 1 0 a ==
45.0
GS>0 1 0 1 1 1 a ==
54.7356071
%
GS>0 1 1 0 0 1 a ==
45.0
GS>0 1 1 0 1 0 a ==
45.0
GS>0 1 1 0 1 1 a ==
0.0
GS>0 1 1 1 0 0 a ==
90.0
GS>0 1 1 1 0 1 a ==
59.9999962
GS>0 1 1 1 1 0 a ==
59.9999962
GS>0 1 1 1 1 1 a ==
35.264389
%
GS>1 0 0 0 0 1 a ==
90.0
GS>1 0 0 0 1 0 a ==
90.0
GS>1 0 0 0 1 1 a ==
90.0
GS>1 0 0 1 0 0 a ==
0.0
GS>1 0 0 1 0 1 a ==
45.0
GS>1 0 0 1 1 0 a ==
45.0
GS>1 0 0 1 1 1 a ==
54.7356071
%
GS>1 0 1 0 0 1 a ==
45.0
GS>1 0 1 1 1 0 a ==
59.9999962
GS>1 0 1 0 1 1 a ==
59.9999962
GS>1 0 1 1 0 0 a ==
45.0
GS>1 0 1 1 0 1 a ==
0.0
GS>1 0 1 1 1 0 a ==
59.9999962
GS>1 0 1 1 1 1 a ==
35.264389
%
GS>1 1 0 0 0 1 a ==
90.0
GS>1 1 0 0 1 0 a ==
45.0
GS>1 1 0 0 1 1 a ==
59.9999962
GS>1 1 0 1 0 0 a ==
45.0
GS>1 1 0 1 0 1 a ==
59.9999962
GS>1 1 0 1 1 0 a ==
0.0
GS>1 1 0 1 1 1 a ==
35.264389
%
GS>1 1 1 0 0 1 a ==
54.7356071
GS>1 1 1 0 1 0 a ==
54.7356071
GS>1 1 1 0 1 1 a ==
35.264389
GS>1 1 1 1 0 0 a ==
54.7356071
GS>1 1 1 1 0 1 a ==
35.264389
GS>1 1 1 1 1 0 a ==
35.264389
GS>1 1 1 1 1 1 a ==
0.0
I hope I didn't mess it up.

Create sequence of binary values with a minimum run length

I want to create a random sequence of 0 or 1 of a certain length, say 100. My only restriction is that the number must be at least in two consecutive periods.
Example of correct sequence, where all runs have at least two values:
1 1 0 0 0 1 1 1 0 0 0
Example of incorrect sequence, where some runs have less than two values:
1 0 0 1 0 1 1 1 0 1 1
^ ^ ^
This is my code, but is not working:
x <- NULL
x[1] <- sample(c(0, 1), replace = TRUE, size = 1)
for(i in 2:100){
x[i] <- sample(c(0, 1), replace = TRUE, size = 1)
x[i] <- if(x[i] + x[i-1] == 1){
if(x[i-1] == 1){
1
} else {
0
}
} else {
sample(c(0, 1), replace = TRUE, size = 1)
}
}
print(x)
Here is a simple version. The first value of x is set to a random binomial number (0 or 1). The second value must be the same as the first. Then, the following code checks for each iteration if the two previous values are the same. If they are, then a random binomial is generated. If not, then x[i-1] is assigned as x[i] also.
set.seed(1234)
n <- 100
x <- numeric(n)
x[1] <- rbinom(1, 1, .5)
x[2] <- x[1]
for(i in 3:n) {
if(x[i-1] == x[i-2]) {
x[i] <- rbinom(1, 1, .5)
} else {
x[i] <- x[i-1]
}
}
x
[1] 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 0 0 1 1 0 0 0 1 1 1 1 1 0 0
[59] 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 0 0 0 0 0 1 1 0 0 1 1
Here is a function version to generate any length (n), while allowing you to change the probability of getting a 1 over a 0.
my_func <- function(n, prob = 0.5) {
x <- numeric(n)
x[1] <- rbinom(1, 1, prob)
x[2] <- x[1]
for(i in 3:n) {
if(x[i-1] == x[i-2]) {
x[i] <- rbinom(1, 1, prob)
} else {
x[i] <- x[i-1]
}
}
x
}
set.seed(1234)
my_func(n = 10, prob = 0.9)
[1] 1 1 1 1 1 1 1 1 1 1
Here is one way using a variable called consecutive_count which counts how many consecutive same values has been created in the series.
set.seed(1432)
#Initialise the vector of size 100
x <- numeric(100)
#Get the 1st value
x[1] <- sample(c(0,1), 1)
consecutive_count <- 1
for(i in 2:100){
#If the count is less than 2, repeat the previous value
if(consecutive_count < 2){
x[i] <- x[i-1]
#Increment the counter
consecutive_count <- consecutive_count + 1
} else {
#Randomly assign 1 or 0
x[i] <- sample(c(0,1), 1)
#If the count is same as previous value increment the count
#Or set consecutive_count to 1.
if(x[i] == x[i-1]) consecutive_count <- consecutive_count + 1
else consecutive_count <- 1
}
}
x
x
#[1] 0 0 0 1 1 0 0 1 1 0 0 0 1 1 0 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1
#[39] 0 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 1
#[77] 1 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 0 0 1 1 1 1 0 0

subscripting not working in R

I have this simple code and it is driving me nuts. The code is simply looping through a vector and subscripting parts of it.
preda <- function(d, k) {
n <- length(d)
cat("Length: ", n, "Loop:", k+1, "-", n, "\n")
for(i in seq(from=k+1, to=n, by=1)) {
cat("Index: ", i, "; Subscript Start: ", i-k, "; End: ", i-1, "\n")
cat("Value: ", d[i-k:i-1], "\n") # on first loop, this should do 1:3
}
}
The output
> X = sample(0:1,100,replace=T)
> preda(X, 3)
Length: 100 Loop: 4 - 100
Index: 4; Subscript Start: 1 End: 3
#it doesn't subscript here.
Value: 0 0 1 0 1 1 0 1 0 1 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 1 1 1 0 1 0 1 1 1 1 0 1 1 1 1 0 0 0 1 1 1 0 0 0 0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 0 0 0 1 0 1 1 0 0 0 0 0 1 0 1 0 1 1 0 0 1 0 1 1 0 0 1 1 1 1 1 0 0
Index: 5 St: 2 En: 4
Error in d[i - k:i - 1] : only 0's may be mixed with negative subscripts
What am I missing?
It seems that you are having problems with the colon operator (:). Swithcing to d[(i-k):(i-1)] will solve the issue:
#> preda(X,3)
#Length: 100 Loop: 4 - 100
#Index: 4 ; Subscript Start: 1 ; End: 3
#Value: 0 0 0
#Index: 5 ; Subscript Start: 2 ; End: 4
#Value: 0 0 1
#...
Remember that the colon operator (see help(":")) needs two arguments (a and b) so a parenthesis will keep things tidy.

How to construct this binary variable in R?

The aim is check if value at index i is 1 and then make the previous six entries as 1.
x <- c(0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1)
## Required output
y <- c(1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1)
## Attempt
for(j in seq_along(x)){
if(x[j] == 1){
for(i in (j-6):j)
x[i] = 1
}}
Could you help solve this or better approach ?
Thanks.
A fully vectorized solution using filter:
as.integer( #turn logical value into numbers
as.logical( #coerce to logical --> 0 becomes FALSE, everything else TRUE
rev( #reverse order
filter( #linear filtering
c(rep(0, 6), #pad with zeros in the beginning to avoid NAs
rev(x)), #revers order of input vector
c(rep(1, 7)), sides=1 #y_i = x_i * 1 + x_(i-1) * 1 +...+ x_(i-6) * 1
)[-(1:6)]))) #remove NA values
#[1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
You could try the following options (though don't forget to initialize x when trying each option as I'm overriding it)
indx <- mapply(function(x, y) x:y, which(x == 1) - 6 , which(x == 1))
x[indx[indx > 0]] <- 1
x
## [1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
Or even simpler
indx <- sapply(which(x == 1) - 6, function(x) x:(x + 6))
x[indx[indx > 0]] <- 1
x
## [1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
Or
indx <- apply(cbind(which(x == 1) - 6 , which(x == 1)), 1, function(x) x[1]:x[2])
x[indx[indx > 0]] <- 1
x
## [1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
Or
indx <- seq_len(6)
indx <- sapply(which(x == 1), function(x) x - indx)
x[indx[indx > 0]] <- 1
x
## [1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
Using 'for' loop:
ddf = data.frame(x,y=0)
for(i in 1:nrow(ddf)){
if(ddf[i,'x']==1){
j = i-5
if(j<1) j=1
ddf[j:i,'y'] = 1
}
}
ddf
x y
1 0 1
2 0 1
3 0 1
4 1 1
5 0 0
6 0 0
7 0 0
8 0 0
9 0 0
10 0 0
11 0 0
12 0 1
13 0 1
14 0 1
15 0 1
16 0 1
17 1 1
18 0 1
19 1 1
y = ddf$y
y
[1] 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
y<-x
y[unlist(sapply(which(x==1),
function(val){
val:(max(val-6,1))
}
)
)
]<-1
> y
[1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
Explanation :
I first look for indices of x=1 with which(x==1). Then, for each of the indices I get the indices from the one with x=1 to the 6th before that with sapply(...) then I unlist the result to only have a vector of indices for which y must be 1.
I then assigned 1 to the corresponding y values.
another writing, in 2 steps :
y<-x
ind<-unlist(sapply(which(x==1),function(val){val:(max(val-6,1))}))
y[ind]<-1
> y
[1] 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1

Using loop to make column selections using different vectors

Let's say I have 3 vectors (strings of 10):
X <- c(1,1,0,1,0, 1,1, 0, NA,NA)
H <- c(0,0,1,0,NA,1,NA,1, 1, 1 )
I <- c(0,0,0,0,0, 1,NA,NA,NA,1 )
Data.frame Y contains 10 columns and 6 rows:
1 2 3 4 5 6 7 8 9 10
0 1 0 0 1 1 1 0 1 0
1 1 1 0 1 0 1 0 0 0
0 0 0 0 1 0 0 1 0 1
1 0 1 1 0 1 1 1 0 0
0 0 0 0 0 0 1 0 0 0
1 1 0 1 0 0 0 0 1 1
I'd like to use vector X, H en I to make column selections in data.frame Y, using "1's" and "0's" in the vector as selection criterium .
So the results for vector X using the '1' as selection criterium should be:
X <- c(1,1,0,1,0, 1,1, 0, NA,NA)
1 2 4 6 7
0 1 0 1 1
1 1 0 0 1
0 0 0 0 0
1 0 1 1 1
0 0 0 0 1
1 1 1 0 0
For vector H using the '1' as selection criterium:
H <- c(0,0,1,0,NA,1,NA,1, 1, 1 )
3 6 8 9 10
0 1 0 1 0
1 0 0 0 0
0 0 1 0 1
1 1 1 0 0
0 0 0 0 0
0 0 0 1 1
For vector I using the '1' as selection criterium:
I <- c(0,0,0,0,0, 1,NA,NA,NA,1 )
6 10
1 0
0 0
0 1
1 0
0 0
0 1
For convenience and speed I'd like to use a loop. It might be something like this:
all.ones <- lapply[,function(x) x %in% 1]
In the outcome (all.ones), the result for each vector should stay separate. For example:
X 1,2,4,6,7
H 3,6,8,9,10
I 6,10
The standard way of doing this is using the %in% operator:
Y[, X %in% 1]
To do this for multiple vectors (assuming you want an AND operation):
mylist = list(X, H, I, D, E, K)
Y[, Reduce(`&`, lapply(mylist, function(x) x %in% 1))]
The problem is the NA, use which to get round it. Consider the following:
x <- c(1,0,1,NA)
x[x==1]
[1] 1 1 NA
x[which(x==1)]
[1] 1 1
How about this?
idx <- which(X==1)
Y[,idx]
EDIT: For six vectors, do
idx <- which(X==1 & H==1 & I==1 & D==1 & E==1 & K==1)
Y[,idx]
Replace & with | if you want all columns of Y where at least one of the lists has a 1.

Resources