Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix visuals in examples #347

Merged
merged 24 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
558bf63
Shorten docstrings to avoid cutoff
AVHopp Aug 20, 2024
e576e66
Remove bold strings since they mess up output & fix campaign output
AVHopp Aug 20, 2024
c33114e
Add utility for indentation in printing
AVHopp Aug 20, 2024
91d8b32
Specifying boolean flag by using keyword
AdrianSosic Aug 26, 2024
28d88ad
Add utility for genereating str representations
AVHopp Sep 2, 2024
1bbd43c
Add option for single line string representation
AVHopp Sep 3, 2024
4586c59
Enhance pretty printing function for dataframes
AVHopp Aug 20, 2024
f0171aa
Improve visuals in examples
AVHopp Aug 20, 2024
43dd762
Replace use of outdated objective
AVHopp Aug 20, 2024
74dc635
Improve printing for surrogates
AVHopp Aug 20, 2024
21345cc
Improve printing for recommenders
AVHopp Aug 20, 2024
8c3f4cc
Improve printing for campaigns
AVHopp Aug 20, 2024
c468288
Improve printing for search spaces
AVHopp Aug 22, 2024
68838f4
Improve printing for objectives
AVHopp Aug 22, 2024
8a77f2b
Make numbered list in example unnumbered
AdrianSosic Aug 26, 2024
2bca721
Fix mypy errors
AVHopp Sep 4, 2024
3ea0669
Rename utility to to_string
AVHopp Sep 5, 2024
a7b3ad3
Improve docstring of new str utility
AdrianSosic Sep 5, 2024
8107f57
Change list of fields into tuple using * operator
AVHopp Sep 5, 2024
dbd7ba4
Remove check for : in header
AVHopp Sep 5, 2024
cfec79b
Remove : in str creation
AVHopp Sep 5, 2024
4fce9f9
Remove redundant comments regarding super call
AVHopp Sep 6, 2024
6e1cac9
Add __str__ function for BetaBernoulliMAB-Surrogate
AVHopp Sep 6, 2024
646fb95
Add colon at the end of single line headers
AVHopp Sep 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions baybe/campaign.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
telemetry_record_value,
)
from baybe.utils.boolean import eq_dataframe
from baybe.utils.plotting import to_string
AVHopp marked this conversation as resolved.
Show resolved Hide resolved


@define
Expand Down Expand Up @@ -84,19 +85,14 @@ class Campaign(SerialMixin):
"""The cached recommendations."""

def __str__(self) -> str:
start_bold = "\033[1m"
end_bold = "\033[0m"

# Get str representation of campaign fields
fields_to_print = [self.searchspace, self.objective, self.recommender]
fields_str = "\n\n".join(str(x) for x in fields_to_print)

# Put all relevant attributes of the campaign in one string
campaign_str = f"""{start_bold}Campaign{end_bold}
\n{start_bold}Meta Data{end_bold}\nBatches Done: {self.n_batches_done}
\rFits Done: {self.n_fits_done}\n\n{fields_str}\n"""

return campaign_str.replace("\n", "\n ").replace("\r", "\r ")
metadata_fields = [
to_string("Batches done", self.n_batches_done, single_line=True),
to_string("Fits done", self.n_fits_done, single_line=True),
]
metadata = to_string("Meta Data", *metadata_fields)
fields = [metadata, self.searchspace, self.objective, self.recommender]

return to_string(self.__class__.__name__, *fields)

@property
def measurements(self) -> pd.DataFrame:
Expand Down
16 changes: 8 additions & 8 deletions baybe/objectives/desirability.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
from baybe.targets.base import Target
from baybe.targets.numerical import NumericalTarget
from baybe.utils.basic import to_tuple
from baybe.utils.dataframe import pretty_print_df
from baybe.utils.numerical import geom_mean
from baybe.utils.plotting import to_string
from baybe.utils.validation import finite_float


Expand Down Expand Up @@ -122,19 +124,17 @@ def _normalized_weights(self) -> np.ndarray:
return np.asarray(self.weights) / np.sum(self.weights)

def __str__(self) -> str:
start_bold = "\033[1m"
end_bold = "\033[0m"

targets_list = [target.summary() for target in self.targets]
targets_df = pd.DataFrame(targets_list)
targets_df["Weight"] = self.weights

objective_str = f"""{start_bold}Objective{end_bold}
\n{start_bold}Type: {end_bold}{self.__class__.__name__}
\n{start_bold}Targets {end_bold}\n{targets_df}
\n{start_bold}Scalarizer: {end_bold}{self.scalarizer.name}"""
fields = [
to_string("Type", self.__class__.__name__, single_line=True),
to_string("Targets", pretty_print_df(targets_df)),
to_string("Scalarizer", self.scalarizer.name, single_line=True),
]

return objective_str.replace("\n", "\n ")
return to_string("Objective", *fields)

def transform(self, data: pd.DataFrame) -> pd.DataFrame: # noqa: D102
# See base class.
Expand Down
14 changes: 7 additions & 7 deletions baybe/objectives/single.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

from baybe.objectives.base import Objective
from baybe.targets.base import Target
from baybe.utils.dataframe import pretty_print_df
from baybe.utils.plotting import to_string


@define(frozen=True, slots=False)
Expand All @@ -16,17 +18,15 @@ class SingleTargetObjective(Objective):
"""The single target considered by the objective."""

def __str__(self) -> str:
start_bold = "\033[1m"
end_bold = "\033[0m"

targets_list = [target.summary() for target in self.targets]
targets_df = pd.DataFrame(targets_list)

objective_str = f"""{start_bold}Objective{end_bold}
\n{start_bold}Type: {end_bold}{self.__class__.__name__}
\n{start_bold}Targets {end_bold}\n{targets_df}"""
fields = [
to_string("Type", self.__class__.__name__, single_line=True),
to_string("Targets", pretty_print_df(targets_df)),
]

return objective_str.replace("\n", "\n ")
return to_string("Objective", *fields)

@property
def targets(self) -> tuple[Target, ...]: # noqa: D102
Expand Down
4 changes: 2 additions & 2 deletions baybe/parameters/numerical.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

@define(frozen=True, slots=False)
class NumericalDiscreteParameter(DiscreteParameter):
"""Parameter class for discrete numerical parameters (a.k.a. setpoints)."""
"""Class for discrete numerical parameters (a.k.a. setpoints)."""

# class variables
is_numerical: ClassVar[bool] = True
Expand Down Expand Up @@ -100,7 +100,7 @@ def is_in_range(self, item: float) -> bool: # noqa: D102

@define(frozen=True, slots=False)
class NumericalContinuousParameter(ContinuousParameter):
"""Parameter class for continuous numerical parameters."""
"""Class for continuous numerical parameters."""

# class variables
is_numerical: ClassVar[bool] = True
Expand Down
22 changes: 22 additions & 0 deletions baybe/recommenders/meta/sequential.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
block_serialization_hook,
converter,
)
from baybe.utils.plotting import to_string


@define
Expand Down Expand Up @@ -64,6 +65,14 @@ def select_recommender( # noqa: D102
else self.initial_recommender
)

def __str__(self) -> str:
fields = [
to_string("Initial recommender", self.initial_recommender),
to_string("Recommender", self.recommender),
to_string("Switch after", self.switch_after, single_line=True),
]
return to_string(self.__class__.__name__, *fields)


@define
class SequentialMetaRecommender(MetaRecommender):
Expand Down Expand Up @@ -164,6 +173,13 @@ def select_recommender( # noqa: D102

return recommender

def __str__(self) -> str:
fields = [
to_string("Recommenders", self.recommenders),
to_string("Mode", self.mode, single_line=True),
]
return to_string(self.__class__.__name__, *fields)


@define
class StreamingSequentialMetaRecommender(MetaRecommender):
Expand Down Expand Up @@ -242,6 +258,12 @@ def select_recommender( # noqa: D102

return self._last_recommender # type: ignore[return-value]

def __str__(self) -> str:
fields = [
to_string("Recommenders", self.recommenders),
]
return to_string(self.__class__.__name__, *fields)


# The recommender iterable cannot be serialized
converter.register_unstructure_hook(
Expand Down
18 changes: 18 additions & 0 deletions baybe/recommenders/pure/bayesian/botorch.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
SubspaceDiscrete,
)
from baybe.utils.dataframe import to_tensor
from baybe.utils.plotting import to_string
from baybe.utils.sampling_algorithms import (
DiscreteSamplingMethod,
sample_numerical_df,
Expand Down Expand Up @@ -295,3 +296,20 @@ def _recommend_hybrid(
rec_exp = pd.concat([rec_disc_exp, rec_cont_exp], axis=1)

return rec_exp

def __str__(self) -> str:
fields = [
to_string("Surrogate", self.surrogate_model),
to_string(
"Acquisition function", self.acquisition_function, single_line=True
),
to_string("Compatibility", self.compatibility, single_line=True),
to_string(
"Sequential continuous", self.sequential_continuous, single_line=True
),
to_string("Hybrid sampler", self.hybrid_sampler, single_line=True),
to_string(
"Sampling percentage", self.sampling_percentage, single_line=True
),
]
return to_string(self.__class__.__name__, *fields)
13 changes: 13 additions & 0 deletions baybe/recommenders/pure/nonpredictive/clustering.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from baybe.recommenders.pure.nonpredictive.base import NonPredictiveRecommender
from baybe.searchspace import SearchSpaceType, SubspaceDiscrete
from baybe.utils.plotting import to_string


@define
Expand Down Expand Up @@ -125,6 +126,18 @@ def _recommend_discrete(
# Convert positional indices into DataFrame indices and return result
return candidates_comp.index[selection]

def __str__(self) -> str:
fields = [
to_string("Compatibility", self.compatibility, single_line=True),
to_string(
"Name of clustering parameter",
self.model_cluster_num_parameter_name,
single_line=True,
),
to_string("Model parameters", self.model_params, single_line=True),
]
return to_string(self.__class__.__name__, *fields)


@define
class PAMClusteringRecommender(SKLearnClusteringRecommender):
Expand Down
9 changes: 9 additions & 0 deletions baybe/recommenders/pure/nonpredictive/sampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from baybe.recommenders.pure.nonpredictive.base import NonPredictiveRecommender
from baybe.searchspace import SearchSpace, SearchSpaceType, SubspaceDiscrete
from baybe.utils.plotting import to_string
from baybe.utils.sampling_algorithms import farthest_point_sampling


Expand Down Expand Up @@ -45,6 +46,10 @@ def _recommend_hybrid(
cont_random.index = disc_random.index
return pd.concat([disc_random, cont_random], axis=1)

def __str__(self) -> str:
fields = [to_string("Compatibility", self.compatibility, single_line=True)]
return to_string(self.__class__.__name__, *fields)


class FPSRecommender(NonPredictiveRecommender):
"""An initial recommender that selects candidates via Farthest Point Sampling."""
Expand All @@ -70,3 +75,7 @@ def _recommend_discrete(
candidates_scaled = np.ascontiguousarray(scaler.transform(candidates_comp))
ilocs = farthest_point_sampling(candidates_scaled, batch_size)
return candidates_comp.index[ilocs]

def __str__(self) -> str:
fields = [to_string("Compatibility", self.compatibility, single_line=True)]
return to_string(self.__class__.__name__, *fields)
31 changes: 13 additions & 18 deletions baybe/searchspace/continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from baybe.serialization import SerialMixin, converter, select_constructor_hook
from baybe.utils.basic import to_tuple
from baybe.utils.dataframe import pretty_print_df
from baybe.utils.plotting import to_string

if TYPE_CHECKING:
from baybe.searchspace.core import SearchSpace
Expand Down Expand Up @@ -71,9 +72,6 @@ def __str__(self) -> str:
if self.is_empty:
return ""

start_bold = "\033[1m"
end_bold = "\033[0m"

# Convert the lists to dataFrames to be able to use pretty_printing
param_list = [param.summary() for param in self.parameters]
eq_constraints_list = [constr.summary() for constr in self.constraints_lin_eq]
Expand All @@ -84,21 +82,18 @@ def __str__(self) -> str:
constr.summary() for constr in self.constraints_nonlin
]
param_df = pd.DataFrame(param_list)
lin_eq_constr_df = pd.DataFrame(eq_constraints_list)
lin_ineq_constr_df = pd.DataFrame(ineq_constraints_list)
nonlinear_constr_df = pd.DataFrame(nonlin_constraints_list)

# Put all attributes of the continuous class in one string
continuous_str = f"""{start_bold}Continuous Search Space{end_bold}
\n{start_bold}Continuous Parameters{end_bold}\n{pretty_print_df(param_df)}
\n{start_bold}List of Linear Equality Constraints{end_bold}
\r{pretty_print_df(lin_eq_constr_df)}
\n{start_bold}List of Linear Inequality Constraints{end_bold}
\r{pretty_print_df(lin_ineq_constr_df)}
\n{start_bold}List of Nonlinear Constraints{end_bold}
\r{pretty_print_df(nonlinear_constr_df)}"""

return continuous_str.replace("\n", "\n ").replace("\r", "\r ")
lin_eq_df = pd.DataFrame(eq_constraints_list)
lin_ineq_df = pd.DataFrame(ineq_constraints_list)
nonlinear_df = pd.DataFrame(nonlin_constraints_list)

fields = [
to_string("Continuous Parameters", pretty_print_df(param_df)),
to_string("Linear Equality Constraints", pretty_print_df(lin_eq_df)),
to_string("Linear Inequality Constraints", pretty_print_df(lin_ineq_df)),
to_string("Non-linear Constraints", pretty_print_df(nonlinear_df)),
]

return to_string(self.__class__.__name__, *fields)

@property
def constraints_cardinality(self) -> tuple[ContinuousCardinalityConstraint, ...]:
Expand Down
22 changes: 9 additions & 13 deletions baybe/searchspace/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from baybe.searchspace.validation import validate_parameters
from baybe.serialization import SerialMixin, converter, select_constructor_hook
from baybe.telemetry import TELEM_LABELS, telemetry_record_value
from baybe.utils.plotting import to_string


class SearchSpaceType(Enum):
Expand Down Expand Up @@ -66,19 +67,14 @@ class SearchSpace(SerialMixin):
"""The (potentially empty) continuous subspace of the overall search space."""

def __str__(self) -> str:
start_bold = "\033[1m"
end_bold = "\033[0m"
head_str = f"""{start_bold}Search Space{end_bold}
\n{start_bold}Search Space Type: {end_bold}{self.type.name}"""

# Check the sub space size to avoid adding unwanted break lines
# if the sub space is empty
discrete_str = f"\n\n{self.discrete}" if not self.discrete.is_empty else ""
continuous_str = (
f"\n\n{self.continuous}" if not self.continuous.is_empty else ""
)
searchspace_str = f"{head_str}{discrete_str}{continuous_str}"
return searchspace_str.replace("\n", "\n ").replace("\r", "\r ")
fields = [
to_string("Search Space Type", self.type.name, single_line=True),
]
if not self.discrete.is_empty:
fields.append(str(self.discrete))
if not self.continuous.is_empty:
fields.append(str(self.continuous))
return to_string(self.__class__.__name__, *fields)

def __attrs_post_init__(self):
"""Perform validation and record telemetry values."""
Expand Down
Loading
Loading