pykp 0.0.22__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.
- pykp-0.0.22/PKG-INFO +108 -0
- pykp-0.0.22/README.md +87 -0
- pykp-0.0.22/pykp/__init__.py +4 -0
- pykp-0.0.22/pykp/arrangement.py +63 -0
- pykp-0.0.22/pykp/item.py +40 -0
- pykp-0.0.22/pykp/knapsack.py +742 -0
- pykp-0.0.22/pykp/sampler.py +81 -0
- pykp-0.0.22/pykp.egg-info/PKG-INFO +108 -0
- pykp-0.0.22/pykp.egg-info/SOURCES.txt +14 -0
- pykp-0.0.22/pykp.egg-info/dependency_links.txt +1 -0
- pykp-0.0.22/pykp.egg-info/requires.txt +8 -0
- pykp-0.0.22/pykp.egg-info/top_level.txt +1 -0
- pykp-0.0.22/setup.cfg +4 -0
- pykp-0.0.22/setup.py +32 -0
- pykp-0.0.22/tests/test_knapsack.py +92 -0
- pykp-0.0.22/tests/test_sampler.py +55 -0
pykp-0.0.22/PKG-INFO
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pykp
|
|
3
|
+
Version: 0.0.22
|
|
4
|
+
Summary: Tooling for sampling and solving instances of the 0-1 Knapsack Problem
|
|
5
|
+
Home-page: https://github.com/HRSAndrabi/pykp
|
|
6
|
+
Author: Hassan Andrabi
|
|
7
|
+
Author-email: hrs.andrabi@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.12
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: anytree>=2.12.1
|
|
15
|
+
Requires-Dist: pandas>=2.2.3
|
|
16
|
+
Requires-Dist: matplotlib==3.9.2
|
|
17
|
+
Requires-Dist: numpy==2.1.3
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
20
|
+
Requires-Dist: twine>=4.0.2; extra == "dev"
|
|
21
|
+
|
|
22
|
+
# PyKP: A Python Package for Knapsack Problem Solving
|
|
23
|
+
|
|
24
|
+
PyKP is a free and open-source library for sampling and solving instances of the knapsack problem. It provides tools to define knapsack instances, solve them efficiently, and analyse computational complexity metrics. You can also use `pykp` to sample knapsack problem instances based on specified distributions.
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- Define knapsack problem instances with custom items, weights, and values.
|
|
29
|
+
- Solve knapsack instances using branch-and-bound and other methods.
|
|
30
|
+
- Compute optimal and feasible solutions for different knapsack configurations.
|
|
31
|
+
- Analyse computational complexity metrics.
|
|
32
|
+
- Generate synthetic knapsack instances with custom weight, density, and solution value ranges.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
PyKP support Python version 3.12 and higher. To install PyKP, run
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
pip install pykp
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### Defining and Solving a Knapsack Problem
|
|
45
|
+
|
|
46
|
+
To start, define a knapsack problem with a set of items and solve it using the Knapsack class.
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import numpy as np
|
|
50
|
+
from pykp import Knapsack
|
|
51
|
+
from pykp import Item
|
|
52
|
+
|
|
53
|
+
# Define items for the knapsack
|
|
54
|
+
items = np.array([
|
|
55
|
+
Item(value=10, weight=5),
|
|
56
|
+
Item(value=15, weight=10),
|
|
57
|
+
Item(value=7, weight=3)
|
|
58
|
+
])
|
|
59
|
+
|
|
60
|
+
# Initialise a Knapsack instance
|
|
61
|
+
capacity = 15
|
|
62
|
+
knapsack = Knapsack(items=items, capacity=capacity)
|
|
63
|
+
knapsack.solve()
|
|
64
|
+
|
|
65
|
+
# Display the optimal solution
|
|
66
|
+
print("Optimal Solution Value:", knapsack.optimal_nodes[0].value)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Generating Knapsack Instances with Sampler
|
|
70
|
+
|
|
71
|
+
The `Sampler` class allows you to generate knapsack instances based on specific ranges for item densities (value/weight ratio) and optimal solution values.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from pykp import Sampler
|
|
75
|
+
|
|
76
|
+
# Initialise a Sampler instance with desired ranges
|
|
77
|
+
sampler = Sampler(
|
|
78
|
+
num_items=5,
|
|
79
|
+
normalised_capacity=0.6,
|
|
80
|
+
density_range=(0.5, 1.5),
|
|
81
|
+
solution_value_range=(100, 200)
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Generate a sampled knapsack instance
|
|
85
|
+
sampled_knapsack = sampler.sample()
|
|
86
|
+
print("Sampled Knapsack Capacity:", sampled_knapsack.capacity)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Analysing Knapsack Solutions
|
|
90
|
+
|
|
91
|
+
The package provides methods to analyse the optimal solutions and other feasible arrangements.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# Display a summary of the knapsack solutions
|
|
95
|
+
print(sampled_knapsack.summary())
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
This project is licensed under the MIT License.
|
|
101
|
+
|
|
102
|
+
## Contributing
|
|
103
|
+
|
|
104
|
+
Contributions are welcome. Please fork the repository and submit a pull request.
|
|
105
|
+
|
|
106
|
+
## Contact
|
|
107
|
+
|
|
108
|
+
For questions or feedback, please reach out at hrs.andrabi@gmail.com.
|
pykp-0.0.22/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# PyKP: A Python Package for Knapsack Problem Solving
|
|
2
|
+
|
|
3
|
+
PyKP is a free and open-source library for sampling and solving instances of the knapsack problem. It provides tools to define knapsack instances, solve them efficiently, and analyse computational complexity metrics. You can also use `pykp` to sample knapsack problem instances based on specified distributions.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Define knapsack problem instances with custom items, weights, and values.
|
|
8
|
+
- Solve knapsack instances using branch-and-bound and other methods.
|
|
9
|
+
- Compute optimal and feasible solutions for different knapsack configurations.
|
|
10
|
+
- Analyse computational complexity metrics.
|
|
11
|
+
- Generate synthetic knapsack instances with custom weight, density, and solution value ranges.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
PyKP support Python version 3.12 and higher. To install PyKP, run
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
pip install pykp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Defining and Solving a Knapsack Problem
|
|
24
|
+
|
|
25
|
+
To start, define a knapsack problem with a set of items and solve it using the Knapsack class.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import numpy as np
|
|
29
|
+
from pykp import Knapsack
|
|
30
|
+
from pykp import Item
|
|
31
|
+
|
|
32
|
+
# Define items for the knapsack
|
|
33
|
+
items = np.array([
|
|
34
|
+
Item(value=10, weight=5),
|
|
35
|
+
Item(value=15, weight=10),
|
|
36
|
+
Item(value=7, weight=3)
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
# Initialise a Knapsack instance
|
|
40
|
+
capacity = 15
|
|
41
|
+
knapsack = Knapsack(items=items, capacity=capacity)
|
|
42
|
+
knapsack.solve()
|
|
43
|
+
|
|
44
|
+
# Display the optimal solution
|
|
45
|
+
print("Optimal Solution Value:", knapsack.optimal_nodes[0].value)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Generating Knapsack Instances with Sampler
|
|
49
|
+
|
|
50
|
+
The `Sampler` class allows you to generate knapsack instances based on specific ranges for item densities (value/weight ratio) and optimal solution values.
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from pykp import Sampler
|
|
54
|
+
|
|
55
|
+
# Initialise a Sampler instance with desired ranges
|
|
56
|
+
sampler = Sampler(
|
|
57
|
+
num_items=5,
|
|
58
|
+
normalised_capacity=0.6,
|
|
59
|
+
density_range=(0.5, 1.5),
|
|
60
|
+
solution_value_range=(100, 200)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Generate a sampled knapsack instance
|
|
64
|
+
sampled_knapsack = sampler.sample()
|
|
65
|
+
print("Sampled Knapsack Capacity:", sampled_knapsack.capacity)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Analysing Knapsack Solutions
|
|
69
|
+
|
|
70
|
+
The package provides methods to analyse the optimal solutions and other feasible arrangements.
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
# Display a summary of the knapsack solutions
|
|
74
|
+
print(sampled_knapsack.summary())
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
This project is licensed under the MIT License.
|
|
80
|
+
|
|
81
|
+
## Contributing
|
|
82
|
+
|
|
83
|
+
Contributions are welcome. Please fork the repository and submit a pull request.
|
|
84
|
+
|
|
85
|
+
## Contact
|
|
86
|
+
|
|
87
|
+
For questions or feedback, please reach out at hrs.andrabi@gmail.com.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from .item import Item
|
|
3
|
+
|
|
4
|
+
class Arrangement():
|
|
5
|
+
"""
|
|
6
|
+
Represents an arrangement of items for the knapsack problem.
|
|
7
|
+
|
|
8
|
+
Attributes:
|
|
9
|
+
* items (np.ndarray[Item]): An array of items for the knapsack problem.
|
|
10
|
+
* state (np.ndarray[int]): Binary array indicating the inclusion/exclusion of items in the arrangement.
|
|
11
|
+
* value (int): The total value of items in the arrangement.
|
|
12
|
+
* weight (int): The total weight of items in the arrangement.
|
|
13
|
+
"""
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
items: np.ndarray[Item],
|
|
17
|
+
state: np.ndarray[int],
|
|
18
|
+
):
|
|
19
|
+
"""Initialises an Arrangement instance.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
items (np.ndarray[Item]): An array of items for the knapsack problem.
|
|
23
|
+
state (np.ndarray[int]): Binary array indicating the inclusion/exclusion of items in the arrangement.
|
|
24
|
+
capacity (int): The maximum weight capacity constraint for the arrangement.
|
|
25
|
+
"""
|
|
26
|
+
if not np.all(np.isin(state, [0, 1])):
|
|
27
|
+
raise ValueError("Elements of `state` must be 0 or 1.")
|
|
28
|
+
|
|
29
|
+
self.items = items
|
|
30
|
+
self.state = state
|
|
31
|
+
self.value = self.__calculate_value()
|
|
32
|
+
self.weight = self.__calculate_weight()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def __calculate_value(self):
|
|
36
|
+
"""
|
|
37
|
+
Calculates the total value of items currently in the knapsack.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
float: The total value of items in the knapsack.
|
|
41
|
+
"""
|
|
42
|
+
return sum([self.items[i].value for i, inside in enumerate(self.state) if bool(inside)])
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def __calculate_weight(self):
|
|
46
|
+
"""
|
|
47
|
+
Calculates the total weight of items currently in the knapsack.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
float: The total weight of items in the knapsack.
|
|
51
|
+
"""
|
|
52
|
+
return sum([self.items[i].weight for i, inside in enumerate(self.state) if bool(inside)])
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def __str__(self):
|
|
56
|
+
state = int("".join(self.state.astype(int).astype(str)), 2)
|
|
57
|
+
return f"(v: {self.value}, w: {self.weight}, s: {state})"
|
|
58
|
+
|
|
59
|
+
def __repr__(self):
|
|
60
|
+
state = int("".join(self.state.astype(int).astype(str)), 2)
|
|
61
|
+
return f"(v: {self.value}, w: {self.weight}, s: {state})"
|
|
62
|
+
|
|
63
|
+
|
pykp-0.0.22/pykp/item.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
class Item:
|
|
2
|
+
"""
|
|
3
|
+
Represents an item for the knapsack problem.
|
|
4
|
+
|
|
5
|
+
Attributes:
|
|
6
|
+
value (int): The value of the item.
|
|
7
|
+
weight (int): The weight of the item.
|
|
8
|
+
"""
|
|
9
|
+
def __init__(self, value: int, weight: int):
|
|
10
|
+
"""
|
|
11
|
+
Initialises an Item instance.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
value (int): The value of the item.
|
|
15
|
+
weight (int): The weight of the item.
|
|
16
|
+
"""
|
|
17
|
+
self.weight = weight
|
|
18
|
+
self.value = value
|
|
19
|
+
|
|
20
|
+
def update_value(self, new_value: int):
|
|
21
|
+
"""Updates the value of the item.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
new_value (int): New value of the item.
|
|
25
|
+
"""
|
|
26
|
+
self.value = new_value
|
|
27
|
+
|
|
28
|
+
def update_weight(self, new_weight: int):
|
|
29
|
+
"""Updates the weight of the item.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
new_weight (int): New weight of the item.
|
|
33
|
+
"""
|
|
34
|
+
self.weight = new_weight
|
|
35
|
+
|
|
36
|
+
def __str__(self):
|
|
37
|
+
return f"weight: {self.weight}; value: {self.value}"
|
|
38
|
+
|
|
39
|
+
def __repr__(self):
|
|
40
|
+
return str(self)
|