Skip to content
This repository has been archived by the owner on May 10, 2023. It is now read-only.

Commit

Permalink
* Working on type hint improvements (2). #41
Browse files Browse the repository at this point in the history
  • Loading branch information
garciparedes committed Aug 31, 2019
1 parent 7f7ef87 commit cd334bc
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 39 deletions.
13 changes: 11 additions & 2 deletions jinete/algorithms/metaheuristics/grasp.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
if TYPE_CHECKING:
from typing import (
Type,
Optional,
)
from ...models import (
Result,
)

logger = logging.getLogger(__name__)
Expand All @@ -37,15 +41,20 @@ def __init__(self, episodes: int = 100, algorithm_cls: Type[Algorithm] = None, s
self.kwargs = kwargs

def build_algorithm(self, *args, **kwargs) -> Algorithm:
return self.algorithm_cls(*self.args, *args, **self.kwargs, **kwargs)
args = (*self.args, *args)
kwargs.update(self.kwargs)
return self.algorithm_cls(*args, **kwargs)

def _optimize(self) -> Planning:
logger.info('Optimizing...')

best = None
best: Optional[Result] = None
for i in range(self.episodes):
seed = self.random.randint(0, MAX_INT)
current = self.build_algorithm(seed=seed).optimize()
best = self.objective.best(best, current)

assert isinstance(best, Result)

logger.info('Optimized!')
return best.planning
14 changes: 13 additions & 1 deletion jinete/algorithms/naive.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from ..models import (
Planning,
)
from .abc import (
Algorithm,
)

if TYPE_CHECKING:
from typing import (
Set,
)
from ..models import (
Route
)


class NaiveAlgorithm(Algorithm):

def _optimize(self) -> Planning:
routes = set()
routes: Set[Route] = set()
return Planning(routes)
11 changes: 9 additions & 2 deletions jinete/algorithms/utils/crossers/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@


class Crosser(ABC):
fleet: Fleet
job: Job
criterion_cls: Type[PlannedTripCriterion]
_criterion: Optional[PlannedTripCriterion]

def __init__(self, fleet: Fleet, job: Job, criterion_cls: Type[PlannedTripCriterion] = None):
def __init__(self, fleet: Fleet, job: Job, criterion_cls: Type[PlannedTripCriterion] = None, *args, **kwargs):
if criterion_cls is None:
criterion_cls = ShortestTimePlannedTripCriterion

Expand All @@ -49,10 +53,13 @@ def __init__(self, fleet: Fleet, job: Job, criterion_cls: Type[PlannedTripCriter
self.criterion_cls = criterion_cls
self._criterion = None

self.args = args
self.kwargs = kwargs

@property
def criterion(self) -> PlannedTripCriterion:
if self._criterion is None:
self._criterion = self.criterion_cls()
self._criterion = self.criterion_cls(*self.args, **self.kwargs)
return self._criterion

@property
Expand Down
3 changes: 2 additions & 1 deletion jinete/algorithms/utils/crossers/randomized.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
if TYPE_CHECKING:
from typing import (
Optional,
List,
)
from ....models import (
PlannedTrip,
Expand All @@ -29,7 +30,7 @@ def get_planned_trip(self) -> Optional[PlannedTrip]:
if len(self.ranking) == 0:
return None

candidates = list()
candidates: List[PlannedTrip] = list()
for sub_ranking in self.ranking.values():
if len(sub_ranking) == 0:
continue
Expand Down
18 changes: 16 additions & 2 deletions jinete/loaders/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
)
from typing import (
TYPE_CHECKING,
)
Any)
from ..models import (
Fleet,
Job,
Expand All @@ -18,19 +18,33 @@
if TYPE_CHECKING:
from typing import (
Type,
Optional,
)
from .formatters import (
LoaderFormatter,
)


class Loader(ABC):
formatter_cls: Type[LoaderFormatter]
_formatter: Optional[LoaderFormatter]

def __init__(self, formatter_cls: Type[LoaderFormatter] = None):
if formatter_cls is None:
formatter_cls = CordeauLaporteLoaderFormatter
self.formatter_cls = formatter_cls
self.formatter: LoaderFormatter = None
self._formatter = None

@property
def formatter(self) -> LoaderFormatter:
if self._formatter is None:
self._formatter = self.formatter_cls(self.data)
return self._formatter

@property
@abstractmethod
def data(self) -> Any:
pass

@property
@abstractmethod
Expand Down
17 changes: 9 additions & 8 deletions jinete/loaders/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pathlib import (
Path,
)
from typing import TYPE_CHECKING

from ..models import (
Job,
Expand All @@ -14,10 +15,18 @@
Loader,
)

if TYPE_CHECKING:
from typing import (
Optional,
)

logger = logging.getLogger(__name__)


class FileLoader(Loader):
_fleet: Optional[Fleet]
_job: Optional[Job]
_surface: Optional[Surface]

def __init__(self, file_path: Path, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand All @@ -31,11 +40,6 @@ def __init__(self, file_path: Path, *args, **kwargs):
self._job = None
self._surface = None

def _build_formatter(self, force: bool = True):
if self.formatter is not None and force is False:
return
self.formatter = self.formatter_cls(self.data)

@property
def data(self):
with self.file_path.open() as file:
Expand All @@ -45,20 +49,17 @@ def data(self):
@property
def fleet(self) -> Fleet:
if self._fleet is None:
self._build_formatter()
self._fleet = self.formatter.fleet(surface=self.surface)
return self._fleet

@property
def job(self) -> Job:
if self._job is None:
self._build_formatter()
self._job = self.formatter.job(surface=self.surface)
return self._job

@property
def surface(self) -> Surface:
if self._surface is None:
self._build_formatter()
self._surface = self.formatter.surface()
return self._surface
4 changes: 2 additions & 2 deletions jinete/loaders/formatters/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ def __init__(self, data: Any):
self.data = data

@abstractmethod
def fleet(self, *args, **kwargs) -> Fleet:
def fleet(self, surface: Surface, *args, **kwargs) -> Fleet:
pass

@abstractmethod
def job(self, *args, **kwargs) -> Job:
def job(self, surface: Surface, *args, **kwargs) -> Job:
pass

@abstractmethod
Expand Down
6 changes: 4 additions & 2 deletions jinete/loaders/formatters/hashcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ def job(self, surface: Surface, *args, **kwargs) -> Job:
bonus = self.data[0][4]
rows = self.data[1:]
trips = set(self._build_trip(surface, str(i), bonus, *row) for i, row in enumerate(rows))
objective_cls = HashCodeObjective
job = Job(trips, objective_cls=objective_cls, *args, **kwargs)

kwargs['objective_cls'] = HashCodeObjective
job = Job(trips, *args, **kwargs)

logger.info(f'Created job!')
return job

Expand Down
2 changes: 1 addition & 1 deletion jinete/models/criterions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __init__(self, name: str, direction: OptimizationDirection):
def scoring(self, planned_trip: PlannedTrip) -> float:
pass

def best(self, *args: PlannedTrip) -> Optional[PlannedTrip]:
def best(self, *args: Optional[PlannedTrip]) -> Optional[PlannedTrip]:
return self.direction(
(arg for arg in args if arg is not None),
key=self.scoring,
Expand Down
22 changes: 16 additions & 6 deletions jinete/models/objectives.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from __future__ import annotations
from abc import ABC

from typing import (
TYPE_CHECKING,
TypeVar)
from .constants import (
OptimizationDirection,
)

from typing import (
Union,
)
from .routes import (
Route,
)
Expand All @@ -24,7 +24,13 @@
Stop,
)

Optimizable = Union[Result, Planning, Route, Stop, PlannedTrip]
if TYPE_CHECKING:
from typing import (
Union,
Optional
)

Optimizable = TypeVar('Optimizable', Result, Planning, Route, Stop, PlannedTrip)


class Objective(ABC):
Expand All @@ -34,8 +40,12 @@ def __init__(self, name: str, direction: OptimizationDirection):
self.name = name
self.direction = direction

def best(self, *args: Optimizable) -> Optimizable:
return self.direction((arg for arg in args if arg is not None), key=self.optimization_function)
def best(self, *args: Optional[Optimizable]) -> Optional[Optimizable]:
return self.direction(
(arg for arg in args if arg is not None),
key=self.optimization_function,
default=None,
)

def optimization_function(self, value: Optimizable) -> float:
if isinstance(value, Result):
Expand Down
4 changes: 2 additions & 2 deletions jinete/storers/formatters/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@


class StorerFormatter(ABC):
def __init__(self, result: Result, remove_empty_routs: bool = False):
def __init__(self, result: Result, remove_empty_routes: bool = False):
self.result = result
self.remove_empty_routes = remove_empty_routs
self.remove_empty_routes = remove_empty_routes

@property
def job(self) -> Job:
Expand Down
4 changes: 2 additions & 2 deletions jinete/storers/formatters/hashcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@


class HashCodeStorerFormatter(StorerFormatter):
def __init__(self, remove_empty_routs: bool = True, *args, **kwargs):
def __init__(self, remove_empty_routes: bool = True, *args, **kwargs):
kwargs['remove_empty_routes'] = remove_empty_routes
super().__init__(
remove_empty_routs=remove_empty_routs,
*args, **kwargs,
)

Expand Down
2 changes: 1 addition & 1 deletion jinete/storers/plots/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
class GraphPlotStorer(Storer):

def _generate_nodes(self, edges: Dict[Tuple[Position, Position], Dict[str, Any]]) -> Dict[Position, Dict[str, Any]]:
nodes = dict()
nodes: Dict[Position, Dict[str, Any]] = dict()
for trip in self.trips:
nodes[trip.origin] = dict()
nodes[trip.destination] = dict()
Expand Down
5 changes: 2 additions & 3 deletions tests/test_loaders/test_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ class TestFileLoader(unittest.TestCase):
def setUpClass(cls) -> None:
cls.directory_path = Path('/tmp/')
cls.file_path = cls.directory_path / 'jinete_problem_test.txt'
data = (
cls.data = (
(1.0, 1, 480, 6.0, 90.0),
(0.0, -1.044, 2.000, 0.0, 0.0, 0.0, 1440.0),
(1.0, -2.973, 6.414, 10.0, 1.0, 0.0, 1440.0),
(2.0, -5.476, 1.437, 10.0, -1.0, 258.0, 287.0),
)
with cls.file_path.open('w') as file:
file.writelines('\t'.join(map(str, row)) + '\n' for row in data)
cls.data = data
file.writelines('\t'.join(str(cell) for cell in row) + '\n' for row in cls.data)

@classmethod
def tearDownClass(cls) -> None:
Expand Down
8 changes: 4 additions & 4 deletions tests/test_models/test_vehicles.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def test_vehicle(self):
self.assertEqual(vehicle.final, vehicle.initial)
self.assertEqual(vehicle.earliest, 0)
self.assertEqual(vehicle.latest, jit.MAX_FLOAT)
self.assertIsNone(vehicle.timeout)
self.assertEqual(vehicle.timeout, jit.MAX_FLOAT)
self.assertIsInstance(vehicle.uuid, UUID)

def test_vehicle_with_capacity(self):
Expand All @@ -35,7 +35,7 @@ def test_vehicle_with_capacity(self):
self.assertEqual(vehicle.final, vehicle.initial)
self.assertEqual(vehicle.earliest, 0)
self.assertEqual(vehicle.latest, jit.MAX_FLOAT)
self.assertIsNone(vehicle.timeout)
self.assertEqual(vehicle.timeout, jit.MAX_FLOAT)
self.assertIsInstance(vehicle.uuid, UUID)

def test_vehicle_with_final(self):
Expand All @@ -51,7 +51,7 @@ def test_vehicle_with_final(self):
self.assertEqual(vehicle.final, final)
self.assertEqual(vehicle.earliest, 0)
self.assertEqual(vehicle.latest, jit.MAX_FLOAT)
self.assertIsNone(vehicle.timeout)
self.assertEqual(vehicle.timeout, jit.MAX_FLOAT)
self.assertIsInstance(vehicle.uuid, UUID)

def test_vehicle_with_earliest(self):
Expand All @@ -66,7 +66,7 @@ def test_vehicle_with_earliest(self):
self.assertEqual(vehicle.final, vehicle.initial)
self.assertEqual(vehicle.earliest, earliest)
self.assertEqual(vehicle.latest, jit.MAX_FLOAT)
self.assertIsNone(vehicle.timeout)
self.assertEqual(vehicle.timeout, jit.MAX_FLOAT)
self.assertIsInstance(vehicle.uuid, UUID)

def test_vehicle_with_timeout(self):
Expand Down

0 comments on commit cd334bc

Please sign in to comment.