城市间最短路径问题——R和Rcpp实现
这里的最短路径问题也叫做相识问题,具体问题来自
刚好在学Rcpp,于是写了R版本和Rcpp版本的函数来解决这个问题,顺便比较一下二者的运行速度。
Rcpp包为在R中使用C++提供了很便捷的方式,这让R代码的运行速度有了很大的提升。使用Rcpp对C++有个基本了解就行,不需要对C++很熟练。学习Rcpp包的资源有很多,这里推荐一本对像我这种C++小白比较友好的电子书:https://teuder.github.io/rcpp4everyone_en/。Rcpp包的安装和配置等细节这里就不提了,感兴趣的读者可以自行搜索,网上资源很多。
R版本,R_shortest()函数定义如下:
R_shortest<-function(M){
n<-max(M)
A<-matrix(Inf,n,n)
for(i in 1:nrow(M)){A[M[i,1],M[i,2]]<-A[M[i,2],M[i,1]]<-1}
diag(A)<-0
while(TRUE){
B<-A
for(i in 1:n){
for(j in 1:n){
for(k in 1:n){
if(A[i,j]>A[i,k]+A[k,j]){
A[i,j]<-A[i,k]+A[k,j]
}
}
}
}
if(identical(B,A)){break}else{B<-A}
}
return(A)
}
Rcpp版本,Rcpp_shortest()函数定义如下:
首先是创建一个名为shortest的cpp文件,文件内容如下:
#include <Rcpp.h>
using namespace Rcpp; // [[Rcpp::export]]
NumericMatrix Rcpp_shortest(NumericMatrix M){
M=M-1; //注意,c++下标从0开始,而R下标从1开始,因此要减去1
int n=max(M(_,1))+1; //由于减了1,因此新矩阵的行数应该是现在M的最大值加1
NumericMatrix A(n,n);
A.fill(R_PosInf);
A.fill_diag(0);
for(int i=0;i<M.nrow();i++){
A(M(i,0),M(i,1))=1;
A(M(i,1),M(i,0))=1;
} while(true){
NumericMatrix B=clone(A);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
for(int k=0;k<n;k++){
if(A(i,j)>A(i,k)+A(k,j)){
A(i,j)=A(i,k)+A(k,j);
}
}
}
}
if(sum(A!=B)==0){break;}else{B=clone(A);}
}
return A;
}
然后是对这个文件在R中调用,调用之后会得到一个名为Rcpp_shortest()的函数:
library(Rcpp)
sourceCpp("shortest.cpp")
速度比较
M<-matrix(c(1,2,2,3,3,4,4,5,5,8,7,9,
9,21,10,11,11,12,13,21,21,100),
ncol=2,byrow=TRUE) #生成包含100个城市的矩阵M;
identical(R_shortest(M),Rcpp_shortest(M)) #考虑返回结果是否一致
library(rbenchmark) #速度比较包
benchmark(R_shortest(M),Rcpp_shortest(M),
columns=c("test","replications","elapsed","relative")) #速度比较
> identical(R_shortest(M),Rcpp_shortest(M))
[1] TRUE
两个函数运行结果一致,速度比较结果如下:
test replications elapsed relative
1 R_shortest(M) 100 110.70 307.5
2 Rcpp_shortest(M) 100 0.36 1.0
在本人电脑上,R版本用时是Rcpp版本的307倍,Rcpp版本的速度远快于R版本,加速效果不错!所以说,懂得一点C++的话,利用Rcpp来编写循环和四则运算的话,还是可以达到对R加速的目的。此外,由于Rcpp的存在,Rcpp版本的函数和R版本的函数其实很像,因此将R版本的函数改写为Rcpp版本的函数难度也不会很大。
- 附带一个Python版本吧,权当练练手,不过这就无关主题了。
import pandas as pd
import numpy as np
def Py_shortest(M):
M=M-1
n=M[:,1].max()+1
A=np.full(shape=(n,n),fill_value=float("inf"))
np.fill_diagonal(a=A,val=0)
for i in range(0,M.shape[0]):
A[M[i,0],M[i,1]]=1
A[M[i,1],M[i,0]]=1
while(True):
B=A.copy()
for i in range(0,n):
for j in range(0,n):
for k in range(0,n):
if A[i,j]>A[i,k]+A[k,j]:
A[i,j]=A[i,k]+A[k,j]
if((A==B).all()):
break
else:
B=A.copy()
return A M=np.array([[1,2],[2,3],[3,4],[4,5],[5,8],[7,9],
[9,21],[10,11],[11,12],[13,21],[21,100]])
import time
time_start=time.time()
Py_shortest(M)
time_end=time.time()
print(time_end-time_start)
本人电脑运行一次Py_shortest(M)的时间在3-4秒内,Python下标也从0开始,写程序时要注意和R、Rcpp的区别和联系。
城市间最短路径问题——R和Rcpp实现的更多相关文章
- 城市间紧急救援(25 分)(dijstra变形)
城市间紧急救援(25 分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标 ...
- PTA-数据结构 Dijkstra 城市间紧急救援
城市间紧急救援(25 分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标 ...
- 5-5 城市间紧急救援 (25分)【最短路spfa】
5-5 城市间紧急救援 (25分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速 ...
- PTA数据结构与算法题目集(中文) 7-35 城市间紧急救援 (25 分)
PTA数据结构与算法题目集(中文) 7-35 城市间紧急救援 (25 分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市 ...
- JS广度优先查找无向无权图两点间最短路径
广度优先查找无向无权图两点间最短路径,可以将图看成是以起点为根节点的树状图,每一层是上一层的子节点,一层一层的查找,直到找到目标节点为止. 起点为0度,与之相邻的节点为1度,以此类推. // 广度优先 ...
- 城市间紧急救援 Dijkstra
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求 ...
- 计算城市间的球面距离(C++实现)
#include<iostream> #include<string> #include<cmath> #include<iomanip> using ...
- 弗洛伊德算法Floyed(求各顶点间最短路径):可打印最短路径
#include <iostream> #include <string> #include <iomanip> using namespace std; #def ...
- 九度OJ 1325:Battle Over Cities(城市间的战争) (并查集)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:376 解决:132 题目描述: It is vitally important to have all the cities connect ...
- Neo4j查询节点间最短路径
Neo4j最短路径问题 1.指定某一结点 无向边: MATCH (p1:Person {name:"aaaaaaa"}),(p2:Person{name:"bbbbbb& ...
随机推荐
- Truenas core 13连接LDAP,获取AD域用户及自动分配权限---chatGPT回复,未做证实
要在TrueNAS Core 13上连接LDAP并从AD域中获取用户,请按照以下步骤操作: 在TrueNAS Core 13上登录到WebUI. 转到"网络"菜单并选择" ...
- day11_多态&抽象类&接口
1.多态 1.1 多态的概述(记忆) 什么是多态 同一对象,在不同时刻表现出来的不同形态. 多态的前提 有继承/实现关系 有方法重写 有父类对象的引用执行子类对象 1.2 多态中的成员访问特点 ...
- Vue框架中有关 computed的相关知识
1,传统使用computed属性的方式如下: 注意:此时如果我们点击修改的时候会有如下警告(表示computed属性不可以修改,如果非得修改,我们应该如下下图所示操作) 2,修改computed属性的 ...
- React Navite环境搭建
俗话说"工欲善其事,必先利其器."所以,我们第一步就是搭建React Native开发坏境. 一.安装Node.js.npm.yarn 1.1 React native需要借助no ...
- 30:33 error 'scope' is defined but never used vue/no-unused-vars
由于一直报错,所以把这个slot-scope="scope"删除掉
- lbaas
目录 - LBaaS v2 - 负载均衡概念 - 服务器池 Pool - 监听器 Listener - L7 转发策略 l7 policy - 负载均衡算法 Algorithms - 健康监测 Mon ...
- APP稳定性测试Monkey工具介绍
一.Monkey工具简介 1.monkey的来源: Monkey是一个命令行工具,使用安卓调试桥(adb)来运行它,模拟用户:触摸屏幕.滑动Trackball.按键等随机事件流来对设备上的程序进行压力 ...
- python调用golang代码
一.调用步骤: 将go代码编译成so库 -> python中通过ctypes引用so库并指定需要调用的函数(同时可指定传入参数类型和返回值类型) -> 指定后按python使用函数方式调用 ...
- 学习笔记-Java面向对象
学习来源: B站[狂神说Java]Java零基础学习视频通俗易懂 static关键字详解 package com.oop.demo07; //static public class Student{ ...
- 在 Windows 上使用VirtualBox 安装 Ubuntu
一.VirtualBox虚拟机软件 之前使用过VMWare,这是第一次尝试使用VirtualBox,记录一下~ 我们可以从官网下载VirtualBox,地址:https://www.virtualbo ...