A typed interface to the Racket generic graph library.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('') and can be up to 35 characters long.


;;; Copyright 2021 Sergiu Ivanov <sivanov@colimite.fr> ;;; ;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;; you may not use this file except in compliance with the License. ;;; You may obtain a copy of the License at ;;; ;;; http://www.apache.org/licenses/LICENSE2.0 ;;; ;;; Unless required by applicable law or agreed to in writing, software ;;; distributed under the License is distributed on an "AS IS" BASIS, ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;; See the License for the specific language governing permissions and ;;; limitations under the License.
#lang typed/racket
;;; This file implements Alex Knauth's solution presented here: ;;; ;;; https://stackoverflow.com/questions/65386334/racketgenericgraphlibraryintypedracket
(module graphwrapper racket
(require (prefixin g: graph))
(provide graph? hasvertex? hasedge? vertex=? addvertex! removevertex!
renamevertex! addedge! adddirectededge! removeedge!
removedirectededge! getvertices invertices getneighbors
inneighbors getedges inedges edgeweight transpose graphcopy
graphunion!
directedgraph
graphviz)
;; Wrap the opaque graph structure coming from the generic ;; graph library. (struct graph (g))
(define gg graphg)
;; 1 Generic Graph Interface (define (hasvertex? g v)
(g:hasvertex? (gg g) v))
(define (hasedge? g u v)
(g:hasedge? (gg g) u v))
(define (vertex=? g u v)
(g:vertex=? (gg g) u v))
(define (addvertex! g v)
(g:addvertex! (gg g) v))
(define (removevertex! g v)
(g:removevertex! (gg g) v))
(define (renamevertex! g u v)
(g:renamevertex! (gg g) u v))
(define (addedge! g u v [weight 'defaultvalue])
(g:addedge! (gg g) u v weight))
(define (adddirectededge! g u v [weight 'defaultvalue])
(g:adddirectededge! (gg g) u v weight))
(define (removeedge! g u v)
(g:removeedge! (gg g) u v))
(define (removedirectededge! g u v)
(g:removedirectededge! (gg g) u v))
(define (getvertices g)
(g:getvertices (gg g)))
(define (invertices g)
(g:invertices (gg g)))
(define (getneighbors g v)
(g:getneighbors (gg g) v))
(define (inneighbors g v)
(g:inneighbors (gg g) v))
(define (getedges g)
(g:getedges (gg g)))
(define (inedges g)
(g:inedges (gg g)))
(define (edgeweight g u v #:default [default +inf.0])
(g:edgeweight (gg g) u v #:default default))
(define (transpose g)
(graph (g:transpose (gg g))))
(define (graphcopy g)
(graph (g:graphcopy (gg g))))
(define (graphunion! g other)
(g:graphunion! (gg g) (gg other)))
;; 2 Graph constructors ;; 2.2 Weighted graphs (define (directedgraph es [ws #f])
(graph (g:directedgraph es ws)))
;; 10 Graphviz (define (graphviz g #:output [output #f] #:colors [colors #f])
(g:graphviz (gg g) #:output output #:colors colors)))
(require/typed/provide 'graphwrapper
[#:opaque Graph graph?]
;; 1 Generic Graph Interface [hasvertex? (> Graph Any Boolean)]
[hasedge? (> Graph Any Any Boolean)]
[vertex=? (> Graph Any Any Boolean)]
[addvertex! (> Graph Any Void)]
[removevertex! (> Graph Any Void)]
[renamevertex! (> Graph Any Any Void)]
[addedge! (>* (Graph Any Any) (Any) Void)]
[adddirectededge! (>* (Graph Any Any) (Any) Void)]
[removeedge! (> Graph Any Any Void)]
[removedirectededge! (> Graph Any Any Void)]
[getvertices (> Graph (Listof Any))]
[invertices (> Graph (Sequenceof Any))]
[getneighbors (> Graph Any (Listof Any))]
[inneighbors (> Graph Any (Sequenceof Any))]
[getedges (> Graph (U (Listof (List Any Any)) (Listof (List Any Any Any))))]
[inedges (> Graph (Sequenceof (U (List Any Any) (List Any Any Any))))]
[edgeweight (>* (Graph Any Any) (#:default Any) Any)]
[transpose (> Graph Graph)]
[graphcopy (> Graph Graph)]
[graphunion! (> Graph Graph Void)]
;; 2 Graph constructors ;; 2.2 Weighted graphs [directedgraph (>* ((Listof (List Any Any))) ((Listof Any)) Graph)]
;; 10 Graphviz [graphviz (>* (Graph)
(#:output OutputPort
#:colors (HashTable Any Natural))
String)])
(module+ test
;; The goal of the tests is to check that all of the provided ;; functions can be invoked without errors. The tests do not check ;; whether the results make sense. (require typed/rackunit)
(testcase "1 Generic Graph Interface"
(define g (directedgraph '((a b) (b c))))
(checkfalse (hasedge? g 'a 'c))
(checktrue (hasvertex? g 'a))
(checkfalse (vertex=? g 'a 'c))
(addvertex! g 'd)
(removevertex! g 'a)
(renamevertex! g 'd 'a)
(addedge! g 'a 'c)
(addedge! g 'a 'c "a>c")
(adddirectededge! g 'a 'c)
(adddirectededge! g 'a 'c "a>c")
(removeedge! g 'a 'c)
(removedirectededge! g 'a 'c)
(checkequal? (getvertices g) '(c b a))
(checkequal? (sequence>list (invertices g)) '(c b a))
(checkequal? (getneighbors g 'b) '(c))
(checkequal? (sequence>list (inneighbors g 'b)) '(c))
(checkequal? (getedges g) '((b c)))
(checkequal? (sequence>list (inedges g)) '((b c)))
(checkequal? (edgeweight g 'a 'c) +inf.0)
(checkequal? (edgeweight g 'a 'c #:default 'none) 'none)
(checkequal? (graphviz (transpose g))
"digraph G {\n\tnode0 [label=\"c\"];\n\tnode1 [label=\"b\"];\n\tnode2 [label=\"a\"];\n\tsubgraph U {\n\t\tedge [dir=none];\n\t}\n\tsubgraph D {\n\t\tnode0 > node1;\n\t}\n}\n")
(checkequal? (graphviz (graphcopy g))
"digraph G {\n\tnode0 [label=\"c\"];\n\tnode1 [label=\"b\"];\n\tnode2 [label=\"a\"];\n\tsubgraph U {\n\t\tedge [dir=none];\n\t}\n\tsubgraph D {\n\t\tnode1 > node0;\n\t}\n}\n")
(graphunion! g (transpose g)))
(testcase "10 Graphviz"
(define g (directedgraph '((a b) (b c))))
(checkequal? (graphviz g)
"digraph G {\n\tnode0 [label=\"c\"];\n\tnode1 [label=\"b\"];\n\tnode2 [label=\"a\"];\n\tsubgraph U {\n\t\tedge [dir=none];\n\t}\n\tsubgraph D {\n\t\tnode1 > node0;\n\t\tnode2 > node1;\n\t}\n}\n")))
