You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, thank you for creating this amazing package. I am trying to solve the chinese postman problem (CPP). So far, I followed the tutorial found here, where I just set 10 points that the postman needs to pass from, given that the starting and ending point are the same. The code:
library(sfnetworks)
library(sf)
library(tidygraph)
library(dplyr)
library(purrr)
library(TSP)
library(igraph)
# Read road layer
r <- st_read("path/test_road.geojson")
# convert to linestring
r_lines = st_cast(r, "LINESTRING")
# Plot the road network (r)
plot(r_lines, col = "gray", lwd = 2, main = "Road Network with Points Overlay")
net = as_sfnetwork(r_lines, directed = FALSE) %>%
activate("edges") %>%
mutate(weight = edge_length())
plot(net)
set.seed(403)
rdm = net %>%
st_bbox() %>%
st_as_sfc() %>%
st_sample(10, type = "random")
net = activate(net, "nodes")
cost_matrix = st_network_cost(net, from = rdm, to = rdm, weights = "weight")
# Use nearest node indices as row and column names.
rdm_idxs = st_nearest_feature(rdm, net)
row.names(cost_matrix) = rdm_idxs
colnames(cost_matrix) = rdm_idxs
round(cost_matrix, 0)
tour = solve_TSP(TSP(units::drop_units(cost_matrix)))
tour_idxs = as.numeric(names(tour))
tour_idxs
# Approximate length of the route.
# In meters, since that was the unit of our cost values.
round(tour_length(tour), 0)
# Define the nodes to calculate the shortest paths from.
# Define the nodes to calculate the shortest paths to.
# All based on the calculated order of visit.
from_idxs = tour_idxs
to_idxs = c(tour_idxs[2:length(tour_idxs)], tour_idxs[1])
# Calculate the specified paths.
tsp_paths = mapply(st_network_paths,
from = from_idxs,
to = to_idxs,
MoreArgs = list(x = net, weights = "weight")
)["node_paths", ] %>%
unlist(recursive = FALSE)
# Plot the results.
plot(net, col = "grey")
colors <- c("red", "blue", "green")
plot(rdm, pch = 20, col = colors[2], add = TRUE)
plot_path = function(node_path) {
net %>%
activate("nodes") %>%
slice(node_path) %>%
plot(cex = 1.5, lwd = 1.5, add = TRUE)
}
walk(tsp_paths, plot_path) # Reuse the plot_path function defined earlier.
plot(
st_as_sf(slice(net, rdm_idxs)),
pch = 20, col = colors[3], add = TRUE
)
plot(
st_as_sf(slice(net, tour_idxs[1])),
pch = 8, cex = 2, lwd = 2, col = colors[3], add = TRUE
)
text(
st_coordinates(st_as_sf(slice(net, tour_idxs[1]))) - c(200, 90),
labels = "start/end\npoint"
)
Now I want to set a point (see the dput(p) below) which will serve as my starting and ending point but the postman needs to pass from every street (if possible) instead of 10 random points. I tried fe things without success (that's why I'm not posting ane example). I am very new to graphs so any help to point me to the right direction would be nice.
The Travelling Salesman Problem finds the optimal route visiting a set of nodes, while (if I am right) the Chinese Postman Problem finds the optimal route visiting a set of edges. How this could normally be solved is by converting the network to its linegraph, in which nodes become edges and vice versa, using tidygraph::to_linegraph(), and then solving a regular TSP. However I have not tried myself before if it works well with sfnetwork objects for this case, would be interesting to find out!
Hi, thank you for creating this amazing package. I am trying to solve the chinese postman problem (CPP). So far, I followed the tutorial found here, where I just set 10 points that the postman needs to pass from, given that the starting and ending point are the same. The code:
Now I want to set a point (see the
dput(p
) below) which will serve as my starting and ending point but the postman needs to pass from every street (if possible) instead of 10 random points. I tried fe things without success (that's why I'm not posting ane example). I am very new to graphs so any help to point me to the right direction would be nice.The dataset I am using:
And the road network
The text was updated successfully, but these errors were encountered: