| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
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 . Comparing two open hypergraphs,
or checking sorts given from outside, asks whether two sorts are isomorphic (Wires xsDecidableIso).
Synopsis
- type SomeSort s = SomeOf (SortOb :: s -> Constraint)
- type SortOb = Ob' :: s -> Constraint
- class (Ob a, a ~ 'FH (Port (PortSorts a :: [s])), SortList (PortSorts a :: [s])) => Sorted s (a :: FINHASK)
- type family PortSorts (a :: FINHASK) :: [s] where ...
- sortOf :: forall s (a :: FINHASK). Sorted s a => UN 'FH a -> SomeSort s
- type Sorts = ListOf (SortOb :: s -> Constraint)
- type SortList (xs :: [s]) = KnownListOf (SortOb :: s -> Constraint) xs
- sorts :: forall s (xs :: [s]). SortList xs => Sorts xs
- sortList :: forall s (xs :: [s]). SortList xs => [SomeSort s]
- newtype Port (xs :: [s]) = Port Int
- type SORTED s = SUBCAT (Sorted s)
- reifySorts :: [SomeSort s] -> (forall (xs :: [s]). SortList xs => r) -> r
- type OPENHG s l = DECCOSPAN (Boxes l :: SORTED s -> Type)
- type Wires (xs :: [s]) = 'DC ('SUB ('FH (Port xs)) :: SUBCAT (Sorted s)) :: DECCOSPAN (Boxes l :: SORTED s -> Type)
- data Box l n = Box {}
- data Boxes l (c :: SORTED s) where
- 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]
- box :: forall {s} l (as :: [s]) (bs :: [s]). (SortList as, SortList bs) => l -> (Wires as :: OPENHG s l) ~> (Wires bs :: OPENHG s l)
- 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))
- 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)
- data SomeHypergraph s l where
- 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))
- 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)
- 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)
- isomorphic :: forall {s} l (a :: OPENHG s l) (b :: OPENHG s l). (Eq l, DecidableIso s) => (a ~> b) -> (a ~> b) -> Bool
- sameSort :: DecidableIso s => SomeSort s -> SomeSort s -> Bool
- data SomeArrow s where
- someArrow :: forall {s} (as :: [s]) (bs :: [s]). (SortList as, SortList bs) => (as ~> bs) -> SomeArrow s
- 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)
- data Wiring s
- permutations :: SymMonoidal s => Wiring s
- copyDiscard :: CopyDiscard s => Wiring s
- frobenius :: (Hypergraph s, Sized s) => Wiring s
- frobeniusWith :: Hypergraph s => (SomeSort s -> Int) -> Wiring s
- tracedWith :: TracedMonoidal s => Wiring s -> Wiring s
- layered :: Sized s => Wiring s -> Wiring s
- type SIMPLIFY k = OPENHG k (Prim k)
- data Prim k
- unsafePrim :: SomeArrow k -> Prim k
- 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))
- prim0 :: forall {k} (a :: k). Monoidal k => ((Unit :: k) ~> a) -> (Wires ('[] :: [k]) :: OPENHG k (Prim k)) ~> (Wires '[a] :: OPENHG k (Prim k))
- prim1 :: forall {k} (a :: k) (b :: k). CategoryOf k => (a ~> b) -> (Wires '[a] :: OPENHG k (Prim k)) ~> (Wires '[b] :: OPENHG k (Prim k))
- 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))
- 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))
- simplify :: forall {k} (a :: SIMPLIFY k) (b :: SIMPLIFY k). Wiring k -> (a ~> b) -> Either String (WireSorts a ~> WireSorts b)
- simplifyHypergraph :: forall {k} (a :: SIMPLIFY k) (b :: SIMPLIFY k). (Hypergraph k, Sized k) => (a ~> b) -> WireSorts a ~> WireSorts b
- simplifyFlat :: forall {k} (a :: SIMPLIFY k) (b :: SIMPLIFY k). (Hypergraph k, Sized k) => (a ~> b) -> WireSorts a ~> WireSorts b
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.
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)
type family PortSorts (a :: FINHASK) :: [s] where ... Source Github #
The sorts of the ports of a sorted finite set.
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.
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.
Instances
| Show (Port xs) Source Github # | |
| Eq (Port xs) Source Github # | |
| Ord (Port xs) Source Github # | |
Defined in Proarrow.Category.Instance.OpenHypergraph | |
| SortList xs => Finite (Port xs) Source Github # | |
| SortList xs => Universe (Port xs) Source Github # | |
Defined in Proarrow.Category.Instance.OpenHypergraph | |
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.
A box with a label, attached to nodes of type n by its inputs and its outputs.
Instances
| Functor (Box l) Source Github # | |
| (Show l, Show n) => Show (Box l n) Source Github # | |
| (Eq l, Eq n) => Eq (Box l n) Source Github # | |
| (Ord l, Ord n) => Ord (Box l n) Source Github # | |
Defined in Proarrow.Category.Instance.OpenHypergraph | |
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.
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.
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.
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
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 #
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.