# Path: guacamol/scoring_function.py
# class ScoringFunction:
#     """
#     Base class for an objective function.
# 
#     In general, do not inherit directly from this class. Prefer `MoleculewiseScoringFunction` or `BatchScoringFunction`.
#     """
# 
#     def __init__(self, score_modifier: ScoreModifier = None) -> None:
#         """
#         Args:
#             score_modifier: Modifier to apply to the score. If None, will be LinearModifier()
#         """
#         self.score_modifier = score_modifier
#         self.corrupt_score = -1.0
# 
#     @property
#     def score_modifier(self):
#         return self._score_modifier
# 
#     @score_modifier.setter
#     def score_modifier(self, modifier: Optional[ScoreModifier]):
#         self._score_modifier = LinearModifier() if modifier is None else modifier
# 
#     def modify_score(self, raw_score: float) -> float:
#         return self._score_modifier(raw_score)
# 
#     @abstractmethod
#     def score(self, smiles: str) -> float:
#         """
#         Score a single molecule as smiles
#         """
#         raise NotImplementedError
# 
#     @abstractmethod
#     def score_list(self, smiles_list: List[str]) -> List[float]:
#         """
#         Score a list of smiles.
# 
#         Args:
#             smiles_list: list of smiles [smiles1, smiles2,...]
# 
#         Returns: a list of scores
# 
#         the order of the input smiles is matched in the output.
# 
#         """
#         raise NotImplementedError


from abc import ABCMeta, abstractmethod
from typing import List, Optional
from guacamol.scoring_function import ScoringFunction



class GoalDirectedGenerator(metaclass=ABCMeta):
    """
    Interface for goal-directed molecule generators.
    """

    @abstractmethod

# Path: guacamol/scoring_function.py
# class ScoringFunction:
#     """
#     Base class for an objective function.
# 
#     In general, do not inherit directly from this class. Prefer `MoleculewiseScoringFunction` or `BatchScoringFunction`.
#     """
# 
#     def __init__(self, score_modifier: ScoreModifier = None) -> None:
#         """
#         Args:
#             score_modifier: Modifier to apply to the score. If None, will be LinearModifier()
#         """
#         self.score_modifier = score_modifier
#         self.corrupt_score = -1.0
# 
#     @property
#     def score_modifier(self):
#         return self._score_modifier
# 
#     @score_modifier.setter
#     def score_modifier(self, modifier: Optional[ScoreModifier]):
#         self._score_modifier = LinearModifier() if modifier is None else modifier
# 
#     def modify_score(self, raw_score: float) -> float:
#         return self._score_modifier(raw_score)
# 
#     @abstractmethod
#     def score(self, smiles: str) -> float:
#         """
#         Score a single molecule as smiles
#         """
#         raise NotImplementedError
# 
#     @abstractmethod
#     def score_list(self, smiles_list: List[str]) -> List[float]:
#         """
#         Score a list of smiles.
# 
#         Args:
#             smiles_list: list of smiles [smiles1, smiles2,...]
# 
#         Returns: a list of scores
# 
#         the order of the input smiles is matched in the output.
# 
#         """
#         raise NotImplementedError


# Path: guacamol/goal_directed_generator.py
from abc import ABCMeta, abstractmethod
from typing import List, Optional
from guacamol.scoring_function import ScoringFunction




class GoalDirectedGenerator(metaclass=ABCMeta):
    """
    Interface for goal-directed molecule generators.
    """

    @abstractmethod

    def generate_optimized_molecules(self, scoring_function: ScoringFunction, number_molecules: int,