-
Notifications
You must be signed in to change notification settings - Fork 0
/
C_PlusPlus_code.R
219 lines (172 loc) · 7.99 KB
/
C_PlusPlus_code.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
##### C++
#load packages
library(Rcpp)
library(inline)
library(rbenchmark)
library(microbenchmark)
###### C++ Moving Average Function ##############
#given R function
movingAverage <- function(x, k) {
n <- length(x) #length of input vector
nMA <- n-k+1 #the number of elements in the moving average
xnew <- rep(NA, nMA) #to store moving average
i <- 1 #counter variable
#to calculate moving average , will calculate average of
#the next k elements starting from position i
while( i <= nMA ){ #until the last moving average
#calculate average for k values starting from element i
xnew[i] <- mean( x[ ( i:(i+k-1) ) ])
i <- i+1
}
xnew #return moving average of period k
}
################
#write body of C++ function as character in R
move2<-'
NumericVector dat(x);//define vector passed from R as C++ data type
int window = as<int>(k); //define integer passed from R as C++ data type
int n = dat.size(); //get length of vector passed from R
NumericVector ret(n-window+1); //define a vector to store the moving averages to pass back to R
double summed = 0.0; //define a float variable for in-loop calcuations
int numMA = (n -window + 1); // number of elements in moving average and length of ret vector
int i =0;
while( i <= numMA ){ //loop to continue until last window of moving average
summed = 0.0; // Reinitialize summed back to zero.
for (int j = i; j < i + window; j++) { //new loop to calculate each moving average window
summed += dat[j]; // increment sum
} // end of for loop
ret[i] = summed / window; // move to output vector
++i; //advance to next iteration
}// end of while
return wrap(ret); // return ret vector to R
'
#cxxfunction to compile, link, load
rcppMovingAverage <- cxxfunction(signature ( x = "numeric", k = "integer"),
body = move2,
plugin = "Rcpp",
verbose=TRUE)
x <- c(3,3,9,1,9,8,0,7)
movingAverage(x, 5)
rcppMovingAverage(x,5)
set.seed(100) #Generate a vector of random Normal data in R as follows:
x <- rnorm(1000)
k <- 2
#call function to test results are equivalent to R function
MAR<-movingAverage(x, 5)
MACPP<-rcppMovingAverage(x,5)
#compare time of both functions
benchmark <- microbenchmark(rcppMovingAverage(x,k), movingAverage(x, k),times = 10)
#Use your code to plot 5-year average (from 1882-2017) and 30-year average (from 1894-2004
k5 <-5
x <- LandOceanTempInd
year5 <- rcppMovingAverage(x,5)
year30 <- movingAverage(x,30)
plot.new()
#calculate 5-year and 30 year moving average using rcpp code and plot from 1882:2017
rcpp_LandOceanTempInd5 <- rcppMovingAverage(LandOceanTempInd, k=5)
rcpp_LandOceanTempInd30 <- rcppMovingAverage(LandOceanTempInd, k=30)
plot(year,LandOceanTempInd)
lines(year[3:138],rcpp_LandOceanTempInd5,col="blue")
lines(year[15:125],rcpp_LandOceanTempInd30, col="green")
title(main="Comparison of 5 and 30 year Moving Average", cex=0.8)
legend("topleft",
legend = c("5-year moving average","30-year moving average"),
col = c("blue","green"),
pch = c(19,19),
bty = "n",
pt.cex = 1,
cex = 1,
text.col = "black",
horiz = F ,
inset = c(0.1, 0.1)
)
####### C++ Random Walk Function ##############
set.seed(18210408) #generate random numbers
#write body of C++ function as character in R
steps <-'
int steps = as<int>(stepsR); //define integer passed from R as C++ data type
int i = 0; //define iteration counter
int reach_dest = 0; //counter for number of times tourist office is reached
int x = 0; //initialise x coordinates
int y=0; //initialise y coordinates
for (i=0;i<steps;i++){ //loop iterates over sequence 1:steps
int step_x = int(rand() % 3)-1; //random generate 0, 1 or -1 to update x and y
int step_y = int(rand() % 3)-1;
x += step_x; // add updated position to x and y
y+= step_y;
if (x==-1 and y == 3){ //check if the tourist office is reached
reach_dest += 1; //count the number of times it is reached
continue; //exit this loop and return to the beginning to start next iteration
}
}
//pass back to R, the number of visits to each tourist office
return wrap(reach_dest);//pass vector ret back to R
'
#cxxfunction to compile, link, load
rcppRandomWalk <- cxxfunction(signature ( stepsR = "int"),
body = steps,
plugin = "Rcpp",
verbose=TRUE)
rcppRandomWalk(10000) #check if code returns expected output
roads <- 20
tourists <- 1000 #the number of tourists that completed a walk over 20 roads
reached_office <- sum(replicate(tourists,rcppRandomWalk(roads))) #number of tourists that reached the tourist office
Prob <- reached_office/tourists
# potential new offices (3,0) or (0,3)
#write body of C++ function as character in R
steps2 <-'
int steps = as<int>(stepsR); //define integer passed from R as C++ data type
int i = 1; //define iteration counter
int reach_dest = 0; //counter for number of times tourist office is reached
int reach_dest1 = 0; //counter for number of times tourist office 1 is reached
int reach_dest2 = 0; //counter for number of times tourist office 2 is reached
int x = 0; //initialise x coordinates
int y=0; //initialise y coordinates
IntegerVector vect = IntegerVector::create(); //vector to store return values to R
for (i=0;i<steps;i++){ //loop iterates over sequence 1:steps
int step_x = int(rand() % 3)-1; //random generate 0, 1 or -1 to update x and y
int step_y = int(rand() % 3)-1;
x += step_x; // add updated position to x and y
y+= step_y;
if (x==-1 and y == 3){ //check if the tourist office is reached
reach_dest += 1; //count the number of times it is reached in this walk
continue; //exit this loop and skip to next iteration
}
if (x==3 and y == 0){ //check if the tourist office 1 is reached
reach_dest1 += 1; //count the number of times it is reached in this walk
continue; //exit this loop and skip to next iteration
}
if (x==0 and y == -3){ //check if the tourist office 2 is reached
reach_dest2 += 1; //count the number of times it is reached in this walk
continue; //exit this loop and skip to next iteration
}
}
return Rcpp::List::create (
Rcpp::Named ("exist_office", reach_dest),
Rcpp::Named ("office1", reach_dest1),
Rcpp::Named ("office2",reach_dest2));
//pass back to R, the number of visits to each tourist office
//pass back to R, list of the number of visits to all tourist offices
'
#cxxfunction to compile, link, load
rcppRandomWalk2 <- cxxfunction(signature ( stepsR = "int"),
body = steps2,
plugin = "Rcpp",
verbose=TRUE)
rcppRandomWalk2(100) #check if code returns expected output
#check the probability of finding existing office or office 1 in 10 roads
roads <- 10
tourists <- 1000 #the number of simulated tourists that completed a walk over 10 roads
reached_offices <- replicate(tourists,rcppRandomWalk2(roads)) #number of tourists that reached any of the tourist offices or missed any of them
table2 <- data.frame(matrix(unlist(reached_offices), nrow=1000, ncol=3,byrow=T))
colnames(table2) <-c("Existing Office", "Proposed Office 1","Proposed Office 2")
#sometimes the same office reached more than once, but this might be a different issue to the question of reaching it at all
#find x>=1 the prob of reaching an office one or more times (signified by "hit") during a walk
table2$exist_hit <- table2[,1]>=1
table2$office1_hit <-table2[,2]>=1
table2$office2_hit <-table2[,3]>=1
#check how many times existing or the proposed new office are reached in one walk
table2$exist_or2 <-table2[,1]>=1 | table2[,2]>=1
table2$exist_or3 <-table2[,1]>=1 | table2[,3]>=1
#find probabilities
prob_all <- colSums(table2)/1000