# Example for using exclusion constraints in discrete searchspaces This examples shows how an exclusion constraint can be created for a discrete searchspace. This can be used if some parameter values are incompatible with values of another parameter. This example assumes some basic familiarity with using BayBE. We thus refer to [`campaign`](./../Basics/campaign.md) for a basic example. ## Necessary imports for this example ```python import numpy as np ``` ```python from baybe import Campaign from baybe.constraints import ( DiscreteExcludeConstraint, SubSelectionCondition, ThresholdCondition, ) from baybe.objectives import SingleTargetObjective from baybe.parameters import ( CategoricalParameter, NumericalDiscreteParameter, SubstanceParameter, ) from baybe.searchspace import SearchSpace from baybe.targets import NumericalTarget from baybe.utils.dataframe import add_fake_results ``` ## Experiment setup We begin by setting up some parameters for our experiments. ```python dict_solvent = { "water": "O", "C1": "C", "C2": "CC", "C3": "CCC", "C4": "CCCC", "C5": "CCCCC", "c6": "c1ccccc1", "C6": "CCCCCC", } solvent = SubstanceParameter(name="Solv", data=dict_solvent, encoding="RDKIT") speed = CategoricalParameter( name="Speed", values=["very slow", "slow", "normal", "fast", "very fast"], encoding="INT", ) temperature = NumericalDiscreteParameter( name="Temp", values=list(np.linspace(100, 200, 15)), tolerance=0.4 ) pressure = NumericalDiscreteParameter( name="Pressure", values=[1, 2, 5, 10], tolerance=0.4 ) ``` ```python parameters = [solvent, speed, temperature, pressure] ``` ## Creating the constraint This constraint simulates a situation where solvents `C2` and `C4` are not compatible with temperatures larger than 151 and should thus be excluded. ```python constraint_1 = DiscreteExcludeConstraint( parameters=["Temp", "Solv"], combiner="AND", conditions=[ ThresholdCondition(threshold=151, operator=">"), SubSelectionCondition(selection=["C4", "C2"]), ], ) ``` This constraint simulates a situation where solvents `C5` and `C6` are not compatible with pressures larger than 5 and should thus be excluded. ```python constraint_2 = DiscreteExcludeConstraint( parameters=["Pressure", "Solv"], combiner="AND", conditions=[ ThresholdCondition(threshold=5, operator=">"), SubSelectionCondition(selection=["C5", "C6"]), ], ) ``` This constraint simulates a situation where pressures below 3 should never be combined with temperatures above 120. ```python constraint_3 = DiscreteExcludeConstraint( parameters=["Pressure", "Temp"], combiner="AND", conditions=[ ThresholdCondition(threshold=3.0, operator="<"), ThresholdCondition(threshold=120.0, operator=">"), ], ) ``` ## Creating the searchspace and the objective We now create the searchspace using the previously defined constraints. ```python searchspace = SearchSpace.from_product( parameters=parameters, constraints=[constraint_1, constraint_2, constraint_3] ) ``` [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator [17:01:06] DEPRECATION WARNING: please use MorganGenerator ```python objective = SingleTargetObjective(target=NumericalTarget(name="Target_1", mode="MAX")) ``` ```python ### Creating and printing the campaign campaign = Campaign(searchspace=searchspace, objective=objective) print(campaign) ``` Campaign Meta Data Batches done: 0 Fits done: 0 SearchSpace Search Space Type: DISCRETE SubspaceDiscrete Discrete Parameters Name Type Num_Values Encoding 0 Pressure NumericalDis... 4 None 1 Solv SubstancePar... 8 SubstanceEnc... 2 Speed CategoricalP... 5 CategoricalE... 3 Temp NumericalDis... 15 None Experimental Representation Solv Speed Temp Pressure 0 C1 fast 100.000 1.0 1 C1 fast 100.000 2.0 2 C1 fast 100.000 5.0 ... ... ... ... ... 1147 water very slow 192.857 10.0 1148 water very slow 200.000 5.0 1149 water very slow 200.000 10.0 [1150 rows x 4 columns] Meta Data was_recommended: 0/1150 was_measured: 0/1150 dont_recommend: 0/1150 Constraints Type Affected_Paramet 0 DiscreteExcl... [Temp, Solv] 1 DiscreteExcl... [Pressure, S... 2 DiscreteExcl... [Pressure, T... Computational Representation Pressure Solv_RDKIT_MaxAb ... Speed Temp 0 1.0 0.0 ... 0.0 100.000 1 2.0 0.0 ... 0.0 100.000 2 5.0 0.0 ... 0.0 100.000 ... ... ... ... ... ... 1147 10.0 0.0 ... 4.0 192.857 1148 5.0 0.0 ... 4.0 200.000 1149 10.0 0.0 ... 4.0 200.000 [1150 rows x 9 columns] Objective Type: SingleTargetObjective Targets Type Name ... Upper_Bound Transformation 0 NumericalTarget Target_1 ... inf None [1 rows x 6 columns] TwoPhaseMetaRecommender Initial recommender RandomRecommender Compatibility: SearchSpaceType.HYBRID Recommender BotorchRecommender Surrogate GaussianProcessSurrogate Supports Transfer Learning: True Kernel factory: DefaultKernelFactory() Acquisition function: qLogExpectedImprovement() Compatibility: SearchSpaceType.HYBRID Sequential continuous: False Hybrid sampler: None Sampling percentage: 1.0 Switch after: 1 ## Manual verification of the constraints The following loop performs some iterations and manually verifies the given constraints. ```python N_ITERATIONS = 3 for kIter in range(N_ITERATIONS): print(f"\n\n#### ITERATION {kIter+1} ####") print("## ASSERTS ##") print( "Number of entries with either Solvents C2 or C4 and a temperature above 151: ", ( campaign.searchspace.discrete.exp_rep["Temp"].apply(lambda x: x > 151) & campaign.searchspace.discrete.exp_rep["Solv"].apply( lambda x: x in ["C2", "C4"] ) ).sum(), ) print( "Number of entries with either Solvents C5 or C6 and a pressure above 5: ", ( campaign.searchspace.discrete.exp_rep["Pressure"].apply(lambda x: x > 5) & campaign.searchspace.discrete.exp_rep["Solv"].apply( lambda x: x in ["C5", "C6"] ) ).sum(), ) print( "Number of entries with pressure below 3 and temperature above 120: ", ( campaign.searchspace.discrete.exp_rep["Pressure"].apply(lambda x: x < 3) & campaign.searchspace.discrete.exp_rep["Temp"].apply(lambda x: x > 120) ).sum(), ) rec = campaign.recommend(batch_size=5) add_fake_results(rec, campaign.targets) campaign.add_measurements(rec) ``` #### ITERATION 1 #### ## ASSERTS ## Number of entries with either Solvents C2 or C4 and a temperature above 151: 0 Number of entries with either Solvents C5 or C6 and a pressure above 5: 0 Number of entries with pressure below 3 and temperature above 120: 0 #### ITERATION 2 #### ## ASSERTS ## Number of entries with either Solvents C2 or C4 and a temperature above 151: 0 Number of entries with either Solvents C5 or C6 and a pressure above 5: 0 Number of entries with pressure below 3 and temperature above 120: 0 #### ITERATION 3 #### ## ASSERTS ## Number of entries with either Solvents C2 or C4 and a temperature above 151: 0 Number of entries with either Solvents C5 or C6 and a pressure above 5: 0 Number of entries with pressure below 3 and temperature above 120: 0