{- |
Module : Data.Graph.Analysis
Description : A Graph-Theoretic Analysis Library.
Copyright : (c) Ivan Lazar Miljenovic 2008
License : 2-Clause BSD
Maintainer : Ivan.Miljenovic@gmail.com
This is the root module of the /Graphalyze/ library, which aims to
provide a way of analysing the relationships inherent in discrete
data as a graph.
This was written as part of my mathematics honours thesis,
/Graph-Theoretic Analysis of the Relationships in Discrete Data/.
-}moduleData.Graph.Analysis(version,-- * Re-exporting other modulesmoduleData.Graph.Analysis.Types,moduleData.Graph.Analysis.Utils,moduleData.Graph.Analysis.Algorithms,moduleData.Graph.Analysis.Reporting,moduleData.Graph.Inductive.Graph,-- * Importing dataImportParams(..),defaultParams,importData,-- * Result analysis-- $analfunctslengthAnalysis,classifyRoots)whereimportData.Graph.Analysis.UtilsimportData.Graph.Analysis.TypesimportData.Graph.Analysis.AlgorithmsimportData.Graph.Analysis.ReportingimportData.Graph.Inductive.GraphimportData.ListimportData.MaybeimportqualifiedData.MapasM-- ------------------------------------------------------------------------------- | The library version.version::Stringversion="0.2"{- |
This represents the information that's being passed in that we want
to analyse. If the graph is undirected, it is better to list each
edge once rather than both directions.
-}dataImportParamsa=Params{-- | The discrete points.dataPoints::[a],-- | The relationships between the points.relationships::[(a,a)],-- | The expected roots of the graph.-- If @'directed' = 'False'@, then this is ignored.roots::[a],-- | 'False' if relationships are symmetric-- (i.e. an undirected graph).directed::Bool}-- | Default values for 'ImportParams', with no roots and a directed graph.defaultParams::ImportParamsadefaultParams=Params{dataPoints=[],relationships=[],roots=[],directed=True}{- |
Import data into a format suitable for analysis. This function is
/edge-safe/: if any datums are listed in the edges of
'ImportParams' that aren't listed in the data points, then those
edges are ignored. Thus, no sanitation of the 'relationships' in
@ImportParams@ is necessary.
-}importData::(Orda)=>ImportParamsa->GraphDataaimportDataparams=GraphData{graph=dGraph,wantedRoots=rootNodes}where-- Adding Node values to each of the data points.lNodes=zip[1..](dataPointsparams)-- Creating a lookup map from the label to the @Node@ value.nodeMap=M.fromList$map(uncurry(flip(,)))lNodes-- Find the Node value for the given data point.findNoden=M.lookupnnodeMap-- Validate a edge after looking its values up.validEdge(v1,v2)=case(findNodev1,findNodev2)of(Justx,Justy)->Just$addLabel(x,y)_->Nothing-- Add an empty edge label.addLabel(x,y)=(x,y,())-- The valid edges in the graph.graphEdges=catMaybes$mapvalidEdge(relationshipsparams)-- Validate an edgevalidNodel=case(findNodel)of(Justn)->Just(n,l)_->Nothing-- Construct the root nodesrootNodes=if(directedparams)thencatMaybes$mapvalidNode(rootsparams)else[]-- Make the graph undirected if necessary.setDirection=if(directedparams)thenidelseundir-- Construct the graph.dGraph=setDirection$mkGraphlNodesgraphEdges-- -----------------------------------------------------------------------------{- $analfuncts
Extra functions for data analysis.
-}-- | Returns the mean and standard deviations of the lengths of the sublists,-- as well all those lists more than one standard deviation longer than-- the mean.lengthAnalysis::[[a]]->(Int,Int,[(Int,[a])])lengthAnalysisas=(av,stdDev,as'')whereas'=addLengthsasls=mapfstas'(av,stdDev)=statistics'lsas''=filter(\(l,_)->l>(av+stdDev))as'{- |
Compare the actual roots in the graph with those that are expected
(i.e. those in 'wantedRoots'). Returns (in order):
* Those roots that are expected (i.e. elements of 'wantedRoots'
that are roots).
* Those roots that are expected but not present (i.e. elements of
'wantedRoots' that /aren't/ roots.
* Unexpected roots (i.e. those roots that aren't present in
'wantedRoots').
-}classifyRoots::(Eqa)=>GraphDataa->([LNodea],[LNodea],[LNodea])classifyRootsgd=(areWanted,notRoots,notWanted)whereg=graphgdwntd=wantedRootsgdrts=rootsOfgareWanted=intersectwntdrtsnotRoots=wntd\\rtsnotWanted=rts\\wntd