diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f8b8a90..cc7888c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: - run: pip install -e . # ADJUST THIS: build your documentation into docs/. # We use a custom build script for pdoc itself, ideally you just run `pdoc -o docs/ ...` here. - - run: pdoc pysheaf/pysheaf.py -o docs/ + - run: pdoc pysheaf/ -o docs/ - uses: actions/upload-pages-artifact@v3 with: diff --git a/pysheaf/__init__.py b/pysheaf/__init__.py index 112b985..52970bf 100644 --- a/pysheaf/__init__.py +++ b/pysheaf/__init__.py @@ -1 +1,24 @@ from .pysheaf import * +""" +# Python 3.6 Sheaf theoretic toolbox + +This library provides tools for manipulating sheaves of pseudometric spaces on partially ordered sets. The primarly class is a `Sheaf`, which subclasses `NetworkX.DiGraph`; the idea is that the `DiGraph` specifies the Hasse diagram for the partially ordered set. + +Most of the details you need to get started are in the `pysheaf` module. Start there first. For specific sheaves that havew linear maps as restrictions, you might consider looking at `dataTools`. Finally, there are several detailed examples to explore. + +## General usage instructions + +1. First (usually on paper!) lay out the cell complex that will serve as the base for your sheaf. *Give each cell a unique label.* + +2. Determine all of the stalks over each cell, and the restriction maps. Restriction maps can be a mixture of `numpy` matrices or arbitrary single-input Python function objects. + +3. Construct a `Sheaf` instance and add each of your cells as `Cell` instances with the `Sheaf.AddCell` method. Make sure to use your unique label for each `Cell`, because that is how PySheaf identifies them! Once you've done that, create each restriction as a `Coface` instance and add it to the sheaf using the `Sheaf.AddCoface` method. The `Sheaf.AddCoface` method will connect the listed `Cell`s based on their labels. `Cell`s and `Coface`s can be added later if you want, and they can be added in any order provided any `Coface` refers to `Cell`s that already exist. + +4. Install some data into the sheaf by way of an `Assignment` to some of the `Cell`s. + +5. Analyze the sheaf and its data: + a. You can compute consistency radius with `Sheaf.ComputeConsistencyRadius()` + b. You can improve the consistency radius by extending or altering the values of the assignment with `Sheaf.FuseAssignment()`. This will only alter Cells whose `Cell.mOptimizationCell` attribute is `True`. You can also change the optimization algorithm if you want. + c. You can find all star open sets whose local consistency is less than a desired bound using `Sheaf.CellIndexesLessThanConsistencyThreshold()`. + +""" diff --git a/pysheaf/pysheaf.py b/pysheaf/pysheaf.py index e70d6b6..be0e4ed 100644 --- a/pysheaf/pysheaf.py +++ b/pysheaf/pysheaf.py @@ -1,5 +1,6 @@ """ -debugg Python 3.6 Sheaf manipulation library +# PySheaf main module and classes + """ # MIT License @@ -54,15 +55,21 @@ def __init__(self,dataTagType,compareAssignmentsMethod=None, serializeAssignment self.mDataAssignment = 0 """Value of the (single) assignment on the Cell instance. Only one assignment is permitted at a time.""" self.mExtendedAssignments = {} + """Values of other parts of the assignment that have been propagated into this `Cell` via the `Cofaces` during extension. Usually you should not touch this!""" self.mDataTagType = dataTagType - self.mOptimizationCell = optimizationCell # if the cell's data assignment can be changed by the optimizer + """Data type tag for limited type checking against `Coface` instances. Can be anything hashable.""" + self.mOptimizationCell = optimizationCell + """True if the cell's data assignment can be changed by the optimizer""" self.mExtendFromThisCell = extendFromThisCell # if the cell should be maximally extended from self.mBounds = [(None,None)] * self.mDataDimension # python magic for a list of tuples the length of dimension - self.mExtendedAssignmentConsistancyWeight = None # If None, only compare assignments against assignment ON this cell. Otherwise, compare incoming assignments using this weight + """List of pairs, one for each data dimension, specifying bounds for the assignment's value. Use `None` if no bound is desired.""" + self.mExtendedAssignmentConsistancyWeight = None + """If None, only compare assignments against assignment ON this cell. Otherwise, compare incoming assignments using this weight. Usually keep the default, which is `None`.""" if compareAssignmentsMethod==None: self.Compare = self.DefaultCompareAssignments else: self.Compare = compareAssignmentsMethod + """The pseudometric for this `Cell`""" if serializeAssignmentMethod==None: self.mSerialize = self.DefaultSerialize @@ -224,10 +231,14 @@ def __init__(self, inputTagType,outputTagType,edgeMethod): edgeMethod is called when the sheaf extends from one cell to another. The edge method return value will set the value on a assignment """ - self.mOrientation = 0 # orientation is either -1 or 1. + self.mOrientation = 0 + """Orientation is either -1 or 1. Unused if set to 0.""" self.mInputTagType = inputTagType + """Type tag for the input""" self.mOutputTagType = outputTagType + """Type tag for the output""" self.mEdgeMethod = edgeMethod + """Function to apply along the edge. This can also be any class that will respond to Python's calling semantics. See `dataTools.py` for other reasonable possibilities""" return # __init__ def SetEdgeMethod(self,methodToSet): @@ -247,7 +258,9 @@ class Assignment: """ def __init__(self, valueType,value): self.mValue = value - self.mValueType = valueType + """Value of the assignment""" + self.mValueType = valueType + """Data type of the assignment. Can be anything hashable""" return # __init__ def __str__(self): return str(self.mValue) # __str__ @@ -281,9 +294,13 @@ def __init__(self): """ nx.DiGraph.__init__(self) self.mNumpyNormType = np.inf - self.mPreventRedundantExtendedAssignments = False # If True, gives a speed up by preventing re-extending the same assignment through different paths. + """Norm for computing the consistency radius. Defaults to `np.inf`, though `2` is also reasonable.""" + self.mPreventRedundantExtendedAssignments = False + """If `True`, gives a speed up by preventing re-extending the same assignment through different paths. Only set to `True` if you are sure that your sheaf's underlying diagram actually commutes!""" self.mMaximumOptimizationIterations = 100 + """Maximum number of iterations to run the optimizer.""" self.mSheafOptimizer = self.DefaultSheafOptimizer + """Function to override the default optimizer if desired.""" return # __init__ def AddCell(self,cellIndex,cellToAdd):