How to vectorize a function not 'inside' but 'outside' in R? - r

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

Related

Find a pattern of a matrix in R?

I have a matrix called my_matrix with 5 rows and 5 columns made up with 1s and 0s.
test.matrix <- matrix(c(0,0,1,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0,1,0,0,1,0,0,1),nrow=5)
test.matrix
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 0 1 1 0 1
[3,] 1 1 1 0 0
[4,] 0 1 1 1 0
[5,] 0 0 0 0 1
I want to find a left2tile pattern of test.matrix as shown:
[,1] [,2]
[1,] 1 0
[2,] 1 0
I also want to find a right2tile pattern of test.matrix as shown:
[,1] [,2]
[1,] 0 1
[2,] 0 1
For left2tile I want to find the number of unique 2-tiles in the matrix where the leftmost two entries are 1 and the rightmost two entries are 0.
For right2tile I want to find the number of unique 2-tiles in the matrix where the rightmost two entries are 1 and the leftmost two entries are 0.
I'm aware that these may overlap. Any idea how to calculate this in R?
Here are example functions that can tell you how many 2x2 matrices in the bigger matrix match the provided 2x2 matrix. The first helper function creates a list of 2x2 matrices that the input matrix is made of. The second function uses the first helper function and returns how many of the first matrix argument is in the second matrix argument.
# Helper functions
decompose=function(x) {
two_by_two=list()
k=1
for (i in 1:(nrow(x)-1)) {
for (j in 1:(ncol(x)-1)) {
two_by_two[[k]]=matrix(c(x[i,j], x[i+1,j], x[i,j+1], x[i+1,j+1]), ncol=2)
k=k+1
}
}
return(two_by_two)
}
how_many=function(x, test) {
my_list=decompose(test)
bools=sapply(my_list, function(y) {
return(identical(x, y))
})
return(sum(bools))
}
#Carrying it out
left2tile=matrix(c(1,1,0,0), ncol=2)
right2tile=matrix(c(0,0,1,1),ncol=2)
how_many(left2tile, test.matrix)
how_many(right2tile, test.matrix)

R: how to calculate element-wise arg-min from a list of matrices?

Suppose I have a list of matrices. Suppose further I have found the smallest values by the column.
Here is my last question
I really need to know from which matrix each smallest value is selected. My original function is very complicated. Therefore, I provided a simple example. I have one idea and really do not know to implement it correctly in R.
My idea is:
Suppose that [i,j] is the elements of the matrix. Then,
if(d[[1]][i,j] < d[[2]][i,j]){
d[[1]][i,j] <– "x"
}else { d[[2]][i,j] <– "z"}
So, I would like to sign the name of the matrix that corresponds to each smallest value. Then, store the names in a separate matrix. So, then I can see the values in one matrix and their corresponding names (from where they come from) in another matrix
For example,
y <- c(3,2,4,5,6, 4,5,5,6,7)
x[lower.tri(x,diag=F)] <- y
> x
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 3 0 0 0 0
[3,] 2 6 0 0 0
[4,] 4 4 5 0 0
[5,] 5 5 6 7 0
k <- c(1,4,5,2,5,-4,4,4,4,5)
z[lower.tri(z,diag=F)] <- k
> z
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 1 0 0 0 0
[3,] 4 5 0 0 0
[4,] 5 -4 4 0 0
[5,] 2 4 4 5 0
d <- list(z, x)
Then:
do.call(pmin, d) (answered by #akrun)
Then, I will only get the matrix with smallest values. I would like to know where each value is come from?
Any idea or help, please?
You can use Map and do.call to create your own functions that will be applied element-wise to a list of inputs,
in your case a list of matrices.
pwhich.min <- function(...) {
which.min(c(...)) # which.min takes a single vector as input
}
di <- unlist(do.call(Map, c(list(f = pwhich.min), d)))
dim(di) <- dim(x) # take dimension from one of the inputs
di
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 2 1 1 1 1
[3,] 1 2 1 1 1
[4,] 1 2 2 1 1
[5,] 2 2 2 2 1
EDIT:
To elaborate,
you could do something like Map(f = min, z, x) to apply min to each pair of values in z and x,
although in that case min already supports arbitrary amount of inputs through an ellipsis (...).
By contrast,
which.min only takes a single vector as input,
so you need a wrapper with an ellipsis that combines all values into a vector
(pwhich.min above).
Since you may want to have more than two matrices,
you can put them all in a list,
and use do.call to put each element in the list as a parameter to the function you specify in f.
Or another option would be to convert it to a 3D array and use apply with which.min
apply(array(unlist(d), c(5, 5, 2)), c(1, 2), which.min)
Or with pmap from purrr
library(purrr)
pmap_int(d, ~ which.min(c(...))) %>%
array(., dim(x))

R binary exhaustive list without for loop

I am trying to come up with every possible combination of a set number of 1's and 0's in a list, without any overlap. I want the list to contain a series of matrices.
I have come up with the following code, which accomplishes that goal, for example if you want 2 values of 1 and 2 of 0 in a 2x2 matrix:
z<-0
for(i in 1:(4-1)){
for(j in (i+1):(4)){
x<-rep(0,4)
x[c(i,j)]<-1
x<-matrix(x,nrow=2,byrow=TRUE)
z<-z+1
k[[z]]<-x
}}
This is fine, but I would like to be able to create lists involving a larger number of 0's and 1's.
The only way I know how to do this is to nest more and more for loops
For example, in order to print every non-repetitive combination of 3 1's in 9 total spaces in a 3x3 matrix:
for(i in 1:(9-2)){
for(j in (i+1):(9-1)){
for(k in (j+1):9){
x<-rep(0,9)
x[c(i,j,k)]<-1
x<-matrix(x,nrow=3,byrow=TRUE)
print(x)
}}}
I feel like there must be a more elegant and quicker solution(especially when dealing with larger numbers of digits). Even if a simple solution could just give me vectors, it'd be easy enough to make them a list of matrices. I would like variable amounts of 1's and 0's enumerated in a list so that I can use them for further manipulation.
Thank you for your help!
Here's a function to do it. The first argument is the size of the sides of the matrix, the second is the number of ones wanted:
makematrix <- function(n, k){
z <- as.data.frame(t(expand.grid(rep(list(c(0,1)), n * n))))
z <- z[ ,colSums(z) == k]
lapply(z, function(x){matrix(x, nrow = n)})
}
First we make all the combinations of 0 and 1 in a data frame using expand.grid, subset by the ones with the correct number of 1s, then we rearrange them into a list of matrices using lapply.
makematrix(2, 2)
$V4
[,1] [,2]
[1,] 1 0
[2,] 1 0
$V6
[,1] [,2]
[1,] 1 1
[2,] 0 0
$V7
[,1] [,2]
[1,] 0 1
[2,] 1 0
$V10
[,1] [,2]
[1,] 1 0
[2,] 0 1
$V11
[,1] [,2]
[1,] 0 0
[2,] 1 1
$V13
[,1] [,2]
[1,] 0 1
[2,] 0 1
You can also directly use library combinat, which permn function giving a direct list:
library(combinat)
unique(permn(c(1,1,0,0),function(x) matrix(x,nrow=sqrt(length(x)))))
#[[1]]
# [,1] [,2]
#[1,] 1 0
#[2,] 1 0
#[[2]]
# [,1] [,2]
#[1,] 1 1
#[2,] 0 0
#[[3]]
# [,1] [,2]
#[1,] 0 1
#[2,] 1 0
#[[4]]
# [,1] [,2]
#[1,] 0 0
#[2,] 1 1
#[[5]]
# [,1] [,2]
#[1,] 1 0
#[2,] 0 1
#[[6]]
# [,1] [,2]
#[1,] 0 1
#[2,] 0 1

Raising a Power on Matrices

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.

Replacing non-diagonal elements in a matrix in R (hopefully a better asked this time) [duplicate]

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

Resources