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.
- {netoptim-0.1 → netoptim-0.2}/.github/workflows/ci.bak +1 -1
- {netoptim-0.1 → netoptim-0.2}/.github/workflows/multi-platforms.yml +6 -5
- {netoptim-0.1 → netoptim-0.2}/.github/workflows/python-app.yml +2 -2
- {netoptim-0.1 → netoptim-0.2}/.github/workflows/python-package.yml +3 -3
- {netoptim-0.1 → netoptim-0.2}/.pre-commit-config.yaml +2 -0
- {netoptim-0.1 → netoptim-0.2}/.readthedocs.yml +1 -1
- {netoptim-0.1 → netoptim-0.2}/CONTRIBUTING.md +20 -18
- netoptim-0.2/GEMINI.md +64 -0
- netoptim-0.2/IFLOW.md +85 -0
- {netoptim-0.1 → netoptim-0.2}/LICENSE.txt +1 -1
- {netoptim-0.1/src/netoptim.egg-info → netoptim-0.2}/PKG-INFO +9 -4
- {netoptim-0.1 → netoptim-0.2}/README.md +2 -2
- {netoptim-0.1 → netoptim-0.2}/docs/api/netoptim.rst +2 -10
- {netoptim-0.1 → netoptim-0.2}/docs/conf.py +3 -27
- {netoptim-0.1 → netoptim-0.2}/docs/requirements.txt +4 -0
- {netoptim-0.1 → netoptim-0.2}/environment.yml +1 -0
- {netoptim-0.1 → netoptim-0.2}/requirements/default.txt +1 -0
- {netoptim-0.1 → netoptim-0.2}/requirements/doc.txt +1 -0
- {netoptim-0.1 → netoptim-0.2}/setup.cfg +6 -1
- netoptim-0.2/src/netoptim/__init__.py +16 -0
- netoptim-0.2/src/netoptim/network_oracle.py +115 -0
- netoptim-0.2/src/netoptim/optscaling_oracle.py +160 -0
- {netoptim-0.1 → netoptim-0.2/src/netoptim.egg-info}/PKG-INFO +9 -4
- {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/SOURCES.txt +11 -7
- {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/requires.txt +1 -0
- netoptim-0.2/tests/__init__.py +0 -0
- netoptim-0.2/tests/test_cycle_finder.py +132 -0
- netoptim-0.2/tests/test_cycle_finder2.py +172 -0
- netoptim-0.2/tests/test_delay_padding.py +133 -0
- netoptim-0.2/tests/test_network_oracle.py +68 -0
- netoptim-0.2/tests/test_network_oracle2.py +96 -0
- netoptim-0.2/tests/test_optscaling.py +157 -0
- netoptim-0.2/tests/test_ratio.py +83 -0
- netoptim-0.2/tests/test_stress_network_oracle.py +70 -0
- netoptim-0.2/tests/test_stress_optscaling.py +112 -0
- netoptim-0.1/docs/authors.rst +0 -2
- netoptim-0.1/docs/changelog.rst +0 -2
- netoptim-0.1/docs/index.rst +0 -59
- netoptim-0.1/docs/license.rst +0 -7
- netoptim-0.1/src/netoptim/__init__.py +0 -16
- netoptim-0.1/src/netoptim/network_oracle.py +0 -72
- netoptim-0.1/src/netoptim/optscaling_oracle.py +0 -90
- netoptim-0.1/src/netoptim/skeleton.py +0 -149
- netoptim-0.1/tests/test_optscaling.py +0 -128
- netoptim-0.1/tests/test_optscaling_raw.py +0 -130
- netoptim-0.1/tests/test_skeleton.py +0 -25
- {netoptim-0.1 → netoptim-0.2}/.coveragerc +0 -0
- {netoptim-0.1 → netoptim-0.2}/.flake8 +0 -0
- {netoptim-0.1 → netoptim-0.2}/.github/workflows/jekyll-gh-pages.yml +0 -0
- {netoptim-0.1 → netoptim-0.2}/.github/workflows/multi-platforms.bak +0 -0
- {netoptim-0.1 → netoptim-0.2}/.github/workflows/python-publish.yml +0 -0
- {netoptim-0.1 → netoptim-0.2}/.gitignore +0 -0
- {netoptim-0.1 → netoptim-0.2}/.gitpod.yml +0 -0
- {netoptim-0.1 → netoptim-0.2}/.isort.cfg +0 -0
- {netoptim-0.1 → netoptim-0.2}/.markdownlint.json +0 -0
- {netoptim-0.1 → netoptim-0.2}/.shellcheckrc +0 -0
- {netoptim-0.1 → netoptim-0.2}/AUTHORS.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/AUTHORS.rst +0 -0
- {netoptim-0.1 → netoptim-0.2}/CHANGELOG.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/CHANGELOG.rst +0 -0
- {netoptim-0.1 → netoptim-0.2}/LICENSE +0 -0
- {netoptim-0.1 → netoptim-0.2}/README.rst +0 -0
- {netoptim-0.1 → netoptim-0.2}/_config.yml +0 -0
- {netoptim-0.1 → netoptim-0.2}/docs/Makefile +0 -0
- {netoptim-0.1 → netoptim-0.2}/docs/_static/.gitignore +0 -0
- {netoptim-0.1 → netoptim-0.2}/docs/api/modules.rst +0 -0
- {netoptim-0.1 → netoptim-0.2}/docs/authors.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/docs/changelog.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/docs/contributing.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/docs/index.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/docs/license.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/docs/readme.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/experiments/plot_node_colormap.ipynb +0 -0
- {netoptim-0.1 → netoptim-0.2}/experiments/plot_node_colormap.py +0 -0
- {netoptim-0.1 → netoptim-0.2}/mypy.ini +0 -0
- {netoptim-0.1 → netoptim-0.2}/note.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/pyproject.toml +0 -0
- {netoptim-0.1 → netoptim-0.2}/requirements/README.md +0 -0
- {netoptim-0.1 → netoptim-0.2}/requirements/test.txt +0 -0
- {netoptim-0.1 → netoptim-0.2}/requirements.txt +0 -0
- {netoptim-0.1 → netoptim-0.2}/setup.py +0 -0
- /netoptim-0.1/tests/__init__.py → /netoptim-0.2/src/netoptim/py.typed +0 -0
- {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/dependency_links.txt +0 -0
- {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/not-zip-safe +0 -0
- {netoptim-0.1 → netoptim-0.2}/src/netoptim.egg-info/top_level.txt +0 -0
- {netoptim-0.1 → netoptim-0.2}/tests/conftest.py +0 -0
- {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.
|
|
11
|
+
version: ["3.9", "3.11"]
|
|
12
12
|
steps:
|
|
13
|
-
- uses: actions/checkout@
|
|
14
|
-
- uses: conda-incubator/setup-miniconda@
|
|
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
|
-
|
|
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
|
-
|
|
40
|
+
pip install -e .
|
|
40
41
|
pytest
|
|
@@ -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.
|
|
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
|
|
@@ -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}
|
|
72
|
+
```{todo}
|
|
73
|
+
Don't forget to mention which markup language you are using.
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
e.g., [reStructuredText] or [CommonMark] with [MyST] extensions.
|
|
75
76
|
```
|
|
76
77
|
|
|
77
|
-
```{todo}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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,15 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: netoptim
|
|
3
|
-
Version: 0.
|
|
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://
|
|
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
|
[](https://netoptim.readthedocs.io/en/latest/?badge=latest)
|
|
39
44
|
[](https://codecov.io/gh/luk036/netoptim)
|
|
40
45
|
|
|
41
|
-
#
|
|
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
|
[](https://netoptim.readthedocs.io/en/latest/?badge=latest)
|
|
15
15
|
[](https://codecov.io/gh/luk036/netoptim)
|
|
16
16
|
|
|
17
|
-
#
|
|
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
|
|
@@ -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://
|
|
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
|