hgeometry-combinatorial 0.11.0.0 → 0.12.0.0
raw patch · 60 files changed
+5051/−331 lines, 60 filesdep +arraydep +math-functionsdep +nonempty-vectordep ~deepseqdep ~lensdep ~vectorPVP ok
version bump matches the API change (PVP)
Dependencies added: array, math-functions, nonempty-vector, unordered-containers, vector-circular
Dependency ranges changed: deepseq, lens, vector
API changes (from Hackage documentation)
- Algorithms.BinarySearch: binarySearchSeq :: (a -> Bool) -> Seq a -> Maybe Int
- Algorithms.BinarySearch: binarySearchVec :: Vector v a => (a -> Bool) -> v a -> Maybe Int
- Control.CanAquire: instance forall k (s :: k) a. Data.Reflection.Reifies s (Data.Vector.Vector a) => Control.CanAquire.CanAquire (Control.CanAquire.I s a) a
- Control.CanAquire: instance forall k1 (s :: k1) k2 (a :: k2). GHC.Classes.Eq (Control.CanAquire.I s a)
- Control.CanAquire: instance forall k1 (s :: k1) k2 (a :: k2). GHC.Classes.Ord (Control.CanAquire.I s a)
- Control.CanAquire: instance forall k1 (s :: k1) k2 (a :: k2). GHC.Enum.Enum (Control.CanAquire.I s a)
- Control.CanAquire: instance forall k1 k2 (s :: k2) (a :: k1). Control.CanAquire.HasIndex (Control.CanAquire.I s a) GHC.Types.Int
- Control.CanAquire: instance forall k1 k2 (s :: k2) (a :: k1). GHC.Show.Show (Control.CanAquire.I s a)
- Data.BinaryTree.Zipper: L :: Ctx a -> a -> BinaryTree a -> Ctx a
- Data.BinaryTree.Zipper: Loc :: BinaryTree a -> Ctx a -> BinaryTreeZipper a
- Data.BinaryTree.Zipper: R :: BinaryTree a -> a -> Ctx a -> Ctx a
- Data.BinaryTree.Zipper: Top :: Ctx a
- Data.BinaryTree.Zipper: accessZ :: BinaryTreeZipper a -> Maybe a
- Data.BinaryTree.Zipper: data BinaryTreeZipper a
- Data.BinaryTree.Zipper: data Ctx a
- Data.BinaryTree.Zipper: instance Data.Foldable.Foldable Data.BinaryTree.Zipper.BinaryTreeZipper
- Data.BinaryTree.Zipper: instance Data.Foldable.Foldable Data.BinaryTree.Zipper.Ctx
- Data.BinaryTree.Zipper: instance Data.Traversable.Traversable Data.BinaryTree.Zipper.BinaryTreeZipper
- Data.BinaryTree.Zipper: instance Data.Traversable.Traversable Data.BinaryTree.Zipper.Ctx
- Data.BinaryTree.Zipper: instance GHC.Base.Functor Data.BinaryTree.Zipper.BinaryTreeZipper
- Data.BinaryTree.Zipper: instance GHC.Base.Functor Data.BinaryTree.Zipper.Ctx
- Data.BinaryTree.Zipper: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.BinaryTree.Zipper.BinaryTreeZipper a)
- Data.BinaryTree.Zipper: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.BinaryTree.Zipper.Ctx a)
- Data.BinaryTree.Zipper: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.BinaryTree.Zipper.BinaryTreeZipper a)
- Data.BinaryTree.Zipper: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.BinaryTree.Zipper.Ctx a)
- Data.BinaryTree.Zipper: instance GHC.Read.Read a => GHC.Read.Read (Data.BinaryTree.Zipper.BinaryTreeZipper a)
- Data.BinaryTree.Zipper: instance GHC.Read.Read a => GHC.Read.Read (Data.BinaryTree.Zipper.Ctx a)
- Data.BinaryTree.Zipper: instance GHC.Show.Show a => GHC.Show.Show (Data.BinaryTree.Zipper.BinaryTreeZipper a)
- Data.BinaryTree.Zipper: instance GHC.Show.Show a => GHC.Show.Show (Data.BinaryTree.Zipper.Ctx a)
- Data.BinaryTree.Zipper: left :: BinaryTreeZipper a -> Maybe (BinaryTreeZipper a)
- Data.BinaryTree.Zipper: right :: BinaryTreeZipper a -> Maybe (BinaryTreeZipper a)
- Data.BinaryTree.Zipper: splitTree :: BinaryTreeZipper a -> (BinaryTree a, BinaryTree a)
- Data.BinaryTree.Zipper: subTrees :: BinaryTree a -> [BinaryTree a]
- Data.BinaryTree.Zipper: toRoot :: BinaryTreeZipper a -> BinaryTreeZipper a
- Data.BinaryTree.Zipper: top :: BinaryTree a -> BinaryTreeZipper a
- Data.BinaryTree.Zipper: up :: BinaryTreeZipper a -> Maybe (BinaryTreeZipper a)
- Data.BinaryTree.Zipper: visitAll :: BinaryTree a -> [BinaryTreeZipper a]
- Data.OrdSeq: Elem :: a -> Elem a
- Data.OrdSeq: Key :: !a -> Key a
- Data.OrdSeq: NoKey :: Key a
- Data.OrdSeq: OrdSeq :: FingerTree (Key a) (Elem a) -> OrdSeq a
- Data.OrdSeq: [_asFingerTree] :: OrdSeq a -> FingerTree (Key a) (Elem a)
- Data.OrdSeq: [getElem] :: Elem a -> a
- Data.OrdSeq: [getKey] :: Key a -> !a
- Data.OrdSeq: data Key a
- Data.OrdSeq: fromAscList' :: [a] -> OrdSeq a
- Data.OrdSeq: liftCmp :: (a -> a -> Ordering) -> Key a -> Key a -> Ordering
- Data.OrdSeq: newtype Elem a
- Data.OrdSeq: newtype OrdSeq a
- Data.RealNumber.Rational: instance Data.Fixed.HasResolution p => GHC.Show.Show (Data.RealNumber.Rational.AsFixed p)
- Data.RealNumber.Rational: instance GHC.Classes.Eq (Data.RealNumber.Rational.AsFixed p)
- Data.UnBounded: _MaxInfinity :: forall a_a1250. Prism' (UnBounded a_a1250) ()
- Data.UnBounded: _MinInfinity :: forall a_a1250. Prism' (UnBounded a_a1250) ()
- Data.UnBounded: unUnBounded :: forall a_a1250 a_a13EP. Traversal (UnBounded a_a1250) (UnBounded a_a13EP) a_a1250 a_a13EP
+ Algorithms.BinarySearch: binarySearchIdxIn :: BinarySearch v => (Elem v -> Bool) -> v -> Maybe (Index v)
+ Algorithms.BinarySearch: binarySearchIn :: BinarySearch v => (Elem v -> Bool) -> v -> Maybe (Elem v)
+ Algorithms.BinarySearch: class BinarySearch v where {
+ Algorithms.BinarySearch: instance Algorithms.BinarySearch.BinarySearch (Data.Sequence.Internal.Seq a)
+ Algorithms.BinarySearch: instance Algorithms.BinarySearch.BinarySearch (Data.Set.Internal.Set a)
+ Algorithms.BinarySearch: instance Data.Vector.Generic.Base.Vector v a => Algorithms.BinarySearch.BinarySearch (v a)
+ Algorithms.BinarySearch: type family Elem v :: *;
+ Algorithms.BinarySearch: }
+ Algorithms.FloydWarshall: floydWarshall :: (Unbox a, Fractional a, Ord a) => Int -> MVector s (a, Int) -> ST s ()
+ Algorithms.FloydWarshall: mkGraph :: (Unbox a, Num a) => Int -> a -> [(Int, Int, a)] -> ST s (MVector s (a, Int))
+ Algorithms.FloydWarshall: mkIndex :: Num a => a -> (a, a) -> a
+ Algorithms.Graph.DFS: dfsFilterCycles :: Tree (VertexId s w) -> Tree (VertexId s w)
+ Algorithms.Graph.DFS: dfsSensitive :: forall s w. (VertexId s w -> [VertexId s w]) -> VertexId s w -> Tree (VertexId s w)
+ Control.CanAquire: instance Data.Reflection.Reifies s (Data.Vector.Vector a) => Control.CanAquire.CanAquire (Control.CanAquire.I s a) a
+ Control.CanAquire: instance forall k s (a :: k). Control.CanAquire.HasIndex (Control.CanAquire.I s a) GHC.Types.Int
+ Control.CanAquire: instance forall k s (a :: k). GHC.Show.Show (Control.CanAquire.I s a)
+ Control.CanAquire: instance forall s k (a :: k). GHC.Classes.Eq (Control.CanAquire.I s a)
+ Control.CanAquire: instance forall s k (a :: k). GHC.Classes.Ord (Control.CanAquire.I s a)
+ Control.CanAquire: instance forall s k (a :: k). GHC.Enum.Enum (Control.CanAquire.I s a)
+ Data.CircularSeq: instance GHC.Read.Read a => GHC.Read.Read (Data.CircularSeq.CSeq a)
+ Data.CircularSeq: withIndices :: CSeq a -> CSeq (Int :+ a)
+ Data.Double.Approximate: DoubleRelAbs :: Double -> DoubleRelAbs (abs :: Nat) (rel :: Nat)
+ Data.Double.Approximate: instance (GHC.TypeNats.KnownNat abs, GHC.TypeNats.KnownNat rel) => GHC.Classes.Eq (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance (GHC.TypeNats.KnownNat abs, GHC.TypeNats.KnownNat rel) => GHC.Classes.Ord (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance (GHC.TypeNats.KnownNat abs, GHC.TypeNats.KnownNat rel) => GHC.Float.RealFloat (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance (GHC.TypeNats.KnownNat abs, GHC.TypeNats.KnownNat rel) => GHC.Real.Real (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance (GHC.TypeNats.KnownNat abs, GHC.TypeNats.KnownNat rel) => GHC.Real.RealFrac (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance Control.DeepSeq.NFData (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance GHC.Enum.Enum (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance GHC.Float.Floating (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance GHC.Num.Num (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance GHC.Read.Read (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance GHC.Real.Fractional (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance GHC.Show.Show (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: instance System.Random.Random (Data.Double.Approximate.DoubleRelAbs abs rel)
+ Data.Double.Approximate: newtype DoubleRelAbs (abs :: Nat) (rel :: Nat)
+ Data.Double.Approximate: type SafeDouble = DoubleRelAbs 10 10
+ Data.Double.Shaman: data SDouble (n :: Nat)
+ Data.Double.Shaman: data Shaman
+ Data.Double.Shaman: instance GHC.Classes.Eq Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.Classes.Ord Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.Float.Floating (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: instance GHC.Float.Floating Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.Float.RealFloat Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.Num.Num (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: instance GHC.Num.Num Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.Read.Read (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: instance GHC.Read.Read Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.Real.Fractional (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: instance GHC.Real.Fractional Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.Real.Real Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.Real.RealFrac Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.Show.Show (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: instance GHC.Show.Show Data.Double.Shaman.Shaman
+ Data.Double.Shaman: instance GHC.TypeNats.KnownNat n => GHC.Classes.Eq (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: instance GHC.TypeNats.KnownNat n => GHC.Classes.Ord (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: instance GHC.TypeNats.KnownNat n => GHC.Float.RealFloat (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: instance GHC.TypeNats.KnownNat n => GHC.Real.Real (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: instance GHC.TypeNats.KnownNat n => GHC.Real.RealFrac (Data.Double.Shaman.SDouble n)
+ Data.Double.Shaman: significativeBits :: Shaman -> Double
+ Data.Double.Shaman: significativeDigits :: Shaman -> Double
+ Data.Ext.Multi: class HasCore extras
+ Data.Ext.Multi: class HasExtras extras extras'
+ Data.Ext.Multi: core :: HasCore extras => Lens (core :+ extras) (core' :+ extras) core core'
+ Data.Ext.Multi: data family core :+ (extras :: [*]) :: *
+ Data.Ext.Multi: ext :: c -> c :+ '[]
+ Data.Ext.Multi: extra :: HasExtras extras extras' => Lens (core :+ extras) (core :+ extras') (HList extras) (HList extras')
+ Data.Ext.Multi: infixr 1 :+
+ Data.Ext.Multi: instance Control.DeepSeq.NFData core => Control.DeepSeq.NFData (core Data.Ext.Multi.:+ '[])
+ Data.Ext.Multi: instance Data.Ext.Multi.HasCore '[]
+ Data.Ext.Multi: instance Data.Ext.Multi.HasCore (t : ts)
+ Data.Ext.Multi: instance Data.Ext.Multi.HasExtras '[] '[]
+ Data.Ext.Multi: instance Data.Ext.Multi.HasExtras '[] (t : ts)
+ Data.Ext.Multi: instance Data.Ext.Multi.HasExtras (t : ts) '[]
+ Data.Ext.Multi: instance Data.Ext.Multi.HasExtras (t : ts) (a : as)
+ Data.Ext.Multi: instance GHC.Classes.Eq core => GHC.Classes.Eq (core Data.Ext.Multi.:+ '[])
+ Data.Ext.Multi: instance GHC.Classes.Ord core => GHC.Classes.Ord (core Data.Ext.Multi.:+ '[])
+ Data.Ext.Multi: instance GHC.Generics.Generic (core Data.Ext.Multi.:+ '[])
+ Data.Ext.Multi: instance GHC.Show.Show core => GHC.Show.Show (core Data.Ext.Multi.:+ '[])
+ Data.Ext.Multi: instance Test.QuickCheck.Arbitrary.Arbitrary core => Test.QuickCheck.Arbitrary.Arbitrary (core Data.Ext.Multi.:+ '[])
+ Data.Ext.Multi: pattern (:+) :: c -> HList (e : extras) -> c :+ (e : extras)
+ Data.LSeq: instance (1 GHC.TypeNats.<= n) => Data.Semigroup.Traversable.Class.Traversable1 (Data.LSeq.LSeq n)
+ Data.List.Util: groupBy' :: (a -> a -> Ordering) -> [a] -> [NonEmpty a]
+ Data.List.Util: partition3 :: Foldable f => (a -> Ordering) -> f a -> ([a], [a], [a])
+ Data.OrdSeq: data OrdSeq a
+ Data.OrdSeq: fromAscList :: [a] -> OrdSeq a
+ Data.PlanarGraph.Immutable: Boundary :: FaceId -> Face
+ Data.PlanarGraph.Immutable: Edge :: Int -> Edge
+ Data.PlanarGraph.Immutable: Face :: FaceId -> Face
+ Data.PlanarGraph.Immutable: HalfEdge :: Int -> HalfEdge
+ Data.PlanarGraph.Immutable: Vertex :: Int -> Vertex
+ Data.PlanarGraph.Immutable: [edgeId] :: Edge -> Int
+ Data.PlanarGraph.Immutable: [halfEdgeId] :: HalfEdge -> Int
+ Data.PlanarGraph.Immutable: [vertexId] :: Vertex -> Int
+ Data.PlanarGraph.Immutable: data Face
+ Data.PlanarGraph.Immutable: data PlanarGraph
+ Data.PlanarGraph.Immutable: edgeHalfEdges :: Edge -> (HalfEdge, HalfEdge)
+ Data.PlanarGraph.Immutable: faceBoundary :: Face -> PlanarGraph -> [Vertex]
+ Data.PlanarGraph.Immutable: faceHalfEdge :: Face -> PlanarGraph -> HalfEdge
+ Data.PlanarGraph.Immutable: faceHalfEdges :: Face -> PlanarGraph -> [HalfEdge]
+ Data.PlanarGraph.Immutable: faceId :: Face -> FaceId
+ Data.PlanarGraph.Immutable: faceIsBoundary :: Face -> Bool
+ Data.PlanarGraph.Immutable: faceIsInterior :: Face -> Bool
+ Data.PlanarGraph.Immutable: faceMember :: Face -> PlanarGraph -> Bool
+ Data.PlanarGraph.Immutable: halfEdgeFace :: HalfEdge -> PlanarGraph -> Face
+ Data.PlanarGraph.Immutable: halfEdgeIsBoundary :: HalfEdge -> PlanarGraph -> Bool
+ Data.PlanarGraph.Immutable: halfEdgeIsInterior :: HalfEdge -> PlanarGraph -> Bool
+ Data.PlanarGraph.Immutable: halfEdgeNext :: HalfEdge -> PlanarGraph -> HalfEdge
+ Data.PlanarGraph.Immutable: halfEdgeNextIncoming :: HalfEdge -> PlanarGraph -> HalfEdge
+ Data.PlanarGraph.Immutable: halfEdgeNextOutgoing :: HalfEdge -> PlanarGraph -> HalfEdge
+ Data.PlanarGraph.Immutable: halfEdgePrev :: HalfEdge -> PlanarGraph -> HalfEdge
+ Data.PlanarGraph.Immutable: halfEdgeTailVertex :: HalfEdge -> PlanarGraph -> Vertex
+ Data.PlanarGraph.Immutable: halfEdgeTipVertex :: HalfEdge -> PlanarGraph -> Vertex
+ Data.PlanarGraph.Immutable: halfEdgeTwin :: HalfEdge -> HalfEdge
+ Data.PlanarGraph.Immutable: halfEdgeVertex :: HalfEdge -> PlanarGraph -> Vertex
+ Data.PlanarGraph.Immutable: instance Data.Hashable.Class.Hashable Data.PlanarGraph.Immutable.Edge
+ Data.PlanarGraph.Immutable: instance Data.Hashable.Class.Hashable Data.PlanarGraph.Immutable.HalfEdge
+ Data.PlanarGraph.Immutable: instance Data.Hashable.Class.Hashable Data.PlanarGraph.Immutable.PlanarGraph
+ Data.PlanarGraph.Immutable: instance Data.Hashable.Class.Hashable Data.PlanarGraph.Immutable.Vertex
+ Data.PlanarGraph.Immutable: instance GHC.Classes.Eq Data.PlanarGraph.Immutable.Edge
+ Data.PlanarGraph.Immutable: instance GHC.Classes.Eq Data.PlanarGraph.Immutable.Face
+ Data.PlanarGraph.Immutable: instance GHC.Classes.Eq Data.PlanarGraph.Immutable.HalfEdge
+ Data.PlanarGraph.Immutable: instance GHC.Classes.Eq Data.PlanarGraph.Immutable.PlanarGraph
+ Data.PlanarGraph.Immutable: instance GHC.Classes.Eq Data.PlanarGraph.Immutable.Vertex
+ Data.PlanarGraph.Immutable: instance GHC.Read.Read Data.PlanarGraph.Immutable.Edge
+ Data.PlanarGraph.Immutable: instance GHC.Read.Read Data.PlanarGraph.Immutable.Face
+ Data.PlanarGraph.Immutable: instance GHC.Read.Read Data.PlanarGraph.Immutable.HalfEdge
+ Data.PlanarGraph.Immutable: instance GHC.Read.Read Data.PlanarGraph.Immutable.Vertex
+ Data.PlanarGraph.Immutable: instance GHC.Show.Show Data.PlanarGraph.Immutable.Edge
+ Data.PlanarGraph.Immutable: instance GHC.Show.Show Data.PlanarGraph.Immutable.Face
+ Data.PlanarGraph.Immutable: instance GHC.Show.Show Data.PlanarGraph.Immutable.HalfEdge
+ Data.PlanarGraph.Immutable: instance GHC.Show.Show Data.PlanarGraph.Immutable.Vertex
+ Data.PlanarGraph.Immutable: newtype Edge
+ Data.PlanarGraph.Immutable: newtype HalfEdge
+ Data.PlanarGraph.Immutable: newtype Vertex
+ Data.PlanarGraph.Immutable: pgBoundaries :: PlanarGraph -> [Face]
+ Data.PlanarGraph.Immutable: pgCreate :: (forall s. ST s (PlanarGraph s)) -> PlanarGraph
+ Data.PlanarGraph.Immutable: pgEdges :: PlanarGraph -> [Edge]
+ Data.PlanarGraph.Immutable: pgFaces :: PlanarGraph -> [Face]
+ Data.PlanarGraph.Immutable: pgFreeze :: PlanarGraph s -> ST s PlanarGraph
+ Data.PlanarGraph.Immutable: pgFromFaces :: [[VertexId]] -> PlanarGraph
+ Data.PlanarGraph.Immutable: pgFromFacesCV :: [CircularVector VertexId] -> PlanarGraph
+ Data.PlanarGraph.Immutable: pgHalfEdges :: PlanarGraph -> [HalfEdge]
+ Data.PlanarGraph.Immutable: pgMutate :: PlanarGraph -> (forall s. PlanarGraph s -> ST s ()) -> PlanarGraph
+ Data.PlanarGraph.Immutable: pgThaw :: PlanarGraph -> ST s (PlanarGraph s)
+ Data.PlanarGraph.Immutable: pgUnsafeFreeze :: PlanarGraph s -> ST s PlanarGraph
+ Data.PlanarGraph.Immutable: pgUnsafeThaw :: PlanarGraph -> ST s (PlanarGraph s)
+ Data.PlanarGraph.Immutable: pgVertices :: PlanarGraph -> [Vertex]
+ Data.PlanarGraph.Immutable: tutteEmbedding :: PlanarGraph -> Vector (V2 Double)
+ Data.PlanarGraph.Immutable: type FaceId = Int
+ Data.PlanarGraph.Immutable: vertexHalfEdge :: Vertex -> PlanarGraph -> HalfEdge
+ Data.PlanarGraph.Immutable: vertexIncomingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]
+ Data.PlanarGraph.Immutable: vertexIsBoundary :: Vertex -> PlanarGraph -> Bool
+ Data.PlanarGraph.Immutable: vertexIsInterior :: Vertex -> PlanarGraph -> Bool
+ Data.PlanarGraph.Immutable: vertexNeighbours :: Vertex -> PlanarGraph -> [Vertex]
+ Data.PlanarGraph.Immutable: vertexOutgoingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]
+ Data.PlanarGraph.Mutable: data Edge s
+ Data.PlanarGraph.Mutable: data Face s
+ Data.PlanarGraph.Mutable: data HalfEdge s
+ Data.PlanarGraph.Mutable: data PlanarGraph s
+ Data.PlanarGraph.Mutable: data Vertex s
+ Data.PlanarGraph.Mutable: edgeFromHalfEdge :: HalfEdge s -> Edge s
+ Data.PlanarGraph.Mutable: edgeFromId :: EdgeId -> PlanarGraph s -> Edge s
+ Data.PlanarGraph.Mutable: edgeToId :: Edge s -> EdgeId
+ Data.PlanarGraph.Mutable: faceBoundary :: Face s -> ST s (CircularVector (Vertex s))
+ Data.PlanarGraph.Mutable: faceFromId :: FaceId -> PlanarGraph s -> Face s
+ Data.PlanarGraph.Mutable: faceHalfEdge :: Face s -> ST s (HalfEdge s)
+ Data.PlanarGraph.Mutable: faceHalfEdges :: Face s -> ST s (CircularVector (HalfEdge s))
+ Data.PlanarGraph.Mutable: faceInvalid :: PlanarGraph s -> Face s
+ Data.PlanarGraph.Mutable: faceIsBoundary :: Face s -> Bool
+ Data.PlanarGraph.Mutable: faceIsInterior :: Face s -> Bool
+ Data.PlanarGraph.Mutable: faceIsInvalid :: Face s -> Bool
+ Data.PlanarGraph.Mutable: faceIsValid :: Face s -> Bool
+ Data.PlanarGraph.Mutable: faceToId :: Face s -> FaceId
+ Data.PlanarGraph.Mutable: halfEdgeFace :: HalfEdge s -> ST s (Face s)
+ Data.PlanarGraph.Mutable: halfEdgeFromId :: HalfEdgeId -> PlanarGraph s -> HalfEdge s
+ Data.PlanarGraph.Mutable: halfEdgeIsInterior :: HalfEdge s -> ST s Bool
+ Data.PlanarGraph.Mutable: halfEdgeNext :: HalfEdge s -> ST s (HalfEdge s)
+ Data.PlanarGraph.Mutable: halfEdgeNextIncoming :: HalfEdge s -> ST s (HalfEdge s)
+ Data.PlanarGraph.Mutable: halfEdgeNextOutgoing :: HalfEdge s -> ST s (HalfEdge s)
+ Data.PlanarGraph.Mutable: halfEdgePrev :: HalfEdge s -> ST s (HalfEdge s)
+ Data.PlanarGraph.Mutable: halfEdgeTailVertex :: HalfEdge s -> ST s (Vertex s)
+ Data.PlanarGraph.Mutable: halfEdgeTipVertex :: HalfEdge s -> ST s (Vertex s)
+ Data.PlanarGraph.Mutable: halfEdgeToId :: HalfEdge s -> HalfEdgeId
+ Data.PlanarGraph.Mutable: halfEdgeTwin :: HalfEdge s -> HalfEdge s
+ Data.PlanarGraph.Mutable: halfEdgeVertex :: HalfEdge s -> ST s (Vertex s)
+ Data.PlanarGraph.Mutable: instance Data.Hashable.Class.Hashable (Data.PlanarGraph.Mutable.HalfEdge s)
+ Data.PlanarGraph.Mutable: instance Data.Hashable.Class.Hashable (Data.PlanarGraph.Mutable.Vertex s)
+ Data.PlanarGraph.Mutable: instance GHC.Classes.Eq (Data.PlanarGraph.Mutable.Edge s)
+ Data.PlanarGraph.Mutable: instance GHC.Classes.Eq (Data.PlanarGraph.Mutable.Face s)
+ Data.PlanarGraph.Mutable: instance GHC.Classes.Eq (Data.PlanarGraph.Mutable.HalfEdge s)
+ Data.PlanarGraph.Mutable: instance GHC.Classes.Eq (Data.PlanarGraph.Mutable.Vertex s)
+ Data.PlanarGraph.Mutable: instance GHC.Show.Show (Data.PlanarGraph.Mutable.Face s)
+ Data.PlanarGraph.Mutable: instance GHC.Show.Show (Data.PlanarGraph.Mutable.HalfEdge s)
+ Data.PlanarGraph.Mutable: instance GHC.Show.Show (Data.PlanarGraph.Mutable.Vertex s)
+ Data.PlanarGraph.Mutable: pgClone :: PlanarGraph s -> ST s (PlanarGraph s)
+ Data.PlanarGraph.Mutable: pgConnectVertices :: HalfEdge s -> HalfEdge s -> ST s (Edge s)
+ Data.PlanarGraph.Mutable: pgFromFaces :: [[VertexId]] -> ST s (PlanarGraph s)
+ Data.PlanarGraph.Mutable: pgFromFacesCV :: [CircularVector VertexId] -> ST s (PlanarGraph s)
+ Data.PlanarGraph.Mutable: pgHash :: PlanarGraph s -> ST s Int
+ Data.PlanarGraph.Mutable: type EdgeId = Int
+ Data.PlanarGraph.Mutable: type FaceId = Int
+ Data.PlanarGraph.Mutable: type HalfEdgeId = Int
+ Data.PlanarGraph.Mutable: type VertexId = Int
+ Data.PlanarGraph.Mutable: vertexFromId :: VertexId -> PlanarGraph s -> Vertex s
+ Data.PlanarGraph.Mutable: vertexHalfEdge :: Vertex s -> ST s (HalfEdge s)
+ Data.PlanarGraph.Mutable: vertexIncomingHalfEdges :: Vertex s -> ST s (CircularVector (HalfEdge s))
+ Data.PlanarGraph.Mutable: vertexIsBoundary :: Vertex s -> ST s Bool
+ Data.PlanarGraph.Mutable: vertexNeighbours :: Vertex s -> ST s (CircularVector (Vertex s))
+ Data.PlanarGraph.Mutable: vertexOutgoingHalfEdges :: Vertex s -> ST s (CircularVector (HalfEdge s))
+ Data.PlanarGraph.Mutable: vertexToId :: Vertex s -> VertexId
+ Data.PlanarGraph.Mutable: vertexWithIncomingHalfEdges :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()
+ Data.PlanarGraph.Mutable: vertexWithOutgoingHalfEdges :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()
+ Data.PlanarGraph.Persistent: PlanarGraph :: HalfEdge -> Vertex -> Face -> HashMap HalfEdge HalfEdge -> HashMap HalfEdge Vertex -> HashMap HalfEdge Face -> HashMap Vertex HalfEdge -> HashMap Face HalfEdge -> PlanarGraph
+ Data.PlanarGraph.Persistent: [pgFace] :: PlanarGraph -> HashMap HalfEdge Face
+ Data.PlanarGraph.Persistent: [pgHalfEdgeFromFace] :: PlanarGraph -> HashMap Face HalfEdge
+ Data.PlanarGraph.Persistent: [pgHalfEdgeFromVertex] :: PlanarGraph -> HashMap Vertex HalfEdge
+ Data.PlanarGraph.Persistent: [pgNextFaceId] :: PlanarGraph -> Face
+ Data.PlanarGraph.Persistent: [pgNextHalfEdgeId] :: PlanarGraph -> HalfEdge
+ Data.PlanarGraph.Persistent: [pgNextVertexId] :: PlanarGraph -> Vertex
+ Data.PlanarGraph.Persistent: [pgNext] :: PlanarGraph -> HashMap HalfEdge HalfEdge
+ Data.PlanarGraph.Persistent: [pgVertex] :: PlanarGraph -> HashMap HalfEdge Vertex
+ Data.PlanarGraph.Persistent: data PlanarGraph
+ Data.PlanarGraph.Persistent: halfEdgeNext :: HalfEdge -> PlanarGraph -> HalfEdge
+ Data.PlanarGraph.Persistent: halfEdgeNextM :: MonadState PlanarGraph m => HalfEdge -> m HalfEdge
+ Data.PlanarGraph.Persistent: new :: Int -> PlanarGraph
+ Data.PlanarGraph.Persistent: type Face = Int
+ Data.PlanarGraph.Persistent: type HalfEdge = Int
+ Data.PlanarGraph.Persistent: type Vertex = Int
+ Data.Range: instance Data.Functor.Classes.Read1 Data.Range.EndPoint
+ Data.Range: instance Data.Functor.Classes.Read1 Data.Range.Range
+ Data.Range: instance Data.Functor.Classes.Show1 Data.Range.EndPoint
+ Data.Range: instance Data.Functor.Classes.Show1 Data.Range.Range
+ Data.Range: instance GHC.Read.Read a => GHC.Read.Read (Data.Range.Range a)
+ Data.RealNumber.Rational: data Nat
+ Data.RealNumber.Rational: instance Control.DeepSeq.NFData (Data.RealNumber.Rational.RealNumber p)
+ Data.RealNumber.Rational: instance Data.Aeson.Types.FromJSON.FromJSON (Data.RealNumber.Rational.RealNumber p)
+ Data.RealNumber.Rational: instance Data.Aeson.Types.ToJSON.ToJSON (Data.RealNumber.Rational.RealNumber p)
+ Data.RealNumber.Rational: instance System.Random.Random (Data.RealNumber.Rational.RealNumber p)
+ Data.RealNumber.Rational: instance forall k (p :: k). Data.Fixed.HasResolution p => GHC.Show.Show (Data.RealNumber.Rational.AsFixed p)
+ Data.RealNumber.Rational: instance forall k (p :: k). GHC.Classes.Eq (Data.RealNumber.Rational.AsFixed p)
+ Data.Set.Util: S :: String -> S
+ Data.Set.Util: cmpS :: S -> S -> Ordering
+ Data.Set.Util: data S
+ Data.Set.Util: instance GHC.Show.Show Data.Set.Util.S
+ Data.Set.Util: queryBy :: (a -> a -> Ordering) -> (forall b. Ord b => b -> Set b -> t b) -> a -> Set a -> t a
+ Data.Set.Util: splitBy :: (a -> Ordering) -> Set a -> (Set a, Set a, Set a)
+ Data.Set.Util: test :: Maybe S
+ Data.Vector.Circular.Util: findRotateTo :: (a -> Bool) -> CircularVector a -> Maybe (CircularVector a)
+ Data.Vector.Circular.Util: instance Data.Semigroup.Foldable.Class.Foldable1 Data.Vector.NonEmpty.Internal.NonEmptyVector
+ Data.Vector.Circular.Util: instance Test.QuickCheck.Arbitrary.Arbitrary a => Test.QuickCheck.Arbitrary.Arbitrary (Data.Vector.Circular.CircularVector a)
+ Data.Vector.Circular.Util: isShiftOf :: Eq a => CircularVector a -> CircularVector a -> Bool
+ Data.Vector.Circular.Util: item :: Int -> Lens' (CircularVector a) a
+ Data.Vector.Circular.Util: leftElements :: CircularVector a -> NonEmptyVector a
+ Data.Vector.Circular.Util: rightElements :: CircularVector a -> NonEmptyVector a
+ Data.Vector.Circular.Util: withIndicesRight :: CircularVector a -> CircularVector (Int :+ a)
- Control.CanAquire: data I s a
+ Control.CanAquire: data I (s :: *) a
- Control.CanAquire: runAcquire :: forall t a b. Traversable t => (forall i. CanAquire i a => t i -> b) -> t a -> b
+ Control.CanAquire: runAcquire :: forall t a b. Traversable t => (forall s. CanAquire (I s a) a => t (I s a) -> b) -> t a -> b
- Data.DynamicOrd: O :: a -> O
+ Data.DynamicOrd: O :: a -> O (s :: *) (a :: *)
- Data.DynamicOrd: [runO] :: O -> a
+ Data.DynamicOrd: [runO] :: O (s :: *) (a :: *) -> a
- Data.DynamicOrd: liftOrd1 :: (f (O s a) -> f (O s a)) -> f a -> O s (f a)
+ Data.DynamicOrd: liftOrd1 :: (f (O s a) -> g (O s a)) -> f a -> O s (g a)
- Data.LSeq: infixl 5 :|>
+ Data.LSeq: infixl 5 :>
- Data.LSeq: infixr 5 :<<
+ Data.LSeq: infixr 5 :<
- Data.Permutation: indexes :: forall a_aALX. Lens' (Permutation a_aALX) (Vector (Int, Int))
+ Data.Permutation: indexes :: forall a_aqCp. Lens' (Permutation a_aqCp) (Vector (Int, Int))
- Data.Permutation: orbits :: forall a_aALX a_aB23. Lens (Permutation a_aALX) (Permutation a_aB23) (Vector (Orbit a_aALX)) (Vector (Orbit a_aB23))
+ Data.Permutation: orbits :: forall a_aqCp a_aqKH. Lens (Permutation a_aqCp) (Permutation a_aqKH) (Vector (Orbit a_aqCp)) (Vector (Orbit a_aqKH))
- Data.PlanarGraph: VertexId :: Int -> VertexId s
+ Data.PlanarGraph: VertexId :: Int -> VertexId s (w :: World)
- Data.PlanarGraph: [_unVertexId] :: VertexId s -> Int
+ Data.PlanarGraph: [_unVertexId] :: VertexId s (w :: World) -> Int
- Data.PlanarGraph: arc :: forall s_aHq7 s_aHUV. Lens (Dart s_aHq7) (Dart s_aHUV) (Arc s_aHq7) (Arc s_aHUV)
+ Data.PlanarGraph: arc :: Lens' (Dart s) (Arc s)
- Data.PlanarGraph: direction :: forall s_aHq7. Lens' (Dart s_aHq7) Direction
+ Data.PlanarGraph: direction :: Lens' (Dart s) Direction
- Data.PlanarGraph.Core: PlanarGraph :: Permutation (Dart s) -> Vector v -> Vector e -> Vector f -> PlanarGraph s (DualOf w) f e v -> PlanarGraph s v e f
+ Data.PlanarGraph.Core: PlanarGraph :: Permutation (Dart s) -> Vector v -> Vector e -> Vector f -> PlanarGraph s (DualOf w) f e v -> PlanarGraph s (w :: World) v e f
- Data.PlanarGraph.Core: VertexId :: Int -> VertexId s
+ Data.PlanarGraph.Core: VertexId :: Int -> VertexId s (w :: World)
- Data.PlanarGraph.Core: [_dual] :: PlanarGraph s v e f -> PlanarGraph s (DualOf w) f e v
+ Data.PlanarGraph.Core: [_dual] :: PlanarGraph s (w :: World) v e f -> PlanarGraph s (DualOf w) f e v
- Data.PlanarGraph.Core: [_embedding] :: PlanarGraph s v e f -> Permutation (Dart s)
+ Data.PlanarGraph.Core: [_embedding] :: PlanarGraph s (w :: World) v e f -> Permutation (Dart s)
- Data.PlanarGraph.Core: [_faceData] :: PlanarGraph s v e f -> Vector f
+ Data.PlanarGraph.Core: [_faceData] :: PlanarGraph s (w :: World) v e f -> Vector f
- Data.PlanarGraph.Core: [_rawDartData] :: PlanarGraph s v e f -> Vector e
+ Data.PlanarGraph.Core: [_rawDartData] :: PlanarGraph s (w :: World) v e f -> Vector e
- Data.PlanarGraph.Core: [_unVertexId] :: VertexId s -> Int
+ Data.PlanarGraph.Core: [_unVertexId] :: VertexId s (w :: World) -> Int
- Data.PlanarGraph.Core: [_vertexData] :: PlanarGraph s v e f -> Vector v
+ Data.PlanarGraph.Core: [_vertexData] :: PlanarGraph s (w :: World) v e f -> Vector v
- Data.PlanarGraph.Dart: arc :: forall s_aHq7 s_aHUV. Lens (Dart s_aHq7) (Dart s_aHUV) (Arc s_aHq7) (Arc s_aHUV)
+ Data.PlanarGraph.Dart: arc :: Lens' (Dart s) (Arc s)
- Data.PlanarGraph.Dart: direction :: forall s_aHq7. Lens' (Dart s_aHq7) Direction
+ Data.PlanarGraph.Dart: direction :: Lens' (Dart s) Direction
- Data.Range: lower :: forall a_aTXI. Lens' (Range a_aTXI) (EndPoint a_aTXI)
+ Data.Range: lower :: Lens' (Range a) (EndPoint a)
- Data.Range: upper :: forall a_aTXI. Lens' (Range a_aTXI) (EndPoint a_aTXI)
+ Data.Range: upper :: Lens' (Range a) (EndPoint a)
- Data.RealNumber.Rational: RealNumber :: Rational -> RealNumber
+ Data.RealNumber.Rational: RealNumber :: Rational -> RealNumber (p :: Nat)
- Data.UnBounded: _Val :: forall a_a1250 a_a13Gs. Prism (UnBounded a_a13Gs) (UnBounded a_a1250) a_a13Gs a_a1250
+ Data.UnBounded: _Val :: Prism (UnBounded a) (UnBounded b) a b
Files
- cbits/erf.c +97/−0
- changelog.org +10/−0
- docs/Data/PlanarGraph/planargraph-1711135548958680232.svg +199/−0
- docs/Data/PlanarGraph/planargraph-1902492848341357096.svg +166/−0
- docs/Data/PlanarGraph/planargraph-2506803680640023584.svg +135/−0
- docs/Data/PlanarGraph/planargraph-2635031442529484236.compact.svg +193/−0
- docs/Data/PlanarGraph/planargraph-2635031442529484236.svg +403/−0
- docs/Data/PlanarGraph/planargraph-2959979592048325618.svg +108/−0
- doctests.hs +6/−1
- hgeometry-combinatorial.cabal +25/−8
- src/Algorithms/BinarySearch.hs +93/−35
- src/Algorithms/DivideAndConquer.hs +9/−1
- src/Algorithms/FloydWarshall.hs +56/−0
- src/Algorithms/Graph/DFS.hs +28/−4
- src/Algorithms/Graph/MST.hs +7/−0
- src/Control/CanAquire.hs +13/−5
- src/Control/Monad/State/Persistent.hs +11/−1
- src/Data/BinaryTree.hs +2/−1
- src/Data/BinaryTree/Zipper.hs +0/−64
- src/Data/CircularList/Util.hs +10/−3
- src/Data/CircularSeq.hs +47/−15
- src/Data/Double/Approximate.hs +83/−0
- src/Data/Double/Shaman.hs +295/−0
- src/Data/DynamicOrd.hs +17/−10
- src/Data/Ext.hs +7/−2
- src/Data/Ext/Multi.hs +62/−0
- src/Data/IndexedDoublyLinkedList.hs +11/−1
- src/Data/IndexedDoublyLinkedList/Bare.hs +12/−3
- src/Data/Intersection.hs +1/−0
- src/Data/LSeq.hs +62/−18
- src/Data/List/Alternating.hs +12/−5
- src/Data/List/Set.hs +16/−17
- src/Data/List/Util.hs +71/−4
- src/Data/List/Zipper.hs +8/−1
- src/Data/Measured.hs +7/−1
- src/Data/Measured/Class.hs +10/−0
- src/Data/Measured/Size.hs +8/−0
- src/Data/OrdSeq.hs +68/−37
- src/Data/PlanarGraph.hs +0/−2
- src/Data/PlanarGraph/AdjRep.hs +5/−4
- src/Data/PlanarGraph/Core.hs +18/−15
- src/Data/PlanarGraph/Dart.hs +10/−1
- src/Data/PlanarGraph/Dual.hs +1/−1
- src/Data/PlanarGraph/IO.hs +6/−7
- src/Data/PlanarGraph/Immutable.hs +1398/−0
- src/Data/PlanarGraph/Internal.hs +92/−0
- src/Data/PlanarGraph/Mutable.hs +690/−0
- src/Data/PlanarGraph/Persistent.hs +71/−0
- src/Data/Range.hs +67/−14
- src/Data/RealNumber/Rational.hs +43/−10
- src/Data/Sequence/Util.hs +8/−1
- src/Data/Set/Util.hs +65/−5
- src/Data/Tree/Util.hs +11/−10
- src/Data/UnBounded.hs +64/−24
- src/Data/Util.hs +2/−0
- src/Data/Vector/Circular/Util.hs +74/−0
- src/Data/Yaml/Util.hs +1/−0
- test/Algorithms/Graph/DFSSpec.hs +29/−0
- test/Data/CircularSeqSpec.hs +3/−0
- test/Data/RealNumber/RationalSpec.hs +25/−0
+ cbits/erf.c view
@@ -0,0 +1,97 @@+#include <math.h>++double erf_log(double number, double error, double result)+{+ long double precise = logl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_exp(double number, double error, double result)+{+ long double precise = expl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_pow(double n1, double e1, double n2, double e2, double result)+{+ long double precise = powl((long double)n1 + (long double)e1, (long double)n2 + (long double)e2);+ return (double) (precise - (long double)result);+}++double erf_sin(double number, double error, double result)+{+ long double precise = sinl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_cos(double number, double error, double result)+{+ long double precise = cosl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_tan(double number, double error, double result)+{+ long double precise = tanl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_asin(double number, double error, double result)+{+ long double precise = asinl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_acos(double number, double error, double result)+{+ long double precise = acosl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_atan(double number, double error, double result)+{+ long double precise = atanl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_sinh(double number, double error, double result)+{+ long double precise = sinhl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_cosh(double number, double error, double result)+{+ long double precise = coshl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_tanh(double number, double error, double result)+{+ long double precise = tanhl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_asinh(double number, double error, double result)+{+ long double precise = asinhl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_acosh(double number, double error, double result)+{+ long double precise = acoshl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_atanh(double number, double error, double result)+{+ long double precise = atanhl((long double)number + (long double)error);+ return (double) (precise - (long double)result);+}++double erf_atan2(double n1, double e1, double n2, double e2, double result)+{+ long double precise = atan2l((long double)n1 + (long double)e1, (long double)n2 + (long double)e2);+ return (double) (precise - (long double)result);+}
changelog.org view
@@ -2,6 +2,16 @@ * Changelog +** 0.12++- Add Data.Double.Approximate: Floating point numbers take take+ imprecision into account when ordering.+- Add Data.Double.Shaman: Floating point numbers that keep track of+ error bounds while not being more than an order of magnitude slower+ than native floating point numbers.+- Add Data.PlanarGraph.Immutable and Data.PlanarGraph.Mutable: New+ planargraph implementation that supports efficient updates and queries.+ ** 0.11 - Changed the implementation of Two and Three in Data.Util
+ docs/Data/PlanarGraph/planargraph-1711135548958680232.svg view
@@ -0,0 +1,199 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+ <g>+ <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+ <rect width="16" height="9" />+ </g>+ <g>+ <g transform="translate(0, 1.2)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.125828, 0)">+ <line x2="0.251656" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -1.2)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+ <g transform="translate(-0.09863, 0)">+ <line x2="0.197261" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g>+ <line stroke="#000000" x1="-3.6" y1="0" x2="0" y2="3.6" />+ <g transform="translate(-2.012132, 2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-1.587868, 1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" y1="-0" x2="-3.6" y2="0" />+ <g transform="translate(-1.8, -0.3)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-1.8, 0.3)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="3.6" y1="-0" y2="-0" />+ <g transform="translate(1.8, -0.3)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(1.8, 0.3)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="3.6" y2="-0" />+ <g transform="translate(2.012132, 2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.269489, -0.325778)">+ <path d="M0.474222,0.606725 C0.483188,0.61868 0.483188,0.620672 0.483188,0.641594 L0.241096,0.641594 C0.119552,0.641594 0.117559,0.654545 0.113574,0.673474 L0.088667,0.673474 L0.055791,0.468244 L0.080697,0.468244 C0.083686,0.484184 0.092653,0.546949 0.105604,0.558904 C0.112578,0.564882 0.190286,0.564882 0.203238,0.564882 L0.409465,0.564882 C0.398506,0.548941 0.319801,0.440349 0.297883,0.407472 C0.208219,0.272976 0.175342,0.134496 0.175342,0.032877 C0.175342,0.022914 0.175342,-0.021918 0.221171,-0.021918 C0.267,-0.021918 0.266999,0.022914 0.266999,0.032877 L0.266999,0.083686 C0.266999,0.138481 0.269988,0.193275 0.277958,0.247073 C0.281943,0.269988 0.29589,0.355666 0.339726,0.417435 L0.474222,0.606725 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(1.587868, 1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.131507,0.326775 L0.131507,0.350685 C0.131507,0.60274 0.255044,0.638605 0.305853,0.638605 C0.329763,0.638605 0.371606,0.632628 0.393524,0.598755 C0.37858,0.598755 0.33873,0.598755 0.33873,0.553923 C0.33873,0.523039 0.36264,0.508095 0.384558,0.508095 C0.400498,0.508095 0.430386,0.517061 0.430386,0.555915 C0.430386,0.615691 0.38655,0.663512 0.303861,0.663512 C0.176339,0.663512 0.041843,0.534994 0.041843,0.314819 C0.041843,0.048817 0.15741,-0.021918 0.250062,-0.021918 C0.360648,-0.021918 0.455293,0.071731 0.455293,0.203238 C0.455293,0.329763 0.366625,0.425405 0.25604,0.425405 C0.188294,0.425405 0.151432,0.374595 0.131507,0.326775 Z M0.250062,0.005978 C0.187298,0.005978 0.15741,0.065753 0.151432,0.080697 C0.133499,0.127522 0.133499,0.207223 0.133499,0.225156 C0.133499,0.302864 0.16538,0.402491 0.255044,0.402491 C0.270984,0.402491 0.316812,0.402491 0.347696,0.340722 C0.365629,0.303861 0.365629,0.253051 0.365629,0.204234 C0.365629,0.156413 0.365629,0.1066 0.348692,0.070735 C0.318804,0.010959 0.272976,0.005978 0.250062,0.005978 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="3.6" y1="-0" x2="-0" y2="-3.6" />+ <g transform="translate(2.012132, -2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.365629,0.316812 L0.365629,0.284932 C0.365629,0.051806 0.262017,0.005978 0.204234,0.005978 C0.187298,0.005978 0.133499,0.00797 0.1066,0.041843 C0.150436,0.041843 0.158406,0.070735 0.158406,0.087671 C0.158406,0.118555 0.134496,0.133499 0.112578,0.133499 C0.096638,0.133499 0.06675,0.124533 0.06675,0.085679 C0.06675,0.018929 0.120548,-0.021918 0.20523,-0.021918 C0.333748,-0.021918 0.455293,0.113574 0.455293,0.327771 C0.455293,0.595766 0.340722,0.663512 0.252055,0.663512 C0.19726,0.663512 0.148443,0.645579 0.105604,0.600747 C0.064757,0.555915 0.041843,0.514072 0.041843,0.439352 C0.041843,0.314819 0.129514,0.217186 0.241096,0.217186 C0.301868,0.217186 0.342715,0.259029 0.365629,0.316812 Z M0.242092,0.2401 C0.226152,0.2401 0.180324,0.2401 0.14944,0.302864 C0.131507,0.339726 0.131507,0.389539 0.131507,0.438356 C0.131507,0.492154 0.131507,0.538979 0.152428,0.575841 C0.179328,0.625654 0.217186,0.638605 0.252055,0.638605 C0.297883,0.638605 0.33076,0.604732 0.347696,0.5599 C0.359651,0.52802 0.363636,0.465255 0.363636,0.419427 C0.363636,0.336737 0.329763,0.2401 0.242092,0.2401 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(1.587868, -1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.162391,0.455293 C0.116563,0.485181 0.112578,0.519054 0.112578,0.53599 C0.112578,0.596762 0.177335,0.638605 0.24807,0.638605 C0.320797,0.638605 0.384558,0.5868 0.384558,0.515068 C0.384558,0.458281 0.345704,0.410461 0.285928,0.375592 L0.162391,0.455293 Z M0.307846,0.360648 C0.379577,0.397509 0.428394,0.449315 0.428394,0.515068 C0.428394,0.606725 0.339726,0.663512 0.249066,0.663512 C0.14944,0.663512 0.068742,0.589788 0.068742,0.497136 C0.068742,0.479203 0.070735,0.434371 0.112578,0.387547 C0.123537,0.375592 0.160399,0.350685 0.185305,0.333748 C0.127522,0.304857 0.041843,0.249066 0.041843,0.150436 C0.041843,0.044832 0.143462,-0.021918 0.24807,-0.021918 C0.360648,-0.021918 0.455293,0.060772 0.455293,0.167372 C0.455293,0.203238 0.444334,0.24807 0.406476,0.289913 C0.387547,0.310834 0.371606,0.320797 0.307846,0.360648 Z M0.208219,0.318804 L0.33076,0.241096 C0.358655,0.222167 0.405479,0.192279 0.405479,0.131507 C0.405479,0.057783 0.33076,0.005978 0.249066,0.005978 C0.163387,0.005978 0.091656,0.067746 0.091656,0.150436 C0.091656,0.208219 0.123537,0.27198 0.208219,0.318804 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="-0" y1="-3.6" x2="-3.6" y2="0" />+ <g transform="translate(-2.012132, -2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.502118, -0.331756)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.791036,0.637609 C0.791036,0.661519 0.791036,0.663512 0.768122,0.663512 C0.706353,0.599751 0.618682,0.599751 0.586801,0.599751 L0.586801,0.568867 C0.606727,0.568867 0.665506,0.568867 0.717312,0.59477 L0.717312,0.078705 C0.717312,0.042839 0.714323,0.030884 0.62466,0.030884 L0.592779,0.030884 L0.592779,0 C0.627648,0.002989 0.714323,0.002989 0.754174,0.002989 C0.794025,0.002989 0.880699,0.002989 0.915569,0 L0.915569,0.030884 L0.883688,0.030884 C0.794024,0.030884 0.791036,0.041843 0.791036,0.078705 L0.791036,0.637609 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-1.587868, -1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.522541, -0.320797)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.956415,0.318804 C0.956415,0.398506 0.951434,0.478207 0.916565,0.55193 C0.870737,0.647572 0.789043,0.663512 0.7472,0.663512 C0.687424,0.663512 0.614697,0.637609 0.57385,0.544956 C0.54197,0.476214 0.536988,0.398506 0.536988,0.318804 C0.536988,0.244085 0.540973,0.154421 0.58182,0.078705 C0.62466,-0.001993 0.697387,-0.021918 0.746204,-0.021918 C0.800002,-0.021918 0.875718,-0.000996 0.919554,0.093649 C0.951434,0.162391 0.956415,0.2401 0.956415,0.318804 Z M0.746204,0 C0.707349,0 0.64857,0.024907 0.630637,0.120548 C0.619678,0.180324 0.619678,0.27198 0.619678,0.33076 C0.619678,0.394521 0.619678,0.460274 0.627648,0.514072 C0.646577,0.632628 0.721297,0.641594 0.746204,0.641594 C0.77908,0.641594 0.844834,0.623661 0.863763,0.525031 C0.873726,0.46924 0.873726,0.393524 0.873726,0.33076 C0.873726,0.25604 0.873726,0.188294 0.862767,0.124533 C0.847823,0.029888 0.791036,0 0.746204,0 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g transform="translate(0, 3.6)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.476841)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-3.6, 0)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.608332)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(0, -0)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.503132)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(3.6, -0)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.483734)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -3.6)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.45316)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-1902492848341357096.svg view
@@ -0,0 +1,166 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+ <g>+ <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+ <rect width="16" height="9" />+ </g>+ <g>+ <g transform="translate(0, 1.2)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.125828, 0)">+ <line x2="0.251656" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -1.2)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+ <g transform="translate(-0.09863, 0)">+ <line x2="0.197261" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g>+ <line stroke="#000000" x1="-3.6" y1="0" x2="0" y2="3.6" />+ <g transform="translate(-2.012132, 2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-1.587868, 1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="-0" y1="-3.6" x2="-3.6" y2="0" />+ <g transform="translate(-2.012132, -2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-1.587868, -1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="3.6" y1="-0" x2="-0" y2="-3.6" />+ <g transform="translate(2.012132, -2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(1.587868, -1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="3.6" y2="-0" />+ <g transform="translate(2.012132, 2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.269489, -0.325778)">+ <path d="M0.474222,0.606725 C0.483188,0.61868 0.483188,0.620672 0.483188,0.641594 L0.241096,0.641594 C0.119552,0.641594 0.117559,0.654545 0.113574,0.673474 L0.088667,0.673474 L0.055791,0.468244 L0.080697,0.468244 C0.083686,0.484184 0.092653,0.546949 0.105604,0.558904 C0.112578,0.564882 0.190286,0.564882 0.203238,0.564882 L0.409465,0.564882 C0.398506,0.548941 0.319801,0.440349 0.297883,0.407472 C0.208219,0.272976 0.175342,0.134496 0.175342,0.032877 C0.175342,0.022914 0.175342,-0.021918 0.221171,-0.021918 C0.267,-0.021918 0.266999,0.022914 0.266999,0.032877 L0.266999,0.083686 C0.266999,0.138481 0.269988,0.193275 0.277958,0.247073 C0.281943,0.269988 0.29589,0.355666 0.339726,0.417435 L0.474222,0.606725 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(1.587868, 1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.131507,0.326775 L0.131507,0.350685 C0.131507,0.60274 0.255044,0.638605 0.305853,0.638605 C0.329763,0.638605 0.371606,0.632628 0.393524,0.598755 C0.37858,0.598755 0.33873,0.598755 0.33873,0.553923 C0.33873,0.523039 0.36264,0.508095 0.384558,0.508095 C0.400498,0.508095 0.430386,0.517061 0.430386,0.555915 C0.430386,0.615691 0.38655,0.663512 0.303861,0.663512 C0.176339,0.663512 0.041843,0.534994 0.041843,0.314819 C0.041843,0.048817 0.15741,-0.021918 0.250062,-0.021918 C0.360648,-0.021918 0.455293,0.071731 0.455293,0.203238 C0.455293,0.329763 0.366625,0.425405 0.25604,0.425405 C0.188294,0.425405 0.151432,0.374595 0.131507,0.326775 Z M0.250062,0.005978 C0.187298,0.005978 0.15741,0.065753 0.151432,0.080697 C0.133499,0.127522 0.133499,0.207223 0.133499,0.225156 C0.133499,0.302864 0.16538,0.402491 0.255044,0.402491 C0.270984,0.402491 0.316812,0.402491 0.347696,0.340722 C0.365629,0.303861 0.365629,0.253051 0.365629,0.204234 C0.365629,0.156413 0.365629,0.1066 0.348692,0.070735 C0.318804,0.010959 0.272976,0.005978 0.250062,0.005978 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="3.6" y1="-0" x2="-3.6" y2="0" />+ <g transform="translate(-0, -0.3)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.365629,0.316812 L0.365629,0.284932 C0.365629,0.051806 0.262017,0.005978 0.204234,0.005978 C0.187298,0.005978 0.133499,0.00797 0.1066,0.041843 C0.150436,0.041843 0.158406,0.070735 0.158406,0.087671 C0.158406,0.118555 0.134496,0.133499 0.112578,0.133499 C0.096638,0.133499 0.06675,0.124533 0.06675,0.085679 C0.06675,0.018929 0.120548,-0.021918 0.20523,-0.021918 C0.333748,-0.021918 0.455293,0.113574 0.455293,0.327771 C0.455293,0.595766 0.340722,0.663512 0.252055,0.663512 C0.19726,0.663512 0.148443,0.645579 0.105604,0.600747 C0.064757,0.555915 0.041843,0.514072 0.041843,0.439352 C0.041843,0.314819 0.129514,0.217186 0.241096,0.217186 C0.301868,0.217186 0.342715,0.259029 0.365629,0.316812 Z M0.242092,0.2401 C0.226152,0.2401 0.180324,0.2401 0.14944,0.302864 C0.131507,0.339726 0.131507,0.389539 0.131507,0.438356 C0.131507,0.492154 0.131507,0.538979 0.152428,0.575841 C0.179328,0.625654 0.217186,0.638605 0.252055,0.638605 C0.297883,0.638605 0.33076,0.604732 0.347696,0.5599 C0.359651,0.52802 0.363636,0.465255 0.363636,0.419427 C0.363636,0.336737 0.329763,0.2401 0.242092,0.2401 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(0, 0.3)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.162391,0.455293 C0.116563,0.485181 0.112578,0.519054 0.112578,0.53599 C0.112578,0.596762 0.177335,0.638605 0.24807,0.638605 C0.320797,0.638605 0.384558,0.5868 0.384558,0.515068 C0.384558,0.458281 0.345704,0.410461 0.285928,0.375592 L0.162391,0.455293 Z M0.307846,0.360648 C0.379577,0.397509 0.428394,0.449315 0.428394,0.515068 C0.428394,0.606725 0.339726,0.663512 0.249066,0.663512 C0.14944,0.663512 0.068742,0.589788 0.068742,0.497136 C0.068742,0.479203 0.070735,0.434371 0.112578,0.387547 C0.123537,0.375592 0.160399,0.350685 0.185305,0.333748 C0.127522,0.304857 0.041843,0.249066 0.041843,0.150436 C0.041843,0.044832 0.143462,-0.021918 0.24807,-0.021918 C0.360648,-0.021918 0.455293,0.060772 0.455293,0.167372 C0.455293,0.203238 0.444334,0.24807 0.406476,0.289913 C0.387547,0.310834 0.371606,0.320797 0.307846,0.360648 Z M0.208219,0.318804 L0.33076,0.241096 C0.358655,0.222167 0.405479,0.192279 0.405479,0.131507 C0.405479,0.057783 0.33076,0.005978 0.249066,0.005978 C0.163387,0.005978 0.091656,0.067746 0.091656,0.150436 C0.091656,0.208219 0.123537,0.27198 0.208219,0.318804 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g transform="translate(0, 3.6)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.476841)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-3.6, 0)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.608332)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -3.6)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.503132)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(3.6, -0)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.483734)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-2506803680640023584.svg view
@@ -0,0 +1,135 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+ <g>+ <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+ <rect width="16" height="9" />+ </g>+ <g>+ <g transform="translate(-0, 0)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.125828, 0)">+ <line x2="0.251656" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g>+ <line stroke="#000000" x1="-3.6" y1="0" x2="0" y2="3.6" />+ <g transform="translate(-2.012132, 2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-1.587868, 1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="-0" y1="-3.6" x2="-3.6" y2="0" />+ <g transform="translate(-2.012132, -2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-1.587868, -1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="3.6" y1="-0" x2="-0" y2="-3.6" />+ <g transform="translate(2.012132, -2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(1.587868, -1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="3.6" y2="-0" />+ <g transform="translate(2.012132, 2.012132)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.269489, -0.325778)">+ <path d="M0.474222,0.606725 C0.483188,0.61868 0.483188,0.620672 0.483188,0.641594 L0.241096,0.641594 C0.119552,0.641594 0.117559,0.654545 0.113574,0.673474 L0.088667,0.673474 L0.055791,0.468244 L0.080697,0.468244 C0.083686,0.484184 0.092653,0.546949 0.105604,0.558904 C0.112578,0.564882 0.190286,0.564882 0.203238,0.564882 L0.409465,0.564882 C0.398506,0.548941 0.319801,0.440349 0.297883,0.407472 C0.208219,0.272976 0.175342,0.134496 0.175342,0.032877 C0.175342,0.022914 0.175342,-0.021918 0.221171,-0.021918 C0.267,-0.021918 0.266999,0.022914 0.266999,0.032877 L0.266999,0.083686 C0.266999,0.138481 0.269988,0.193275 0.277958,0.247073 C0.281943,0.269988 0.29589,0.355666 0.339726,0.417435 L0.474222,0.606725 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(1.587868, 1.587868)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.131507,0.326775 L0.131507,0.350685 C0.131507,0.60274 0.255044,0.638605 0.305853,0.638605 C0.329763,0.638605 0.371606,0.632628 0.393524,0.598755 C0.37858,0.598755 0.33873,0.598755 0.33873,0.553923 C0.33873,0.523039 0.36264,0.508095 0.384558,0.508095 C0.400498,0.508095 0.430386,0.517061 0.430386,0.555915 C0.430386,0.615691 0.38655,0.663512 0.303861,0.663512 C0.176339,0.663512 0.041843,0.534994 0.041843,0.314819 C0.041843,0.048817 0.15741,-0.021918 0.250062,-0.021918 C0.360648,-0.021918 0.455293,0.071731 0.455293,0.203238 C0.455293,0.329763 0.366625,0.425405 0.25604,0.425405 C0.188294,0.425405 0.151432,0.374595 0.131507,0.326775 Z M0.250062,0.005978 C0.187298,0.005978 0.15741,0.065753 0.151432,0.080697 C0.133499,0.127522 0.133499,0.207223 0.133499,0.225156 C0.133499,0.302864 0.16538,0.402491 0.255044,0.402491 C0.270984,0.402491 0.316812,0.402491 0.347696,0.340722 C0.365629,0.303861 0.365629,0.253051 0.365629,0.204234 C0.365629,0.156413 0.365629,0.1066 0.348692,0.070735 C0.318804,0.010959 0.272976,0.005978 0.250062,0.005978 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g transform="translate(0, 3.6)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.476841)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-3.6, 0)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.608332)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -3.6)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.503132)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(3.6, -0)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.483734)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-2635031442529484236.compact.svg view
@@ -0,0 +1,193 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+ <g>+ <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+ <rect width="16" height="9" />+ </g>+ <g>+ <g transform="translate(-1.247077, 0.72)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.125828, 0)">+ <line x2="0.251656" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, 1.44)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+ <g transform="translate(-0.09863, 0)">+ <line x2="0.197261" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-1.247077, -0.72)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+ <g transform="translate(-0.119253, 0)">+ <line x2="0.238506" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -1.44)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.124035, 0)">+ <line x2="0.24807" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(1.247077, -0.72)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.218618)" fill-opacity="0">+ <g transform="translate(-0.132403, 0)">+ <line x2="0.264807" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(1.247077, 0.72)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.119253, 0)">+ <line x2="0.238506" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g>+ <line stroke="#000000" x1="-3.117691" y1="-1.8" x2="0" y2="3.6" />+ </g>+ <g>+ <line stroke="#000000" x1="-0.623538" y1="0.36" x2="-3.117691" y2="-1.8" />+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="-0.623538" y2="0.36" />+ </g>+ <g>+ <line stroke="#000000" x1="0.623538" y1="0.36" x2="-0.623538" y2="0.36" />+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="0.623538" y2="0.36" />+ </g>+ <g>+ <line stroke="#000000" x1="-0" y1="-0.72" x2="-3.117691" y2="-1.8" />+ </g>+ <g>+ <line stroke="#000000" x1="-0.623538" y1="0.36" x2="-0" y2="-0.72" />+ </g>+ <g>+ <line stroke="#000000" x1="3.117691" y1="-1.8" x2="-3.117691" y2="-1.8" />+ </g>+ <g>+ <line stroke="#000000" x1="-0" y1="-0.72" x2="3.117691" y2="-1.8" />+ </g>+ <g>+ <line stroke="#000000" x1="0.623538" y1="0.36" x2="3.117691" y2="-1.8" />+ </g>+ <g>+ <line stroke="#000000" x1="-0" y1="-0.72" x2="0.623538" y2="0.36" />+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="3.117691" y2="-1.8" />+ </g>+ </g>+ <g>+ <g transform="translate(0, 3.6)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.476841)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0.623538, 0.36)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.608332)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(0.623538, 0.36)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.503132)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -0.72)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.483734)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-3.117691, -1.8)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.45316)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(3.117691, -1.8)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.503132)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-2635031442529484236.svg view
@@ -0,0 +1,403 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+ <g>+ <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+ <rect width="16" height="9" />+ </g>+ <g>+ <g transform="translate(-1.247077, 0.72)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.125828, 0)">+ <line x2="0.251656" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, 1.44)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+ <g transform="translate(-0.09863, 0)">+ <line x2="0.197261" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-1.247077, -0.72)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+ <g transform="translate(-0.119253, 0)">+ <line x2="0.238506" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -1.44)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.124035, 0)">+ <line x2="0.24807" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(1.247077, -0.72)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.218618)" fill-opacity="0">+ <g transform="translate(-0.132403, 0)">+ <line x2="0.264807" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(1.247077, 0.72)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.119253, 0)">+ <line x2="0.238506" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g>+ <line stroke="#000000" x1="-3.117691" y1="-1.8" x2="0" y2="3.6" />+ <g transform="translate(-1.818653, 1.05)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-1.299038, 0.75)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="-0.623538" y1="0.36" x2="-3.117691" y2="-1.8" />+ <g transform="translate(-1.674219, -0.946779)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-2.067011, -0.493221)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="-0.623538" y2="0.36" />+ <g transform="translate(-0.017175, 1.923305)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-0.606363, 2.036695)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="0.623538" y1="0.36" x2="-0.623538" y2="0.36" />+ <g transform="translate(-0, 0.06)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.269489, -0.325778)">+ <path d="M0.474222,0.606725 C0.483188,0.61868 0.483188,0.620672 0.483188,0.641594 L0.241096,0.641594 C0.119552,0.641594 0.117559,0.654545 0.113574,0.673474 L0.088667,0.673474 L0.055791,0.468244 L0.080697,0.468244 C0.083686,0.484184 0.092653,0.546949 0.105604,0.558904 C0.112578,0.564882 0.190286,0.564882 0.203238,0.564882 L0.409465,0.564882 C0.398506,0.548941 0.319801,0.440349 0.297883,0.407472 C0.208219,0.272976 0.175342,0.134496 0.175342,0.032877 C0.175342,0.022914 0.175342,-0.021918 0.221171,-0.021918 C0.267,-0.021918 0.266999,0.022914 0.266999,0.032877 L0.266999,0.083686 C0.266999,0.138481 0.269988,0.193275 0.277958,0.247073 C0.281943,0.269988 0.29589,0.355666 0.339726,0.417435 L0.474222,0.606725 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-0, 0.66)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.131507,0.326775 L0.131507,0.350685 C0.131507,0.60274 0.255044,0.638605 0.305853,0.638605 C0.329763,0.638605 0.371606,0.632628 0.393524,0.598755 C0.37858,0.598755 0.33873,0.598755 0.33873,0.553923 C0.33873,0.523039 0.36264,0.508095 0.384558,0.508095 C0.400498,0.508095 0.430386,0.517061 0.430386,0.555915 C0.430386,0.615691 0.38655,0.663512 0.303861,0.663512 C0.176339,0.663512 0.041843,0.534994 0.041843,0.314819 C0.041843,0.048817 0.15741,-0.021918 0.250062,-0.021918 C0.360648,-0.021918 0.455293,0.071731 0.455293,0.203238 C0.455293,0.329763 0.366625,0.425405 0.25604,0.425405 C0.188294,0.425405 0.151432,0.374595 0.131507,0.326775 Z M0.250062,0.005978 C0.187298,0.005978 0.15741,0.065753 0.151432,0.080697 C0.133499,0.127522 0.133499,0.207223 0.133499,0.225156 C0.133499,0.302864 0.16538,0.402491 0.255044,0.402491 C0.270984,0.402491 0.316812,0.402491 0.347696,0.340722 C0.365629,0.303861 0.365629,0.253051 0.365629,0.204234 C0.365629,0.156413 0.365629,0.1066 0.348692,0.070735 C0.318804,0.010959 0.272976,0.005978 0.250062,0.005978 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="0.623538" y2="0.36" />+ <g transform="translate(0.606363, 2.036695)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.365629,0.316812 L0.365629,0.284932 C0.365629,0.051806 0.262017,0.005978 0.204234,0.005978 C0.187298,0.005978 0.133499,0.00797 0.1066,0.041843 C0.150436,0.041843 0.158406,0.070735 0.158406,0.087671 C0.158406,0.118555 0.134496,0.133499 0.112578,0.133499 C0.096638,0.133499 0.06675,0.124533 0.06675,0.085679 C0.06675,0.018929 0.120548,-0.021918 0.20523,-0.021918 C0.333748,-0.021918 0.455293,0.113574 0.455293,0.327771 C0.455293,0.595766 0.340722,0.663512 0.252055,0.663512 C0.19726,0.663512 0.148443,0.645579 0.105604,0.600747 C0.064757,0.555915 0.041843,0.514072 0.041843,0.439352 C0.041843,0.314819 0.129514,0.217186 0.241096,0.217186 C0.301868,0.217186 0.342715,0.259029 0.365629,0.316812 Z M0.242092,0.2401 C0.226152,0.2401 0.180324,0.2401 0.14944,0.302864 C0.131507,0.339726 0.131507,0.389539 0.131507,0.438356 C0.131507,0.492154 0.131507,0.538979 0.152428,0.575841 C0.179328,0.625654 0.217186,0.638605 0.252055,0.638605 C0.297883,0.638605 0.33076,0.604732 0.347696,0.5599 C0.359651,0.52802 0.363636,0.465255 0.363636,0.419427 C0.363636,0.336737 0.329763,0.2401 0.242092,0.2401 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(0.017175, 1.923305)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.162391,0.455293 C0.116563,0.485181 0.112578,0.519054 0.112578,0.53599 C0.112578,0.596762 0.177335,0.638605 0.24807,0.638605 C0.320797,0.638605 0.384558,0.5868 0.384558,0.515068 C0.384558,0.458281 0.345704,0.410461 0.285928,0.375592 L0.162391,0.455293 Z M0.307846,0.360648 C0.379577,0.397509 0.428394,0.449315 0.428394,0.515068 C0.428394,0.606725 0.339726,0.663512 0.249066,0.663512 C0.14944,0.663512 0.068742,0.589788 0.068742,0.497136 C0.068742,0.479203 0.070735,0.434371 0.112578,0.387547 C0.123537,0.375592 0.160399,0.350685 0.185305,0.333748 C0.127522,0.304857 0.041843,0.249066 0.041843,0.150436 C0.041843,0.044832 0.143462,-0.021918 0.24807,-0.021918 C0.360648,-0.021918 0.455293,0.060772 0.455293,0.167372 C0.455293,0.203238 0.444334,0.24807 0.406476,0.289913 C0.387547,0.310834 0.371606,0.320797 0.307846,0.360648 Z M0.208219,0.318804 L0.33076,0.241096 C0.358655,0.222167 0.405479,0.192279 0.405479,0.131507 C0.405479,0.057783 0.33076,0.005978 0.249066,0.005978 C0.163387,0.005978 0.091656,0.067746 0.091656,0.150436 C0.091656,0.208219 0.123537,0.27198 0.208219,0.318804 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="-0" y1="-0.72" x2="-3.117691" y2="-1.8" />+ <g transform="translate(-1.460648, -1.543473)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.502118, -0.331756)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.791036,0.637609 C0.791036,0.661519 0.791036,0.663512 0.768122,0.663512 C0.706353,0.599751 0.618682,0.599751 0.586801,0.599751 L0.586801,0.568867 C0.606727,0.568867 0.665506,0.568867 0.717312,0.59477 L0.717312,0.078705 C0.717312,0.042839 0.714323,0.030884 0.62466,0.030884 L0.592779,0.030884 L0.592779,0 C0.627648,0.002989 0.714323,0.002989 0.754174,0.002989 C0.794025,0.002989 0.880699,0.002989 0.915569,0 L0.915569,0.030884 L0.883688,0.030884 C0.794024,0.030884 0.791036,0.041843 0.791036,0.078705 L0.791036,0.637609 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-1.657044, -0.976527)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.522541, -0.320797)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.956415,0.318804 C0.956415,0.398506 0.951434,0.478207 0.916565,0.55193 C0.870737,0.647572 0.789043,0.663512 0.7472,0.663512 C0.687424,0.663512 0.614697,0.637609 0.57385,0.544956 C0.54197,0.476214 0.536988,0.398506 0.536988,0.318804 C0.536988,0.244085 0.540973,0.154421 0.58182,0.078705 C0.62466,-0.001993 0.697387,-0.021918 0.746204,-0.021918 C0.800002,-0.021918 0.875718,-0.000996 0.919554,0.093649 C0.951434,0.162391 0.956415,0.2401 0.956415,0.318804 Z M0.746204,0 C0.707349,0 0.64857,0.024907 0.630637,0.120548 C0.619678,0.180324 0.619678,0.27198 0.619678,0.33076 C0.619678,0.394521 0.619678,0.460274 0.627648,0.514072 C0.646577,0.632628 0.721297,0.641594 0.746204,0.641594 C0.77908,0.641594 0.844834,0.623661 0.863763,0.525031 C0.873726,0.46924 0.873726,0.393524 0.873726,0.33076 C0.873726,0.25604 0.873726,0.188294 0.862767,0.124533 C0.847823,0.029888 0.791036,0 0.746204,0 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="-0.623538" y1="0.36" x2="-0" y2="-0.72" />+ <g transform="translate(-0.051962, -0.03)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.521047, -0.320797)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.787051,0.350685 C0.868744,0.377584 0.926528,0.447323 0.926528,0.526027 C0.926528,0.607721 0.838856,0.663512 0.743215,0.663512 C0.642592,0.663512 0.566876,0.603736 0.566876,0.52802 C0.566876,0.495143 0.588794,0.476214 0.617686,0.476214 C0.64857,0.476214 0.668495,0.498132 0.668495,0.527024 C0.668495,0.576837 0.621671,0.576837 0.606727,0.576837 C0.637611,0.625654 0.703364,0.638605 0.73923,0.638605 C0.780077,0.638605 0.834871,0.616687 0.834871,0.527024 C0.834871,0.515068 0.832879,0.457285 0.806976,0.41345 C0.777088,0.365629 0.743215,0.36264 0.718308,0.361644 C0.710338,0.360648 0.686428,0.358655 0.679454,0.358655 C0.671484,0.357659 0.66451,0.356663 0.66451,0.3467 C0.66451,0.335741 0.671484,0.335741 0.68842,0.335741 L0.732256,0.335741 C0.81395,0.335741 0.850811,0.267995 0.850811,0.170361 C0.850811,0.034869 0.782069,0.005978 0.738234,0.005978 C0.695394,0.005978 0.620674,0.022914 0.585805,0.081694 C0.620674,0.076712 0.651559,0.09863 0.651559,0.136488 C0.651559,0.172354 0.62466,0.192279 0.595768,0.192279 C0.571858,0.192279 0.539977,0.178331 0.539977,0.134496 C0.539977,0.043836 0.63263,-0.021918 0.741222,-0.021918 C0.862767,-0.021918 0.953427,0.068742 0.953427,0.170361 C0.953427,0.252055 0.890662,0.329763 0.787051,0.350685 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0.571577, -0.33)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.517062, -0.331756)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.62466,0.076712 L0.730264,0.179328 C0.885681,0.316812 0.945457,0.37061 0.945457,0.470237 C0.945457,0.583811 0.855793,0.663512 0.734249,0.663512 C0.621671,0.663512 0.547947,0.571856 0.547947,0.483188 C0.547947,0.427397 0.59776,0.427397 0.600749,0.427397 C0.617686,0.427397 0.652555,0.439352 0.652555,0.480199 C0.652555,0.506102 0.634622,0.532005 0.599753,0.532005 C0.591783,0.532005 0.58979,0.532005 0.586801,0.531009 C0.609716,0.595766 0.663514,0.632628 0.721297,0.632628 C0.811957,0.632628 0.854797,0.55193 0.854797,0.470237 C0.854797,0.390535 0.804983,0.311831 0.750189,0.250062 L0.558906,0.036862 C0.547947,0.025903 0.547947,0.02391 0.547947,0 L0.917561,0 L0.945457,0.17335 L0.92055,0.17335 C0.915569,0.143462 0.908595,0.099626 0.898632,0.084682 C0.891658,0.076712 0.825905,0.076712 0.803987,0.076712 L0.62466,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="3.117691" y1="-1.8" x2="-3.117691" y2="-1.8" />+ <g transform="translate(-0, -2.1)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.517062, -0.320797)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.945457,0.200249 C0.945457,0.318804 0.863763,0.418431 0.756166,0.418431 C0.708346,0.418431 0.665506,0.402491 0.629641,0.367621 L0.629641,0.561893 C0.649566,0.555915 0.682443,0.548941 0.714323,0.548941 C0.836864,0.548941 0.906602,0.639601 0.906602,0.652553 C0.906602,0.658531 0.903613,0.663512 0.89664,0.663512 C0.895643,0.663512 0.893651,0.663512 0.888669,0.660523 C0.868744,0.651557 0.819927,0.631631 0.753178,0.631631 C0.713327,0.631631 0.667499,0.638605 0.620674,0.659527 C0.612704,0.662516 0.610712,0.662516 0.608719,0.662516 C0.598757,0.662516 0.598757,0.654545 0.598757,0.638605 L0.598757,0.343711 C0.598757,0.325778 0.598757,0.317808 0.612704,0.317808 C0.619678,0.317808 0.621671,0.320797 0.625656,0.326775 C0.636615,0.342715 0.673476,0.396513 0.754174,0.396513 C0.80598,0.396513 0.830886,0.350685 0.838856,0.332752 C0.854797,0.29589 0.856789,0.257036 0.856789,0.207223 C0.856789,0.172354 0.856789,0.112578 0.832879,0.070735 C0.808968,0.03188 0.772107,0.005978 0.726278,0.005978 C0.653551,0.005978 0.596764,0.05878 0.579828,0.117559 C0.582816,0.116563 0.585805,0.115567 0.596764,0.115567 C0.629641,0.115567 0.646577,0.140473 0.646577,0.164384 C0.646577,0.188295 0.629641,0.2132 0.596764,0.2132 C0.582816,0.2132 0.547947,0.206227 0.547947,0.160399 C0.547947,0.07472 0.616689,-0.021918 0.728271,-0.021918 C0.843838,-0.021918 0.945457,0.073724 0.945457,0.200249 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -1.5)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.528021, -0.337236)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.791036,0.164384 L0.791036,0.077709 C0.791036,0.041843 0.789043,0.030884 0.71532,0.030884 L0.694398,0.030884 L0.694398,0 C0.735245,0.002989 0.787051,0.002989 0.828894,0.002989 C0.870737,0.002989 0.923539,0.002989 0.964386,0 L0.964386,0.030884 L0.943464,0.030884 C0.86974,0.030884 0.867748,0.041843 0.867748,0.077709 L0.867748,0.164384 L0.967374,0.164384 L0.967374,0.195268 L0.867748,0.195268 L0.867748,0.648568 C0.867748,0.668493 0.867748,0.674471 0.851808,0.674471 C0.842841,0.674471 0.839853,0.674471 0.831882,0.662516 L0.526029,0.195268 L0.526029,0.164384 L0.791036,0.164384 Z M0.797013,0.195268 L0.553925,0.195268 L0.797013,0.566874 L0.797013,0.195268 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="-0" y1="-0.72" x2="3.117691" y2="-1.8" />+ <g transform="translate(1.657044, -0.976527)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.534995, -0.325778)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.972356,0.606725 C0.981322,0.61868 0.981322,0.620672 0.981322,0.641594 L0.73923,0.641594 C0.617686,0.641594 0.615693,0.654545 0.611708,0.673474 L0.586801,0.673474 L0.553925,0.468244 L0.578831,0.468244 C0.58182,0.484184 0.590787,0.546949 0.603738,0.558904 C0.610712,0.564882 0.68842,0.564882 0.701372,0.564882 L0.907599,0.564882 C0.89664,0.548941 0.817935,0.440349 0.796017,0.407472 C0.706353,0.272976 0.673476,0.134496 0.673476,0.032877 C0.673476,0.022914 0.673476,-0.021918 0.719305,-0.021918 C0.765134,-0.021918 0.765133,0.022914 0.765133,0.032877 L0.765133,0.083686 C0.765133,0.138481 0.768122,0.193275 0.776092,0.247073 C0.780077,0.269988 0.794024,0.355666 0.83786,0.417435 L0.972356,0.606725 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(1.460648, -1.543473)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.521047, -0.320797)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.629641,0.326775 L0.629641,0.350685 C0.629641,0.60274 0.753178,0.638605 0.803987,0.638605 C0.827897,0.638605 0.86974,0.632628 0.891658,0.598755 C0.876714,0.598755 0.836864,0.598755 0.836864,0.553923 C0.836864,0.523039 0.860774,0.508095 0.882692,0.508095 C0.898632,0.508095 0.92852,0.517061 0.92852,0.555915 C0.92852,0.615691 0.884684,0.663512 0.801995,0.663512 C0.674473,0.663512 0.539977,0.534994 0.539977,0.314819 C0.539977,0.048817 0.655544,-0.021918 0.748196,-0.021918 C0.858782,-0.021918 0.953427,0.071731 0.953427,0.203238 C0.953427,0.329763 0.864759,0.425405 0.754174,0.425405 C0.686428,0.425405 0.649566,0.374595 0.629641,0.326775 Z M0.748196,0.005978 C0.685432,0.005978 0.655544,0.065753 0.649566,0.080697 C0.631633,0.127522 0.631633,0.207223 0.631633,0.225156 C0.631633,0.302864 0.663514,0.402491 0.753178,0.402491 C0.769118,0.402491 0.814946,0.402491 0.84583,0.340722 C0.863763,0.303861 0.863763,0.253051 0.863763,0.204234 C0.863763,0.156413 0.863763,0.1066 0.846826,0.070735 C0.816938,0.010959 0.77111,0.005978 0.748196,0.005978 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="0.623538" y1="0.36" x2="3.117691" y2="-1.8" />+ <g transform="translate(2.067011, -0.493221)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.521047, -0.320797)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.863763,0.316812 L0.863763,0.284932 C0.863763,0.051806 0.760151,0.005978 0.702368,0.005978 C0.685432,0.005978 0.631633,0.00797 0.604734,0.041843 C0.64857,0.041843 0.65654,0.070735 0.65654,0.087671 C0.65654,0.118555 0.63263,0.133499 0.610712,0.133499 C0.594772,0.133499 0.564884,0.124533 0.564884,0.085679 C0.564884,0.018929 0.618682,-0.021918 0.703364,-0.021918 C0.831882,-0.021918 0.953427,0.113574 0.953427,0.327771 C0.953427,0.595766 0.838856,0.663512 0.750189,0.663512 C0.695394,0.663512 0.646577,0.645579 0.603738,0.600747 C0.562891,0.555915 0.539977,0.514072 0.539977,0.439352 C0.539977,0.314819 0.627648,0.217186 0.73923,0.217186 C0.800002,0.217186 0.840849,0.259029 0.863763,0.316812 Z M0.740226,0.2401 C0.724286,0.2401 0.678458,0.2401 0.647574,0.302864 C0.629641,0.339726 0.629641,0.389539 0.629641,0.438356 C0.629641,0.492154 0.629641,0.538979 0.650562,0.575841 C0.677462,0.625654 0.71532,0.638605 0.750189,0.638605 C0.796017,0.638605 0.828894,0.604732 0.84583,0.5599 C0.857785,0.52802 0.86177,0.465255 0.86177,0.419427 C0.86177,0.336737 0.827897,0.2401 0.740226,0.2401 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(1.674219, -0.946779)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.521047, -0.320797)">+ <g>+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ <path d="M0.660525,0.455293 C0.614697,0.485181 0.610712,0.519054 0.610712,0.53599 C0.610712,0.596762 0.675469,0.638605 0.746204,0.638605 C0.818931,0.638605 0.882692,0.5868 0.882692,0.515068 C0.882692,0.458281 0.843838,0.410461 0.784062,0.375592 L0.660525,0.455293 Z M0.80598,0.360648 C0.877711,0.397509 0.926528,0.449315 0.926528,0.515068 C0.926528,0.606725 0.83786,0.663512 0.7472,0.663512 C0.647574,0.663512 0.566876,0.589788 0.566876,0.497136 C0.566876,0.479203 0.568869,0.434371 0.610712,0.387547 C0.621671,0.375592 0.658533,0.350685 0.683439,0.333748 C0.625656,0.304857 0.539977,0.249066 0.539977,0.150436 C0.539977,0.044832 0.641596,-0.021918 0.746204,-0.021918 C0.858782,-0.021918 0.953427,0.060772 0.953427,0.167372 C0.953427,0.203238 0.942468,0.24807 0.90461,0.289913 C0.885681,0.310834 0.86974,0.320797 0.80598,0.360648 Z M0.706353,0.318804 L0.828894,0.241096 C0.856789,0.222167 0.903613,0.192279 0.903613,0.131507 C0.903613,0.057783 0.828894,0.005978 0.7472,0.005978 C0.661521,0.005978 0.58979,0.067746 0.58979,0.150436 C0.58979,0.208219 0.621671,0.27198 0.706353,0.318804 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="-0" y1="-0.72" x2="0.623538" y2="0.36" />+ <g transform="translate(0.051962, -0.03)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.482691, -0.331756)">+ <g>+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ <path d="M0.791036,0.637609 C0.791036,0.661519 0.791036,0.663512 0.768122,0.663512 C0.706353,0.599751 0.618682,0.599751 0.586801,0.599751 L0.586801,0.568867 C0.606727,0.568867 0.665506,0.568867 0.717312,0.59477 L0.717312,0.078705 C0.717312,0.042839 0.714323,0.030884 0.62466,0.030884 L0.592779,0.030884 L0.592779,0 C0.627648,0.002989 0.714323,0.002989 0.754174,0.002989 C0.794025,0.002989 0.880699,0.002989 0.915569,0 L0.915569,0.030884 L0.883688,0.030884 C0.794024,0.030884 0.791036,0.041843 0.791036,0.078705 L0.791036,0.637609 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(0.571577, -0.33)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.503114, -0.320797)">+ <g>+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ <path d="M0.956415,0.318804 C0.956415,0.398506 0.951434,0.478207 0.916565,0.55193 C0.870737,0.647572 0.789043,0.663512 0.7472,0.663512 C0.687424,0.663512 0.614697,0.637609 0.57385,0.544956 C0.54197,0.476214 0.536988,0.398506 0.536988,0.318804 C0.536988,0.244085 0.540973,0.154421 0.58182,0.078705 C0.62466,-0.001993 0.697387,-0.021918 0.746204,-0.021918 C0.800002,-0.021918 0.875718,-0.000996 0.919554,0.093649 C0.951434,0.162391 0.956415,0.2401 0.956415,0.318804 Z M0.746204,0 C0.707349,0 0.64857,0.024907 0.630637,0.120548 C0.619678,0.180324 0.619678,0.27198 0.619678,0.33076 C0.619678,0.394521 0.619678,0.460274 0.627648,0.514072 C0.646577,0.632628 0.721297,0.641594 0.746204,0.641594 C0.77908,0.641594 0.844834,0.623661 0.863763,0.525031 C0.873726,0.46924 0.873726,0.393524 0.873726,0.33076 C0.873726,0.25604 0.873726,0.188294 0.862767,0.124533 C0.847823,0.029888 0.791036,0 0.746204,0 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="3.117691" y2="-1.8" />+ <g transform="translate(1.818653, 1.05)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.50162, -0.320797)">+ <g>+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ <path d="M0.787051,0.350685 C0.868744,0.377584 0.926528,0.447323 0.926528,0.526027 C0.926528,0.607721 0.838856,0.663512 0.743215,0.663512 C0.642592,0.663512 0.566876,0.603736 0.566876,0.52802 C0.566876,0.495143 0.588794,0.476214 0.617686,0.476214 C0.64857,0.476214 0.668495,0.498132 0.668495,0.527024 C0.668495,0.576837 0.621671,0.576837 0.606727,0.576837 C0.637611,0.625654 0.703364,0.638605 0.73923,0.638605 C0.780077,0.638605 0.834871,0.616687 0.834871,0.527024 C0.834871,0.515068 0.832879,0.457285 0.806976,0.41345 C0.777088,0.365629 0.743215,0.36264 0.718308,0.361644 C0.710338,0.360648 0.686428,0.358655 0.679454,0.358655 C0.671484,0.357659 0.66451,0.356663 0.66451,0.3467 C0.66451,0.335741 0.671484,0.335741 0.68842,0.335741 L0.732256,0.335741 C0.81395,0.335741 0.850811,0.267995 0.850811,0.170361 C0.850811,0.034869 0.782069,0.005978 0.738234,0.005978 C0.695394,0.005978 0.620674,0.022914 0.585805,0.081694 C0.620674,0.076712 0.651559,0.09863 0.651559,0.136488 C0.651559,0.172354 0.62466,0.192279 0.595768,0.192279 C0.571858,0.192279 0.539977,0.178331 0.539977,0.134496 C0.539977,0.043836 0.63263,-0.021918 0.741222,-0.021918 C0.862767,-0.021918 0.953427,0.068742 0.953427,0.170361 C0.953427,0.252055 0.890662,0.329763 0.787051,0.350685 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(1.299038, 0.75)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.497635, -0.331756)">+ <g>+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ <path d="M0.62466,0.076712 L0.730264,0.179328 C0.885681,0.316812 0.945457,0.37061 0.945457,0.470237 C0.945457,0.583811 0.855793,0.663512 0.734249,0.663512 C0.621671,0.663512 0.547947,0.571856 0.547947,0.483188 C0.547947,0.427397 0.59776,0.427397 0.600749,0.427397 C0.617686,0.427397 0.652555,0.439352 0.652555,0.480199 C0.652555,0.506102 0.634622,0.532005 0.599753,0.532005 C0.591783,0.532005 0.58979,0.532005 0.586801,0.531009 C0.609716,0.595766 0.663514,0.632628 0.721297,0.632628 C0.811957,0.632628 0.854797,0.55193 0.854797,0.470237 C0.854797,0.390535 0.804983,0.311831 0.750189,0.250062 L0.558906,0.036862 C0.547947,0.025903 0.547947,0.02391 0.547947,0 L0.917561,0 L0.945457,0.17335 L0.92055,0.17335 C0.915569,0.143462 0.908595,0.099626 0.898632,0.084682 C0.891658,0.076712 0.825905,0.076712 0.803987,0.076712 L0.62466,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g transform="translate(0, 3.6)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.476841)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0.623538, 0.36)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.608332)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(0.623538, 0.36)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.503132)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-0, -0.72)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.483734)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-3.117691, -1.8)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.45316)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(3.117691, -1.8)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.503132)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-2959979592048325618.svg view
@@ -0,0 +1,108 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+ <g>+ <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+ <rect width="16" height="9" />+ </g>+ <g>+ <g transform="translate(-0, -0)">+ <g>+ <g transform="scale(0.5)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+ <g transform="translate(-0.125828, 0)">+ <line x2="0.251656" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g>+ <line stroke="#000000" x1="-3.117691" y1="-1.8" x2="0" y2="3.6" />+ <g transform="translate(-1.818653, 1.05)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-1.299038, 0.75)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="3.117691" y1="-1.8" x2="-3.117691" y2="-1.8" />+ <g transform="translate(-0, -2.1)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(-0, -1.5)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ <g>+ <line stroke="#000000" x1="0" y1="3.6" x2="3.117691" y2="-1.8" />+ <g transform="translate(1.818653, 1.05)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248568, -0.320797)">+ <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+ </g>+ </g>+ </g>+ <g transform="translate(1.299038, 0.75)">+ <g transform="scale(0.4)">+ <g transform="translate(-0.248567, -0.337236)">+ <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ <g>+ <g transform="translate(0, 3.6)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.476841)">+ <g transform="translate(-0.248567, -0.320797)">+ <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(-3.117691, -1.8)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.608332)">+ <g transform="translate(-0.253051, -0.331756)">+ <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+ </g>+ </g>+ </g>+ </g>+ <g transform="translate(3.117691, -1.8)">+ <g>+ <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+ <g transform="scale(0.503132)">+ <g transform="translate(-0.248568, -0.331756)">+ <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+</svg></g></g></svg>
doctests.hs view
@@ -31,7 +31,6 @@ , "DeriveFunctor" , "DeriveFoldable" , "DeriveTraversable"- , "AutoDeriveTypeable" , "DeriveGeneric" , "FlexibleInstances" , "FlexibleContexts"@@ -55,16 +54,22 @@ modules = [ "Data.Range" , "Data.CircularList.Util"+ , "Data.Vector.Circular.Util" , "Data.Permutation" , "Data.CircularSeq" , "Data.LSeq" , "Data.PlanarGraph" , "Data.PlanarGraph.Dart" , "Data.PlanarGraph.Core"+ , "Data.PlanarGraph.Mutable"+ , "Data.PlanarGraph.Immutable" , "Data.Tree.Util" , "Data.Set.Util" , "Data.List.Util" , "Data.List.Alternating" , "Data.List.Zipper"++ , "Data.Double.Approximate"+ , "Data.Double.Shaman" ]
hgeometry-combinatorial.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: hgeometry-combinatorial-version: 0.11.0.0+version: 0.12.0.0 synopsis: Data structures, and Data types. description: The Non-geometric data types and algorithms used in HGeometry.@@ -28,6 +28,8 @@ Extra-doc-files: docs/Data/PlanarGraph/testG.png docs/Data/PlaneGraph/planegraph.png+ docs/Data/PlanarGraph/*.svg+ docs/Data/PlanarGraph/*.compact.svg -- docs/**/*.png cabal-version: 2.0@@ -47,12 +49,15 @@ -- * Graph Algorithms Algorithms.Graph.DFS Algorithms.Graph.MST+ Algorithms.FloydWarshall Algorithms.StringSearch.KMP -- * Numeric Data Types Data.RealNumber.Rational+ Data.Double.Approximate+ Data.Double.Shaman -- * Measurements Data.Measured@@ -65,15 +70,15 @@ Data.Range Data.Ext- -- Data.Ext.Multi+ Data.Ext.Multi Data.LSeq Data.CircularSeq Data.Sequence.Util Data.BinaryTree- Data.BinaryTree.Zipper Data.CircularList.Util+ Data.Vector.Circular.Util Data.OrdSeq Data.Tree.Util Data.Util@@ -94,6 +99,9 @@ -- * Planar Graphs Data.Permutation Data.PlanarGraph+ Data.PlanarGraph.Persistent+ Data.PlanarGraph.Mutable+ Data.PlanarGraph.Immutable Data.PlanarGraph.AdjRep Data.PlanarGraph.IO Data.PlanarGraph.Dart@@ -110,16 +118,17 @@ Data.Yaml.Util - other-modules:+ other-modules: Data.PlanarGraph.Internal -- other-extensions: build-depends: base >= 4.11 && < 5+ , array >= 0.4 , bifunctors >= 4.1 , bytestring >= 0.10 , containers >= 0.5.9 , dlist >= 0.7- , lens >= 4.2+ , lens >= 4.18 , contravariant >= 1.5 , semigroupoids >= 5 , semigroups >= 0.18@@ -135,13 +144,17 @@ , linear >= 1.20.8 , hashable >= 1.2 - , vector >= 0.11+ , vector >= 0.11 && < 0.12.2.0 , data-clist >= 0.1.2.3+ , vector-circular >= 0.1.2+ , nonempty-vector >= 0.2.0.0 , vector-builder >= 0.3.7+ , unordered-containers , aeson >= 1.0 , yaml >= 0.8 , text >= 1.1.1.0+ , math-functions , mtl , template-haskell@@ -181,6 +194,9 @@ , FlexibleContexts , MultiParamTypeClasses + c-sources: cbits/erf.c+ extra-libraries: m+ test-suite doctests type: exitcode-stdio-1.0 ghc-options: -threaded@@ -204,12 +220,14 @@ other-modules: Algorithms.StringSearch.KMPSpec Algorithms.DivideAndConquerSpec+ Algorithms.Graph.DFSSpec Data.RangeSpec Data.EdgeOracleSpec Data.PlanarGraphSpec Data.OrdSeqSpec Data.CircularSeqSpec Data.IndexedDoublyLinkedListSpec+ Data.RealNumber.RationalSpec build-depends: base@@ -218,6 +236,7 @@ , quickcheck-instances >= 0.3 , approximate-equality >= 1.1.0.2 , hgeometry-combinatorial+ , deepseq , lens , data-clist , linear@@ -256,8 +275,6 @@ , DeriveFunctor , DeriveFoldable , DeriveTraversable-- , AutoDeriveTypeable , FlexibleInstances , FlexibleContexts
src/Algorithms/BinarySearch.hs view
@@ -1,7 +1,18 @@+{-# LANGUAGE UndecidableInstances #-}+--------------------------------------------------------------------------------+-- |+-- Module : Algorithms.BinarySearch+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Algorithms.BinarySearch where -import Data.Sequence(Seq, ViewL(..),ViewR(..))-import qualified Data.Sequence as S+import Control.Applicative ((<|>))+import Data.Sequence (Seq, ViewL(..),ViewR(..))+import qualified Data.Sequence as Seq+import Data.Set (Set)+import qualified Data.Set.Internal as Set import qualified Data.Vector.Generic as V --------------------------------------------------------------------------------@@ -54,38 +65,85 @@ --------------------------------------------------------------------------------+-- * Binary Searching in some data structure --- | Given a monotonic predicate, Get the index h such that everything strictly--- smaller than h has: p i = False, and all i >= h, we have p h = True------ returns Nothing if no element satisfies p------ running time: \(O(\log^2 n + T*\log n)\), where \(T\) is the time to execute the--- predicate.-binarySearchSeq :: (a -> Bool) -> Seq a -> Maybe Int-binarySearchSeq p s = case S.viewr s of- EmptyR -> Nothing- (_ :> x) | p x -> Just $ case S.viewl s of- (y :< _) | p y -> 0- _ -> binarySearch p' 0 u- | otherwise -> Nothing- where- p' = p . S.index s- u = S.length s - 1 --- | Given a monotonic predicate, get the index h such that everything strictly--- smaller than h has: p i = False, and all i >= h, we have p h = True------ returns Nothing if no element satisfies p------ running time: \(O(T*\log n)\), where \(T\) is the time to execute the--- predicate.-binarySearchVec :: V.Vector v a- => (a -> Bool) -> v a -> Maybe Int-binarySearchVec p' v | V.null v = Nothing- | not $ p n' = Nothing- | otherwise = Just $ if p 0 then 0- else binarySearch p 0 n'- where- n' = V.length v - 1- p = p' . (v V.!)+class BinarySearch v where+ type Index v :: *+ type Elem v :: *++ -- | Given a monotonic predicate p and a data structure v, find the+ -- element v[h] such that that+ --+ -- for every index i < h we have p v[i] = False, and+ -- for every inedx i >= h we have p v[i] = True+ --+ -- returns Nothing if no element satisfies p+ --+ -- running time: \(O(T*\log n)\), where \(T\) is the time to execute the+ -- predicate.+ binarySearchIn :: (Elem v -> Bool) -> v -> Maybe (Elem v)++ -- | Given a monotonic predicate p and a data structure v, find the+ -- index h such that that+ --+ -- for every index i < h we have p v[i] = False, and+ -- for every inedx i >= h we have p v[i] = True+ --+ -- returns Nothing if no element satisfies p+ --+ -- running time: \(O(T*\log n)\), where \(T\) is the time to execute the+ -- predicate.+ binarySearchIdxIn :: (Elem v -> Bool) -> v -> Maybe (Index v)++--------------------------------------------------------------------------------+-- * Searching on a Sequence++instance BinarySearch (Seq a) where+ type Index (Seq a) = Int+ type Elem (Seq a) = a++ -- ^ runs in \(O(T*\log^2 n)\) time.+ binarySearchIn p s = Seq.index s <$> binarySearchIdxIn p s++ -- ^ runs in \(O(T*\log^2 n)\) time.+ binarySearchIdxIn p s = case Seq.viewr s of+ EmptyR -> Nothing+ (_ :> x) | p x -> Just $ case Seq.viewl s of+ (y :< _) | p y -> 0+ _ -> binarySearch p' 0 u+ | otherwise -> Nothing+ where+ p' = p . Seq.index s+ u = Seq.length s - 1++instance {-# OVERLAPPABLE #-} V.Vector v a => BinarySearch (v a) where+ type Index (v a) = Int+ type Elem (v a) = a++ binarySearchIdxIn p' v | V.null v = Nothing+ | not $ p n' = Nothing+ | otherwise = Just $ if p 0 then 0 else binarySearch p 0 n'+ where+ n' = V.length v - 1+ p = p' . (v V.!)++ binarySearchIn p v = (v V.!) <$> binarySearchIdxIn p v++instance BinarySearch (Set a) where+ type Index (Set a) = Int+ type Elem (Set a) = a++ binarySearchIn p = go+ where+ go = \case+ Set.Tip -> Nothing+ Set.Bin _ k l r | p k -> go l <|> Just k+ | otherwise -> go r++ binarySearchIdxIn p = go+ where+ go = \case+ Set.Tip -> Nothing+ Set.Bin _ k l r | p k -> go l <|> Just (Set.size l)+ | otherwise -> (+ (1 + Set.size l)) <$> go r
src/Algorithms/DivideAndConquer.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Algorithms.DivideAndConquer+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Algorithms.DivideAndConquer( divideAndConquer , divideAndConquer1 , divideAndConquer1With@@ -26,6 +33,7 @@ divideAndConquer :: (Foldable f, Monoid s) => (a -> s) -> f a -> s divideAndConquer g = maybe mempty (divideAndConquer1 g) . NonEmpty.nonEmpty . F.toList +{- HLINT ignore divideAndConquer1With -} -- | Divide and conquer strategy -- -- the running time satifies T(n) = 2T(n/2) + M(n),@@ -40,7 +48,7 @@ merge ts@(_ :| []) = ts merge (l :| r : []) = l <.> r :| []- merge (l :| r : ts) = l <.> r <| (merge $ NonEmpty.fromList ts)+ merge (l :| r : ts) = l <.> r <| merge (NonEmpty.fromList ts) --------------------------------------------------------------------------------
+ src/Algorithms/FloydWarshall.hs view
@@ -0,0 +1,56 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.Geometry.Polygon.Core+-- Copyright : (C) David Himmelstrup+-- License : see the LICENSE file+-- Maintainer : David Himmelstrup+--+-- Implementation of Floyd-Warshall shortest path algorithm.+--+-- See Wikipedia article for details: https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm+--+--------------------------------------------------------------------------------+module Algorithms.FloydWarshall+ ( mkIndex+ , mkGraph+ , floydWarshall+ ) where++import Control.Monad (forM_, when)+import Control.Monad.ST (ST)+import Data.Vector.Unboxed.Mutable as V (MVector, length, replicate, unsafeRead,+ unsafeWrite, Unbox)++-- | \( O(n^3) \)+floydWarshall :: (Unbox a, Fractional a, Ord a) => Int -> MVector s (a, Int) -> ST s ()+floydWarshall n graph = do+ let nSq = V.length graph+ when (n*n /= nSq) $ error "Bad bounds"+ forM_ [0 .. n-1] $ \k ->+ forM_ [0 .. n-1] $ \i ->+ forM_ [0 .. n-1] $ \j -> do+ (distIJ, _) <- access (i,j)+ (distIK, pathIK) <- access (i,k)+ (distKJ, _) <- access (k,j)+ let indirectDist = distIK + distKJ+ when (distIJ > indirectDist+indirectDist*eps && distIJ > distIK && distIJ > distKJ) $+ put (i,j) (indirectDist, pathIK)+ where+ access idx = V.unsafeRead graph (mkIndex n idx)+ put idx e = V.unsafeWrite graph (mkIndex n idx) e+ eps = 1e-10 -- When two paths are nearly the same length, pick the one with the fewest segments.++-- | Compute the index of an element in a given range.+mkIndex :: Num a => a -> (a, a) -> a+mkIndex n (i,j) = i*n+j++-- | Construct a weighted graph from \(n\) vertices, a max bound, and a list of weighted edges.+mkGraph :: (Unbox a, Num a) => Int -> a -> [(Int,Int,a)] -> ST s (MVector s (a, Int))+mkGraph n maxValue edges = do+ graph <- V.replicate (n*n) (maxValue, maxBound)+ forM_ [0..n-1] $ \v -> do+ unsafeWrite graph (mkIndex n (v,v)) (0, v)+ forM_ edges $ \(i,j,cost) -> do+ unsafeWrite graph (mkIndex n (i,j)) (cost, j)+ unsafeWrite graph (mkIndex n (j,i)) (cost, i)+ return graph
src/Algorithms/Graph/DFS.hs view
@@ -1,14 +1,21 @@ {-# LANGUAGE ScopedTypeVariables #-}+--------------------------------------------------------------------------------+-- |+-- Module : Algorithms.Graph.DFS+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Algorithms.Graph.DFS where -import Control.Monad.ST (ST,runST)+import Control.Monad.ST (ST, runST) import Data.Maybe import Data.PlanarGraph import Data.Tree-import qualified Data.Vector as V-import qualified Data.Vector.Generic as GV+import qualified Data.Vector as V+import qualified Data.Vector.Generic as GV import qualified Data.Vector.Unboxed.Mutable as UMV-+import qualified Data.IntSet as IntSet -- | DFS on a planar graph. --@@ -51,3 +58,20 @@ False -> do visit bv u Just . Node u . catMaybes <$> mapM (dfs'' bv) (neighs u)++-- | DFS, from a given vertex, on a graph in AdjacencyLists representation. Cycles are not removed.+-- If your graph may contain cycles, see 'dfsFilterCycles'.+--+-- Running time: \(O(k)\), where \(k\) is the number of nodes consumed.+dfsSensitive :: forall s w. (VertexId s w -> [VertexId s w]) -> VertexId s w -> Tree (VertexId s w)+dfsSensitive neighs u = Node u $ map (dfsSensitive neighs) (neighs u)++-- | Remove infinite cycles from a DFS search tree.+dfsFilterCycles :: Tree (VertexId s w) -> Tree (VertexId s w)+dfsFilterCycles = worker IntSet.empty+ where+ worker seen (Node root forest) = Node root+ [ Node (VertexId v) (map (worker (IntSet.insert v seen)) sub)+ | Node (VertexId v) sub <- forest+ , v `IntSet.notMember` seen+ ]
src/Algorithms/Graph/MST.hs view
@@ -1,4 +1,11 @@ {-# LANGUAGE ScopedTypeVariables #-}+--------------------------------------------------------------------------------+-- |+-- Module : Algorithms.Graph.MST+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Algorithms.Graph.MST( mst , mstEdges , makeTree
src/Control/CanAquire.hs view
@@ -1,4 +1,11 @@ {-# LANGUAGE FunctionalDependencies #-}+--------------------------------------------------------------------------------+-- |+-- Module : Control.CanAquire+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Control.CanAquire( runAcquire , CanAquire(..)@@ -13,23 +20,24 @@ import Data.Reflection import qualified Data.Vector as V import qualified Data.Vector.Mutable as MV+import Unsafe.Coerce(unsafeCoerce) -------------------------------------------------------------------------------- -- | Run a computation on something that can aquire i's. runAcquire :: forall t a b. Traversable t- => (forall i. CanAquire i a => t i -> b)+ => (forall s. CanAquire (I s a) a => t (I s a) -> b) -> t a -> b runAcquire alg pts = reify v $ \px -> alg (coerceTS px ts) where (v,ts) = replaceByIndex pts coerceTS :: proxy s -> t Int -> t (I s a)- coerceTS _ = fmap I+ coerceTS _ = unsafeCoerce -- fmap I -- Ideally this would just be a coerce. But GHC doesn't want to do that. class HasIndex i Int => CanAquire i a where- -- | A value of type i can obtain something of type 'a'+ -- | A value of type i can obtain something of type @\'a\'@ aquire :: i -> a class HasIndex t i | t -> i where@@ -67,7 +75,7 @@ -------------------------------------------------------------------------------- -- | A type that can act as an Index.-newtype I s a = I Int deriving (Eq, Ord, Enum)+newtype I (s :: *) a = I Int deriving (Eq, Ord, Enum) instance Show (I s a) where showsPrec i (I j) = showsPrec i j@@ -75,5 +83,5 @@ instance HasIndex (I s a) Int where indexOf (I i) = i -instance Reifies s (V.Vector a) => (I s a) `CanAquire` a where+instance Reifies s (V.Vector a) => I s a `CanAquire` a where aquire (I i) = let v = reflect @s undefined in v V.! i
src/Control/Monad/State/Persistent.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Control.Monad.State.Persistent+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Control.Monad.State.Persistent( PersistentStateT , PersistentState , store@@ -32,7 +39,7 @@ put (s' :| os) return x --- | run a persistentStateT, returns a triplet with the value, the last state+-- | Run a persistentStateT, returns a triplet with the value, the last state -- and a list of all states (including the last one) in chronological order runPersistentStateT :: Functor m => PersistentStateT s m a -> s -> m (a,s,[s]) runPersistentStateT (PersistentStateT act) initS = f <$> runStateT act (initS :| [])@@ -42,7 +49,10 @@ -------------------------------------------------------------------------------- +-- | A State monad that can store earlier versions of the state. type PersistentState s = PersistentStateT s Identity +-- | Run a persistentStateT, returns a triplet with the value, the last state+-- and a list of all states (including the last one) in chronological order runPersistentState :: PersistentState s a -> s -> (a,s,[s]) runPersistentState act = runIdentity . runPersistentStateT act
src/Data/BinaryTree.hs view
@@ -119,11 +119,12 @@ -------------------------------------------------------------------------------- -- * Converting into a Data.Tree +-- | \( O(n) \) Convert binary tree to a rose tree, aka 'Tree.Tree'. toRoseTree :: BinLeafTree v a -> Tree.Tree (TreeNode v a) toRoseTree (Leaf x) = Tree.Node (LeafNode x) [] toRoseTree (Node l v r) = Tree.Node (InternalNode v) (map toRoseTree [l,r]) -+-- | 2-dimensional ASCII drawing of a tree. drawTree :: (Show v, Show a) => BinLeafTree v a -> String drawTree = Tree.drawTree . fmap show . toRoseTree
− src/Data/BinaryTree/Zipper.hs
@@ -1,64 +0,0 @@-module Data.BinaryTree.Zipper where--import Data.BinaryTree------------------------------------------------------------------------------------data Ctx a = Top | L (Ctx a) a (BinaryTree a) | R (BinaryTree a) a (Ctx a)- deriving (Show,Read,Eq,Ord,Functor,Foldable,Traversable)--data BinaryTreeZipper a = Loc (BinaryTree a) (Ctx a)- deriving (Show,Read,Eq,Ord,Functor,Foldable,Traversable)---- | Focus on the root-top :: BinaryTree a -> BinaryTreeZipper a-top t = Loc t Top---- | Go to the left child-left :: BinaryTreeZipper a -> Maybe (BinaryTreeZipper a)-left (Loc (Internal l x r) ctx) = Just $ Loc l (L ctx x r)-left (Loc Nil _) = Nothing---- | Go to the right child-right :: BinaryTreeZipper a -> Maybe (BinaryTreeZipper a)-right (Loc (Internal l x r) ctx) = Just $ Loc r (R l x ctx)-right (Loc Nil _) = Nothing---- | Move to the parent-up :: BinaryTreeZipper a -> Maybe (BinaryTreeZipper a)-up (Loc _ Top) = Nothing-up (Loc l (L ctx x r)) = Just $ Loc (Internal l x r) ctx-up (Loc r (R l x ctx)) = Just $ Loc (Internal l x r) ctx---- | Navigate to the root-toRoot :: BinaryTreeZipper a -> BinaryTreeZipper a-toRoot z = toRoot' z (Just z)- where- toRoot' z' Nothing = z'- toRoot' _ (Just z') = toRoot' z' (up z')----- | Returns a list of zippers; one focussed on each node in the tree-visitAll :: BinaryTree a -> [BinaryTreeZipper a]-visitAll t = visitAll' (top t)- where- f = maybe [] visitAll'- visitAll' z = z : f (left z) <> f (right z)---- | Get the value stored at the current node-accessZ :: BinaryTreeZipper a -> Maybe a-accessZ (Loc t _) = access t----- | Returns all subtrees; i.e. every node with all its decendents-subTrees :: BinaryTree a -> [BinaryTree a]-subTrees t = Nil : subTrees' t- where- subTrees' Nil = []- subTrees' tt@(Internal l _ r) = tt : subTrees' l <> subTrees' r----- | Splits the tree here, returns a pair (innerTree,outerTree)-splitTree :: BinaryTreeZipper a -> (BinaryTree a, BinaryTree a)-splitTree (Loc t ctx) = let (Loc r _) = toRoot $ Loc Nil ctx- in (t, r)
src/Data/CircularList/Util.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.CircularList.Util+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.CircularList.Util where import Control.Lens@@ -43,14 +50,14 @@ insertOrdBy' :: (a -> a -> Ordering) -> a -> [a] -> [a] insertOrdBy' cmp x xs = case (rest, x `cmp` head rest) of ([], _) -> L.insertBy cmp x pref- (z:zs, GT) -> (z : L.insertBy cmp x zs) ++ pref- (_:_, EQ) -> (x : xs) -- == x : rest ++ pref+ (z:zs, GT) -> z : L.insertBy cmp x zs ++ pref+ (_:_, EQ) -> x : xs -- == x : rest ++ pref (_:_, LT) -> rest ++ L.insertBy cmp x pref where -- split the list at its maximum. (pref,rest) = splitIncr cmp xs --- given a list of elements that is supposedly a a cyclic-shift of a list of+-- | Given a list of elements that is supposedly a a cyclic-shift of a list of -- increasing items, find the splitting point. I.e. returns a pair of lists -- (ys,zs) such that xs = zs ++ ys, and ys ++ zs is (supposedly) in sorted -- order.
src/Data/CircularSeq.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.CircularSeq+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.CircularSeq( CSeq , cseq , singleton@@ -15,6 +22,7 @@ , rightElements , leftElements , asSeq+ , withIndices , reverseDirection , allRotations@@ -32,18 +40,20 @@ import Algorithms.StringSearch.KMP (isSubStringOf) import Control.DeepSeq-import Control.Lens (lens, Lens', bimap)+import Control.Lens (Lens', bimap, lens)+import Data.Ext import qualified Data.Foldable as F import qualified Data.List as L import qualified Data.List.NonEmpty as NonEmpty-import Data.Maybe (listToMaybe, isJust)+import Data.Maybe (isJust) import Data.Semigroup.Foldable-import Data.Sequence ((|>),(<|),ViewL(..),ViewR(..),Seq)+import Data.Sequence (Seq, ViewL (..), ViewR (..), (<|),+ (|>)) import qualified Data.Sequence as S import qualified Data.Traversable as T import Data.Tuple (swap) import GHC.Generics (Generic)-import Test.QuickCheck(Arbitrary(..))+import Test.QuickCheck (Arbitrary (..)) import Test.QuickCheck.Instances () --------------------------------------------------------------------------------@@ -67,6 +77,11 @@ showString (("CSeq " <>) . show . F.toList . rightElements $ s) where app_prec = 10 +instance Read a => Read (CSeq a) where+ readsPrec d = readParen (d > app_prec) $ \r ->+ [ (fromList lst, t) | ("CSeq", s) <- lex r, (lst, t) <- reads s ]+ where app_prec = 10+ -- traverses starting at the focus, going to the right. instance T.Traversable CSeq where traverse f (CSeq l x r) = (\x' r' l' -> CSeq l' x' r')@@ -87,15 +102,18 @@ instance Arbitrary a => Arbitrary (CSeq a) where arbitrary = CSeq <$> arbitrary <*> arbitrary <*> arbitrary +-- | /O(1)/ CSeq with exactly one element. singleton :: a -> CSeq a singleton x = CSeq S.empty x S.empty --- | Gets the focus of the CSeq+-- | Gets the focus of the CSeq.+-- -- running time: O(1) focus :: CSeq a -> a focus (CSeq _ x _) = x --- | Access the i^th item (w.r.t the focus) in the CSeq (indices modulo n).+-- | Access the i^th item (w.r.t the focus; elements numbered in+-- increasing order towards the right) in the CSeq (indices modulo n). -- -- running time: \(O(\log (i \mod n))\) --@@ -120,6 +138,15 @@ else if i - 1 < rn then S.index r (i - 1) else S.index l (i - rn - 1) +-- | Label the elements with indices.+--+-- >>> withIndices $ fromList [0..5]+-- CSeq [0 :+ 0,1 :+ 1,2 :+ 2,3 :+ 3,4 :+ 4,5 :+ 5]+withIndices :: CSeq a -> CSeq (Int :+ a)+withIndices (CSeq l x r) = let s = 1 + length r in+ CSeq (S.mapWithIndex (\i y -> i + s :+ y) l) (0 :+ x) (S.mapWithIndex (\i y -> i+1 :+ y) r)++ -- | Adjusts the i^th element w.r.t the focus in the CSeq -- -- running time: \(O(\log (i \mod n))\)@@ -135,9 +162,9 @@ else CSeq (S.adjust f (i - rn - 1) l) x r --- | Access te ith item in the CSeq (w.r.t the focus) as a lens+-- | Access the ith item in the CSeq (w.r.t the focus) as a lens item :: Int -> Lens' (CSeq a) a-item i = lens (flip index i) (\s x -> adjust (const x) i s)+item i = lens (`index` i) (\s x -> adjust (const x) i s) resplit :: Seq a -> (Seq a, Seq a)@@ -194,8 +221,8 @@ rotateL :: CSeq a -> CSeq a rotateL s@(CSeq l x r) = case S.viewr l of EmptyR -> case S.viewr r of- EmptyR -> s- (r' :> y) -> cseq r' y (S.singleton x)+ EmptyR -> s+ (r' :> y) -> cseq r' y (S.singleton x) (l' :> y) -> cseq l' y (x <| r) @@ -223,6 +250,11 @@ fromNonEmpty :: NonEmpty.NonEmpty a -> CSeq a fromNonEmpty (x NonEmpty.:| xs) = withFocus x $ S.fromList xs +{- HLINT ignore fromList -}+-- | /O(n)/ Convert from a list to a CSeq.+--+-- Warning: the onus is on the user to ensure that their list+-- is not empty, otherwise all bets are off! fromList :: [a] -> CSeq a fromList (x:xs) = withFocus x $ S.fromList xs fromList [] = error "fromList: Empty list"@@ -266,7 +298,7 @@ S.EmptyR -> let (y :< r') = S.viewl r in cseq l' y r' --- | Reversres the direction of the CSeq+-- | Reverses the direction of the CSeq -- -- running time: \(O(n)\) --@@ -283,9 +315,9 @@ -- >>> findRotateTo (== 7) $ fromList [1..5] -- Nothing findRotateTo :: (a -> Bool) -> CSeq a -> Maybe (CSeq a)-findRotateTo p = listToMaybe . filter (p . focus) . allRotations'-+findRotateTo p = L.find (p . focus) . allRotations' +-- | Rotate to a specific element in the CSeq. rotateTo :: Eq a => a -> CSeq a -> Maybe (CSeq a) rotateTo x = findRotateTo (== x) @@ -354,8 +386,8 @@ insertOrdBy' :: (a -> a -> Ordering) -> a -> [a] -> [a] insertOrdBy' cmp x xs = case (rest, x `cmp` head rest) of ([], _) -> L.insertBy cmp x pref- (z:zs, GT) -> (z : L.insertBy cmp x zs) ++ pref- (_:_, EQ) -> (x : xs) -- == x : rest ++ pref+ (z:zs, GT) -> z : L.insertBy cmp x zs ++ pref+ (_:_, EQ) -> x : xs -- == x : rest ++ pref (_:_, LT) -> rest ++ L.insertBy cmp x pref where -- split the list at its maximum.
+ src/Data/Double/Approximate.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- | See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/+module Data.Double.Approximate+ ( SafeDouble+ , DoubleRelAbs(..)+ ) where++import Control.DeepSeq+import Data.Proxy+import GHC.TypeLits+import Numeric.MathFunctions.Comparison+import Numeric.MathFunctions.Constants+import System.Random+import Text.Read++-- | Relatively safe double floating-point type with a relative error+-- margin of 10 <https://en.wikipedia.org/wiki/Unit_in_the_last_place ULPs>+-- and an absolute margin around zero of+-- @10*<https://en.wikipedia.org/wiki/Machine_epsilon epsilon>@.+--+-- Warning: All numbers within+-- @10*<https://en.wikipedia.org/wiki/Machine_epsilon epsilon>@ of zero will be considered zero.+--+-- >>> m_epsilon * 10+-- 2.220446049250313e-15+--+-- >>> realToFrac (m_epsilon * 10) == (0::SafeDouble)+-- False+--+-- >>> realToFrac (m_epsilon * 9) == (0::SafeDouble)+-- True+--+-- >>> 1e-20 == (5e-20 :: Double)+-- False+-- >>> 1e-20 == (5e-20 :: SafeDouble)+-- True+--+-- 'pi' and 'sin' are approximations:+--+-- >>> sin pi+-- 1.2246467991473532e-16+--+-- >>> sin pi == (0 :: Double)+-- False+--+-- >>> sin pi == (0 :: SafeDouble)+-- True+--+type SafeDouble = DoubleRelAbs 10 10++-- | Custom double floating-point type with a relative error margin of+-- @rel@ number of+-- <https://en.wikipedia.org/wiki/Unit_in_the_last_place ULPs> and an+-- absolute error margin of @abs@ times+-- <https://en.wikipedia.org/wiki/Machine_epsilon epsilon>.+--+-- The relative error margin is the primary tool for good numerical+-- robustness and can relatively safely be set to a high number such+-- as 100. The absolute error margin is a last ditch attempt at fixing+-- broken algorithms and dramatically limits the resolution around zero.+-- If possible, use a low absolute error margin.+newtype DoubleRelAbs (abs :: Nat) (rel :: Nat) = DoubleRelAbs Double+ deriving (Num, Enum, Floating, Fractional, Real, RealFloat, RealFrac, Random, NFData)++instance (KnownNat abs, KnownNat rel) => Eq (DoubleRelAbs abs rel) where+ DoubleRelAbs d1 == DoubleRelAbs d2 =+ within (fromIntegral (natVal @rel Proxy)) d1 d2 ||+ (abs d1 < m_epsilon * fromIntegral (natVal @abs Proxy) &&+ abs d2 < m_epsilon * fromIntegral (natVal @abs Proxy))++instance (KnownNat abs, KnownNat rel) => Ord (DoubleRelAbs abs rel) where+ lhs@(DoubleRelAbs d1) `compare` rhs@(DoubleRelAbs d2)+ | lhs == rhs = EQ+ | otherwise = d1 `compare` d2++instance Show (DoubleRelAbs abs rel) where+ showsPrec i (DoubleRelAbs d) = showsPrec i d++instance Read (DoubleRelAbs abs rel) where+ readPrec = DoubleRelAbs <$> readPrec+
+ src/Data/Double/Shaman.hs view
@@ -0,0 +1,295 @@+-- https://tel.archives-ouvertes.fr/tel-03116750/document+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RecordWildCards #-}+module Data.Double.Shaman+ ( Shaman+ , significativeBits+ , significativeDigits+ , SDouble+ ) where++import Numeric.MathFunctions.Comparison ( addUlps)+import Numeric.MathFunctions.Constants+import GHC.TypeLits+import Data.Double.Approximate++-- | Double-precision floating point numbers that throw exceptions if+-- the accumulated errors grow large enough to cause unstable branching.+--+-- If @SDouble n@ works without throwing any exceptions, it'll be safe to+-- use @DoubleRelAbs n 0@ instead for a sizable performance boost.+--+-- >>> sin pi == (0 :: SDouble 0)+-- *** Exception: Insufficient precision.+-- ...+--+-- @SDouble 0@ failed so @DoubleRelAbs 0 0@ will lead to an unstable branch. In+-- other words, it'll return @False@ when it should have returned @True@:+--+-- >>> sin pi == (0 :: DoubleRelAbs 0 0)+-- False+--+-- Comparing to within 1 ULP stabalizes the branch:+--+-- >>> sin pi == (0 :: SDouble 1)+-- True+--+-- >>> sin pi == (0 :: DoubleRelAbs 1 0)+-- True+--+newtype SDouble (n::Nat) = SDouble Shaman+ deriving (Num, Fractional, Floating, Real, RealFrac, RealFloat)++instance Show (SDouble n) where+ showsPrec d (SDouble s) = showsPrec d s++instance Read (SDouble n) where+ readsPrec d inp = [ (SDouble v, r) | (v, r) <- readsPrec d inp ]+++-- shamanUlpDistance :: Shaman -> Word64+-- shamanUlpDistance (Shaman n e) = ulpDistance n (n+e)++compareSDouble :: KnownNat n => SDouble n -> SDouble n -> Ordering+compareSDouble a@(SDouble a') b@(SDouble b')+ | a == b = EQ+ | otherwise = shamanValue a' `compare` shamanValue b'++toDoubleRelAbs :: SDouble n -> DoubleRelAbs n 0+toDoubleRelAbs (SDouble (Shaman v _e)) = DoubleRelAbs v++-- If (a :: DoubleRelAbs n 0) == (b :: DoubleRelAbs n 0)+instance KnownNat n => Eq (SDouble n) where+ a@(SDouble a') == b@(SDouble b')+ | blessedResult == approxResult = blessedResult+ | otherwise = error "Insufficient precision."+ where+ blessedResult = a' == b'+ approxResult = toDoubleRelAbs a == toDoubleRelAbs b++instance KnownNat n => Ord (SDouble n) where+ compare = compareSDouble++++++-- | Double-precision floating point numbers with error-bounds.+--+-- Some digits can be represented exactly and have essentially an infinitely number of significant digits:+--+-- >>> significativeDigits 1+-- Infinity+--+-- Some fractional numbers can also be represented exactly:+--+-- >>> significativeDigits 0.5+-- Infinity+--+-- Other numbers are merely approximations:+--+-- >>> significativeDigits 0.1+-- 16.255619765854984+--+-- Pi is an irrational number so we can't represent it with infinite precision:+--+-- >>> significativeDigits pi+-- 15.849679651557175+--+-- @sin pi@ should theoretically be zero but we cannot do better than saying it is near zero:+--+-- >>> sin pi+-- 1.2246467991473532e-16+--+-- The error margins are greater than value itself so we have no significant digits:+--+-- >>> significativeDigits (sin pi)+-- 0.0+--+-- Since 'near zero' is not zero, the following fails when using Doubles:+--+-- >>> sin pi == (0 :: Double)+-- False+--+-- Equality testing for Shaman numbers tests whether the two intervals+-- overlap:+--+-- >>> sin pi == (0 :: Shaman)+-- True+data Shaman = Shaman+ { shamanValue :: {-# UNPACK #-} !Double+ , shamanError :: {-# UNPACK #-} !Double+ }++instance Show Shaman where+ showsPrec d Shaman{..} = showParen (d > 10) $+ shows shamanValue . showChar '±' . shows shamanError++instance Read Shaman where+ readsPrec d = readParen (d > app_prec) $ \r ->+ [ (Shaman{..}, t')+ | (shamanValue, '±':t) <- reads r+ , (shamanError, t') <- reads t]+ where app_prec = 10++-- | Number of significant bits (base 2).+significativeBits :: Shaman -> Double+significativeBits v = significativeValue v / log 2++-- | Number of significant digits (base 10).+significativeDigits :: Shaman -> Double+significativeDigits v = significativeValue v / log 10++significativeValue :: Shaman -> Double+significativeValue (Shaman v e)+ | e == 0 = m_pos_inf+ | isNaN e = 0+ | v == 0 = max 0 (log (abs e - 1))+ | otherwise =+ let relError = abs (e / v) in+ if relError >= 1+ then 0+ else negate $ log relError++instance Num Shaman where+ Shaman x dx + Shaman y dy =+ case x+y of+ !xy -> Shaman xy (dx+dy+twoSum x y xy)++ Shaman x dx * Shaman y dy =+ case x*y of+ !z -> Shaman z (dx * y + dy * x + fma x y (-z))+ + abs (Shaman x dx) = Shaman (abs x) dx++ signum (Shaman x dx) = Shaman (signum x) dx++ negate (Shaman x dx) = Shaman (negate x) dx++ fromInteger i =+ let d = fromInteger i+ in Shaman d (abs $ realToFrac $ i - round d)++instance Fractional Shaman where+ Shaman x dx / Shaman y dy =+ let z = x/y+ numerator = dx - fma y z (-x) - z * dy+ denominator = y + dy+ in Shaman z (numerator / denominator)+ fromRational r =+ let d = fromRational r+ in Shaman d (abs $ realToFrac $ r - realToFrac d)++instance Floating Shaman where+ pi = Shaman pi (addUlps 1 pi - pi)+ sqrt (Shaman x dx)+ | z == 0, dx == 0 =+ Shaman z 0+ | z == 0 =+ Shaman z (sqrt (abs dx)) -- FIXME: Use long double.+ | otherwise =+ Shaman z ((r + dx) / (z+z))+ where+ r = negate $ fma z z (negate x)+ z = sqrt x+ log = foreignOp erf_log log+ exp = foreignOp erf_exp exp+ (**) = foreignBinOp erf_pow (**)+ sin = foreignOp erf_sin sin+ cos = foreignOp erf_cos cos+ tan = foreignOp erf_tan tan+ asin = foreignOp erf_asin asin+ acos = foreignOp erf_acos acos+ atan = foreignOp erf_atan atan+ sinh = foreignOp erf_sinh sinh+ cosh = foreignOp erf_cosh cosh+ tanh = foreignOp erf_tanh tanh+ asinh = foreignOp erf_asinh asinh+ acosh = foreignOp erf_acosh acosh+ atanh = foreignOp erf_atanh atanh++instance Real Shaman where+ toRational (Shaman v _) = toRational v++instance RealFrac Shaman where+ properFraction (Shaman v e) =+ case properFraction v of+ (i, v') -> (i, Shaman v' e)+ truncate (Shaman v _e) = truncate v+ round (Shaman v _e) = round v+ ceiling (Shaman v e) = ceiling (v+e)+ floor (Shaman v e) = floor (v-e)++instance RealFloat Shaman where+ floatRadix = floatRadix . shamanValue+ floatDigits = floatDigits . shamanValue+ floatRange = floatRange . shamanValue+ decodeFloat = decodeFloat . shamanValue+ encodeFloat m e = Shaman (encodeFloat m e) 0 -- FIXME: 1 ULP error bound?+ exponent = exponent . shamanValue+ significand s = Shaman (significand $ shamanValue s) 0+ scaleFloat p (Shaman v e) = Shaman (scaleFloat p v) e+ isNaN = isNaN . shamanValue+ isInfinite = isInfinite . shamanValue+ isDenormalized = isDenormalized . shamanValue+ isNegativeZero = isNegativeZero . shamanValue+ isIEEE = isIEEE . shamanValue+ atan2 = foreignBinOp erf_atan2 atan2+++instance Eq Shaman where+ x == y = compareShaman x y == EQ++instance Ord Shaman where+ compare = compareShaman++-- Returns EQ iff the two numbers overlap.+compareShaman :: Shaman -> Shaman -> Ordering+compareShaman (Shaman x dx) (Shaman y dy)+ | abs (x-y) < abs dx+ abs dy = EQ+ | x < y = LT+ | otherwise = GT++twoSum :: Double -> Double -> Double -> Double+twoSum x y xy = abs (x-x') + abs (y-y')+ where+ x' = xy-y+ y' = xy-x++foreignOp :: (Double -> Double -> Double -> Double) -> (Double -> Double) -> Shaman -> Shaman+foreignOp mkDelta fn (Shaman x dx) =+ let !z = fn x+ in Shaman z (abs $ mkDelta x dx z)++foreignBinOp ::+ (Double -> Double -> Double -> Double -> Double -> Double) ->+ (Double -> Double -> Double) ->+ Shaman -> Shaman -> Shaman+foreignBinOp mkDelta fn (Shaman x dx) (Shaman y dy) =+ let !z = fn x y+ in Shaman z (mkDelta x dx y dy z)++foreign import ccall unsafe "fma" fma :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_log" erf_log :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_exp" erf_exp :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_pow" erf_pow :: Double -> Double -> Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_sin" erf_sin :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_cos" erf_cos :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_tan" erf_tan :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_asin" erf_asin :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_acos" erf_acos :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_atan" erf_atan :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_sinh" erf_sinh :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_cosh" erf_cosh :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_tanh" erf_tanh :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_asinh" erf_asinh :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_acosh" erf_acosh :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_atanh" erf_atanh :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_atan2" erf_atan2 :: Double -> Double -> Double -> Double -> Double -> Double
src/Data/DynamicOrd.hs view
@@ -1,4 +1,11 @@ {-# LANGUAGE UndecidableInstances #-}+--------------------------------------------------------------------------------+-- |+-- Module : Data.DynamicOrd+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.DynamicOrd where import Data.Proxy@@ -10,7 +17,7 @@ -- Implementation from -- https://www.schoolofhaskell.com/user/thoughtpolice/using-reflection --- | Values of type 'a' in our dynamically constructed 'Ord' instance+-- | Values of type '@a@' in our dynamically constructed 'Ord' instance newtype O (s :: *) (a :: *) = O { runO :: a } deriving (Show) -- | An Ord Dictionary@@ -37,35 +44,35 @@ -- * Introducing and removing the dynamic order type -- Note that all of these may be unsafe if used incorrectly --- | Lifts a container f whose values (of type a) depend on 's' into a--- more general computation in that produces a 'f a' (depending on s).+-- | Lifts a container f whose values (of type a) depend on '@s@' into a+-- more general computation in that produces a '@f a@' (depending on s). -- -- running time: \(O(1)\) extractOrd1 :: f (O s a) -> O s (f a) extractOrd1 = unsafeCoerce --- | Introduce dynamic order in a container 'f'.+-- | Introduce dynamic order in a container '@f@'. -- -- running time: \(O(1)\) introOrd1 :: f a -> f (O s a) introOrd1 = unsafeCoerce --- | Lifts a function that works on a container 'f' of+-- | Lifts a function that works on a container '@f@' of -- orderable-things into one that works on dynamically ordered ones.-liftOrd1 :: (f (O s a) -> f (O s a))- -> f a -> O s (f a)+liftOrd1 :: (f (O s a) -> g (O s a))+ -> f a -> O s (g a) liftOrd1 f = extractOrd1 . f . introOrd1 --- | Lifts a container f whose keys (of type k) depend on 's' into a--- more general computation in that produces a 'f k v' (depending on s).+-- | Lifts a container f whose keys (of type k) depend on '@s@' into a+-- more general computation in that produces a @`f k v`@ (depending on s). -- -- running time: \(O(1)\) extractOrd2 :: f (O s k) v -> O s (f k v) extractOrd2 = unsafeCoerce --- | Introduce dynamic order in a container 'f' that has keys of type+-- | Introduce dynamic order in a container '@f@' that has keys of type -- k. -- -- running time: \(O(1)\)
src/Data/Ext.hs view
@@ -74,22 +74,27 @@ instance (Arbitrary c, Arbitrary e) => Arbitrary (c :+ e) where arbitrary = (:+) <$> arbitrary <*> arbitrary +-- | Access the core of an extended value. _core :: (core :+ extra) -> core _core (c :+ _) = c {-# INLINABLE _core #-} +-- | Access the extra part of an extended value. _extra :: (core :+ extra) -> extra _extra (_ :+ e) = e {-# INLINABLE _extra #-} +-- | Lens access to the core of an extended value. core :: Lens (core :+ extra) (core' :+ extra) core core'-core = lens _core (\(_ :+ e) c -> (c :+ e))+core = lens _core (\(_ :+ e) c -> c :+ e) {-# INLINABLE core #-} +-- | Lens access to the extra part of an extended value. extra :: Lens (core :+ extra) (core :+ extra') extra extra'-extra = lens _extra (\(c :+ _) e -> (c :+ e))+extra = lens _extra (\(c :+ _) e -> c :+ e) {-# INLINABLE extra #-} +-- | Tag a value with the unit type. ext :: a -> a :+ () ext x = x :+ () {-# INLINABLE ext #-}
+ src/Data/Ext/Multi.hs view
@@ -0,0 +1,62 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.Ext+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+--+-- A pair-like data type to represent a 'core' type that has extra information+-- as well.+--+--------------------------------------------------------------------------------+module Data.Ext.Multi where++import Control.DeepSeq+import Control.Lens+import Data.Coerce+import Data.Vinyl+import GHC.Generics (Generic)+import Test.QuickCheck++--------------------------------------------------------------------------------++data family core :+ (extras :: [*]) :: *++newtype instance core :+ '[] = Only core deriving (Eq,Ord,NFData,Arbitrary,Generic,Show)+data instance core :+ (t:ts) = WithExtra !core (HList (t:ts))+++infixr 1 :+++pattern (:+) :: c -> HList (e:extras) -> c :+ (e:extras)+pattern c :+ r = WithExtra c r+{-# COMPLETE (:+) #-}++ext :: c -> c :+ '[]+ext = Only++--------------------------------------------------------------------------------++class HasCore extras where+ core :: Lens (core :+ extras) (core' :+ extras) core core'++instance HasCore '[] where+ core = lens coerce (const coerce)+instance HasCore (t:ts) where+ core = lens (\(c :+ _) -> c) (\(_ :+ r) c -> c :+ r)++--------------------------------------------------------------------------------++class HasExtras extras extras' where+ extra :: Lens (core :+ extras) (core :+ extras') (HList extras) (HList extras')++instance HasExtras '[] '[] where+ extra = lens (const RNil) const+instance HasExtras '[] (t:ts) where+ extra = lens (const RNil) (\(Only c) r -> c :+ r)+instance HasExtras (t:ts) '[] where+ extra = lens (\(_ :+ r) -> r) (\(c :+ _) _ -> Only c)+instance HasExtras (t:ts) (a:as) where+ extra = lens (\(_ :+ r) -> r) (\(c :+ _) r' -> c :+ r')++--------------------------------------------------------------------------------
src/Data/IndexedDoublyLinkedList.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.IndexedDoublyLinkedList+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.IndexedDoublyLinkedList( DLList(..) , Cell(..), emptyCell , DLListMonad, runDLListMonad@@ -26,6 +33,7 @@ -------------------------------------------------------------------------------- +-- | Cell indices. Must be non-negative. type Index = Int -- TODO: Switch to unobxed sums for these!@@ -35,6 +43,7 @@ , next :: Maybe Index } deriving (Show,Eq) +-- | Empty cell with no next or prev cells. emptyCell :: Cell emptyCell = Cell Nothing Nothing @@ -63,7 +72,7 @@ instance MonadReader (DLList s b) (DLListMonad s b) where local f = DLListMonad . local f . runDLListMonad'- ask = DLListMonad $ ask+ ask = DLListMonad ask -- | Runs a DLList Computation, starting with singleton values, crated -- from the input vector.@@ -121,6 +130,7 @@ toListFromR :: Index -> DLListMonad s b (NonEmpty Index) toListFromR i = (i :|) <$> iterateM getPrev i +-- | Takes the current element and its k prev's toListFromRK :: Index -> Int -> DLListMonad s b (NonEmpty Index) toListFromRK i k = (i :|) <$> replicateM k getPrev i
src/Data/IndexedDoublyLinkedList/Bare.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.IndexedDoublyLinkedList.Bare+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.IndexedDoublyLinkedList.Bare( IDLList(..) , Cell(..), emptyCell@@ -27,6 +34,7 @@ -------------------------------------------------------------------------------- +-- | Cell indices. Must be non-negative. type Index = Int -- | Cells in the Linked List@@ -34,6 +42,7 @@ , next :: !(Maybe Index) } deriving (Show,Eq) +-- | Empty cell with no next or prev cells. emptyCell :: Cell emptyCell = Cell Nothing Nothing @@ -56,7 +65,7 @@ instance MonadReader (IDLList s) (IDLListMonad s) where local f = IDLListMonad . local f . runIDLListMonad'- ask = IDLListMonad $ ask+ ask = IDLListMonad ask -- | Runs a DLList Computation, starting with n singleton values runIDLListMonad :: Int -> (forall s. IDLListMonad s a) -> a@@ -109,6 +118,7 @@ toListFromR :: Index -> IDLListMonad s (NonEmpty Index) toListFromR i = (i :|) <$> iterateM getPrev i +-- | Takes the current element and its k prev's toListFromRK :: Index -> Int -> IDLListMonad s (NonEmpty Index) toListFromRK i k = (i :|) <$> replicateM k getPrev i @@ -184,5 +194,4 @@ -- | For debugging purposes, dump the values and the cells dump :: IDLListMonad s (V.Vector Cell) dump = do IDLList cs <- ask- cs' <- V.freeze cs- pure cs'+ V.freeze cs
src/Data/Intersection.hs view
@@ -35,6 +35,7 @@ coRec :: (a ∈ as) => a -> CoRec Identity as coRec = CoRec . Identity +-- | Class relationship between intersectable geometric objects. class IsIntersectableWith g h where intersect :: g -> h -> Intersection g h
src/Data/LSeq.hs view
@@ -9,7 +9,7 @@ -- Description : Wrapper around Data.Sequence with type level length annotation. -- ---------------------------------------------------------------------------------module Data.LSeq( LSeq+module Data.LSeq( LSeq( EmptyL, (:<|), (:<<), (:|>) ) , toSeq , empty , fromList@@ -32,14 +32,9 @@ , ViewL(..) , viewl- , pattern (:<|) - , pattern (:<<)- , pattern EmptyL- , ViewR(..) , viewr- , pattern (:|>) , zipWith @@ -79,6 +74,7 @@ deriving (Show,Read,Eq,Ord,Foldable,Functor,Traversable ,Generic,NFData) +-- | \( O(1) \) Convert to a sequence by dropping the type-level size. toSeq :: LSeq n a -> S.Seq a toSeq (LSeq s) = s @@ -107,29 +103,42 @@ | otherwise = pure s instance (1 <= n) => Foldable1 (LSeq n)--- instance (1 <= n) => Traversable1 (LSeq n) where--- traverse1 f s = case traverse1 f $ viewl s of--- x :< s' -> x <| s'-+instance (1 <= n) => Traversable1 (LSeq n) where+ traverse1 f (LSeq xs) = case runMaybeApply $ traverse (MaybeApply . Left . f) xs of+ Left xs' -> LSeq <$> xs'+ Right _ -> error "Data.LSeq.traverse1: impossible" +-- | \( O(1) \) The empty sequence. empty :: LSeq 0 a empty = LSeq S.empty +-- | \( O(1) \) Add an element to the left end of a sequence.+-- Mnemonic: a triangle with the single element at the pointy end. (<|) :: a -> LSeq n a -> LSeq (1 + n) a x <| xs = LSeq (x S.<| toSeq xs) +-- | \( O(1) \) Add an element to the right end of a sequence.+-- Mnemonic: a triangle with the single element at the pointy end. (|>) :: LSeq n a -> a -> LSeq (1 + n) a xs |> x = LSeq (toSeq xs S.|> x) infixr 5 <| infixl 5 |> +-- | \( O(log(min(n,m))) \) Concatenate two sequences. (><) :: LSeq n a -> LSeq m a -> LSeq (n + m) a xs >< ys = LSeq (toSeq xs <> toSeq ys) infix 5 >< -+-- | \( O(1) \) Prove a sequence has at least @n@ elements.+--+-- >>> eval (Proxy :: Proxy 3) (fromList [1,2,3])+-- Just (LSeq (fromList [1,2,3]))+-- >>> eval (Proxy :: Proxy 3) (fromList [1,2])+-- Nothing+-- >>> eval (Proxy :: Proxy 3) (fromList [1..10])+-- Just (LSeq (fromList [1,2,3,4,5,6,7,8,9,10])) eval :: forall proxy n m a. KnownNat n => proxy n -> LSeq m a -> Maybe (LSeq n a) eval n (LSeq xs) | toInteger (S.length xs) >= natVal n = Just $ LSeq xs@@ -163,37 +172,59 @@ -- | appends two sequences. -- append :: LSeq n a -> LSeq m a -> LSeq (n + m) a-sa `append` sb = LSeq $ (toSeq sa) <> toSeq sb+sa `append` sb = LSeq $ toSeq sa <> toSeq sb -------------------------------------------------------------------------------- --- | get the element with index i, counting from the left and starting at 0.--- O(log(min(i,n-i)))+-- | \( O(log(min(i,n-i))) \)+-- Get the element with index i, counting from the left and starting at 0. index :: LSeq n a -> Int -> a index s i = s^?!ix i +-- | \( O(log(min(i,n−i))) \) Update the element at the specified position. If the+-- position is out of range, the original sequence is returned. adjust can lead+-- to poor performance and even memory leaks, because it does not force the new+-- value before installing it in the sequence. adjust' should usually be preferred. adjust :: (a -> a) -> Int -> LSeq n a -> LSeq n a adjust f i s = s&ix i %~ f -+-- | \( O(n) \) The partition function takes a predicate p and a sequence xs and+-- returns sequences of those elements which do and do not satisfy the predicate. partition :: (a -> Bool) -> LSeq n a -> (LSeq 0 a, LSeq 0 a) partition p = bimap LSeq LSeq . S.partition p . toSeq +-- | A generalization of 'fmap', 'mapWithIndex' takes a mapping+-- function that also depends on the element's index, and applies it to every+-- element in the sequence. mapWithIndex :: (Int -> a -> b) -> LSeq n a -> LSeq n b mapWithIndex f = wrapUnsafe (S.mapWithIndex f) +-- | \( O(\log(\min(i,n-i))) \). The first @i@ elements of a sequence.+-- If @i@ is negative, @'take' i s@ yields the empty sequence.+-- If the sequence contains fewer than @i@ elements, the whole sequence+-- is returned. take :: Int -> LSeq n a -> LSeq 0 a take i = wrapUnsafe (S.take i) +-- | \( O(\log(\min(i,n-i))) \). Elements of a sequence after the first @i@.+-- If @i@ is negative, @'drop' i s@ yields the whole sequence.+-- If the sequence contains fewer than @i@ elements, the empty sequence+-- is returned. drop :: Int -> LSeq n a -> LSeq 0 a drop i = wrapUnsafe (S.drop i) -+-- | \( O(n \log n) \). A generalization of 'unstableSort', 'unstableSortBy'+-- takes an arbitrary comparator and sorts the specified sequence.+-- The sort is not stable. This algorithm is frequently faster and+-- uses less memory than 'Data.Sequence.sortBy'. unstableSortBy :: (a -> a -> Ordering) -> LSeq n a -> LSeq n a unstableSortBy f = wrapUnsafe (S.unstableSortBy f) +-- | \( O(n \log n) \). 'unstableSort' sorts the specified 'LSeq' by+-- the natural ordering of its elements, but the sort is not stable.+-- This algorithm is frequently faster and uses less memory than 'Data.Sequence.sort'. unstableSort :: Ord a => LSeq n a -> LSeq n a-unstableSort = wrapUnsafe (S.unstableSort)+unstableSort = wrapUnsafe S.unstableSort wrapUnsafe :: (S.Seq a -> S.Seq b) -> LSeq n a -> LSeq m b@@ -201,18 +232,22 @@ -------------------------------------------------------------------------------- +-- | \( O(n) \). Create an l-sequence from a sequence of elements. fromSeq :: S.Seq a -> LSeq 0 a fromSeq = LSeq +-- | \( O(n) \). Create an l-sequence from a finite list of elements. fromList :: Foldable f => f a -> LSeq 0 a fromList = LSeq . S.fromList . F.toList +-- | \( O(n) \). Create an l-sequence from a non-empty list. fromNonEmpty :: NonEmpty.NonEmpty a -> LSeq 1 a fromNonEmpty = LSeq . S.fromList . F.toList -------------------------------------------------------------------------------- +-- | View of the left end of a sequence. data ViewL n a where (:<) :: a -> LSeq n a -> ViewL (1 + n) a @@ -242,7 +277,7 @@ instance Ord a => Ord (ViewL n a) where s `compare` s' = F.toList s `compare` F.toList s' -+-- | \( O(1) )\. Analyse the left end of a sequence. viewl :: LSeq (1 + n) a -> ViewL (1 + n) a viewl xs = let ~(x S.:< ys) = S.viewl $ toSeq xs in x :< LSeq ys @@ -251,6 +286,8 @@ infixr 5 :<| +-- | A bidirectional pattern synonym viewing the front of a non-empty+-- sequence. pattern (:<|) :: a -> LSeq n a -> LSeq (1 + n) a pattern x :<| xs <- (viewl' -> (x,xs)) -- we need the coerce unfortunately where@@ -261,9 +298,12 @@ infixr 5 :<< +-- | A unidirectional pattern synonym viewing the front of a non-empty+-- sequence. pattern (:<<) :: a -> LSeq 0 a -> LSeq n a pattern x :<< xs <- (viewLSeq -> Just (x,xs)) +-- | The empty sequence. pattern EmptyL :: LSeq n a pattern EmptyL <- (viewLSeq -> Nothing) @@ -275,6 +315,7 @@ -------------------------------------------------------------------------------- +-- | View of the right end of a sequence. data ViewR n a where (:>) :: LSeq n a -> a -> ViewR (1 + n) a @@ -295,6 +336,7 @@ instance Ord a => Ord (ViewR n a) where s `compare` s' = F.toList s `compare` F.toList s' +-- | \( O(1) \). Analyse the right end of a sequence. viewr :: LSeq (1 + n) a -> ViewR (1 + n) a viewr xs = let ~(ys S.:> x) = S.viewr $ toSeq xs in LSeq ys :> x @@ -303,6 +345,8 @@ infixl 5 :|> +-- | A bidirectional pattern synonym viewing the rear of a non-empty+-- sequence. pattern (:|>) :: forall n a. LSeq n a -> a -> LSeq (1 + n) a pattern xs :|> x <- (viewr' -> (xs,x)) where
src/Data/List/Alternating.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.List.Alternating+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.List.Alternating( Alternating(..) , withNeighbours@@ -15,7 +22,7 @@ -------------------------------------------------------------------------------- --- | A (non-empty) alternating list of a's and b's+-- | A (non-empty) alternating list of @a@\'s and @b@\'s data Alternating a b = Alternating a [b :+ a] deriving (Show,Eq,Ord) instance Bifunctor Alternating where@@ -32,12 +39,12 @@ -- [(0,'a' :+ 1),(1,'b' :+ 2),(2,'c' :+ 3)] withNeighbours :: Alternating a b -> [(a,b :+ a)] withNeighbours (Alternating a0 xs) = let as = a0 : map (^.extra) xs- in zipWith (\a ba -> (a,ba)) as xs+ in zip as xs -- | Generic merging scheme that merges two Alternatings and applies--- the function 'f', with the current/new value at every event. So+-- the function '@f@', with the current/new value at every event. So -- note that if the alternating consists of 'Alternating a0 [t1 :+ -- a1]' then the function is applied to a1, not to a0 (i.e. every -- value ai is considered alive on the interval [ti,t(i+1))@@ -65,7 +72,7 @@ -- | Adds additional t-values in the alternating, (in sorted order). I.e. if we insert a--- "breakpoint" at time t the current 'a' value is used at that time.+-- "breakpoint" at time t the current '@a@' value is used at that time. -- -- >>> insertBreakPoints [0,2,4,6,8,10] $ Alternating "a" [3 :+ "c", 5 :+ "e", 7 :+ "g"] -- Alternating "a" [0 :+ "a",2 :+ "a",3 :+ "c",4 :+ "c",5 :+ "e",6 :+ "e",7 :+ "g",8 :+ "g",10 :+ "g"]@@ -82,5 +89,5 @@ reverse p@(Alternating s xs) = case xs of [] -> p ((e1 :+ _):tl) -> let ys = (e1 :+ s) : List.zipWith (\(_ :+ v) (e :+ _) -> e :+ v) xs tl- t = (last xs)^.extra+ t = last xs ^. extra in Alternating t (List.reverse ys)
src/Data/List/Set.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.List.Set+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.List.Set( Set, singleton , insert, delete , union, intersection, difference@@ -8,9 +15,9 @@ -------------------------------------------------------------------------------- --- | A Set of 'a's, implemented using a simple list. The only+-- | A Set of @a@\'s, implemented using a simple list. The only -- advantage of this implementation over 'Data.Set' from containers is--- that most operations require only 'Eq a' rather than 'Ord a'.+-- that most operations require only @'Eq a'@ rather than @'Ord a'@. newtype Set a = Set { toList :: [a] } deriving (Show,Read,Functor,Foldable,Traversable) @@ -28,22 +35,20 @@ singleton :: a -> Set a singleton x = Set [x] --- | Inserts an element in the set------ running time: \(O(n)\)+-- | \(O(n)\) Inserts an element in the set insert :: Eq a => a -> Set a -> Set a insert x s@(Set xs) | x `elem` s = s | otherwise = Set (x:xs) +-- | \( O(n^2) \) Insert an element in a set. insertAll :: Eq a => [a] -> Set a -> Set a insertAll xs s = List.foldl' (flip insert) s xs +-- | \( O(n^2) \) Create a set from a finite list of elements. fromList :: Eq a => [a] -> Set a fromList = flip insertAll mempty --- | Deletes an element from the set------ running time: \(O(n)\)+-- | \(O(n)\) Deletes an element from the set delete :: Eq a => a -> Set a -> Set a delete x (Set xs) = Set $ go xs where@@ -52,20 +57,14 @@ (y:ys) | x == y -> ys -- found the element, no need to continue looking | otherwise -> y:go ys --- | Computes the union of two sets------ running time: \(O(n^2)\)+-- | \(O(n^2)\) Computes the union of two sets union :: Eq a => Set a -> Set a -> Set a union = (<>) --- | Computes the intersection of two sets------ running time: \(O(n^2)\)+-- | \(O(n^2)\) Computes the intersection of two sets intersection :: Eq a => Set a -> Set a -> Set a (Set xs) `intersection` (Set ys) = Set (xs `List.intersect` ys) --- | Computes the difference of two sets------ running time: \(O(n^2)\)+-- | \(O(n^2)\) Computes the difference of two sets difference :: Eq a => Set a -> Set a -> Set a (Set xs) `difference` (Set ys) = Set $ xs List.\\ ys
src/Data/List/Util.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.List.Util+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.List.Util where import Data.Bifunctor@@ -26,35 +33,60 @@ -- >>> leaveOutOne [1] -- [(1,[])] leaveOutOne :: [a] -> [(a,[a])]-leaveOutOne xs = (second F.toList . fromJust . extractNext)+leaveOutOne xs = second F.toList . fromJust . extractNext <$> allNonEmptyNexts (Zipper.fromList xs) -------------------------------------------------------------------------------- -- * Improved functions for minima and maxima +-- | Safe variant of Prelude.minimum.+--+-- >>> minimum1 [] :: Maybe ()+-- Nothing+-- >>> minimum1 [1,2,3]+-- Just 1 minimum1 :: Ord a => [a] -> Maybe a minimum1 = minimum1By compare +-- | Safe variant of Prelude.maximum.+--+-- >>> maximum1 [] :: Maybe ()+-- Nothing+-- >>> maximum1 [1,2,3]+-- Just 3 maximum1 :: Ord a => [a] -> Maybe a maximum1 = minimum1By (flip compare) +-- | Total variant of Data.List.minimumBy.+--+-- >>> minimum1By (comparing abs) [] :: Maybe Int+-- Nothing+-- >>> minimum1By (comparing abs) [1,-2,3]+-- Just 1 minimum1By :: (a -> a -> Ordering) -> [a] -> Maybe a minimum1By cmp = \case [] -> Nothing xs -> Just $ List.minimumBy cmp xs +-- | Computes all minima by comparing some property.+--+-- >>> minimaOn (max 2) [1,2,3,4,5,-1]+-- [-1,2,1] minimaOn :: Ord b => (a -> b) -> [a] -> [a] minimaOn f = minimaBy (comparing f) --- | computes all minima+-- | Computes all minima.+--+-- >>> minimaBy (comparing abs) [1,2,3,2,1,-1]+-- [-1,1,1] minimaBy :: (a -> a -> Ordering) -> [a] -> [a] minimaBy cmp = \case [] -> [] (x:xs) -> NonEmpty.toList $ List.foldl' (\mins@(m:|_) y -> case m `cmp` y of LT -> mins- EQ -> (y NonEmpty.<| mins)- GT -> (y:|[])+ EQ -> y NonEmpty.<| mins+ GT -> y:|[] ) (x:|[]) xs -- | extracts all minima from the list. The result consists of the@@ -75,3 +107,38 @@ -- TODO: This is actually a good scenario for testing how much slower :+ is compared -- to doing nothing. i..e compare minimaBy and extractMinimaBy -- note that I'm using foldr here, and foldl' before+++--------------------------------------------------------------------------------+-- * Partitioning and Grouping++-- | Given a function f, partitions the list into three lists+-- (lts,eqs,gts) such that:+--+-- - f x == LT for all x in lts+-- - f x == EQ for all x in eqs+-- - f x == gt for all x in gts+--+-- >>> partition3 (compare 4) [0,1,2,2,3,4,5,5,6,6,7,7,7,7,7,8]+-- ([5,5,6,6,7,7,7,7,7,8],[4],[0,1,2,2,3])+--+partition3 :: Foldable f => (a -> Ordering) -> f a -> ([a],[a],[a])+partition3 f = foldr g ([],[],[])+ where+ g x (lts,eqs,gts) = case f x of+ LT -> (x:lts, eqs, gts)+ EQ -> ( lts, x:eqs, gts)+ GT -> ( lts, eqs,x:gts)++-- | A version of groupBy that uses the given Ordering to group+-- consecutive Equal items+--+-- >>> groupBy' compare [0,1,2,2,3,4,5,5,6,6,7,7,7,7,7,8]+-- [0 :| [],1 :| [],2 :| [2],3 :| [],4 :| [],5 :| [5],6 :| [6],7 :| [7,7,7,7],8 :| []]+groupBy' :: (a -> a -> Ordering) -> [a] -> [NonEmpty a]+groupBy' cmp = go+ where+ go = \case+ [] -> []+ (x:xs) -> let (pref,rest) = List.span (\y -> x `cmp` y == EQ) xs+ in (x :| pref) : go rest
src/Data/List/Zipper.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.List.Zipper+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.List.Zipper where import qualified Data.List as List@@ -51,7 +58,7 @@ extractNext :: Zipper a -> Maybe (a, Zipper a) extractNext (Zipper xs ys) = case ys of [] -> Nothing- (y:ys') -> Just $ (y,Zipper xs ys')+ (y:ys') -> Just (y,Zipper xs ys') -- | Drops the next element in the zipper.
src/Data/Measured.hs view
@@ -1,4 +1,10 @@-{-# Language FunctionalDependencies #-}+--------------------------------------------------------------------------------+-- |+-- Module : Data.Measured+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.Measured( module Data.Measured.Class ) where
src/Data/Measured/Class.hs view
@@ -1,11 +1,21 @@ {-# Language FunctionalDependencies #-}+--------------------------------------------------------------------------------+-- |+-- Module : Data.Measured.Class+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.Measured.Class where +-- | Things that can be measured. class Semigroup v => Measured v a | a -> v where measure :: a -> v +-- | Things that can be inserted. class Measured v a => CanInsert v a where insertA :: a -> v -> v +-- | Things that can be deleted. class Measured v a => CanDelete v a where deleteA :: a -> v -> Maybe v
src/Data/Measured/Size.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.Measured.Size+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.Measured.Size where import Control.DeepSeq@@ -6,6 +13,7 @@ -------------------------------------------------------------------------------- +-- | Measured size. Always non-negative. newtype Size = Size Word deriving (Show,Read,Eq,Num,Integral,Enum,Real,Ord,Generic,NFData) instance Semigroup Size where
src/Data/OrdSeq.hs view
@@ -1,12 +1,41 @@-module Data.OrdSeq where+--------------------------------------------------------------------------------+-- |+-- Module : Data.OrdSeq+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+--------------------------------------------------------------------------------+module Data.OrdSeq+ ( OrdSeq+ , Compare+ , insertBy+ , insert+ , splitBy+ , splitOn+ , splitMonotonic+ , deleteAll+ , deleteAllBy+ , fromListBy+ , fromListByOrd+ , fromAscList+ , lookupBy+ , memberBy+ , mapMonotonic+ , viewl+ , viewr+ , minView+ , lookupMin+ , maxView+ , lookupMax+ ) where -import Control.Lens (bimap)-import qualified Data.FingerTree as FT+import Control.Lens (bimap) import Data.FingerTree hiding (null, viewl, viewr)-import qualified Data.Foldable as F-import Data.Maybe-import Test.QuickCheck+import qualified Data.FingerTree as FT+import qualified Data.Foldable as F+import Data.Maybe (fromJust, isJust, listToMaybe)+import Test.QuickCheck (Arbitrary (arbitrary)) -------------------------------------------------------------------------------- @@ -28,15 +57,18 @@ -newtype Elem a = Elem { getElem :: a } deriving (Eq,Ord,Traversable,Foldable,Functor)+newtype Elem a = Elem a deriving (Eq,Ord,Traversable,Foldable,Functor) instance Show a => Show (Elem a) where show (Elem x) = "Elem " <> show x -+-- | Sequence of ordered elements. newtype OrdSeq a = OrdSeq { _asFingerTree :: FingerTree (Key a) (Elem a) }- deriving (Show,Eq)+ deriving (Eq) +instance Show a => Show (OrdSeq a) where+ show s = "fromAscList " ++ show (F.toList s)+ instance Semigroup (OrdSeq a) where (OrdSeq s) <> (OrdSeq t) = OrdSeq $ s `mappend` t @@ -57,7 +89,7 @@ instance Measured (Key a) (Elem a) where measure (Elem x) = Key x -+-- | Signature for functions that give the ordering of two values. type Compare a = a -> a -> Ordering -- | Insert into a monotone OrdSeq.@@ -76,6 +108,7 @@ insert :: Ord a => a -> OrdSeq a -> OrdSeq a insert = insertBy compare +-- | \( O(\log n) \). Delete all elements that compare as equal to @x@. deleteAllBy :: Compare a -> a -> OrdSeq a -> OrdSeq a deleteAllBy cmp x s = l <> r where@@ -93,18 +126,18 @@ (m',r) = split (\v -> liftCmp cmp v (Key x) == GT) m +{- HLINT ignore splitOn -} -- | Given a monotonic function f that maps a to b, split the sequence s -- depending on the b values. I.e. the result (l,m,r) is such that--- * all (< x) . fmap f $ l--- * all (== x) . fmap f $ m--- * all (> x) . fmap f $ r ----- >>> splitOn id 3 $ fromAscList' [1..5]--- (OrdSeq {_asFingerTree = fromList [Elem 1,Elem 2]},OrdSeq {_asFingerTree = fromList [Elem 3]},OrdSeq {_asFingerTree = fromList [Elem 4,Elem 5]})--- >>> splitOn fst 2 $ fromAscList' [(0,"-"),(1,"A"),(2,"B"),(2,"C"),(3,"D"),(4,"E")]--- (OrdSeq {_asFingerTree = fromList [Elem (0,"-"),Elem (1,"A")]},OrdSeq {_asFingerTree = fromList [Elem (2,"B"),Elem (2,"C")]},OrdSeq {_asFingerTree = fromList [Elem (3,"D"),Elem (4,"E")]})+-- * @all (< x) . fmap f $ l@+-- * @all (== x) . fmap f $ m@+-- * @all (> x) . fmap f $ r@ ----- \(O(\log n)\)+-- >>> splitOn id 3 $ fromAscList [1..5]+-- (fromAscList [1,2],fromAscList [3],fromAscList [4,5])+-- >>> splitOn fst 2 $ fromAscList [(0,"-"),(1,"A"),(2,"B"),(2,"C"),(3,"D"),(4,"E")]+-- (fromAscList [(0,"-"),(1,"A")],fromAscList [(2,"B"),(2,"C")],fromAscList [(3,"D"),(4,"E")]) splitOn :: Ord b => (a -> b) -> b -> OrdSeq a -> (OrdSeq a, OrdSeq a, OrdSeq a) splitOn f x (OrdSeq s) = (OrdSeq l, OrdSeq m', OrdSeq r) where@@ -119,7 +152,7 @@ splitMonotonic p = bimap OrdSeq OrdSeq . split (p . getKey) . _asFingerTree --- Deletes all elements from the OrdDeq+-- | Deletes all elements from the OrdDeq -- -- \(O(n\log n)\) deleteAll :: Ord a => a -> OrdSeq a -> OrdSeq a@@ -136,58 +169,56 @@ fromListByOrd :: Ord a => [a] -> OrdSeq a fromListByOrd = fromListBy compare --- | O(n)-fromAscList' :: [a] -> OrdSeq a-fromAscList' = OrdSeq . fromList . fmap Elem+-- | \( O(n) \)+fromAscList :: [a] -> OrdSeq a+fromAscList = OrdSeq . fromList . fmap Elem -- | \(O(\log n)\) lookupBy :: Compare a -> a -> OrdSeq a -> Maybe a lookupBy cmp x s = let (_,m,_) = splitBy cmp x s in listToMaybe . F.toList $ m +-- | \(O(\log n)\). Queries for the existance of any elements that compare as equal to @x@. memberBy :: Compare a -> a -> OrdSeq a -> Bool memberBy cmp x = isJust . lookupBy cmp x --- | Fmap, assumes the order does not change--- O(n)+-- | \( O(n) \) Fmap, assumes the order does not change mapMonotonic :: (a -> b) -> OrdSeq a -> OrdSeq b-mapMonotonic f = fromAscList' . map f . F.toList+mapMonotonic f = fromAscList . map f . F.toList --- | Gets the first element from the sequence--- \(O(1)\)+-- | \(O(1)\) Gets the first element from the sequence viewl :: OrdSeq a -> ViewL OrdSeq a viewl = f . FT.viewl . _asFingerTree where- f EmptyL = EmptyL- f (Elem x :< s) = x :< OrdSeq s+ f EmptyL = EmptyL+ f (Elem x :< s) = x :< OrdSeq s --- Last element--- \(O(1)\)+-- | \(O(1)\) Gets the last element from the sequence viewr :: OrdSeq a -> ViewR OrdSeq a viewr = f . FT.viewr . _asFingerTree where- f EmptyR = EmptyR- f (s :> Elem x) = OrdSeq s :> x+ f EmptyR = EmptyR+ f (s :> Elem x) = OrdSeq s :> x --- \(O(1)\)+-- | \(O(1)\) minView :: OrdSeq a -> Maybe (a, OrdSeq a) minView s = case viewl s of EmptyL -> Nothing (x :< t) -> Just (x,t) --- \(O(1)\)+-- | \(O(1)\) lookupMin :: OrdSeq a -> Maybe a lookupMin = fmap fst . minView --- \(O(1)\)+-- | \(O(1)\) maxView :: OrdSeq a -> Maybe (a, OrdSeq a) maxView s = case viewr s of EmptyR -> Nothing (t :> x) -> Just (x,t) --- \(O(1)\)+-- | \(O(1)\) lookupMax :: OrdSeq a -> Maybe a lookupMax = fmap fst . maxView
src/Data/PlanarGraph.hs view
@@ -1,6 +1,4 @@-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE OverloadedStrings #-} -------------------------------------------------------------------------------- -- | -- Module : Data.PlanarGraph
src/Data/PlanarGraph/AdjRep.hs view
@@ -11,9 +11,10 @@ -------------------------------------------------------------------------------- module Data.PlanarGraph.AdjRep where -import Data.Aeson-import GHC.Generics (Generic)-import Control.Lens(Bifunctor(..))+import Control.Lens (Bifunctor (..))+import Data.Aeson+import Data.Bifunctor (second)+import GHC.Generics (Generic) -------------------------------------------------------------------------------- @@ -46,7 +47,7 @@ } deriving (Generic) instance Bifunctor Vtx where- bimap f g (Vtx i as x) = Vtx i (map (\(j,y) -> (j,g y)) as) (f x)+ bimap f g (Vtx i as x) = Vtx i (map (second g) as) (f x) instance (ToJSON v, ToJSON e) => ToJSON (Vtx v e) where toEncoding = genericToEncoding defaultOptions
src/Data/PlanarGraph/Core.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ScopedTypeVariables #-} -------------------------------------------------------------------------------- -- |@@ -13,17 +12,17 @@ import Control.DeepSeq-import Control.Lens hiding ((.=))+import Control.Lens hiding ((.=)) import Control.Monad.State.Strict import Data.Aeson-import qualified Data.Foldable as F+import qualified Data.Foldable as F import Data.Permutation import Data.PlanarGraph.Dart-import Data.Type.Equality (gcastWith, (:~:)(..))-import qualified Data.Vector as V-import qualified Data.Vector.Mutable as MV-import GHC.Generics (Generic)-import Unsafe.Coerce (unsafeCoerce)+import Data.Type.Equality (gcastWith)+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as MV+import GHC.Generics (Generic)+import Unsafe.Coerce (unsafeCoerce) -------------------------------------------------------------------------------- @@ -90,6 +89,7 @@ -- | Shorthand for vertices in the primal. type VertexId' s = VertexId s Primal +-- | Getter for a VertexId's unique number. unVertexId :: Getter (VertexId s w) Int unVertexId = to _unVertexId @@ -99,7 +99,7 @@ -------------------------------------------------------------------------------- -- * FaceId's --- | The type to reprsent FaceId's+-- | The type to represent FaceId's newtype FaceId s w = FaceId { _unFaceId :: VertexId s (DualOf w) } deriving (Eq,Ord,Enum,ToJSON,FromJSON) @@ -145,19 +145,22 @@ -- ** lenses and getters --- | Get the embedding, reprsented as a permutation of the darts, of this+-- | Get the embedding, represented as a permutation of the darts, of this -- graph. embedding :: Getter (PlanarGraph s w v e f) (Permutation (Dart s)) embedding = to _embedding +-- | O\(1\) access, \( O(n) \) update. vertexData :: Lens (PlanarGraph s w v e f) (PlanarGraph s w v' e f) (V.Vector v) (V.Vector v') vertexData = lens _vertexData (\g vD -> updateData (const vD) id id g) +-- | O\(1\) access, \( O(n) \) update. rawDartData :: Lens (PlanarGraph s w v e f) (PlanarGraph s w v e' f) (V.Vector e) (V.Vector e') rawDartData = lens _rawDartData (\g dD -> updateData id (const dD) id g) +-- | O\(1\) access, \( O(n) \) update. faceData :: Lens (PlanarGraph s w v e f) (PlanarGraph s w v e f') (V.Vector f) (V.Vector f') faceData = lens _faceData (\g fD -> updateData id id (const fD) g)@@ -222,7 +225,7 @@ -- | Traverse the vertices ----- (^.vertexData) <$> traverseVertices (\i x -> Just (i,x)) myGraph+-- >>> (^.vertexData) <$> traverseVertices (\i x -> Just (i,x)) myGraph -- Just [(VertexId 0,()),(VertexId 1,()),(VertexId 2,()),(VertexId 3,())] -- >>> traverseVertices (\i x -> print (i,x)) myGraph >> pure () -- (VertexId 0,())@@ -233,7 +236,7 @@ => (VertexId s w -> v -> m v') -> PlanarGraph s w v e f -> m (PlanarGraph s w v' e f)-traverseVertices f = itraverseOf (vertexData.itraversed) (\i -> f (VertexId i))+traverseVertices f = itraverseOf (vertexData.itraversed) (f . VertexId) -- | Traverses the darts --@@ -254,7 +257,7 @@ => (Dart s -> e -> m e') -> PlanarGraph s w v e f -> m (PlanarGraph s w v e' f)-traverseDarts f = itraverseOf (rawDartData.itraversed) (\i -> f (toEnum i))+traverseDarts f = itraverseOf (rawDartData.itraversed) (f . toEnum) -- | Traverses the faces --@@ -294,7 +297,7 @@ -- -- running time: \(O(n)\). planarGraph :: [[(Dart s,e)]] -> PlanarGraph s Primal () e ()-planarGraph ds = (planarGraph' perm)&dartData .~ (V.fromList . concat $ ds)+planarGraph ds = planarGraph' perm & dartData .~ (V.fromList . concat $ ds) where n = sum . map length $ ds perm = toCycleRep n $ map (map fst) ds@@ -481,7 +484,7 @@ -------------------------------------------------------------------------------- -- * Access data -+-- | General interface to accessing vertex data, dart data, and face data. class HasDataOf g i where type DataOf g i -- | get the data associated with the value i.
src/Data/PlanarGraph/Dart.hs view
@@ -62,7 +62,16 @@ data Dart s = Dart { _arc :: !(Arc s) , _direction :: !Direction } deriving (Eq,Ord,Generic)-makeLenses ''Dart++-- | Arc lens.+arc :: Lens' (Dart s) (Arc s)+arc = lens _arc (\d a -> d{_arc = a})++-- | Direction lens.+direction :: Lens' (Dart s) Direction+direction = lens _direction (\d dir -> d{_direction = dir})++-- makeLenses ''Dart instance NFData (Dart s)
src/Data/PlanarGraph/Dual.hs view
@@ -138,7 +138,7 @@ -- -- running time: \(O(k)\), where \(k\) is the output size. boundaryVertices :: FaceId s w -> PlanarGraph s w v e f -> V.Vector (VertexId s w)-boundaryVertices f g = fmap (flip tailOf g) $ boundary f g+boundaryVertices f g = flip tailOf g <$> boundary f g -- -- | Gets the next dart along the face -- nextDart :: Dart s -> PlanarGraph s w v e f -> Dart s
src/Data/PlanarGraph/IO.hs view
@@ -13,22 +13,21 @@ module Data.PlanarGraph.IO where import Control.Lens-import Control.Monad (forM_) import Control.Monad.State.Strict import Data.Aeson import Data.Bifunctor import Data.Ext-import qualified Data.Foldable as F-import Data.Maybe (fromJust)+import qualified Data.Foldable as F+import Data.Maybe (fromJust) import Data.Permutation-import Data.PlanarGraph.AdjRep (Face(Face), Vtx(Vtx),Gr(Gr))+import Data.PlanarGraph.AdjRep (Face (Face), Gr (Gr), Vtx (Vtx)) import Data.PlanarGraph.Core import Data.PlanarGraph.Dart import Data.PlanarGraph.Dual import Data.PlanarGraph.EdgeOracle import Data.Proxy-import qualified Data.Vector as V-import qualified Data.Vector.Mutable as MV+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as MV -------------------------------------------------------------------------------- @@ -126,7 +125,7 @@ fromAdjacencyLists adjM = planarGraph' . toCycleRep n $ perm where n = sum . fmap length $ perm- perm = map toOrbit $ adjM'+ perm = map toOrbit adjM' adjM' = fmap (second F.toList) adjM
+ src/Data/PlanarGraph/Immutable.hs view
@@ -0,0 +1,1398 @@+{-# LANGUAGE RecordWildCards #-}+--------------------------------------------------------------------------------+-- |+-- Module : Data.PlanarGraph.Immutable+-- Copyright : (C) David Himmelstrup+-- License : see the LICENSE file+-- Maintainer : David Himmelstrup+--+-- A graph is planar if it can be drawn on a flat piece of+-- paper without any crossing edges. More theory is explained on wikipedia:+-- <https://en.wikipedia.org/wiki/Planar_graph>+--+-- This module describes the connectivity of planar graphs without knowing+-- the 2D coordinates of each vertex. Algorithms that require the vertex+-- positions (such as planar point locators or mesh smoothers) have to store+-- that information somewhere else. Vertices are identified by dense, consecutive+-- integers and can be efficiently used with arrays or finite maps.+-- +-- A planar graph consists of directed edges (also called half-edges or darts),+-- vertices, and faces. If a face lies on the outside of a set of vertices, this+-- face is called a boundary.+--+-- The simplest planar graph has just three vertices and three edges:+--+-- @'pgFromFaces' [[0,1,2]]@+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- The above pictures shows three vertices (named @'0'@, @'1'@, and @'2'@), a single face+-- (named @'0'@ with an underscore), and 6 half-edges (named @'0'@ through @'5'@).+-- Vertices, faces, and half-edges can be efficiently queried and traversed.+--+-- >>> let pg = pgFromFaces [[0,1,2]]+-- >>> pgFaces pg+-- [Face 0]+-- >>> faceBoundary (Face 0) pg+-- [Vertex 1,Vertex 2,Vertex 0]+--+--+-- == Planar graph examples:+--+-- Faces in planar graphs do not have to be triangular:+--+-- @'pgFromFaces' [[0,1,2,3]]@+--+-- <<docs/Data/PlanarGraph/planargraph-2506803680640023584.svg>>+--+-- Vertices may be interior or lie on a boundary:+--+-- @'pgFromFaces' [[0,1,2,3],[4,3,2,1]]@+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- >>> pgFaces pg+-- [Face 0,Face 1]+-- >>> vertexIsBoundary (Vertex 0) pg+-- True+-- >>> vertexIsBoundary (Vertex 2) pg+-- False+--+-- Planar graphs may have multiple boundaries. Notice how the area between vertices+-- @'1'@, @'2'@ and @'3'@ does not have a face ID:+--+-- @'pgFromFaces' [[0,4,1],[0,1,2],[4,3,1],[4,5,3],[3,5,2],[2,5,0]]@+--+-- <<docs/Data/PlanarGraph/planargraph-2635031442529484236.compact.svg>>+--+-- >>> let pg = pgFromFaces [[0,4,1],[0,1,2],[4,3,1],[4,5,3],[3,5,2],[2,5,0]]+-- >>> pgFaces pg+-- [Face 0,Face 1,Face 2,Face 3,Face 4,Face 5]+-- >>> pgBoundaries pg+-- [Boundary 0,Boundary 1]+-- >>> faceBoundary (Boundary 0) pg {- Outer boundary -}+-- [Vertex 0,Vertex 4,Vertex 5]+-- >>> faceBoundary (Boundary 1) pg {- Inner boundary -}+-- [Vertex 1,Vertex 2,Vertex 3]+--+-- Planar graphs may also have multiple unconnected components but they cannot be+-- automatically rendered:+--+-- >>> let pg = pgFromFaces [[0,1,2], [3,4,5]]+-- >>> pgFaces pg+-- [Face 0,Face 1]+-- >>> pgBoundaries pg+-- [Boundary 0,Boundary 1]+-- >>> faceBoundary (Boundary 0) pg+-- [Vertex 0,Vertex 1,Vertex 2]+-- >>> faceBoundary (Boundary 1) pg+-- [Vertex 3,Vertex 4,Vertex 5]+--+-- == Big-O Notation+--+-- When describing runtime complexity, @n@ refers to the size of the graph+-- (vertices, half-edges, faces, etcs). Some functions are output-sensitive+-- and use @k@ to indicate the amount of data consumed. For example,+-- 'vertexNeighbours' runs in \( O(k) \) and taking the first neighbour is therefore+-- an \( O(1) \) operation (because k=1).+--------------------------------------------------------------------------------+module Data.PlanarGraph.Immutable+ ( -- * Planar graphs+ PlanarGraph+ , pgFromFaces -- :: [[VertexId]] -> PlanarGraph+ , pgFromFacesCV -- :: [CircularVector VertexId] -> PlanarGraph+ , pgVertices -- :: PlanarGraph -> [Vertex]+ , pgEdges -- :: PlanarGraph -> [Edge]+ , pgHalfEdges -- :: PlanarGraph -> [HalfEdge]+ , pgFaces -- :: PlanarGraph -> [Face]+ , pgBoundaries -- :: PlanarGraph -> [Face]++ -- * Elements+ -- ** Vertices+ , Vertex(..)+ , vertexHalfEdge -- :: Vertex -> PlanarGraph -> HalfEdge+ , vertexIsInterior -- :: Vertex -> PlanarGraph -> Bool+ , vertexIsBoundary -- :: Vertex -> PlanarGraph -> Bool+ , vertexOutgoingHalfEdges -- :: Vertex -> PlanarGraph -> [HalfEdge]+ , vertexIncomingHalfEdges -- :: Vertex -> PlanarGraph -> [HalfEdge]+ , vertexNeighbours -- :: Vertex -> PlanarGraph -> [Vertex]++ -- ** Edges+ , Edge(..)+ , edgeHalfEdges -- :: Edge -> (HalfEdge, HalfEdge)++ -- ** Half-edges+ , HalfEdge(..)+ , halfEdgeNext -- :: HalfEdge -> PlanarGraph -> HalfEdge+ , halfEdgePrev -- :: HalfEdge -> PlanarGraph -> HalfEdge+ , halfEdgeTwin -- :: HalfEdge -> HalfEdge+ , halfEdgeNextOutgoing -- :: HalfEdge -> PlanarGraph -> HalfEdge+ , halfEdgeNextIncoming -- :: HalfEdge -> PlanarGraph -> HalfEdge+ , halfEdgeVertex -- :: HalfEdge -> PlanarGraph -> Vertex+ , halfEdgeTailVertex -- :: HalfEdge -> PlanarGraph -> Vertex+ , halfEdgeTipVertex -- :: HalfEdge -> PlanarGraph -> Vertex+ , halfEdgeFace -- :: HalfEdge -> PlanarGraph -> Face+ , halfEdgeIsInterior -- :: HalfEdge -> PlanarGraph -> Bool+ , halfEdgeIsBoundary -- :: HalfEdge -> PlanarGraph -> Bool++ -- ** Faces+ , Face(..), FaceId+ , faceMember -- :: Face -> PlanarGraph -> Bool+ , faceId -- :: Face -> FaceId+ , faceHalfEdge -- :: Face -> PlanarGraph -> HalfEdge+ , faceIsInterior -- :: Face -> Bool+ , faceIsBoundary -- :: Face -> Bool+ , faceHalfEdges -- :: Face -> PlanarGraph -> CircularVector HalfEdge+ , faceBoundary -- :: Face -> PlanarGraph -> CircularVector Vertex++ -- * Mutation+ , pgMutate -- :: PlanarGraph -> (forall s. Mut.PlanarGraph s -> ST s ()) -> PlanarGraph+ , pgCreate -- :: (forall s. ST s (Mut.PlanarGraph s)) -> PlanarGraph+ , pgThaw -- :: PlanarGraph -> ST s (Mut.PlanarGraph s)+ , pgFreeze -- :: Mut.PlanarGraph s -> ST s PlanarGraph+ , pgUnsafeThaw -- :: PlanarGraph -> ST s (Mut.PlanarGraph s)+ , pgUnsafeFreeze -- :: Mut.PlanarGraph s -> ST s PlanarGraph++ -- * Misc+ , tutteEmbedding -- :: PlanarGraph -> Vector.Vector (V2 Double)+ )+ where++import Control.Monad+import Control.Monad.ST+import Data.Bits+import Data.Coerce+import Data.Hashable+import Data.PlanarGraph.Internal (FaceId, HalfEdgeId, VertexId)+import qualified Data.PlanarGraph.Internal as Mut+import qualified Data.PlanarGraph.Mutable as Mut+import Data.Proxy+import Data.STRef+import Data.Vector (Vector)+import qualified Data.Vector as Vector+import Data.Vector.Circular (CircularVector)+import qualified Data.Vector.Circular as CV+import qualified Data.Vector.Mutable as V+import GHC.Exts+import Linear.Matrix (luSolve)+import Linear.V+import Linear.V2++-- import Debug.Trace++-------------------------------------------------------------------------------+-- Elements: Half-edges, vertices, faces.+++-- | Half-edges are directed edges between vertices. All Half-edge have a twin+-- in the opposite direction. Half-edges have individual identity but are always+-- created in pairs.+newtype HalfEdge = HalfEdge {halfEdgeId :: Int}+ deriving (Eq, Hashable)++instance Show HalfEdge where+ showsPrec d (HalfEdge v) = showParen (d > 10) $+ showString "HalfEdge " . shows v++instance Read HalfEdge where+ readsPrec d = readParen (d > app_prec) $ \r ->+ [ (HalfEdge v, t)+ | ("HalfEdge", s) <- lex r, (v, t) <- reads s ]+ where app_prec = 10++-- | Edges are bidirectional and connect two vertices. No two edges are allowed+-- to cross.+newtype Edge = Edge {edgeId :: Int}+ deriving (Eq, Hashable)++instance Show Edge where+ showsPrec d (Edge v) = showParen (d > 10) $+ showString "Edge " . shows v++instance Read Edge where+ readsPrec d = readParen (d > app_prec) $ \r ->+ [ (Edge v, t)+ | ("Edge", s) <- lex r, (v, t) <- reads s ]+ where app_prec = 10++-- | Graph vertices. For best performance, make sure to use consecutive numbers.+newtype Vertex = Vertex {vertexId :: Int}+ deriving (Eq, Hashable)++instance Show Vertex where+ showsPrec d (Vertex v) = showParen (d > 10) $+ showString "Vertex " . shows v++instance Read Vertex where+ readsPrec d = readParen (d > app_prec) $ \r ->+ [ (Vertex v, t)+ | ("Vertex", s) <- lex r, (v, t) <- reads s ]+ where app_prec = 10++-- | Faces are the areas divided by edges. If a face is not surrounded by a set of vertices,+-- it is called a boundary.+data Face = Face FaceId | Boundary FaceId+ deriving (Eq, Read, Show)++-------------------------------------------------------------------------------+-- Planar graph++-- PlanarGraphs have vertices, edges, and faces.+-- Invariant: The half-edge of a boundary vertex is interior, twin is exterior.++-- FIXME: Use STRefU ?+-- PlanarGraph with 0 vertices: No edges, no vertices, no faces.+-- PlanarGraph with 1 vertex: No edges, no interior faces.+-- PlanarGraph with 2 vertices: One edge, no interior faces.+-- PlanarGraph with 3+ vertices: Usual properties hold.+-- | Immutable planar graph.+data PlanarGraph = PlanarGraph+ { pgHalfEdgeNext :: !(Vector HalfEdgeId) -- HalfEdge indexed+ , pgHalfEdgePrev :: !(Vector HalfEdgeId) -- HalfEdge indexed+ , pgHalfEdgeVertex :: !(Vector VertexId) -- HalfEdge indexed+ , pgHalfEdgeFace :: !(Vector FaceId) -- HalfEdge indexed+ , pgVertexEdges :: !(Vector HalfEdgeId) -- Vertex indexed+ , pgFaceEdges :: !(Vector HalfEdgeId) -- Face indexed+ , pgBoundaryEdges :: !(Vector HalfEdgeId) -- Boundary faces+ } deriving Eq++panic :: String -> String -> a+panic tag msg = error $ "Data.PlanarGraph.Immutable." ++ tag ++ ": " ++ msg+++-- $setup+--+-- >>> hash $ pgFromFaces [[0,1,2]]+-- 2959979592048325618+-- >>> hash $ pgFromFaces [[1,2,3]]+-- 2486673127436488352+-- >>> hash $ pgFromFaces [[0,1,2,3]]+-- 2506803680640023584+-- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- 1711135548958680232+--++-- | \( O(n \log n) \)+--+-- Construct a planar graph from a list of faces. Vertices are assumed to be dense+-- (ie without gaps) but this only affects performance, not correctness. Memory+-- usage is defined by the largest vertex ID. That means @'pgFromFaces' [[0,1,2]]@+-- has the same connectivity as @'pgFromFaces' [[7,8,9]]@ but uses three times less+-- memory.+--+-- ==== __Examples:__+-- @+-- 'pgFromFaces' [[0,1,2]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- @+-- 'pgFromFaces' [[0,1,2,3]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2506803680640023584.svg>>+--+-- @+-- 'pgFromFaces' [[1,2,3]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2486673127436488352.svg>>+--+-- @since 0.12.0.0+pgFromFaces :: [[VertexId]] -> PlanarGraph+pgFromFaces = pgFromFacesCV . map CV.unsafeFromList++-- | \( O(n \log n) \)+--+-- Construct a planar graph from a list of faces. This is a slightly more+-- efficient version of 'pgFromFacesCV'.+-- +-- @since 0.12.0.0+pgFromFacesCV :: [CircularVector VertexId] -> PlanarGraph+pgFromFacesCV faces = pgCreate $ Mut.pgFromFacesCV faces++-- fromFaces' :: Int -> Int -> Int -> [CircularVector VertexId] -> ST s (PlanarGraph)+-- fromFaces' nFaces nHalfEdges maxVertexId faces = do+-- undefined++-- dualTree :: Face -> ST s (Tree Face)+-- dualTree = undefined++instance Hashable PlanarGraph where+ hashWithSalt salt = hashWithSalt salt . pgHash+ hash = pgHash++-- | O(n)+-- +-- @since 0.12.0.0+pgHash :: PlanarGraph -> Int+pgHash pg =+ let loop [] salt = salt+ loop (edgeId:rest) salt =+ let he = HalfEdge (edgeId*2)+ vTail = halfEdgeTailVertex he pg+ vTip = halfEdgeTipVertex he pg+ in loop rest (hashWithSalt salt (vTail, vTip))+ in abs $ loop [0..Vector.length (pgHalfEdgeNext pg)`div`2-1] 0++-------------------------------------------------------------------------------+-- Vertices++-- | O(1)+vertexCheck :: String -> Vertex -> PlanarGraph -> a -> a+vertexCheck tag (Vertex vId) pg _val+ | vId >= Vector.length (pgVertexEdges pg) || vId < 0 =+ panic tag ("Out-of-bounds vertex access: " ++ show vId)+ | not (halfEdgeIsValid (HalfEdge (pgVertexEdges pg Vector.! vId))) =+ panic tag ("Tried to access deleted vertex: " ++ show vId)+vertexCheck _tag _face _pg val = val++-- | \( O(k) \)+-- +-- List all vertices in a graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> pgVertices pg+-- [Vertex 0,Vertex 1,Vertex 2]+--+-- @since 0.12.0.0+pgVertices :: PlanarGraph -> [Vertex]+pgVertices pg =+ [ Vertex v+ | v <- [0 .. Vector.length (pgVertexEdges pg)-1 ]+ , halfEdgeIsValid (HalfEdge $ pgVertexEdges pg Vector.! v)+ ]++-- -- | \( O(1) \)+-- vertexFromId :: VertexId -> Vertex+-- vertexFromId vId = Vertex vId++-- -- | \( O(1) \)+-- vertexId :: Vertex -> VertexId+-- vertexId (Vertex vId) = vId++-- $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2]]+-- 2959979592048325618++-- | \( O(1) \)+--+-- Each vertex has an assigned half-edge with the following properties:+--+-- @'halfEdgeVertex' ('vertexHalfEdge' vertex pg) pg = vertex@+--+-- @'faceIsInterior' ('halfEdgeFace' ('vertexHalfEdge' vertex pg) pg) = True@+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> vertexHalfEdge (Vertex 0) pg+-- HalfEdge 4+--+-- >>> vertexHalfEdge (Vertex 1) pg+-- HalfEdge 0+--+-- >>> vertexHalfEdge (Vertex 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexHalfEdge: Out-of-bounds vertex access: 6+-- ...+--+-- >>> vertexHalfEdge (Vertex (-10)) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexHalfEdge: Out-of-bounds vertex access: -10+-- ...+--+-- >>> halfEdgeVertex (vertexHalfEdge (Vertex 2) pg) pg+-- Vertex 2+--+-- >>> halfEdgeFace (vertexHalfEdge (Vertex 0) pg) pg+-- Face 0+--+-- @since 0.12.0.0+vertexHalfEdge :: Vertex -> PlanarGraph -> HalfEdge+vertexHalfEdge vertex pg | vertexCheck "vertexHalfEdge" vertex pg False = undefined+vertexHalfEdge (Vertex vId) pg = HalfEdge $ pgVertexEdges pg Vector.! vId+++-- $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- 1711135548958680232++-- | \( O(1) \)+--+-- Returns @True@ iff the vertex lies on a boundary.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexIsBoundary (Vertex 0) pg+-- True+--+-- >>> vertexIsBoundary (Vertex 2) pg+-- False+--+-- >>> vertexIsBoundary (Vertex 4) pg+-- True+--+-- >>> vertexIsBoundary (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexIsBoundary: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexIsBoundary :: Vertex -> PlanarGraph -> Bool+vertexIsBoundary vertex pg | vertexCheck "vertexIsBoundary" vertex pg False = undefined+vertexIsBoundary vertex pg =+ faceIsBoundary $ halfEdgeFace (halfEdgeTwin $ vertexHalfEdge vertex pg) pg++-- | \( O(1) \)+--+-- Returns @True@ iff the vertex is interior, ie. does not lie on a boundary.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexIsInterior (Vertex 0) pg+-- False+--+-- >>> vertexIsInterior (Vertex 2) pg+-- True+--+-- >>> vertexIsInterior (Vertex 4) pg+-- False+--+-- >>> vertexIsInterior (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexIsInterior: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexIsInterior :: Vertex -> PlanarGraph -> Bool+vertexIsInterior vertex pg | vertexCheck "vertexIsInterior" vertex pg False = undefined+vertexIsInterior vertex pg = not $ vertexIsBoundary vertex pg++-- | \( O(k) \)+--+-- Query outgoing half-edges from a given vertex in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexOutgoingHalfEdges (Vertex 1) pg+-- [HalfEdge 0,HalfEdge 11,HalfEdge 3]+--+-- Each half-edge will point out from the origin vertex:+--+-- >>> map (`halfEdgeVertex` pg) $ vertexOutgoingHalfEdges (Vertex 1) pg+-- [Vertex 1,Vertex 1,Vertex 1]+--+-- >>> map (`halfEdgeTipVertex` pg) $ vertexOutgoingHalfEdges (Vertex 1) pg+-- [Vertex 0,Vertex 4,Vertex 2]+--+-- >>> vertexOutgoingHalfEdges (Vertex 2) pg+-- [HalfEdge 2,HalfEdge 5]+--+-- >>> vertexOutgoingHalfEdges (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexOutgoingHalfEdges: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexOutgoingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]+vertexOutgoingHalfEdges vertex pg | vertexCheck "vertexOutgoingHalfEdges" vertex pg False = undefined+vertexOutgoingHalfEdges vertex pg = first : build (g (advance first))+ where+ advance he = halfEdgeNext (halfEdgeTwin he) pg+ first = vertexHalfEdge vertex pg+ g :: HalfEdge -> (HalfEdge -> b -> b) -> b -> b+ g he cons nil+ | he == first = nil+ | otherwise = cons he (g (advance he) cons nil)++-- $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- 1711135548958680232++-- | \( O(k) \)+--+-- Query incoming half-edges from a given vertex in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexIncomingHalfEdges (Vertex 1) pg+-- [HalfEdge 1,HalfEdge 10,HalfEdge 2]+--+-- >>> map (`halfEdgeVertex` pg) $ vertexIncomingHalfEdges (Vertex 1) pg+-- [Vertex 0,Vertex 4,Vertex 2]+--+-- >>> map (`halfEdgeTipVertex` pg) $ vertexIncomingHalfEdges (Vertex 1) pg+-- [Vertex 1,Vertex 1,Vertex 1]+--+-- >>> vertexIncomingHalfEdges (Vertex 2) pg+-- [HalfEdge 3,HalfEdge 4]+--+-- >>> vertexIncomingHalfEdges (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexIncomingHalfEdges: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexIncomingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]+vertexIncomingHalfEdges vertex pg | vertexCheck "vertexIncomingHalfEdges" vertex pg False = undefined+vertexIncomingHalfEdges vertex pg = map halfEdgeTwin $ vertexOutgoingHalfEdges vertex pg++-- | \( O(k) \)+--+-- Query vertex neighbours in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexNeighbours (Vertex 0) pg+-- [Vertex 3,Vertex 1]+--+-- >>> vertexNeighbours (Vertex 1) pg+-- [Vertex 0,Vertex 4,Vertex 2]+--+-- >>> vertexNeighbours (Vertex 2) pg+-- [Vertex 1,Vertex 3]+--+-- >>> vertexNeighbours (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexNeighbours: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexNeighbours :: Vertex -> PlanarGraph -> [Vertex]+vertexNeighbours vertex pg | vertexCheck "vertexNeighbours" vertex pg False = undefined+vertexNeighbours vertex pg = map (`halfEdgeVertex` pg) $ vertexIncomingHalfEdges vertex pg++-- vertexAdjacentVertices :: Vertex -> PlanarGraph -> [Vertex]+-- vertexAdjacentFaces :: Vertex -> PlanarGraph -> [Face]++-------------------------------------------------------------------------------+-- Edges++-- | \( O(k) \)+-- +-- List all edges in a graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> pgEdges pg+-- [Edge 0,Edge 1,Edge 2]+--+-- >>> map edgeHalfEdges $ pgEdges pg+-- [(HalfEdge 0,HalfEdge 1),(HalfEdge 2,HalfEdge 3),(HalfEdge 4,HalfEdge 5)]+--+-- @since 0.12.0.0+pgEdges :: PlanarGraph -> [Edge]+pgEdges pg =+ [ Edge e+ | e <- [0 .. Vector.length (pgHalfEdgeNext pg) `div` 2 -1]+ , let he = e*2+ , halfEdgeIsValid (HalfEdge he)+ ]++-- | \( O(1) \)+--+-- Split a bidirectional edge into directed half-edges.+--+-- @since 0.12.0.0+edgeHalfEdges :: Edge -> (HalfEdge, HalfEdge)+edgeHalfEdges (Edge e) = (HalfEdge $ e*2, HalfEdge $ e*2+1)++-------------------------------------------------------------------------------+-- Half-edges++-- | O(1)+halfEdgeCheck :: String -> HalfEdgeId -> PlanarGraph -> a -> a+halfEdgeCheck tag eId pg _val+ | eId >= Vector.length (pgHalfEdgeVertex pg) || eId < 0 =+ panic tag ("Out-of-bounds half-edge access: " ++ show eId)+ | pgHalfEdgeVertex pg Vector.! eId < 0 =+ panic tag ("Tried to access deleted half-edge: " ++ show eId)+halfEdgeCheck _tag _face _pg val = val++-- | \( O(k) \)+-- +-- List all half-edges in a graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> pgHalfEdges pg+-- [HalfEdge 0,HalfEdge 1,HalfEdge 2,HalfEdge 3,HalfEdge 4,HalfEdge 5]+--+-- @since 0.12.0.0+pgHalfEdges :: PlanarGraph -> [HalfEdge]+pgHalfEdges pg =+ [ he+ | he <- map HalfEdge [0 .. Vector.length (pgHalfEdgeNext pg)-1 ]+ , halfEdgeIsValid he+ ]+++-- | O(1)+--+-- @since 0.12.0.0+halfEdgeIsValid :: HalfEdge -> Bool+halfEdgeIsValid (HalfEdge eId) = eId >= 0++-- -- | O(1)+-- halfEdgeFromId :: HalfEdgeId -> HalfEdge+-- halfEdgeFromId eId = HalfEdge eId++-- -- | O(1)+-- halfEdgeId :: HalfEdge -> HalfEdgeId+-- halfEdgeId (HalfEdge eId) = eId++-- $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- 1711135548958680232++-- | \( O(1) \)+--+-- Query the half-edge in the pointed direction. Internal half-edges+-- are arranged clockwise and external half-edges go counter-clockwise.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> halfEdgeNext (HalfEdge 4) pg {- clockwise -}+-- HalfEdge 2+--+-- >>> halfEdgeNext (HalfEdge 3) pg {- clockwise -}+-- HalfEdge 5+--+-- >>> halfEdgeNext (HalfEdge 1) pg {- counter-clockwise -}+-- HalfEdge 11+--+-- >>> halfEdgeNext (HalfEdge 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeNext: Out-of-bounds half-edge access: 12+-- ...+--+-- @since 0.12.0.0+halfEdgeNext :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgeNext (HalfEdge eId) pg = halfEdgeCheck "halfEdgeNext" eId pg $+ HalfEdge $ pgHalfEdgeNext pg Vector.! eId++-- | \( O(1) \)+--+-- Query the half-edge opposite the pointed direction. This means counter-clockwise+-- for internal half-edges and clockwise for external half-edges.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> halfEdgePrev (HalfEdge 4) pg {- counter-clockwise -}+-- HalfEdge 6+--+-- >>> halfEdgePrev (HalfEdge 3) pg {- counter-clockwise -}+-- HalfEdge 10+--+-- >>> halfEdgePrev (HalfEdge 1) pg {- clockwise -}+-- HalfEdge 7+--+-- >>> halfEdgePrev (HalfEdge 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgePrev: Out-of-bounds half-edge access: 12+-- ...+--+-- @since 0.12.0.0+halfEdgePrev :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgePrev (HalfEdge eId) pg = halfEdgeCheck "halfEdgePrev" eId pg $+ HalfEdge $ pgHalfEdgePrev pg Vector.! eId++-- | \( O(1) \)+--+-- Next half-edge with the same vertex in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- @HalfEdge 0@ is poiting out from @Vertex 1@. Moving counter-clockwise+-- around @Vertex 1@ yields @HalfEdge 11@ and @HalfEdge 3@.+--+-- >>> halfEdgeNextOutgoing (HalfEdge 0) pg+-- HalfEdge 11+--+-- >>> halfEdgeNextOutgoing (HalfEdge 11) pg+-- HalfEdge 3+--+-- >>> halfEdgeNextOutgoing (HalfEdge 3) pg+-- HalfEdge 0+--+-- >>> halfEdgeNextOutgoing (HalfEdge 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeNextOutgoing: Out-of-bounds half-edge access: 12+-- ...+--+-- @since 0.12.0.0+halfEdgeNextOutgoing :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgeNextOutgoing e pg = halfEdgeCheck "halfEdgeNextOutgoing" (halfEdgeId e) pg $+ halfEdgeNext (halfEdgeTwin e) pg++-- | \( O(1) \)+--+-- Next half-edge with the same vertex in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- @HalfEdge 6@ is poiting towards @Vertex 3@. Moving clockwise+-- around @Vertex 3@ yields @HalfEdge 11@ and @HalfEdge 3@.+--+-- >>> halfEdgeNextIncoming (HalfEdge 6) pg+-- HalfEdge 5+--+-- >>> halfEdgeNextIncoming (HalfEdge 5) pg+-- HalfEdge 9+--+-- >>> halfEdgeNextIncoming (HalfEdge 9) pg+-- HalfEdge 6+--+-- >>> halfEdgeNextIncoming (HalfEdge 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeNextIncoming: Out-of-bounds half-edge access: 12+-- ...+--+-- @since 0.12.0.0+halfEdgeNextIncoming :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgeNextIncoming e pg = halfEdgeCheck "halfEdgeNextIncoming" (halfEdgeId e) pg $+ halfEdgeTwin (halfEdgeNext e pg)++-- | \( O(1) \)+--+-- @+-- 'halfEdgeTwin' . 'halfEdgeTwin' == id+-- @+--+-- @since 0.12.0.0+halfEdgeTwin :: HalfEdge -> HalfEdge+halfEdgeTwin (HalfEdge idx) = HalfEdge (idx `xor` 1)+++-- | \( O(1) \)+--+-- Tail-end of a half-edge. Synonym of 'halfEdgeTailVertex'.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeVertex (HalfEdge 1) pg+-- Vertex 0+--+-- >>> halfEdgeVertex (HalfEdge 2) pg+-- Vertex 2+--+-- >>> halfEdgeVertex (HalfEdge 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeVertex: Out-of-bounds half-edge access: 6+-- ...+--+-- @since 0.12.0.0+halfEdgeVertex :: HalfEdge -> PlanarGraph -> Vertex+halfEdgeVertex (HalfEdge idx) pg = halfEdgeCheck "halfEdgeVertex" idx pg $+ Vertex $ pgHalfEdgeVertex pg Vector.! idx++-- | O(1)+--+-- Tail-end of a half-edge. Synonym of 'halfEdgeVertex'.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeTailVertex (HalfEdge 1) pg+-- Vertex 0+--+-- >>> halfEdgeTailVertex (HalfEdge 2) pg+-- Vertex 2+--+-- @since 0.12.0.0+halfEdgeTailVertex :: HalfEdge -> PlanarGraph -> Vertex+halfEdgeTailVertex e pg = halfEdgeVertex e pg++-- | O(1)+--+-- Tip-end of a half-edge. This is the tail-end vertex of the twin half-edge.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeTipVertex (HalfEdge 1) pg+-- Vertex 1+--+-- >>> halfEdgeTipVertex (HalfEdge 5) pg+-- Vertex 0+--+-- @since 0.12.0.0+halfEdgeTipVertex :: HalfEdge -> PlanarGraph -> Vertex+halfEdgeTipVertex e pg = halfEdgeVertex (halfEdgeTwin e) pg++-- $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2]]+-- 2959979592048325618++-- | \( O(1) \)+--+-- Query the face of a half-edge.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeFace (HalfEdge 0) pg+-- Face 0+--+-- >>> halfEdgeFace (HalfEdge 1) pg+-- Boundary 0+--+-- >>> halfEdgeFace (HalfEdge 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeFace: Out-of-bounds half-edge access: 6+-- ...+--+-- @since 0.12.0.0+halfEdgeFace :: HalfEdge -> PlanarGraph -> Face+halfEdgeFace (HalfEdge eId) pg = halfEdgeCheck "halfEdgeFace" eId pg $+ faceFromId $ pgHalfEdgeFace pg Vector.! eId++-- | \( O(1) \)+--+-- Check if a half-edge's face is on a boundary.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeIsBoundary (HalfEdge 0) pg+-- False+--+-- >>> halfEdgeIsBoundary (HalfEdge 1) pg+-- True+--+-- >>> halfEdgeIsBoundary (HalfEdge 2) pg+-- False+--+-- >>> halfEdgeIsBoundary (HalfEdge 3) pg+-- True+--+-- >>> halfEdgeIsBoundary (HalfEdge 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeIsBoundary: Out-of-bounds half-edge access: 6+-- ...+--+-- @since 0.12.0.0+halfEdgeIsBoundary :: HalfEdge -> PlanarGraph -> Bool+halfEdgeIsBoundary edge pg = halfEdgeCheck "halfEdgeIsBoundary" (halfEdgeId edge) pg $+ faceIsBoundary $ halfEdgeFace edge pg++-- | \( O(1) \)+--+-- Check if a half-edge's face is interior.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeIsInterior (HalfEdge 0) pg+-- True+--+-- >>> halfEdgeIsInterior (HalfEdge 1) pg+-- False+--+-- >>> halfEdgeIsInterior (HalfEdge 2) pg+-- True+--+-- >>> halfEdgeIsInterior (HalfEdge 3) pg+-- False+--+-- >>> halfEdgeIsInterior (HalfEdge 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeIsInterior: Out-of-bounds half-edge access: 6+-- ...+--+-- @since 0.12.0.0+halfEdgeIsInterior :: HalfEdge -> PlanarGraph -> Bool+halfEdgeIsInterior edge pg = halfEdgeCheck "halfEdgeIsInterior" (halfEdgeId edge) pg $+ faceIsInterior $ halfEdgeFace edge pg++-------------------------------------------------------------------------------+-- Faces++-- | \( O(k) \)+-- +-- List all faces in a graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,4,1],[0,1,2],[4,3,1],[4,5,3],[3,5,2],[2,5,0]]+--+-- <<docs/Data/PlanarGraph/planargraph-2635031442529484236.compact.svg>>+--+-- >>> pgFaces pg+-- [Face 0,Face 1,Face 2,Face 3,Face 4,Face 5]+--+-- @since 0.12.0.0+pgFaces :: PlanarGraph -> [Face]+pgFaces pg =+ [ Face fId+ | fId <- [0 .. Vector.length (pgFaceEdges pg)-1 ]+ , halfEdgeIsValid (faceHalfEdge (Face fId) pg)+ ]++-- | \( O(k) \)+-- +-- List all boundaries (ie external faces) in a graph. There may be+-- multiple boundaries and they may or may not be reachable from each other.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,4,1],[0,1,2],[4,3,1],[4,5,3],[3,5,2],[2,5,0]]+--+-- <<docs/Data/PlanarGraph/planargraph-2635031442529484236.compact.svg>>+--+-- >>> pgBoundaries pg+-- [Boundary 0,Boundary 1]+--+-- >>> faceBoundary (Boundary 0) pg+-- [Vertex 0,Vertex 4,Vertex 5]+--+-- >>> faceBoundary (Boundary 1) pg+-- [Vertex 1,Vertex 2,Vertex 3]+--+-- @since 0.12.0.0+pgBoundaries :: PlanarGraph -> [Face]+pgBoundaries pg =+ [ Boundary fId+ | fId <- [0 .. Vector.length (pgBoundaryEdges pg)-1 ]+ , halfEdgeIsValid (faceHalfEdge (Boundary fId) pg)+ ]++-- | O(1)+faceCheck :: String -> Face -> PlanarGraph -> a -> a+faceCheck tag (Face fId) pg _val+ | fId >= Vector.length (pgFaceEdges pg) || fId < 0 =+ panic tag ("Out-of-bounds face access: " ++ show fId)+ | pgFaceEdges pg Vector.! fId < 0 =+ panic tag ("Tried to access deleted face: " ++ show fId)+faceCheck tag (Boundary fId) pg _val+ | fId >= Vector.length (pgBoundaryEdges pg) || fId < 0 =+ panic tag ("Out-of-bounds boundary access: " ++ show fId)+ | pgBoundaryEdges pg Vector.! fId < 0 =+ panic tag ("Tried to access deleted boundary: " ++ show fId)+faceCheck _tag _face _pg val = val++-- | \( O(1) \)+--+-- Returns @True@ iff a face or boundary is part of the planar graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> faceMember (Face 0) pg+-- True+--+-- >>> faceMember (Face 1) pg+-- False+--+-- >>> faceMember (Face 100) pg+-- False+--+-- >>> faceMember (Face (-100)) pg+-- False+--+-- >>> faceMember (Boundary 0) pg+-- True+--+-- >>> faceMember (Boundary 1) pg+-- False+--+-- @since 0.12.0.0+faceMember :: Face -> PlanarGraph -> Bool+faceMember face@(Face fId) pg =+ fId < Vector.length (pgFaceEdges pg) &&+ fId >= 0 &&+ halfEdgeIsValid (faceHalfEdge face pg)+faceMember face@(Boundary fId) pg =+ fId < Vector.length (pgFaceEdges pg) &&+ fId >= 0 &&+ halfEdgeIsValid (faceHalfEdge face pg)+++-- -- | O(1)+-- faceInvalid :: Face+-- faceInvalid = faceFromId maxBound++-- -- | O(1)+-- faceIsValid :: Face -> Bool+-- faceIsValid = not . faceIsInvalid++-- -- | O(1)+-- faceIsInvalid :: Face -> Bool+-- faceIsInvalid (Face fId) = fId == maxBound+-- faceIsInvalid (Boundary fId) = fId == maxBound++-- | O(1)+--+-- @since 0.12.0.0+faceFromId :: FaceId -> Face+faceFromId fId | fId < 0 = Boundary (negate fId - 1)+faceFromId fId = Face fId++-- | \( O(1) \)+--+-- Maps interior faces to positive integers and boundary faces to negative integers.+--+-- ==== __Examples:__+--+-- >>> faceId (Face 0)+-- 0+--+-- >>> faceId (Face 10)+-- 10+--+-- >>> faceId (Boundary 0)+-- -1+--+-- >>> faceId (Boundary 10)+-- -11+--+-- @since 0.12.0.0+faceId :: Face -> FaceId+faceId (Face fId) = fId+faceId (Boundary fId) = negate fId - 1+++-- | \( O(1) \)+--+-- Query the half-edge associated with a face or boundary.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> faceHalfEdge (Face 0) pg+-- HalfEdge 0+--+-- >>> faceHalfEdge (Face 1) pg+-- HalfEdge 8+--+-- >>> faceHalfEdge (Boundary 0) pg+-- HalfEdge 1+--+-- >>> faceHalfEdge (Face 10) pg {- Invalid face -}+-- ... Exception: Data.PlanarGraph.Immutable.faceHalfEdge: Out-of-bounds face access: 10+-- ...+--+-- @since 0.12.0.0+faceHalfEdge :: Face -> PlanarGraph -> HalfEdge+faceHalfEdge face pg = faceCheck "faceHalfEdge" face pg $+ case face of+ Face fId -> HalfEdge $ pgFaceEdges pg Vector.! fId+ Boundary fId -> HalfEdge $ pgBoundaryEdges pg Vector.! fId++-- | \( O(1) \)+--+-- Returns @True@ iff a face is interior. Does not check if the face actually exists.+--+-- ==== __Examples:__+--+-- >>> faceIsInterior (Face 0)+-- True+--+-- >>> faceIsInterior (Face 10000)+-- True+--+-- >>> faceIsInterior (Boundary 0)+-- False+--+-- @since 0.12.0.0+faceIsInterior :: Face -> Bool+faceIsInterior = not . faceIsBoundary++-- | \( O(1) \)+--+-- Returns @True@ iff a face is a boundary. Does not check if the face actually exists.+--+-- ==== __Examples:__+--+-- >>> faceIsBoundary (Face 0)+-- False+--+-- >>> faceIsBoundary (Face 10000)+-- False+--+-- >>> faceIsBoundary (Boundary 0)+-- True+--+-- @since 0.12.0.0+faceIsBoundary :: Face -> Bool+faceIsBoundary Face{} = False+faceIsBoundary Boundary{} = True++-- faceVertices :: Face -> ST s (CircularVector Vertex)++-- | \( O(k) \)+--+-- Query the half-edges around a face in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> faceHalfEdges (Face 0) pg+-- [HalfEdge 0,HalfEdge 2,HalfEdge 4,HalfEdge 6]+--+-- >>> faceHalfEdges (Face 1) pg+-- [HalfEdge 8,HalfEdge 5,HalfEdge 3,HalfEdge 10]+--+-- >>> faceHalfEdges (Boundary 0) pg+-- [HalfEdge 1,HalfEdge 11,HalfEdge 9,HalfEdge 7]+--+-- >>> faceHalfEdges (Face 10) pg+-- ... Exception: Data.PlanarGraph.Immutable.faceHalfEdges: Out-of-bounds face access: 10+-- ...+--+-- @since 0.12.0.0+faceHalfEdges :: Face -> PlanarGraph -> [HalfEdge]+faceHalfEdges face pg | faceCheck "faceHalfEdges" face pg False = undefined+faceHalfEdges face pg+ | faceIsBoundary face = first : build (worker halfEdgeNext (halfEdgeNext first pg))+ | otherwise = first : build (worker halfEdgePrev (halfEdgePrev first pg))+ where+ first = faceHalfEdge face pg+ worker :: (HalfEdge -> PlanarGraph -> HalfEdge) -> HalfEdge -> (HalfEdge -> b -> b) -> b -> b+ worker advance he cons nil+ | he == first = nil+ | otherwise = cons he (worker advance (advance he pg) cons nil)++-- | \( O(k) \)+--+-- Query the vertices of a face in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> faceBoundary (Face 0) pg+-- [Vertex 1,Vertex 2,Vertex 3,Vertex 0]+--+-- >>> faceBoundary (Face 1) pg+-- [Vertex 3,Vertex 2,Vertex 1,Vertex 4]+--+-- >>> faceBoundary (Boundary 0) pg+-- [Vertex 0,Vertex 1,Vertex 4,Vertex 3]+--+-- >>> faceBoundary (Face 10) pg+-- ... Exception: Data.PlanarGraph.Immutable.faceBoundary: Out-of-bounds face access: 10+-- ...+--+-- @since 0.12.0.0+faceBoundary :: Face -> PlanarGraph -> [Vertex]+faceBoundary face pg = faceCheck "faceBoundary" face pg $+ map (`halfEdgeVertex` pg) $ faceHalfEdges face pg++-- faceAdjacentFaces :: Face -> ST s (CircularVector Face)++-------------------------------------------------------------------------------+-- Mutation++-- | \( O(n) \)+--+-- @since 0.12.0.0+pgMutate :: PlanarGraph -> (forall s. Mut.PlanarGraph s -> ST s ()) -> PlanarGraph+pgMutate pg action = runST $ do+ mutPG <- pgThaw pg+ action mutPG+ pgUnsafeFreeze mutPG++-- | \( O(1) \)+--+-- @since 0.12.0.0+pgCreate :: (forall s. ST s (Mut.PlanarGraph s)) -> PlanarGraph+pgCreate action = runST (action >>= pgUnsafeFreeze)++-- | \( O(n) \)+--+-- @since 0.12.0.0+pgThaw :: PlanarGraph -> ST s (Mut.PlanarGraph s)+pgThaw pg = do+ pgNextHalfEdgeId <- newSTRef $ Vector.length (pgHalfEdgeNext pg) `div` 2+ pgNextVertexId <- newSTRef $ Vector.length $ pgVertexEdges pg+ pgNextFaceId <- newSTRef $ Vector.length $ pgFaceEdges pg+ pgNextBoundaryId <- newSTRef $ Vector.length $ pgBoundaryEdges pg++ pgHalfEdgeNext <- Mut.thawVector $ pgHalfEdgeNext pg+ pgHalfEdgePrev <- Mut.thawVector $ pgHalfEdgePrev pg+ pgHalfEdgeFace <- Mut.thawVector $ pgHalfEdgeFace pg+ pgHalfEdgeVertex <- Mut.thawVector $ pgHalfEdgeVertex pg+ pgVertexEdges <- Mut.thawVector $ pgVertexEdges pg+ pgFaceEdges <- Mut.thawVector $ pgFaceEdges pg+ pgBoundaryEdges <- Mut.thawVector $ pgBoundaryEdges pg+ pure Mut.PlanarGraph {..}++-- | \( O(1) \)+--+-- @since 0.12.0.0+pgUnsafeThaw :: PlanarGraph -> ST s (Mut.PlanarGraph s)+pgUnsafeThaw pg = do+ pgNextHalfEdgeId <- newSTRef $ Vector.length $ pgHalfEdgeNext pg+ pgNextVertexId <- newSTRef $ Vector.length $ pgVertexEdges pg+ pgNextFaceId <- newSTRef $ Vector.length $ pgFaceEdges pg+ pgNextBoundaryId <- newSTRef $ Vector.length $ pgBoundaryEdges pg++ pgHalfEdgeNext <- Mut.unsafeThawVector $ pgHalfEdgeNext pg+ pgHalfEdgePrev <- Mut.unsafeThawVector $ pgHalfEdgePrev pg+ pgHalfEdgeFace <- Mut.unsafeThawVector $ pgHalfEdgeFace pg+ pgHalfEdgeVertex <- Mut.unsafeThawVector $ pgHalfEdgeVertex pg+ pgVertexEdges <- Mut.unsafeThawVector $ pgVertexEdges pg+ pgFaceEdges <- Mut.unsafeThawVector $ pgFaceEdges pg+ pgBoundaryEdges <- Mut.unsafeThawVector $ pgBoundaryEdges pg+ pure Mut.PlanarGraph {..}++-- | \( O(n) \)+--+-- @since 0.12.0.0+pgFreeze :: Mut.PlanarGraph s -> ST s PlanarGraph+pgFreeze pg = do+ maxEdgeId <- readSTRef (Mut.pgNextHalfEdgeId pg)+ maxVertexId <- readSTRef (Mut.pgNextVertexId pg)+ maxFaceId <- readSTRef (Mut.pgNextFaceId pg)+ maxBoundaryId <- readSTRef (Mut.pgNextBoundaryId pg)++ pgHalfEdgeNext <- Vector.take (maxEdgeId*2) <$> Mut.freezeVector (Mut.pgHalfEdgeNext pg)+ pgHalfEdgePrev <- Vector.take (maxEdgeId*2) <$> Mut.freezeVector (Mut.pgHalfEdgePrev pg)+ pgHalfEdgeFace <- Vector.take (maxEdgeId*2) <$> Mut.freezeVector (Mut.pgHalfEdgeFace pg)+ pgHalfEdgeVertex <- Vector.take (maxEdgeId*2) <$> Mut.freezeVector (Mut.pgHalfEdgeVertex pg)+ pgVertexEdges <- Vector.take maxVertexId <$> Mut.freezeVector (Mut.pgVertexEdges pg)+ pgFaceEdges <- Vector.take maxFaceId <$> Mut.freezeVector (Mut.pgFaceEdges pg)+ pgBoundaryEdges <- Vector.take maxBoundaryId <$> Mut.freezeVector (Mut.pgBoundaryEdges pg)+ pure PlanarGraph { .. }++-- | \( O(1) \)+--+-- @since 0.12.0.0+pgUnsafeFreeze :: Mut.PlanarGraph s -> ST s PlanarGraph+pgUnsafeFreeze pg = do+ maxEdgeId <- readSTRef (Mut.pgNextHalfEdgeId pg)+ maxVertexId <- readSTRef (Mut.pgNextVertexId pg)+ maxFaceId <- readSTRef (Mut.pgNextFaceId pg)+ maxBoundaryId <- readSTRef (Mut.pgNextBoundaryId pg)++ pgHalfEdgeNext <- Vector.take (maxEdgeId*2) <$> Mut.unsafeFreezeVector (Mut.pgHalfEdgeNext pg)+ pgHalfEdgePrev <- Vector.take (maxEdgeId*2) <$> Mut.unsafeFreezeVector (Mut.pgHalfEdgePrev pg)+ pgHalfEdgeFace <- Vector.take (maxEdgeId*2) <$> Mut.unsafeFreezeVector (Mut.pgHalfEdgeFace pg)+ pgHalfEdgeVertex <- Vector.take (maxEdgeId*2) <$> Mut.unsafeFreezeVector (Mut.pgHalfEdgeVertex pg)+ pgVertexEdges <- Vector.take maxVertexId <$> Mut.unsafeFreezeVector (Mut.pgVertexEdges pg)+ pgFaceEdges <- Vector.take maxFaceId <$> Mut.unsafeFreezeVector (Mut.pgFaceEdges pg)+ pgBoundaryEdges <- Vector.take maxBoundaryId <$> Mut.unsafeFreezeVector (Mut.pgBoundaryEdges pg)+ pure PlanarGraph { .. }++-------------------------------------------------------------------------------+-- Tutte embedding++-- | \( O(n^3) \)+--+-- @since 0.12.0.0+tutteEmbedding :: PlanarGraph -> Vector.Vector (V2 Double)+tutteEmbedding pg = runST $ do+ let nVertices = Vector.length (pgVertexEdges pg)+ -- trace ("nVertices: " ++ show nVertices) $ return ()+ m <- Vector.replicateM nVertices (V.replicate nVertices 0)+ vx <- V.replicate nVertices 0+ vy <- V.replicate nVertices 0++ let boundary = faceBoundary (Boundary 0) pg+ let nBoundary = length boundary+ -- trace ("Vectors: " ++ show boundary) $+ forM_ (zip boundary (regularPolygon nBoundary)) $ \(vertex,(x,y)) -> do+ let valid = halfEdgeIsValid $ vertexHalfEdge vertex pg+ when valid $ do+ V.write (m Vector.! vertexId vertex) (vertexId vertex) (1::Double)+ V.write vx (vertexId vertex) x+ V.write vy (vertexId vertex) y++ forM_ [0..nVertices-1] $ \vId -> -- trace ("Vertex: " ++ show vId) $+ do+ let valid = halfEdgeIsValid $ vertexHalfEdge (Vertex vId) pg+ unless valid $ do+ V.write (m Vector.! vId) vId (1::Double)+ when valid $ do+ let onOuterBoundary =+ Boundary 0 == halfEdgeFace (halfEdgeTwin $ vertexHalfEdge (Vertex vId) pg) pg+ unless onOuterBoundary $ do+ let vertex = Vertex vId+ let neighbours = vertexNeighbours vertex pg+ forM_ neighbours $ \neighbour ->+ V.write (m Vector.! vId) (vertexId neighbour) (1::Double)+ V.write (m Vector.! vId) vId (negate $ fromIntegral $ length neighbours)++ mi <- mapM Vector.freeze m+ vxi <- Vector.freeze vx+ vyi <- Vector.freeze vy++ let xPos = reifyMatrix mi vxi luSolve+ yPos = reifyMatrix mi vyi luSolve++ pure $ Vector.zipWith V2 xPos yPos++reifyMatrix :: forall a. Vector.Vector (Vector.Vector a) ->+ Vector.Vector a ->+ (forall (n :: *). Dim n => V n (V n a) -> V n a -> V n a) ->+ Vector.Vector a+reifyMatrix m v f = reifyDim (Vector.length m) $ \(Proxy :: Proxy n) ->+ toVector (f (coerce m :: (V n (V n a))) (coerce v))++regularPolygon :: Int -> [(Double, Double)]+regularPolygon n =+ [ (cos ang, sin ang)+ | i <- [0 .. n-1]+ , let ang = fromIntegral i * frac + pi/2]+ where+ frac = 2*pi / fromIntegral n
+ src/Data/PlanarGraph/Internal.hs view
@@ -0,0 +1,92 @@+module Data.PlanarGraph.Internal where++import Control.Monad.ST+import Data.STRef+import qualified Data.Vector as V (unsafeFreeze)+import qualified Data.Vector as Vector+import Data.Vector.Circular (CircularVector)+import qualified Data.Vector.Circular as CV+import Data.Vector.Mutable (STVector)+import qualified Data.Vector.Mutable as V++-------------------------------------------------------------------------------+-- Resizeable vector++type GrowVector s v = STRef s (STVector s v)++newVector :: Int -> ST s (GrowVector s v)+newVector n = newSTRef =<< V.new n++setVector :: GrowVector s v -> v -> ST s ()+setVector ref val = do+ vec <- readSTRef ref+ V.set vec val++readVector :: GrowVector s v -> Int -> ST s v+readVector ref idx = do+ v <- readSTRef ref+ V.read v idx++writeVector :: GrowVector s v -> Int -> v -> ST s ()+writeVector ref idx val = do+ v <- readSTRef ref+ let l = V.length v+ if idx >= l+ then {-trace ("Growing: " ++ show (idx, l)) $ -} do+ v' <- V.grow v ((idx+1)*2)+ V.write v' idx val+ writeSTRef ref v'+ else -- trace ("Writing: " ++ show (idx, l)) $+ V.write v idx val++freezeVector :: GrowVector s v -> ST s (Vector.Vector v)+freezeVector ref = Vector.freeze =<< readSTRef ref++unsafeFreezeVector :: GrowVector s v -> ST s (Vector.Vector v)+unsafeFreezeVector ref = Vector.unsafeFreeze =<< readSTRef ref++thawVector :: Vector.Vector v -> ST s (GrowVector s v)+thawVector v = newSTRef =<< Vector.thaw v++unsafeThawVector :: Vector.Vector v -> ST s (GrowVector s v)+unsafeThawVector v = newSTRef =<< Vector.unsafeThaw v+++freezeCircularVector :: Int -> GrowVector s v -> ST s (CircularVector v)+freezeCircularVector n ref =+ (CV.unsafeFromVector . Vector.take n) <$> (V.unsafeFreeze =<< readSTRef ref)+++-------------------------------------------------------------------------------+-- Planar graph++type EdgeId = Int+type HalfEdgeId = Int+type VertexId = Int++-- | Numerical face identifier. Negative numbers indicate boundaries, non-negative numbers+-- are internal faces.+type FaceId = Int++-- PlanarGraphs have vertices, edges, and faces.+-- Invariant: The half-edge of a boundary vertex is interior, twin is exterior.++-- FIXME: Use STRefU ?+-- PlanarGraph with 0 vertices: No edges, no vertices, no faces.+-- PlanarGraph with 1 vertex: No edges, no interior faces.+-- PlanarGraph with 2 vertices: One edge, no interior faces.+-- PlanarGraph with 3+ vertices: Usual properties hold.+data PlanarGraph s = PlanarGraph+ { pgNextHalfEdgeId :: !(STRef s HalfEdgeId)+ , pgNextVertexId :: !(STRef s VertexId)+ , pgNextFaceId :: !(STRef s FaceId)+ , pgNextBoundaryId :: !(STRef s FaceId)+ , pgHalfEdgeNext :: !(GrowVector s HalfEdgeId) -- HalfEdge indexed+ , pgHalfEdgePrev :: !(GrowVector s HalfEdgeId) -- HalfEdge indexed+ , pgHalfEdgeVertex :: !(GrowVector s VertexId) -- HalfEdge indexed+ , pgHalfEdgeFace :: !(GrowVector s FaceId) -- HalfEdge indexed+ , pgVertexEdges :: !(GrowVector s HalfEdgeId) -- Vertex indexed+ , pgFaceEdges :: !(GrowVector s HalfEdgeId) -- Face indexed+ , pgBoundaryEdges :: !(GrowVector s HalfEdgeId) -- Boundary faces+ } deriving Eq+
+ src/Data/PlanarGraph/Mutable.hs view
@@ -0,0 +1,690 @@+module Data.PlanarGraph.Mutable+ ( -- * Planar graphs+ PlanarGraph+ , pgFromFaces -- :: [[VertexId]] -> ST s (PlanarGraph s)+ , pgFromFacesCV -- :: [CircularVector VertexId] -> ST s (PlanarGraph s)+ , pgClone -- :: PlanarGraph s -> ST s (PlanarGraph s)+ , pgHash -- :: PlanarGraph s -> ST s Int++ -- * Elements+ -- ** Vertices+ , Vertex, VertexId+ , vertexFromId -- :: VertexId -> PlanarGraph s -> Vertex s+ , vertexToId -- :: Vertex s -> VertexId+ , vertexHalfEdge -- :: Vertex s -> ST s (HalfEdge s)+ , vertexIsBoundary -- :: Vertex s -> ST s Bool+ , vertexOutgoingHalfEdges -- :: Vertex s -> ST s (CircularVector (HalfEdge s))+ , vertexWithOutgoingHalfEdges -- :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()+ , vertexIncomingHalfEdges -- :: Vertex s -> ST s (CircularVector (HalfEdge s))+ , vertexWithIncomingHalfEdges -- :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()+ , vertexNeighbours -- :: Vertex s -> ST s (CircularVector (Vertex s))+ -- , vertexNew -- :: PlanarGraph s -> ST s (Vertex s)+ -- , vertexSetHalfEdge -- :: Vertex s -> HalfEdge s -> ST s ()++ -- ** Edges+ , Edge, EdgeId+ , edgeFromId -- :: EdgeId -> PlanarGraph s -> Edge s+ , edgeToId -- :: Edge s -> EdgeId+ , edgeFromHalfEdge -- :: HalfEdge s -> Edge s++ -- ** Half-edges+ , HalfEdge, HalfEdgeId+ , halfEdgeFromId -- :: HalfEdgeId -> PlanarGraph s -> HalfEdge s+ , halfEdgeToId -- :: HalfEdge s -> HalfEdgeId+ , halfEdgeNext -- :: HalfEdge s -> ST s (HalfEdge s)+ , halfEdgePrev -- :: HalfEdge s -> ST s (HalfEdge s)+ , halfEdgeNextOutgoing -- :: HalfEdge s -> ST s (HalfEdge s)+ , halfEdgeNextIncoming -- :: HalfEdge s -> ST s (HalfEdge s)+ , halfEdgeVertex -- :: HalfEdge s -> ST s (Vertex s)+ , halfEdgeTwin -- :: HalfEdge s -> HalfEdge s+ , halfEdgeTailVertex -- :: HalfEdge s -> ST s (Vertex s)+ , halfEdgeTipVertex -- :: HalfEdge s -> ST s (Vertex s)+ , halfEdgeFace -- :: HalfEdge s -> ST s (Face s)+ , halfEdgeIsInterior -- :: HalfEdge s -> ST s Bool+ -- , halfEdgeNew -- :: PlanarGraph s -> ST s (HalfEdge s)+ -- , halfEdgeSetNext -- :: HalfEdge s -> HalfEdge s -> ST s ()+ -- , halfEdgeSetPrev -- :: HalfEdge s -> HalfEdge s -> ST s ()+ -- , halfEdgeSetFace -- :: HalfEdge s -> Face s -> ST s ()+ -- , halfEdgeSetVertex -- :: HalfEdge s -> Vertex s -> ST s ()++ -- ** Faces+ , Face, FaceId+ , faceInvalid -- :: PlanarGraph s -> Face s+ , faceIsValid -- :: Face s -> Bool+ , faceIsInvalid -- :: Face s -> Bool+ , faceFromId -- :: FaceId -> PlanarGraph s -> Face s+ , faceToId -- :: Face s -> FaceId+ , faceHalfEdge -- :: Face s -> ST s (HalfEdge s)+ , faceIsInterior -- :: Face s -> Bool+ , faceIsBoundary -- :: Face s -> Bool+ , faceHalfEdges -- :: Face s -> ST s (CircularVector (HalfEdge s))+ , faceBoundary -- :: Face s -> ST s (CircularVector (Vertex s))+ -- , faceNew :: PlanarGraph s -> ST s (Face s)+ -- , faceNewBoundary :: PlanarGraph s -> ST s (Face s)+ -- , faceSetHalfEdge :: Face s -> HalfEdge s -> ST s ()++ -- * Mutation+ , pgConnectVertices -- :: HalfEdge s -> HalfEdge s -> ST s (Edge s)+-- pgSplitHalfEdge :: HalfEdge s -> ST s (Vertex s)++-- pgRemoveFace :: Face s -> ST s ()+-- pgRemoveHalfEdge :: HalfEdge s -> ST s ()+-- pgRemoveVertex :: Vertex s -> ST s ()+ -- * Misc+ -- , tutteEmbedding -- :: PlanarGraph s -> ST s (Vector.Vector (Double, Double))+ )+ where++import Control.Monad (forM_, unless, when)+import Control.Monad.ST (ST)+import Data.Bits (Bits (xor))+import qualified Data.HashMap.Strict as HM+import Data.Hashable (Hashable (hashWithSalt))+import Data.PlanarGraph.Internal+import Data.STRef (modifySTRef', newSTRef, readSTRef, writeSTRef)+import Data.Vector.Circular (CircularVector)+import qualified Data.Vector.Circular as CV++import Debug.Trace++-------------------------------------------------------------------------------+-- Elements: Half-edges, vertices, faces.++data HalfEdge s = HalfEdge HalfEdgeId (PlanarGraph s)+ deriving Eq+instance Show (HalfEdge s) where+ showsPrec d (HalfEdge s _) = showsPrec d s+instance Hashable (HalfEdge s) where+ hashWithSalt salt (HalfEdge eId _) = hashWithSalt salt eId+++data Edge s = Edge EdgeId (PlanarGraph s)+ deriving Eq++data Vertex s = Vertex VertexId (PlanarGraph s)+ deriving Eq+instance Show (Vertex s) where+ showsPrec d (Vertex v _) = showsPrec d v+instance Hashable (Vertex s) where+ hashWithSalt salt (Vertex vId _) = hashWithSalt salt vId++data Face s = Face FaceId (PlanarGraph s) | Boundary FaceId (PlanarGraph s)+ deriving Eq+instance Show (Face s) where+ showsPrec d (Face fId _) = showString "Face " . shows fId+ showsPrec d (Boundary fId _) = showString "Boundary " . shows fId++-------------------------------------------------------------------------------+-- Planar graph++panic :: String -> String -> a+panic tag msg = error $ "Data.PlanarGraph.Mutable." ++ tag ++ ": " ++ msg++eqCheck :: String -> PlanarGraph s -> PlanarGraph s -> a -> a+eqCheck tag pg1 pg2 v+ | pg1 == pg2 = v+ | otherwise = panic tag "Invalid cross reference."++empty :: Int -> Int -> Int -> ST s (PlanarGraph s)+empty nFaces nVertices nEdges = PlanarGraph+ <$> newSTRef 0+ <*> newSTRef 0+ <*> newSTRef 0+ <*> newSTRef 0+ <*> newVector (nEdges*2)+ <*> newVector (nEdges*2)+ <*> newVector (nEdges*2)+ <*> newVector (nEdges*2)+ <*> newVector nVertices+ <*> newVector nFaces+ <*> newVector 0++{-+ For all boundary vertices:+ vertex.half-edge.face == interior+ vertex.half-edge.twin.face == exterior+ Boundary face: 0++ create N+-}+-- | O(n)+-- Create a planar graph with N boundary vertices.+new :: Int -> ST s (PlanarGraph s)+new n | n < 0 = panic "new" "Cannot contain negative vertices."+new 0 = empty 0 0 0+new 1 = undefined+new 2 = undefined+new n = pgFromFaces [[0..n-1]]++-- $setup+--+-- >>> import Control.Monad.ST+-- >>> runST $ pgFromFaces [[0,1,2]] >>= pgHash+-- 2959979592048325618+-- >>> runST $ pgFromFaces [[0,1,2,3]] >>= pgHash+-- 2506803680640023584+-- >>> runST $ pgFromFaces [[0,1,2,3],[4,3,2,1]] >>= pgHash+-- 1711135548958680232++-- | \( O(n \log n) \)+--+--+--+-- ==== __Examples:__+-- @+-- 'pgFromFaces' [[0,1,2]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- @+-- 'pgFromFaces' [[0,1,2,3]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2506803680640023584.svg>>+pgFromFaces :: [[VertexId]] -> ST s (PlanarGraph s)+pgFromFaces = pgFromFacesCV . map CV.unsafeFromList++pgFromFacesCV :: [CircularVector VertexId] -> ST s (PlanarGraph s)+pgFromFacesCV [] = empty 0 0 0+pgFromFacesCV faces = do+ let maxVertexId = maximum (map CV.maximum faces)+ nFaces = length faces+ nHalfEdges = sum (map length faces)+ pg <- empty nFaces (maxVertexId+1) (nHalfEdges `div` 2)+ setVector (pgVertexEdges pg) (-1)+ writeSTRef (pgNextVertexId pg) (maxVertexId+1)+ edgeMap <- newSTRef HM.empty+ let getHalfEdge (vTail, vTip) = do+ hm <- readSTRef edgeMap+ case HM.lookup (vTail, vTip) hm of+ Just{} -> panic "fromFaces" "Duplicate half-edge."+ Nothing ->+ case HM.lookup (vTip, vTail) hm of+ Just twin -> pure (halfEdgeTwin twin)+ Nothing -> {-trace ("Creating new half-edge: " ++ show (vTip, vTail)) $ -} do+ halfEdge <- halfEdgeNew pg+ halfEdgeSetFace (halfEdgeTwin halfEdge) (faceInvalid pg)+ vertexSetHalfEdge (vertexFromId vTip pg) halfEdge+ writeSTRef edgeMap $ HM.insert (vTail, vTip) halfEdge hm+ halfEdgeSetVertex halfEdge (vertexFromId vTip pg)+ halfEdgeSetVertex (halfEdgeTwin halfEdge) (vertexFromId vTail pg)+ pure halfEdge+ addFace face | length face < 3 = panic "fromFaces" "Faces must have at least 3 vertices."+ addFace face = {- trace "Adding face" $ -} do+ fId <- faceNew pg+ let edges = CV.zip face (CV.rotateRight 1 face)+ halfEdges <- {- trace ("getHalfEdge") $ -} mapM getHalfEdge edges+ faceSetHalfEdge fId (CV.head halfEdges)+ setNextPrevFace fId (CV.reverse halfEdges)+ forM_ faces addFace++ maxHalfEdgeId <- readSTRef (pgNextHalfEdgeId pg)+ -- For each half-edge:+ -- If face is invalid:+ -- Find loop and add it as a boundary.+ forM_ (map (`halfEdgeFromId` pg) [0..maxHalfEdgeId*2-1]) $ \he -> {- trace ("Scan halfedge: " ++ show he) $ -} do+ -- f <- halfEdgeFace he+ validFace <- faceIsValid <$> halfEdgeFace he+ unless validFace $ {- trace ("Found invalid face: " ++ show f) $ -} do+ face <- faceNewBoundary pg+ boundary <- halfEdgeConstructBoundary he+ -- trace ("Boundary: " ++ show (face, boundary)) $ return ()+ faceSetHalfEdge face (CV.head boundary)+ setNextPrevFace face boundary+ pure pg+ where+ setNextPrevFace fId halfEdges = do+ let edgeTriples = CV.zip3 (CV.rotateLeft 1 halfEdges) halfEdges (CV.rotateRight 1 halfEdges)+ forM_ (edgeTriples) $ \(prev, edge, next) -> do+ halfEdgeSetNext edge next+ halfEdgeSetPrev edge prev+ halfEdgeSetFace edge fId++-- fromFaces' :: Int -> Int -> Int -> [CircularVector VertexId] -> ST s (PlanarGraph s)+-- fromFaces' nFaces nHalfEdges maxVertexId faces = do+-- undefined++-- | \( O(n) \)+pgClone :: PlanarGraph s -> ST s (PlanarGraph s)+pgClone = undefined++-- dualTree :: Face s -> ST s (Tree (Face s))+-- dualTree = undefined++pgHash :: PlanarGraph s -> ST s Int+pgHash pg = do+ eMax <- readSTRef (pgNextHalfEdgeId pg)+ let loop [] salt = pure salt+ loop (edgeId:rest) salt = do+ let he = halfEdgeFromId (edgeId*2) pg+ vTail <- halfEdgeTailVertex he+ vTip <- halfEdgeTipVertex he+ loop rest (hashWithSalt salt (vTail, vTip))+ abs <$> loop [0..eMax-1] 0++-------------------------------------------------------------------------------+-- Vertices++-- | \( O(1) \)+vertexFromId :: VertexId -> PlanarGraph s -> Vertex s+vertexFromId vId pg = Vertex vId pg++-- | \( O(1) \)+vertexToId :: Vertex s -> VertexId+vertexToId (Vertex vId _pg) = vId++-- | \( O(1) \)+vertexHalfEdge :: Vertex s -> ST s (HalfEdge s)+vertexHalfEdge (Vertex vId pg) = do+ eId <- readVector (pgVertexEdges pg) vId+ pure $ HalfEdge eId pg++-- | \( O(1) \)+vertexIsBoundary :: Vertex s -> ST s Bool+vertexIsBoundary vertex = faceIsBoundary <$> (halfEdgeFace =<< (halfEdgeTwin <$> vertexHalfEdge vertex))++-- | O(k)+vertexOutgoingHalfEdges :: Vertex s -> ST s (CircularVector (HalfEdge s))+vertexOutgoingHalfEdges vertex = do+ tmp <- newVector 10+ iRef <- newSTRef 0+ vertexWithOutgoingHalfEdges vertex $ \edge -> do+ i <- readSTRef iRef+ modifySTRef' iRef succ+ writeVector tmp i edge+ i <- readSTRef iRef+ freezeCircularVector i tmp++-- | O(k), more efficient than 'vertexOutgoingHalfEdges'.+vertexWithOutgoingHalfEdges :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()+vertexWithOutgoingHalfEdges vertex cb = do+ first <- vertexHalfEdge vertex+ cb first+ let loop edge | edge == first = return ()+ loop edge = trace ("At edge: "++ show (first, edge)) $ do+ cb edge+ loop =<< halfEdgeNext (halfEdgeTwin edge)+ loop =<< halfEdgeNext (halfEdgeTwin first)++-- | O(k)+vertexIncomingHalfEdges :: Vertex s -> ST s (CircularVector (HalfEdge s))+vertexIncomingHalfEdges vertex = CV.map halfEdgeTwin <$> vertexOutgoingHalfEdges vertex++-- | O(k)+vertexWithIncomingHalfEdges :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()+vertexWithIncomingHalfEdges = undefined++-- | O(k)+vertexNeighbours :: Vertex s -> ST s (CircularVector (Vertex s))+vertexNeighbours vertex = CV.mapM halfEdgeVertex =<< vertexIncomingHalfEdges vertex++-- vertexAdjacentVertices :: Vertex -> PlanarGraph -> [Vertex]+-- vertexAdjacentFaces :: Vertex -> PlanarGraph -> [Face]++-- O(1), internal function.+vertexNew :: PlanarGraph s -> ST s (Vertex s)+vertexNew pg = do+ vId <- readSTRef (pgNextVertexId pg)+ writeSTRef (pgNextVertexId pg) (vId+1)+ return (Vertex vId pg)++vertexSetHalfEdge :: Vertex s -> HalfEdge s -> ST s ()+vertexSetHalfEdge (Vertex vId pg) (HalfEdge eId pg') = eqCheck "vertexSetHalfEdge" pg pg' $+ writeVector (pgVertexEdges pg) vId eId++-------------------------------------------------------------------------------+-- Edges++-- | O(1)+edgeFromId :: EdgeId -> PlanarGraph s -> Edge s+edgeFromId = Edge++-- | O(1)+edgeToId :: Edge s -> EdgeId+edgeToId (Edge e _) = e++-- | O(1)+edgeFromHalfEdge :: HalfEdge s -> Edge s+edgeFromHalfEdge (HalfEdge he pg) = Edge (he `div` 2) pg++-- | O(1)+edgeToHalfEdges :: Edge s -> (HalfEdge s, HalfEdge s)+edgeToHalfEdges (Edge e pg) = (HalfEdge (e*2) pg, HalfEdge (e*2+1) pg)++-------------------------------------------------------------------------------+-- Half-edges++-- | O(1)+halfEdgePlanarGraph :: HalfEdge s -> PlanarGraph s+halfEdgePlanarGraph (HalfEdge _ pg) = pg++-- | O(1)+halfEdgeIsValid :: HalfEdge s -> Bool+halfEdgeIsValid (HalfEdge eId _) = eId >= 0++-- | O(1)+halfEdgeFromId :: HalfEdgeId -> PlanarGraph s -> HalfEdge s+halfEdgeFromId eId pg = HalfEdge eId pg++-- | O(1)+halfEdgeToId :: HalfEdge s -> HalfEdgeId+halfEdgeToId (HalfEdge eId _pg) = eId++-- | O(1)+halfEdgeNext :: HalfEdge s -> ST s (HalfEdge s)+halfEdgeNext (HalfEdge eId pg) = do+ next <- readVector (pgHalfEdgeNext pg) eId+ pure $ HalfEdge next pg++-- | O(1)+halfEdgePrev :: HalfEdge s -> ST s (HalfEdge s)+halfEdgePrev (HalfEdge eId pg) = do+ prev <- readVector (pgHalfEdgePrev pg) eId+ pure $ HalfEdge prev pg++-- | O(1)+-- Next half-edge with the same vertex.+halfEdgeNextOutgoing :: HalfEdge s -> ST s (HalfEdge s)+halfEdgeNextOutgoing = halfEdgeNext . halfEdgeTwin++-- | O(1)+-- Next half-edge with the same vertex.+halfEdgeNextIncoming :: HalfEdge s -> ST s (HalfEdge s)+halfEdgeNextIncoming = halfEdgePrev . halfEdgeTwin++-- | O(1)+halfEdgeVertex :: HalfEdge s -> ST s (Vertex s)+halfEdgeVertex (HalfEdge idx pg) = do+ v <- readVector (pgHalfEdgeVertex pg) idx+ pure $ Vertex v pg++-- | O(1)+halfEdgeTwin :: HalfEdge s -> HalfEdge s+halfEdgeTwin (HalfEdge idx graph) = HalfEdge (idx `xor` 1) graph++-- | O(1)+-- Tail vertex. IE. the vertex of the twin edge.+halfEdgeTailVertex :: HalfEdge s -> ST s (Vertex s)+halfEdgeTailVertex = halfEdgeVertex++-- | O(1)+-- Synonym of `halfEdgeVertex`.+halfEdgeTipVertex :: HalfEdge s -> ST s (Vertex s)+halfEdgeTipVertex = halfEdgeVertex . halfEdgeTwin++-- | \( O(1) \)+--+-- ==== __Examples:__+-- @+-- 'pgFromFaces' [[0,1,2]]+-- @+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; show <$> halfEdgeFace (halfEdgeFromId 0 pg)+-- "Face 0"+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; show <$> halfEdgeFace (halfEdgeFromId 1 pg)+-- "Boundary 0"+--+halfEdgeFace :: HalfEdge s -> ST s (Face s)+halfEdgeFace (HalfEdge eId pg) = do+ fId <- readVector (pgHalfEdgeFace pg) eId+ pure $ faceFromId fId pg++-- | O(n)+-- Scan boundary half-edges without using 'next' or 'prev'.+halfEdgeConstructBoundary :: HalfEdge s -> ST s (CircularVector (HalfEdge s))+halfEdgeConstructBoundary halfEdge = {- trace ("mkBoundary from: " ++ show halfEdge) $ -} do+ tmp <- newVector 10+ writeVector tmp 0 halfEdge+ let loop i edge | edge == halfEdge = {- trace "Done" $ -} return i+ loop i edge = {- trace ("Going to: " ++ show edge) $ -} do+ face <- halfEdgeFace edge+ if faceIsInvalid face+ then do+ writeVector tmp i edge+ loop (i+1) =<< (halfEdgeTwin <$> halfEdgeNextIncoming edge)+ else+ loop i =<< (halfEdgeTwin <$> halfEdgePrev edge)+ i <- loop 1 =<< (halfEdgeTwin <$> halfEdgeNextIncoming halfEdge)+ cv <- freezeCircularVector i tmp+ -- trace ("Boundary: " ++ show cv) $ pure cv+ pure cv++-- | O(k)+halfEdgeWithLoop :: HalfEdge s -> (HalfEdge s -> ST s ()) -> ST s ()+halfEdgeWithLoop he cb = worker =<< halfEdgeNext he+ where+ worker edge+ | edge == he = return ()+ | otherwise = do cb edge; worker =<< halfEdgeNext edge++-- $setup+-- >>> let genPG = pgFromFaces [[0,1,2]]++-- | \( O(1) \)+-- Check if a half-edge's face is interior or exterior.+--+-- ==== __Examples:__+-- @+-- 'pgFromFaces' [[0,1,2]]+-- @+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; halfEdgeIsInterior (halfEdgeFromId 0 pg)+-- True+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; halfEdgeIsInterior (halfEdgeFromId 1 pg)+-- False+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; halfEdgeIsInterior (halfEdgeFromId 2 pg)+-- True+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; halfEdgeIsInterior (halfEdgeFromId 3 pg)+-- False+halfEdgeIsInterior :: HalfEdge s -> ST s Bool+halfEdgeIsInterior edge = faceIsInterior <$> halfEdgeFace edge++-- O(1) Allocate new half-edge pair.+halfEdgeNew :: PlanarGraph s -> ST s (HalfEdge s)+halfEdgeNew pg = do+ eId <- readSTRef (pgNextHalfEdgeId pg)+ writeSTRef (pgNextHalfEdgeId pg) (eId+1)+ return (HalfEdge (eId*2) pg)++halfEdgeSetNext :: HalfEdge s -> HalfEdge s -> ST s ()+halfEdgeSetNext (HalfEdge e pg) (HalfEdge next pg') = eqCheck "halfEdgeSetNext" pg pg' $+ -- trace ("Set next: " ++ show (e, next)) $+ writeVector (pgHalfEdgeNext pg) e next++halfEdgeSetPrev :: HalfEdge s -> HalfEdge s -> ST s ()+halfEdgeSetPrev (HalfEdge e pg) (HalfEdge prev pg') = eqCheck "halfEdgeSetPrev" pg pg' $+ -- trace ("Set prev: " ++ show (e, prev)) $+ writeVector (pgHalfEdgePrev pg) e prev++halfEdgeSetFace :: HalfEdge s -> Face s -> ST s ()+halfEdgeSetFace (HalfEdge e pg) face =+ -- trace ("Set face: " ++ show (e, face)) $+ writeVector (pgHalfEdgeFace pg) e (faceToId face)++halfEdgeSetVertex :: HalfEdge s -> Vertex s -> ST s ()+halfEdgeSetVertex (HalfEdge e pg) vertex =+ -- trace ("Set vertex: " ++ show (e, vertex)) $+ writeVector (pgHalfEdgeVertex pg) e (vertexToId vertex)++-------------------------------------------------------------------------------+-- Faces++-- | O(1)+faceInvalid :: PlanarGraph s -> Face s+faceInvalid = faceFromId maxBound++-- | O(1)+faceIsValid :: Face s -> Bool+faceIsValid = not . faceIsInvalid++-- | O(1)+faceIsInvalid :: Face s -> Bool+faceIsInvalid (Face fId _) = fId == maxBound+faceIsInvalid (Boundary fId _) = fId == maxBound++-- | O(1)+faceFromId :: FaceId -> PlanarGraph s -> Face s+faceFromId fId pg | fId < 0 = Boundary (negate fId - 1) pg+faceFromId fId pg = Face fId pg++-- | O(1)+faceToId :: Face s -> FaceId+faceToId (Face fId _) = fId+faceToId (Boundary fId _) = negate fId - 1++-- | O(1)+faceHalfEdge :: Face s -> ST s (HalfEdge s)+faceHalfEdge (Face fId pg) = do+ eId <- readVector (pgFaceEdges pg) fId+ pure $ HalfEdge eId pg+faceHalfEdge (Boundary fId pg) = do+ eId <- readVector (pgBoundaryEdges pg) fId+ pure $ HalfEdge eId pg++-- | O(1)+faceIsInterior :: Face s -> Bool+faceIsInterior = not . faceIsBoundary++-- | O(1)+faceIsBoundary :: Face s -> Bool+faceIsBoundary Face{} = False+faceIsBoundary Boundary{} = True++-- faceVertices :: Face s -> ST s (CircularVector (Vertex s))++-- | O(k)+-- Counterclockwise vector of edges.+faceHalfEdges :: Face s -> ST s (CircularVector (HalfEdge s))+faceHalfEdges face+ | faceIsBoundary face = worker halfEdgeNext+ | otherwise = worker halfEdgePrev+ where+ worker advance = do+ first <- faceHalfEdge face+ tmp <- newVector 10+ writeVector tmp 0 first+ let loop i edge | edge == first = return i+ loop i edge = do+ writeVector tmp i edge+ loop (i+1) =<< advance edge+ i <- loop 1 =<< advance first+ freezeCircularVector i tmp++-- | O(k)+faceBoundary :: Face s -> ST s (CircularVector (Vertex s))+faceBoundary face = CV.mapM halfEdgeVertex =<< faceHalfEdges face++-- faceAdjacentFaces :: Face s -> ST s (CircularVector (Face s))++faceNew :: PlanarGraph s -> ST s (Face s)+faceNew pg = do+ fId <- readSTRef (pgNextFaceId pg)+ writeSTRef (pgNextFaceId pg) (fId+1)+ return (Face fId pg)++faceNewBoundary :: PlanarGraph s -> ST s (Face s)+faceNewBoundary pg = do+ fId <- readSTRef (pgNextBoundaryId pg)+ writeSTRef (pgNextBoundaryId pg) (fId+1)+ return (Boundary fId pg)++faceSetHalfEdge :: Face s -> HalfEdge s -> ST s ()+faceSetHalfEdge (Boundary fId pg) (HalfEdge eId pg') = eqCheck "faceSetHalfEdge" pg pg' $+ -- trace ("faceSetHalfEdge: " ++ show (fId, eId)) $+ writeVector (pgBoundaryEdges pg) fId eId+faceSetHalfEdge (Face fId pg) (HalfEdge eId pg') = eqCheck "faceSetHalfEdge" pg pg' $+ writeVector (pgFaceEdges pg) fId eId++-------------------------------------------------------------------------------+-- Mutation++-- | O(k) where @k@ is the number of edges in new face.+--+-- The two half-edges must be different, must have the same face, and may not be+-- consecutive. The first half-edge will stay in the original face. The second+-- half-edge will be in the newly created face.+--+-- ==== __Examples:__+--+-- @+-- 'pgFromFaces' [[0,1,2,3]]+-- @+--+-- <<docs/Data/PlanarGraph/planargraph-2506803680640023584.svg>>+--+-- @+-- do pg <- 'pgFromFaces' [[0,1,2,3]]+-- let he0 = 'halfEdgeFromId' 0 pg'+-- he4 = 'halfEdgeFromId' 4 pg'+-- 'pgConnectVertices' he0 he4+-- @+--+-- <<docs/Data/PlanarGraph/planargraph-1902492848341357096.svg>>+pgConnectVertices :: HalfEdge s -> HalfEdge s -> ST s (Edge s)+pgConnectVertices e1 e2 =+ eqCheck "pgConnectVertices" (halfEdgePlanarGraph e1) (halfEdgePlanarGraph e2) $ do+ let pg = halfEdgePlanarGraph e1+ when (e1 == e2) $ fail "Edges must be different"+ f1 <- halfEdgeFace e1+ f2 <- halfEdgeFace e2+ unless (f1==f2) $ fail "Faces must be the same"+ e1' <- halfEdgeNext e1+ e2' <- halfEdgeNext e2+ when (e1' == e2 || e2' == e1) $ fail "Edges must not be consecutive"++ e1_prev <- halfEdgePrev e1+ e2_prev <- halfEdgePrev e2++ he <- halfEdgeNew pg+ halfEdgeSetFace he f1+ let he' = halfEdgeTwin he+ + halfEdgeSetVertex he =<< halfEdgeVertex e2+ halfEdgeSetVertex he' =<< halfEdgeVertex e1++ halfEdgeSetNext he e1+ halfEdgeSetPrev he e2_prev++ halfEdgeSetNext he' e2+ halfEdgeSetPrev he' =<< halfEdgePrev e1++ halfEdgeSetPrev e1 he+ halfEdgeSetNext e2_prev he++ halfEdgeSetNext e1_prev he'+ halfEdgeSetPrev e2 he'++ face <- faceNew pg+ faceSetHalfEdge face he'+ halfEdgeWithLoop he' (`halfEdgeSetFace` face)++ pure $ Edge (halfEdgeToId he `div` 2) pg++-- pgInsertVertex :: HalfEdge s -> ST s (Vertex s)++-- pgRemoveEdge :: Edge s -> ST s ()+-- pgRemoveEdges :: [Edge s] -> ST s ()+-- pgRemoveVertex :: Vertex s -> ST s ()+-- pgRemoveBorder :: Edge s -> ST s ()++-------------------------------------------------------------------------------+-- Use cases++-- Use cases:+-- Triangulate polygon.+-- Create PlanarGraph from polygon. Holes have unique faces.+-- Update with [LineSegment 2 Vertex r]+-- Update Face ids at the end.+-- Cut planar graph in two.+-- Re-triangulate part of graph.+-- Mesh smoothing.+-- 1. Keep vertex positions separate. Can update without changing the graph.+-- 2. Swap edges. HalfEdge+Twin. Find next of each. Delete original half-edges.+-- Then insert half-edges to next.
+ src/Data/PlanarGraph/Persistent.hs view
@@ -0,0 +1,71 @@+module Data.PlanarGraph.Persistent where++import Data.HashMap.Strict+import Control.Monad.State++type HalfEdge = Int+type Vertex = Int+type Face = Int++-- PlanarGraphs have vertices, edges, and faces.+-- Invariant: The half-edge of a boundary vertex is interior, twin is exterior.+data PlanarGraph = PlanarGraph+ { pgNextHalfEdgeId :: HalfEdge+ , pgNextVertexId :: Vertex+ , pgNextFaceId :: Face+ , pgNext :: HashMap HalfEdge HalfEdge+ , pgVertex :: HashMap HalfEdge Vertex+ , pgFace :: HashMap HalfEdge Face+ , pgHalfEdgeFromVertex :: HashMap Vertex HalfEdge+ , pgHalfEdgeFromFace :: HashMap Face HalfEdge+ }++-- data PlaneGraph r = PlaneGraph PlanarGraph (HashMap Vertex (Point 2 r))++new :: Int -> PlanarGraph+new = undefined++-- O(log n)+-- vertexHalfEdge :: Vertex -> PlanarGraph -> HalfEdge+-- O(k log n)+-- vertexOutgoingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]+-- O(k log n)+-- vertexIncomingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]+-- vertexAdjacentVertices :: Vertex -> PlanarGraph -> [Vertex]+-- vertexAdjacentFaces :: Vertex -> PlanarGraph -> [Face]++halfEdgeNext :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgeNext = undefined++halfEdgeNextM :: MonadState PlanarGraph m => HalfEdge -> m HalfEdge+halfEdgeNextM = gets . halfEdgeNext++-- halfEdgeNext :: HalfEdge -> PlanarGraph -> HalfEdge+-- halfEdgeVertex :: HalfEdge -> PlanarGraph -> Vertex+-- halfEdgeTwin :: HalfEdge -> PlanarGraph -> HalfEdge+-- halfEdgeTailVertex :: HalfEdge -> PlanarGraph -> Vertex+-- halfEdgeTipVertex :: HalfEdge -> PlanarGraph -> Vertex+-- halfEdgeFace :: HalfEdge -> PlanarGraph -> Face+-- halfEdgeIsInterior++-- faceHalfEdge :: Face -> PlanarGraph -> HalfEdge+-- faceIsInterior+-- faceIsBoundary+-- faceAdjacentVertices :: +-- faceAdjaventFaces :: Face -> PlanarGraph -> [Face]++-- connectVertices :: HalfEdge -> HalfEdge -> PlanarGraph -> PlanarGraph+-- splitHalfEdge :: HalfEdge -> PlanarGraph -> (PlanarGraph, Vertex)++-- Use cases:+-- Triangulate polygon.+-- Create PlanarGraph from polygon. Holes have unique faces.+-- Update with [LineSegment 2 Vertex r]+-- Update Face ids at the end.+-- Cut planar graph in two.+-- Re-triangulate part of graph.+-- Mesh smoothing.+-- 1. Keep vertex positions separate. Can update without changing the graph.+-- 2. Swap edges. HalfEdge+Twin. Find next of each. Delete original half-edges.+-- Then insert half-edges to next.+
src/Data/Range.hs view
@@ -14,10 +14,9 @@ module Data.Range( EndPoint(..) , isOpen, isClosed , unEndPoint- , Range(..)+ , Range(.., OpenRange, ClosedRange, Range') , prettyShow , lower, upper- , pattern OpenRange, pattern ClosedRange, pattern Range' , inRange, width, clipLower, clipUpper, midPoint, clampTo , isValid, covers @@ -26,11 +25,13 @@ import Control.DeepSeq import Control.Lens+import Control.Applicative import Data.Intersection import Data.Vinyl.CoRec import GHC.Generics (Generic) import Test.QuickCheck-import Text.Printf (printf)+import Data.Functor.Classes+import Text.Read -------------------------------------------------------------------------------- -- * Representing Endpoints of a Range@@ -38,8 +39,26 @@ -- | Endpoints of a range may either be open or closed. data EndPoint a = Open !a | Closed !a- deriving (Show,Read,Eq,Functor,Foldable,Traversable,Generic,NFData)+ deriving (Eq,Functor,Foldable,Traversable,Generic,NFData) +instance (Show a) => Show (EndPoint a) where+ showsPrec = liftShowsPrec showsPrec showList++instance Show1 EndPoint where+ liftShowsPrec sp _sl d (Open a) = showsUnaryWith sp "Open" d a+ liftShowsPrec sp _sl d (Closed a) = showsUnaryWith sp "Closed" d a++instance (Read a) => Read (EndPoint a) where+ readPrec = liftReadPrec readPrec readListPrec+ readListPrec = readListPrecDefault++instance Read1 EndPoint where+ liftReadPrec rp _rl = readData $+ readUnaryWith rp "Open" Open <|>+ readUnaryWith rp "Closed" Closed+ liftReadListPrec = liftReadListPrecDefault++ instance Ord a => Ord (EndPoint a) where -- | order on the actual value, and Open before Closed a `compare` b = f a `compare` f b@@ -56,6 +75,14 @@ _unEndPoint (Open a) = a _unEndPoint (Closed a) = a +-- | Access lens for EndPoint value regardless of whether it is open or closed.+--+-- >>> Open 5 ^. unEndPoint+-- 5+-- >>> Closed 10 ^. unEndPoint+-- 10+-- >>> Open 4 & unEndPoint .~ 0+-- Open 0 unEndPoint :: Lens (EndPoint a) (EndPoint b) a b unEndPoint = lens _unEndPoint f where@@ -63,10 +90,12 @@ f (Closed _) a = Closed a {-# INLINE unEndPoint #-} +-- | True iff EndPoint is open. isOpen :: EndPoint a -> Bool-isOpen (Open _) = True-isOpen _ = False+isOpen Open{} = True+isOpen _ = False +-- | True iff EndPoint is closed. isClosed :: EndPoint a -> Bool isClosed = not . isOpen @@ -79,12 +108,35 @@ , _upper :: !(EndPoint a) } deriving (Eq,Functor,Foldable,Traversable,Generic,NFData)-makeLenses ''Range -instance Show a => Show (Range a) where- show (Range l u) = printf "Range (%s) (%s)" (show l) (show u)+-- | Lens access for the lower part of a range.+lower :: Lens' (Range a) (EndPoint a)+lower = lens _lower (\r l -> r{_lower=l}) +-- | Lens access for the upper part of a range.+upper :: Lens' (Range a) (EndPoint a)+upper = lens _upper (\r u -> r{_upper=u}) +-- instance Show a => Show (Range a) where+-- show (Range l u) = printf "Range (%s) (%s)" (show l) (show u)++instance (Show a) => Show (Range a) where+ showsPrec = liftShowsPrec showsPrec showList++instance Show1 Range where+ liftShowsPrec sp sl d (Range l u) =+ showsBinaryWith (liftShowsPrec sp sl) (liftShowsPrec sp sl) "Range" d l u++instance (Read a) => Read (Range a) where+ readPrec = liftReadPrec readPrec readListPrec+ readListPrec = readListPrecDefault++instance Read1 Range where+ liftReadPrec rp rl = readData $+ readBinaryWith (liftReadPrec rp rl) (liftReadPrec rp rl) "Range" Range+ liftReadListPrec = liftReadListPrecDefault++ pattern OpenRange :: a -> a -> Range a pattern OpenRange l u = Range (Open l) (Open u) @@ -156,7 +208,7 @@ type instance IntersectionOf (Range a) (Range a) = [ NoIntersection, Range a] -instance Ord a => (Range a) `IsIntersectableWith` (Range a) where+instance Ord a => Range a `IsIntersectableWith` Range a where nonEmptyIntersection = defaultNonEmptyIntersection @@ -174,6 +226,7 @@ width :: Num r => Range r -> r width i = i^.upper.unEndPoint - i^.lower.unEndPoint +-- | Compute the halfway point between the start and end of a range. midPoint :: Fractional r => Range r -> r midPoint r = let w = width r in r^.lower.unEndPoint + (w / 2) @@ -213,14 +266,14 @@ -- | Wether or not the first range completely covers the second one covers :: forall a. Ord a => Range a -> Range a -> Bool-x `covers` y = maybe False (== y) . asA @(Range a) $ x `intersect` y+x `covers` y = (== Just y) . asA @(Range a) $ x `intersect` y -- | Check if the range is valid and nonEmpty, i.e. if the lower endpoint is -- indeed smaller than the right endpoint. Note that we treat empty open-ranges -- as invalid as well. isValid :: Ord a => Range a -> Bool-isValid (Range l u) = case (_unEndPoint l) `compare` (_unEndPoint u) of+isValid (Range l u) = case _unEndPoint l `compare` _unEndPoint u of LT -> True EQ | isClosed l || isClosed u -> True _ -> False@@ -238,7 +291,7 @@ -- | Compare end points, Closed < Open cmpLower :: Ord a => EndPoint a -> EndPoint a -> Ordering-cmpLower a b = case (_unEndPoint a) `compare` (_unEndPoint b) of+cmpLower a b = case _unEndPoint a `compare` _unEndPoint b of LT -> LT GT -> GT EQ -> case (a,b) of@@ -250,7 +303,7 @@ -- | Compare the end points, Open < Closed cmpUpper :: Ord a => EndPoint a -> EndPoint a -> Ordering-cmpUpper a b = case (_unEndPoint a) `compare` (_unEndPoint b) of+cmpUpper a b = case _unEndPoint a `compare` _unEndPoint b of LT -> LT GT -> GT EQ -> case (a,b) of
src/Data/RealNumber/Rational.hs view
@@ -1,18 +1,30 @@ {-# LANGUAGE DeriveDataTypeable #-}+--------------------------------------------------------------------------------+-- |+-- Module : Data.RealNumber.Rational+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.RealNumber.Rational(RealNumber(..) -- * Converting to and from RealNumber's , AsFixed(..), asFixed , toFixed, fromFixed+ , Nat ) where +import Data.Aeson import Data.Data import Data.Fixed import Data.Hashable-import Data.List (dropWhileEnd)-import GHC.Generics (Generic(..))+import Data.List (dropWhileEnd)+import GHC.Generics (Generic (..)) import GHC.TypeLits-import Test.QuickCheck(Arbitrary(..))+import Test.QuickCheck (Arbitrary (..))+import Control.Monad.Random+import Data.Ratio+import Control.DeepSeq -------------------------------------------------------------------------------- @@ -27,19 +39,21 @@ -- If the number cannot be displayed exactly a '~' is printed after -- the number. newtype RealNumber (p :: Nat) = RealNumber Rational- deriving (Eq,Ord,Data,Num,Fractional,Real,RealFrac,Generic,Hashable)-+ deriving (Eq,Ord,Data,Num,Fractional,Real,RealFrac,Generic,Hashable,ToJSON,FromJSON,NFData) data NatPrec (p :: Nat) = NatPrec instance KnownNat p => HasResolution (NatPrec p) where- resolution _ = 10 ^ (1 + natVal (NatPrec @p))+ resolution _ = 10 ^ (natVal (NatPrec @p)) instance KnownNat p => Show (RealNumber p) where- show r = case asFixed r of- Exact p -> dropWhileEnd (== '.') . dropWhileEnd (== '0') . show $ p- Lossy p -> (<> "~") . show $ p+ showsPrec d r = showParen (d > app_prec && r < 0) $+ case asFixed r of+ Exact p -> showString (dropWhileEnd (== '.') . dropWhileEnd (== '0') . show $ p)+ Lossy p -> shows p . showChar '~'+ where+ app_prec = 10 instance KnownNat p => Read (RealNumber p) where readsPrec i = map wrap . readsPrec @(Fixed (NatPrec p)) i@@ -51,18 +65,37 @@ instance KnownNat p => Arbitrary (RealNumber p) where arbitrary = fromFixed <$> arbitrary --------------------------------------------------------------------------------- +instance Random (RealNumber p) where+ -- Generate a random number between a and b with 'maxBound `div` 2 :: Int' discrete increments.+ randomR (a,b) = runRand $ do+ v <- getRandom+ pure $ (b-a)*abs v + a+ -- Generate a random number between -1 and +1 with 'maxBound::Int' discrete increments.+ random = runRand $ do+ v <- getRandom+ let fromInt :: Int -> Integer; fromInt = fromIntegral+ pure $ RealNumber $ fromInt v % fromInt maxBound +-------------------------------------------------------------------------------- ++-- | Fixed-precision representation of a 'RealNumber'. If there's insufficient+-- precision to accurately represent the 'RealNumber' then the 'Lossy' constructor+-- will be used. data AsFixed p = Exact !(Fixed p) | Lossy !(Fixed p) deriving (Show,Eq) +-- | Cast 'RealNumber' to a fixed-precision number. Data is silently lost if there's+-- insufficient precision. toFixed :: KnownNat p => RealNumber p -> Fixed (NatPrec p) toFixed = realToFrac +-- | Cast a fixed-precision number to a 'RealNumber'. fromFixed :: KnownNat p => Fixed (NatPrec p) -> RealNumber p fromFixed = realToFrac +-- | Cast 'RealNumber' to a fixed-precision number. Data-loss caused by insufficient+-- precision will be marked by the 'Lossy' constructor. asFixed :: KnownNat p => RealNumber p -> AsFixed (NatPrec p) asFixed r = let p = toFixed r in if r == fromFixed p then Exact p else Lossy p
src/Data/Sequence/Util.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.Sequence.Util+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.Sequence.Util where import Algorithms.BinarySearch@@ -16,6 +23,6 @@ -- running time: \(O(\log^2 n + T*\log n)\), where \(T\) is the time to execute the -- predicate. splitMonotone :: (a -> Bool) -> Seq a -> (Seq a, Seq a)-splitMonotone p s = case binarySearchSeq p s of+splitMonotone p s = case binarySearchIdxIn p s of Nothing -> (s,S.empty) Just i -> S.splitAt i s
src/Data/Set/Util.hs view
@@ -1,16 +1,23 @@+--------------------------------------------------------------------------------+-- |+-- Module : Data.Set.Util+-- Copyright : (C) Frank Staals+-- License : see the LICENSE file+-- Maintainer : Frank Staals+-------------------------------------------------------------------------------- module Data.Set.Util where import Data.DynamicOrd-import qualified Data.Set as Set import Data.Set (Set)+import qualified Data.Set as Set import qualified Data.Set.Internal as Internal --- import Data.Ord(comparing)+import Data.Ord (comparing) --- data S = S String deriving Show--- cmpS :: S -> S -> Ordering--- cmpS = comparing (\(S s) -> length s)+data S = S String deriving Show+cmpS :: S -> S -> Ordering+cmpS = comparing (\(S s) -> length s) -- $setup@@ -32,6 +39,18 @@ g c y = y `compare` x == c in (l,m,r) +-- | Given a monotonic function f that orders @a@, split the sequence @s@+-- into three parts. I.e. the result (lt,eq,gt) is such that+-- * all (\x -> f x == LT) . fmap f $ lt+-- * all (\x -> f x == EQ) . fmap f $ eq+-- * all (\x -> f x == GT) . fmap f $ gt+--+-- running time: \(O(\log n)\)+splitBy :: (a -> Ordering) -> Set a -> (Set a, Set a, Set a)+splitBy f s = let (l,s') = Set.spanAntitone ((==) LT . f) s+ (m,r) = Set.spanAntitone ((==) EQ . f) s'+ in (l,m,r)+ -- | Constructs a Set using the given Order. -- -- Note that this is dangerous as the resulting set may not abide the@@ -78,3 +97,44 @@ -- running time: \(O(\log n)\) deleteAllBy :: (a -> a -> Ordering) -> a -> Set a -> Set a deleteAllBy cmp x s = withOrd cmp $ liftOrd1 (Set.delete $ O x) s++-- | Run a query, eg. lookupGE, on the set with the given ordering.+--+-- Note: The 'Algorithms.BinarySearch.binarySearchIn' function may be+-- a useful alternative to 'queryBy'+--+-- >>> queryBy cmpS Set.lookupGE (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]+-- Just (S "bbb")+-- >>> queryBy cmpS Set.lookupLE (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]+-- Just (S "a")+-- >>> queryBy cmpS Set.lookupGE (S "333") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]+-- Just (S "bbb")+queryBy :: (a -> a -> Ordering)+ -> (forall b. Ord b => b -> Set b -> t b)+ -> a -> Set a -> t a+queryBy cmp fs q s = withOrd cmp $ liftOrd1 (fs $ O q) s+++++-- queryBy' :: Ord r+-- => (a -> r)+-- -> r+-- -> (forall b. Ord b => b -> Set b -> t b)+-- -> a -> Set a -> t a+-- queryBy' g fs q s = queryBy+-- where++++-- withOrd cmp $ liftOrd1 (fs $ O q) s++++ -- withOrd cmp $ liftOrd1 (Set.lookupGE $ O q) s+++++test = queryBy cmpS Set.lookupGE (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]+-- test = succBy cmpS (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]
src/Data/Tree/Util.hs view
@@ -1,3 +1,4 @@+-- | Tree-related utilities. module Data.Tree.Util where import Data.Bifoldable@@ -79,16 +80,16 @@ -- Just (Zipper {focus = Node {rootLabel = 2, subForest = []}, ancestors = [([Node {rootLabel = 1, subForest = []}],0,[Node {rootLabel = 3, subForest = [Node {rootLabel = 4, subForest = []}]}])]}) nextSibling :: Zipper a -> Maybe (Zipper a) nextSibling (Zipper t as) = case as of- [] -> Nothing -- no parent- ((_,_,[]):_) -> Nothing -- no next sibling- ((ls,p,(r:rs)):as') -> Just $ Zipper r ((t:ls,p,rs):as')+ [] -> Nothing -- no parent+ ((_,_,[]):_) -> Nothing -- no next sibling+ ((ls,p,r:rs):as') -> Just $ Zipper r ((t:ls,p,rs):as') -- | Move the focus to the next sibling of this node prevSibling :: Zipper a -> Maybe (Zipper a) prevSibling (Zipper t as) = case as of- [] -> Nothing -- no parent- (([],_,_):_) -> Nothing -- no prev sibling- (((l:ls),p,rs):as') -> Just $ Zipper l ((ls,p,t:rs):as')+ [] -> Nothing -- no parent+ (([],_,_):_) -> Nothing -- no prev sibling+ ((l:ls,p,rs):as') -> Just $ Zipper l ((ls,p,t:rs):as') -- | Given a zipper that focussses on some subtree t, construct a list with -- zippers that focus on each child.@@ -132,15 +133,15 @@ -- running time: \(O(nT(n))\) where \(n\) is the size of the tree, and \(T(m)\) is -- the time to evaluate a predicate on a subtree of size \(m\). findEvert' :: (Tree a -> Bool) -> Tree a -> Maybe (Tree a)-findEvert' p = fmap unZipperLocal . listToMaybe . filter (p . focus) . allTrees . root+findEvert' p = fmap unZipperLocal . List.find (p . focus) . allTrees . root -- | Function to extract a path between a start node and an end node (if such a --path exists). If there are multiple paths, no guarantees are given about --which one is returned. -- -- running time: \(O(n(T_p+T_s)\), where \(n\) is the size of the tree, and--- \(T_p\) and \(T_s\) are the times it takes to evaluate the 'isStartingNode'--- and 'isEndingNode' predicates.+-- \(T_p\) and \(T_s\) are the times it takes to evaluate the @isStartingNode@+-- and @isEndingNode@ predicates. -- -- -- >>> findPath (== 1) (==4) myTree@@ -179,7 +180,7 @@ findNodes :: (Tree a -> Bool) -> Tree a -> [[a]] findNodes p = go where- go t = let mh = if p t then [[]] else []+ go t = let mh = [ [] | p t ] -- [[]] iff 'p t' in map (rootLabel t:) $ mh <> concatMap go (children t)
src/Data/UnBounded.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TemplateHaskell #-} -------------------------------------------------------------------------------- -- | -- Module : Data.UnBounded@@ -7,39 +8,40 @@ -- Maintainer : Frank Staals -- -- Add an unbounded/infintity element to a data type. Essentially,--- 'Bottom' adds \(-\infty\) (and is pretty much identical to Maybe),--- whereas 'Top' adds \(\infty\). The Unbounded type adds both.+-- t'Bottom' adds \(-\infty\) (and is pretty much identical to Maybe),+-- whereas t'Top' adds \(\infty\). The 'UnBounded' type adds both. -- ---------------------------------------------------------------------------------module Data.UnBounded( Top, topToMaybe- , pattern ValT, pattern Top+module Data.UnBounded( Top( ValT, Top), topToMaybe , _ValT, _Top, _TopMaybe - , Bottom, bottomToMaybe- , pattern Bottom, pattern ValB+ , Bottom(Bottom, ValB), bottomToMaybe , _ValB, _Bottom, _BottomMaybe , UnBounded(..)- , unUnBounded- , _MinInfinity, _Val, _MaxInfinity+ , _Val , unBoundedToMaybe ) where import Control.Lens-import qualified Data.Foldable as F-import qualified Data.Traversable as T+import qualified Data.Foldable as F import Data.Functor.Classes+import qualified Data.Traversable as T -------------------------------------------------------------------------------- -- * Top and Bottom --- | `Top a` represents the type a, together with a 'Top' element, i.e. an element+-- | @Top a@ represents the type a, together with a v'Top' element, i.e. an element -- that is greater than any other element. We can think of `Top a` being defined as: -- -- >>> data Top a = ValT a | Top-newtype Top a = GTop { topToMaybe :: Maybe a }+newtype Top a = GTop (Maybe a) deriving (Eq,Functor,F.Foldable,T.Traversable,Applicative,Monad,Eq1) +-- | @Top a@ values are isomorphing to @Maybe a@ values.+topToMaybe :: Top a -> Maybe a+topToMaybe (GTop mb) = mb+ pattern ValT :: a -> Top a pattern ValT x = GTop (Just x) @@ -62,14 +64,22 @@ show Top = "Top" show ~(ValT x) = "ValT " ++ show x +-- | 'ValT' prism. Can be used to access the non-bottom element if it exists:+--+-- >>> ValT True & _ValT %~ not+-- ValT False+--+-- >>> Top & _ValT %~ not+-- Top _ValT :: Prism (Top a) (Top b) a b-_ValT = prism ValT (\ta -> case ta of Top -> Left Top ; ValT x -> Right x)+_ValT = prism ValT (\case Top -> Left Top ; ValT x -> Right x) +-- | t'Top' prism. _Top :: Prism' (Top a) ()-_Top = prism' (const Top) (\ta -> case ta of Top -> Just () ; ValT _ -> Nothing)+_Top = prism' (const Top) (\case Top -> Just () ; ValT _ -> Nothing) --- | Iso between a 'Top a' and a 'Maybe a', interpreting a Top as a--- Nothing and vice versa. Note that this reverses the ordering of+-- | Iso between a @Top a@ and a @Maybe a@, interpreting a v'Top' as a+-- 'Nothing' and vice versa. Note that this reverses the ordering of -- the elements. -- -- >>> ValT 5 ^. _TopMaybe@@ -85,14 +95,18 @@ -------------------------------------------------------------------------------- --- | `Bottom a` represents the type a, together with a 'Bottom' element,+-- | @`Bottom a`@ represents the type a, together with a v'Bottom' element, -- i.e. an element that is smaller than any other element. We can think of--- `Bottom a` being defined as:+-- @`Bottom a`@ being defined as: -- -- >>> data Bottom a = Bottom | ValB a-newtype Bottom a = GBottom { bottomToMaybe :: Maybe a }+newtype Bottom a = GBottom (Maybe a) deriving (Eq,Ord,Functor,F.Foldable,T.Traversable,Applicative,Monad,Eq1,Ord1) +-- | `Bottom a` values are isomorphing to `Maybe a` values.+bottomToMaybe :: Bottom a -> Maybe a+bottomToMaybe (GBottom mb) = mb+ pattern Bottom :: Bottom a pattern Bottom = GBottom Nothing @@ -105,11 +119,19 @@ show Bottom = "Bottom" show ~(ValB x) = "ValB " ++ show x +-- | 'ValB' prism. Can be used to access the non-bottom element if it exists:+--+-- >>> ValB True & _ValB %~ not+-- ValB False+--+-- >>> Bottom & _ValB %~ not+-- Bottom _ValB :: Prism (Bottom a) (Bottom b) a b-_ValB = prism ValB (\ba -> case ba of Bottom -> Left Bottom ; ValB x -> Right x)+_ValB = prism ValB (\case Bottom -> Left Bottom ; ValB x -> Right x) +-- | t'Bottom' prism. _Bottom :: Prism' (Bottom a) ()-_Bottom = prism' (const Bottom) (\ba -> case ba of Bottom -> Just () ; ValB _ -> Nothing)+_Bottom = prism' (const Bottom) (\case Bottom -> Just () ; ValB _ -> Nothing) -- | Iso between a 'Bottom a' and a 'Maybe a', interpreting a Bottom as a -- Nothing and vice versa.@@ -132,8 +154,26 @@ -- smaller than any other element. data UnBounded a = MinInfinity | Val { _unUnBounded :: a } | MaxInfinity deriving (Eq,Ord,Functor,F.Foldable,T.Traversable)-makeLenses ''UnBounded-makePrisms ''UnBounded++-- | Prism to access unbounded value if it exists.+--+-- >>> Val True ^? _Val+-- Just True+--+-- >>> MinInfinity ^? _Val :: Maybe Bool+-- Nothing+--+-- >>> Val True & _Val %~ not+-- Val False+--+-- >>> MaxInfinity & _Val %~ not+-- MaxInfinity+_Val :: Prism (UnBounded a) (UnBounded b) a b+_Val = prism Val fromUnBounded+ where+ fromUnBounded MinInfinity = Left MinInfinity+ fromUnBounded MaxInfinity = Left MaxInfinity+ fromUnBounded (Val v) = Right v instance Show a => Show (UnBounded a) where show MinInfinity = "MinInfinity"
src/Data/Util.hs view
@@ -48,6 +48,7 @@ -- | Strict Triple with all items the same type Three = V3 +-- | Pattern synonym for strict triples. pattern Three :: a -> a -> a -> Three a pattern Three a b c = V3 a b c {-# COMPLETE Three #-}@@ -89,6 +90,7 @@ -- | Strict pair with both items the same type Two = V2 +-- | Pattern synonym for strict pairs. pattern Two :: a -> a -> Two a pattern Two a b = V2 a b {-# COMPLETE Two #-}
+ src/Data/Vector/Circular/Util.hs view
@@ -0,0 +1,74 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+--------------------------------------------------------------------------------+-- |+-- Module : Data.Vector.Circular.Util+-- Copyright : (C) Frank Staals, David Himmelstrup+-- License : see the LICENSE file+-- Maintainer : David Himmelstrup+--------------------------------------------------------------------------------+module Data.Vector.Circular.Util where++import Algorithms.StringSearch.KMP (isSubStringOf)+import Control.Lens+import Data.Ext+import Data.Maybe+import Data.Semigroup.Foldable+import qualified Data.Vector as V+import Data.Vector.Circular as CV+import qualified Data.Vector.NonEmpty as NV+import Test.QuickCheck (Arbitrary (..), NonEmptyList (..))+++-- FIXME: Upstream this to the non-empty vector library?+instance Foldable1 NV.NonEmptyVector++-- | Access the ith item in the CircularVector (w.r.t the rotation) as a lens+item :: Int -> Lens' (CircularVector a) a+item i = lens (`CV.index` i) (\s x -> unsafeFromVector (toVector s V.// [(i,x)]))++-- | All elements, starting with the focus, going to the right+--+-- >>> rightElements $ unsafeFromList [3,4,5,1,2]+-- [3,4,5,1,2]+rightElements :: CircularVector a -> NV.NonEmptyVector a+rightElements = toNonEmptyVector++-- | All elements, starting with the focus, going to the left+--+-- >>> leftElements $ unsafeFromList [3,4,5,1,2]+-- [3,2,1,5,4]+leftElements :: CircularVector a -> NV.NonEmptyVector a+leftElements v = NV.generate1 (length v) (CV.index v . negate)++-- | Finds an element in the CircularVector+--+-- >>> findRotateTo (== 3) $ unsafeFromList [1..5]+-- Just (CircularVector {vector = [1,2,3,4,5], rotation = 2})+-- >>> findRotateTo (== 7) $ unsafeFromList [1..5]+-- Nothing+findRotateTo :: (a -> Bool) -> CircularVector a -> Maybe (CircularVector a)+findRotateTo p (CircularVector v _rot) = CircularVector v <$> NV.findIndex p v++-- | Test if the circular list is a cyclic shift of the second+-- list.+--+-- Running time: \(O(n+m)\), where \(n\) and \(m\) are the sizes of+-- the lists.+isShiftOf :: Eq a => CircularVector a -> CircularVector a -> Bool+xs `isShiftOf` ys = let twice zs = let zs' = leftElements zs in zs' <> zs'+ once = leftElements+ check as bs = isJust $ once as `isSubStringOf` twice bs+ in length xs == length ys && check xs ys++instance Arbitrary a => Arbitrary (CircularVector a) where+ arbitrary = unsafeFromList <$> (getNonEmpty <$> arbitrary)++-- | label the circular vector with indices, starting from zero at the+-- current focus, going right.+--+-- Running time: \(O(n)\)+withIndicesRight :: CircularVector a -> CircularVector (Int :+ a)+withIndicesRight (CircularVector v s) = CircularVector v' s+ where+ n = length v+ v' = NV.imap (\i x -> ((i-s) `mod` n) :+ x) v
src/Data/Yaml/Util.hs view
@@ -66,6 +66,7 @@ , content :: a } deriving (Show,Read,Generic,Eq,Functor,Foldable,Traversable) +-- | Unpack versioned data type. unversioned :: Versioned a -> a unversioned = content
+ test/Algorithms/Graph/DFSSpec.hs view
@@ -0,0 +1,29 @@+module Algorithms.Graph.DFSSpec (spec) where+++import Algorithms.Graph.DFS (dfsSensitive)+import Control.DeepSeq (NFData (rnf))+import Control.Exception (evaluate)+import qualified Data.Foldable as F+import Data.PlanarGraph.Core (VertexId (VertexId), World (Primal))+import qualified Data.Set as S+import Data.Tree (Tree (rootLabel, subForest))+import Test.Hspec (Spec, anyErrorCall, describe, it, shouldBe, shouldThrow)++{-+ 0+ / \+1 2+-}+tree1 :: Tree (VertexId () Primal)+tree1 = dfsSensitive (\i -> case i of VertexId 0 -> [VertexId 1, VertexId 2]; _ -> error "fail!") (VertexId 0)++spec :: Spec+spec = do+ describe "DFS output sensitivity" $ do+ it "fails when forced" $+ evaluate (rnf tree1) `shouldThrow` anyErrorCall+ it "outputs root label lazily" $+ rootLabel tree1 `shouldBe` VertexId 0+ it "outputs forest lazily" $+ length (subForest tree1) `shouldBe` 2
test/Data/CircularSeqSpec.hs view
@@ -39,6 +39,9 @@ -- let cs = fromNonEmpty xs -- cs' = rotateNR i cs -- in+ it "read . show = id" $ do+ property $ \(lst :: CSeq Rational) ->+ read (show lst) == lst
+ test/Data/RealNumber/RationalSpec.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE DataKinds #-}+module Data.RealNumber.RationalSpec where++import Data.RealNumber.Rational+import Test.Hspec+import Test.QuickCheck++type R = RealNumber 5++spec :: Spec+spec = do+ describe "Read/Show" $ do+ it "read basic" $ do+ read (show (1::R)) `shouldBe` (1::R)+ read (show (negate 1::R)) `shouldBe` negate (1::R)+ it "read nested" $ do+ read (show (Just (1::R))) `shouldBe` Just (1::R)+ read (show (Just (negate 1::R))) `shouldBe` Just (negate (1::R))+ specify "significant digits" $ do+ show (0.12345::RealNumber 2) `shouldBe` "0.12~"+ show (0.12345::RealNumber 5) `shouldBe` "0.12345"+ it "should discard tail" $ do+ read (show (0.12345::RealNumber 2)) `shouldBe` (0.12 ::R)+ reads "0.12345~" `shouldBe` [(0.12::RealNumber 2, "")]+