dega2 0.1.0__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.
- dega2-0.1.0/LICENSE +21 -0
- dega2-0.1.0/PKG-INFO +122 -0
- dega2-0.1.0/README.md +101 -0
- dega2-0.1.0/pyproject.toml +33 -0
- dega2-0.1.0/setup.cfg +4 -0
- dega2-0.1.0/src/dega2/BuildpopGA.py +51 -0
- dega2-0.1.0/src/dega2/ConsChek.py +13 -0
- dega2-0.1.0/src/dega2/ConsChekGA4.py +19 -0
- dega2-0.1.0/src/dega2/DomChek.py +19 -0
- dega2-0.1.0/src/dega2/DomChekGA4.py +78 -0
- dega2-0.1.0/src/dega2/GA4.py +64 -0
- dega2-0.1.0/src/dega2/GenPop.py +32 -0
- dega2-0.1.0/src/dega2/__init__.py +9 -0
- dega2-0.1.0/src/dega2/__main__.py +4 -0
- dega2-0.1.0/src/dega2/cli.py +139 -0
- dega2-0.1.0/src/dega2/entree.py +180 -0
- dega2-0.1.0/src/dega2/example.py +29 -0
- dega2-0.1.0/src/dega2/influ_cof.py +29 -0
- dega2-0.1.0/src/dega2/plotting.py +32 -0
- dega2-0.1.0/src/dega2/problems.py +15 -0
- dega2-0.1.0/src/dega2/solver.py +120 -0
- dega2-0.1.0/src/dega2/upload_cofGA.py +72 -0
- dega2-0.1.0/src/dega2.egg-info/PKG-INFO +122 -0
- dega2-0.1.0/src/dega2.egg-info/SOURCES.txt +27 -0
- dega2-0.1.0/src/dega2.egg-info/dependency_links.txt +1 -0
- dega2-0.1.0/src/dega2.egg-info/entry_points.txt +2 -0
- dega2-0.1.0/src/dega2.egg-info/requires.txt +8 -0
- dega2-0.1.0/src/dega2.egg-info/top_level.txt +1 -0
- dega2-0.1.0/tests/test_dega2.py +151 -0
dega2-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ali Zaidi
|
|
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.
|
dega2-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dega2
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: DEGA-2: A optimization a function over the efficient set of multi-objective integer variables using the genetics algorithms
|
|
5
|
+
Author-email: Ali Zaidi <a.zaidi@crlca.dz>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: optimization,genetic algorithm,multi-objective,integer programming
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: tqdm
|
|
16
|
+
Provides-Extra: plot
|
|
17
|
+
Requires-Dist: matplotlib; extra == "plot"
|
|
18
|
+
Provides-Extra: test
|
|
19
|
+
Requires-Dist: pytest; extra == "test"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# DEGA-2
|
|
23
|
+
|
|
24
|
+
A optimisation of function over the efficient set of multi-objective integer variables using a genetics algorithms, by Ali Zaidi.
|
|
25
|
+
|
|
26
|
+
It minimizes a function `phi·x` subject to linear constraints `a·x <= b`
|
|
27
|
+
(`x` integer, and `x >= 0` by default), using `p` objectives `c·x` for the
|
|
28
|
+
non-dominance test.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install dega2
|
|
34
|
+
# with the convergence plot:
|
|
35
|
+
pip install "dega2[plot]"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Entering your problem and parameters
|
|
39
|
+
|
|
40
|
+
### 1. Interactive assistant
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
dega2
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The assistant asks for the problem (file, keyboard entry, or a random example),
|
|
47
|
+
then for the parameters (population size, alpha, number of explored variables,
|
|
48
|
+
iterations, `x >= 0` constraints). Press Enter to accept the suggested value.
|
|
49
|
+
|
|
50
|
+
### 2. `.json` file
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
dega2 --exemple my_problem.json # writes a template to edit
|
|
54
|
+
dega2 -f my_problem.json # runs the computation
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
File format:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"a": [[2, 3, 1], [1, 1, 2]],
|
|
62
|
+
"b": [20, 15],
|
|
63
|
+
"c": [[3, -1, 2], [-2, 4, 1]],
|
|
64
|
+
"phi": [-3, -2, -4],
|
|
65
|
+
"parametres": {
|
|
66
|
+
"n_population": 20, "alpha": 4, "explor": 3,
|
|
67
|
+
"iterations": 10, "positivity": true
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `a`: constraint matrix (m rows, n columns); `b`: right-hand side (m values)
|
|
73
|
+
- `c`: objectives matrix (p rows, n columns); `phi`: function to minimize (n values)
|
|
74
|
+
- `parametres` is optional. Command-line options (`--population`, `--alpha`,
|
|
75
|
+
`--explor`, `-T`, `--sans-positivite`, `--seed`, `--no-plot`) take precedence over
|
|
76
|
+
the file. A `.npz` file (keys `a`, `b`, `c`, `phi`) is also accepted.
|
|
77
|
+
|
|
78
|
+
### 3. In Python code
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
import numpy as np
|
|
82
|
+
import dega2
|
|
83
|
+
|
|
84
|
+
a = np.array([[2, 3, 1], [1, 1, 2]])
|
|
85
|
+
b = np.array([20, 15])
|
|
86
|
+
c = np.array([[3, -1, 2], [-2, 4, 1]])
|
|
87
|
+
phi = np.array([-3, -2, -4])
|
|
88
|
+
|
|
89
|
+
res = dega2.solve(a, b, c, phi, n_population=20, explor=3, iterations=10, seed=0)
|
|
90
|
+
|
|
91
|
+
print(res.phi) # best value of phi
|
|
92
|
+
print(res.x) # best solution
|
|
93
|
+
res.plot() # convergence curve (requires matplotlib)
|
|
94
|
+
|
|
95
|
+
# or from a file:
|
|
96
|
+
a, b, c, phi, params = dega2.charger_probleme("my_problem.json")
|
|
97
|
+
res = dega2.solve(a, b, c, phi, **params)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`solve` parameters: `n_population=80`, `alpha=4`, `explor=3`,
|
|
101
|
+
`iterations=None` (2·n by default), `positivity=True`, `seed=None`, `verbose=True`.
|
|
102
|
+
`solve` returns a `Result` object: `x`, `phi`, `history` (minimum of phi at each
|
|
103
|
+
iteration), `population`, `time`, `iterations`.
|
|
104
|
+
|
|
105
|
+
Note: the algorithm builds a population of `n_population` feasible solutions that
|
|
106
|
+
are mutually non-dominated. With very few objectives or variables, such a
|
|
107
|
+
population may not exist; `dega2` then stops with an error message (reduce
|
|
108
|
+
`n_population` or add objectives).
|
|
109
|
+
|
|
110
|
+
## Random demonstration
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
dega2 --demo --seed 1
|
|
114
|
+
dega2 --demo -n 20 -p 5 --no-plot
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Tests
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
pip install -e ".[test]"
|
|
121
|
+
pytest
|
|
122
|
+
```
|
dega2-0.1.0/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# DEGA-2
|
|
2
|
+
|
|
3
|
+
A optimisation of function over the efficient set of multi-objective integer variables using a genetics algorithms, by Ali Zaidi.
|
|
4
|
+
|
|
5
|
+
It minimizes a function `phi·x` subject to linear constraints `a·x <= b`
|
|
6
|
+
(`x` integer, and `x >= 0` by default), using `p` objectives `c·x` for the
|
|
7
|
+
non-dominance test.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install dega2
|
|
13
|
+
# with the convergence plot:
|
|
14
|
+
pip install "dega2[plot]"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Entering your problem and parameters
|
|
18
|
+
|
|
19
|
+
### 1. Interactive assistant
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
dega2
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The assistant asks for the problem (file, keyboard entry, or a random example),
|
|
26
|
+
then for the parameters (population size, alpha, number of explored variables,
|
|
27
|
+
iterations, `x >= 0` constraints). Press Enter to accept the suggested value.
|
|
28
|
+
|
|
29
|
+
### 2. `.json` file
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
dega2 --exemple my_problem.json # writes a template to edit
|
|
33
|
+
dega2 -f my_problem.json # runs the computation
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
File format:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"a": [[2, 3, 1], [1, 1, 2]],
|
|
41
|
+
"b": [20, 15],
|
|
42
|
+
"c": [[3, -1, 2], [-2, 4, 1]],
|
|
43
|
+
"phi": [-3, -2, -4],
|
|
44
|
+
"parametres": {
|
|
45
|
+
"n_population": 20, "alpha": 4, "explor": 3,
|
|
46
|
+
"iterations": 10, "positivity": true
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- `a`: constraint matrix (m rows, n columns); `b`: right-hand side (m values)
|
|
52
|
+
- `c`: objectives matrix (p rows, n columns); `phi`: function to minimize (n values)
|
|
53
|
+
- `parametres` is optional. Command-line options (`--population`, `--alpha`,
|
|
54
|
+
`--explor`, `-T`, `--sans-positivite`, `--seed`, `--no-plot`) take precedence over
|
|
55
|
+
the file. A `.npz` file (keys `a`, `b`, `c`, `phi`) is also accepted.
|
|
56
|
+
|
|
57
|
+
### 3. In Python code
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
import numpy as np
|
|
61
|
+
import dega2
|
|
62
|
+
|
|
63
|
+
a = np.array([[2, 3, 1], [1, 1, 2]])
|
|
64
|
+
b = np.array([20, 15])
|
|
65
|
+
c = np.array([[3, -1, 2], [-2, 4, 1]])
|
|
66
|
+
phi = np.array([-3, -2, -4])
|
|
67
|
+
|
|
68
|
+
res = dega2.solve(a, b, c, phi, n_population=20, explor=3, iterations=10, seed=0)
|
|
69
|
+
|
|
70
|
+
print(res.phi) # best value of phi
|
|
71
|
+
print(res.x) # best solution
|
|
72
|
+
res.plot() # convergence curve (requires matplotlib)
|
|
73
|
+
|
|
74
|
+
# or from a file:
|
|
75
|
+
a, b, c, phi, params = dega2.charger_probleme("my_problem.json")
|
|
76
|
+
res = dega2.solve(a, b, c, phi, **params)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`solve` parameters: `n_population=80`, `alpha=4`, `explor=3`,
|
|
80
|
+
`iterations=None` (2·n by default), `positivity=True`, `seed=None`, `verbose=True`.
|
|
81
|
+
`solve` returns a `Result` object: `x`, `phi`, `history` (minimum of phi at each
|
|
82
|
+
iteration), `population`, `time`, `iterations`.
|
|
83
|
+
|
|
84
|
+
Note: the algorithm builds a population of `n_population` feasible solutions that
|
|
85
|
+
are mutually non-dominated. With very few objectives or variables, such a
|
|
86
|
+
population may not exist; `dega2` then stops with an error message (reduce
|
|
87
|
+
`n_population` or add objectives).
|
|
88
|
+
|
|
89
|
+
## Random demonstration
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
dega2 --demo --seed 1
|
|
93
|
+
dega2 --demo -n 20 -p 5 --no-plot
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Tests
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install -e ".[test]"
|
|
100
|
+
pytest
|
|
101
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "dega2"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "DEGA-2: A optimization a function over the efficient set of multi-objective integer variables using the genetics algorithms"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Ali Zaidi", email = "a.zaidi@crlca.dz" }]
|
|
14
|
+
keywords = ["optimization", "genetic algorithm", "multi-objective", "integer programming"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Intended Audience :: Science/Research",
|
|
18
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
19
|
+
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"numpy",
|
|
22
|
+
"tqdm",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
plot = ["matplotlib"]
|
|
27
|
+
test = ["pytest"]
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
dega2 = "dega2.cli:main"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.packages.find]
|
|
33
|
+
where = ["src"]
|
dega2-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from . import ConsChekGA4, DomChekGA4
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def explorer(population1, n_population, explor, p_cof1, index_p, p_cofphi1, index_phi,
|
|
7
|
+
n_pop, n_pop_phi):
|
|
8
|
+
"""Phase d'exploration, vectorisée : pour chaque variable j, on ajoute +1 ou -1
|
|
9
|
+
sur toute la ligne concernée (au lieu de boucler colonne par colonne)."""
|
|
10
|
+
blocs_phi, blocs_p = [], []
|
|
11
|
+
tab_ind1, tab_ind1_ph = [], []
|
|
12
|
+
n_p = n_pop - n_pop_phi # nombre de colonnes modifiées dans la 2e moitié
|
|
13
|
+
|
|
14
|
+
for j in range(explor):
|
|
15
|
+
a1 = np.array(population1[:, 0:n_pop_phi])
|
|
16
|
+
a2 = np.array(population1[:, n_pop_phi:n_population])
|
|
17
|
+
|
|
18
|
+
r_phi = index_phi[0, j]
|
|
19
|
+
r_p = index_p[0, j]
|
|
20
|
+
a1[r_phi, :] += 1 if p_cofphi1[2, j] < 0 else -1
|
|
21
|
+
a2[r_p, :n_p] += 1 if p_cof1[2, j] < 0 else -1
|
|
22
|
+
|
|
23
|
+
tab_ind1_ph.extend([r_phi] * n_pop_phi)
|
|
24
|
+
tab_ind1.extend([r_p] * n_p)
|
|
25
|
+
blocs_phi.append(a1)
|
|
26
|
+
blocs_p.append(a2)
|
|
27
|
+
|
|
28
|
+
a3 = np.concatenate(blocs_phi, axis=1) # une seule concaténation
|
|
29
|
+
a4 = np.concatenate(blocs_p, axis=1)
|
|
30
|
+
return a3, a4, tab_ind1, tab_ind1_ph
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def Build_PT(population1, n_population, explor, p_cof1, index_p, p_cofphi1, index_phi,
|
|
34
|
+
phi, alpha, a, b, c, n_pop, n_pop_phi, n):
|
|
35
|
+
|
|
36
|
+
###################### Variables exploration ##############################
|
|
37
|
+
a3, a4, tab_ind1, tab_ind1_ph = explorer(
|
|
38
|
+
population1, n_population, explor, p_cof1, index_p, p_cofphi1, index_phi,
|
|
39
|
+
n_pop, n_pop_phi)
|
|
40
|
+
|
|
41
|
+
############ Check the constraints and dominance of new populations ########
|
|
42
|
+
tab_ind11 = tab_ind1.copy()
|
|
43
|
+
tab_ind11_phi = tab_ind1_ph.copy()
|
|
44
|
+
|
|
45
|
+
[pop1, pop1_phi, tab_ind11, tab_ind11_phi] = ConsChekGA4.chek(
|
|
46
|
+
a3, a4, a, b, tab_ind11_phi, tab_ind11)
|
|
47
|
+
|
|
48
|
+
[pop2, tab_ind11_phi, tab_ind11] = DomChekGA4.nd_update(
|
|
49
|
+
c, population1, pop1, pop1_phi, tab_ind11, tab_ind11_phi)
|
|
50
|
+
|
|
51
|
+
return pop2, tab_ind1, tab_ind11, tab_ind1_ph, tab_ind11_phi
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _realisables(a, b, pop):
|
|
5
|
+
"""Indices des colonnes de `pop` qui vérifient a @ x <= b (test fait pour toutes
|
|
6
|
+
les colonnes en un seul produit matriciel)."""
|
|
7
|
+
if pop.shape[1] == 0:
|
|
8
|
+
return np.arange(0)
|
|
9
|
+
return np.flatnonzero((a @ pop <= b).all(axis=0))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def chek(pop_phi, pop, a, b, tab_ind11_phi, tab_ind11):
|
|
13
|
+
idx = _realisables(a, b, pop)
|
|
14
|
+
idx_phi = _realisables(a, b, pop_phi)
|
|
15
|
+
|
|
16
|
+
return (pop[:, idx],
|
|
17
|
+
pop_phi[:, idx_phi],
|
|
18
|
+
[tab_ind11[k] for k in idx],
|
|
19
|
+
[tab_ind11_phi[k] for k in idx_phi])
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def non_dominance(c, pop):
|
|
5
|
+
obj_val = np.dot(c, pop)
|
|
6
|
+
idx = np.arange(obj_val.shape[1])
|
|
7
|
+
i = 0
|
|
8
|
+
while i < len(idx) - 1:
|
|
9
|
+
oi = obj_val[:, idx[i]][:, None]
|
|
10
|
+
reste = obj_val[:, idx[i + 1:]]
|
|
11
|
+
le = (oi <= reste).all(axis=0) # i domine (faiblement) j -> j supprimé
|
|
12
|
+
gt = (oi > reste).all(axis=0) # j domine strictement i -> i supprimé
|
|
13
|
+
if gt.any():
|
|
14
|
+
jg = int(gt.argmax()) # premier j qui domine i
|
|
15
|
+
idx = np.delete(idx, np.append(np.flatnonzero(le[:jg]) + i + 1, i))
|
|
16
|
+
else:
|
|
17
|
+
idx = np.delete(idx, np.flatnonzero(le) + i + 1)
|
|
18
|
+
i += 1
|
|
19
|
+
return pop[:, idx]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _indices_non_domines(obj):
|
|
5
|
+
"""Équivalent exact de la boucle de `non_dominance`, mais sans np.delete répétés
|
|
6
|
+
et avec la comparaison de i contre tous les j restants faite en une seule fois.
|
|
7
|
+
Renvoie les indices (dans l'ordre d'origine) des colonnes conservées."""
|
|
8
|
+
idx = np.arange(obj.shape[1])
|
|
9
|
+
i = 0
|
|
10
|
+
while i < len(idx) - 1:
|
|
11
|
+
oi = obj[:, idx[i]][:, None]
|
|
12
|
+
reste = obj[:, idx[i + 1:]]
|
|
13
|
+
le = (oi <= reste).all(axis=0) # i domine (faiblement) j -> j supprimé
|
|
14
|
+
gt = (oi > reste).all(axis=0) # j domine strictement i -> i supprimé
|
|
15
|
+
if gt.any():
|
|
16
|
+
jg = int(gt.argmax()) # premier j qui domine i
|
|
17
|
+
a_supprimer = np.append(np.flatnonzero(le[:jg]) + i + 1, i)
|
|
18
|
+
idx = np.delete(idx, a_supprimer) # i reste à la même position
|
|
19
|
+
else:
|
|
20
|
+
idx = np.delete(idx, np.flatnonzero(le) + i + 1)
|
|
21
|
+
i += 1
|
|
22
|
+
return idx
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def non_dominance(c, pop, tab_ind3):
|
|
26
|
+
obj_val = np.dot(c, pop)
|
|
27
|
+
idx = _indices_non_domines(obj_val)
|
|
28
|
+
return pop[:, idx], [tab_ind3[k] for k in idx], obj_val[:, idx]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _filtrer_contre(obj_p, idx_p, obj_ref, idx_ref, limite_fixe=None):
|
|
32
|
+
"""Compare chaque individu de la population (idx_p) à l'ensemble de référence
|
|
33
|
+
(idx_ref) : un individu de référence dominé est supprimé, et l'individu de la
|
|
34
|
+
population est supprimé dès qu'un élément de référence le domine strictement.
|
|
35
|
+
`limite_fixe` reproduit la borne de balayage de la 2e boucle d'origine."""
|
|
36
|
+
i = 0
|
|
37
|
+
while i < len(idx_p):
|
|
38
|
+
oi = obj_p[:, idx_p[i]][:, None]
|
|
39
|
+
L = len(idx_ref) if limite_fixe is None else min(limite_fixe, len(idx_ref))
|
|
40
|
+
ref = obj_ref[:, idx_ref[:L]]
|
|
41
|
+
le = (oi <= ref).all(axis=0)
|
|
42
|
+
gt = (oi > ref).all(axis=0)
|
|
43
|
+
if gt.any():
|
|
44
|
+
jg = int(gt.argmax())
|
|
45
|
+
idx_ref = np.delete(idx_ref, np.flatnonzero(le[:jg]))
|
|
46
|
+
idx_p = np.delete(idx_p, i) # i reste à la même position
|
|
47
|
+
else:
|
|
48
|
+
idx_ref = np.delete(idx_ref, np.flatnonzero(le))
|
|
49
|
+
i += 1
|
|
50
|
+
return idx_p, idx_ref
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def nd_update(c, population, pop1, pop1_phi, tab_ind11, tab_ind11_phi):
|
|
54
|
+
|
|
55
|
+
# non-dominance interne de pop1_phi puis de pop1
|
|
56
|
+
pop1_phi, tab_ind11_phi, obj_val_phi = non_dominance(c, pop1_phi, tab_ind11_phi)
|
|
57
|
+
pop1, tab_ind11, obj_val1 = non_dominance(c, pop1, tab_ind11)
|
|
58
|
+
|
|
59
|
+
obj_val_p = np.dot(c, population)
|
|
60
|
+
idx_p = np.arange(population.shape[1])
|
|
61
|
+
|
|
62
|
+
# population contre pop1
|
|
63
|
+
idx_p, idx1 = _filtrer_contre(obj_val_p, idx_p, obj_val1,
|
|
64
|
+
np.arange(pop1.shape[1]))
|
|
65
|
+
|
|
66
|
+
# population contre pop1_phi
|
|
67
|
+
# NB : comportement d'origine conservé. Le balayage de pop1_phi est borné par la
|
|
68
|
+
# taille de la population (size_popkD), pas par celle de pop1_phi : si pop1_phi
|
|
69
|
+
# est plus grande, ses derniers éléments ne sont pas comparés.
|
|
70
|
+
D = len(idx_p)
|
|
71
|
+
idx_p, idx_phi = _filtrer_contre(obj_val_p, idx_p, obj_val_phi,
|
|
72
|
+
np.arange(pop1_phi.shape[1]), limite_fixe=D)
|
|
73
|
+
|
|
74
|
+
pop2 = np.concatenate((population[:, idx_p], pop1_phi[:, idx_phi], pop1[:, idx1]),
|
|
75
|
+
axis=1)
|
|
76
|
+
return (pop2,
|
|
77
|
+
[tab_ind11_phi[k] for k in idx_phi],
|
|
78
|
+
[tab_ind11[k] for k in idx1])
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from . import BuildpopGA, GenPop, upload_cofGA
|
|
3
|
+
from tqdm import tqdm
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def NewPop(population1, n_population, explor, p_cof1, index_p, p_cofphi1, index_phi,
|
|
7
|
+
phi, alpha, a, b, c, T, n, verbose=True):
|
|
8
|
+
|
|
9
|
+
n_pop = len(population1.T)
|
|
10
|
+
n_pop_phi = int(n_pop / alpha)
|
|
11
|
+
|
|
12
|
+
min_phi = []
|
|
13
|
+
|
|
14
|
+
barre = tqdm(
|
|
15
|
+
range(T),
|
|
16
|
+
desc="DEGA-2",
|
|
17
|
+
unit="it",
|
|
18
|
+
colour="green",
|
|
19
|
+
disable=not verbose,
|
|
20
|
+
bar_format="{desc} {percentage:3.0f}%|{bar:35}| {n_fmt}/{total_fmt} "
|
|
21
|
+
"[{elapsed}<{remaining}, {rate_fmt}] {postfix}",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
for _ in barre:
|
|
25
|
+
[pop2, tab_ind1, tab_ind11, tab_ind1_phi, tab_ind11_phi] = BuildpopGA.Build_PT(
|
|
26
|
+
population1, n_population, explor, p_cof1, index_p, p_cofphi1, index_phi,
|
|
27
|
+
phi, alpha, a, b, c, n_pop, n_pop_phi, n)
|
|
28
|
+
|
|
29
|
+
s = pop2.shape[1]
|
|
30
|
+
|
|
31
|
+
if s > n_population:
|
|
32
|
+
# sélection des n_pop meilleurs individus (tri croissant de phi)
|
|
33
|
+
xphi1 = np.dot(phi, pop2)
|
|
34
|
+
ind_phi1 = np.argsort(xphi1, axis=1)
|
|
35
|
+
pop3 = pop2[:, ind_phi1[0, :n_pop]].astype(int)
|
|
36
|
+
elif s < n_population:
|
|
37
|
+
pop3 = GenPop.Gen(a, b, c, n, n_population - s)
|
|
38
|
+
pop3 = np.concatenate((pop2, pop3), axis=1)
|
|
39
|
+
else:
|
|
40
|
+
pop3 = pop2
|
|
41
|
+
|
|
42
|
+
population1 = pop3
|
|
43
|
+
xphi1 = np.dot(phi, pop3)
|
|
44
|
+
|
|
45
|
+
xphi2 = xphi1.min()
|
|
46
|
+
min_phi.append(xphi2)
|
|
47
|
+
|
|
48
|
+
##################### Candidats ####################################
|
|
49
|
+
condidat_phi = list(index_phi[0, :explor])
|
|
50
|
+
condidat = list(index_p[0, :explor])
|
|
51
|
+
|
|
52
|
+
##################### Mise à jour des coefficients #################
|
|
53
|
+
[p_cof1, p_cofphi1, index_p, index_phi] = upload_cofGA.upload(
|
|
54
|
+
p_cof1, index_p, p_cofphi1, index_phi,
|
|
55
|
+
tab_ind1, tab_ind1_phi, tab_ind11, tab_ind11_phi,
|
|
56
|
+
explor, condidat_phi, condidat, n_pop, n_pop_phi)
|
|
57
|
+
|
|
58
|
+
barre.set_postfix_str(f"min_phi={xphi2:.4e}", refresh=False)
|
|
59
|
+
|
|
60
|
+
# Correction : l'indice vient de pop3 (= population1), pas de pop2
|
|
61
|
+
min_index = xphi1.argmin()
|
|
62
|
+
xopt = population1[:, min_index]
|
|
63
|
+
|
|
64
|
+
return pop2, xphi2, min_phi, xopt
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from . import ConsChek, DomChek
|
|
3
|
+
|
|
4
|
+
# Nombre maximal de tirages consécutifs sans progression avant d'abandonner.
|
|
5
|
+
_ESSAIS_MAX = 5000
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def Gen(a,b,c,n,n_population):
|
|
9
|
+
population=np.random.randint(0,3,(n,n_population),dtype=int);
|
|
10
|
+
pop2=ConsChek.chek(population, a, b)
|
|
11
|
+
pop3=DomChek.non_dominance(c, pop2)
|
|
12
|
+
np1=n_population-len(pop3.T)
|
|
13
|
+
sans_progres=0
|
|
14
|
+
while np1!=0:
|
|
15
|
+
population=np.random.randint(0,3,(n,np1),dtype=int);
|
|
16
|
+
pop2=ConsChek.chek(population, a, b)
|
|
17
|
+
pop3=np.concatenate((pop3,pop2),axis=1);
|
|
18
|
+
pop3=DomChek.non_dominance(c, pop3)
|
|
19
|
+
np1_nouveau=n_population-len(pop3.T)
|
|
20
|
+
# Garde-fou : sans lui, un problème où il n'existe pas assez de solutions
|
|
21
|
+
# réalisables et deux à deux non dominées (peu d'objectifs, peu de variables,
|
|
22
|
+
# contraintes très serrées...) faisait tourner la boucle indéfiniment.
|
|
23
|
+
sans_progres = 0 if np1_nouveau < np1 else sans_progres + 1
|
|
24
|
+
if sans_progres > _ESSAIS_MAX:
|
|
25
|
+
raise RuntimeError(
|
|
26
|
+
"Impossible de construire une population de %d solutions réalisables "
|
|
27
|
+
"et non dominées entre elles (%d trouvées). Réduis la taille de la "
|
|
28
|
+
"population, ajoute des objectifs (lignes de c) ou relâche les "
|
|
29
|
+
"contraintes." % (n_population, n_population - np1_nouveau))
|
|
30
|
+
np1=np1_nouveau
|
|
31
|
+
|
|
32
|
+
return(pop3)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""DEGA-2 : algorithme génétique multi-objectifs à variables entières."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.1.0"
|
|
4
|
+
|
|
5
|
+
from .solver import Result, solve
|
|
6
|
+
from .entree import charger_probleme, ecrire_exemple
|
|
7
|
+
from .example import demo
|
|
8
|
+
|
|
9
|
+
__all__ = ["solve", "charger_probleme", "ecrire_exemple", "demo", "Result", "__version__"]
|