I'm trying to create a function that will give me the value of a matrix once it has been raised to a power. This is what I've done so far:
A <- matrix(c(1,2,3,4,0,1,2,3,0,0,1,2,0,0,0,1),nrow=4,ncol=4)
power <- function(A,n){
+ if(n == 0){
+ return(diag(4))
+ }else{
+ return(A%*%A^(n-1))
+ }
+ }
OUTCOME:
> power(A,4)
[,1] [,2] [,3] [,4]
[1,] 1 0 0 0
[2,] 10 1 0 0
[3,] 46 10 1 0
[4,] 146 46 10 1
This is giving a different value from what my calculator gets and I'm trying to figure what I'm doing wrong. Any help is appreciated!
We could use %^% from library(expm)
library(expm)
A%*%(A%^%3)
Using this in a function
power <- function(A,n){
if(n == 0){
return(diag(4))
}else{
return(A%*%(A%^%(n-1)))
}
}
power(A,4)
# [,1] [,2] [,3] [,4]
#[1,] 1 0 0 0
#[2,] 8 1 0 0
#[3,] 36 8 1 0
#[4,] 120 36 8 1
According to the description in ?matpow
Compute the k-th power of a matrix. Whereas ‘x^k’ computes
element wise powers, ‘x %^% k’ corresponds to k - 1 matrix
multiplications, ‘x %% x %% ... %*% x’.
Or a base R option is Reduce with %*% (but this would be slow compared to %^%.
Reduce(`%*%`,replicate(4, A, simplify=FALSE))
In a function,
power1 <- function(A,n){
if(n == 0){
return(diag(4))
}else{
Reduce(`%*%`,replicate(n, A, simplify=FALSE))
}
}
power1(A,4)
# [,1] [,2] [,3] [,4]
#[1,] 1 0 0 0
#[2,] 8 1 0 0
#[3,] 36 8 1 0
#[4,] 120 36 8 1
You have a problem with the way you are computing your matrix product. I use a while loop inside your power() function instead. It simply multiples the input matrix against itself n times and then returns the result. Here is a base R solution which is a continuation of the direction in which you were already going.
A <- matrix(c(1,2,3,4,0,1,2,3,0,0,1,2,0,0,0,1),nrow=4,ncol=4)
power <- function(A,n){
B <- diag(nrow(A))
if (n == 0) {
return(diag(nrow(A)))
} else {
while (n > 0) {
B <- A%*%B
n <- n - 1
}
return(B)
}
}
> power(A, 4)
[,1] [,2] [,3] [,4]
[1,] 1 0 0 0
[2,] 8 1 0 0
[3,] 36 8 1 0
[4,] 120 36 8 1
I assume you want to make the muliplication of the matrix.You have to first make the multiply the matrix and then try to multiply them using the same powers as you want ,so you can do two things
Write code to multiply the matrix .
Loop the code to multiply.
Related
I need to create a lower triangular matrix out of a specified matrix, without using the lower.try function, specifically with nested for loops.
I have gotten this far...
d <- 6
m <- matrix(1:(d*d), d, d)
for(i in 2:nrow(m)) {
for (j in 1:col(m)) {
#...skipped code
}
}
Please help!
You should try to implement a gaussian elimination's steps but instead of eliminating the i'th column elements in the i'th step, you should try to eliminate the last elements.
mymat <- matrix(sample(x = c(1:10),replace = T,size = 25), ncol = 5, nrow = 5, byrow = T)
#iterating from the last row, to the first
for(j in nrow(mymat):1){
if(j>1){
#iterating from first, to the one before the current
for(i in 1:(j-1)){
#subtract the two rows but with the corresponding multiplier to eliminate the column's variables
multiplier <- mymat[i,j]/mymat[j,j]
mymat[i,] <- mymat[i,]-multiplier*mymat[j,]
}
}
#to get 1s in the diagonal line
mymat[j,] <- mymat[j,]/mymat[j,j]
}
If you don't want to get 1s in the diagonal:
for(j in nrow(mymat):1){
if(j>1){
for(i in 1:(j-1)){
multiplier <- mymat[i,j]/mymat[j,j]
mymat[i,] <- mymat[i,]-multiplier*mymat[j,]
}
}
mymat[j,] <- mymat[j,]/mymat[j,j]
}
I was able to get the answer with the following code, but I wish I could get the same output without the if statement
d <- 6
m <- matrix(1:(d*d), d, d)
for(i in 2:nrow(m)) {
for (j in 1:ncol(m)) {
if (m[i,j] < diag(m)[i]) {
m[i,j] <-0
}
}
} m
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 7 13 19 25 31
[2,] 0 8 14 20 26 32
[3,] 0 0 15 21 27 33
[4,] 0 0 0 22 28 34
[5,] 0 0 0 0 29 35
[6,] 0 0 0 0 0 36
Since I can not add a comment yet, I'm going to post this as another answer. You can do the following, without the if statement:
d <- 6
m <- matrix(1:(d*d), d, d)
for(i in c(2:dim(m)[1])) # from 2 to the number of rows
for(j in c(1:(i-1))) # from 1 to the number of the current iteration - 1
m[i,j] <- 0
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 7 13 19 25 31
[2,] 0 8 14 20 26 32
[3,] 0 0 15 21 27 33
[4,] 0 0 0 22 28 34
[5,] 0 0 0 0 29 35
[6,] 0 0 0 0 0 36
d <- 6
m <- matrix(1:(d*d), d, d)
for (j in 1:(d-1)) {
for (i in (j+1):d) {
m[i,j] = 0
}
}
Val A's answer gave me some insight. I just fix the minor error. Now you do not need if statement to do the work.
I am looking for an easier way to do the following:
m <- matrix(0, nrow=3, 3)
v <- c(1, 3, 2)
for (i in 1:nrow(m)) {
m[[i, v[i]]] = 1
}
The above code creates the following index matrix:
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 0 1
[3,] 0 1 0
There surely must be a better way to do this?!
One way to do it without pre-defining the matrix would be to use outer:
num.col <- 3
outer(v, seq_len(num.col), "==") * 1
# [,1] [,2] [,3]
# [1,] 1 0 0
# [2,] 0 0 1
# [3,] 0 1 0
I am trying to program tic-tac-toe in R - here are my two functions for making a move and evaluating all valid moves (the ones are X's, zeros are O's and NA is not taken yet):
move <- function(board,square,mark)
{
if (square < 1 || square > 9 || !is.na(board[square]))
{
return(NA)
}
else
board[square] <- mark
return(board)
}
valid.moves <- function(board)
{
return(which(is.na(board)))
}
Now setting up a test position, evaluating all valid moves and then make those moves...
test.last <- matrix(c(1,1,NA,0,NA,0,NA,0,1),nrow=3)
moves <- valid.moves(test.last)
move(test.last,moves,1)
...gives a result which I didn't intend:
[,1] [,2] [,3]
[1,] 1 0 1
[2,] 1 1 0
[3,] 1 0 1
I wanted to have three different boards with the respective valid moves (which will then be evaluated with another function whether it is a winning position) and not one board with all valid moves made at once.
I don't want to do this with a loop but the vectorization should not take place all at once 'inside' the move function but 'outside' of it - so basically I want to do the following without a loop (the eval.pos function to evaluate the position is of the form eval.pos <- function(board){}):
for (i in 1:length(moves))
{
after.moves <- move(test.last,moves[i],1)
print(after.moves)
print(eval.pos(after.moves))
}
How can I accomplish this without a loop?
move2 <- function(board, square, mark) {
lapply(square, function(x,i,value) `[<-`(x,i,value), x=board, value=mark)
}
Note that the anonymous function() is needed because [<- is primitive.
Expanding my suggestion in the comment. How to use matrix indices to generate a list of move options:
valid.moves <- function(board)
{
return(which(is.na(board), arr.ind=TRUE))
}
> moves <- valid.moves(test.last)
> moves
row col
[1,] 3 1
[2,] 2 2
[3,] 1 3
> lapply(1:3, function( mv) {start <- test.last
start[matrix(moves[mv,],ncol=2)] <- 1
start})
[[1]]
[,1] [,2] [,3]
[1,] 1 0 NA
[2,] 1 NA 0
[3,] 1 0 1
[[2]]
[,1] [,2] [,3]
[1,] 1 0 NA
[2,] 1 1 0
[3,] NA 0 1
[[3]]
[,1] [,2] [,3]
[1,] 1 0 1
[2,] 1 NA 0
[3,] NA 0 1
I have two Matrices, one is binary (Zero or One) and the other is an integer matrix of the same dimensions, these are square matrices.
I'd like an efficient way of combining them in a specific way, without iteration along each element.
The way I'd like to combine them is to have a resultant matrix from matrix A and matrix B, that for the element, takes the lowest number that is not zero.
Can anyone think of a trick in R to achieve this, I've tried to do it mathematically but keep coming up short, I was wondering if there was a way to overlay the matrices with a conditional statement?
matA <- matrix(-8:7, 4,4); set.seed(123)
matB <- matrix(sample(0:1, 16, repl=TRUE), 4, 4)
matC <- matrix(NA, nrow(matA), ncol(matA))
matC[] <- pmin( matA, MatB)
matC[ matB==0] <- matA[matB==0]
matB
#-----------
[,1] [,2] [,3] [,4]
[1,] 0 1 1 1
[2,] 1 0 0 1
[3,] 0 1 1 0
[4,] 1 1 0 1
matC
#---------
[,1] [,2] [,3] [,4]
[1,] -8 -4 0 1
[2,] -7 -3 1 1
[3,] -6 -2 1 6
[4,] -5 -1 3 1
flodel's method produces:
> ifelse(matB == 0, matB, pmin(matA, matB))
[,1] [,2] [,3] [,4]
[1,] 0 -4 0 1
[2,] -7 0 0 1
[3,] 0 -2 1 0
[4,] -5 -1 0 1
mnel's method produces:
> (matB * !matA) + matA
[,1] [,2] [,3] [,4]
[1,] -8 -4 1 4
[2,] -7 -3 1 5
[3,] -6 -2 2 6
[4,] -5 -1 3 7
My guess is:
ifelse(A == 0, B, pmin(A, B))
or maybe
ifelse(A == 0, B, ifelse(B == 0, A, pmin(A, B)))
If this is not what you are looking for, please clarify (and maybe provide an example.)
From #A_Skeleton's comment on scaling, you could break your matrix into chunks:
mnel <- function(matA, matB) {
(matB * !matA) + matA
}
# method takes a function as the argument
mcombine <- function(matA, matB, method) {
chunkSize <- 10000
matC <- matrix(0, nrow(matA), ncol(matA))
for (i in 1:floor(nrow(matA) / chunkSize)) {
curRange <- (chunkSize * (i-1) + 1):(i * chunkSize)
matC[curRange,] <- method(matA[curRange,], matB[curRange,])
}
# handle case where dimensions don't divide exactly into chunks
lastRange <- i*chunkSize:nrow(matA)
matC[lastRange,] <- method(matA[lastRange,], matB[lastRange,])
matC
}
# Using mnel's method:
matC <- mcombine(matA, matB, mnel)
This question already has answers here:
How to replace non-diagonal elements in a matrix?
(6 answers)
Closed 9 years ago.
Okay, I asked this question earlier but I got bashed (deservedly) for not specifying anything and showing no sign of previous attempt. So let me try again..
I'm using R, and I have a 463✕463 matrix. What I would like to do is to replace all elements other than the diagonal ones (X11, X22, X33,...,Xjj) with zero.
E.g. I want:
[1 4 5
2 3 5
3 9 8]
to be:
[1 0 0
0 3 0
0 0 8]
When I use the diag() function, it simply gives me a column vector of the diagonal values. I imagine I can use the replace() function somehow combined with a "if not diagonal" logic...but I am lost.
And yes, as some here have guessed, I am probably much younger than many people here and am completely new at this...so please put me in the right direction. Really appreciate all your help!
In R, the diag method has two functions.
It returns the diagonal of a matrix. I.e.
m <- matrix(1:9, ncol=3)
m
# [,1] [,2] [,3]
# [1,] 1 4 7
# [2,] 2 5 8
# [3,] 3 6 9
diag(m)
# [1] 1 5 9
It can construct a diagonal matrix.
diag(1:3)
# [,1] [,2] [,3]
# [1,] 1 0 0
# [2,] 0 2 0
# [3,] 0 0 3
So in your case, extract the diagonal from your existing matrix and supply it to diag:
diag(diag(m))
# [,1] [,2] [,3]
# [1,] 1 0 0
# [2,] 0 5 0
# [3,] 0 0 9
using outer
You can use the following to compute a logical matrix which describes the non-diagonal entries of a n×n matrix:
outer(1:n, 1:n, function(i,j) i!=j)
Applied to your example:
> m <- matrix(c(1,2,3,4,3,9,5,5,8),ncol=3)
> m
[,1] [,2] [,3]
[1,] 1 4 5
[2,] 2 3 5
[3,] 3 9 8
> m[outer(1:3, 1:3, function(i,j) i!=j)] <- 0
> m
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 3 0
[3,] 0 0 8
using triangles
A possible alternative would be combining the two triangles on either side of the diagonal. In this case, you use the matrix m itself as input to determine the size.
upper.tri(m) | lower.tri(m)
Applied to your use case:
> m[upper.tri(m) | lower.tri(m)] <- 0
It seems you already got this answer in response to your original post…
m[ col(m)==row(m) ] <- 0
> m <- matrix(1:9, 3)
> m[ col(m)==row(m) ]
[1] 1 5 9
> m[ col(m)!=row(m) ] <- 0
> m
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 5 0
[3,] 0 0 9