Skip to content

Commit

Permalink
move to new moptipy
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasWeise committed Dec 22, 2024
1 parent a35d60f commit b6907f6
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 118 deletions.
67 changes: 20 additions & 47 deletions moptipyapps/binpacking2d/packing_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
from pycommons.io.csv import (
SCOPE_SEPARATOR,
csv_column,
csv_read,
csv_scope,
csv_select_scope,
csv_write,
)
from pycommons.io.csv import CsvReader as CsvReaderBase
from pycommons.io.csv import CsvWriter as CsvWriterBase
from pycommons.io.path import Path, file_path, line_writer
from pycommons.strings.string_conv import (
num_to_str,
Expand Down Expand Up @@ -401,14 +401,7 @@ def to_csv(results: Iterable[PackingResult], file: str) -> Path:
path.ensure_parent_dir_exists()
with path.open_for_write() as wt:
consumer: Final[Callable[[str], None]] = line_writer(wt)
for p in csv_write(
data=sorted(results),
setup=CsvWriter().setup,
column_titles=CsvWriter.get_column_titles,
get_row=CsvWriter.get_row,
header_comments=CsvWriter.get_header_comments,
footer_comments=CsvWriter.get_footer_comments,
footer_bottom_comments=CsvWriter.get_footer_bottom_comments):
for p in CsvWriter.write(sorted(results)):
consumer(p)
logger(f"Done writing packing results to CSV file {path!r}.")
return path
Expand All @@ -424,58 +417,38 @@ def from_csv(file: str) -> Iterable[PackingResult]:
path: Final[Path] = file_path(file)
logger(f"Now reading CSV file {path!r}.")
with path.open_for_read() as rd:
yield from csv_read(
rows=rd, setup=CsvReader, parse_row=CsvReader.parse_row)
yield from CsvReader.read(rd)
logger(f"Done reading CSV file {path!r}.")


class CsvWriter:
class CsvWriter(CsvWriterBase[PackingResult]):
"""A class for CSV writing of :class:`PackingResult`."""

def __init__(self, scope: str | None = None) -> None:
def __init__(self, data: Iterable[PackingResult],
scope: str | None = None) -> None:
"""
Initialize the csv writer.
:param data: the data to write
:param scope: the prefix to be pre-pended to all columns
"""
#: an optional scope
self.scope: Final[str | None] = (
str.strip(scope)) if scope is not None else None

#: has this writer been set up?
self.__setup: bool = False
#: the end result writer
self.__er: Final[ErCsvWriter] = ErCsvWriter(scope)
#: the bin bounds
self.__bin_bounds: list[str] | None = None
#: the objectives
self.__objectives: list[str] | None = None

def setup(self, data: Iterable[PackingResult]) -> "CsvWriter":
"""
Set up this csv writer based on existing data.
:param data: the data to setup with
:returns: this writer
"""
if self.__setup:
raise ValueError("CSV writer has already been set up.")
self.__setup = True

data = reiterable(data)
self.__er.setup(pr.end_result for pr in data)
super().__init__(data, scope)
#: the end result writer
self.__er: Final[ErCsvWriter] = ErCsvWriter((
pr.end_result for pr in data), scope)

bin_bounds_set: Final[set[str]] = set()
objectives_set: Final[set[str]] = set()
for pr in data:
bin_bounds_set.update(pr.bin_bounds.keys())
objectives_set.update(pr.objectives.keys())
if set.__len__(bin_bounds_set) > 0:
self.__bin_bounds = sorted(bin_bounds_set)
if set.__len__(objectives_set) > 0:
self.__objectives = sorted(objectives_set)

return self
#: the bin bounds
self.__bin_bounds: Final[list[str] | None] = None \
if set.__len__(bin_bounds_set) <= 0 else sorted(bin_bounds_set)
#: the objectives
self.__objectives: Final[list[str] | None] = None \
if set.__len__(objectives_set) <= 0 else sorted(objectives_set)

def get_column_titles(self) -> Iterable[str]:
"""
Expand Down Expand Up @@ -571,7 +544,7 @@ def get_footer_bottom_comments(self) -> Iterable[str]:
yield from ErCsvWriter.get_footer_bottom_comments(self.__er)


class CsvReader:
class CsvReader(CsvReaderBase):
"""A class for CSV reading of :class:`PackingResult` instances."""

def __init__(self, columns: dict[str, int]) -> None:
Expand All @@ -580,7 +553,7 @@ def __init__(self, columns: dict[str, int]) -> None:
:param columns: the columns
"""
super().__init__()
super().__init__(columns)
#: the end result csv reader
self.__er: Final[ErCsvReader] = ErCsvReader(columns)
#: the index of the n-items column
Expand Down
106 changes: 46 additions & 60 deletions moptipyapps/binpacking2d/packing_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
from pycommons.io.csv import (
SCOPE_SEPARATOR,
csv_column,
csv_read,
csv_scope,
csv_select_scope,
csv_write,
)
from pycommons.io.csv import CsvReader as CsvReaderBase
from pycommons.io.csv import CsvWriter as CsvWriterBase
from pycommons.io.path import Path, file_path, line_writer
from pycommons.math.sample_statistics import CsvReader as SsCsvReader
from pycommons.math.sample_statistics import CsvWriter as SsCsvWriter
Expand Down Expand Up @@ -313,14 +313,7 @@ def to_csv(results: Iterable[PackingStatistics], file: str) -> Path:
path.ensure_parent_dir_exists()
with path.open_for_write() as wt:
consumer: Final[Callable[[str], None]] = line_writer(wt)
for p in csv_write(
data=sorted(results),
setup=CsvWriter().setup,
column_titles=CsvWriter.get_column_titles,
get_row=CsvWriter.get_row,
header_comments=CsvWriter.get_header_comments,
footer_comments=CsvWriter.get_footer_comments,
footer_bottom_comments=CsvWriter.get_footer_bottom_comments):
for p in CsvWriter.write(sorted(results)):
consumer(p)
logger(f"Done writing packing statistics to CSV file {path!r}.")
return path
Expand All @@ -336,75 +329,68 @@ def from_csv(file: str) -> Iterable[PackingStatistics]:
path: Final[Path] = file_path(file)
logger(f"Now reading CSV file {path!r}.")
with path.open_for_read() as rd:
yield from csv_read(rows=rd,
setup=CsvReader,
parse_row=CsvReader.parse_row)
yield from CsvReader.read(rd)
logger(f"Done reading CSV file {path!r}.")


class CsvWriter:
class CsvWriter(CsvWriterBase[PackingStatistics]):
"""A class for CSV writing of :class:`PackingStatistics`."""

def __init__(self, scope: str | None = None) -> None:
def __init__(self, data: Iterable[PackingStatistics],
scope: str | None = None) -> None:
"""
Initialize the csv writer.
:param data: the data to write
:param scope: the prefix to be pre-pended to all columns
"""
#: an optional scope
self.scope: Final[str | None] = (
str.strip(scope)) if scope is not None else None

#: has this writer been set up?
self.__setup: bool = False
#: the end statistics writer
self.__es: Final[EsCsvWriter] = EsCsvWriter(scope)
#: the bin bounds
self.__bin_bounds: list[str] | None = None
#: the objectives
self.__objectives: list[SsCsvWriter] | None = None
#: the objective names
self.__objective_names: tuple[str, ...] | None = None
#: the lower bound names
self.__objective_lb_names: tuple[str, ...] | None = None
#: the upper bound names
self.__objective_ub_names: tuple[str, ...] | None = None

def setup(self, data: Iterable[PackingStatistics]) -> "CsvWriter":
"""
Set up this csv writer based on existing data.
:param data: the data to setup with
:returns: this writer
"""
if self.__setup:
raise ValueError("CSV writer has already been set up.")
self.__setup = True

data = reiterable(data)
self.__es.setup(pr.end_statistics for pr in data)
super().__init__(data, scope)
#: the end statistics writer
self.__es: Final[EsCsvWriter] = EsCsvWriter((
pr.end_statistics for pr in data), scope)

bin_bounds_set: Final[set[str]] = set()
objectives_set: Final[set[str]] = set()
for pr in data:
bin_bounds_set.update(pr.bin_bounds.keys())
objectives_set.update(pr.objectives.keys())
if set.__len__(bin_bounds_set) > 0:
self.__bin_bounds = sorted(bin_bounds_set)

#: the bin bounds
self.__bin_bounds: list[str] | None = None \
if set.__len__(bin_bounds_set) <= 0 else sorted(bin_bounds_set)

#: the objectives
objectives: list[SsCsvWriter] | None = None
#: the objective names
objective_names: tuple[str, ...] | None = None
#: the lower bound names
objective_lb_names: tuple[str, ...] | None = None
#: the upper bound names
objective_ub_names: tuple[str, ...] | None = None
if set.__len__(objectives_set) > 0:
p: Final[str | None] = self.scope
self.__objective_names = tuple(sorted(objectives_set))
self.__objective_lb_names = tuple(csv_scope(
oxx, _OBJECTIVE_LOWER) for oxx in self.__objective_names)
self.__objective_ub_names = tuple(csv_scope(
oxx, _OBJECTIVE_UPPER) for oxx in self.__objective_names)
self.__objectives = [SsCsvWriter(
objective_names = tuple(sorted(objectives_set))
objective_lb_names = tuple(csv_scope(
oxx, _OBJECTIVE_LOWER) for oxx in objective_names)
objective_ub_names = tuple(csv_scope(
oxx, _OBJECTIVE_UPPER) for oxx in objective_names)
objectives = [SsCsvWriter(
data=(ddd.objectives[k] for ddd in data),
scope=csv_scope(p, k), n_not_needed=True, what_short=k,
what_long=f"objective function {k}").setup(
ddd.objectives[k] for ddd in data
) for k in self.__objective_names]
what_long=f"objective function {k}") for k in objective_names]

return self
#: the objectives
self.__objectives: Final[list[SsCsvWriter] | None] = objectives
#: the objective names
self.__objective_names: Final[tuple[str, ...] | None] \
= objective_names
#: the lower bound names
self.__objective_lb_names: Final[tuple[str, ...] | None] \
= objective_lb_names
#: the upper bound names
self.__objective_ub_names: Final[tuple[str, ...] | None] \
= objective_ub_names

def get_column_titles(self) -> Iterable[str]:
"""
Expand Down Expand Up @@ -502,7 +488,7 @@ def get_footer_bottom_comments(self) -> Iterable[str]:
yield from EsCsvWriter.get_footer_bottom_comments(self.__es)


class CsvReader:
class CsvReader(CsvReaderBase[PackingStatistics]):
"""A class for CSV parsing to get :class:`PackingStatistics`."""

def __init__(self, columns: dict[str, int]) -> None:
Expand All @@ -511,7 +497,7 @@ def __init__(self, columns: dict[str, int]) -> None:
:param columns: the columns
"""
super().__init__()
super().__init__(columns)
#: the end result csv reader
self.__es: Final[EsCsvReader] = EsCsvReader(columns)
#: the index of the n-items column
Expand Down
2 changes: 1 addition & 1 deletion moptipyapps/version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""An internal file with the version of the `moptipyapps` package."""
from typing import Final

__version__: Final[str] = "0.8.63"
__version__: Final[str] = "0.8.64"
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[build-system]
requires = ["setuptools>=75.5.0"]
requires = ["setuptools>=75.6.0"]
build-backend = "setuptools.build_meta"
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@
#

# pycommons provides lots of utilities
pycommons[dev] >= 0.8.58
pycommons[dev] >= 0.8.59
8 changes: 4 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@

# `moptipy` provides the basic optimization infrastructure and the spaces and
# tools that we use for optimization.
moptipy == 0.9.136
moptipy == 0.9.138

# the common tools package
pycommons == 0.8.58
pycommons == 0.8.59

# `numpy` is needed for its efficient data structures.
numpy == 1.26.4
Expand All @@ -34,7 +34,7 @@ numpy == 1.26.4
numba == 0.60.0

# matplotlib is used to create plots in the evaluation procedures.
matplotlib == 3.9.2
matplotlib == 3.10.0

# scipy is used, e.g., for integrating systems of differential equations.
scipy == 1.14.1
Expand All @@ -43,7 +43,7 @@ scipy == 1.14.1
# They are also used to check the URLs in the README.md as part of the build
# process, we check all the URLs in the README.md file..
urllib3 == 2.2.3
certifi == 2024.8.30
certifi == 2024.12.14

# defusedxml is used as safe alternative for XML parsing the TTP data
defusedxml == 0.7.1
8 changes: 4 additions & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ project_urls =
[options]
include_package_data = True
install_requires =
certifi >= 2024.8.30
certifi >= 2024.12.14
defusedxml >= 0.7.1
moptipy >= 0.9.136
moptipy >= 0.9.138
numpy < 2
numba >= 0.60.0
matplotlib >= 3.9.2
pycommons >= 0.8.58
matplotlib >= 3.10.0
pycommons >= 0.8.59
scipy >= 1.14.1
urllib3 >= 2.2.3
packages = find:
Expand Down

0 comments on commit b6907f6

Please sign in to comment.