Editing / updating charts in Haskell

I am using Data.Graph Graph to simulate a simulation in Haskell. Modeling is limited to the two-dimensional grid that my graph models. A node at each point in the grid below will contain the Maybe Molecule type, so there may be a molecule or just Nothing.

1 - 2 - 3 | | | 4 - 5 - 6 | | | 7 - 8 - 9 

I have established this view, but when it comes to updating the position of the molecule, I feel that I am moving along this path. What I have done so far splits all nodes into a list of nodes. I wrote a function to replace two elements in this list of nodes. But now, when I come to pin everything together, I get into problems because to create a new graph I need a list of vertices, which I get easily from the Graph function. But I also need to zip this up with a list of vertices that the edge touches. Unfortunately, the Data.Graph edge function. The Graph function returns a list of tuples of type Edge, which does not immediately help in creating the graph, as far as I can see, although I could write a function to get the tops of the list that have edges to the top. It seems to me that there is enough work for this to doubt that I do not understand if there is a Graph function there that simply takes a graph and returns a graph with the updated node?

+7
source share
2 answers

FGL has this excellent “contextual” mechanism, which allows you to map a pattern to a graph request. You can imagine this as pulling the selected vertex so that it is away from the rest of the graph. This allows you to see how this vertex is related to the rest of the graph.

 {-# LANGUAGE TupleSections #-} import Control.Applicative import Control.Arrow import Data.Graph.Inductive -- Example graph from SO question. graph :: Gr (Maybe Int) () graph = mkGraph (map (id&&&Just) [1,2,3,4,5,6,7,8,9]) (map (\(x,y) -> (x,y,())) $ concatMap gridNeighbors [1..9]) where gridNeighbors n = map (n,) . filter ((&&) <$> valid <*> not . boundary n) $ [n-3,n-1,n+1,n+3] valid x = x > 0 && x < 10 boundary nx = case n `rem` 3 of 0 -> x == n + 1 1 -> x == n - 1 _ -> False -- Swap the labels of nodes 4 and 7 swapTest g = case match 4 g of (Just c4, g') -> case match 7 g' of (Just c7, g'') -> setLabel c4 (lab' c7) & (setLabel c7 (lab' c4) & g'') _ -> error "No node 7!" _ -> error "No node 4!" where setLabel :: Context ab -> a -> Context ab setLabel (inEdges, n, _, outEdges) l = (inEdges, n, l, outEdges) 

You can try running the swapTest graph to see that the labels for nodes 4 and 7 in your diagram are reversed.

+7
source

Is there a specific reason you use graphics? It seems to me that the many edges are largely fixed and that your nets only change in the positions of the molecules.

Why don't you just use arrays or some other data structure that allows you to focus on molecules and their positions? For example:

 import Data.Array data Molecule = H2O | CO2 | NH3 type Grid = Array (Int, Int) (Maybe Molecule) -- creates an empty grid grid :: Int -> Int -> Grid grid mn = array ((0, 0), (m - 1, n - 1)) assocs where assocs = [((i, j), Nothing) | i <- [0 .. m - 1], j <- [0 .. n - 1]] -- swap the molecules at the specified indices swap :: (Int, Int) -> (Int, Int) -> Grid -> Grid swap (i, j) (u, v) grid = grid // [((i, j), grid ! (u, v)), ((u, v), grid ! (i, j))] -- etc. 

(If you have good reason to use graphs, I'm certainly completely out of order, in which case I apologize ...)

+4
source

All Articles