morazanm / fsm

A DSL for the Automata Theory Classroom
14 stars 6 forks source link

(graph->bitmap ...) returns horizontal array of rules, rather than vertical #72

Closed oliwial23 closed 1 year ago

oliwial23 commented 1 year ago

Describe the bug

A long list of rules in a pda graph is displayed horizontally, rather than in vertical array. This occurs specifically when using the function (graph->bitmap ...).

Steps to Reproduce

1) Use #lang fsm 2) Copy the following code, that converts a sample pda to a bitmap:

;; -> image
;; Purpose: Creates a .png file from a .dot file, and returns a bitmap for a sample pda        
(define (computation-diagram-pda)
  (define fname "fsm")
  ;; image
  ;; Purpose: Stores a computation graph image 
  (define cgraph (create-graph 'cgraph #:atb (hash 'rankdir "LR" 'label (format "word = ~a" '(a b c d d)))))
  (begin
    (set! cgraph (add-node cgraph 'S #:atb (hash 'color "black" 'shape "circle" 'fontcolor "black")))
    (set! cgraph (add-node cgraph 'X #:atb (hash 'color "black" 'shape "circle" 'fontcolor "black")))
    (set! cgraph (add-node cgraph 'Y #:atb (hash 'color "black" 'shape "circle" 'fontcolor "black")))
    (set! cgraph (add-node cgraph 'Z #:atb (hash 'color "black" 'shape "doublecircle" 'fontcolor "black")))
    (set! cgraph (add-node cgraph `'ds` #:atb (hash 'color "crimson" 'shape "circle" 'fontcolor "black")))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'S 'X))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'X 'Y))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'Y 'Z))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'S 'ds))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'X 'ds))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'Y 'ds))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'Z 'ds))
    (set! cgraph (add-edge cgraph "[a ε (c d)]" 'S 'S))
    (set! cgraph (add-edge cgraph "[b ε (c d)]" 'X 'X))
    (set! cgraph (add-edge cgraph "[c (c d) ε]" 'Y 'Y))
    (set! cgraph (add-edge cgraph "[d (c d) ε]" 'Z 'Z))
    (set! cgraph (add-edge cgraph "[b ε ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[ε (c) ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[ε (d) ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[a ε ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[c ε ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[d ε ε]" 'ds 'ds))
    (let [(res (graph->bitmap cgraph (current-directory) fname))]
      (begin
        (delete-file (string-append fname ".dot"))
        (delete-file (string-append fname ".png"))
        res))))

3) Run

(computation-diagram-pda)

4) See error

Expected Behavior

The list of rules of the dead state should be arranged vertically, rather than horizontally.

OS Observed On

The operating system the bug was found on: macOS Ventura 13.1

Screenshots

Bildschirm­foto 2023-06-06 um 23 39 57
jschappel commented 1 year ago

Hi @oliwial23 :wave:. This is not a bug but is the default behavior. If you wish to add custom formatting for the rules then you need to add a formatter to the graph.

I realize there is very little documentation for this so I will work on adding a scribble file this weekend explaining the whole library for you. In the meantime the way a formatter works is that you subscribe a to-string function for a graph attribute and then that function is called when we compile the dot file. Since in the dot language graphs, nodes, and edges can share the same attributes a formatter has 3 levels that the implementer can subscribe to-string functions to.

Below is an example for a custom formatter with an edge level to-string function added to the label attribute:

#lang fsm
(require "lib.rkt")

;; one-rule-per-line :: listof(string) -> string 
;; creates a string where each value in the list is on a new line
(define (one-rule-per-line rules)
  (string-join rules "\n"))

(define graph-formatters (formatters
                          (hash) ; graph level formatters
                          (hash) ; node level formatters
                          (hash 'label one-rule-per-line))) ; edge level formatters

;; -> image
;; Purpose: Creates a .png file from a .dot file, and returns a bitmap for a sample pda
(define (computation-diagram-pda)
  (define fname "fsm")
  ;; image
  ;; Purpose: Stores a computation graph image
  (define cgraph (create-graph
                  'cgraph
                  #:atb (hash 'rankdir "LR" 'label (format "word = ~a" '(a b c d d)))
                  #:fmtrs graph-formatters)) ; we add the formatters when we create the graph
  (begin
    (set! cgraph (add-node cgraph 'S #:atb (hash 'color "black" 'shape "circle" 'fontcolor "black")))
    (set! cgraph (add-node cgraph 'X #:atb (hash 'color "black" 'shape "circle" 'fontcolor "black")))
    (set! cgraph (add-node cgraph 'Y #:atb (hash 'color "black" 'shape "circle" 'fontcolor "black")))
    (set! cgraph (add-node cgraph 'Z #:atb (hash 'color "black" 'shape "doublecircle" 'fontcolor "black")))
    (set! cgraph (add-node cgraph 'ds #:atb (hash 'color "crimson" 'shape "circle" 'fontcolor "black")))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'S 'X))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'X 'Y))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'Y 'Z))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'S 'ds))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'X 'ds))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'Y 'ds))
    (set! cgraph (add-edge cgraph "[ε ε ε]" 'Z 'ds))
    (set! cgraph (add-edge cgraph "[a ε (c d)]" 'S 'S))
    (set! cgraph (add-edge cgraph "[b ε (c d)]" 'X 'X))
    (set! cgraph (add-edge cgraph "[c (c d) ε]" 'Y 'Y))
    (set! cgraph (add-edge cgraph "[d (c d) ε]" 'Z 'Z))
    (set! cgraph (add-edge cgraph "[b ε ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[ε (c) ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[ε (d) ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[a ε ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[c ε ε]" 'ds 'ds))
    (set! cgraph (add-edge cgraph "[d ε ε]" 'ds 'ds))
    (let [(res (graph->bitmap cgraph (current-directory) fname))]
      (begin
        (delete-file (string-append fname ".dot"))
        (delete-file (string-append fname ".png"))
        res))))

(computation-diagram-pda)

and this is the output (which i think is what you are looking for)

tmp