Zora 1.1.17 → 1.1.18
raw patch · 3 files changed
+57/−69 lines, 3 files
Files
- Zora.cabal +1/−1
- Zora/Graphing/DAGGraphing.hs +33/−59
- Zora/Math.hs +23/−9
Zora.cabal view
@@ -1,5 +1,5 @@ Name: Zora-Version: 1.1.17+Version: 1.1.18 Synopsis: Graphing library wrapper + assorted useful functions Description: A library of assorted useful functions for working with lists, doing mathematical operations and graphing custom data types. Category: Unclassified
Zora/Graphing/DAGGraphing.hs view
@@ -18,7 +18,9 @@ module Zora.Graphing.DAGGraphing ( DAGGraphable-, graph+, render+, to_dotfile+, render_dotfile , expand ) where @@ -47,14 +49,13 @@ type Label = Int -- | A typeclass for tree-like algebraic data types that are able to be graphed.------ For these descriptions, assume the following example data type:--- --- > data Tree a = Empty | Leaf a | Node a (Tree a) (Tree a)--- class DAGGraphable g where- -- | Expands a node into its show_node and children. For example,- -- + -- | Expands a node into its show_node and children. For example, with the following example data type+ --+ -- > data Tree a = Empty | Leaf a | Node a (Tree a) (Tree a)+ --+ -- , you might have the following definition:+ -- -- > expand (Empty) = Nothing -- > expand (Leaf x) = Just (Just $ show x, []) -- > expand (Node x l r) = Just (Just $ show x, [("L child", l), ("R child", r)])@@ -67,9 +68,9 @@ is_empty :: (DAGGraphable g) => g -> Bool is_empty = isNothing . expand --- | Gets the show_node contained in a node. For example,+-- | Gets the contents of a node as a string, if it exists. For example, -- --- > show_node (Empty) = error "Empty nodes don't contain show_nodes."+-- > show_node (Empty) = error "Empty nodes don't contain values." -- > show_node (Leaf x) = Just x -- > show_node (Node x _ _) = -- > if x == 0@@ -77,7 +78,7 @@ -- > else Just x show_node :: (DAGGraphable g) => g -> Maybe String show_node node = if is_empty node- then error "DAGGraphable implementation error. We shouldn't be calling this function for an empty node."+ then error "Zora implementation error. We shouldn't be calling this function for an empty node." else fst . fromJust . expand $ node -- | Gets the children of the current node together with edge label information. For example,@@ -88,16 +89,10 @@ get_children :: (DAGGraphable g) => g -> [(Maybe String, g)] get_children node = if is_empty node- then error "DAGGraphable implementation error. We shouldn't be calling this function for an empty node."+ then error "Zora implementation error. We shouldn't be calling this function for an empty node." else snd . fromJust . expand $ node -zoldMap :: (Monoid m, DAGGraphable g) => (g -> m) -> g -> m-zoldMap f node =- if is_empty node- then mempty- else (f node) `mappend` (mconcat . map (zoldMap f) . map snd . get_children $ node)---- | Returns a @String@ to be put into a .dot file for the given @DAGGraphable@ type. You shouldn't need to override this implementation.+-- | Not exposed. Returns a @String@ to be put into a .dot file for the given @DAGGraphable@ type. You shouldn't need to override this implementation. as_graph :: forall g. (Eq g, Show g, DAGGraphable g) => g -> ([LNode Ly.Text], [LEdge Ly.Text]) as_graph g = (nodes, edges) where@@ -116,6 +111,12 @@ . L.nub . zoldMap (\a -> [a]) $ g+ where+ zoldMap :: (Monoid m, DAGGraphable g) => (g -> m) -> g -> m+ zoldMap f node =+ if is_empty node+ then mempty+ else (f node) `mappend` (mconcat . map (zoldMap f) . map snd . get_children $ node) edges :: [LEdge Ly.Text] edges = concatMap edgeify nodes_in_g@@ -141,9 +142,9 @@ $ zip nodes_in_g [0..] -- TODO: Multiple trees (e.g. binomial heaps / random access lists)--- | Returns a @String@ to be put into a @.dot@ file for the given @DAGGraphable@ type. You won't need to override this implementation.-as_dotfile :: forall g. (Eq g, Show g, DAGGraphable g) => g -> String-as_dotfile+-- | Returns a @String@ to be put into a <http://en.wikipedia.org/wiki/DOT_(graph_description_language) DOT> file for the given @DAGGraphable@ type.+to_dotfile :: forall g. (Eq g, Show g, DAGGraphable g) => g -> String+to_dotfile = Ly.unpack . printDotGraph . graphToDot params@@ -169,56 +170,29 @@ , Width 0.1 , Height 0.1 ] ] --- | Graphs the given @DAGGraphable@ data type. Output is written to a file named \"graph-i.dot\", where /i/ is the successor of the highest /i/-show_node of all existing \"graph-i.dot\" files in the current directory.You won't need to override this implementation.-graph :: (Eq g, Show g, DAGGraphable g) => g -> IO String-graph g = do- outfile_name <- calc_outfile_name+-- | Graphs the given string as if it were the contents of a <http://en.wikipedia.org/wiki/DOT_(graph_description_language) DOT> file. Output is written to the specified file. The first parameter is the outfile name, and the second is the contents of the dotfile.+render_dotfile :: String -> String -> IO String+render_dotfile outfile_name dotfile = do write_dot_file run_dot_cmd remove_dot_file return ("Graphed data structure to " ++ outfile_name) where- calc_outfile_name :: IO String- calc_outfile_name = do- index <- calc_index_of_graph_file- return $ "graph-" ++ index ++ ".png"- where- calc_index_of_graph_file :: IO String- calc_index_of_graph_file = do- existing_graph_files_in_dir <- calc_existing_graph_files_in_dir- return- . show- . (+) 1- . (\s -> read s :: Integer)- . takeWhile ((/=) '.')- . drop 6 -- length "graph-"- . last- . L.sort- . ((:) "graph--1")- $ existing_graph_files_in_dir- - calc_existing_graph_files_in_dir :: IO [String]- calc_existing_graph_files_in_dir = do- directory_contents <- (getDirectoryContents "." :: IO [String])- return . filter is_graph_file $ directory_contents- where- is_graph_file :: String -> Bool- is_graph_file = starts_with "graph-"-- starts_with :: String -> String -> Bool- starts_with prefix str = take (length prefix) str == prefix- run_dot_cmd :: IO () run_dot_cmd = do- outfile_name <- calc_outfile_name shelly $ do cmd "dot" "-Tpng" "graph.dot" (Tx.pack $ "-o" ++ outfile_name) write_dot_file :: IO ()- write_dot_file = do writeFile "graph.dot" $ as_dotfile g+ write_dot_file = do writeFile "graph.dot" $ dotfile remove_dot_file :: IO () remove_dot_file = removeFile "graph.dot" `catch` handleExists where handleExists e = if isDoesNotExistError e then return ()- else throwIO e+ else throwIO e ++-- | Graphs the given @DAGGraphable@ data type to a PDF file. Output is written to the specified file. This is a convenience function that is the composition of @render_dotfile@ and @to_dotfile@.+render :: (Eq g, Show g, DAGGraphable g) => String -> g -> IO String+render outfile_name = render_dotfile outfile_name . to_dotfile+
Zora/Math.hs view
@@ -316,8 +316,10 @@ -- | /O(log_2 e)/ Raises base /b/ (2nd param) to exponent /e/ (3rd param) mod /m/ (1st param). E.g.: --+-- -- > pow_mod 13 2 4--- 3 +--+-- > 3 pow_mod :: Integer -> Integer -> Integer -> Integer pow_mod m b e = pow b e (mul_mod m) (square_mod m) where@@ -326,30 +328,38 @@ -- | Multiplies the second parameter by the third, mod the first. E.g.: --+-- -- > mul_mod 5 2 4--- 3+--+-- > 3 mul_mod :: Integer -> Integer -> Integer -> Integer mul_mod m a b = (a * b) `mod` m -- | Adds the second parameter by the third, mod the first. E.g.: --+-- -- > add_mod 5 3 4--- 2+--+-- > 2 add_mod :: Integer -> Integer -> Integer -> Integer add_mod m a b = (a + b) `mod` m -- | Subtracts the third parameter from the second, mod the first. E.g.: --+-- -- > sub_mod 5 16 7--- 4+--+-- > 4 sub_mod :: Integer -> Integer -> Integer -> Integer sub_mod m a b = (a - b) `mod` m -- | Divides the second parameter by the third, mod the first. More explicitly, it multiplies the second by the multiplicative inverse of the third, mod the first. E.g.: --+-- -- > div_mod 5 16 7--- Just 3 --+-- > Just 3+-- -- Note that only elements coprime to the modulus will have inverses; in cases that do not match this criterion, we return Nothing. div_mod :: Integer -> Integer -> Integer -> Maybe Integer div_mod m a b =@@ -364,11 +374,13 @@ div_mod_prime :: Integer -> Integer -> Integer -> Integer div_mod_prime m a b = fromJust (div_mod m a b) --- | /O(log m) Computes the multiplicative inverse of the second parameter, in the group /Z_m/, where /m/ is the first parameter. E.g.:+-- | /O(log m)/ Computes the multiplicative inverse of the second parameter, in the group /Z_m/, where /m/ is the first parameter. E.g.: --+-- -- > multiplicative_inverse 13 6--- Just 11 --+-- > Just 11+-- -- That is, 6 * 11 = 66, and 66 `mod` 13 == 1 . Note that only elements coprime to the modulus will have inverses; in cases that do not match this criterion, we return Nothing. multiplicative_inverse :: Integer -> Integer -> Maybe Integer@@ -420,10 +432,12 @@ type RowAndRHS = ([Double], Double) type LinearSystem = [RowAndRHS]--- | Solves a given system of linear equations. Can be subject to rounding errors for large numbers in the input. Here's an example:+-- | Solves a given system of linear equations. Can be subject to rounding errors. Here's an example: --+-- -- > solve_linear_system [[2, 3, 4],[6, -3, 9],[2, 0, 1]] [20, -6, 8]--- [4.999999999999999,6.0,-2.0]+--+-- > [4.999999999999999,6.0,-2.0] solve_linear_system :: [[Double]] -> [Double] -> [Double] solve_linear_system a b = map (\n -> if n == 0 then 0 else n)