netoptim 0.1__tar.gz → 0.2__tar.gz

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.
Files changed (87) hide show
  1. {netoptim-0.1 → netoptim-0.2}/.github/workflows/ci.bak +1 -1
  2. {netoptim-0.1 → netoptim-0.2}/.github/workflows/multi-platforms.yml +6 -5
  3. {netoptim-0.1 → netoptim-0.2}/.github/workflows/python-app.yml +2 -2
  4. {netoptim-0.1 → netoptim-0.2}/.github/workflows/python-package.yml +3 -3
  5. {netoptim-0.1 → netoptim-0.2}/.pre-commit-config.yaml +2 -0
  6. {netoptim-0.1 → netoptim-0.2}/.readthedocs.yml +1 -1
  7. {netoptim-0.1 → netoptim-0.2}/CONTRIBUTING.md +20 -18
  8. netoptim-0.2/GEMINI.md +64 -0
  9. netoptim-0.2/IFLOW.md +85 -0
  10. {netoptim-0.1 → netoptim-0.2}/LICENSE.txt +1 -1
  11. {netoptim-0.1/src/netoptim.egg-info → netoptim-0.2}/PKG-INFO +9 -4
  12. {netoptim-0.1 → netoptim-0.2}/README.md +2 -2
  13. {netoptim-0.1 → netoptim-0.2}/docs/api/netoptim.rst +2 -10
  14. {netoptim-0.1 → netoptim-0.2}/docs/conf.py +3 -27
  15. {netoptim-0.1 → netoptim-0.2}/docs/requirements.txt +4 -0
  16. {netoptim-0.1 → netoptim-0.2}/environment.yml +1 -0
  17. {netoptim-0.1 → netoptim-0.2}/requirements/default.txt +1 -0
  18. {netoptim-0.1 → netoptim-0.2}/requirements/doc.txt +1 -0
  19. {netoptim-0.1 → netoptim-0.2}/setup.cfg +6 -1
  20. netoptim-0.2/src/netoptim/__init__.py +16 -0
  21. netoptim-0.2/src/netoptim/network_oracle.py +115 -0
  22. netoptim-0.2/src/netoptim/optscaling_oracle.py +160 -0
  23. {netoptim-0.1 → netoptim-0.2/src/netoptim.egg-info}/PKG-INFO +9 -4
  24. {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/SOURCES.txt +11 -7
  25. {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/requires.txt +1 -0
  26. netoptim-0.2/tests/__init__.py +0 -0
  27. netoptim-0.2/tests/test_cycle_finder.py +132 -0
  28. netoptim-0.2/tests/test_cycle_finder2.py +172 -0
  29. netoptim-0.2/tests/test_delay_padding.py +133 -0
  30. netoptim-0.2/tests/test_network_oracle.py +68 -0
  31. netoptim-0.2/tests/test_network_oracle2.py +96 -0
  32. netoptim-0.2/tests/test_optscaling.py +157 -0
  33. netoptim-0.2/tests/test_ratio.py +83 -0
  34. netoptim-0.2/tests/test_stress_network_oracle.py +70 -0
  35. netoptim-0.2/tests/test_stress_optscaling.py +112 -0
  36. netoptim-0.1/docs/authors.rst +0 -2
  37. netoptim-0.1/docs/changelog.rst +0 -2
  38. netoptim-0.1/docs/index.rst +0 -59
  39. netoptim-0.1/docs/license.rst +0 -7
  40. netoptim-0.1/src/netoptim/__init__.py +0 -16
  41. netoptim-0.1/src/netoptim/network_oracle.py +0 -72
  42. netoptim-0.1/src/netoptim/optscaling_oracle.py +0 -90
  43. netoptim-0.1/src/netoptim/skeleton.py +0 -149
  44. netoptim-0.1/tests/test_optscaling.py +0 -128
  45. netoptim-0.1/tests/test_optscaling_raw.py +0 -130
  46. netoptim-0.1/tests/test_skeleton.py +0 -25
  47. {netoptim-0.1 → netoptim-0.2}/.coveragerc +0 -0
  48. {netoptim-0.1 → netoptim-0.2}/.flake8 +0 -0
  49. {netoptim-0.1 → netoptim-0.2}/.github/workflows/jekyll-gh-pages.yml +0 -0
  50. {netoptim-0.1 → netoptim-0.2}/.github/workflows/multi-platforms.bak +0 -0
  51. {netoptim-0.1 → netoptim-0.2}/.github/workflows/python-publish.yml +0 -0
  52. {netoptim-0.1 → netoptim-0.2}/.gitignore +0 -0
  53. {netoptim-0.1 → netoptim-0.2}/.gitpod.yml +0 -0
  54. {netoptim-0.1 → netoptim-0.2}/.isort.cfg +0 -0
  55. {netoptim-0.1 → netoptim-0.2}/.markdownlint.json +0 -0
  56. {netoptim-0.1 → netoptim-0.2}/.shellcheckrc +0 -0
  57. {netoptim-0.1 → netoptim-0.2}/AUTHORS.md +0 -0
  58. {netoptim-0.1 → netoptim-0.2}/AUTHORS.rst +0 -0
  59. {netoptim-0.1 → netoptim-0.2}/CHANGELOG.md +0 -0
  60. {netoptim-0.1 → netoptim-0.2}/CHANGELOG.rst +0 -0
  61. {netoptim-0.1 → netoptim-0.2}/LICENSE +0 -0
  62. {netoptim-0.1 → netoptim-0.2}/README.rst +0 -0
  63. {netoptim-0.1 → netoptim-0.2}/_config.yml +0 -0
  64. {netoptim-0.1 → netoptim-0.2}/docs/Makefile +0 -0
  65. {netoptim-0.1 → netoptim-0.2}/docs/_static/.gitignore +0 -0
  66. {netoptim-0.1 → netoptim-0.2}/docs/api/modules.rst +0 -0
  67. {netoptim-0.1 → netoptim-0.2}/docs/authors.md +0 -0
  68. {netoptim-0.1 → netoptim-0.2}/docs/changelog.md +0 -0
  69. {netoptim-0.1 → netoptim-0.2}/docs/contributing.md +0 -0
  70. {netoptim-0.1 → netoptim-0.2}/docs/index.md +0 -0
  71. {netoptim-0.1 → netoptim-0.2}/docs/license.md +0 -0
  72. {netoptim-0.1 → netoptim-0.2}/docs/readme.md +0 -0
  73. {netoptim-0.1 → netoptim-0.2}/experiments/plot_node_colormap.ipynb +0 -0
  74. {netoptim-0.1 → netoptim-0.2}/experiments/plot_node_colormap.py +0 -0
  75. {netoptim-0.1 → netoptim-0.2}/mypy.ini +0 -0
  76. {netoptim-0.1 → netoptim-0.2}/note.md +0 -0
  77. {netoptim-0.1 → netoptim-0.2}/pyproject.toml +0 -0
  78. {netoptim-0.1 → netoptim-0.2}/requirements/README.md +0 -0
  79. {netoptim-0.1 → netoptim-0.2}/requirements/test.txt +0 -0
  80. {netoptim-0.1 → netoptim-0.2}/requirements.txt +0 -0
  81. {netoptim-0.1 → netoptim-0.2}/setup.py +0 -0
  82. /netoptim-0.1/tests/__init__.py → /netoptim-0.2/src/netoptim/py.typed +0 -0
  83. {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/dependency_links.txt +0 -0
  84. {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/not-zip-safe +0 -0
  85. {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/top_level.txt +0 -0
  86. {netoptim-0.1 → netoptim-0.2}/tests/conftest.py +0 -0
  87. {netoptim-0.1 → netoptim-0.2}/tox.ini +0 -0
@@ -8,7 +8,7 @@ on:
8
8
  push:
9
9
  # Avoid using all the resources/limits available by checking only
10
10
  # relevant branches and tags. Other branches can be checked via PRs.
11
- branches: [master]
11
+ branches: [ master, dev ]
12
12
  tags: ['v[0-9]*', '[0-9]+.[0-9]+*'] # Match tags that resemble a version
13
13
  pull_request: # Run in every PR
14
14
  workflow_dispatch: # Allow manually triggering the workflow
@@ -8,10 +8,10 @@ jobs:
8
8
  strategy:
9
9
  matrix:
10
10
  os: ["ubuntu-latest", "windows-latest"]
11
- version: ["3.9", "3.12"]
11
+ version: ["3.9", "3.11"]
12
12
  steps:
13
- - uses: actions/checkout@v2
14
- - uses: conda-incubator/setup-miniconda@v2
13
+ - uses: actions/checkout@v3
14
+ - uses: conda-incubator/setup-miniconda@v3
15
15
  with:
16
16
  activate-environment: test
17
17
  environment-file: environment.yml
@@ -31,10 +31,11 @@ jobs:
31
31
  shell: bash -l {0}
32
32
  run: |
33
33
  conda install pytest
34
- python -m pip install --upgrade pip
34
+ conda install pip
35
+ conda install setuptools wheel setuptools_scm
35
36
  if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
36
37
  pip install git+https://github.com/luk036/mywheel.git
37
38
  pip install git+https://github.com/luk036/ellalgo.git
38
39
  pip install git+https://github.com/luk036/digraphx.git
39
- python setup.py develop
40
+ pip install -e .
40
41
  pytest
@@ -5,9 +5,9 @@ name: Python application
5
5
 
6
6
  on:
7
7
  push:
8
- branches: [master]
8
+ branches: [ master, dev ]
9
9
  pull_request:
10
- branches: [master]
10
+ branches: [ master, dev ]
11
11
 
12
12
  jobs:
13
13
  build:
@@ -5,9 +5,9 @@ name: Python package
5
5
 
6
6
  on:
7
7
  push:
8
- branches: [master]
8
+ branches: [ master, dev ]
9
9
  pull_request:
10
- branches: [master]
10
+ branches: [ master, dev ]
11
11
 
12
12
  jobs:
13
13
  build:
@@ -15,7 +15,7 @@ jobs:
15
15
  strategy:
16
16
  fail-fast: false
17
17
  matrix:
18
- python-version: ["3.9", "3.12"]
18
+ python-version: ["3.9", "3.11"]
19
19
 
20
20
  steps:
21
21
  - uses: actions/checkout@v2
@@ -14,8 +14,10 @@ repos:
14
14
  - id: debug-statements
15
15
  - id: end-of-file-fixer
16
16
  - id: requirements-txt-fixer
17
+ exclude: "requirements[.]txt$"
17
18
  - id: mixed-line-ending
18
19
  args: ["--fix=auto"] # replace 'auto' with 'lf' to enforce Linux/Mac line endings or 'crlf' for Windows
20
+ exclude: "requirements[.]txt$"
19
21
 
20
22
  ## If you want to automatically "modernize" your Python code:
21
23
  # - repo: https://github.com/asottile/pyupgrade
@@ -9,7 +9,7 @@ version: 2
9
9
  build:
10
10
  os: ubuntu-22.04
11
11
  tools:
12
- python: "3.12"
12
+ python: "3.11"
13
13
  # You can also specify other tool versions:
14
14
  # nodejs: "19"
15
15
  # rust: "1.64"
@@ -69,27 +69,29 @@ by adding missing information and correcting mistakes.
69
69
  This means that the docs are kept in the same repository as the project code, and
70
70
  that any documentation update is done in the same way was a code contribution.
71
71
 
72
- ```{todo} Don't forget to mention which markup language you are using.
72
+ ```{todo}
73
+ Don't forget to mention which markup language you are using.
73
74
 
74
- e.g., [reStructuredText] or [CommonMark] with [MyST] extensions.
75
+ e.g., [reStructuredText] or [CommonMark] with [MyST] extensions.
75
76
  ```
76
77
 
77
- ```{todo} If your project is hosted on GitHub, you can also mention the following tip:
78
-
79
- :::{tip}
80
- Please notice that the [GitHub web interface] provides a quick way of
81
- propose changes in `netoptim`'s files. While this mechanism can
82
- be tricky for normal code contributions, it works perfectly fine for
83
- contributing to the docs, and can be quite handy.
84
-
85
- If you are interested in trying this method out, please navigate to
86
- the `docs` folder in the source [repository], find which file you
87
- would like to propose changes and click in the little pencil icon at the
88
- top, to open [GitHub's code editor]. Once you finish editing the file,
89
- please write a message in the form at the bottom of the page describing
90
- which changes have you made and what are the motivations behind them and
91
- submit your proposal.
92
- :::
78
+ ```{todo}
79
+ If your project is hosted on GitHub, you can also mention the following tip:
80
+
81
+ :::{tip}
82
+ Please notice that the [GitHub web interface] provides a quick way of
83
+ propose changes in `netoptim`'s files. While this mechanism can
84
+ be tricky for normal code contributions, it works perfectly fine for
85
+ contributing to the docs, and can be quite handy.
86
+
87
+ If you are interested in trying this method out, please navigate to
88
+ the `docs` folder in the source [repository], find which file you
89
+ would like to propose changes and click in the little pencil icon at the
90
+ top, to open [GitHub's code editor]. Once you finish editing the file,
91
+ please write a message in the form at the bottom of the page describing
92
+ which changes have you made and what are the motivations behind them and
93
+ submit your proposal.
94
+ :::
93
95
  ```
94
96
 
95
97
  When working on documentation changes in your local machine, you can
netoptim-0.2/GEMINI.md ADDED
@@ -0,0 +1,64 @@
1
+ # Gemini Code Assistant Context
2
+
3
+ ## Project Overview
4
+
5
+ This is a Python project for **Network Optimization**. It uses `networkx` for graph-related operations. The project is set up using `PyScaffold`, and the packaging is configured in `setup.cfg`.
6
+
7
+ The project's source code is located in the `src` directory, and the tests are in the `tests` directory.
8
+
9
+ ## Building and Running
10
+
11
+ ### Dependencies
12
+
13
+ The main dependencies are:
14
+ - `networkx`
15
+ - `ellalgo`
16
+ - `mywheel`
17
+ - `digraphx`
18
+ - `numpy`
19
+
20
+ To install all the necessary dependencies, you can use the `requirements.txt` file:
21
+
22
+ ```bash
23
+ pip install -r requirements.txt
24
+ ```
25
+
26
+ ### Running Tests
27
+
28
+ The project uses `pytest` for testing. To run the tests, use the following command:
29
+
30
+ ```bash
31
+ pytest
32
+ ```
33
+
34
+ You can also use `tox` to run the tests in an isolated environment:
35
+
36
+ ```bash
37
+ tox
38
+ ```
39
+
40
+ ### Building the Project
41
+
42
+ To build the project, you can use the `build` environment in `tox`:
43
+
44
+ ```bash
45
+ tox -e build
46
+ ```
47
+
48
+ This will create a `dist` directory with the built package.
49
+
50
+ ## Development Conventions
51
+
52
+ ### Code Style
53
+
54
+ The project uses the following tools to maintain code quality:
55
+
56
+ - **Formatting:** `black` is used for code formatting.
57
+ - **Import Sorting:** `isort` is used to sort imports automatically.
58
+ - **Linting:** `flake8` is used for linting the code.
59
+
60
+ These tools are configured in the `.pre-commit-config.yaml` file and are run automatically before each commit.
61
+
62
+ ### Contribution Guidelines
63
+
64
+ The `CONTRIBUTING.md` file provides guidelines for contributing to the project. It is recommended to read this file before making any contributions.
netoptim-0.2/IFLOW.md ADDED
@@ -0,0 +1,85 @@
1
+ # IFLOW.md - Network Optimization Python Code (netoptim)
2
+
3
+ ## 项目概述
4
+
5
+ `netoptim` 是一个用于网络优化的 Python 代码库,基于 PyScaffold 4.5 创建。该项目主要解决参数化网络问题,包括网络流优化和最优矩阵缩放等。项目依赖于一些专门的库,如 `ellalgo`(椭球算法优化库)、`digraphx`(有向图处理)和 `mywheel`(工具库)。
6
+
7
+ 核心功能包括:
8
+ - `NetworkOracle`:用于解决参数化网络问题的 oracle 类,通过寻找负圈来评估约束满足性
9
+ - `OptScalingOracle`:用于最优矩阵缩放问题的 oracle 类,实现 Orlin 和 Rothblum (1985) 提出的算法
10
+
11
+ ## 项目结构
12
+
13
+ ```
14
+ netoptim/
15
+ ├── src/netoptim/ # 源代码目录
16
+ │ ├── __init__.py
17
+ │ ├── network_oracle.py # 网络 oracle 实现
18
+ │ ├── optscaling_oracle.py # 最优缩放 oracle 实现
19
+ │ └── py.typed
20
+ ├── tests/ # 测试文件目录
21
+ ├── requirements/ # 依赖文件目录
22
+ │ ├── default.txt
23
+ │ ├── test.txt
24
+ │ └── doc.txt
25
+ ├── pyproject.toml # 项目构建配置
26
+ ├── setup.cfg # 项目配置
27
+ ├── README.md # 项目说明
28
+ └── ...
29
+ ```
30
+
31
+ ## 依赖
32
+
33
+ - `luk036/ellalgo` - 椭球优化算法库
34
+ - `luk036/mywheel` - 工具库
35
+ - `luk036/digraphx` - 有向图处理库
36
+ - `networkx` - 网络分析库
37
+ - `numpy` - 数值计算库
38
+ - `icecream` - 调试输出库
39
+
40
+ ## 构建和运行
41
+
42
+ ### 安装依赖
43
+
44
+ ```bash
45
+ pip install -r requirements/default.txt
46
+ pip install -r requirements/test.txt # 测试依赖
47
+ ```
48
+
49
+ ### 运行测试
50
+
51
+ ```bash
52
+ pytest # 运行所有测试
53
+ pytest tests/ -v # 运行测试并显示详细信息
54
+ pytest --cov=netoptim # 运行测试并生成覆盖率报告
55
+ ```
56
+
57
+ ### 使用示例
58
+
59
+ ```python
60
+ from netoptim.network_oracle import NetworkOracle
61
+ from unittest.mock import Mock
62
+
63
+ # 创建图结构
64
+ gra = {
65
+ "v1": {"v2": {"w": 3}, "v3": {"w": 4}},
66
+ "v2": {"v1": {"w": -2}, "v3": {"w": 1}},
67
+ "v3": {"v1": {"w": -3}, "v2": {"w": -2}},
68
+ }
69
+
70
+ u = {"v1": 0, "v2": 0, "v3": 0}
71
+ oracle = Mock()
72
+ oracle.eval.side_effect = lambda e, x: e["w"] - x
73
+ oracle.grad.side_effect = lambda e, x: -1
74
+
75
+ network = NetworkOracle(gra, u, oracle)
76
+ result = network.assess_feas(1)
77
+ ```
78
+
79
+ ## 开发约定
80
+
81
+ - 代码遵循 PEP 8 编码风格
82
+ - 使用 pytest 进行单元测试
83
+ - 项目使用语义化版本控制
84
+ - 通过 `setup.cfg` 配置项目选项和测试参数
85
+ - 使用 `flake8` 进行代码风格检查
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2023 Wai-Shing Luk
3
+ Copyright (c) 2025 Wai-Shing Luk
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,15 +1,19 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netoptim
3
- Version: 0.1
3
+ Version: 0.2
4
4
  Summary: Network Optimization Python Code
5
5
  Home-page: https://github.com/luk036/netoptim
6
6
  Author: Wai-Shing Luk
7
7
  Author-email: luk036@gmail.com
8
8
  License: MIT
9
- Project-URL: Documentation, https://pyscaffold.org/
9
+ Project-URL: Documentation, https://netoptim.readthedocs.io/
10
+ Project-URL: Source, https://github.com/luk036/netoptim
11
+ Project-URL: Changelog, https://github.com/luk036/netoptim/blob/main/CHANGELOG.md
12
+ Project-URL: Tracker, https://github.com/luk036/netoptim/issues
10
13
  Platform: any
11
14
  Classifier: Development Status :: 4 - Beta
12
15
  Classifier: Programming Language :: Python
16
+ Requires-Python: >=3.9
13
17
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
14
18
  License-File: LICENSE.txt
15
19
  Requires-Dist: importlib-metadata; python_version < "3.9"
@@ -20,6 +24,7 @@ Requires-Dist: pytest; extra == "testing"
20
24
  Requires-Dist: pytest-cov; extra == "testing"
21
25
  Requires-Dist: networkx; extra == "testing"
22
26
  Requires-Dist: numpy; extra == "testing"
27
+ Requires-Dist: icecream; extra == "testing"
23
28
  Dynamic: license-file
24
29
 
25
30
  <!-- These are examples of badges you might want to add to your README:
@@ -38,9 +43,9 @@ Dynamic: license-file
38
43
  [![Documentation Status](https://readthedocs.org/projects/netoptim/badge/?version=latest)](https://netoptim.readthedocs.io/en/latest/?badge=latest)
39
44
  [![codecov](https://codecov.io/gh/luk036/netoptim/graph/badge.svg?token=BqErpMZbCK)](https://codecov.io/gh/luk036/netoptim)
40
45
 
41
- # 🖧 netoptim
46
+ # 🌊 netoptim
42
47
 
43
- > Network Optimization Python Code
48
+ > Network Flow Optimization Python Code
44
49
 
45
50
  A longer description of your project goes here...
46
51
 
@@ -14,9 +14,9 @@
14
14
  [![Documentation Status](https://readthedocs.org/projects/netoptim/badge/?version=latest)](https://netoptim.readthedocs.io/en/latest/?badge=latest)
15
15
  [![codecov](https://codecov.io/gh/luk036/netoptim/graph/badge.svg?token=BqErpMZbCK)](https://codecov.io/gh/luk036/netoptim)
16
16
 
17
- # 🖧 netoptim
17
+ # 🌊 netoptim
18
18
 
19
- > Network Optimization Python Code
19
+ > Network Flow Optimization Python Code
20
20
 
21
21
  A longer description of your project goes here...
22
22
 
@@ -9,29 +9,21 @@ netoptim.network\_oracle module
9
9
 
10
10
  .. automodule:: netoptim.network_oracle
11
11
  :members:
12
- :undoc-members:
13
12
  :show-inheritance:
13
+ :undoc-members:
14
14
 
15
15
  netoptim.optscaling\_oracle module
16
16
  ----------------------------------
17
17
 
18
18
  .. automodule:: netoptim.optscaling_oracle
19
19
  :members:
20
- :undoc-members:
21
20
  :show-inheritance:
22
-
23
- netoptim.skeleton module
24
- ------------------------
25
-
26
- .. automodule:: netoptim.skeleton
27
- :members:
28
21
  :undoc-members:
29
- :show-inheritance:
30
22
 
31
23
  Module contents
32
24
  ---------------
33
25
 
34
26
  .. automodule:: netoptim
35
27
  :members:
36
- :undoc-members:
37
28
  :show-inheritance:
29
+ :undoc-members:
@@ -9,7 +9,6 @@
9
9
 
10
10
  import os
11
11
  import sys
12
- import shutil
13
12
 
14
13
  # -- Path setup --------------------------------------------------------------
15
14
 
@@ -28,31 +27,6 @@ sys.path.insert(0, os.path.join(__location__, "../src"))
28
27
  # setup.py install" in the RTD Advanced Settings.
29
28
  # Additionally it helps us to avoid running apidoc manually
30
29
 
31
- try: # for Sphinx >= 1.7
32
- from sphinx.ext import apidoc
33
- except ImportError:
34
- from sphinx import apidoc
35
-
36
- output_dir = os.path.join(__location__, "api")
37
- module_dir = os.path.join(__location__, "../src/netoptim")
38
- try:
39
- shutil.rmtree(output_dir)
40
- except FileNotFoundError:
41
- pass
42
-
43
- try:
44
- import sphinx
45
-
46
- cmd_line = f"sphinx-apidoc --implicit-namespaces -f -o {output_dir} {module_dir}"
47
-
48
- args = cmd_line.split(" ")
49
- if tuple(sphinx.__version__.split(".")) >= ("1", "7"):
50
- # This is a rudimentary parse_version to avoid external dependencies
51
- args = args[1:]
52
-
53
- apidoc.main(args)
54
- except Exception as e:
55
- print("Running `sphinx-apidoc` failed!\n{}".format(e))
56
30
 
57
31
  # -- General configuration ---------------------------------------------------
58
32
 
@@ -62,6 +36,7 @@ except Exception as e:
62
36
  # Add any Sphinx extension module names here, as strings. They can be extensions
63
37
  # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
64
38
  extensions = [
39
+ "sphinx.ext.apidoc",
65
40
  "sphinx.ext.autodoc",
66
41
  "sphinx.ext.intersphinx",
67
42
  "sphinx.ext.todo",
@@ -72,6 +47,7 @@ extensions = [
72
47
  "sphinx.ext.ifconfig",
73
48
  "sphinx.ext.mathjax",
74
49
  "sphinx.ext.napoleon",
50
+ "sphinxcontrib.svgbob",
75
51
  ]
76
52
 
77
53
  # Add any paths that contain templates here, relative to this directory.
@@ -249,7 +225,7 @@ htmlhelp_basename = "netoptim-doc"
249
225
 
250
226
  # -- Options for LaTeX output ------------------------------------------------
251
227
 
252
- latex_elements = {
228
+ latex_elements: dict[str, str] = {
253
229
  # The paper size ("letterpaper" or "a4paper").
254
230
  # "papersize": "letterpaper",
255
231
  # The font size ("10pt", "11pt" or "12pt").
@@ -1,6 +1,10 @@
1
+ digraphx
2
+ ellalgo
1
3
  # Requirements file for ReadTheDocs, check .readthedocs.yml.
2
4
  # To build the module reference correctly, make sure every external package
3
5
  # under `install_requires` in `setup.cfg` is also listed here!
4
6
  # sphinx_rtd_theme
5
7
  myst-parser[linkify]
8
+ numpy
6
9
  sphinx>=3.2.1
10
+ sphinxcontrib-svgbob
@@ -5,3 +5,4 @@ dependencies:
5
5
  - pytest
6
6
  - pytest-benchmark
7
7
  - networkx
8
+ - icecream
@@ -1,3 +1,4 @@
1
1
  decorator>=4.1.0
2
+ icecream>=1.0
2
3
  networkx>=2.1
3
4
  numpy>=1.12.0
@@ -1,2 +1,3 @@
1
1
  sphinx>=1.6.3
2
2
  sphinx_rtd_theme>=0.2.4
3
+ sphinxcontrib-svgbob>=1.0.0
@@ -9,7 +9,10 @@ long_description = file: README.md
9
9
  long_description_content_type = text/markdown; charset=UTF-8; variant=GFM
10
10
  url = https://github.com/luk036/netoptim
11
11
  project_urls =
12
- Documentation = https://pyscaffold.org/
12
+ Documentation = https://netoptim.readthedocs.io/
13
+ Source = https://github.com/luk036/netoptim
14
+ Changelog = https://github.com/luk036/netoptim/blob/main/CHANGELOG.md
15
+ Tracker = https://github.com/luk036/netoptim/issues
13
16
  platforms = any
14
17
  classifiers =
15
18
  Development Status :: 4 - Beta
@@ -21,6 +24,7 @@ packages = find_namespace:
21
24
  include_package_data = True
22
25
  package_dir =
23
26
  =src
27
+ python_requires = >=3.9
24
28
  install_requires =
25
29
  importlib-metadata; python_version<"3.9"
26
30
  networkx
@@ -37,6 +41,7 @@ testing =
37
41
  pytest-cov
38
42
  networkx
39
43
  numpy
44
+ icecream
40
45
 
41
46
  [options.entry_points]
42
47
 
@@ -0,0 +1,16 @@
1
+ """Network Flow Optimization Package.
2
+
3
+ Provides tools for solving parametric network flow problems
4
+ using cutting-plane methods and ellipsoid algorithms.
5
+ """
6
+
7
+ from importlib.metadata import PackageNotFoundError, version # pragma: no cover
8
+
9
+ try:
10
+ # Change here if project is renamed and does not equal the package name
11
+ dist_name = __name__
12
+ __version__ = version(dist_name)
13
+ except PackageNotFoundError: # pragma: no cover
14
+ __version__ = "unknown"
15
+ finally:
16
+ del version, PackageNotFoundError
@@ -0,0 +1,115 @@
1
+ from typing import Any, Dict, Optional, Tuple, Union
2
+
3
+ from digraphx.neg_cycle import NegCycleFinder
4
+
5
+ Cut = Tuple[Any, float]
6
+ """A cutting plane represented as a tuple of (gradient, intercept).
7
+
8
+ The gradient is typically a vector representing the subgradient of the
9
+ objective function, and the intercept is the constant term in the
10
+ linear cut.
11
+ """
12
+
13
+ Graph = Dict[Any, Dict[Any, Union[Dict[str, Any], Tuple[Any, Any]]]]
14
+ """A directed graph represented as an adjacency dictionary.
15
+
16
+ The outer dict maps each node to a dict of its neighbors.
17
+ Each neighbor maps to either a dict of edge attributes (e.g., {'w': weight})
18
+ or a tuple of (source, target) edge information.
19
+ """
20
+
21
+
22
+ class NetworkOracle:
23
+ """Oracle for Parametric Network Problem:
24
+
25
+ The `NetworkOracle` class represents an oracle for solving a parametric network problem, where the
26
+ goal is to find values for variables `x` and `u` that satisfy certain constraints.
27
+
28
+ .. svgbob::
29
+
30
+ (u_i) ------ w(i,j) ------> (u_j)
31
+
32
+ u_j - u_i <= w(i,j)
33
+
34
+ | find x, u
35
+ | s.t. u[j] − u[i] ≤ oracle(edge, x)
36
+ | ∀ edge(i, j) ∈ E
37
+
38
+ Examples:
39
+ >>> from unittest.mock import Mock
40
+ >>> gra = {
41
+ ... "v1": {"v2": {"w": 3}, "v3": {"w": 4}},
42
+ ... "v2": {"v1": {"w": -2}, "v3": {"w": 1}},
43
+ ... "v3": {"v1": {"w": -3}, "v2": {"w": -2}},
44
+ ... }
45
+ >>> u = {"v1": 0, "v2": 0, "v3": 0}
46
+ >>> oracle = Mock()
47
+ >>> oracle.eval.side_effect = lambda e, x: e["w"] - x
48
+ >>> oracle.grad.side_effect = lambda e, x: -1
49
+ >>> network = NetworkOracle(gra, u, oracle)
50
+ >>> network.assess_feas(1)
51
+ (2, 3)
52
+ """
53
+
54
+ def __init__(self, gra: Graph, u: Dict[Any, int], oracle: Any) -> None:
55
+ """
56
+ Initialize the network oracle with a graph, node potentials, and an edge oracle.
57
+
58
+ :param gra: The directed graph represented as an adjacency dictionary
59
+ mapping each node to its neighbors and edge attributes.
60
+ :param u: The initial node potentials, a dictionary mapping each node
61
+ to its starting potential value.
62
+ :param oracle: The oracle object that provides `eval(edge, x)` and
63
+ `grad(edge, x)` methods for evaluating edge weights and their
64
+ subgradients at a given iterate x.
65
+ """
66
+ self._gra = gra
67
+ self._potential = u
68
+ self._oracle = oracle
69
+ self._ncf = NegCycleFinder(gra)
70
+
71
+ def update(self, t: float) -> None:
72
+ """Update the oracle with the best-so-far optimal value.
73
+
74
+ This method notifies the underlying oracle about the current best
75
+ feasible solution value, which may be used to refine cutting planes.
76
+
77
+ Args:
78
+ t: The best-so-far optimal value to update the oracle with.
79
+ """
80
+ self._oracle.update(t)
81
+
82
+ def assess_feas(self, x: Any) -> Optional[Cut]:
83
+ """Assess feasibility and generate a cutting plane if infeasible.
84
+
85
+ This method implements the feasibility oracle for the parametric
86
+ network problem. It searches for negative cycles in the graph
87
+ using Howard's algorithm. If a negative cycle exists, it returns
88
+ a cutting plane (gradient, intercept) to cut off the infeasible point.
89
+
90
+ Args:
91
+ x: The current iterate value to assess for feasibility.
92
+
93
+ Returns:
94
+ A Cut tuple (gradient, intercept) if the point is infeasible
95
+ (negative cycle exists), or None if feasible.
96
+ """
97
+
98
+ def get_weight(edge: Any) -> float:
99
+ """Compute the weight of an edge given the current iterate.
100
+
101
+ Args:
102
+ edge: The edge (i, j) to compute weight for.
103
+
104
+ Returns:
105
+ The oracle evaluation value for the edge at iterate x.
106
+ """
107
+ return self._oracle.eval(edge, x)
108
+
109
+ for cycle in self._ncf.howard(self._potential, get_weight):
110
+ f = -sum(self._oracle.eval(edge, x) for edge in cycle)
111
+ g = -sum(self._oracle.grad(edge, x) for edge in cycle)
112
+ # TODO: choose the minumum cycle
113
+ return g, f # use the first cycle only
114
+
115
+ return None