How to chain a list of binary functions - r

I am interested in the following construction:
Let's suppose I have a list of n binary functions and a vector of n+1 arguments. For arguments sake lets use
flist = c(`+`,`-`)
args = 1:3
What I would like to do is create the following function call f2(f1(x1,x2),x3) i.e in this example
`-`(`+`(1,2),3)
where the return value is the vector of cumulative results
[1] 3 0
I have a solution of the form
f = function(x,op,res = NULL){
if(is.null(res)){
res = op[[1]](x[1],x[2])
x = x[-1]
} else{
res = c(res,op[[1]](res[length(res)],x[1]))
}
if(length(op) == 1) res
else f(x[-1],op[-1],res)
}
such that is gives the correct answer
f(x,flist)
[1] 3 0
but it doesn't feel particularly R like or elegant. Is there a better way to do this. I suspect that my implementation isn't the most efficient either and so anything that is more efficient would also be of interest.
Any one got any ideas?
Alternatively if relaxing the requirement to have cumulative answers, i.e just the final answer 0 returned, was imposed is there a nice R way to do this? I know I could modify my f to deal with this alternative but if there exists a way to do this already I would love to hear about either option.
Edit:
A comment suggested a for loop implementation so we could have
falt = function(x,op){
res = numeric(length(op))
res[1] = op[[1]](x[1],x[2])
for(i in 2:length(res)) res[i] = op[[i]](res[i-1],x[i+1])
res
}
which does work out more efficient. But I still feel there must be a neater way to do this.

If your functions are already in curried form, it's a lot easier
comp <- function (f) function (g) function (x) f(g(x))
comp2 <- comp (comp) (comp) # if this is confusing, details later
add <- function (x) function (y) y + x
mult <- function (x) function (y) y * x
comp2 (mult) (add) (3) (4) (5)
# 5 * (4 + 3)
# 5 * 7
# 35
Because everything is curried, you can apply as many arguments as you want, then apply the rest later
compute <- comp2 (mult) (add)
compute (5) (6) (7)
# 7 * (6 + 5)
# 7 * 30
# 210
If you have list of binary functions, you can use a left fold (or "reduce") to create an entire sequence
identity <- function(x) x
comp <- function (f) function (g) function (x) f(g(x))
comp2 <- comp (comp) (comp)
uncurry <- function (f) function (x,y) f(x)(y)
reduce <- function(f) function(y) function (xs) Reduce(uncurry(f), xs, y)
comp2All <- reduce (comp2) (identity)
# some binary functions to use in our sequence
sub <- function (x) function (y) y - x
add <- function (x) function (y) y + x
mult <- function (x) function (y) y * x
# create a sequence of N binary functions
compute <- comp2All (list(mult, sub, mult, add))
# apply the computation to N+1 args
compute (3) (4) (5) (100) (0.2)
# 0.2 * (100 - (5 * (3 + 4))
# 0.2 * (100 - (5 * 7))
# 0.2 * (100 - 35)
# 0.2 * 65
# => 13
So you probably don't like having to apply the computation one argument at a time...
# this kind sucks, right?
compute (3) (4) (5) (6) (7)
Well we can fix that by making a function that applies a curried function to a list or arguments
capply <- reduce (identity)
capply (compute) (3:7)
# 7 * (6 - (5 * (4 + 3)))
# 7 * (6 - (5 * 7))
# 7 * (6 - 35)
# 7 * -29
# => -203
If your binary functions are not yet curried:
You can easily curry a binary function using curry2
curry2 <- function(f) function(x) function(y) f(x,y)
curry2 (`+`) (3) (4)
# => 7
If you have an entire list of binary functions that are not already curried, you can transform the entire list using map
map <- function (f) function (xs) Map(f,xs)
compute <- comp2All (map (curry2) (list (`*`, `+`, `*`, `+`)))
compute (3) (4) (5) (6) (7)
# 7 * (6 + (5 * (3 + 4)))
# 7 * (6 + (5 * 7))
# 7 * (6 + 35)
# 7 * 41
# => 287
comp vs comp2
Because you want to create a sequence of binary functions, I used
comp2All <- reduce (comp2) (identity)
If you wanted a sequence of unary functions, you would use
compAll <- reduce (comp) (identity)
what is comp2?
The comp2 definition might seem baffling, but don't let it confuse you
comp2 <- comp (comp) (comp)
If we were to expand this, we'd first see
comp2 <- function (x) comp(comp(x))
Upon further expansion (this is a fun exercise for you to do), you should see
comp2 <- function (f) function (g) function (x) function (y) f(g(x)(y))
Which can be easily understand as the composition of unary function, f, with binary function, g

Related

Using mosaicCalc::D() to differentiate expression giving unexpected result

I am attempting to differentiate the expression -1+3*x^2/1+x^2 with respect to x, but the output is incorrect. The correct output should be:
8x/(1+x^2)^2
#> library(mosaicCalc)
#>
#> l=D(-1+3*x^2/1+x^2 ~x)
#> l
function (x)
8 * x
Edit:
I have used parenthesis, but the output is still incorrect
#> t=D((-1+3*x^2)/1+x^2 ~x)
#> t
function (x)
8 * x
Furthermore, I have used parenthesis for both the numerator and the denominator, and the output for the second derivative is incorrect.
> b = D((-1+3*x^2)/(1+x^2) ~x)
> b
function (x)
{
.e1 <- x^2
.e2 <- 1 + .e1
x * (6 - 2 * ((3 * .e1 - 1)/.e2))/.e2
}
> k = D(b~ x)
> k
function (x, t)
0
The correct answer for the second derivative is 8(-3x^2+1)/(1+x^2)^3
https://www.symbolab.com/solver/step-by-step/%5Cfrac%7Bd%7D%7Bdx%7D%5Cfrac%7B8x%7D%7B%5Cleft(1%2Bx%5E%7B2%7D%5Cright)%5E%7B2%7D%7D?or=input
I think you need b(x) ~ x to get your second derivative. That will give you an expression in x that can be differentiated. As is, you are differentiating an expression that doesn’t depend on x, so the derivative is 0.
I might create an issue on GitHub to see if it is possible to emit a useful message in this case.

How to make a function that sums the exponential's of a vector in R?

My professor has assigned a question for programming in R and I am stuck. He wants us to make a function that will take the exponential (e^(x[i]) of all the numbers in a vector and then sum them. the equation is:
the summation of e^x(i), n, and i=1.
I have made a function that will give me the exponential of the first value in my vector. But I want to get the exponential of all the values and sum them. Here is my code
#Vector for summing
x=c(2,1,3,0.4)
#Code for function
mysum = 0
myfun=function(x){
for (i in 1:length(x)){
mysum = mysum + exp(x[i])
return(mysum)
}
}
myfun(x)
#returns 7.389056
I have also tried using i = 1:1 because the equation specifies i=1, even though I knew that would only go through 1 number, and it gave me the same answer.... obviously.
myfun=function(x){
for (i in 1:1)
Does anyone have any suggestions to get it to sum?
You need to set the initial value of mysum to the accumulation afterwards, and also move the line return(mysum) outsides your for loop to return the result, i.e.,
myfun=function(x){
mysum <- 0
for (i in 1:length(x)){
mysum = mysum + exp(x[i])
}
return(mysum)
}
or just
myfun=function(x){
mysum <- 0
for (i in x){
mysum = mysum + exp(x)
}
return(mysum)
}
Since exp operation is vectoroized, you can also define your function myfun like below
myfun <- function(x) sum(exp(x))
You could also use the fact that most base functions are already vectorized :
1) create a dummy vector
1:10
#> [1] 1 2 3 4 5 6 7 8 9 10
2) apply your function on that vector, you get vectorized result
exp(1:10)
#> [1] 2.718282 7.389056 20.085537 54.598150 148.413159
#> [6] 403.428793 1096.633158 2980.957987 8103.083928 22026.465795
3) Sum that vector
sum(exp(1:10))
#> [1] 34843.77
4) Write your function to gain (a little) time
my_fun <- function(x){sum(exp(x))}
my_fun(1:10)
#> [1] 34843.77

Applying a matrix to a function [duplicate]

This question already has answers here:
R: matrix by vector multiplication
(3 answers)
Closed 3 years ago.
Trying to apply a matrix to a function, using mapply without success
I'm trying to solve a set of equations for different parameters. In a more simplistic form of the set of functions, I'm trying to pass a function to a matrix - constants -
a b c
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
and trying to solve the the equation 3*a + 2*b + 3*c and return the answer for each row in the matrix. I have changed the original function to a linear and more simple one - that is why I prefer using #mapply and that former explanations have not assisted me.
building the matrix
my_vector <- 1:9
constants <- matrix(my_vector, 3, 3)
colnames(constants) <- c("a", "b", "c")
constants
the target function
fun_abc <- function(a, b, c){
return(3 * a + 2 * b + 3 * c)
}
applying constants to the function
mapply(fun_abc, 2, constants)
I keep getting Error in (function (a, b, c) : argument "c" is missing, with no default
Can anyone spot the problems?
You can directly multiply values and take rowSums to get row-wise sum
vals <- c(3, 2, 3)
rowSums(t(t(constants) * vals))
#[1] 32 40 48
We use transpose since constants * vals would multiply vals in each column, so the first transpose is to multiply vals row-wise and the second transpose is to get matrix in original format again. If we would always have a square matrix (nrow == ncol), we can reduce one transpose and use colSums instead to get the same value.
colSums(t(constants) * vals)
#[1] 32 40 48
If we want to avoid transposing we can also use sweep
rowSums(sweep(constants, 2, vals, `*`))
One simple way to do this using matrix multiplication, and then changing it to vector if you want so:
my_vector <- 1:9
constants <- matrix(my_vector, 3, 3)
colnames(constants) <- c("a", "b", "c")
vals <- c(3, 2, 3)
c(constants %*% vals)
#> [1] 32 40 48
Or, redefine your function and use apply:
fun_x <- function(x){
sum(x * vals) # same as 3 * x[1] + 2 * x[2] + 3 * x[3]
}
apply(constants, 1, fun_x)
An alternative albeit admittedly overly complicated possibility:
fun_abc <- function(my_matrix,multiplier,...){
columns <- match(c(...),colnames(my_matrix))
rowSums(mapply(function(x, y) my_matrix[,x] * y ,
columns, multiplier))
}
fun_abc(constants, c(3,2, 3),"a", "b", "c")
[1] 32 40 48
This assumes that the user would like to programmatically access columns, otherwise:
constants[,"a"] * 3 + constants[,"b"] * 2 + constants[,"c"] * 3
[1] 32 40 48

Solving a system of nonlinear equations in R

Suppose I have the following system of equations:
a * b = 5
sqrt(a * b^2) = 10
How can I solve these equations for a and b in R ?
I guess this problem can be stated as an optimisation problem, with the following function... ?
fn <- function(a, b) {
rate <- a * b
shape <- sqrt(a * b^2)
return(c(rate, shape) )
}
In a comment the poster specifically asks about using solve and optim so we show how to solve this (1) by hand, (2) using solve, (3) using optim and (4) a fixed point iteration.
1) by hand First note that if we write a = 5/b based on the first equation and substitute that into the second equation we get sqrt(5/b * b^2) = sqrt(5 * b) = 10 so b = 20 and a = 0.25.
2) solve Regarding the use of solve these equations can be transformed into linear form by taking the log of both sides giving:
log(a) + log(b) = log(5)
0.5 * (loga + 2 * log(b)) = log(10)
which can be expressed as:
m <- matrix(c(1, .5, 1, 1), 2)
exp(solve(m, log(c(5, 10))))
## [1] 0.25 20.00
3) optim Using optim we can write this where fn is from the question. fn2 is formed by subtracting off the RHS of the equations and using crossprod to form the sum of squares.
fn2 <- function(x) crossprod( fn(x[1], x[2]) - c(5, 10))
optim(c(1, 1), fn2)
giving:
$par
[1] 0.2500805 19.9958117
$value
[1] 5.51508e-07
$counts
function gradient
97 NA
$convergence
[1] 0
$message
NULL
4) fixed point For this one rewrite the equations in a fixed point form, i.e. in the form c(a, b) = f(c(a, b)) and then iterate. In general, there will be several ways to do this and not all of them will converge but in this case this seems to work. We use starting values of 1 for both a and b and divide both side of the first equation by b to get the first equation in fixed point form and we divide both sides of the second equation by sqrt(a) to get the second equation in fixed point form:
a <- b <- 1 # starting values
for(i in 1:100) {
a = 5 / b
b = 10 / sqrt(a)
}
data.frame(a, b)
## a b
## 1 0.25 20
Use this library.
library("nleqslv")
You need to define the multivariate function you want to solve for.
fn <- function(x) {
rate <- x[1] * x[2] - 5
shape <- sqrt(x[1] * x[2]^2) - 10
return(c(rate, shape))
}
Then you're good to go.
nleqslv(c(1,5), fn)
Always look at the detailed results. Numerical calculations can be tricky. In this case I got this:
Warning message:
In sqrt(x[1] * x[2]^2) : NaNs produced
That just means the procedure searched a region that included x[1] < 0 and then presumably noped the heck back to the right hand side of the plane.

R - How to get row & column subscripts of matched elements from a distance matrix

I have an integer vector vec1 and I am generating a distant matrix using dist function. I want to get the coordinates (row and column) of element of certain value in the distance matrix. Essentially I would like to get the pair of elements that are d-distant apart. For example:
vec1 <- c(2,3,6,12,17)
distMatrix <- dist(vec1)
# 1 2 3 4
#2 1
#3 4 3
#4 10 9 6
#5 15 14 11 5
Say, I am interested in pair of elements in the vector that are 5 unit apart. I wanted to get the coordinate1 which are the rows and coordinate2 which are the columns of the distance matrix. In this toy example, I would expect
coord1
# [1] 5
coord2
# [1] 4
I am wondering if there is an efficient way to get these values that doesn't involve converting the dist object to a matrix or looping through the matrix?
A distance matrix is a lower triangular matrix in packed format, where the lower triangular is stored as a 1D vector by column. You can check this via
str(distMatrix)
# Class 'dist' atomic [1:10] 1 4 10 15 3 9 14 6 11 5
# ...
Even if we call dist(vec1, diag = TRUE, upper = TRUE), the vector is still the same; only the printing styles changes. That is, no matter how you call dist, you always get a vector.
This answer focus on how to transform between 1D and 2D index, so that you can work with a "dist" object without first making it a complete matrix using as.matrix. If you do want to make it a matrix, use the dist2mat function defined in as.matrix on a distance object is extremely slow; how to make it faster?.
R functions
It is easy to write vectorized R functions for those index transforms. We only need some care dealing with "out-of-bound" index, for which NA should be returned.
## 2D index to 1D index
f <- function (i, j, dist_obj) {
if (!inherits(dist_obj, "dist")) stop("please provide a 'dist' object")
n <- attr(dist_obj, "Size")
valid <- (i >= 1) & (j >= 1) & (i > j) & (i <= n) & (j <= n)
k <- (2 * n - j) * (j - 1) / 2 + (i - j)
k[!valid] <- NA_real_
k
}
## 1D index to 2D index
finv <- function (k, dist_obj) {
if (!inherits(dist_obj, "dist")) stop("please provide a 'dist' object")
n <- attr(dist_obj, "Size")
valid <- (k >= 1) & (k <= n * (n - 1) / 2)
k_valid <- k[valid]
j <- rep.int(NA_real_, length(k))
j[valid] <- floor(((2 * n + 1) - sqrt((2 * n - 1) ^ 2 - 8 * (k_valid - 1))) / 2)
i <- j + k - (2 * n - j) * (j - 1) / 2
cbind(i, j)
}
These functions are extremely cheap in memory usage, as they work with index instead of matrices.
Applying finv to your question
You can use
vec1 <- c(2,3,6,12,17)
distMatrix <- dist(vec1)
finv(which(distMatrix == 5), distMatrix)
# i j
#[1,] 5 4
Generally speaking, a distance matrix contains floating point numbers. It is risky to use == to judge whether two floating point numbers are equal. Read Why are these numbers not equal? for more and possible strategies.
Alternative with dist2mat
Using the dist2mat function given in as.matrix on a distance object is extremely slow; how to make it faster?, we may use which(, arr.ind = TRUE).
library(Rcpp)
sourceCpp("dist2mat.cpp")
mat <- dist2mat(distMatrix, 128)
which(mat == 5, arr.ind = TRUE)
# row col
#5 5 4
#4 4 5
Appendix: Markdown (needs MathJax support) for the picture
## 2D index to 1D index
The lower triangular looks like this: $$\begin{pmatrix} 0 & 0 & \cdots & 0\\ \times & 0 & \cdots & 0\\ \times & \times & \cdots & 0\\ \vdots & \vdots & \ddots & 0\\ \times & \times & \cdots & 0\end{pmatrix}$$ If the matrix is $n \times n$, then there are $(n - 1)$ elements ("$\times$") in the 1st column, and $(n - j)$ elements in the j<sup>th</sup> column. Thus, for element $(i,\ j)$ (with $i > j$, $j < n$) in the lower triangular, there are $$(n - 1) + \cdots (n - (j - 1)) = \frac{(2n - j)(j - 1)}{2}$$ "$\times$" in the previous $(j - 1)$ columns, and it is the $(i - j)$<sup>th</sup> "$\times$" in the $j$<sup>th</sup> column. So it is the $$\left\{\frac{(2n - j)(j - 1)}{2} + (i - j)\right\}^{\textit{th}}$$ "$\times$" in the lower triangular.
----
## 1D index to 2D index
Now for the $k$<sup>th</sup> "$\times$" in the lower triangular, how can we find its matrix index $(i,\ j)$? We take two steps: 1> find $j$; 2> obtain $i$ from $k$ and $j$.
The first "$\times$" of the $j$<sup>th</sup> column, i.e., $(j + 1,\ j)$, is the $\left\{\frac{(2n - j)(j - 1)}{2} + 1\right\}^{\textit{th}}$ "$\times$" of the lower triangular, thus $j$ is the maximum value such that $\frac{(2n - j)(j - 1)}{2} + 1 \leq k$. This is equivalent to finding the max $j$ so that $$j^2 - (2n + 1)j + 2(k + n - 1) \geq 0.$$ The LHS is a quadratic polynomial, and it is easy to see that the solution is the integer no larger than its first root (i.e., the root on the left side): $$j = \left\lfloor\frac{(2n + 1) - \sqrt{(2n-1)^2 - 8(k-1)}}{2}\right\rfloor.$$ Then $i$ can be obtained from $$i = j + k - \left\{\frac{(2n - j)(j - 1)}{2}\right\}.$$
If the vector is not too large, the best way is probably to wrap the output of dist into as.matrix and to use which with the option arr.ind=TRUE. The only disadvantage of this standard method to retrieve the index numbers within a dist matrix is an increase of memory usage, which may become important in the case of very large vectors passed to dist. This is because the conversion of the lower triangular matrix returned by dist into a regular, dense matrix effectively doubles the amount of stored data.
An alternative consists in converting the dist object into a list, such that each column in the lower triangular matrix of dist represents one member of the list. The index number of the list members and the position of the elements within the list members can then be mapped to the column and row number of the dense N x N matrix, without generating the matrix.
Here is one possible implementation of this list-based approach:
distToList <- function(x) {
idx <- sum(seq(length(x) - 1)) - rev(cumsum(seq(length(x) - 1))) + 1
listDist <- unname(split(dist(x), cumsum(seq_along(dist(x)) %in% idx)))
# http://stackoverflow.com/a/16358095/4770166
}
findDistPairs <- function(vec, theDist) {
listDist <- distToList(vec)
inList <- lapply(listDist, is.element, theDist)
matchedCols <- which(sapply(inList, sum) > 0)
if (length(matchedCols) > 0) found <- TRUE else found <- FALSE
if (found) {
matchedRows <- sapply(matchedCols, function(x) which(inList[[x]]) + x )
} else {matchedRows <- integer(length = 0)}
matches <- cbind(col=rep(matchedCols, sapply(matchedRows,length)),
row=unlist(matchedRows))
return(matches)
}
vec1 <- c(2, 3, 6, 12, 17)
findDistPairs(vec1, 5)
# col row
#[1,] 4 5
The parts of the code that might be somewhat unclear concern the mapping of the position of an entry within the list to a column / row value of the N x N matrix. While not trivial, these transformations are straightforward.
In a comment within the code I have pointed out an answer on StackOverflow which has been used here to split a vector into a list. The loops (sapply, lapply) should be unproblematic in terms of performance since their range is of order O(N). The memory usage of this code is largely determined by the storage of the list. This amount of memory should be similar to that of the dist object since both objects contain the same data.
The dist object is calculated and transformed into a list in the function distToList(). Because of the dist calculation, which is required in any case, this function could be time-consuming in the case of large vectors. If the goal is to find several pairs with different distance values, then it may be better to calculate listDist only once for a given vector and to store the resulting list, e.g., in the global environment.
Long story short
The usual way to treat such problems is simple and fast:
distMatrix <- as.matrix(dist(vec1)) * lower.tri(diag(vec1))
which(distMatrix == 5, arr.ind = TRUE)
# row col
#5 5 4
I suggest using this method by default. More complicated solutions may become necessary in situations where memory limits are reached, i.e., in the case of very large vectors vec1. The list-based approach described above could then provide a remedy.

Resources