proarrow
Safe HaskellNone
LanguageGHC2024

Proarrow.Category.Instance.OpenHypergraph

Description

Open hypergraphs with typed wires: decorated cospans (Proarrow.Category.Instance.DecoratedCospan) of finite sets whose elements have sorts, decorated with labelled boxes. A morphism has nodes, each of some sort, boxes attached to them, and two boundaries of sorted ports. It is a morphism of the free hypergraph category on its boxes, and two such morphisms are equal by the Frobenius laws exactly when they are isomorphic.

The sorts are objects of a category s, known at runtime, so that a computed apex knows the sorts of its nodes. A list of sorts xs gives the boundary Wires xs. Comparing two open hypergraphs, or checking sorts given from outside, asks whether two sorts are isomorphic (DecidableIso).

Synopsis

Sorts

type SomeSort s = SomeOf (SortOb :: s -> Constraint) Source Github #

A sort of kind s, an object of the category of s, known at runtime.

type SortOb = Ob' :: s -> Constraint Source Github #

The evidence a sort carries: objecthood.

class (Ob a, a ~ 'FH (Port (PortSorts a :: [s])), SortList (PortSorts a :: [s])) => Sorted s (a :: FINHASK) Source Github #

The finite sets of ports with sorts of kind s, FH (Port xs).

Instances

Instances details
(Ob a, a ~ 'FH (Port (PortSorts a :: [s])), SortList (PortSorts a :: [s])) => Sorted s a Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

type family PortSorts (a :: FINHASK) :: [s] where ... Source Github #

The sorts of the ports of a sorted finite set.

Equations

PortSorts ('FH (Port xs)) = xs 

sortOf :: forall s (a :: FINHASK). Sorted s a => UN 'FH a -> SomeSort s Source Github #

The sort of a port.

type Sorts = ListOf (SortOb :: s -> Constraint) Source Github #

A list of sorts, each an object known at runtime.

type SortList (xs :: [s]) = KnownListOf (SortOb :: s -> Constraint) xs Source Github #

A list of sorts known at runtime.

sorts :: forall s (xs :: [s]). SortList xs => Sorts xs Source Github #

The list of sorts as a value.

sortList :: forall s (xs :: [s]). SortList xs => [SomeSort s] Source Github #

The sorts of the list, one by one.

newtype Port (xs :: [s]) Source Github #

The ports of a list of sorts: one for each position, of the sort at that position.

Constructors

Port Int 

Instances

Instances details
Show (Port xs) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

showsPrec :: Int -> Port xs -> ShowS Github #

show :: Port xs -> String Github #

showList :: [Port xs] -> ShowS Github #

Eq (Port xs) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

(==) :: Port xs -> Port xs -> Bool Github #

(/=) :: Port xs -> Port xs -> Bool Github #

Ord (Port xs) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

compare :: Port xs -> Port xs -> Ordering Github #

(<) :: Port xs -> Port xs -> Bool Github #

(<=) :: Port xs -> Port xs -> Bool Github #

(>) :: Port xs -> Port xs -> Bool Github #

(>=) :: Port xs -> Port xs -> Bool Github #

max :: Port xs -> Port xs -> Port xs Github #

min :: Port xs -> Port xs -> Port xs Github #

SortList xs => Finite (Port xs) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

SortList xs => Universe (Port xs) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

universe :: [Port xs] Github #

type SORTED s = SUBCAT (Sorted s) Source Github #

The finite sets whose elements have sorts of kind s: a full subcategory of FINHASK.

reifySorts :: [SomeSort s] -> (forall (xs :: [s]). SortList xs => r) -> r Source Github #

A list of sorts known at runtime as a type-level list.

Open hypergraphs

type OPENHG s l = DECCOSPAN (Boxes l :: SORTED s -> Type) Source Github #

Open hypergraphs with boxes labelled by l and wires of sorts of kind s.

type Wires (xs :: [s]) = 'DC ('SUB ('FH (Port xs)) :: SUBCAT (Sorted s)) :: DECCOSPAN (Boxes l :: SORTED s -> Type) Source Github #

The boundary with a wire for each sort in the list.

data Box l n Source Github #

A box with a label, attached to nodes of type n by its inputs and its outputs.

Constructors

Box 

Fields

Instances

Instances details
Functor (Box l) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

fmap :: (a -> b) -> Box l a -> Box l b Github #

(<$) :: a -> Box l b -> Box l a Github #

(Show l, Show n) => Show (Box l n) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

showsPrec :: Int -> Box l n -> ShowS Github #

show :: Box l n -> String Github #

showList :: [Box l n] -> ShowS Github #

(Eq l, Eq n) => Eq (Box l n) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

(==) :: Box l n -> Box l n -> Bool Github #

(/=) :: Box l n -> Box l n -> Bool Github #

(Ord l, Ord n) => Ord (Box l n) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

compare :: Box l n -> Box l n -> Ordering Github #

(<) :: Box l n -> Box l n -> Bool Github #

(<=) :: Box l n -> Box l n -> Bool Github #

(>) :: Box l n -> Box l n -> Bool Github #

(>=) :: Box l n -> Box l n -> Bool Github #

max :: Box l n -> Box l n -> Box l n Github #

min :: Box l n -> Box l n -> Box l n Github #

data Boxes l (c :: SORTED s) where Source Github #

Labelled boxes on the nodes of a sorted finite set. Two lists of boxes in a different order describe the same hypergraph, which isomorphic takes into account.

Constructors

Boxes :: forall {s} l n. [Box l n] -> Boxes l ('SUB ('FH n) :: SUBCAT (Sorted s)) 

Instances

Instances details
Alternative (Boxes l :: SORTED s -> Type) Source Github #

No boxes, and the boxes of both sides, the nodes of the second numbered after those of the first.

Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

empty :: forall (a :: SORTED s). Ob a => (Unit :: Type) ~> Boxes l a Source Github #

alt :: forall (a :: SORTED s) (b :: SORTED s) (c :: SORTED s). (Ob a, Ob b) => ((a || b) ~> c) -> (Boxes l a ** Boxes l b) ~> Boxes l c Source Github #

Functor (Boxes l :: SORTED s -> Type) Source Github # 
Instance details

Defined in Proarrow.Category.Instance.OpenHypergraph

Methods

map :: forall (a :: SORTED s) (b :: SORTED s). (a ~> b) -> Boxes l a ~> Boxes l b Source Github #

type WireSorts (a :: OPENHG s l) = PortSorts (UN ('SUB :: FINHASK -> SUBCAT (Sorted s)) (UN ('DC :: SORTED s -> DECCOSPAN (Boxes l :: SORTED s -> Type)) a)) :: [s] Source Github #

The sorts of the wires of a boundary.

box :: forall {s} l (as :: [s]) (bs :: [s]). (SortList as, SortList bs) => l -> (Wires as :: OPENHG s l) ~> (Wires bs :: OPENHG s l) Source Github #

One box with the given label, its inputs the wires of as and its outputs those of bs: a generator of the free hypergraph category.

openHypergraph :: forall {s} l (as :: [s]) (bs :: [s]). (SortList as, SortList bs, DecidableIso s) => [SomeSort s] -> [Int] -> [Int] -> [Box l Int] -> Either String ((Wires as :: OPENHG s l) ~> (Wires bs :: OPENHG s l)) Source Github #

The open hypergraph with the given nodes, boundaries and boxes. The first argument lists the sorts of the nodes, and a node is referred to by its position in that list, counting from 0. The second and third arguments give, for each wire of as and of bs in order, the node it is attached to, and each box lists the nodes of its inputs and of its outputs. A node that occurs several times joins all those wires and ports. Fails with a message unless every node referred to exists and every wire has a sort isomorphic to that of its node.

The product of a box a from x to y and a box b from y to z has nodes of the sorts x, y and z, with y shared between the boxes:

openHypergraph @'[x] @'[z] [sx, sy, sz] [0] [2] [Box a [0] [1], Box b [1] [2]]

unsafeOpenHypergraph :: forall {s} l (as :: [s]) (bs :: [s]). (SortList as, SortList bs) => [SomeSort s] -> [Int] -> [Int] -> [Box l Int] -> (Wires as :: OPENHG s l) ~> (Wires bs :: OPENHG s l) Source Github #

openHypergraph without its checks, with the same arguments: the boundaries must have as many wires as their sorts, every wire and box must be attached to nodes that exist, and every wire must have the sort of its node. Only for hypergraphs that satisfy this by construction, such as those that simplify is given, which trusts the sorts to be equal.

data SomeHypergraph s l where Source Github #

An open hypergraph whose boundaries are known at runtime, for replacing a labelled box.

Constructors

SomeHypergraph :: forall s l (a :: OPENHG s l) (b :: OPENHG s l). (a ~> b) -> SomeHypergraph s l 

substitute :: forall {s} l m (a :: OPENHG s l) (b :: OPENHG s l). DecidableIso s => (l -> SomeHypergraph s m) -> (a ~> b) -> Either String ((Wires (WireSorts a) :: OPENHG s m) ~> (Wires (WireSorts b) :: OPENHG s m)) Source Github #

Replace every box by the diagram assigned to its label. Each replacement must have as many inputs and outputs as the box, in the same order, with isomorphic sorts. All replacements are glued together in one union-find pass. Shared nodes, repeated ports and isolated nodes are kept. Replacement labels are not substituted again.

Adapted from the functor-application construction in §9 of Wilson and Zanasi, Data-Parallel Algorithms for String Diagrams, restricted to an identity object map. This implementation uses maps and union-find rather than the paper's data-parallel representation.

substituteWith :: forall {s} {t} l m (a :: OPENHG s l) (b :: OPENHG s l). DecidableIso t => (SomeSort s -> [SomeSort t]) -> (l -> SomeHypergraph t m) -> (a ~> b) -> Either String (SomeHypergraph t m) Source Github #

Apply an object map and a generator map to an open hypergraph. Each source sort becomes a list of target sorts, and each box is replaced by a diagram with the expanded inputs and outputs. Every occurrence of a node uses the same expanded nodes, including repeated ports and boundaries. An empty list removes a node; an isolated node expands to one isolated node per target sort. The resulting boundaries are known at runtime, so the result is a SomeHypergraph.

The object map must send isomorphic source sorts to lists of pairwise isomorphic target sorts for composition to be preserved. Replacement boundaries are checked as in substitute.

Adapted from the functor-application construction in §9 of Wilson and Zanasi, Data-Parallel Algorithms for String Diagrams. This implementation uses lists, maps and union-find rather than the paper's data-parallel representation.

unsafeSubstituteWith :: forall {s} {t} l m (a :: OPENHG s l) (b :: OPENHG s l). (SomeSort s -> [SomeSort t]) -> (l -> SomeHypergraph t m) -> (a ~> b) -> Either String (SomeHypergraph t m) Source Github #

substituteWith without comparing sorts. Replacement boundaries must have the sorts specified by the object map, in order. Arity is still checked. For typed primitive translations whose source and replacement ports agree by construction; otherwise use substituteWith.

isomorphic :: forall {s} l (a :: OPENHG s l) (b :: OPENHG s l). (Eq l, DecidableIso s) => (a ~> b) -> (a ~> b) -> Bool Source Github #

Whether two open hypergraphs differ only in the names of their nodes, the order of their boxes and their sorts up to isomorphism: a bijection between the nodes that keeps their sorts, agrees with both boundaries and takes the boxes of one to those of the other.

sameSort :: DecidableIso s => SomeSort s -> SomeSort s -> Bool Source Github #

Whether two sorts are isomorphic.

Read-back

data SomeArrow s where Source Github #

An arrow of the strictified category of s whose lists of sorts are known at runtime, such as the interpretation of a box.

Constructors

SomeArrow :: forall {s} (as :: [s]) (bs :: [s]). Sorts as -> Sorts bs -> (as ~> bs) -> SomeArrow s 

someArrow :: forall {s} (as :: [s]) (bs :: [s]). (SortList as, SortList bs) => (as ~> bs) -> SomeArrow s Source Github #

An arrow as one whose sorts are known at runtime.

readBack :: forall {s} l (a :: OPENHG s l) (b :: OPENHG s l). DecidableIso s => Wiring s -> (l -> SomeArrow s) -> (a ~> b) -> Either String (WireSorts a ~> WireSorts b) Source Github #

Interpret a graph using the given wiring, for example readBack copyDiscard interpret graph or readBack (tracedWith permutations) interpret graph. Sorts supplied from outside are compared by DecidableIso; boxes are transported along the resulting isomorphisms. Unsupported incidences or feedback return an error.

data Wiring s Source Github #

Wiring operations, feedback and box scheduling. permutations and copyDiscard reject cycles; frobenius supplies its cup-and-cap trace. tracedWith replaces the feedback policy with the target's trace while keeping the wiring operations and contraction plan. Read-back reduces estimated swap cost; layered also places independent boxes side by side.

permutations :: SymMonoidal s => Wiring s Source Github #

Only permutations: every node has one producer and one consumer. Nullary boxes and scalars are allowed; copying, merging and discarding need stronger wiring operations. With tracedWith, isolated loops are traced identities.

copyDiscard :: CopyDiscard s => Wiring s Source Github #

Each node has one producer and any number of consumers. Copy when a wire branches and discard it when unused. Boxes with unused outputs still run; copying and discarding need not be natural. Directed cycles are rejected unless tracedWith enables the target's trace. With tracing, nodes without producers feed themselves and their consumers through copying.

frobenius :: (Hypergraph s, Sized s) => Wiring s Source Github #

Frobenius spiders with sizes from Sized, planned as in frobeniusWith.

frobeniusWith :: Hypergraph s => (SomeSort s -> Int) -> Wiring s Source Github #

Frobenius spiders with the given wire sizes. State boxes are contracted as a tree, using the cheaper of numpy's greedy order and min-fill elimination. Remaining boxes follow a path; nodes are merged and discarded as soon as their other uses allow. This preserves the contraction planner used by einsum. Feedback uses the trace from Frobenius cups and caps. The given sizes also weight swap reduction, including wire routing within state contractions; routing preserves the contraction tree and its eliminated indices.

tracedWith :: TracedMonoidal s => Wiring s -> Wiring s Source Github #

Use the target's trace for feedback, replacing the wiring's default feedback policy. For example, tracedWith copyDiscard supports copying, discarding and directed cycles.

layered :: Sized s => Wiring s -> Wiring s Source Github #

Place independent boxes side by side with tensor, routing wires between layers. Swap reduction uses the wiring's existing sizes, or Sized when no sizes were supplied. Each crossing is weighted by the product of the wire sizes. Wiring operations and feedback are unchanged. Without this modifier boxes are placed one at a time, with uniform swap costs unless the wiring supplies sizes, as frobenius and frobeniusWith do.

Simplifying

type SIMPLIFY k = OPENHG k (Prim k) Source Github #

Open hypergraphs whose boxes are arrows of k: the category to run a term of a hypergraph category in, with the arrows it uses made boxes by prim, to simplify it.

data Prim k Source Github #

The label of a box of SIMPLIFY: the arrow the box was made from, whose sorts are those of the box. Made only by prim, so simplify can trust the sorts. Taking a label out of one hypergraph and attaching it to other nodes with openHypergraph breaks that trust.

unsafePrim :: SomeArrow k -> Prim k Source Github #

An arrow as the label of a box with any sorts. Only for boxes whose sorts are equal to the arrow's by construction, as for unsafeOpenHypergraph.

prim :: forall {k} (as :: [k]) (bs :: [k]). (SortList as, SortList bs) => (as ~> bs) -> (Wires as :: OPENHG k (Prim k)) ~> (Wires bs :: OPENHG k (Prim k)) Source Github #

An arrow of k between lists of objects as one box.

prim0 :: forall {k} (a :: k). Monoidal k => ((Unit :: k) ~> a) -> (Wires ('[] :: [k]) :: OPENHG k (Prim k)) ~> (Wires '[a] :: OPENHG k (Prim k)) Source Github #

An arrow from the tensor unit as a box with no inputs and one output.

prim1 :: forall {k} (a :: k) (b :: k). CategoryOf k => (a ~> b) -> (Wires '[a] :: OPENHG k (Prim k)) ~> (Wires '[b] :: OPENHG k (Prim k)) Source Github #

An arrow as a box with one input and one output.

prim2 :: forall {k} (a :: k) (b :: k) (c :: k). (Monoidal k, Ob a, Ob b) => ((a ** b) ~> c) -> (Wires '[a, b] :: OPENHG k (Prim k)) ~> (Wires '[c] :: OPENHG k (Prim k)) Source Github #

An arrow from a tensor as a box with two inputs and one output.

prim3 :: forall {k} (a :: k) (b :: k) (c :: k) (d :: k). (Monoidal k, Ob a, Ob b, Ob c) => (((a ** b) ** c) ~> d) -> (Wires '[a, b, c] :: OPENHG k (Prim k)) ~> (Wires '[d] :: OPENHG k (Prim k)) Source Github #

An arrow from a left-associated tensor as a box with three inputs and one output. Reassociates the right-associated port list to the arrow's input tensor.

simplify :: forall {k} (a :: SIMPLIFY k) (b :: SIMPLIFY k). Wiring k -> (a ~> b) -> Either String (WireSorts a ~> WireSorts b) Source Github #

Read a primitive graph using the given wiring. Primitive sorts are trusted, so DecidableIso is unnecessary: for example, simplify copyDiscard graph can execute a graph as a Haskell function.

simplifyHypergraph :: forall {k} (a :: SIMPLIFY k) (b :: SIMPLIFY k). (Hypergraph k, Sized k) => (a ~> b) -> WireSorts a ~> WireSorts b Source Github #

Interpret a primitive graph in its hypergraph target, with wire sizes from Sized. This is simplify with frobenius: every graph is supported and primitive sorts are trusted, so the result needs no Either.

simplifyFlat :: forall {k} (a :: SIMPLIFY k) (b :: SIMPLIFY k). (Hypergraph k, Sized k) => (a ~> b) -> WireSorts a ~> WireSorts b Source Github #

simplifyHypergraph with every box bent into a state on all its wires, its inputs turned into outputs with cups. The read-back then contracts the whole network in the order of planContraction, instead of following the flow from inputs to outputs, and needs no traces for cycles. For computing with a term rather than drawing it, as the result is drawn with cups and caps.