Hello,
I am hoping someone can help tackle the problem below, for which I require a
fast solution. It feels like there should be an elegant approach, but I am
drawing blanks.
Take a vector 'x' with random values > 0:
x = runif(10,1,5)
Assume some reasonably small positive value 'delta':
delta = 0.75
The task is to find a solution vector 'y' of same length as 'x'
such that:
The absolute difference between y[i] and y[i-1] is >= 'delta'
and y[i] >= x[i]
and that the sum of y[i] - x[i] be as small as possible -- i.e. minimize
sum(y-x).
The real-world application that (loosely) inspires this problem is the case of
thermal power plants that face limits ('delta') in the speed with which
they can "ramp" output up (or down) in response to changing demand.
The period-to-period difference in output cannot exceed the absolute value of
'delta'. The other constraints I've imposed are specific to my
application, but also provide a more neatly defined problem. A real-world
problem would not have random starting values for 'x', but I figure the
random values will present a particular difficulty in terms of solution time.
SPEED IS CRITICAL here, as this example must handle 'x' with
length=10,000 in practice and is located within an optimization routine that
requires it be iterated over different 'x' vectors many times. My
Neanderthal-ish solution (below) may or may not give the theoretically optimal
solution, but, regardless, is too slow when 'x' becomes lengthy due to
its reliance on loops.
Hope you can help!
x = runif(10,1,5)
delta = 0.75
chg = diff(c(x,x[1]))
y = x
while (any(abs(chg)>delta)) {
temp = sign(chg)*chg - delta
temp1=temp
temp1[chg>=(-delta)] = 0
temp1 = c(temp1[length(temp1)],temp1[-length(temp1)])
temp2 = temp
temp2[chg<=delta] = 0
y = y+temp1+temp2
chg = diff(c(y,y[1]))
}
#Solution vector:
y
Thank you,
Kevin
Kevin Ummel
CARMA Project Manager
Center for Global Development
[[alternative HTML version deleted]]
Rui Barradas
2011-Dec-12 17:17 UTC
[R] Lagged values problem requiring short solution time
Kevin,
Your problem seems to have three restrictions: (1) abs(x[i] - x[i-1]) >delta
(2) y[i] >= x[i]
and (3) minimize sum(y-x). If this is the case I believe I have a better
solution, with a smaller sum
and in much less time.
The problem is restriction (2). If the diffs are negative you can't subtract
negative,
the new y[i] would be less than x[i]. So, add. Here is the code:
fun1 <- your code
fun2 <- function(x, delta){
n <- length(x) # don't need
to
create a work y
if(abs(x[1] - x[n]) < delta) x[1] <- x[n] + delta # special case, wraps
around.
ix <- which(abs(x[2:n] - x[2:n - 1]) < delta) # make up an index
vector
x[ix] <- x[ix - 1] + delta # and use it.
x
}
# First test both
x = runif(10,1,5)
y1 <- fun1(x, delta=0.75); s1 <- sum(y1 - x)
y2 <- fun2(x, delta=0.75); s2 <- sum(y2 - x)
# and display results
rbind(fun1=c(y=y1, s=s1), c(diff(c(y1,y1[1])), NA),
fun2=c(y=y2, s=s2), c(diff(c(y2,y2[1])), NA),
x=c(x, NA), c(diff(c(x,x[1])), NA))
# now time them!
x <- runif(10^5, 1, 5)
t1 <- system.time(for(i in 1:10^2) y1 <- fun1(x, delta=0.75))[c(1, 3)]
t2 <- system.time(for(i in 1:10^2) y2 <- fun2(x, delta=0.75))[c(1, 3)]
rbind(fun1=t1, fun2=t2, ratio=t1/t2)
#
# Sample run
#
user.self elapsed
fun1 26.99000 29.60000
fun2 0.92000 1.09000
ratio 29.33696 27.15596
29 times faster!
I hope it's usefull
Rui Barradas
--
View this message in context:
http://r.789695.n4.nabble.com/Lagged-values-problem-requiring-short-solution-time-tp4184566p4186786.html
Sent from the R help mailing list archive at Nabble.com.