• F#实现图及其部分操作


    这是在工作之余弄了些这个,做的也不太好,留个纪念,今后要用可以做个笔记:)

    namespace FSharp.Graph
    #if INTERACTIVE
    #r "System.Xml.dll"
    #r "System.Xml.Linq"
    #endif
    open System
    open System.Xml.Linq
    open System.Xml
    type Graph() = 
        let mutable nodes = []
        let mutable edges = []
    
        member this.Nodes with get() = nodes
        member this.Edges with get() = edges
    
        member this.CreateNode(id) = 
            match this.FindNode(id) with
                | Some(n) -> None
                | None -> 
                    let node = Node(ID=id)
                    nodes <- nodes @ [ node ]
                    Some node
        member this.CreateEdgeFromNode(from:Node, ``to``:Node, id) = 
            match this.FindEdge id with
            | Some(edge) -> None
            | _ -> 
                let edge = new Edge(from,``to``,id)
                from.AddOutgoingEdge(edge)
                ``to``.AddIncomingEdge(edge)
    
                edges <- edges @ [edge]
                Some edge
    
        member this.CreateEdgeFromID(from, ``to``, id) = 
            let fromNode = this.FindNode(from)
            let toNode = this.FindNode(``to``)
            match fromNode, toNode with
                | Some(n0), Some(n1) -> this.CreateEdgeFromNode(n0, n1, id)
                | _ -> None
    
        member this.FindNode(id) = 
            (nodes:Node list) |> Seq.tryFind(fun n -> n.ID = id)
        member this.FindEdge(id) = 
            (edges:Edge list) |> Seq.tryFind(fun edge -> edge.ID = id)
    
        member this.RemoveEdge(edge:Edge) = 
            (edge.FromNode:Node).RemoveOutgoingEdge(edge)
            (edge.ToNode:Node).RemoveIncomingEdge(edge)
            edges <- edges |> List.filter (fun n -> n<>edge)
        member this.RemoveNode(node:Node) = 
            node.OutgoingEdges @ node.IncomingEdges |> List.iter this.RemoveEdge
            nodes <- nodes |> List.filter (fun n -> n<>node)  
    
        member this.CreateGraphFormDGML(path : string) =
            let doc = new System.Xml.XmlDocument()
            doc.Load(path)
            
            let directedGraphChildNodes=
                doc.ChildNodes.[1].ChildNodes
            let directedGraphChildList = seq{for i in 0..(directedGraphChildNodes.Count - 1) do yield directedGraphChildNodes.ItemOf(i)}
            let getElemOfGraph (nodeOrEdage : String) = 
                query{
                    for i in directedGraphChildList do
                    where(i.Name = nodeOrEdage)
                    select i}
                |> Seq.map(fun x -> 
                    x.ChildNodes )                     
    
                |> Seq.map(fun x -> 
                            let nodes = seq{for i in 0..(x.Count - 1) do yield x.ItemOf(i) }
                            nodes)                        
                |> Seq.concat
                
            let nodes = getElemOfGraph "Nodes"
            let links = getElemOfGraph "Links"
            nodes        
            |> Seq.iter(fun xmlNode -> 
                                    this.CreateNode(xmlNode.Attributes.[0].Value) |> ignore )                            
            links
                |> Seq.iter(fun xmlNode ->
                                    let from = this.FindNode(xmlNode.Attributes.[0].Value).Value
                                    let ``to`` = this.FindNode(xmlNode.Attributes.[1].Value).Value
                                    let xmlElement = xmlNode :?> XmlElement
                                    let mutable id = ""
                                    if(xmlElement.GetAttribute("Label") = "") then
                                        id <- "from" + from.ID + "To" + ``to``.ID
                                    else
                                        id <- xmlElement.GetAttribute("Label")
                                               
                                    this.CreateEdgeFromNode(from,``to``,id) |> ignore
                                    )
    
    and Node() =
        let mutable incomingEdges = []
        let mutable outgoingEdges = [] 
    
        member val ID = Unchecked.defaultof<_> with get, set
        member val Data = Unchecked.defaultof<_> with get, set    
        member this.IncomingEdges with get() = incomingEdges
        member this.OutgoingEdges with get() = outgoingEdges
        
    
        member this.AddIncomingEdge(edge:Edge) = 
            if edge.ToNode = this then
                incomingEdges <- incomingEdges |> List.append [edge]
        member this.AddOutgoingEdge(edge:Edge) = 
            if edge.FromNode = this then
                outgoingEdges <- outgoingEdges |> List.append [edge]
    
        member this.RemoveIncomingEdge(edge:Edge) = 
            incomingEdges <- incomingEdges |> List.filter (fun n -> n<>edge)
        member this.RemoveOutgoingEdge(edge:Edge) = 
            outgoingEdges <- outgoingEdges |> List.filter (fun n -> n<> edge)
    
        override this.ToString() =
            sprintf "Node(%A)" this.ID
    
    and Edge() =  
        member val ID = Unchecked.defaultof<_> with get, set
        member val FromNode = Unchecked.defaultof<_> with get, set
        member val ToNode = Unchecked.defaultof<_> with get, set
    
    
        new(fromNode:Node,toNode:Node,iD) as this = 
            new Edge()        
            then
                this.FromNode <- fromNode
                this.ToNode <- toNode
                this.ID <- iD                                      

    这些都是在VS2012上实现的。

    利用方法member this.CreateGraphFormDGML(path : string),可以用DGML文件生成图,利用DGML文件我们可以手动的画出自己想要的图,能够自己定义图中各节点之间的关系,也可以利用这个函数检查自己需要实现的一些其他图的算法。

    代码中有一点需要指出的是:and 关键字。 and关键字用来连接两个或者多个相互调用的类或者函数。

    代码中的“member val ID = Unchecked.defaultof<_> with get, set” 是F#3.0(VS2012)中的新特性—— 属性构造器,新的特性方便了用户定义类的属性。当然在F#3.0之前的版本,我们可以这样实现

        let mutable _id = Unchecked.defaultof<_>
        member this.ID
            with get() =
                _id
            and set(v) =
                _id <- v

    关于Unchecked.defaultof<_>,这个也就相当于null

  • 相关阅读:
    每日一练leetcode
    sql把逗号分隔的字符串拆成临时表
    Java的图片处理工具类
    入门贴:利用jQuery插件扩展识别浏览器内核与外壳的类型和版本
    javascript中对Date类型的常用操作
    在同一个页面使用多个不同的jQuery版本,让它们并存而不冲突
    HTML5 中 audio 播放声音 迎客
    noteFirefox中使用event对象
    what is AJAX exactly?
    noteactiveX
  • 原文地址:https://www.cnblogs.com/FsharpZack/p/2759928.html
Copyright © 2020-2023  润新知