Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Graph 以集合为顶点的图_Graph_Set_Ocaml - Fatal编程技术网

Graph 以集合为顶点的图

Graph 以集合为顶点的图,graph,set,ocaml,Graph,Set,Ocaml,我有一个很小的语法,表示为一个变体类型term,字符串是令牌/令牌的一部分(type term)。 给定语法中的表达式,我从表达式中收集所有字符串并将它们打包到集合中(functionvars)。最后,我想用这些集合作为顶点创建一些图(第48-49行) 出于某种原因,以这种复杂方式创建的图形无法识别包含相同变量的集合,并创建具有相同内容的多个顶点。我真的不明白为什么会这样 以下是此行为的最低工作示例: (*demo.ml*) 类型术语= |字符串变量 |术语列表*字符串选项列表 |术语表元组 模

我有一个很小的语法,表示为一个变体类型
term
,字符串是令牌/令牌的一部分(type term)。 给定语法中的表达式,我从表达式中收集所有字符串并将它们打包到集合中(function
vars
)。最后,我想用这些集合作为顶点创建一些图(第48-49行)

出于某种原因,以这种复杂方式创建的图形无法识别包含相同变量的集合,并创建具有相同内容的多个顶点。我真的不明白为什么会这样

以下是此行为的最低工作示例:

(*demo.ml*)
类型术语=
|字符串变量
|术语列表*字符串选项列表
|术语表元组
模块SSet=Set.Make(
结构
让compare=String.compare
类型t=字符串
(完)
设rec vars=函数
|变量v->SSet.singleton v
|列表(x,尾部)->
让tl=将尾部与
|无->SSet.empty
|中的某些var->SSet.singleton var
SSet.union tl(List.fold_left SSet.union SSet.empty(List.map vars x))
|Tuple x->List.fold\u left SSet.union SSet.empty(List.map vars x)
模块节点=结构
类型t=SSet.t
让我们比较一下
设相等=设相等
让hash=Hashtbl.hash
结束
模块G=图.命令式.有向图.双向(节点)
(*用于图示的图形的点输出*)
模块点=图形.Graphviz.Dot(结构
包括G
让边_属性=[]
让默认的_边_属性=[]
设get_子图u=None
让顶点_属性=[]
让vertex_name v=Printf.sprintf“{%s}”(String.concat),“(SSet.elements v))
让默认的_顶点_属性=[]
让图_属性=[]
(完)
让我们=
(*创建两个术语*)
让a,b=列表([Var“a”],一些“b”),元组[Var“a”;Var“b”]in
(*从打包到集合中的术语中获取字符串*)
让avars,bvars=vars a,vars b进入
让g=g.create()在
G.添加边G avars bvars;
Printf.Printf“内容相同:[%s][%s]\n”
(String.concat“,(SSet.elements avars))
(String.concat“,”(SSet.elements bvars));
Printf.Printf“比较/相等输出:%d%b\n”
(SSet.avars bvars比较)
(SSet.equal avars bvars);
Printf.Printf“哈希值不同:%d%d\n”
(Hashtbl.hash avars)(Hashtbl.hash bvars);
Dot.fprint_graph Format.str_格式化程序g;
Printf.Printf“图形表示:\n%s”(Format.flush\u str\u formatter())
为了编译,输入
ocamlc-c-I+ocamlgraph demo.ml;ocamlc-I+ocamlgraph graph.cma demo.cmo
。执行程序时,您会得到以下输出:

The content is the same: [a, b] [a, b]
compare/equal output: 0 true
Hash values are different: 814436103 1017954833
Graph representation:
digraph G {
  {a, b};
  {a, b};


  {a, b} -> {a, b};
  {a, b} -> {a, b};

  }

总之,我很好奇为什么集合的散列值不相等,并且在图形中创建两个相同的顶点,尽管这些集合通过所有其他方式都相等。

我怀疑一般的答案是OCaml的内置散列是基于值的物理属性,而集合相等是一个更抽象的概念。如果将集合表示为有序的二叉树,则有许多树表示同一集合(众所周知)。这些将作为集合相等,但很可能散列为不同的值


如果您想对集合进行哈希运算,您可能必须提供自己的函数。

正如Jeffrey指出的那样,问题似乎在于作为
节点
模块一部分的哈希函数的定义中


将其更改为
let hash x=Hashtbl.hash(SSet.elements x)
解决了这个问题。

看来您是对的。但是,如果标准函数不起作用,为什么不在集合的
Set
模块中提供
hash
函数呢?我希望OCaml标准库中有很多这样的函数。较新的库如和正在填补空白。