关于类似图形的数据结构的建议

时间:2018-09-05 09:22:38

标签: haskell data-structures

我需要数据结构来表示像模型一样的图形。

  • 它具有带有输入和输出的节点。
  • 这些输入和输出可以通过链接连接。
  • 一个输入最多可以连接一个输出。
  • 一个输出可以连接到多个输入。

执行最多的两个操作是:

  • 组合两个模型(将一些输入链接到输出)。
  • 用不同的图代替子图。

什么是代表此模型的最佳数据结构?

编辑

我将其用作编译器的一部分。该模型表示计算,其中节点是计算块,而链接是它们之间传递的数据。

我需要从源代码构建此模型。这就是为什么我需要组合操作。我将按语句处理源代码并调整模型,添加新的计算步骤。

我还想通过各种启发式方法“优化”我的计算。这就是为什么我需要用更优化的图替换该图的一部分(优化本身不在问题范围内,但是我需要“替换”操作)。

3 个答案:

答案 0 :(得分:1)

实际上,您在这里可以自由地做自己想做的事情:要解决的主要问题是,普通ADT不会给您可变的引用。以下是一些您可能会开始使用的示例。您甚至可能希望使用多个并在它们之间进行转换。

-- Here we have a pair of int indexed maps: the first one associates each
-- vertex index with a vertex value and a list of edge indices, and the
-- second one associates each edge index with an edge value and a pair of
-- vertex indices.
data Graph e v = Graph (M.Map Int (v, [Int])) (M.Map Int (e,Int,Int))

-- Here we use mutable references
newtype Graph s e v = Graph (STRef s (v,[(e,Graph s e v)]))

-- Here we use a single map and assume each vertex value is unique
newtype Graph e v = Graph (M.map v [(e,v)])

-- Single map again: but using ints to distinguish the vertices
newtype Graph e v = Graph (M.map Int (v,[(e,Int)]))

答案 1 :(得分:0)

这是一个间接答案。您问题的模糊性表明您可能是Haskell的新手,如果我认为做错了,请原谅我。

在纯FP中不能很好地使用图形,尤其是与algebraic data types(ADT)可以使用时相比。 ADT是表示抽象语法的常用方法,而反过来又是编译器通常进行操作和优化的方法(直到您开始生成机器代码,然后图形才开始发挥更大作用)。

这是一种非常简单的命令式语言的ADT,可以激发您的胃口:

data Statement
    = Assign String Expr
    | Print Expr
    | If Expr Statement Statement
    | Block [Statement]

data Expr
    = Variable String
    | Add Expr Expr
    | Multiply Expr Expr
    | Constant Integer

制作语言的常用方法是定义与您的语言功能相对应的这种类型,并围绕该类型组织大部分工作。您使用parser从真实源代码获取该表示形式。

作为Haskell的简介和使用标准工具对编程语言的简单实现,我都听说过关于Write Yourself A Scheme in 48 Hours的美好事情。

除此之外,Implementing Functional Languages: A Tutorial(由GHC的主要负责人Simon Peyton Jones和David Lester撰写)深入探讨了有关实现特定于Haskell的语言的更多细节。它是从1992年开始的,并且语言已经发展了很多,并且从那时起发现了新技术,但是本书仍然应该提供很多指导。

祝你好运!

答案 2 :(得分:0)

使用Haskells模块系统和newtype构造函数的组合,定义一个newtype,它包装图形但不从模块导出其构造函数。除了提供构造函数以外,还提供用于构造并使用可强制执行所需不变式的类图结构的方法。看起来像这样:

module SpecialGraph 
  ( SpecialGraph --not e.g. SpecialGraph(..)
  , specialGraph) where

import Graph

newtype SpecialGraph = Sg Graph 

specialGraph :: Graph -> Maybe SpecialGraph
specialGraph gr = ...

新类型所基于的基础Graph库可能是在Hackage中找到的几个库之一。我已经使用过fgl,“功能图库”,并且喜欢它。

在编译器中,您将导入此模块并通过其提供的功能使用SpecialGraph

这是解决没有简单的仅ADT表示的问题的标准方法。这里的总体思想是,我们在术语级别(正常的haskell表达式)限制了更通用的数据结构。 fgl图的实现方式类似,它们是对不同种类Maps的限制和实用程序,而这些npm run build又(我认为)是基于对基础树的限制和实用程序。