diff --git a/Microsoft.ML.sln b/Microsoft.ML.sln
index e491a54d2f..8f75429645 100644
--- a/Microsoft.ML.sln
+++ b/Microsoft.ML.sln
@@ -153,6 +153,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.SearchSpace",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ML.SearchSpace.Tests", "test\Microsoft.ML.SearchSpace.Tests\Microsoft.ML.SearchSpace.Tests.csproj", "{A3E9F25F-2718-4FF9-A35A-54C232A847AB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ML.AutoML.SourceGenerator", "tools-local\Microsoft.ML.AutoML.SourceGenerator\Microsoft.ML.AutoML.SourceGenerator.csproj", "{C804B990-390E-41D7-8FF1-6774495D70E2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -717,6 +719,14 @@ Global
{A3E9F25F-2718-4FF9-A35A-54C232A847AB}.Release|Any CPU.Build.0 = Release|Any CPU
{A3E9F25F-2718-4FF9-A35A-54C232A847AB}.Release|x64.ActiveCfg = Release|Any CPU
{A3E9F25F-2718-4FF9-A35A-54C232A847AB}.Release|x64.Build.0 = Release|Any CPU
+ {C804B990-390E-41D7-8FF1-6774495D70E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C804B990-390E-41D7-8FF1-6774495D70E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C804B990-390E-41D7-8FF1-6774495D70E2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C804B990-390E-41D7-8FF1-6774495D70E2}.Debug|x64.Build.0 = Debug|Any CPU
+ {C804B990-390E-41D7-8FF1-6774495D70E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C804B990-390E-41D7-8FF1-6774495D70E2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C804B990-390E-41D7-8FF1-6774495D70E2}.Release|x64.ActiveCfg = Release|Any CPU
+ {C804B990-390E-41D7-8FF1-6774495D70E2}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -792,6 +802,7 @@ Global
{8AFB8CC3-DA0B-4364-BFB3-296A7C54CC25} = {AED9C836-31E3-4F3F-8ABC-929555D3F3C4}
{A8F4F08F-1F9D-4AAE-8C8D-502CDBBDE7D3} = {09EADF06-BE25-4228-AB53-95AE3E15B530}
{A3E9F25F-2718-4FF9-A35A-54C232A847AB} = {AED9C836-31E3-4F3F-8ABC-929555D3F3C4}
+ {C804B990-390E-41D7-8FF1-6774495D70E2} = {7F13E156-3EBA-4021-84A5-CD56BA72F99E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {41165AF1-35BB-4832-A189-73060F82B01D}
diff --git a/src/Microsoft.ML.AutoML/API/ExperimentSettings.cs b/src/Microsoft.ML.AutoML/API/ExperimentSettings.cs
index 4ff9df0bae..8b54f697c4 100644
--- a/src/Microsoft.ML.AutoML/API/ExperimentSettings.cs
+++ b/src/Microsoft.ML.AutoML/API/ExperimentSettings.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.IO;
using System.Threading;
namespace Microsoft.ML.AutoML
diff --git a/src/Microsoft.ML.AutoML/CodeGen/apply_onnx_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/apply_onnx_search_space.json
new file mode 100644
index 0000000000..8cddde3c64
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/apply_onnx_search_space.json
@@ -0,0 +1,27 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "apply_onnx_model_option",
+ "search_space": [
+ {
+ "name": "ModelFile",
+ "type": "string"
+ },
+ {
+ "name": "GpuDeviceId",
+ "type": "integer"
+ },
+ {
+ "name": "FallbackToCpu",
+ "type": "boolean",
+ "default": false
+ },
+ {
+ "name": "OutputColumnName",
+ "type": "string"
+ },
+ {
+ "name": "InputColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/code_gen_flag.json b/src/Microsoft.ML.AutoML/CodeGen/code_gen_flag.json
new file mode 100644
index 0000000000..477ae9aa07
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/code_gen_flag.json
@@ -0,0 +1,7 @@
+{
+ "EstimatorFactoryGenerator": false,
+ "CodeGenCatalogGenerator": false,
+ "EstimatorTypeGenerator": false,
+ "SearchSpaceGenerator": true,
+ "SweepableEstimatorGenerator": false
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/concat_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/concat_search_space.json
new file mode 100644
index 0000000000..6f98a3069c
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/concat_search_space.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "concat_option",
+ "search_space": [
+ {
+ "name": "InputColumnNames",
+ "type": "strings"
+ },
+ {
+ "name": "OutputColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/extra_pixels_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/extra_pixels_search_space.json
new file mode 100644
index 0000000000..bad9158a0f
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/extra_pixels_search_space.json
@@ -0,0 +1,30 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "extract_pixels_option",
+ "search_space": [
+ {
+ "name": "OutputColumnName",
+ "type": "string",
+ "default": "Output"
+ },
+ {
+ "name": "InputColumnName",
+ "type": "string"
+ },
+ {
+ "name": "ColorsToExtract",
+ "type": "colorBits",
+ "default": "ColorBits.Rgb"
+ },
+ {
+ "name": "OrderOfExtraction",
+ "type": "colorsOrder",
+ "default": "ColorsOrder.ARGB"
+ },
+ {
+ "name": "OutputAsFloatArray",
+ "type": "boolean",
+ "default": true
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/fast_forest_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/fast_forest_search_space.json
new file mode 100644
index 0000000000..4e5cf1536b
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/fast_forest_search_space.json
@@ -0,0 +1,50 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "fast_forest_option",
+ "search_space": [
+ {
+ "name": "NumberOfTrees",
+ "type": "integer",
+ "default": 4,
+ "search_space": {
+ "min": 4,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "NumberOfLeaves",
+ "type": "integer",
+ "default": 4,
+ "search_space": {
+ "min": 4,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "FeatureFraction",
+ "type": "float",
+ "default": 1,
+ "search_space": {
+ "min": 2e-10,
+ "max": 1,
+ "log_base": false
+ }
+ },
+ {
+ "name": "LabelColumnName",
+ "type": "string",
+ "default": "Label"
+ },
+ {
+ "name": "FeatureColumnName",
+ "type": "string",
+ "default": "Feature"
+ },
+ {
+ "name": "ExampleWeightColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/fast_tree_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/fast_tree_search_space.json
new file mode 100644
index 0000000000..0a3af2790e
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/fast_tree_search_space.json
@@ -0,0 +1,80 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "fast_tree_option",
+ "search_space": [
+ {
+ "name": "NumberOfLeaves",
+ "type": "integer",
+ "default": 4,
+ "search_space": {
+ "log_base": true,
+ "min": 4,
+ "max": 32768
+ }
+ },
+ {
+ "name": "MinimumExampleCountPerLeaf",
+ "type": "integer",
+ "default": 20,
+ "search_space": {
+ "log_base": true,
+ "min": 2,
+ "max": 128
+ }
+ },
+ {
+ "name": "NumberOfTrees",
+ "type": "integer",
+ "default": 4,
+ "search_space": {
+ "min": 4,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "MaximumBinCountPerFeature",
+ "type": "integer",
+ "default": 256,
+ "search_space": {
+ "min": 8,
+ "max": 1024,
+ "log_base": true
+ }
+ },
+ {
+ "name": "FeatureFraction",
+ "type": "double",
+ "default": 1,
+ "search_space": {
+ "min": 2e-10,
+ "max": 1,
+ "log_base": false
+ }
+ },
+ {
+ "name": "LearningRate",
+ "type": "double",
+ "default": 0.1,
+ "search_space": {
+ "min": 2e-10,
+ "max": 1,
+ "log_base": true
+ }
+ },
+ {
+ "name": "LabelColumnName",
+ "type": "string",
+ "default": "Label"
+ },
+ {
+ "name": "FeatureColumnName",
+ "type": "string",
+ "default": "Feature"
+ },
+ {
+ "name": "ExampleWeightColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/featurize_text_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/featurize_text_search_space.json
new file mode 100644
index 0000000000..aaca712c65
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/featurize_text_search_space.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "featurize_text_option",
+ "search_space": [
+ {
+ "name": "InputColumnName",
+ "type": "string"
+ },
+ {
+ "name": "OutputColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/image_classification_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/image_classification_search_space.json
new file mode 100644
index 0000000000..0359ff78d0
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/image_classification_search_space.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "image_classification_option",
+ "search_space": [
+ {
+ "name": "LabelColumnName",
+ "type": "string",
+ "default": "Label"
+ },
+ {
+ "name": "ScoreColumnName",
+ "type": "string",
+ "default": "Score"
+ },
+ {
+ "name": "FeatureColumnName",
+ "type": "string",
+ "default": "Feature"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/lbfgs_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/lbfgs_search_space.json
new file mode 100644
index 0000000000..1aa3702448
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/lbfgs_search_space.json
@@ -0,0 +1,40 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "lbfgs_option",
+ "search_space": [
+ {
+ "name": "L1Regularization",
+ "type": "float",
+ "default": 1,
+ "search_space": {
+ "min": 0.03125,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "L2Regularization",
+ "type": "float",
+ "default": 1,
+ "search_space": {
+ "min": 0.03125,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "LabelColumnName",
+ "type": "string",
+ "default": "Label"
+ },
+ {
+ "name": "FeatureColumnName",
+ "type": "string",
+ "default": "Feature"
+ },
+ {
+ "name": "ExampleWeightColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/lgbm_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/lgbm_search_space.json
new file mode 100644
index 0000000000..2794e3c961
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/lgbm_search_space.json
@@ -0,0 +1,110 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "lgbm_option",
+ "search_space": [
+ {
+ "name": "NumberOfLeaves",
+ "type": "integer",
+ "default": 4,
+ "search_space": {
+ "log_base": true,
+ "max": 32768,
+ "min": 4
+ }
+ },
+ {
+ "name": "MinimumExampleCountPerLeaf",
+ "type": "integer",
+ "default": 20,
+ "search_space": {
+ "min": 20,
+ "max": 1024,
+ "log_base": true
+ }
+ },
+ {
+ "name": "LearningRate",
+ "type": "double",
+ "default": 1,
+ "search_space": {
+ "min": 2e-10,
+ "max": 1,
+ "log_base": true
+ }
+ },
+ {
+ "name": "NumberOfTrees",
+ "type": "integer",
+ "default": 4,
+ "search_space": {
+ "min": 4,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "SubsampleFraction",
+ "type": "double",
+ "default": 1,
+ "search_space": {
+ "min": 2e-10,
+ "max": 1,
+ "log_base": true
+ }
+ },
+ {
+ "name": "MaximumBinCountPerFeature",
+ "type": "integer",
+ "default": 256,
+ "search_space": {
+ "min": 8,
+ "max": 1024,
+ "log_base": true
+ }
+ },
+ {
+ "name": "FeatureFraction",
+ "type": "double",
+ "default": 1,
+ "search_space": {
+ "min": 2e-10,
+ "max": 1,
+ "log_base": false
+ }
+ },
+ {
+ "name": "L1Regularization",
+ "type": "double",
+ "default": 2e-10,
+ "search_space": {
+ "min": 2e-10,
+ "max": 1,
+ "log_base": true
+ }
+ },
+ {
+ "name": "L2Regularization",
+ "type": "double",
+ "default": 1,
+ "search_space": {
+ "min": 2e-10,
+ "max": 1,
+ "log_base": true
+ }
+ },
+ {
+ "name": "LabelColumnName",
+ "type": "string",
+ "default": "Label"
+ },
+ {
+ "name": "FeatureColumnName",
+ "type": "string",
+ "default": "Feature"
+ },
+ {
+ "name": "ExampleWeightColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/load_image_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/load_image_search_space.json
new file mode 100644
index 0000000000..2ef8ba27af
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/load_image_search_space.json
@@ -0,0 +1,19 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "load_image_option",
+ "search_space": [
+ {
+ "name": "OutputColumnName",
+ "type": "string",
+ "default": "Output"
+ },
+ {
+ "name": "ImageFolder",
+ "type": "string"
+ },
+ {
+ "name": "InputColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/map_key_to_value_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/map_key_to_value_search_space.json
new file mode 100644
index 0000000000..2c1b988a3b
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/map_key_to_value_search_space.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "map_key_to_value_option",
+ "search_space": [
+ {
+ "name": "OutputColumnName",
+ "type": "string"
+ },
+ {
+ "name": "InputColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/map_value_to_key_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/map_value_to_key_search_space.json
new file mode 100644
index 0000000000..6b52fa5bb4
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/map_value_to_key_search_space.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "map_value_to_key_option",
+ "search_space": [
+ {
+ "name": "OutputColumnName",
+ "type": "string"
+ },
+ {
+ "name": "InputColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/matrix_factorization_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/matrix_factorization_search_space.json
new file mode 100644
index 0000000000..af2302d06b
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/matrix_factorization_search_space.json
@@ -0,0 +1,54 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "matrix_factorization_option",
+ "search_space": [
+ {
+ "name": "LabelColumnName",
+ "type": "string",
+ "default": "Label"
+ },
+ {
+ "name": "MatrixColumnIndexColumnName",
+ "type": "string"
+ },
+ {
+ "name": "MatrixRowIndexColumnName",
+ "type": "string"
+ },
+ {
+ "name": "ApproximationRank",
+ "type": "integer",
+ "default": 20,
+ "search_space": {
+ "min": 10,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "LearningRate",
+ "type": "double",
+ "default": 1,
+ "search_space": {
+ "min": 2e-10,
+ "max": 1,
+ "log_base": true
+ }
+ },
+ {
+ "name": "NumberOfIterations",
+ "type": "integer",
+ "default": 128,
+ "search_space": {
+ "min": 4,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "Quiet",
+ "type": "boolean",
+ "default": true
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/naive_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/naive_search_space.json
new file mode 100644
index 0000000000..34faad6b26
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/naive_search_space.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "naive_option",
+ "search_space": [
+ {
+ "name": "LabelColumnName",
+ "type": "string",
+ "default": "Label"
+ },
+ {
+ "name": "ScoreColumnName",
+ "type": "string",
+ "default": "Score"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/normalize_min_max_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/normalize_min_max_search_space.json
new file mode 100644
index 0000000000..980d01a534
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/normalize_min_max_search_space.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "normalize_min_max_option",
+ "search_space": [
+ {
+ "name": "OutputColumnNames",
+ "type": "strings"
+ },
+ {
+ "name": "InputColumnNames",
+ "type": "strings"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/onehot_encoding_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/onehot_encoding_search_space.json
new file mode 100644
index 0000000000..e018023484
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/onehot_encoding_search_space.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "one_hot_option",
+ "search_space": [
+ {
+ "name": "OutputColumnNames",
+ "type": "strings"
+ },
+ {
+ "name": "InputColumnNames",
+ "type": "strings"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/replace_missing_value_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/replace_missing_value_search_space.json
new file mode 100644
index 0000000000..a633061160
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/replace_missing_value_search_space.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "replace_missing_value_option",
+ "search_space": [
+ {
+ "name": "OutputColumnNames",
+ "type": "strings"
+ },
+ {
+ "name": "InputColumnNames",
+ "type": "strings"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/resize_image_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/resize_image_search_space.json
new file mode 100644
index 0000000000..128fdbab3e
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/resize_image_search_space.json
@@ -0,0 +1,35 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "resize_image_option",
+ "search_space": [
+ {
+ "name": "OutputColumnName",
+ "type": "string",
+ "default": "Output"
+ },
+ {
+ "name": "InputColumnName",
+ "type": "string"
+ },
+ {
+ "name": "ImageHeight",
+ "type": "integer",
+ "default": 225
+ },
+ {
+ "name": "ImageWidth",
+ "type": "integer",
+ "default": 225
+ },
+ {
+ "name": "CropAnchor",
+ "type": "anchor",
+ "default": "Anchor.Center"
+ },
+ {
+ "name": "Resizing",
+ "type": "resizingKind",
+ "default": "ResizingKind.Fill"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/sdca_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/sdca_search_space.json
new file mode 100644
index 0000000000..a87bd47193
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/sdca_search_space.json
@@ -0,0 +1,40 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "sdca_option",
+ "search_space": [
+ {
+ "name": "L1Regularization",
+ "type": "float",
+ "default": 1,
+ "search_space": {
+ "min": 0.03125,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "L2Regularization",
+ "type": "float",
+ "default": 0.1,
+ "search_space": {
+ "min": 0.03125,
+ "max": 32768,
+ "log_base": true
+ }
+ },
+ {
+ "name": "LabelColumnName",
+ "type": "string",
+ "default": "Label"
+ },
+ {
+ "name": "FeatureColumnName",
+ "type": "string",
+ "default": "Feature"
+ },
+ {
+ "name": "ExampleWeightColumnName",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/search-space-schema.json b/src/Microsoft.ML.AutoML/CodeGen/search-space-schema.json
new file mode 100644
index 0000000000..224ea9a375
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/search-space-schema.json
@@ -0,0 +1,163 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema",
+ "title": "Search Space",
+ "definitions": {
+ "range": {
+ "type": "object",
+ "properties": {
+ "min": { "type": "number" },
+ "max": { "type": "number" },
+ "log_base": { "type": "boolean" }
+ },
+ "required": [ "min", "max" ]
+ },
+ "choice": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "oneOf": [
+ { "type": "string" },
+ { "type": "number" },
+ { "type": "integer" },
+ { "type": "boolean" }
+ ]
+ }
+ },
+ "required": [ "value" ]
+ },
+ "option": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/option_name"
+ },
+ "type": {
+ "$ref": "#/definitions/option_type"
+ },
+ "default": {
+ "oneOf": [
+ { "type": "string" },
+ { "type": "number" },
+ { "type": "boolean" }
+ ]
+ },
+ "search_space": {
+ "oneOf": [
+ { "$ref": "#/definitions/range" },
+ { "$ref": "#/definitions/choice" },
+ { "$ref": "#/definitions/nest_search_space" }
+ ]
+ }
+ },
+ "required": [ "name", "type" ]
+ },
+ "nest_search_space": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/option"
+ },
+ "minItems": 1
+ },
+ "search_space_name": {
+ "type": "string",
+ "enum": [
+ "lgbm_option",
+ "fast_tree_option",
+ "fast_forest_option",
+ "lbfgs_option",
+ "sdca_option",
+ "ssa_option",
+ "concat_option",
+ "naive_option",
+ "one_hot_option",
+ "one_hot_hash_option",
+ "load_raw_image_byte_option",
+ "copy_columns_option",
+ "hash_option",
+ "map_key_to_value_option",
+ "indicate_missing_value_option",
+ "replace_missing_value_option",
+ "normalize_min_max_option",
+ "featurize_text_option",
+ "convert_type_option",
+ "map_value_to_key_option",
+ "apply_onnx_model_option",
+ "resize_image_option",
+ "extract_pixels_option",
+ "load_image_option",
+ "image_classification_option",
+ "matrix_factorization_option"
+ ]
+ },
+ "option_name": {
+ "type": "string",
+ "enum": [
+ "NumberOfLeaves",
+ "MinimumExampleCountPerLeaf",
+ "LearningRate",
+ "NumberOfTrees",
+ "SubsampleFraction",
+ "MaximumBinCountPerFeature",
+ "FeatureFraction",
+ "L1Regularization",
+ "L2Regularization",
+ "LabelColumnName",
+ "FeatureColumnName",
+ "ExampleWeightColumnName",
+ "WindowSize",
+ "SeriesLength",
+ "TrainSize",
+ "Horizon",
+ "OutputColumnName",
+ "OutputColumnNames",
+ "InputColumnName",
+ "ConfidenceLowerBoundColumn",
+ "ConfidenceUpperBoundColumn",
+ "InputColumnNames",
+ "ModelFile",
+ "GpuDeviceId",
+ "FallbackToCpu",
+ "ScoreColumnName",
+ "ImageFolder",
+ "ImageWidth",
+ "ImageHeight",
+ "CropAnchor",
+ "Resizing",
+ "ColorsToExtract",
+ "OrderOfExtraction",
+ "MatrixColumnIndexColumnName",
+ "MatrixRowIndexColumnName",
+ "ApproximationRank",
+ "NumberOfIterations",
+ "Quiet",
+ "OutputAsFloatArray"
+ ]
+ },
+ "option_type": {
+ "type": "string",
+ "enum": [
+ "integer",
+ "float",
+ "double",
+ "string",
+ "strings",
+ "boolean",
+ "resizingKind",
+ "colorBits",
+ "colorsOrder",
+ "anchor"
+ ]
+ }
+ },
+
+ "type": "object",
+ "properties": {
+ "name": {
+ "$ref": "#/definitions/search_space_name"
+ },
+ "search_space": {
+ "$ref": "#/definitions/nest_search_space"
+ }
+ },
+ "required": [ "name", "search_space" ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/ssa_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/ssa_search_space.json
new file mode 100644
index 0000000000..05e6c97ffb
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/ssa_search_space.json
@@ -0,0 +1,52 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "ssa_option",
+ "search_space": [
+ {
+ "name": "WindowSize",
+ "type": "integer",
+ "default": 2,
+ "search_space": {
+ "min": 2,
+ "max": 32768,
+ "log_base": false
+ }
+ },
+ {
+ "name": "SeriesLength",
+ "type": "integer",
+ "default": 10,
+ "search_space": {
+ "min": 2,
+ "max": 32768,
+ "log_base": false
+ }
+ },
+ {
+ "name": "TrainSize",
+ "type": "integer",
+ "default": 100
+ },
+ {
+ "name": "Horizon",
+ "type": "integer",
+ "default": 10
+ },
+ {
+ "name": "OutputColumnName",
+ "type": "string"
+ },
+ {
+ "name": "InputColumnName",
+ "type": "string"
+ },
+ {
+ "name": "ConfidenceLowerBoundColumn",
+ "type": "string"
+ },
+ {
+ "name": "ConfidenceUpperBoundColumn",
+ "type": "string"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/CodeGen/type_converter_search_space.json b/src/Microsoft.ML.AutoML/CodeGen/type_converter_search_space.json
new file mode 100644
index 0000000000..d91293b857
--- /dev/null
+++ b/src/Microsoft.ML.AutoML/CodeGen/type_converter_search_space.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "./search-space-schema.json#",
+ "name": "convert_type_option",
+ "search_space": [
+ {
+ "name": "OutputColumnNames",
+ "type": "strings"
+ },
+ {
+ "name": "InputColumnNames",
+ "type": "strings"
+ }
+ ]
+}
diff --git a/src/Microsoft.ML.AutoML/ColumnInference/ColumnGroupingInference.cs b/src/Microsoft.ML.AutoML/ColumnInference/ColumnGroupingInference.cs
index 0f6b6e3c2d..a7c89f7875 100644
--- a/src/Microsoft.ML.AutoML/ColumnInference/ColumnGroupingInference.cs
+++ b/src/Microsoft.ML.AutoML/ColumnInference/ColumnGroupingInference.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using Microsoft.ML.Data;
using static Microsoft.ML.Data.TextLoader;
diff --git a/src/Microsoft.ML.AutoML/EstimatorExtensions/EstimatorExtensions.cs b/src/Microsoft.ML.AutoML/EstimatorExtensions/EstimatorExtensions.cs
index ff8fac6766..394336e6c1 100644
--- a/src/Microsoft.ML.AutoML/EstimatorExtensions/EstimatorExtensions.cs
+++ b/src/Microsoft.ML.AutoML/EstimatorExtensions/EstimatorExtensions.cs
@@ -3,8 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
-using Microsoft.ML.Data;
-using Microsoft.ML.Transforms;
namespace Microsoft.ML.AutoML
{
diff --git a/src/Microsoft.ML.AutoML/Experiment/Runners/CrossValRunner.cs b/src/Microsoft.ML.AutoML/Experiment/Runners/CrossValRunner.cs
index 84ca684bb5..402a6dd974 100644
--- a/src/Microsoft.ML.AutoML/Experiment/Runners/CrossValRunner.cs
+++ b/src/Microsoft.ML.AutoML/Experiment/Runners/CrossValRunner.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
diff --git a/src/Microsoft.ML.AutoML/Experiment/SuggestedTrainer.cs b/src/Microsoft.ML.AutoML/Experiment/SuggestedTrainer.cs
index 08a48c7ae2..ae1c98b242 100644
--- a/src/Microsoft.ML.AutoML/Experiment/SuggestedTrainer.cs
+++ b/src/Microsoft.ML.AutoML/Experiment/SuggestedTrainer.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML.Trainers;
diff --git a/src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj b/src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
index 83d749800c..7a87c44ac7 100644
--- a/src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
+++ b/src/Microsoft.ML.AutoML/Microsoft.ML.AutoML.csproj
@@ -5,25 +5,49 @@
netstandard2.0
Microsoft.ML.AutoML
ML.NET AutoML: Optimizes an ML pipeline for your dataset, by automatically locating the best feature engineering, model, and hyperparameters
+ $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage
-
+
+
all
+
+ all
+ true
+
-
+
all
-
+
all
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.ML.AutoML/PipelineSuggesters/PipelineSuggester.cs b/src/Microsoft.ML.AutoML/PipelineSuggesters/PipelineSuggester.cs
index fece093026..ccdcdbec7b 100644
--- a/src/Microsoft.ML.AutoML/PipelineSuggesters/PipelineSuggester.cs
+++ b/src/Microsoft.ML.AutoML/PipelineSuggesters/PipelineSuggester.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Microsoft.ML.Data;
using Microsoft.ML.Internal.Utilities;
using Microsoft.ML.Runtime;
diff --git a/src/Microsoft.ML.AutoML/TrainerExtensions/MultiTrainerExtensions.cs b/src/Microsoft.ML.AutoML/TrainerExtensions/MultiTrainerExtensions.cs
index d5643f79ff..8a18ce2e0b 100644
--- a/src/Microsoft.ML.AutoML/TrainerExtensions/MultiTrainerExtensions.cs
+++ b/src/Microsoft.ML.AutoML/TrainerExtensions/MultiTrainerExtensions.cs
@@ -4,7 +4,6 @@
using System.Collections.Generic;
using Microsoft.ML.Data;
-using Microsoft.ML.Runtime;
using Microsoft.ML.Trainers;
using Microsoft.ML.Trainers.FastTree;
using Microsoft.ML.Trainers.LightGbm;
diff --git a/src/Microsoft.ML.AutoML/TransformInference/TransformInference.cs b/src/Microsoft.ML.AutoML/TransformInference/TransformInference.cs
index 1d3384dd54..8a9bbbc728 100644
--- a/src/Microsoft.ML.AutoML/TransformInference/TransformInference.cs
+++ b/src/Microsoft.ML.AutoML/TransformInference/TransformInference.cs
@@ -7,7 +7,6 @@
using System.Linq;
using System.Text;
using Microsoft.ML.Data;
-using Microsoft.ML.Transforms;
namespace Microsoft.ML.AutoML
{
diff --git a/src/Microsoft.ML.AutoML/TransformInference/TransformInferenceApi.cs b/src/Microsoft.ML.AutoML/TransformInference/TransformInferenceApi.cs
index 4843f6ef7e..7fadcded71 100644
--- a/src/Microsoft.ML.AutoML/TransformInference/TransformInferenceApi.cs
+++ b/src/Microsoft.ML.AutoML/TransformInference/TransformInferenceApi.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
-using Microsoft.ML.Data;
namespace Microsoft.ML.AutoML
{
diff --git a/src/Microsoft.ML.SearchSpace/Microsoft.ML.SearchSpace.csproj b/src/Microsoft.ML.SearchSpace/Microsoft.ML.SearchSpace.csproj
index 022510e78a..0eb3260f6b 100644
--- a/src/Microsoft.ML.SearchSpace/Microsoft.ML.SearchSpace.csproj
+++ b/src/Microsoft.ML.SearchSpace/Microsoft.ML.SearchSpace.csproj
@@ -2,6 +2,7 @@
netstandard2.0
+ Microsoft.ML.AutoML
true
MSML_ContractsCheckMessageNotLiteralOrIdentifier
9.0
diff --git a/tools-local/Microsoft.ML.AutoML.SourceGenerator/Constant.cs b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Constant.cs
new file mode 100644
index 0000000000..055eda2500
--- /dev/null
+++ b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Constant.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.ML.AutoML.SourceGenerator
+{
+ internal class Constant
+ {
+ public const string CodeGeneratorNameSpace = "Microsoft.ML.AutoML.CodeGen";
+ }
+}
diff --git a/tools-local/Microsoft.ML.AutoML.SourceGenerator/Microsoft.ML.AutoML.SourceGenerator.csproj b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Microsoft.ML.AutoML.SourceGenerator.csproj
new file mode 100644
index 0000000000..2c1c9cb675
--- /dev/null
+++ b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Microsoft.ML.AutoML.SourceGenerator.csproj
@@ -0,0 +1,44 @@
+
+
+
+ netstandard2.0
+ 9.0
+ $(GetTargetPathDependsOn);GetDependencyTargetPaths
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ SearchSpace.tt
+
+
+
+
+
+ TextTemplatingFilePreprocessor
+ SearchSpace.cs
+
+
+
+
diff --git a/tools-local/Microsoft.ML.AutoML.SourceGenerator/SearchSpaceGenerator.cs b/tools-local/Microsoft.ML.AutoML.SourceGenerator/SearchSpaceGenerator.cs
new file mode 100644
index 0000000000..b36702c074
--- /dev/null
+++ b/tools-local/Microsoft.ML.AutoML.SourceGenerator/SearchSpaceGenerator.cs
@@ -0,0 +1,137 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using Microsoft.CodeAnalysis;
+using Microsoft.ML.AutoML.SourceGenerator.Template;
+
+namespace Microsoft.ML.AutoML.SourceGenerator
+{
+ [Generator]
+ public class SearchSpaceGenerator : ISourceGenerator
+ {
+ public void Execute(GeneratorExecutionContext context)
+ {
+ if (context.AdditionalFiles.Where(f => f.Path.Contains("code_gen_flag.json")).First() is AdditionalText text)
+ {
+ var json = text.GetText().ToString();
+ var flags = JsonSerializer.Deserialize>(json);
+ if (flags.TryGetValue(nameof(SearchSpaceGenerator), out var res) && res == false)
+ {
+ return;
+ }
+ }
+
+ var searchSpacesJson = context.AdditionalFiles.Where(f => f.Path.Contains("search_space.json"))
+ .Select(f => f.GetText().ToString())
+ .ToArray();
+ var searchSpacesJNodes = searchSpacesJson.Select(x => JsonNode.Parse(x));
+
+ foreach (var jNode in searchSpacesJNodes)
+ {
+ var className = Utils.ToTitleCase(jNode["name"].GetValue());
+ var searchSpaceJArray = jNode["search_space"].AsArray();
+ var options = searchSpaceJArray.Select(t =>
+ {
+ var optionName = Utils.ToTitleCase(t["name"].GetValue());
+ string optionTypeName = t["type"].GetValue() switch
+ {
+ "integer" => "int",
+ "float" => "float",
+ "double" => "double",
+ "string" => "string",
+ "boolean" => "bool",
+ "strings" => "string[]",
+ "resizingKind" => "ResizingKind",
+ "anchor" => "Anchor",
+ "colorBits" => "ColorBits",
+ "colorsOrder" => "ColorsOrder",
+ _ => throw new ArgumentException("unknown type"),
+ };
+
+ var defaultToken = t.AsObject().ContainsKey("default") ? t["default"] : null;
+ string optionDefaultValue = (defaultToken, optionTypeName) switch
+ {
+ (null, _) => string.Empty,
+ (_, "string") => $"\"{defaultToken.GetValue()}\"",
+ (_, "int") => $"{defaultToken.GetValue().ToString(CultureInfo.InvariantCulture)}",
+ (_, "double") => $"{defaultToken.GetValue().ToString(CultureInfo.InvariantCulture)}",
+ (_, "float") => $"{defaultToken.GetValue().ToString(CultureInfo.InvariantCulture)}F",
+ (_, "bool") => defaultToken.GetValue() ? "true" : "false",
+ (_, "Anchor") => defaultToken.GetValue(),
+ (_, "ResizingKind") => defaultToken.GetValue(),
+ (_, "ColorBits") => defaultToken.GetValue(),
+ (_, "ColorsOrder") => defaultToken.GetValue(),
+ (_, _) => throw new ArgumentException("unknown"),
+ };
+
+ var searchSpaceNode = t.AsObject().ContainsKey("search_space") ? t["search_space"] : null;
+ string optionAttribution = null;
+ if (searchSpaceNode is null)
+ {
+ // default option
+ optionAttribution = string.Empty;
+ }
+ else
+ {
+ var searchSpaceObject = searchSpaceNode.AsObject();
+ if (searchSpaceObject.ContainsKey("min"))
+ {
+ // range option
+ var minToken = searchSpaceNode["min"];
+ var minValue = searchSpaceNode["min"].GetValue();
+ var maxValue = searchSpaceNode["max"].GetValue();
+ var logBase = searchSpaceObject.ContainsKey("log_base") is false ? "false" : searchSpaceNode["log_base"].GetValue() ? "true" : "false";
+ optionAttribution = (optionTypeName, minValue, maxValue, logBase, optionDefaultValue) switch
+ {
+ ("int", _, _, _, null) => $"Range((int){Convert.ToInt32(minValue).ToString(CultureInfo.InvariantCulture)}, (int){Convert.ToInt32(maxValue).ToString(CultureInfo.InvariantCulture)}, logBase: {logBase.ToString(CultureInfo.InvariantCulture)})",
+ ("float", _, _, _, null) => $"Range((float){Convert.ToSingle(minValue).ToString(CultureInfo.InvariantCulture)}, (float){Convert.ToSingle(maxValue).ToString(CultureInfo.InvariantCulture)}, logBase: {logBase.ToString(CultureInfo.InvariantCulture)})",
+ ("double", _, _, _, null) => $"Range((double){minValue.ToString(CultureInfo.InvariantCulture)}, (double){maxValue.ToString(CultureInfo.InvariantCulture)}, logBase: {logBase.ToString(CultureInfo.InvariantCulture)})",
+ ("int", _, _, _, _) => $"Range((int){Convert.ToInt32(minValue).ToString(CultureInfo.InvariantCulture)}, (int){Convert.ToInt32(maxValue).ToString(CultureInfo.InvariantCulture)}, init: (int){optionDefaultValue.ToString(CultureInfo.InvariantCulture)}, logBase: {logBase.ToString(CultureInfo.InvariantCulture)})",
+ ("float", _, _, _, _) => $"Range((float){Convert.ToSingle(minValue).ToString(CultureInfo.InvariantCulture)}, (float){Convert.ToSingle(maxValue).ToString(CultureInfo.InvariantCulture)}, init: (float){optionDefaultValue.ToString(CultureInfo.InvariantCulture)}, logBase: {logBase.ToString(CultureInfo.InvariantCulture)})",
+ ("double", _, _, _, _) => $"Range((double){minValue.ToString(CultureInfo.InvariantCulture)}, (double){maxValue.ToString(CultureInfo.InvariantCulture)}, init: (double){optionDefaultValue.ToString(CultureInfo.InvariantCulture)}, logBase: {logBase.ToString(CultureInfo.InvariantCulture)})",
+ _ => throw new NotImplementedException(),
+ };
+ optionAttribution = $"[{optionAttribution}]";
+ }
+ else
+ {
+ // choice option
+ var values = searchSpaceNode["value"].GetValue();
+ var valuesParam = optionTypeName switch
+ {
+ "int" => $"new object[]{{ {string.Join(",", values)} }}",
+ "boolean" => $"new object[]{{ {string.Join(",", values)} }}",
+ "string" => $"new object[]{{ {string.Join(",", values.Select(x => $"\"{x}\""))} }}",
+ _ => throw new NotImplementedException("only support int|boolean|string"),
+ };
+
+ optionAttribution = optionDefaultValue == null ? $"[Choice({valuesParam})]" : $"[Choice({valuesParam}, {optionDefaultValue})]";
+ }
+ }
+
+ return (optionTypeName, optionName, optionAttribution, optionDefaultValue);
+ });
+
+ var code = new SearchSpace()
+ {
+ NameSpace = Constant.CodeGeneratorNameSpace,
+ ClassName = className,
+ Properties = options,
+ }.TransformText();
+
+ context.AddSource($"{className}.cs", code);
+ }
+ }
+
+ public void Initialize(GeneratorInitializationContext context)
+ {
+ }
+ }
+}
diff --git a/tools-local/Microsoft.ML.AutoML.SourceGenerator/Template/SearchSpace.cs b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Template/SearchSpace.cs
new file mode 100644
index 0000000000..141ffeff1e
--- /dev/null
+++ b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Template/SearchSpace.cs
@@ -0,0 +1,347 @@
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version: 17.0.0.0
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+namespace Microsoft.ML.AutoML.SourceGenerator.Template
+{
+ using System.Linq;
+ using System.Text;
+ using System.Collections.Generic;
+ using System;
+
+ ///
+ /// Class to produce the template output
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ internal partial class SearchSpace : SearchSpaceBase
+ {
+ ///
+ /// Create the template output
+ ///
+ public virtual string TransformText()
+ {
+ this.Write(@"
+using Microsoft.ML.SearchSpace;
+using OptionAttribute = Microsoft.ML.SearchSpace.OptionAttribute;
+using ColorsOrder = Microsoft.ML.Transforms.Image.ImagePixelExtractingEstimator.ColorsOrder;
+using ColorBits = Microsoft.ML.Transforms.Image.ImagePixelExtractingEstimator.ColorBits;
+using ResizingKind = Microsoft.ML.Transforms.Image.ImageResizingEstimator.ResizingKind;
+using Anchor = Microsoft.ML.Transforms.Image.ImageResizingEstimator.Anchor;
+
+#nullable enable
+
+namespace ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(NameSpace));
+ this.Write("\r\n{\r\n public class ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(ClassName));
+ this.Write("\r\n {\r\n");
+foreach((var optionType, var optionName, var optionAttribution, var defaultValue) in Properties){
+ this.Write(" ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(optionAttribution));
+ this.Write("\r\n");
+if(defaultValue == string.Empty){
+ this.Write(" public ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(optionType));
+ this.Write("? ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(optionName));
+ this.Write(" {get; set;}\r\n");
+}else{
+ this.Write(" [System.Diagnostics.CodeAnalysis.SuppressMessage(\"Declaration\", \"MSML_NoI" +
+ "nstanceInitializers:No initializers on instance fields or properties\")]\r\n " +
+ " public ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(optionType));
+ this.Write(" ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(optionName));
+ this.Write(" {get; set;} = ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(defaultValue));
+ this.Write(";\r\n");
+}
+ this.Write("\r\n");
+}
+ this.Write("\r\n }\r\n}\r\n\r\n");
+ return this.GenerationEnvironment.ToString();
+ }
+
+public string NameSpace {get;set;}
+public string ClassName {get;set;}
+public IEnumerable<(string, string, string, string)> Properties {get; set;}
+
+ }
+ #region Base class
+ ///
+ /// Base class for this transformation
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ internal class SearchSpaceBase
+ {
+ #region Fields
+ private global::System.Text.StringBuilder generationEnvironmentField;
+ private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
+ private global::System.Collections.Generic.List indentLengthsField;
+ private string currentIndentField = "";
+ private bool endsWithNewline;
+ private global::System.Collections.Generic.IDictionary sessionField;
+ #endregion
+ #region Properties
+ ///
+ /// The string builder that generation-time code is using to assemble generated output
+ ///
+ protected System.Text.StringBuilder GenerationEnvironment
+ {
+ get
+ {
+ if ((this.generationEnvironmentField == null))
+ {
+ this.generationEnvironmentField = new global::System.Text.StringBuilder();
+ }
+ return this.generationEnvironmentField;
+ }
+ set
+ {
+ this.generationEnvironmentField = value;
+ }
+ }
+ ///
+ /// The error collection for the generation process
+ ///
+ public System.CodeDom.Compiler.CompilerErrorCollection Errors
+ {
+ get
+ {
+ if ((this.errorsField == null))
+ {
+ this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
+ }
+ return this.errorsField;
+ }
+ }
+ ///
+ /// A list of the lengths of each indent that was added with PushIndent
+ ///
+ private System.Collections.Generic.List indentLengths
+ {
+ get
+ {
+ if ((this.indentLengthsField == null))
+ {
+ this.indentLengthsField = new global::System.Collections.Generic.List();
+ }
+ return this.indentLengthsField;
+ }
+ }
+ ///
+ /// Gets the current indent we use when adding lines to the output
+ ///
+ public string CurrentIndent
+ {
+ get
+ {
+ return this.currentIndentField;
+ }
+ }
+ ///
+ /// Current transformation session
+ ///
+ public virtual global::System.Collections.Generic.IDictionary Session
+ {
+ get
+ {
+ return this.sessionField;
+ }
+ set
+ {
+ this.sessionField = value;
+ }
+ }
+ #endregion
+ #region Transform-time helpers
+ ///
+ /// Write text directly into the generated output
+ ///
+ public void Write(string textToAppend)
+ {
+ if (string.IsNullOrEmpty(textToAppend))
+ {
+ return;
+ }
+ // If we're starting off, or if the previous text ended with a newline,
+ // we have to append the current indent first.
+ if (((this.GenerationEnvironment.Length == 0)
+ || this.endsWithNewline))
+ {
+ this.GenerationEnvironment.Append(this.currentIndentField);
+ this.endsWithNewline = false;
+ }
+ // Check if the current text ends with a newline
+ if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
+ {
+ this.endsWithNewline = true;
+ }
+ // This is an optimization. If the current indent is "", then we don't have to do any
+ // of the more complex stuff further down.
+ if ((this.currentIndentField.Length == 0))
+ {
+ this.GenerationEnvironment.Append(textToAppend);
+ return;
+ }
+ // Everywhere there is a newline in the text, add an indent after it
+ textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
+ // If the text ends with a newline, then we should strip off the indent added at the very end
+ // because the appropriate indent will be added when the next time Write() is called
+ if (this.endsWithNewline)
+ {
+ this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
+ }
+ else
+ {
+ this.GenerationEnvironment.Append(textToAppend);
+ }
+ }
+ ///
+ /// Write text directly into the generated output
+ ///
+ public void WriteLine(string textToAppend)
+ {
+ this.Write(textToAppend);
+ this.GenerationEnvironment.AppendLine();
+ this.endsWithNewline = true;
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void Write(string format, params object[] args)
+ {
+ this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void WriteLine(string format, params object[] args)
+ {
+ this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Raise an error
+ ///
+ public void Error(string message)
+ {
+ System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
+ error.ErrorText = message;
+ this.Errors.Add(error);
+ }
+ ///
+ /// Raise a warning
+ ///
+ public void Warning(string message)
+ {
+ System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
+ error.ErrorText = message;
+ error.IsWarning = true;
+ this.Errors.Add(error);
+ }
+ ///
+ /// Increase the indent
+ ///
+ public void PushIndent(string indent)
+ {
+ if ((indent == null))
+ {
+ throw new global::System.ArgumentNullException("indent");
+ }
+ this.currentIndentField = (this.currentIndentField + indent);
+ this.indentLengths.Add(indent.Length);
+ }
+ ///
+ /// Remove the last indent that was added with PushIndent
+ ///
+ public string PopIndent()
+ {
+ string returnValue = "";
+ if ((this.indentLengths.Count > 0))
+ {
+ int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
+ this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
+ if ((indentLength > 0))
+ {
+ returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
+ this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
+ }
+ }
+ return returnValue;
+ }
+ ///
+ /// Remove any indentation
+ ///
+ public void ClearIndent()
+ {
+ this.indentLengths.Clear();
+ this.currentIndentField = "";
+ }
+ #endregion
+ #region ToString Helpers
+ ///
+ /// Utility class to produce culture-oriented representation of an object as a string.
+ ///
+ public class ToStringInstanceHelper
+ {
+ private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
+ ///
+ /// Gets or sets format provider to be used by ToStringWithCulture method.
+ ///
+ public System.IFormatProvider FormatProvider
+ {
+ get
+ {
+ return this.formatProviderField ;
+ }
+ set
+ {
+ if ((value != null))
+ {
+ this.formatProviderField = value;
+ }
+ }
+ }
+ ///
+ /// This is called from the compile/run appdomain to convert objects within an expression block to a string
+ ///
+ public string ToStringWithCulture(object objectToConvert)
+ {
+ if ((objectToConvert == null))
+ {
+ throw new global::System.ArgumentNullException("objectToConvert");
+ }
+ System.Type t = objectToConvert.GetType();
+ System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
+ typeof(System.IFormatProvider)});
+ if ((method == null))
+ {
+ return objectToConvert.ToString();
+ }
+ else
+ {
+ return ((string)(method.Invoke(objectToConvert, new object[] {
+ this.formatProviderField })));
+ }
+ }
+ }
+ private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
+ ///
+ /// Helper to produce culture-oriented representation of an object as a string
+ ///
+ public ToStringInstanceHelper ToStringHelper
+ {
+ get
+ {
+ return this.toStringHelperField;
+ }
+ }
+ #endregion
+ }
+ #endregion
+}
diff --git a/tools-local/Microsoft.ML.AutoML.SourceGenerator/Template/SearchSpace.tt b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Template/SearchSpace.tt
new file mode 100644
index 0000000000..8bf28cc1b0
--- /dev/null
+++ b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Template/SearchSpace.tt
@@ -0,0 +1,38 @@
+<#@ template language="C#" linePragmas="false" visibility = "internal" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+
+using Microsoft.ML.SearchSpace;
+using OptionAttribute = Microsoft.ML.SearchSpace.OptionAttribute;
+using ColorsOrder = Microsoft.ML.Transforms.Image.ImagePixelExtractingEstimator.ColorsOrder;
+using ColorBits = Microsoft.ML.Transforms.Image.ImagePixelExtractingEstimator.ColorBits;
+using ResizingKind = Microsoft.ML.Transforms.Image.ImageResizingEstimator.ResizingKind;
+using Anchor = Microsoft.ML.Transforms.Image.ImageResizingEstimator.Anchor;
+
+#nullable enable
+
+namespace <#=NameSpace#>
+{
+ public class <#=ClassName#>
+ {
+<#foreach((var optionType, var optionName, var optionAttribution, var defaultValue) in Properties){#>
+ <#=optionAttribution#>
+<#if(defaultValue == string.Empty){#>
+ public <#=optionType#>? <#=optionName#> {get; set;}
+<#}else{#>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Declaration", "MSML_NoInstanceInitializers:No initializers on instance fields or properties")]
+ public <#=optionType#> <#=optionName#> {get; set;} = <#=defaultValue#>;
+<#}#>
+
+<#}#>
+
+ }
+}
+
+<#+
+public string NameSpace {get;set;}
+public string ClassName {get;set;}
+public IEnumerable<(string, string, string, string)> Properties {get; set;}
+#>
\ No newline at end of file
diff --git a/tools-local/Microsoft.ML.AutoML.SourceGenerator/Utils.cs b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Utils.cs
new file mode 100644
index 0000000000..ab77f56e97
--- /dev/null
+++ b/tools-local/Microsoft.ML.AutoML.SourceGenerator/Utils.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Microsoft.ML.AutoML.SourceGenerator
+{
+ internal class Utils
+ {
+ public static string CapitalFirstLetter(string str)
+ {
+ if (str == null)
+ return null;
+
+ if (str.Length > 1)
+ return char.ToUpper(str[0]) + str.Substring(1);
+
+ return str.ToUpper();
+ }
+
+ public static string PrettyPrintListOfString(IEnumerable strs)
+ {
+ // ["str1", "str2", "str3"] => "\"str1\", \"str2\", \"str3\""
+ var sb = new StringBuilder();
+ foreach (var str in strs)
+ {
+ sb.Append($"\"{str}\"");
+ sb.Append(", ");
+ }
+
+ return sb.ToString();
+ }
+
+ public static string ToTitleCase(string str)
+ {
+ return string.Join(string.Empty, str.Split('_', ' ', '-').Select(x => CapitalFirstLetter(x)));
+ }
+ }
+}