I have a graph with each edge having cost and quality. I need to modify the dijkstras to find the path with the highest quality - but if the quality of two path is the same, then the path with the least cost should be chosen.
Initially, I was using dijkstras to find the path with minimum cost (code is pasted below).
Is it possible to modify those dijkstras in the above mentioned way?
If not, then please suggest another way to achieve this.
R code:
dijs<-function(n,v,cost,dist)
{
dist<-numeric(n)
flag<- numeric(n)
prev<-numeric(n)
for(i in 1:n)
prev[i] = -1
for(i in 1:n)
dist[i]<-cost[v,i]
count=2
while(count <= n)
{
min=999
for(w in 1:n)
{
if(dist[w] < min && !flag[w])
{
min=dist[w]
u=w
}
}
flag[u]=1
count<-count+1
for(w in 1:n)
{
if((dist[u]+cost[u,w] < dist[w]) && !flag[w])
{
dist[w]=dist[u]+cost[u,w]
prev[w]=u
}
}
}
printmin(v,dist,n)
return(prev)
}
main<-function()
{
cat('Enter no of nodes:', '\n')
n<-scan("",n=1,quiet=TRUE)
cat('Enter cost matrix','\n')
cost<-matrix(0,n,n)
for(i in 1:n) for(j in 1:n)
{
if(i == j)
cost[i,j]<-999
if(i != j && cost[i,j] == 0)
{
cat(sprintf("enter the cost from node %d to %d",i,j))
cost[i,j]<-scan("",n=1,quiet=TRUE)
if(cost[i,j] == 0)
cost[i,j]=999
cost[j,i]<-cost[i,j]
}
}
print(cost)
print('Enter the source:',quote=FALSE)
v<-scan("",n=1,quiet=TRUE)
prev<-digs(n,v,cost,dest)
print("the shortest distance")
for(i in 1:n)
{
cat(sprintf("path to %d ->",i))
printpath(i,prev)
cat('\n')
}
}
printmin<-function(v,mindist,n)
{
for(i in 1:n)
{
if(i != v)
{
cat(sprintf("%d -> %d, cost =%f",v,i,mindist[i]))
cat('\n')
}
}
}
printpath<-function(dest,prev)
{
if(prev[dest] != -1)
printpath(prev[dest],prev)
cat(sprintf("%d ",dest))
}
Assuming the quality that you use as the cost does not lead to negative cycles, I think the easiest way to do so is to compute all shortest path between source and dest and then rank all paths according to your second objective. You can use the default Dijkstra implementation to compute all equivalent shortest paths according to the first objective, just keep exploring the queue (instead of stopping when you reach the goal) until the next path taken from the queue is bigger than the optimal one. Then, compute the costs for each min path using your second objective and rank them using a sorting algorithm.
If you want to modify the original Dijkstra to compare the cost using prioritized objectives (first quality then cost or vice-versa) then you must prove that your modified version is optimal and complete
Related
I have been trying to find the observations associated with rank j in Ranked Set Sampling method. The problem is I don't know how to use the simulations to find the Xj values I'm supposed to work with further. Please help!
#The rankedsets function selects ranked sets from a target population. The selection of units in a set is without replacement, but the sets are selecting with replacement.
rankedsets<-function(X,m,s=m){
if(s==m){
x=sample(X,(m^2),replace=F)
n=matrix(x,ncol=m,nrow=m,byrow=T)
ms=matrix(0,ncol=m,nrow=m)
for (i in 1:m){
ms[i,]=sort(n[i,])
}
}else {
x=sample(X,(m*s),replace=F)
n=matrix(x,ncol=m,nrow=s,byrow=T)
ms=matrix(0,ncol=m,nrow=s)
for (i in 1:s){
ms[i,]=sort(n[i,])
}
}
return(ms)
}
#The rss function samples from a target population by using ranked set sampling method
rss<-function(X,m,r=1,sets=FALSE){
rss=numeric()
set=matrix(0,ncol=m,nrow=(m*r))
if (is.vector(X)){
a=0
for (j in 1:r){
ms=rankedsets(X,m)
for (i in 1:(m)){
set[i+a,]=ms[i,]
rss[i+a]=ms[i,i]
}
a=a+m
}
rss=matrix(rss,ncol=m,nrow=r,byrow=T)
cn=rn=numeric()
for (i in 1:r){
rn[i]=paste("r","=",i)
}
for (i in 1:m){
cn[i]=paste("m","=",i)
}
rownames(rss)=rn
colnames(rss)=cn
if (sets){
s=list(sets=set,sample=rss)
return(s)
} else {
return(rss)}
}else stop(" X must be a vector!",call.=F)
}
#RSS Data Generation
data=rnorm(10000,1,3)
rss(data,m=5,r=3,sets=TRUE)
I was trying using simulations but the code doesn't return Xj values:
sims = 1000
Xj = rep(NA, sims)
because I don't really know where I should put my for loop.
I am trying to code the Markov Chain approximation for some control problems.
But I have the following bug in R and I checked similar question in Stackoverflow and still have
no idea how to solve it. Any help will be greatly appreciated.
The bug comes from where I would like to find the minimum value among all of 'u' in a for loop.
To specific, in the uit-for-loop, for each next uit I could get a new single value (I thought) temp and would like to compare this with the temporary minimal stored by a single value variable vmin. That is the idea in the if-else sentence.
It is better to skip the parameter setting and initialization procedure.
#----- parameters ------
xleft=0; xright=10
yleft=0; yright=10
h=0.01
Nx=(xright-xleft)/h
Ns=2
Nu=11; hu=0.2
la=0.1
qMainDiag=c(-0.5,-0.5)
qSubDiag=c(0.5,0.5)
alpha=c(0.2,0.25)
beta=c(0.35,0.2)
a=c(0.6,0.8)
b=c(0.5,0.3)
c=c(0.45,0.5)
d=c(0.65,0.8)
tol=10^(-8)
maxitr=10000
#---- Initialization -----
Vold=array(0,dim=c(Nx+1,Nx+1,Ns))
Vnew=array(0,dim=c(Nx+1,Nx+1,Ns))
Uopt=array(0,dim=c(Nx+1,Nx+1,Ns))
for(r in 1:Ns){
for(i in 1:(Nx+1)){
for(j in 1:(Nx+1)){
Vold[i,j,r]=1
}
}
}
#---- iteration ----
for(n in 1:maxitr){
for(r in 1:Ns){
# inner of O
for(i in 2:Nx){
for(j in 2:Nx){
vInt=0
for(it in 1:(min(i,j)+1)){
vInt=vInt+Vold[i-it+1,j-it+1,r]*0.1*exp(-0.1*(it-1)*h)*h
}
# For each u, want to find the minimum temp value and its u.
for(uit in 1:Nu){
x=xleft+(i-1)*h; y=yleft+(j-1)*h
u=hu*(uit-1)
Xi11=(alpha[r]*x)^2; Xi22=(beta[r]*y)^2
f1=x*(a[r]-b[r]*y+u); f2=y*(-c[r]+d[r]*x+u)
g=1+r*(x+y)*(1+u^2)
Qh=(Xi11+Xi22)+h*(abs(f1)+abs(f2))+h-(h^2)*qMainDiag[r]
dlt=(h*h)/Qh
pforward=0.5*(Xi11+2*h*max(f1,0.0))/Qh
pback=0.5*(Xi11+2*h*max(-f1,0.0))/Qh
pup=0.5*(Xi22+2*h*max(f2,0.0))/Qh
pdown=0.5*(Xi22+2*h*max(-f2,0.0))/Qh
pswitch=(h*h*qSubDiag[r])/Qh
pstay=h/Qh
temp=(1-la*dlt)*(pforward*Vold[i+1,j,r]+pback*Vold[i-1,j,r]
+pup*Vold[i,j+1,r]+pdown*Vold[i,j-1,r]
+pswitch*Vold[i,j,3-r]
+pstay*Vold[i,j,r])+la*dlt*vInt+dlt*g
# find the minimal value (Here is the spot!!!)
if(uit==1){
vmin=temp; umin=u
}else if(temp<vmin){
vmin=temp; umin=u
}
}
Vnew[i,j,r]=vmin
Uopt[i,j,r]=umin
}
}
errormax=max(abs(Vold-Vnew))
print(n)
print(errormax)
Vold=Vnew
if(errormax<tol){
break
}
}
}
I have a question how to make a IF
for (i in 1:12){
for (j in 1:12) {
if (i != j) {
var = x + b
}
else{ }
}}
"else" I need that when they are equal to continue with j + 1 example: if i = 4 and j = 4 then continue with j = 5 and continue counting until the end of j and continue the process of when i! = j
I think you don't understand what is going on in your code or you don't understand what for loops do. One "trick" you can do is to actually print what happens in your for loops so that you will have one idea of what is going on. You could also do this with a piece of paper.
As they already pointed you out, you don't need the else because the for already takes care of this.
for (i in 1:12){
print("-------------------------------")
valueI <- paste0("my i value is ",i)
print(valueI)
for (j in 1:12) {
valueJ <- paste0("my j value is ",j)
print(valueJ)
if (i != j) {
#var = x + b
diff <- paste0(i, " is different than ", j)
print(diff)
}
else{
}
}
}
This code is the same as yours and will generate a log that explains you what happens step from step, you could also use a debugger but seeing your struggles, better use this for now. What are you trying to calculate? I feel like you want to calculate the power of something...
In my previous question:How do I put arena limits on a random walk? the community helped create a random walk function in a set arena. This function is designed to simulate a fish moving through an area, but now I need to make it decide when to stop when a certain condition is satisfied.
I thought it would be as simple as
{{if(z>P)break}} put in just before the loop function. What I want it to understand is "if this condition is satisfied then stop, otherwise keep going until you reach the maximum number of steps.
Instead it caused my random walk to become deterministic (I always get the same path and it never stops before step.max).
Main question: How do I tell the random walk to stop if z>P?
For reference:
step.max<-125
step.prob<-function(n.times=step.max){
draw=sample(0:100,1,replace=T)
CS<-sample(draw,size=1,replace=TRUE)
CS.max<-100
step.num<-15
SP<-((CS/CS.max)*(1-(step.num/step.max))+(step.num/step.max))*100
if(SP>P){stop('Settled at step number',P)}else{SP
}
}
z<-step.prob(1) #renaming the above function to be easier to reference later
P<-80 #preset cutoff point for value z, ranges from 0-100
walkE <- function(n.times=125,
xlim=c(524058,542800),
ylim=c(2799758,2818500),
start=c(525000,2810000),
stepsize=c(4000,4000)) {
plot(c(0,0),type="n",xlim=xlim,ylim=ylim,
xlab="Easting",ylab="Northing")
x <- start[1]
y <- start[2]
steps <- 1/c(1,2,4,8,12,16)
steps.y <- c(steps,-steps,0)
steps.x <- c(steps,-steps[c(1,5,6)],0)
points(x,y,pch=16,col="red",cex=1)
for (i in 1:n.times) {
repeat {
xi <- stepsize[1]*sample(steps.x,1)
yi <- stepsize[2]*sample(steps.y,1)
newx <- x+xi
newy <- y+yi
if (newx>xlim[1] && newx<xlim[2] &&
newy>ylim[1] && newy<ylim[2]) break
}
lines(c(x,newx),c(y,newy),col="blue")
x <- newx
y <- newy
if(z>P){stop(points(newx,newy,col="green",cex=1))}
#this is where I want it to stop if z>P
else
if(z<P){points(newx,newy,pch=1,col="blue",cex=1)}
else
if(step.max){points(newx,newy,pch=16,col="green",cex=1)}
set.seed(101)}
}
walkE(step.max) #run above random walk function walkE looped for the step.max number
Thanks in advance!!!
This is pretty easy and can be accomplished by inserting a stop(...) function in your user defined step.prob function.
step.prob<-function(n.times=step.max, p){
draw=sample(0:100,1,replace=T)
CS<-sample(draw,size=1,replace=TRUE)
CS.max<-100
CS.max
step.num<-15
SP<-((CS/CS.max)*(1-(step.num/step.max))+(step.num/step.max))*100
if(SP > p) {
stop('Your random walk exceeded ', p)
} else {
SP
}
}
If this doesn't do it for you look into the break command.
So, when the random walk value is > p:
step.prob(p=300000)
# Error in step.prob(p = 3) : Your random walk exceeded 3
And if you want to set the value returned by the function to p you can just add in SP <- p before the stop command.
I'm trying to implement Bin Fu's approximate sum algorithm
in a real language to have a better feel of how it works.
In a nutshell, this is an algorithm to compute $\hat{s}(x)$,an $(1+\epsilon)$ approximation on the value of $s(x)=\sum_{i=1}^n x_i$
(e.g. this means that $\hat{s}(x)$ satisfies: $\hat{s}(x)/(1+\epsilon)\leq s(x)\leq (1+\epsilon)\hat{s}(x)$[1]).
However, I must be doing something wrong because running my implementation doesn't give the right result, e.g. the $\hat{s}(x)$ I get out of it doesn't satisfy [1].
I suspect that in my implementation below, I'm existing too early, but I don't see what is causing this.
ApproxRegion<-function(x,b,delta,n){
if(n<=1 || x[n]<b) return(NULL)
if(x[n-1]<b) return(c(n,n))
if(x[1]>=b) return(c(1,n))
m<-2
while(n-m**2>0 && x[n-m**2+1]>=b) m<-m**2
r<-m
while(m>=(1+delta)){
m<-sqrt(m)
if(n-floor(m*r)>=0 && x[n-floor(m*r)+1]>=b) r=m*r
}
return(c(n-floor(m*r)+1,n))
}
ApproxSum<-function(x,n,epsilon){
if(x[n]==0) return(0)
delta=3*epsilon/4
rp<-n
i<-0
s<-0
b<-x[n]/(1+delta)
while(b>=delta*x[n]/(3*n)){
R<-ApproxRegion(x,b,delta,rp)
if(is.null(R)) break
rp<-R[1]-1;
b<-x[rp]/(1+delta)
si<-(R[2]-R[1]+1)*b
s<-s+si
i<-i+1
}
return(list(s=s,i=i))
}
However, when I run it
n<-100;
set.seed(123)
x<-sort(rexp(n));
eps<-1/10
y0<-ApproxSum(x=x,n=n,epsilon=eps);
y0$s*(1+eps)
sum(x)
I get that y0$s*(1+eps) is smaller than sum(x)
Looks like you're loosing track of i vs i+1 in two places, the second while loop in ApproxRegion and the loop in ApproxSum. This looks like it works on your example:
ApproxRegion<-function(x,b,delta,n){
if(n<=1 || x[n]<b) return(NULL)
if(x[n-1]<b) return(c(n,n))
if(x[1]>=b) return(c(1,n))
m<-2
while(n-m**2>0 && x[n-m**2+1]>=b) m<-m**2
r<-m
while(m>=(1+delta)){
m<-sqrt(m)
if(n-floor(m*r)>=0 && x[n-floor(m*r)+1]>=b) r=m*r
}
return(c(n-floor(r)+1,n))
}
ApproxSum<-function(x,n,epsilon){
if(x[n]==0) return(0)
delta=3*epsilon/4
rp<-n
i<-0
s<-0
b<-x[n]/(1+delta)
while(b>=delta*x[n]/(3*n)){
R<-ApproxRegion(x,b,delta,rp)
if(is.null(R)) break
si<-(R[2]-R[1]+1)*b
s<-s+si
i<-i+1
rp<-R[1]-1;
b<-x[rp]/(1+delta)
}
return(list(s=s,i=i))
}
n<-100;
set.seed(123)
x<-sort(rexp(n));
eps<-0.001
y0<-ApproxSum(x=x,n=n,epsilon=eps);
> y0$s*(1+eps)
[1] 104.5955
> sum(x)
[1] 104.5719
> y0$s/(1+eps)
[1] 104.3866