在基于图论的Java程序中基于DSL的输入图数据的方法

我们大多数人已经编写了一些程序来处理图论算法,例如查找两个顶点之间的最短路径,查找给定图的最小生成树等等。 在这些算法的每一种中,表示图形的编程方式是使用邻接矩阵或邻接表 。 两者都不是定义图形输入的非常直观的方法。 例如,如果未在正确的列和行中进行输入,则邻接矩阵可能会导致错误。 而且,在运行时,您不太确定哪个行/列代表哪个边,当涉及到具有大量顶点的图形的输入时,事情会变得更加复杂。

在我的工程研究期间,我已经用Java实现了许多图形算法,并且在所有这些图形算法中,我都嵌套了for循环以获取邻接矩阵输入。 最近,当我阅读Martin Fowlers的DSL书籍时,我想到了创建DSL来提供图形输入的想法,即DSL,它允许用户指定顶点,边和权重。 我选择了已实现的图形算法,只是去除了邻接矩阵输入,而是使用了我创建的DSL。 该算法就像一个魅力。

在这篇文章中,我将通过采用不同的图形输入并为它们显示DSL来显示DSL的有效语法。 然后,我将向您展示我创建的库,该库由图的语义模型,DSL的解析器和词法分析器以及一个简单的构建器API组成,该API从DSL脚本中填充语义模型。 解析器和词法分析器是使用ANTLR生成的,因此此库要求ANTLR Jar在类路径中可用。 最后,我将展示如何使用Kruskals算法将该DSL用于查找最小生成树。

DSL语法和一些示例

下图(g1)的DSL:

图表G1

图表G1

Graph {A1 -> B2 (12.3)B2 -> C3(0.98)C3->D4 (2)D4 ->E5 (12.45)
}

请注意,上述DSL中的元素之间存在不同的空间。 这只是为了显示可以编写DSL的不同方式。

下图(g2)的DSL为:

图G2

图G2

Graph{A1 -> B2 (12.3)B2 -> C3 (0.98)C3 -> D4 (2)E5
}

请注意,“图形”和“ {”之间没有空格。 这只是为了显示它的不同编写方式。

下图(g3)的DSL为:

图G3

图G3

Graph {A -> B (12.3)B -> C (0.98)C -> D (2)D -> E (12.45)
}

现在显示一些无效的DSL脚本:

Graph {1A -> B (12.3)B -> C (0.98)
}

上面的无效,因为顶点名称以数字开头。

Graph {
}

上面的方法无效,因为Graph希望至少定义一个顶点。 但是它可以具有零个或多个边。

基于DSL的图形输入库

我已经利用ANTLR来完成为我为DSL定义的语法创建词法分析器和解析器的所有任务。 这样,我不必担心创建解析器或担心从DSL输入脚本创建令牌。

解析器和词法分析器类以及语义模型类一起打包到一个jar中,并且必须将这个jar和ANTLR jar一起包括在内,以利用编写用于图形输入的DSL来使用。

DSL jar的结构可以在下面的屏幕截图中看到:

GraphDSL Jar

GraphDSL Jar

图包中的类对应于语义模型,即它们是通用类,可以在不考虑是否有人在使用DSL的情况下使用。 graph.dsl中的类对应于ANTLR为lexer和parser生成的Java类。

ANTLR用于词法分析和解析的语法为:

grammar Graph;graph: GRAPH_START (edge|vertex)+ GRAPH_END;
edge: (vertex) TO (vertex) weight;
vertex: ID;
weight: '(' NUM ')';
GRAPH_START : 'Graph'([ ])*'{';
GRAPH_END : '}';
WEIGHT_START: '(';
WEIGHT_END: ')'; 
TO: '->';
ID: ^[a-zA-Z][a-zA-Z0-9]*;
NUM: [0-9]*[.]?[0-9]+;
WS: [ \t\r\n]+ -> skip;

上面的语法有待改进,但作为我的第一次尝试,我试图将其保持在这个水平。

  • 从此处下载DSL jar(GraphDSL.jar)。
  • 从此处下载ANTLR jar(antlr-4.1-complete.jar)。

注意:此DSL是使用ANTLR版本4开发的。

对于使用ANTLR的外部DSL的推荐书是《 语言实现模式:创建自己的域》特定和通用编程语言

Kruskals算法找到最小生成树

用于测试此算法实现的图形为:

样本图

样本图

和DSL相同的是:

Graph  {A -> B (7)B -> C (8)A -> D (5)B -> D (9)D -> E (15)D -> F (6)E -> F (8)E -> C (5)B -> E (7)E -> G (9)F -> G (11)
}

让我们看一下实现:

package kruskalsalgo;import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
import graph.Edge;
import graph.Graph;
import graph.Vertex;
import graph.GraphBuilder;
import java.io.IOException;
import java.util.Comparator;public class KruskalsAlgorithm {public static void main(String[] args) throws IOException {//Load the graph data from the DSLGraph g = new GraphBuilder().buildGraph("graph.gr");ArrayList<Set> forest = new ArrayList<Set>();ArrayList<Edge> finalEdgeSet = new ArrayList<Edge>();//Creating disjoint set of vertices which represents the initial forestfor (Vertex v : g.getVertices()) {Set newSet = new Set();newSet.getVertexList().add(v);forest.add(newSet); //Creating Disjoint Sets}//sort the edges in the graph based on their weightCollections.sort(g.getEdges(), new Comparator<Edge>(){public int compare(Edge o1, Edge o2) {return o1.getWeight().compareTo(o2.getWeight());}});for (Edge edge : g.getEdges()) {//Find in which set the vertices in the edges belongint rep1 = Set.findRep(edge.getFromVertex(), forest);int rep2 = Set.findRep(edge.getToVertex(), forest);//If in different sets then merge them into one set and pick the edge.if (rep1 != rep2) {finalEdgeSet.add(edge);Set.Union(rep1, rep2, forest);}}System.out.println("The Minimum Spanning tree is");for (Edge edge : finalEdgeSet) {System.out.println("Vertex: " + edge.getFromVertex().getLabel() + " to Vertex: " + edge.getToVertex().getLabel());}System.out.println("");}//End of Main
}class Set {private ArrayList<Vertex> vertexList;private int representative;static int count;public Set() {vertexList = new ArrayList<Vertex>();this.representative = ++(Set.count);}//Find the set identifier in which the given vertex belongs to.public static int findRep(Vertex vertex, ArrayList<Set> forest) {int rep = 0;for (Set set : forest) {for (Vertex v : set.getVertexList()) {if (v.getLabel().equals(vertex.getLabel())) {return set.getRepresentative();}}}return rep;}//Find the set given the step identifier.public static Set findSet(int rep, ArrayList<Set> forest) {Set resultSet = null;for (Set set : forest) {if (set.getRepresentative() == rep) {return set;}}return resultSet;}//Merge the set into another and remove it from the main set.public static void Union(int rep1, int rep2, ArrayList<Set> forest) {Set set1 = Set.findSet(rep1, forest);Set set2 = Set.findSet(rep2, forest);for (Vertex v : set2.getVertexList()) {set1.getVertexList().add(v);}forest.remove(set2);}public ArrayList<Vertex> getVertexList() {return vertexList;}public int getRepresentative() {return representative;}
}

上面的代码从dslgraph.gr加载图形数据。 DSL脚本必须放在资源包中,以便DSL库可以找到它。

上面代码的输出:

The Minimum Spanning tree is
Vertex: A to Vertex: D
Vertex: E to Vertex: C
Vertex: D to Vertex: F
Vertex: A to Vertex: B
Vertex: B to Vertex: E
Vertex: E to Vertex: G

并以示意图形式显示

最小生成树

最小生成树

参考:来自CG的合作伙伴 Mohamed Sanaulla(来自Experiences Unlimited博客)中的基于DSL的方法,用于在基于图论的Java程序中输入图数据 。

翻译自: https://www.javacodegeeks.com/2013/07/dsl-based-approach-to-input-graph-data-in-graph-theory-based-java-programs.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/368054.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Remmarguts' Date(POJ2449+最短路+A*算法)

题目链接&#xff1a;http://poj.org/problem?id2449 题目&#xff1a; 题意&#xff1a;求有向图两点间的k短路。 思路&#xff1a;最短路A*算法 代码实现如下&#xff1a; 1 #include <set>2 #include <map>3 #include <queue>4 #include <stack>5 …

usb3.0 linux无法识别,USB3.0接口不能识别U盘的解决方法

USB接口可以说是电脑的标配&#xff0c;现在基本上所有电脑都会搭载USB接口。而USB标准从1.0发展到现在的3.0&#xff0c;甚至更新的也已出来。不过&#xff0c;如果USB3.0无法识别U盘&#xff0c;那该怎么办呢?USB3.0是一种技术也是一种规范&#xff0c;现在很多笔记本都是默…

table 鼠标移上去改变单元格边框颜色。

表格定义了 border-collapse:collapse;边框会合并为一个单一的边框。会忽略 border-spacing 和 empty-cells 属性。用td:hover,显示不全 搜索了好久&#xff0c;没有找到好的方法&#xff0c;用左右边框也不完美。 于是就在想&#xff0c;移上去的时候给加个伪元素after&#…

PotPlayer安装与配置

目录 1.简介 2.安装 3.设置 基本选项设置&#xff1a; 播放选项设置&#xff1a; PotPlayer皮肤设置&#xff1a; 1.简介 PotPlayer一款小巧简单的视频播放软件&#xff0c;具有于强大的定制能力和个性化功能。 2.安装 官网下载 potplayer http://potplayer.daum.net/?langzh_…

Hadoop的目录结构

转载于:https://www.cnblogs.com/wzlbigdata/p/8392162.html

linux 实验 ps,Linux实验室:监控命令iostat与ps_服务器x86服务器-中关村在线

4、iostat与上面的命令相似&#xff0c;很显然&#xff0c;这个linux系统监控命令是属于IO监控系列的&#xff0c;iostat(I/O statistics&#xff0c;输入输出统计)是一个用于收集显示系统存储设备输入和输出状态统计的简单工具。例如命令&#xff1a;iostat -m -x 1 1000。从结…

基于浏览器的密钥生成以及与浏览器的密钥/证书存储的交互

想象以下情况&#xff1a; 您需要从访问您的网站的用户那里获取一个密钥&#xff08;在非对称情况下为用户的公共密钥 &#xff09;&#xff0c;并希望浏览器记住私有部分&#xff0c;而不会因冗长的导入过程而困扰用户。 老实说&#xff0c;实际上&#xff0c;您甚至不希望用…

linux制作一键恢复,Linux/Centos Mondo 一键部署、镜像恢复,快速部署

1.环境准备image.png2.安装mondocurl -o /etc/yum.repos.d/mondorescue.repo ftp://ftp.mondorescue.org/rhel/7/x86_64/mondorescue.reposed -i s#gpgcheck1#gpgcheck0#g /etc/yum.repos.d/mondorescue.repoyum -y install mondosed -i s#EXTRA_SPACE150000#EXTRA_SPACE650000…

转载:pycharm最新版新建工程没导入本地包问题:module 'selenium.webdriver' has no attribute 'Firefox'...

pycharm最新版新建工程没导入本地包问题&#xff1a;module selenium.webdriver has no attribute Firefox 前言 最新版的pycharm做了很大的改变&#xff0c;新建工程的时候&#xff0c;默认不导入本地的安装包&#xff0c;这就导致很多小伙伴踩坑了。。。明明已经pip安装过sel…

chrome 开发者工具,查看元素 hover 样式

在web开发中&#xff0c;浏览器开发者工具是我们常用的调试工具。我们经常会有这样的需求&#xff0c;就是查看元素的时候需要查看它的hover样式。相信有很多小伙伴都遇到过这样的情形&#xff0c;始终选不中hover后的元素状态。其实在开发者工具中是有地方可以设置的。方法如下…

.net ad域登录 form认证_golang|给Gitbook做个认证代理

后台管理系统嵌入了Gitbook做帮助中心&#xff0c;需要给Gitbook添加下认证。思路如下&#xff1a;修改Gitbook发布时的js&#xff0c;给每个URL拼接上用户登录后的Token&#xff0c;Gitbook前面有个代理获取这个Token&#xff0c;Token验证成功&#xff0c;则将请求发送给Gitb…

strtoul()要优于atoi()函数---C语言

strtoul()&#xff1a;将字符串转为长整型整数 atoi()&#xff1a;将字符串转为整型整数 在32位STM32中&#xff0c;int是32位的&#xff0c;如果字符串是“3123456789”&#xff0c;大于0x7fff fff&#xff0c;用atoi()函数返回的值就是0x7fff fff&#xff0c;而使用strtoul就…

Web前端行业的机遇与自我规划,如果你对未来没有方向 不如看一看,或许就是一道曙光!

本篇是来自西安前端开发者分享社区的经验分享&#xff0c;给出前端工作人员在行业中的发展建议&#xff0c;如果我们没有目标时候 不妨看看别人是怎么做的&#xff01; 感谢西安前端开发者分享社区的分享&#xff01; 资源下载&#xff1a;来自示说网平台&#xff08;https://…

中职升高职c语言程序设计教程课后答案,中职C语言教学创新与实践论文

中职C语言教学创新与实践论文摘要&#xff1a;自主学习体现了以学生为中心、以人为本的教学思想&#xff0c;是一种行之有效的教学方法&#xff0c;但中职学生自主学习能力整体比较欠缺&#xff0c;学生怕学、厌学现象严重&#xff0c;给教师的教学带来一定的难度。文章以C语言…

cv岗工作做什么_职场速递:我应该做什么工作?

我曾经7年换过6份工作&#xff0c;转行3次&#xff0c;只是因为一直纠结于&#xff1a;到底什么才是我想要的工作。我和很多职场人一样&#xff0c;在“我想做的&#xff0c;我喜欢的”和“我能做的&#xff0c;能养活我的”选项之间迷惘过。大部分人提起自己工作的时候&#x…

【校招面试 之 网络】第3题 HTTP请求行、请求头、请求体详解

1、HTTP请求报文解剖 HTTP请求报文由3部分组成&#xff08;请求行请求头请求体&#xff09;&#xff1a; 下面是一个实际的请求报文&#xff1a; ①是请求方法&#xff0c;GET和POST是最常见的HTTP方法&#xff0c;除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。不过&a…

奇妙的 CSS shapes(CSS图形)

CSS 发展到今天已经越来越强大了。其语法的日新月异&#xff0c;让很多以前完成不了的事情&#xff0c;现在可以非常轻松的做到。今天就向大家介绍几个比较新的强大的 CSS 功能&#xff1a; clip-pathshape-outside shape 的意思是图形&#xff0c;CSS shapes 也就是 CSS 图形…

c++ map 多线程同时更新值 崩溃_深入理解并发安全的 sync.Map

golang中内置了map关键字&#xff0c;但是它是非线程安全的。从go 1.9开始&#xff0c;标准库加入了sync.Map&#xff0c;提供用于并发安全的map。普通map的并发问题map的并发读写代码func main() { m : make(map[int]int) go func() { for { _ m[1] // 读 } }(…

java 递归从子节点删除父节点_LeetCode450. 删除二叉搜索树中的节点

删除一个二叉搜索树中的节点&#xff0c;需要进行情况的分类讨论&#xff0c;看一下将这个节点删除之后是否需要对二叉搜索树进行调整&#xff08;为了保持树的连接和维持二叉搜索树的性质&#xff09;。&#xff08;1&#xff09;如果删除的是一个叶子节点&#xff0c;那问题不…

1. [文件]- 文件类型,文件open模式

1.文件类型&#xff1a;文本文件和二进制文件 硬盘中的文件保存为01010101格式&#xff0c;一般读取文件是把文件从硬盘中读取到内存中。 文本文件需要进行格式转换才能读取出来。二进制文件一般用于传输二进制文件&#xff1a;视频图片 2.文件打开模式 几种不同的读取和遍历文…