ado-trim 1.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. ado_trim-1.6.0/PKG-INFO +65 -0
  2. ado_trim-1.6.0/README.md +53 -0
  3. ado_trim-1.6.0/ado_trim.egg-info/PKG-INFO +65 -0
  4. ado_trim-1.6.0/ado_trim.egg-info/SOURCES.txt +29 -0
  5. ado_trim-1.6.0/ado_trim.egg-info/dependency_links.txt +1 -0
  6. ado_trim-1.6.0/ado_trim.egg-info/entry_points.txt +2 -0
  7. ado_trim-1.6.0/ado_trim.egg-info/requires.txt +5 -0
  8. ado_trim-1.6.0/ado_trim.egg-info/top_level.txt +1 -0
  9. ado_trim-1.6.0/pyproject.toml +29 -0
  10. ado_trim-1.6.0/setup.cfg +4 -0
  11. ado_trim-1.6.0/trim/__init__.py +2 -0
  12. ado_trim-1.6.0/trim/no_priors_pydantic.py +72 -0
  13. ado_trim-1.6.0/trim/no_priors_sampler.py +132 -0
  14. ado_trim-1.6.0/trim/operator.py +189 -0
  15. ado_trim-1.6.0/trim/test/test_data_documentation.py +357 -0
  16. ado_trim-1.6.0/trim/test/test_high_dimensional_sampling.py +269 -0
  17. ado_trim-1.6.0/trim/test/test_rowsring.py +134 -0
  18. ado_trim-1.6.0/trim/test/test_sampling.py +56 -0
  19. ado_trim-1.6.0/trim/trim_pydantic.py +237 -0
  20. ado_trim-1.6.0/trim/trim_sampler.py +762 -0
  21. ado_trim-1.6.0/trim/utils/__init__.py +2 -0
  22. ado_trim-1.6.0/trim/utils/exceptions.py +14 -0
  23. ado_trim-1.6.0/trim/utils/high_dimensional_sampling.py +446 -0
  24. ado_trim-1.6.0/trim/utils/logging_utils.py +219 -0
  25. ado_trim-1.6.0/trim/utils/miscellaneous.py +15 -0
  26. ado_trim-1.6.0/trim/utils/one_dimensional_sampling.py +293 -0
  27. ado_trim-1.6.0/trim/utils/order.py +365 -0
  28. ado_trim-1.6.0/trim/utils/rowsring.py +104 -0
  29. ado_trim-1.6.0/trim/utils/space_df_connector.py +527 -0
  30. ado_trim-1.6.0/trim/utils/split_common_and_diff.py +65 -0
  31. ado_trim-1.6.0/trim/utils/stopping_criterion.py +46 -0
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: ado-trim
3
+ Version: 1.6.0
4
+ Summary: TRIM (Transfer Refined Iterative Modeling) builds an accurate predictive model from a small dataset by iteratively sampling a Discovery Space.
5
+ Requires-Python: <3.14,>=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: ado-core
8
+ Requires-Dist: autogluon-tabular[catboost,xgboost]==1.5
9
+ Requires-Dist: numpy
10
+ Requires-Dist: pandas>=2.2.0
11
+ Requires-Dist: scikit-learn
12
+
13
+ # ADO TRIM Operator
14
+
15
+ `ado-trim` is an operator plugin for the
16
+ [Accelerated Discovery Orchestrator (ADO)](https://github.com/IBM/ado),
17
+ providing the Transfer Refined Iterative Modeling (TRIM) characterization
18
+ operator.
19
+
20
+ **TRIM** is designed to efficiently build a surrogate model of a complex system.
21
+ It is ideal for scenarios where exploring a parameter space is time-consuming or
22
+ expensive. TRIM intelligently samples just enough points to create a stable and
23
+ accurate predictive model, saving significant time and resources.
24
+
25
+ ## How it Works
26
+
27
+ The `TRIM` operator works in two main phases:
28
+
29
+ 1. **No-Priors Characterization**: If the system has not been measured before,
30
+ TRIM starts by sampling a small, representative set of points using a
31
+ space-filling algorithm to get a baseline understanding of the parameter
32
+ space.
33
+
34
+ 2. **Iterative Modeling**: This phase begins by using all currently available
35
+ data to train a single preliminary surrogate model. The feature importance
36
+ from this model is used to order for all remaining unmeasured points. TRIM
37
+ then enters a loop where it:
38
+ - Samples the next point and adds it to the dataset.
39
+ - Trains a model on the gathered data.
40
+ - Evaluates the expected improvement of a model trained on a larger dataset
41
+ by comparing the new model's performance against that of previous models.
42
+
43
+ This loop continues until the improvement is below a threshold, at which point
44
+ TRIM automatically stops. Finally, it trains one high-quality model on all
45
+ collected data and saves it for your use. It also outputs a file containing the
46
+ measured values and predictions for all points in your space.
47
+
48
+ ## Installation
49
+
50
+ You can install the `TRIM` operator and its dependencies (including `ado-core`)
51
+ directly from PyPI:
52
+
53
+ ```bash
54
+ pip install ado-trim
55
+ ```
56
+
57
+ ## More Information
58
+
59
+ To learn more about TRIM and explore the full capabilities of ADO, including
60
+ detailed documentation, configuration guides, and additional examples, visit the
61
+ official ADO website:
62
+
63
+ - **TRIM Quickstart**: <https://ibm.github.io/ado/examples/trim/>
64
+ - **Configuring TRIM**: <https://ibm.github.io/ado/operators/trim/>
65
+ - **ADO Documentation**: <https://ibm.github.io/ado/>
@@ -0,0 +1,53 @@
1
+ # ADO TRIM Operator
2
+
3
+ `ado-trim` is an operator plugin for the
4
+ [Accelerated Discovery Orchestrator (ADO)](https://github.com/IBM/ado),
5
+ providing the Transfer Refined Iterative Modeling (TRIM) characterization
6
+ operator.
7
+
8
+ **TRIM** is designed to efficiently build a surrogate model of a complex system.
9
+ It is ideal for scenarios where exploring a parameter space is time-consuming or
10
+ expensive. TRIM intelligently samples just enough points to create a stable and
11
+ accurate predictive model, saving significant time and resources.
12
+
13
+ ## How it Works
14
+
15
+ The `TRIM` operator works in two main phases:
16
+
17
+ 1. **No-Priors Characterization**: If the system has not been measured before,
18
+ TRIM starts by sampling a small, representative set of points using a
19
+ space-filling algorithm to get a baseline understanding of the parameter
20
+ space.
21
+
22
+ 2. **Iterative Modeling**: This phase begins by using all currently available
23
+ data to train a single preliminary surrogate model. The feature importance
24
+ from this model is used to order for all remaining unmeasured points. TRIM
25
+ then enters a loop where it:
26
+ - Samples the next point and adds it to the dataset.
27
+ - Trains a model on the gathered data.
28
+ - Evaluates the expected improvement of a model trained on a larger dataset
29
+ by comparing the new model's performance against that of previous models.
30
+
31
+ This loop continues until the improvement is below a threshold, at which point
32
+ TRIM automatically stops. Finally, it trains one high-quality model on all
33
+ collected data and saves it for your use. It also outputs a file containing the
34
+ measured values and predictions for all points in your space.
35
+
36
+ ## Installation
37
+
38
+ You can install the `TRIM` operator and its dependencies (including `ado-core`)
39
+ directly from PyPI:
40
+
41
+ ```bash
42
+ pip install ado-trim
43
+ ```
44
+
45
+ ## More Information
46
+
47
+ To learn more about TRIM and explore the full capabilities of ADO, including
48
+ detailed documentation, configuration guides, and additional examples, visit the
49
+ official ADO website:
50
+
51
+ - **TRIM Quickstart**: <https://ibm.github.io/ado/examples/trim/>
52
+ - **Configuring TRIM**: <https://ibm.github.io/ado/operators/trim/>
53
+ - **ADO Documentation**: <https://ibm.github.io/ado/>
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: ado-trim
3
+ Version: 1.6.0
4
+ Summary: TRIM (Transfer Refined Iterative Modeling) builds an accurate predictive model from a small dataset by iteratively sampling a Discovery Space.
5
+ Requires-Python: <3.14,>=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: ado-core
8
+ Requires-Dist: autogluon-tabular[catboost,xgboost]==1.5
9
+ Requires-Dist: numpy
10
+ Requires-Dist: pandas>=2.2.0
11
+ Requires-Dist: scikit-learn
12
+
13
+ # ADO TRIM Operator
14
+
15
+ `ado-trim` is an operator plugin for the
16
+ [Accelerated Discovery Orchestrator (ADO)](https://github.com/IBM/ado),
17
+ providing the Transfer Refined Iterative Modeling (TRIM) characterization
18
+ operator.
19
+
20
+ **TRIM** is designed to efficiently build a surrogate model of a complex system.
21
+ It is ideal for scenarios where exploring a parameter space is time-consuming or
22
+ expensive. TRIM intelligently samples just enough points to create a stable and
23
+ accurate predictive model, saving significant time and resources.
24
+
25
+ ## How it Works
26
+
27
+ The `TRIM` operator works in two main phases:
28
+
29
+ 1. **No-Priors Characterization**: If the system has not been measured before,
30
+ TRIM starts by sampling a small, representative set of points using a
31
+ space-filling algorithm to get a baseline understanding of the parameter
32
+ space.
33
+
34
+ 2. **Iterative Modeling**: This phase begins by using all currently available
35
+ data to train a single preliminary surrogate model. The feature importance
36
+ from this model is used to order for all remaining unmeasured points. TRIM
37
+ then enters a loop where it:
38
+ - Samples the next point and adds it to the dataset.
39
+ - Trains a model on the gathered data.
40
+ - Evaluates the expected improvement of a model trained on a larger dataset
41
+ by comparing the new model's performance against that of previous models.
42
+
43
+ This loop continues until the improvement is below a threshold, at which point
44
+ TRIM automatically stops. Finally, it trains one high-quality model on all
45
+ collected data and saves it for your use. It also outputs a file containing the
46
+ measured values and predictions for all points in your space.
47
+
48
+ ## Installation
49
+
50
+ You can install the `TRIM` operator and its dependencies (including `ado-core`)
51
+ directly from PyPI:
52
+
53
+ ```bash
54
+ pip install ado-trim
55
+ ```
56
+
57
+ ## More Information
58
+
59
+ To learn more about TRIM and explore the full capabilities of ADO, including
60
+ detailed documentation, configuration guides, and additional examples, visit the
61
+ official ADO website:
62
+
63
+ - **TRIM Quickstart**: <https://ibm.github.io/ado/examples/trim/>
64
+ - **Configuring TRIM**: <https://ibm.github.io/ado/operators/trim/>
65
+ - **ADO Documentation**: <https://ibm.github.io/ado/>
@@ -0,0 +1,29 @@
1
+ README.md
2
+ pyproject.toml
3
+ ado_trim.egg-info/PKG-INFO
4
+ ado_trim.egg-info/SOURCES.txt
5
+ ado_trim.egg-info/dependency_links.txt
6
+ ado_trim.egg-info/entry_points.txt
7
+ ado_trim.egg-info/requires.txt
8
+ ado_trim.egg-info/top_level.txt
9
+ trim/__init__.py
10
+ trim/no_priors_pydantic.py
11
+ trim/no_priors_sampler.py
12
+ trim/operator.py
13
+ trim/trim_pydantic.py
14
+ trim/trim_sampler.py
15
+ trim/test/test_data_documentation.py
16
+ trim/test/test_high_dimensional_sampling.py
17
+ trim/test/test_rowsring.py
18
+ trim/test/test_sampling.py
19
+ trim/utils/__init__.py
20
+ trim/utils/exceptions.py
21
+ trim/utils/high_dimensional_sampling.py
22
+ trim/utils/logging_utils.py
23
+ trim/utils/miscellaneous.py
24
+ trim/utils/one_dimensional_sampling.py
25
+ trim/utils/order.py
26
+ trim/utils/rowsring.py
27
+ trim/utils/space_df_connector.py
28
+ trim/utils/split_common_and_diff.py
29
+ trim/utils/stopping_criterion.py
@@ -0,0 +1,2 @@
1
+ [ado.operators]
2
+ trim = trim.operator
@@ -0,0 +1,5 @@
1
+ ado-core
2
+ autogluon-tabular[catboost,xgboost]==1.5
3
+ numpy
4
+ pandas>=2.2.0
5
+ scikit-learn
@@ -0,0 +1 @@
1
+ trim
@@ -0,0 +1,29 @@
1
+ [project]
2
+ name = "ado-trim"
3
+ description = "TRIM (Transfer Refined Iterative Modeling) builds an accurate predictive model from a small dataset by iteratively sampling a Discovery Space."
4
+ readme = "README.md"
5
+ requires-python = ">=3.10,<3.14"
6
+ dependencies = [
7
+ "ado-core",
8
+ "autogluon-tabular[catboost,xgboost]==1.5",
9
+ "numpy",
10
+ "pandas>=2.2.0",
11
+ "scikit-learn",
12
+ ]
13
+ dynamic = ["version"]
14
+
15
+ [project.entry-points."ado.operators"]
16
+ trim = "trim.operator"
17
+
18
+ [build-system]
19
+ requires = ["setuptools", "setuptools_scm"]
20
+ build-backend = "setuptools.build_meta"
21
+
22
+ [tool.setuptools]
23
+ packages = ["trim"]
24
+
25
+ [tool.setuptools_scm]
26
+ root = "../../../"
27
+
28
+ [tool.uv.sources]
29
+ ado-core = { workspace = true }
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,2 @@
1
+ # Copyright IBM Corporation 2025, 2026
2
+ # SPDX-License-Identifier: MIT
@@ -0,0 +1,72 @@
1
+ # Copyright IBM Corporation 2025, 2026
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ from typing import Annotated, Literal
5
+
6
+ from pydantic import BaseModel, BeforeValidator, Field
7
+
8
+
9
+ class NoPriorsParameters(BaseModel):
10
+ """
11
+ Parameters for sampling high-dimensional spaces without prior model structure.
12
+
13
+ The `sampling_strategy` must be one of the Literals supported.
14
+ Source of truth for supported strategies is the comment block right here:
15
+
16
+ strategy (str): sampling subroutine:
17
+ - 'random': selects random points from the beginning
18
+ - 'one_shift': refer to one_shift_then_random_points_high_dimensional_sampling
19
+ - 'recursive_aggregation': refer to recursive_aggregation_high_dimensional_sampling
20
+ - 'clhs': refer to concatenated_latin_hypercube_sampling
21
+ - 'sobol': sobol sampling
22
+ """
23
+
24
+ targetOutput: Annotated[
25
+ str,
26
+ Field(
27
+ description="The measured property you will treat as a target variable.",
28
+ ),
29
+ ]
30
+
31
+ samples: Annotated[
32
+ int,
33
+ Field(
34
+ ge=1,
35
+ description="Number of unique points to sample (must be >= 1).",
36
+ ),
37
+ ] = 20
38
+
39
+ batchSize: Annotated[
40
+ int,
41
+ Field(
42
+ ge=1,
43
+ description=(
44
+ "Batch size parameter used by certain samplers (e.g., randomWalk) via continuous batching; "
45
+ "by default set equal to iterationSize in those contexts. Must be >= 1."
46
+ ),
47
+ ),
48
+ ] = 1
49
+
50
+ sampling_strategy: Annotated[
51
+ Literal["random", "one_shift", "recursive_aggregation", "clhs", "sobol"],
52
+ BeforeValidator(lambda s: s.lower()),
53
+ Field(
54
+ description=(
55
+ "Sampling subroutine. Supported values:\n"
56
+ " - 'random': selects random points from the beginning\n"
57
+ " - 'one_shift': see one_shift_then_random_points_high_dimensional_sampling\n"
58
+ " - 'recursive_aggregation': see recursive_aggregation_high_dimensional_sampling\n"
59
+ " - 'clhs': dimension-wise random without replacement until each dim cycles\n"
60
+ " - 'sobol': sobol sampling via scipy\n"
61
+ "Aliases: 'random_shifts' → 'recursive_aggregation'.\n"
62
+ "Validation is case-insensitive; value is normalized to lowercase."
63
+ ),
64
+ ),
65
+ ] = "clhs"
66
+
67
+
68
+ if __name__ == "__main__":
69
+ params = NoPriorsParameters.model_validate(NoPriorsParameters(targetOutput="test"))
70
+ print(
71
+ f"type of model_validate output on no-priors-characterization default is {type(params)}, printing the full object gives {params}"
72
+ )
@@ -0,0 +1,132 @@
1
+ # Copyright IBM Corporation 2025, 2026
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ import asyncio
5
+ import logging
6
+ import typing
7
+
8
+ from pydantic import BaseModel
9
+
10
+ from orchestrator.core.discoveryspace.samplers import BaseSampler
11
+ from orchestrator.core.discoveryspace.space import DiscoverySpace, Entity
12
+ from orchestrator.modules.operators.discovery_space_manager import DiscoverySpaceManager
13
+ from trim.no_priors_pydantic import NoPriorsParameters
14
+ from trim.utils.order import order_df_for_sampling_with_no_priors
15
+ from trim.utils.space_df_connector import (
16
+ get_list_of_entities_from_df_and_space,
17
+ get_source_and_target,
18
+ )
19
+
20
+ logger_no_priors = logging.getLogger(__name__)
21
+
22
+
23
+ # NOTE: to repeat the operation on the same space I can delete the operation if the output of this operation
24
+ # are not used by another operation
25
+ class NoPriorsSampleSelector(BaseSampler):
26
+ @classmethod
27
+ def samplerCompatibleWithDiscoverySpaceRemote(
28
+ cls, remoteDiscoverySpace: DiscoverySpaceManager # type: ignore[name-defined]
29
+ ) -> bool:
30
+ return True
31
+
32
+ async def remoteEntityIterator(
33
+ self, remoteDiscoverySpace: DiscoverySpaceManager, batchsize: int = 1
34
+ ) -> typing.AsyncGenerator[list[Entity], None]:
35
+ """
36
+ Generate entities for no-priors characterization sampling.
37
+
38
+ Orders the target space using a high-dimensional sampling strategy (e.g., CLHS, Sobol)
39
+ without relying on prior model knowledge or feature importance.
40
+
41
+ Args:
42
+ remoteDiscoverySpace: Manager for the discovery space state
43
+ batchsize: Number of entities to yield per iteration
44
+
45
+ Yields:
46
+ List of Entity objects to be measured, in the determined order
47
+ """
48
+
49
+ async def iterator_closure(
50
+ stateHandle: DiscoverySpaceManager, # type: ignore[name-defined]
51
+ ) -> typing.Callable[[], typing.AsyncGenerator[list[Entity], None]]:
52
+
53
+ logger_no_priors.info("Characterization with no-priors starts.\n")
54
+ logger_no_priors.info(f"PARAMETERS ARE:\n{self.params}\n\n")
55
+
56
+ discoverySpace = await stateHandle.discoverySpace.remote()
57
+ source_df, target_df = get_source_and_target(
58
+ discoverySpace, self.params.targetOutput
59
+ )
60
+ logger_no_priors.info(f"Target dataframe has length {len(target_df)}")
61
+ target_df = order_df_for_sampling_with_no_priors(
62
+ target_df,
63
+ [
64
+ cp.identifier
65
+ for cp in discoverySpace.entitySpace.constitutiveProperties
66
+ ],
67
+ self.params.samples - len(source_df),
68
+ strategy=self.params.sampling_strategy,
69
+ )
70
+ list_of_entities_for_no_prior_characterization = (
71
+ get_list_of_entities_from_df_and_space(
72
+ df=target_df, space=discoverySpace
73
+ )
74
+ )
75
+
76
+ logger_no_priors.info(
77
+ "\n\nCharacterization with no-priors finished. Starting Iterative Modeling.\n"
78
+ )
79
+
80
+ async def iterator() -> typing.AsyncGenerator[list[Entity], None]: # type: ignore[name-defined]
81
+ logger_no_priors.info(
82
+ "\n\nIteration over sorted entities for no priors characterization starts.\n"
83
+ )
84
+ await asyncio.sleep(0.1)
85
+ for i in range(
86
+ 0, len(list_of_entities_for_no_prior_characterization), batchsize
87
+ ):
88
+ entities = list_of_entities_for_no_prior_characterization[
89
+ i : i + batchsize
90
+ ]
91
+ if len(entities) == 0:
92
+ logger_no_priors.info(
93
+ "\n\nCharacterization with no-priors finished.\n"
94
+ )
95
+ break
96
+ else:
97
+ yield entities
98
+ logger_no_priors.info("\n\nCharacterization with no-priors finished.\n")
99
+
100
+ return iterator
101
+
102
+ retval = await iterator_closure(remoteDiscoverySpace)
103
+
104
+ return retval()
105
+
106
+ def entityIterator(
107
+ self, discoverySpace: DiscoverySpace, batchsize: int = 1
108
+ ) -> typing.Generator[list[Entity], None, None]:
109
+ """Returns an remoteEntityIterator that returns entities in order"""
110
+
111
+ def iterator_closure(
112
+ space: DiscoverySpace,
113
+ ) -> typing.Callable[[], typing.Generator[list[Entity], None, None]]:
114
+
115
+ # list_of_entities = list(...) # type: ignore[name-defined]
116
+ # numberEntities = len(list_of_entities)
117
+
118
+ def iterator() -> typing.Generator[list[Entity], None, None]: # type: ignore[name-defined]
119
+ raise NotImplementedError
120
+ # ...for i in range(0, numberEntities, batchsize):
121
+
122
+ return iterator
123
+
124
+ retval = iterator_closure(discoverySpace)
125
+ return retval()
126
+
127
+ @classmethod
128
+ def parameters_model(cls) -> type[BaseModel] | None:
129
+ return NoPriorsParameters
130
+
131
+ def __init__(self, parameters: NoPriorsParameters) -> None:
132
+ self.params = parameters
@@ -0,0 +1,189 @@
1
+ # Copyright IBM Corporation 2025, 2026
2
+ # SPDX-License-Identifier: MIT
3
+
4
+
5
+ import logging
6
+
7
+ from orchestrator.core.discoveryspace.space import DiscoverySpace
8
+ from orchestrator.core.operation.config import FunctionOperationInfo
9
+ from orchestrator.core.operation.operation import OperationOutput
10
+ from orchestrator.modules.operators.collections import characterize_operation
11
+ from trim.trim_pydantic import (
12
+ TrimParameters,
13
+ ) # Importing this way works when the package is installed
14
+ from trim.utils.logging_utils import (
15
+ log_and_save_characterization,
16
+ log_unable_to_proceed_with_iterative_modeling_and_raise_error,
17
+ )
18
+ from trim.utils.space_df_connector import get_source_and_target
19
+
20
+ logger_trim = logging.getLogger(__name__)
21
+
22
+
23
+ @characterize_operation(
24
+ name="trim",
25
+ configuration_model=TrimParameters,
26
+ configuration_model_default=TrimParameters.defaultOperationParameters(),
27
+ description="""
28
+ Trim is used to characterise a Discovery space.
29
+ In its first implementation it starts from a space,
30
+ Retrieves all measured entities from the entity source and samples the others following a certain order.
31
+ If the number of measured entity is too small, Trim instantiates a no-priors characterization operation.
32
+ """,
33
+ )
34
+ def trim(
35
+ discoverySpace: DiscoverySpace = None, # type: ignore[name-defined]
36
+ operationInfo: FunctionOperationInfo | None = None,
37
+ **kwargs: object,
38
+ ) -> OperationOutput:
39
+ """
40
+ Execute the TRIM (Transfer Refined Iterative Modeling) operation on a discovery space.
41
+
42
+ TRIM characterizes a discovery space by first ensuring sufficient measured entities exist,
43
+ then performing iterative modeling to sample additional entities in an informed order.
44
+ If insufficient data exists, it runs a no-priors characterization first.
45
+
46
+ Args:
47
+ discoverySpace: The discovery space to characterize
48
+ operationInfo: Optional operation metadata
49
+ **kwargs: Additional parameters validated against TrimParameters model
50
+
51
+ Returns:
52
+ OperationOutput containing the operation resources and metadata
53
+ """
54
+ # Lazy import to avoid circular import issues during plugin loading
55
+ from orchestrator.modules.operators.randomwalk import (
56
+ CustomSamplerConfiguration,
57
+ RandomWalkParameters,
58
+ SamplerModuleConf,
59
+ random_walk,
60
+ )
61
+
62
+ params = TrimParameters.model_validate(kwargs)
63
+ logger_trim.info(
64
+ "Transfer Refined Iterative Modeling starts."
65
+ f"Target variable = {params.targetOutput}"
66
+ )
67
+ logger_trim.info(f"Parameters are {params}")
68
+
69
+ nopriors_module = SamplerModuleConf(
70
+ moduleClass="NoPriorsSampleSelector", moduleName="trim.no_priors_sampler"
71
+ )
72
+
73
+ # Checks if the source space has been already characterized appropriately
74
+ source_df, target_df = get_source_and_target(
75
+ discoverySpace, params.targetOutput, log_string="First query"
76
+ )
77
+ initial_source_space_size = len(source_df)
78
+
79
+ op_output_characterization_no_prior = OperationOutput.model_validate(
80
+ {
81
+ "metadata": {
82
+ "skipping operation": f"Prior source space characterization: {len(source_df)} sample. Minimal sample size: {params.samplingBudget.minPoints }"
83
+ }
84
+ }
85
+ )
86
+
87
+ if logger_trim.isEnabledFor(logging.DEBUG):
88
+ log_and_save_characterization(source_df, target_df)
89
+
90
+ if len(source_df) < params.samplingBudget.minPoints:
91
+ logger_trim.warning(
92
+ f"Only {len(source_df)} points in the source space.\n"
93
+ "Starting with no-prior characterization operation, "
94
+ f"it will sample {params.samplingBudget.minPoints - len(source_df)} points.\n"
95
+ f"Note: Trim sampler has been called with a minimum budget of {params.samplingBudget.minPoints} points."
96
+ )
97
+
98
+ no_priors_params = params.noPriorParameters
99
+ no_priors_sampler_config = CustomSamplerConfiguration(
100
+ module=nopriors_module, parameters=no_priors_params
101
+ )
102
+
103
+ no_priors_rwparams = RandomWalkParameters(
104
+ samplerConfig=no_priors_sampler_config,
105
+ # here you set up the rw params
106
+ batchSize=no_priors_params.batchSize,
107
+ numberEntities=no_priors_params.samples,
108
+ singleMeasurement=True,
109
+ )
110
+
111
+ op_output_characterization_no_prior = random_walk(
112
+ discoverySpace=discoverySpace,
113
+ operationInfo=FunctionOperationInfo.model_validate(
114
+ {
115
+ "metadata": {
116
+ "completed operation": "Characterization with no priors",
117
+ "summary of collected data": f"No-priors characterization produced {len(source_df)} samples with the required property {params.targetOutput}. Minimal sample size: {params.samplingBudget.minPoints }",
118
+ },
119
+ "actuatorConfigurationIdentifiers": operationInfo.actuatorConfigurationIdentifiers,
120
+ }
121
+ ),
122
+ **no_priors_rwparams.model_dump(),
123
+ )
124
+
125
+ source_df, target_df = get_source_and_target(
126
+ discoverySpace, params.targetOutput
127
+ )
128
+
129
+ if logger_trim.isEnabledFor(logging.DEBUG):
130
+ logger_trim.debug(
131
+ "Saving updated source space after no-priors characterization"
132
+ )
133
+ log_and_save_characterization(source_df, target_df)
134
+
135
+ if len(source_df) < params.samplingBudget.minPoints:
136
+ log_unable_to_proceed_with_iterative_modeling_and_raise_error(
137
+ discoverySpace,
138
+ target_output=params.targetOutput,
139
+ additional_info=f"This was detected during the no-priors characterization phase: {params.samplingBudget.minPoints - len(source_df)} out of {params.samplingBudget.minPoints}.",
140
+ )
141
+
142
+ # TRIM Iterative Modeling
143
+ trim_module = SamplerModuleConf(
144
+ moduleClass="TrimSampleSelector", # this is the name of our custom sampler class -> which I guess is CustomSequentialSampleSelector
145
+ moduleName="trim.trim_sampler", ### If CustomSequentialSampleSelector is imported as "from trim.trim_sampler import TrimSampleSelector" then this is correct
146
+ )
147
+ trim_sampler_config = CustomSamplerConfiguration(
148
+ module=trim_module, parameters=params
149
+ )
150
+ numberEntities_iterative_modeling = (
151
+ len(source_df) - initial_source_space_size
152
+ if op_output_characterization_no_prior.operation
153
+ else params.samplingBudget.maxPoints
154
+ )
155
+ trim_rwparams = RandomWalkParameters(
156
+ samplerConfig=trim_sampler_config,
157
+ batchSize=1,
158
+ numberEntities=numberEntities_iterative_modeling,
159
+ singleMeasurement=True,
160
+ )
161
+
162
+ op_output_iterative_modeling = random_walk(
163
+ discoverySpace=discoverySpace,
164
+ operationInfo=FunctionOperationInfo.model_validate(
165
+ {
166
+ "metadata": {"completed operation": "Iterative Modeling Operation"},
167
+ "actuatorConfigurationIdentifiers": operationInfo.actuatorConfigurationIdentifiers,
168
+ }
169
+ ),
170
+ **trim_rwparams.model_dump(),
171
+ )
172
+
173
+ logger_trim.info(
174
+ f"op_output_iterative_modeling.operation = {op_output_iterative_modeling.operation} "
175
+ )
176
+
177
+ if op_output_characterization_no_prior.operation:
178
+ return OperationOutput(
179
+ other=[],
180
+ resources=[
181
+ op_output_characterization_no_prior.operation,
182
+ op_output_iterative_modeling.operation,
183
+ ],
184
+ metadata={},
185
+ )
186
+
187
+ return OperationOutput(
188
+ other=[], resources=[op_output_iterative_modeling.operation], metadata={}
189
+ )