Skip to content

Commit

Permalink
connect 'pysatmc' subcomponent to other evoguess modules, update requ…
Browse files Browse the repository at this point in the history
…irements
  • Loading branch information
alpavlenko committed Sep 14, 2023
1 parent 8a15f72 commit bde91b6
Show file tree
Hide file tree
Showing 42 changed files with 543 additions and 436 deletions.
16 changes: 6 additions & 10 deletions core/abc/core.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
from typing import Any, Dict
from typing import Any, Dict, Optional
from numpy.random import randint, RandomState

from output import Logger
from instance import Instance
from pysatmc.problem import Problem

from ..static import DEBUGGER

from typings.optional import Int
from numpy.random import randint, RandomState


class Core:
slug = None

def __init__(self,
logger: Logger,
instance: Instance,
random_seed: Int = None):
def __init__(self, logger: Logger, problem: Problem,
random_seed: Optional[int] = None):
self.logger = logger
self.instance = instance
self.problem = problem

DEBUGGER.initialize(logger)
self.random_seed = random_seed or randint(2 ** 32 - 1)
Expand Down
25 changes: 11 additions & 14 deletions core/abc/estimate.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from typing import Any
from typing import Any, Optional, Dict

from space import Space
from output import Logger
from executor import Executor
from function import Function
from instance import Instance

from ..abc.core import *
from ..model.job import Job
Expand All @@ -16,28 +15,22 @@
from ..module.sampling import Sampling
from ..module.comparator import Comparator

from typings.optional import Int
from pysatmc.problem import Problem
from typings.searchable import Searchable


class Estimate(Core):
slug = 'core:estimate'

def __init__(self,
space: Space,
logger: Logger,
instance: Instance,
executor: Executor,
sampling: Sampling,
function: Function,
comparator: Comparator,
random_seed: Int = None):
def __init__(self, space: Space, logger: Logger, problem: Problem,
executor: Executor, sampling: Sampling, function: Function,
comparator: Comparator, random_seed: Optional[int] = None):
self.space = space
self.executor = executor
self.sampling = sampling
self.function = function
self.comparator = comparator
super().__init__(logger, instance, random_seed)
super().__init__(logger, problem, random_seed)

self._job_number = 0
CORE_CACHE.canceled = {}
Expand Down Expand Up @@ -68,7 +61,7 @@ def _estimate(self, point: Point) -> Handle:
self._job_number += 1
handle = JobHandle(Job(Context(
space=self.space,
instance=self.instance,
problem=self.problem,
function=self.function,
sampling=self.sampling,
executor=self.executor,
Expand All @@ -80,6 +73,10 @@ def _estimate(self, point: Point) -> Handle:

return handle

def __config__(self) -> Dict[str, Any]:
# todo: add realisation
return {}


__all__ = [
'Estimate'
Expand Down
64 changes: 31 additions & 33 deletions core/impl/combine.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
from math import ceil
from time import time as now
from typing import List, Dict, Any
from typing import Any, List, Dict, Optional
from itertools import chain, product
from util.iterable import concat, slice_by

from output import Logger
from executor import Executor
from instance import Instance

from ..abc import Core

from function.module.measure import Measure
from function.model import Status, Estimation
from function.impl.function_gad import sequence_mapper
from function.module.solver import Solver, Report, IncrSolver

from typings.optional import Int
from typings.searchable import Searchable, Assumptions
from pysatmc.problem import Problem
from pysatmc.variables import Assumptions
from pysatmc.solver import Solver, _Solver, Report

from typings.searchable import Searchable
from util.iterable import concat, slice_by


def get_propagation(solver: IncrSolver, searchable: Searchable) -> Report:
dimension = searchable.dimension()
def get_propagation(solver: _Solver, searchable: Searchable) -> Report:
time_sum, value_sum, up_tasks, hard_tasks = 0, 0, [], []
for substitution in map(sequence_mapper(dimension), range(searchable.power())):
assumptions, _ = searchable.substitute(with_substitution=substitution)
time, value, status, _ = solver.propagate(assumptions, add_model=False)
(up_tasks if status == Status.RESOLVED else hard_tasks).append(assumptions)
for supplements in searchable.enumerate():
time, value, status, _ = solver.propagate(supplements)
assumptions, _ = supplements
(up_tasks if status == Status.RESOLVED else hard_tasks).append(
assumptions)
time_sum, value_sum = time_sum + time, value_sum + value

status = Status.SOLVED if len(hard_tasks) else Status.RESOLVED
return Report(time_sum, value_sum, status, (up_tasks, hard_tasks))


def hard_worker(solver: Solver, measure: Measure, instance: Instance,
up_tasks: List[Assumptions], hard_tasks: List[Assumptions]) -> Report:
time_sum, value_sum, encoding_data = 0, 0, instance.encoding.get_data()
with solver.use_incremental(encoding_data, measure) as incremental:
def hard_worker(solver: Solver, problem: Problem, up_tasks: List[Assumptions],
hard_tasks: List[Assumptions]) -> Report:
time_sum, value_sum, formula = 0, 0, problem.encoding.get_formula()
with solver.get_instance(formula) as incremental:
for up_task_assumptions in chain(up_tasks, hard_tasks):
time, value, _, _ = incremental.solve(up_task_assumptions, add_model=False)
time, value, _, _ = incremental.solve(
(up_task_assumptions, []), extract_model=False
)
time_sum, value_sum = time_sum + time, value_sum + value

return Report(time_sum, value_sum, Status.RESOLVED, None)
Expand All @@ -46,23 +48,17 @@ def hard_worker(solver: Solver, measure: Measure, instance: Instance,
class Combine(Core):
slug = 'core:combine'

def __init__(self,
logger: Logger,
solver: Solver,
measure: Measure,
instance: Instance,
executor: Executor,
random_seed: Int = None):
self.solver = solver
def __init__(self, logger: Logger, measure: Measure, problem: Problem,
executor: Executor, random_seed: Optional[int] = None):
self.measure = measure
self.executor = executor
super().__init__(logger, instance, random_seed)
super().__init__(logger, problem, random_seed)

def launch(self, *searchables: Searchable) -> Estimation:
encoding_data = self.instance.encoding.get_data()
formula = self.problem.encoding.get_formula()
total_var_set, start_stamp = set(concat(*searchables)), now()
time_sum, value_sum, all_up_tasks, all_hard_tasks = 0, 0, [], []
with self.solver.use_incremental(encoding_data, self.measure) as solver:
with self.problem.solver.get_instance(formula) as solver:
for searchable in searchables:
report = get_propagation(solver, searchable)
time, value, status, (up_tasks, hard_tasks) = report
Expand All @@ -75,15 +71,17 @@ def launch(self, *searchables: Searchable) -> Estimation:
for hard_tasks, count in [(ts, len(ts)) for ts in all_hard_tasks]:
hard_tasks_count = count * len(acc_hard_tasks)
acc_hard_tasks = [
concat(*parts) for parts in product(acc_hard_tasks, hard_tasks)
if solver.propagate(concat(*parts))[2] == Status.SOLVED
concat(*parts) for parts in
product(acc_hard_tasks, hard_tasks)
if solver.propagate((concat(*parts), [])).status
]
ratio = round(len(acc_hard_tasks) / hard_tasks_count, 2)
print(f'reduced: {hard_tasks_count} -> {len(acc_hard_tasks)} (x{ratio})')
print(
f'reduced: {hard_tasks_count} -> {len(acc_hard_tasks)} (x{ratio})')

split_into = ceil(len(acc_hard_tasks) / self.executor.max_workers)
for future in self.executor.submit_all(hard_worker, *(
(self.solver, self.measure, self.instance, all_up_tasks, hard_tasks)
(self.solver, self.problem, all_up_tasks, hard_tasks)
for hard_tasks in slice_by(acc_hard_tasks, split_into)
)).as_complete():
time, value, _, _ = future.result()
Expand Down
25 changes: 9 additions & 16 deletions core/impl/optimize.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from math import ceil
from time import time as now
from typing import Tuple, List, Dict, Any
from typing import Tuple, List, Dict, Any, Optional

from space import Space
from output import Logger
from executor import Executor
from function import Function
from instance import Instance
from algorithm import Algorithm

from ..abc import Estimate
Expand All @@ -18,37 +17,30 @@
from ..module.comparator import Comparator
from ..module.limitation import Limitation

from typings.optional import Int
from util.iterable import omit_by
from pysatmc.problem import Problem

Await = Tuple[PointSet, List[Handle]]


class Optimize(Estimate):
slug = 'core:optimize'

def __init__(self,
space: Space,
logger: Logger,
executor: Executor,
instance: Instance,
sampling: Sampling,
function: Function,
algorithm: Algorithm,
comparator: Comparator,
limitation: Limitation,
random_seed: Int = None):
def __init__(self, space: Space, logger: Logger, problem: Problem,
executor: Executor, sampling: Sampling, function: Function,
algorithm: Algorithm, comparator: Comparator,
limitation: Limitation, random_seed: Optional[int] = None):
self.algorithm = algorithm
self.limitation = limitation
super().__init__(space, logger, instance, executor,
super().__init__(space, logger, problem, executor,
sampling, function, comparator, random_seed)

self.optimization_trace = []

def launch(self, *args, **kwargs) -> PointSet:
start_stamp = now()
with self.logger:
initial = self.space.get_initial(self.instance)
initial = self.space.get_initial(self.problem)
self.logger.meta(initial, self.comparator)
# todo: search root estimation in cache
point, handles = self.estimate(initial).result(), []
Expand Down Expand Up @@ -81,6 +73,7 @@ def _await(self, *handles: Handle, count: int = 1) -> Await:
return [h.result() for h in done], not_done

def __config__(self) -> Dict[str, Any]:
# todo: add realisation
return {}


Expand Down
8 changes: 4 additions & 4 deletions core/model/contex.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from space import Space
from executor import Executor
from instance import Instance
from function import Function

from typing import List, Optional
Expand All @@ -9,6 +8,7 @@
from ..static import CORE_CACHE
from ..module.sampling import Sampling

from pysatmc.problem import Problem
from typings.searchable import Searchable
from function.model import Estimation, Results, WorkerArgs

Expand All @@ -17,23 +17,23 @@ class Context:
def __init__(
self,
space: Space,
instance: Instance,
problem: Problem,
function: Function,
sampling: Sampling,
executor: Executor,
searchable: Searchable,
sample_seed: Optional[int]
):
self.space = space
self.instance = instance
self.problem = problem
self.function = function
self.sampling = sampling
self.executor = executor
self.searchable = searchable

self.sample_seed = sample_seed
self.sample_size = min(searchable.power(), self.sampling.max_size) \
if not self.instance.input_dependent else self.sampling.max_size
if not self.problem.output_set else self.sampling.max_size
self.sample_state = self.sampling.get_state(0, self.sample_size)

def get_tasks(self, results: Results) -> List[WorkerArgs]:
Expand Down
5 changes: 3 additions & 2 deletions core/model/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

from .contex import Context

from util.iterable import list_of
from function.model import ChunkResult, Results

from util.iterable import list_of
from typings.error import AlreadyRunning, CancelledError
from typings.future import Future, Timeout, AcquireFutures

Expand Down Expand Up @@ -76,7 +77,7 @@ def __init__(self, context: Context, job_id: int):
def _process(self, context: Context):
fn = context.function.get_worker_fn()
payload = context.function.get_payload(
context.space, context.instance, context.searchable
context.space, context.problem, context.searchable
)

tasks = context.get_tasks(self._results)
Expand Down
Loading

0 comments on commit bde91b6

Please sign in to comment.