pyoframe 0.0.8__tar.gz → 0.0.9__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 (28) hide show
  1. {pyoframe-0.0.8/src/pyoframe.egg-info → pyoframe-0.0.9}/PKG-INFO +1 -2
  2. {pyoframe-0.0.8 → pyoframe-0.0.9}/pyproject.toml +2 -2
  3. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/core.py +25 -26
  4. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/io.py +76 -9
  5. {pyoframe-0.0.8 → pyoframe-0.0.9/src/pyoframe.egg-info}/PKG-INFO +1 -2
  6. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe.egg-info/requires.txt +0 -1
  7. {pyoframe-0.0.8 → pyoframe-0.0.9}/LICENSE +0 -0
  8. {pyoframe-0.0.8 → pyoframe-0.0.9}/README.md +0 -0
  9. {pyoframe-0.0.8 → pyoframe-0.0.9}/setup.cfg +0 -0
  10. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/__init__.py +0 -0
  11. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/_arithmetic.py +0 -0
  12. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/constants.py +0 -0
  13. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/io_mappers.py +0 -0
  14. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/model.py +0 -0
  15. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/model_element.py +0 -0
  16. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/monkey_patch.py +0 -0
  17. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/objective.py +0 -0
  18. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/solvers.py +0 -0
  19. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/user_defined.py +0 -0
  20. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe/util.py +0 -0
  21. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe.egg-info/SOURCES.txt +0 -0
  22. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe.egg-info/dependency_links.txt +0 -0
  23. {pyoframe-0.0.8 → pyoframe-0.0.9}/src/pyoframe.egg-info/top_level.txt +0 -0
  24. {pyoframe-0.0.8 → pyoframe-0.0.9}/tests/test_arithmetic.py +0 -0
  25. {pyoframe-0.0.8 → pyoframe-0.0.9}/tests/test_examples.py +0 -0
  26. {pyoframe-0.0.8 → pyoframe-0.0.9}/tests/test_io.py +0 -0
  27. {pyoframe-0.0.8 → pyoframe-0.0.9}/tests/test_operations.py +0 -0
  28. {pyoframe-0.0.8 → pyoframe-0.0.9}/tests/test_solver.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyoframe
3
- Version: 0.0.8
3
+ Version: 0.0.9
4
4
  Summary: Blazing fast linear program interface
5
5
  Author-email: Bravos Power <dev@bravospower.com>
6
6
  Project-URL: Homepage, https://bravos-power.github.io/pyoframe/
@@ -19,7 +19,6 @@ Requires-Dist: polars==0.20.27
19
19
  Requires-Dist: numpy
20
20
  Requires-Dist: pyarrow
21
21
  Requires-Dist: pandas
22
- Requires-Dist: tqdm
23
22
  Provides-Extra: dev
24
23
  Requires-Dist: black; extra == "dev"
25
24
  Requires-Dist: bumpver; extra == "dev"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyoframe"
7
- version = "0.0.8"
7
+ version = "0.0.9"
8
8
  authors = [{ name = "Bravos Power", email = "dev@bravospower.com" }]
9
9
  description = "Blazing fast linear program interface"
10
10
  readme = "README.md"
@@ -16,7 +16,7 @@ classifiers = [
16
16
  "License :: OSI Approved :: MIT License",
17
17
  "Natural Language :: English",
18
18
  ]
19
- dependencies = ["polars==0.20.27", "numpy", "pyarrow", "pandas", "tqdm"]
19
+ dependencies = ["polars==0.20.27", "numpy", "pyarrow", "pandas"]
20
20
 
21
21
  [project.optional-dependencies]
22
22
  dev = [
@@ -1,16 +1,17 @@
1
1
  from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
2
4
  from typing import (
5
+ TYPE_CHECKING,
3
6
  Iterable,
4
7
  List,
5
8
  Mapping,
9
+ Optional,
6
10
  Protocol,
7
11
  Sequence,
8
- overload,
9
12
  Union,
10
- Optional,
11
- TYPE_CHECKING,
13
+ overload,
12
14
  )
13
- from abc import ABC, abstractmethod
14
15
 
15
16
  import pandas as pd
16
17
  import polars as pl
@@ -21,33 +22,32 @@ from pyoframe.constants import (
21
22
  CONST_TERM,
22
23
  CONSTRAINT_KEY,
23
24
  DUAL_KEY,
25
+ RC_COL,
24
26
  RESERVED_COL_KEYS,
25
27
  SLACK_COL,
26
- VAR_KEY,
27
28
  SOLUTION_KEY,
28
- RC_COL,
29
- VType,
30
- VTypeValue,
29
+ VAR_KEY,
31
30
  Config,
32
31
  ConstraintSense,
33
- UnmatchedStrategy,
34
- PyoframeError,
35
32
  ObjSense,
33
+ PyoframeError,
34
+ UnmatchedStrategy,
35
+ VType,
36
+ VTypeValue,
37
+ )
38
+ from pyoframe.model_element import (
39
+ ModelElement,
40
+ ModelElementWithId,
41
+ SupportPolarsMethodMixin,
36
42
  )
37
43
  from pyoframe.util import (
44
+ FuncArgs,
38
45
  cast_coef_to_string,
39
46
  concat_dimensions,
47
+ dataframe_to_tupled_list,
40
48
  get_obj_repr,
41
49
  parse_inputs_as_iterable,
42
50
  unwrap_single_values,
43
- dataframe_to_tupled_list,
44
- FuncArgs,
45
- )
46
-
47
- from pyoframe.model_element import (
48
- ModelElement,
49
- ModelElementWithId,
50
- SupportPolarsMethodMixin,
51
51
  )
52
52
 
53
53
  if TYPE_CHECKING: # pragma: no cover
@@ -692,7 +692,9 @@ class Expression(ModelElement, SupportsMath, SupportPolarsMethodMixin):
692
692
  >>> m.expr_1 = 2 * m.X + 1
693
693
  >>> m.expr_2 = pf.sum(m.expr_1)
694
694
  >>> m.objective = m.expr_2 - 3
695
- >>> result = m.solve(log_to_console=False)
695
+ >>> result = m.solve(log_to_console=False) # doctest: +ELLIPSIS
696
+ <BLANKLINE>
697
+ ...
696
698
  >>> m.expr_1.value
697
699
  shape: (3, 2)
698
700
  ┌──────┬──────────┐
@@ -1003,13 +1005,9 @@ class Constraint(ModelElementWithId):
1003
1005
  >>> m.hours_spent = pf.Variable(homework_due_tomorrow[["project"]], lb=0)
1004
1006
  >>> m.must_finish_project = m.hours_spent >= homework_due_tomorrow[["project", "hours_to_finish"]]
1005
1007
  >>> m.only_one_day = sum("project", m.hours_spent) <= 24
1006
- >>> m.solve(log_to_console=False)
1007
- Status: warning
1008
- Termination condition: infeasible
1009
- <BLANKLINE>
1010
-
1011
1008
  >>> _ = m.must_finish_project.relax(homework_due_tomorrow[["project", "cost_per_hour_underdelivered"]], max=homework_due_tomorrow[["project", "max_underdelivered"]])
1012
- >>> result = m.solve(log_to_console=False)
1009
+ >>> _ = m.solve(log_to_console=False) # doctest: +ELLIPSIS
1010
+ \rWriting ...
1013
1011
  >>> m.hours_spent.solution
1014
1012
  shape: (3, 2)
1015
1013
  ┌─────────┬──────────┐
@@ -1029,7 +1027,8 @@ class Constraint(ModelElementWithId):
1029
1027
  >>> m.hours_spent = pf.Variable(homework_due_tomorrow[["project"]], lb=0)
1030
1028
  >>> m.must_finish_project = (m.hours_spent >= homework_due_tomorrow[["project", "hours_to_finish"]]).relax(5)
1031
1029
  >>> m.only_one_day = (sum("project", m.hours_spent) <= 24).relax(1)
1032
- >>> _ = m.solve(log_to_console=False)
1030
+ >>> _ = m.solve(log_to_console=False) # doctest: +ELLIPSIS
1031
+ \rWriting ...
1033
1032
  >>> m.objective.value
1034
1033
  -3.0
1035
1034
  >>> m.hours_spent.solution
@@ -2,11 +2,12 @@
2
2
  Module containing all import/export functionalities.
3
3
  """
4
4
 
5
+ import sys
6
+ import time
5
7
  from io import TextIOWrapper
6
- from tempfile import NamedTemporaryFile
7
8
  from pathlib import Path
9
+ from tempfile import NamedTemporaryFile
8
10
  from typing import TYPE_CHECKING, Iterable, Optional, TypeVar, Union
9
- from tqdm import tqdm
10
11
 
11
12
  from pyoframe.constants import CONST_TERM, VAR_KEY, ObjSense
12
13
  from pyoframe.core import Constraint, Variable
@@ -24,6 +25,57 @@ if TYPE_CHECKING: # pragma: no cover
24
25
 
25
26
  import polars as pl
26
27
 
28
+ T = TypeVar("T")
29
+
30
+
31
+ def io_progress_bar(
32
+ iterable: Iterable[T],
33
+ prefix: str = "",
34
+ suffix: str = "",
35
+ length: int = 50,
36
+ fill: str = "█",
37
+ update_every: int = 1,
38
+ ):
39
+ """
40
+ Display progress bar for I/O operations.
41
+ """
42
+ try:
43
+ total = len(iterable)
44
+ except TypeError:
45
+ total = None
46
+
47
+ start_time = time.time()
48
+
49
+ def print_progress(iteration: int):
50
+ if total is not None:
51
+ percent = f"{100 * (iteration / float(total)):.1f}"
52
+ filled_length = int(length * iteration // total)
53
+ bar = fill * filled_length + "-" * (length - filled_length)
54
+ else:
55
+ percent = "N/A"
56
+ bar = fill * (iteration % length) + "-" * (length - (iteration % length))
57
+ elapsed_time = time.time() - start_time
58
+ if iteration > 0:
59
+ estimated_total_time = (
60
+ elapsed_time * (total / iteration) if total else elapsed_time
61
+ )
62
+ estimated_remaining_time = estimated_total_time - elapsed_time
63
+ eta = time.strftime("%H:%M:%S", time.gmtime(estimated_remaining_time))
64
+ else:
65
+ eta = "Estimating..." # pragma: no cover
66
+ sys.stdout.write(
67
+ f'\r{prefix} |{bar}| {percent}% Complete ({iteration}/{total if total else "?"}) ETA: {eta} {suffix}'
68
+ )
69
+ sys.stdout.flush()
70
+
71
+ for i, item in enumerate(iterable):
72
+ yield item
73
+ if (i + 1) % update_every == 0 or total is None or i == total - 1:
74
+ print_progress(i + 1)
75
+
76
+ sys.stdout.write("\n")
77
+ sys.stdout.flush()
78
+
27
79
 
28
80
  def objective_to_file(m: "Model", f: TextIOWrapper, var_map):
29
81
  """
@@ -41,7 +93,11 @@ def objective_to_file(m: "Model", f: TextIOWrapper, var_map):
41
93
 
42
94
  def constraints_to_file(m: "Model", f: TextIOWrapper, var_map, const_map):
43
95
  for constraint in create_section(
44
- tqdm(m.constraints, desc="Writing constraints to file"), f, "s.t."
96
+ io_progress_bar(
97
+ m.constraints, prefix="Writing constraints to file", update_every=5
98
+ ),
99
+ f,
100
+ "s.t.",
45
101
  ):
46
102
  f.write(constraint.to_str(var_map=var_map, const_map=const_map) + "\n")
47
103
 
@@ -58,7 +114,9 @@ def bounds_to_file(m: "Model", f, var_map):
58
114
  )
59
115
  f.write(f"{var_map.apply(const_term_df).item()} = 1\n")
60
116
 
61
- for variable in tqdm(m.variables, desc="Writing bounds to file"):
117
+ for variable in io_progress_bar(
118
+ m.variables, prefix="Writing bounds to file", update_every=1
119
+ ):
62
120
  terms = []
63
121
 
64
122
  if variable.lb != 0:
@@ -88,7 +146,13 @@ def binaries_to_file(m: "Model", f, var_map: Mapper):
88
146
  Write out binaries of a model to a lp file.
89
147
  """
90
148
  for variable in create_section(
91
- tqdm(m.binary_variables, "Writing binary variables to file"), f, "binary"
149
+ io_progress_bar(
150
+ m.binary_variables,
151
+ prefix="Writing binary variables to file",
152
+ update_every=1,
153
+ ),
154
+ f,
155
+ "binary",
92
156
  ):
93
157
  lines = (
94
158
  var_map.apply(variable.data, to_col=None)
@@ -103,7 +167,13 @@ def integers_to_file(m: "Model", f, var_map: Mapper):
103
167
  Write out integers of a model to a lp file.
104
168
  """
105
169
  for variable in create_section(
106
- tqdm(m.integer_variables, "Writing integer variables to file"), f, "general"
170
+ io_progress_bar(
171
+ m.integer_variables,
172
+ prefix="Writing integer variables to file",
173
+ update_every=5,
174
+ ),
175
+ f,
176
+ "general",
107
177
  ):
108
178
  lines = (
109
179
  var_map.apply(variable.data, to_col=None)
@@ -113,9 +183,6 @@ def integers_to_file(m: "Model", f, var_map: Mapper):
113
183
  f.write(lines + "\n")
114
184
 
115
185
 
116
- T = TypeVar("T")
117
-
118
-
119
186
  def create_section(iterable: Iterable[T], f, section_header) -> Iterable[T]:
120
187
  wrote = False
121
188
  for item in iterable:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyoframe
3
- Version: 0.0.8
3
+ Version: 0.0.9
4
4
  Summary: Blazing fast linear program interface
5
5
  Author-email: Bravos Power <dev@bravospower.com>
6
6
  Project-URL: Homepage, https://bravos-power.github.io/pyoframe/
@@ -19,7 +19,6 @@ Requires-Dist: polars==0.20.27
19
19
  Requires-Dist: numpy
20
20
  Requires-Dist: pyarrow
21
21
  Requires-Dist: pandas
22
- Requires-Dist: tqdm
23
22
  Provides-Extra: dev
24
23
  Requires-Dist: black; extra == "dev"
25
24
  Requires-Dist: bumpver; extra == "dev"
@@ -2,7 +2,6 @@ polars==0.20.27
2
2
  numpy
3
3
  pyarrow
4
4
  pandas
5
- tqdm
6
5
 
7
6
  [dev]
8
7
  black
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes