digraphx 0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- digraphx/__init__.py +16 -0
- digraphx/max_cycle_ratio.tpy +134 -0
- digraphx/min_cycle_ratio.py +174 -0
- digraphx/min_parmetric_q.py +150 -0
- digraphx/neg_cycle.py +241 -0
- digraphx/neg_cycle_q.py +342 -0
- digraphx/parametric.py +135 -0
- digraphx/skeleton.py +149 -0
- digraphx/tiny_digraph.py +79 -0
- digraphx-0.1.dist-info/METADATA +56 -0
- digraphx-0.1.dist-info/RECORD +14 -0
- digraphx-0.1.dist-info/WHEEL +5 -0
- digraphx-0.1.dist-info/licenses/LICENSE.txt +21 -0
- digraphx-0.1.dist-info/top_level.txt +1 -0
digraphx/parametric.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Parametric Network Solver
|
|
3
|
+
|
|
4
|
+
This code defines a system for solving parametric network problems, which are a type of optimization problem in graph theory. The main purpose of this code is to find the maximum ratio that satisfies certain conditions in a graph, where the distances between nodes depend on this ratio.
|
|
5
|
+
|
|
6
|
+
The code takes two main inputs: a graph (represented as a mapping of nodes and edges) and an object that defines how to calculate distances based on the ratio. It produces two outputs: the maximum ratio that satisfies the conditions and a cycle in the graph that corresponds to this ratio.
|
|
7
|
+
|
|
8
|
+
The code achieves its purpose through an iterative algorithm implemented in the run method of the MaxParametricSolver class. This method starts with an initial ratio and repeatedly finds cycles in the graph that could potentially improve this ratio. It uses a negative cycle finder (NCF) to detect these cycles efficiently.
|
|
9
|
+
|
|
10
|
+
The algorithm works as follows:
|
|
11
|
+
|
|
12
|
+
1. It starts with an initial ratio and distance estimates for each node.
|
|
13
|
+
2. It uses the NCF to find cycles in the graph where the total distance is negative.
|
|
14
|
+
3. For each negative cycle found, it calculates a new ratio that would make the cycle's total distance zero.
|
|
15
|
+
4. If this new ratio is smaller than the current best ratio, it updates the best ratio and remembers this cycle.
|
|
16
|
+
5. It repeats steps 2-4 until no better ratio can be found.
|
|
17
|
+
|
|
18
|
+
The main data transformation happening here is the continuous updating of the ratio based on the cycles found in the graph. The algorithm is essentially searching for the highest ratio that doesn't allow any negative cycles in the graph, when distances are calculated using this ratio.
|
|
19
|
+
|
|
20
|
+
This code is designed to be flexible, using generic types for nodes, edges, and ratios. This allows it to work with different types of graphs and different ways of calculating distances. The ParametricAPI class defines an interface for how distances should be calculated and how to find the ratio that makes a cycle's total distance zero.
|
|
21
|
+
|
|
22
|
+
Overall, this code provides a framework for solving a specific type of optimization problem on graphs, where the goal is to maximize a ratio while maintaining certain constraints on the distances between nodes in the graph.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from abc import abstractmethod
|
|
26
|
+
from fractions import Fraction
|
|
27
|
+
from typing import Generic, Mapping, MutableMapping, Tuple, TypeVar
|
|
28
|
+
|
|
29
|
+
from .neg_cycle import Cycle, Domain, Edge, NegCycleFinder, Node
|
|
30
|
+
|
|
31
|
+
Ratio = TypeVar("Ratio", Fraction, float)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ParametricAPI(Generic[Node, Edge, Ratio]):
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def distance(self, ratio: Ratio, edge: Edge) -> Ratio:
|
|
37
|
+
"""
|
|
38
|
+
The `distance` function calculates the distance between a given ratio and edge.
|
|
39
|
+
|
|
40
|
+
:param ratio: The `ratio` parameter is of type `Ratio`. It represents a ratio or proportion
|
|
41
|
+
:type ratio: Ratio
|
|
42
|
+
:param edge: The `edge` parameter represents an edge in a graph. It is of type `Edge`
|
|
43
|
+
:type edge: Edge
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def zero_cancel(self, cycle: Cycle) -> Ratio:
|
|
48
|
+
"""
|
|
49
|
+
The `zero_cancel` function takes a `Cycle` object as input and returns a `Ratio` object.
|
|
50
|
+
|
|
51
|
+
:param cycle: The `cycle` parameter is of type `Cycle`.
|
|
52
|
+
:type cycle: Cycle
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class MaxParametricSolver(Generic[Node, Edge, Ratio]):
|
|
57
|
+
"""Maximum Parametric Solver
|
|
58
|
+
|
|
59
|
+
This class solves the following parametric network problem:
|
|
60
|
+
|
|
61
|
+
| max r
|
|
62
|
+
| s.t. dist[v] - dist[u] <= distrance(e, r)
|
|
63
|
+
| forall e(u, v) in G(V, E)
|
|
64
|
+
|
|
65
|
+
A parametric network problem refers to a type of optimization problem that
|
|
66
|
+
involves finding the optimal solution to a network flow problem as a function
|
|
67
|
+
of one single parameter.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
def __init__(
|
|
71
|
+
self,
|
|
72
|
+
digraph: Mapping[Node, Mapping[Node, Edge]],
|
|
73
|
+
omega: ParametricAPI[Node, Edge, Ratio],
|
|
74
|
+
) -> None:
|
|
75
|
+
"""
|
|
76
|
+
The `__init__` function initializes an object with a graph and an omega parameter.
|
|
77
|
+
|
|
78
|
+
:param digraph: digraph is a mapping of nodes to a mapping of nodes to edges. It represents a graph
|
|
79
|
+
where each node is connected to other nodes through edges. The edges are represented by the
|
|
80
|
+
mapping of nodes to edges
|
|
81
|
+
|
|
82
|
+
:type digraph: Mapping[Node, Mapping[Node, Edge]]
|
|
83
|
+
|
|
84
|
+
:param omega: The `omega` parameter is an instance of the `ParametricAPI` class. It represents
|
|
85
|
+
some kind of parametric API that takes three type parameters: `Node`, `Edge`, and `Ratio`
|
|
86
|
+
|
|
87
|
+
:type omega: ParametricAPI[Node, Edge, Ratio]
|
|
88
|
+
"""
|
|
89
|
+
# self.ncf = NegCycleFinder(digraph)
|
|
90
|
+
self.digraph = digraph
|
|
91
|
+
self.omega: ParametricAPI[Node, Edge, Ratio] = omega
|
|
92
|
+
|
|
93
|
+
def run(
|
|
94
|
+
self, dist: MutableMapping[Node, Domain], ratio: Ratio
|
|
95
|
+
) -> Tuple[Ratio, Cycle]:
|
|
96
|
+
"""
|
|
97
|
+
The `run` function takes in a distance mapping and a ratio, and iteratively finds the minimum
|
|
98
|
+
ratio and corresponding cycle until the minimum ratio is greater than or equal to the input
|
|
99
|
+
ratio.
|
|
100
|
+
|
|
101
|
+
:param dist: The `dist` parameter is a mutable mapping where the keys are `Node` objects and the
|
|
102
|
+
values are `Domain` objects. It represents the distance between nodes in a graph
|
|
103
|
+
|
|
104
|
+
:type dist: MutableMapping[Node, Domain]
|
|
105
|
+
|
|
106
|
+
:param ratio: The `ratio` parameter is a value that represents a ratio or proportion. It is used
|
|
107
|
+
as a threshold or target value in the algorithm
|
|
108
|
+
|
|
109
|
+
:type ratio: Ratio
|
|
110
|
+
|
|
111
|
+
:return: The function `run` returns a tuple containing the updated ratio (`ratio`) and the cycle (`cycle`).
|
|
112
|
+
"""
|
|
113
|
+
D = type(next(iter(dist.values())))
|
|
114
|
+
|
|
115
|
+
def get_weight(e: Edge) -> Domain:
|
|
116
|
+
return D(self.omega.distance(ratio, e))
|
|
117
|
+
|
|
118
|
+
r_min = ratio
|
|
119
|
+
c_min = []
|
|
120
|
+
cycle = []
|
|
121
|
+
|
|
122
|
+
ncf: NegCycleFinder[Node, Edge, Domain] = NegCycleFinder(self.digraph)
|
|
123
|
+
|
|
124
|
+
while True:
|
|
125
|
+
for ci in ncf.howard(dist, get_weight):
|
|
126
|
+
ri = self.omega.zero_cancel(ci)
|
|
127
|
+
if r_min > ri:
|
|
128
|
+
r_min = ri
|
|
129
|
+
c_min = ci
|
|
130
|
+
if r_min >= ratio:
|
|
131
|
+
break
|
|
132
|
+
|
|
133
|
+
cycle = c_min
|
|
134
|
+
ratio = r_min
|
|
135
|
+
return ratio, cycle
|
digraphx/skeleton.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is a skeleton file that can serve as a starting point for a Python
|
|
3
|
+
console script. To run this script uncomment the following lines in the
|
|
4
|
+
``[options.entry_points]`` section in ``setup.cfg``::
|
|
5
|
+
|
|
6
|
+
console_scripts =
|
|
7
|
+
fibonacci = digraphx.skeleton:run
|
|
8
|
+
|
|
9
|
+
Then run ``pip install .`` (or ``pip install -e .`` for editable mode)
|
|
10
|
+
which will install the command ``fibonacci`` inside your current environment.
|
|
11
|
+
|
|
12
|
+
Besides console scripts, the header (i.e. until ``_logger``...) of this file can
|
|
13
|
+
also be used as template for Python modules.
|
|
14
|
+
|
|
15
|
+
Note:
|
|
16
|
+
This file can be renamed depending on your needs or safely removed if not needed.
|
|
17
|
+
|
|
18
|
+
References:
|
|
19
|
+
- https://setuptools.pypa.io/en/latest/userguide/entry_point.html
|
|
20
|
+
- https://pip.pypa.io/en/stable/reference/pip_install
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import argparse
|
|
24
|
+
import logging
|
|
25
|
+
import sys
|
|
26
|
+
|
|
27
|
+
from digraphx import __version__
|
|
28
|
+
|
|
29
|
+
__author__ = "Wai-Shing Luk"
|
|
30
|
+
__copyright__ = "Wai-Shing Luk"
|
|
31
|
+
__license__ = "MIT"
|
|
32
|
+
|
|
33
|
+
_logger = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# ---- Python API ----
|
|
37
|
+
# The functions defined in this section can be imported by users in their
|
|
38
|
+
# Python scripts/interactive interpreter, e.g. via
|
|
39
|
+
# `from digraphx.skeleton import fib`,
|
|
40
|
+
# when using this Python module as a library.
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def fib(n):
|
|
44
|
+
"""Fibonacci example function
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
n (int): integer
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
int: n-th Fibonacci number
|
|
51
|
+
"""
|
|
52
|
+
assert n > 0
|
|
53
|
+
a, b = 1, 1
|
|
54
|
+
for _i in range(n - 1):
|
|
55
|
+
a, b = b, a + b
|
|
56
|
+
return a
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# ---- CLI ----
|
|
60
|
+
# The functions defined in this section are wrappers around the main Python
|
|
61
|
+
# API allowing them to be called directly from the terminal as a CLI
|
|
62
|
+
# executable/script.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def parse_args(args):
|
|
66
|
+
"""Parse command line parameters
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
args (List[str]): command line parameters as list of strings
|
|
70
|
+
(for example ``["--help"]``).
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
:obj:`argparse.Namespace`: command line parameters namespace
|
|
74
|
+
"""
|
|
75
|
+
parser = argparse.ArgumentParser(description="Just a Fibonacci demonstration")
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
"--version",
|
|
78
|
+
action="version",
|
|
79
|
+
version=f"digraphx {__version__}",
|
|
80
|
+
)
|
|
81
|
+
parser.add_argument(dest="n", help="n-th Fibonacci number", type=int, metavar="INT")
|
|
82
|
+
parser.add_argument(
|
|
83
|
+
"-v",
|
|
84
|
+
"--verbose",
|
|
85
|
+
dest="loglevel",
|
|
86
|
+
help="set loglevel to INFO",
|
|
87
|
+
action="store_const",
|
|
88
|
+
const=logging.INFO,
|
|
89
|
+
)
|
|
90
|
+
parser.add_argument(
|
|
91
|
+
"-vv",
|
|
92
|
+
"--very-verbose",
|
|
93
|
+
dest="loglevel",
|
|
94
|
+
help="set loglevel to DEBUG",
|
|
95
|
+
action="store_const",
|
|
96
|
+
const=logging.DEBUG,
|
|
97
|
+
)
|
|
98
|
+
return parser.parse_args(args)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def setup_logging(loglevel):
|
|
102
|
+
"""Setup basic logging
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
loglevel (int): minimum loglevel for emitting messages
|
|
106
|
+
"""
|
|
107
|
+
logformat = "[%(asctime)s] %(levelname)s:%(name)s:%(message)s"
|
|
108
|
+
logging.basicConfig(
|
|
109
|
+
level=loglevel, stream=sys.stdout, format=logformat, datefmt="%Y-%m-%d %H:%M:%S"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def main(args):
|
|
114
|
+
"""Wrapper allowing :func:`fib` to be called with string arguments in a CLI fashion
|
|
115
|
+
|
|
116
|
+
Instead of returning the value from :func:`fib`, it prints the result to the
|
|
117
|
+
``stdout`` in a nicely formatted message.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
args (List[str]): command line parameters as list of strings
|
|
121
|
+
(for example ``["--verbose", "42"]``).
|
|
122
|
+
"""
|
|
123
|
+
args = parse_args(args)
|
|
124
|
+
setup_logging(args.loglevel)
|
|
125
|
+
_logger.debug("Starting crazy calculations...")
|
|
126
|
+
print(f"The {args.n}-th Fibonacci number is {fib(args.n)}")
|
|
127
|
+
_logger.info("Script ends here")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def run():
|
|
131
|
+
"""Calls :func:`main` passing the CLI arguments extracted from :obj:`sys.argv`
|
|
132
|
+
|
|
133
|
+
This function can be used as entry point to create console scripts with setuptools.
|
|
134
|
+
"""
|
|
135
|
+
main(sys.argv[1:])
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
if __name__ == "__main__":
|
|
139
|
+
# ^ This is a guard statement that will prevent the following code from
|
|
140
|
+
# being executed in the case someone imports this file instead of
|
|
141
|
+
# executing it as a script.
|
|
142
|
+
# https://docs.python.org/3/library/__main__.html
|
|
143
|
+
|
|
144
|
+
# After installing your project with pip, users can also run your Python
|
|
145
|
+
# modules as scripts via the ``-m`` flag, as defined in PEP 338::
|
|
146
|
+
#
|
|
147
|
+
# python -m digraphx.skeleton 42
|
|
148
|
+
#
|
|
149
|
+
run()
|
digraphx/tiny_digraph.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TinyDiGraph
|
|
3
|
+
|
|
4
|
+
This code defines a custom graph data structure called TinyDiGraph, which is designed to be a lightweight and efficient implementation of a directed graph. The purpose of this code is to provide a simple way to create and manipulate directed graphs, particularly for cases where performance and memory efficiency are important.
|
|
5
|
+
|
|
6
|
+
The main input for this code is the number of nodes in the graph, which is set when initializing the graph using the init_nodes method. The code doesn't directly produce any output, but it provides methods to add edges, count nodes and edges, and iterate through the graph's structure.
|
|
7
|
+
|
|
8
|
+
TinyDiGraph achieves its purpose by subclassing from DiGraphAdapter, which in turn inherits from NetworkX's DiGraph class. This allows TinyDiGraph to leverage existing graph functionality while customizing certain aspects for efficiency. The key feature of TinyDiGraph is its use of a custom data structure called MapAdapter (likely a list-based dictionary) to store node and edge information.
|
|
9
|
+
|
|
10
|
+
The code implements several important methods:
|
|
11
|
+
|
|
12
|
+
1. cheat_node_dict and cheat_adjlist_outer_dict: These methods create MapAdapter objects to store node and edge information efficiently.
|
|
13
|
+
2. init_nodes: This method initializes the graph with a specified number of nodes, setting up the necessary data structures.
|
|
14
|
+
|
|
15
|
+
The main logic flow of the code is as follows:
|
|
16
|
+
|
|
17
|
+
1. Define the TinyDiGraph class with custom node and edge storage methods.
|
|
18
|
+
2. Provide a method to initialize the graph with a given number of nodes.
|
|
19
|
+
3. Set up the graph structure using MapAdapter objects for efficient storage and access.
|
|
20
|
+
|
|
21
|
+
At the end of the file, there's a small example of how to use TinyDiGraph. It creates a graph with 1000 nodes, adds an edge, and then demonstrates how to iterate through the graph and access its properties.
|
|
22
|
+
|
|
23
|
+
The code also includes a brief demonstration of the MapAdapter data structure, showing how it can be used as an efficient list-like dictionary.
|
|
24
|
+
|
|
25
|
+
Overall, this code provides a foundation for working with directed graphs in a memory-efficient manner, which could be particularly useful for large graphs or in situations where performance is critical.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
import networkx as nx
|
|
29
|
+
from mywheel.map_adapter import MapAdapter
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class DiGraphAdapter(nx.DiGraph):
|
|
33
|
+
def items(self):
|
|
34
|
+
return self.adjacency()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class TinyDiGraph(DiGraphAdapter):
|
|
38
|
+
num_nodes = 0
|
|
39
|
+
|
|
40
|
+
def cheat_node_dict(self):
|
|
41
|
+
return MapAdapter([dict() for _ in range(self.num_nodes)])
|
|
42
|
+
|
|
43
|
+
def cheat_adjlist_outer_dict(self):
|
|
44
|
+
return MapAdapter([dict() for _ in range(self.num_nodes)])
|
|
45
|
+
|
|
46
|
+
node_dict_factory = cheat_node_dict
|
|
47
|
+
adjlist_outer_dict_factory = cheat_adjlist_outer_dict
|
|
48
|
+
|
|
49
|
+
def init_nodes(self, n: int):
|
|
50
|
+
"""
|
|
51
|
+
The function initializes the number of nodes, a dictionary for nodes, and dictionaries for
|
|
52
|
+
adjacency and predecessor lists.
|
|
53
|
+
|
|
54
|
+
:param n: The parameter `n` represents the number of nodes in the graph
|
|
55
|
+
:type n: int
|
|
56
|
+
"""
|
|
57
|
+
self.num_nodes = n
|
|
58
|
+
self._node = self.cheat_node_dict()
|
|
59
|
+
self._adj = self.cheat_adjlist_outer_dict()
|
|
60
|
+
self._pred = self.cheat_adjlist_outer_dict()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
if __name__ == "__main__":
|
|
64
|
+
gr = TinyDiGraph()
|
|
65
|
+
gr.init_nodes(1000)
|
|
66
|
+
gr.add_edge(2, 1)
|
|
67
|
+
print(gr.number_of_nodes())
|
|
68
|
+
print(gr.number_of_edges())
|
|
69
|
+
|
|
70
|
+
for utx in gr:
|
|
71
|
+
for vtx in gr.neighbors(utx):
|
|
72
|
+
print(f"{utx}, {vtx}")
|
|
73
|
+
|
|
74
|
+
a = MapAdapter([0] * 8)
|
|
75
|
+
for i in a:
|
|
76
|
+
a[i] = i * i
|
|
77
|
+
for i, vtx in a.items():
|
|
78
|
+
print(f"{i}: {vtx}")
|
|
79
|
+
print(3 in a)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: digraphx
|
|
3
|
+
Version: 0.1
|
|
4
|
+
Summary: Network Optimization Python Code
|
|
5
|
+
Home-page: https://github.com/luk036/digraphx
|
|
6
|
+
Author: Wai-Shing Luk
|
|
7
|
+
Author-email: luk036@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Documentation, https://pyscaffold.org/
|
|
10
|
+
Platform: any
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
14
|
+
License-File: LICENSE.txt
|
|
15
|
+
Requires-Dist: importlib-metadata; python_version < "3.9"
|
|
16
|
+
Requires-Dist: networkx
|
|
17
|
+
Provides-Extra: testing
|
|
18
|
+
Requires-Dist: setuptools; extra == "testing"
|
|
19
|
+
Requires-Dist: pytest; extra == "testing"
|
|
20
|
+
Requires-Dist: pytest-cov; extra == "testing"
|
|
21
|
+
Requires-Dist: networkx; extra == "testing"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
<!-- These are examples of badges you might want to add to your README:
|
|
25
|
+
please update the URLs accordingly
|
|
26
|
+
|
|
27
|
+
[](https://cirrus-ci.com/github/<USER>/digraphx)
|
|
28
|
+
[](https://digraphx.readthedocs.io/en/stable/)
|
|
29
|
+
[](https://coveralls.io/r/<USER>/digraphx)
|
|
30
|
+
[](https://pypi.org/project/digraphx/)
|
|
31
|
+
[](https://anaconda.org/conda-forge/digraphx)
|
|
32
|
+
[](https://pepy.tech/project/digraphx)
|
|
33
|
+
[](https://twitter.com/digraphx)
|
|
34
|
+
-->
|
|
35
|
+
|
|
36
|
+
[](https://pyscaffold.org/)
|
|
37
|
+
[](https://digraphx.readthedocs.io/en/latest/?badge=latest)
|
|
38
|
+
[](https://codecov.io/gh/luk036/digraphx)
|
|
39
|
+
|
|
40
|
+
# 🔀 digraphx
|
|
41
|
+
|
|
42
|
+
> Directed Graph X in Python
|
|
43
|
+
|
|
44
|
+
A longer description of your project goes here...
|
|
45
|
+
|
|
46
|
+
## Dependencies
|
|
47
|
+
|
|
48
|
+
- [luk036/mywheel](https://github.com/luk036/mywheel)
|
|
49
|
+
- networkx
|
|
50
|
+
|
|
51
|
+
<!-- pyscaffold-notes -->
|
|
52
|
+
|
|
53
|
+
## 👉 Note
|
|
54
|
+
|
|
55
|
+
This project has been set up using PyScaffold 4.5. For details and usage
|
|
56
|
+
information on PyScaffold see https://pyscaffold.org/.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
digraphx/__init__.py,sha256=ethe4DV1CwbXvO2DSjEzt5SL_7jt2fxQnF4RPgRgTDI,577
|
|
2
|
+
digraphx/max_cycle_ratio.tpy,sha256=e3GWroIm17nNEmVhjJ90ozCeRs5RhpeKkBkyACSwfSc,6623
|
|
3
|
+
digraphx/min_cycle_ratio.py,sha256=L6VzD2mPS7kcKBWQL-THCCEF-Bq39gEzMiccM2qs27g,9200
|
|
4
|
+
digraphx/min_parmetric_q.py,sha256=k-E77T1WB-FkCRadv6dtsBTOc3CzDujsLQI24W5LrPc,7120
|
|
5
|
+
digraphx/neg_cycle.py,sha256=H1IAMjk1M6Z5y92Ct14a_lQsVWzMafR0yPyoYiveK9M,11592
|
|
6
|
+
digraphx/neg_cycle_q.py,sha256=kHinHqeKkeRHVDo0l3B6YJAGt_so1aPHbMwf4isvy64,15876
|
|
7
|
+
digraphx/parametric.py,sha256=3TM9Sppy62b8mkxFEqoS4uUu9FF8V23CP9WOEu2eFYg,6384
|
|
8
|
+
digraphx/skeleton.py,sha256=uQaIAFPqpGOAEfyndv4qjIj1SSJk_P_gP2Rrk4BKGSQ,4219
|
|
9
|
+
digraphx/tiny_digraph.py,sha256=_Y9k58HleY5kso6rgo540ETYkM3hmtDNEPD5DmY64ns,3577
|
|
10
|
+
digraphx-0.1.dist-info/licenses/LICENSE.txt,sha256=MyvlyWiWdJ3ZpAOA4wziXlNa9Hbx8XnEL1Aztt9F7W8,1080
|
|
11
|
+
digraphx-0.1.dist-info/METADATA,sha256=CTlcQ9wPwvM4NN5YhW3kdu87OHT9Evi4voFHigbIbD4,2456
|
|
12
|
+
digraphx-0.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
13
|
+
digraphx-0.1.dist-info/top_level.txt,sha256=ZrZmsCjPDRkUco9-v0BMtqpg7GXOF8g5ZCETmPlU5oE,9
|
|
14
|
+
digraphx-0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Wai-Shing Luk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
digraphx
|