From 88bf9006fc168173cc457b7fab08df0229bd4b8b Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Fri, 19 Sep 2025 00:46:31 -0700 Subject: [PATCH 01/18] Structured ML Functions --- .gitignore | 2 + src/ml_functions/CMakeLists.txt | 9 +- src/ml_functions/matrix_multiplication.cpp | 255 +++++++++++++++++++++ src/ml_functions/min_max_scaler.cpp | 103 +++++++++ src/ml_functions/ml_functions_scalar.cpp | 224 +----------------- src/ml_functions/one_hot_encoder.cpp | 0 test/sql/cactusdb.test | 56 +++-- 7 files changed, 416 insertions(+), 233 deletions(-) create mode 100644 src/ml_functions/matrix_multiplication.cpp create mode 100644 src/ml_functions/min_max_scaler.cpp create mode 100644 src/ml_functions/one_hot_encoder.cpp diff --git a/.gitignore b/.gitignore index b9f264b..ca1efe4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ duckdb_unittest_tempdir/ testext test/python/__pycache__/ .Rhistory +*.csv +vcpkg/ \ No newline at end of file diff --git a/src/ml_functions/CMakeLists.txt b/src/ml_functions/CMakeLists.txt index 5d5c838..e113310 100644 --- a/src/ml_functions/CMakeLists.txt +++ b/src/ml_functions/CMakeLists.txt @@ -1,4 +1,11 @@ +set(ML_FUNCTIONS_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/ml_functions_scalar.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/matrix_multiplication.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/min_max_scaler.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/one_hot_encoder.cpp +) + set(EXTENSION_SOURCES ${EXTENSION_SOURCES} - ${CMAKE_CURRENT_SOURCE_DIR}/ml_functions_scalar.cpp + ${ML_FUNCTIONS_SRCS} PARENT_SCOPE) diff --git a/src/ml_functions/matrix_multiplication.cpp b/src/ml_functions/matrix_multiplication.cpp new file mode 100644 index 0000000..72db1de --- /dev/null +++ b/src/ml_functions/matrix_multiplication.cpp @@ -0,0 +1,255 @@ +#include +#include +#include +#include +#include +#include "functions.hpp" +#include "duckdb.hpp" +#include "duckdb/common/types/value.hpp" +#include "duckdb/common/types.hpp" +#include "duckdb/common/enum_util.hpp" +#include "duckdb/common/exception.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/function/scalar_function.hpp" +#include +#include "duckdb/common/constants.hpp" +#include "duckdb/common/types/blob.hpp" +#include "duckdb/common/vector_operations/generic_executor.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/common/vector_operations/septenary_executor.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" + +namespace duckdb { + +struct ML_MatrixMultiply { + +public: + // ------------------------- + // Helpers + // ------------------------- + static void ParseCSVWeights(const std::string &path, + std::vector &W, idx_t &k, idx_t &n) { + std::ifstream f(path); + if (!f.is_open()) { + throw InvalidInputException("matmul: cannot open weights file: %s", path.c_str()); + } + W.clear(); + k = 0; + + bool have_n = false; // <- replace the sentinel + n = 0; + + std::string line; + while (std::getline(f, line)) { + if (line.empty()) continue; + + std::stringstream ss(line); + std::string cell; + idx_t col_count = 0; + + while (std::getline(ss, cell, ',')) { + auto l = cell.find_first_not_of(" \t\r\n"); + auto r = cell.find_last_not_of(" \t\r\n"); + std::string trimmed = (l == std::string::npos) ? "" : cell.substr(l, r - l + 1); + + if (trimmed.empty()) { + throw InvalidInputException("matmul: empty field in weights file: %s", path.c_str()); + } + try { + W.emplace_back(std::stod(trimmed)); + } catch (...) { + throw InvalidInputException("matmul: non-numeric weight '%s' in %s", + trimmed.c_str(), path.c_str()); + } + col_count++; + } + + if (col_count == 0) continue; + + if (!have_n) { + n = col_count; + have_n = true; + } else if (n != col_count) { + throw InvalidInputException( + "matmul: ragged row in weights file %s (got %llu cols, expected %llu)", + path.c_str(), + (unsigned long long)col_count, + (unsigned long long)n + ); + } + k++; + } + + if (k == 0 || !have_n) { + throw InvalidInputException("matmul: empty weights file: %s", path.c_str()); + } + if (W.size() != (size_t)(k * n)) { + throw InternalException("matmul: internal size mismatch after parsing %s", path.c_str()); + } + } + + + + // ------------------------- + // Bind Data + // ------------------------- + // add binding structure here + struct BindData final : public FunctionData { + std::vector weights; // row-major [k * n] + idx_t k = 0; // rows in weights (input length) + idx_t n = 0; // cols in weights (output length) + std::string weights_file; + bool has_bound_weights = false; + + BindData() = default; + + BindData(const std::vector &w, idx_t k_, idx_t n_, + const std::string &file, bool bound) + : weights(w), k(k_), n(n_), weights_file(file), has_bound_weights(bound) {} + + unique_ptr Copy() const override { + // deep copy (vector/string copy is deep) + return make_uniq(weights, k, n, weights_file, has_bound_weights); + } + + bool Equals(const FunctionData &other_p) const override { + auto &o = other_p.Cast(); + return has_bound_weights == o.has_bound_weights && + k == o.k && n == o.n && + weights_file == o.weights_file && + weights == o.weights; + } + }; + + + // add binding method here + static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + // Expect: x LIST, filename VARCHAR + if (args.size() != 2) { + throw BinderException("matmul expects 2 arguments: (x LIST, weights_file VARCHAR)"); + } + + // Force filename to be constant; fold it at bind time + if (!args[1]->IsFoldable()) { + throw BinderException("matmul: weights_file must be a constant string"); + } + + auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); + if (vFile.IsNull()) { + throw BinderException("matmul: weights_file is NULL"); + } + const std::string path = vFile.ToString(); + + std::vector W; + idx_t K = 0, N = 0; + ParseCSVWeights(path, W, K, N); + + // Erase filename argument so execution only receives x + Function::EraseArgument(bound_function, args, 1); + + return make_uniq(W, K, N, path, /*bound*/ true); + } + + // ------------------------- + // Execute + // ------------------------- + static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { + + idx_t count = args.size(); //number of tuples in a DataChunk + + // Read Left Matrix from the argument + Vector &lhs = args.data[0]; + UnifiedVectorFormat lhs_uvf; + lhs.ToUnifiedFormat(count,lhs_uvf); + const auto *entries = UnifiedVectorFormat::GetData(lhs_uvf); // Holds the entries {offset, length}for each row + + auto &child = ListVector::GetEntry(lhs); // pointer to child reference that actually holds the list + const idx_t total_elems = ListVector::GetListSize(lhs); + UnifiedVectorFormat child_uvf; + child.ToUnifiedFormat(total_elems, child_uvf); + const double *child_data = UnifiedVectorFormat::GetData(child_uvf); // from this child using the offset and length of the parent unified vector we can get the individual elements. + + Eigen::Matrix X; + idx_t columns = -1; + + // Check the selectivity and create matrix of only selected rows + for(idx_t i = 0; i < count; i++){ + idx_t idx = lhs_uvf.sel->get_index(i); + if(lhs_uvf.validity.RowIsValid(idx)){ + idx_t c_ = entries[idx].length; + if(i == 0){ + columns = c_; + X.resize((Eigen::Index)count, (Eigen::Index)columns); + } + else { + if(columns != c_){ + throw InvalidInputException("Input Matrix has uneven rows. Error at row %lld",(unsigned long long) i); + } + } + const double *row_ptr = child_data + entries[idx].offset; + std::memcpy(X.data() + i * columns, row_ptr, sizeof(double) * (size_t)columns); + } + } + + // Prepare weight matrix using the Bound Data + const auto &func_expr = state.expr.Cast(); + const auto &bd = func_expr.bind_info->Cast(); + const idx_t k = bd.k, n = bd.n; + const double *Wbuf = bd.weights.data(); + using RowMat = Eigen::Matrix; + Eigen::Map W(bd.weights.data(), (Eigen::Index)bd.k, (Eigen::Index)bd.n); + + // Matrix Multiplication of a chunk of rows + Eigen::Matrix Y = X * W; + + // Prepare result in a FlatVector + // Prepare its parent vector by setting the offset and length in the entries and set the data in child + // Use the Left matrix to check if the row should be null or not using similar selectivity logic. + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + + const idx_t total = count * n; + ListVector::Reserve(result, total); + ListVector::SetListSize(result, total); + double *out = FlatVector::GetData(res_child); + auto &res_valid = FlatVector::Validity(result); + idx_t cursor = 0; + for (idx_t i = 0; i < count; ++i) { + idx_t idx = lhs_uvf.sel->get_index(i); + if(!lhs_uvf.validity.RowIsValid(idx)){ + res_entries[i] = {0,0}; + res_valid.Set(i,false); + } + res_entries[i].offset = cursor; + res_entries[i].length = n; + std::memcpy(out + cursor, Y.data() + i * n, sizeof(double) * (size_t)n); + cursor += n; + } + } + + static void Register(ExtensionLoader &loader) { + // Logical signature with filename; Bind erases it so Exec sees only x. + ScalarFunction fn( + "matmul", + { LogicalType::LIST(LogicalType::DOUBLE), // x + LogicalType::VARCHAR }, // weights_file + LogicalType::LIST(LogicalType::DOUBLE), + Execute + ); + fn.bind = Bind; + loader.RegisterFunction(fn); +} + +}; + +// void RegisterMLScalarFunctions(ExtensionLoader &loader) { + +// ML_MatrixMultiply::Register(loader); + +// } + +} // namespace duckdb \ No newline at end of file diff --git a/src/ml_functions/min_max_scaler.cpp b/src/ml_functions/min_max_scaler.cpp new file mode 100644 index 0000000..8b94247 --- /dev/null +++ b/src/ml_functions/min_max_scaler.cpp @@ -0,0 +1,103 @@ +#include "functions.hpp" +#include "duckdb.hpp" + +namespace duckdb { + struct ML_MinMaxScaler { + public: + // ------------------------- + // Helpers + // ------------------------- + + // ------------------------- + // Bind Data + // ------------------------- + struct BindData final : public FunctionData { + std::vector min; // min values for each column + std::vector max; // max values for each column + idx_t cols = 0; // number of columns + std::string min_max_file; + bool has_bound_min_max = false; + + BindData() = default; + + BindData(const std::vector &min_, const std::vector &max_, idx_t cols_, + const std::string &file, bool bound) + : min(min_), max(max_), cols(cols_), min_max_file(file), has_bound_min_max(bound) {} + + unique_ptr Copy() const override { + // deep copy (vector/string copy is deep) + return make_uniq(min, max, cols, min_max_file, has_bound_min_max); + } + + bool Equals(const FunctionData &other_p) const override { + auto &o = other_p.Cast(); + return has_bound_min_max == o.has_bound_min_max && + cols == o.cols && + min_max_file == o.min_max_file && + min == o.min && + max == o.max; + } + }; + + // ------------------------- + // Bind Functions + // ------------------------- + static unique_ptr Bind_List(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + // Expecting 4 arguments: x, min_list, max_list, no_of_columns + if (args.size() != 4) { + throw InvalidInputException("min_max_scaler with list arguments expects 4 arguments: x, min_list, max_list, no_of_columns"); + } + //TODO + + } + + static unique_ptr Bind_File(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + // Expecting 2 arguments: x, min_max_file + if (args.size() != 2) { + throw InvalidInputException("min_max_scaler with file argument expects 2 arguments: x, min_max_file"); + } + //TODO + } + + // ------------------------- + // Execute + // ------------------------- + static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { + //TODO + } + + // ------------------------- + // Register + // ------------------------- + static void Register(ExtensionLoader &loader) { + // Logical signature with filename; Bind erases it so Exec sees only x. + ScalerFunctionSet set("min_max_scaler"); + ScalerFunction fn_list( + { LogicalType::LIST(LogicalType::DOUBLE), //x + LogicalType::LIST(LogicalType::DOUBLE), //min + LogicalType::LIST(LogicalType::DOUBLE), //max + LogicalType::idx_t }, //cols //PARAMETERS MIN_LIST, MAX_LIST, NO_OF_COLUMNS + LogicalType::LIST(LogicalType::DOUBLE), //return type + Execute + ); + fn_list.bind = Bind_List; + set.AddFunction(fn_list); + + ScalerFunction fn_file( + { LogicalType::LIST(LogicalType::DOUBLE), //x + LogicalType::VARCHAR }, //min_max_file + LogicalType::LIST(LogicalType::DOUBLE), //return type + Execute + ); + fn_file.bind = Bind_File; + set.AddFunction(fn_file); + + loader.RegisterFunction(set); + } + + }; +} \ No newline at end of file diff --git a/src/ml_functions/ml_functions_scalar.cpp b/src/ml_functions/ml_functions_scalar.cpp index 7a00bcd..ec5977d 100644 --- a/src/ml_functions/ml_functions_scalar.cpp +++ b/src/ml_functions/ml_functions_scalar.cpp @@ -1,224 +1,16 @@ -#include -#include -#include "functions.hpp" -#include "function_builder.hpp" #include "duckdb.hpp" -#include "duckdb/common/types/value.hpp" -#include "duckdb/common/types.hpp" -#include "duckdb/common/enum_util.hpp" -#include "duckdb/common/exception.hpp" -#include "duckdb/common/string_util.hpp" -#include "duckdb/function/scalar_function.hpp" -#include -#include "duckdb/common/constants.hpp" -#include "duckdb/common/types/blob.hpp" -#include "duckdb/common/vector_operations/generic_executor.hpp" -#include "duckdb/execution/expression_executor.hpp" -#include "duckdb/planner/expression/bound_function_expression.hpp" -#include "duckdb/common/vector_operations/septenary_executor.hpp" -#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "matrix_multiplication.cpp" +#include "min_max_scaler.cpp" +// #include "one_hot_encoder.cpp" namespace duckdb { -class MatrixData final : public FunctionData { - -public: - unsigned int num_rows_; - unsigned int num_columns_; - - bool use_gpu_; - - explicit MatrixData(int num_rows, int num_columns, bool use_gpu) { - num_rows_ = num_rows; - num_columns_ = num_columns; - use_gpu_ = use_gpu; - } - - unique_ptr Copy() const override { - return make_uniq(num_rows_, num_columns_, use_gpu_); - } - - bool Equals(const FunctionData &other) const override { - auto &other_data = other.Cast(); - return num_rows_ == other_data.num_rows_ && num_columns_ == other_data.num_columns_ && - use_gpu_ == other_data.use_gpu_; - } -}; - -class MatrixDataByPointer final : public FunctionData { - -public: - float *weights_; - unsigned int num_rows_; - unsigned int num_columns_; - bool use_gpu_; - - explicit MatrixDataByPointer(float *weights, int num_rows, int num_columns, bool use_gpu) { - weights_ = new float[num_rows * num_columns]; - std::memcpy(weights_, weights, num_rows * num_columns * sizeof(float)); - num_rows_ = num_rows; - num_columns_ = num_columns; - use_gpu_ = use_gpu; - } - - unique_ptr Copy() const override { - return make_uniq(weights_, num_rows_, num_columns_, use_gpu_); - } - - bool Equals(const FunctionData &other) const override { - auto &other_data = other.Cast(); - return num_rows_ == other_data.num_rows_ && num_columns_ == other_data.num_columns_ && - weights_ == other_data.weights_ && use_gpu_ == other_data.use_gpu_; - } -}; - -/* -static unique_ptr MatrixBindByPointer(ClientContext &context, ScalarFunction &bound_function, - vector> &arguments) { - - const auto expr0 = ExpressionExecutor::EvaluateScalar(context, *arguments[0]); - const auto weights_value = expr0.GetPointer(); - const auto expr1 = ExpressionExecutor::EvaluateScalar(context, *arguments[1]); - const auto num_rows_value = expr1.GetValue(); - const auto expr2 = ExpressionExecutor::EvaluateScalar(context, *arguments[2]); - const auto num_columns_value = expr2.GetValue(); - const auto expr3 = ExpressionExecutor::EvaluateScalar(context, *arguments[3]); - const auto use_gpu = expr3.GetValue(); - return make_uniq((float *)weights_value, num_rows_value, num_columns_value, use_gpu); - -} - - -static unique_ptr MatrixBind(ClientContext &context, ScalarFunction &bound_function, - vector> &arguments) { - return make_uniq(8, 2, false); -} - -*/ - -struct ML_MatrixMultiply { - -public: - static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { - - const auto count = args.size(); - - auto &lhs = ArrayVector::GetEntry(args.data[0]); - auto &rhs = ArrayVector::GetEntry(args.data[1]); - auto &res = ArrayVector::GetEntry(result); - - const auto &lhs_validity = FlatVector::Validity(lhs); - const auto &rhs_validity = FlatVector::Validity(rhs); - - UnifiedVectorFormat lhs_format; - UnifiedVectorFormat rhs_format; - - args.data[0].ToUnifiedFormat(count, lhs_format); - args.data[1].ToUnifiedFormat(count, rhs_format); - - auto lhs_data = FlatVector::GetData(lhs); - auto rhs_data = FlatVector::GetData(rhs); - auto res_data = FlatVector::GetData(res); - - /* - for (int i = 0; i < count; i++) { - std::cout << "lhs-"<< i << ":" << lhs.GetValue(i) << std::endl; - std::cout << "rhs-"<< i << ":"<< rhs.GetValue(i) << std::endl; - } - std::cout << "lhs type:" << int(lhs.GetVectorType()) << std::endl; - std::cout << "lhs type:" << lhs.GetType().ToString() << std::endl; - std::cout << "lhs type:" << EnumUtil::ToChars(lhs.GetType().InternalType()) << std::endl; - std::cout << "rhs type:" << int(GetTypeIdSize(lhs.GetType().InternalType())) << std::endl; - std::cout << "rhs type:" << int(rhs.GetVectorType()) << std::endl; - std::cout << "rhs type:" << EnumUtil::ToChars(rhs.GetType().InternalType()) << std::endl; - std::cout << "rhs type:" << int(GetTypeIdSize(rhs.GetType().InternalType())) << std::endl; - - auto lhs_buffer = lhs.GetBuffer(); - auto rhs_buffer = rhs.GetBuffer(); - - std::cout << "lhs buffer type:" << EnumUtil::ToChars(lhs_buffer->GetBufferType()) << - std::endl; std::cout << "rhs buffer type:" << EnumUtil::ToChars(rhs_buffer->GetBufferType()) - << std::endl; - */ - - Value v2 = args.data[2].GetValue(0); - Value v3 = args.data[3].GetValue(0); - int num_rows = IntegerValue::Get(v2); - int num_columns = IntegerValue::Get(v3); - std::cout << "num rows: " << num_rows << "; num columns: " << num_columns << std::endl; - - const auto rhs_idx = rhs_format.sel->get_index(0); - const auto right_offset = rhs_idx * num_rows; - if (!rhs_validity.CheckAllValid(right_offset + num_rows, right_offset)) { - throw InvalidInputException(StringUtil::Format("right argument can not contain NULL values")); - } - const auto rhs_data_ptr = rhs_data + right_offset; - Eigen::Map> weight_matrix( - (float *)rhs_data_ptr, num_rows, num_columns); - - for (idx_t i = 0; i < count; i++) { - const auto lhs_idx = lhs_format.sel->get_index(i); - - if (!lhs_format.validity.RowIsValid(lhs_idx)) { - FlatVector::SetNull(result, i, true); - continue; - } - - const auto left_offset = lhs_idx * num_rows; - if (!lhs_validity.CheckAllValid(left_offset + num_rows, left_offset)) { - throw InvalidInputException(StringUtil::Format("left argument can not contain NULL values")); - } - - const auto result_offset = i * num_rows; - - const auto lhs_data_ptr = lhs_data + left_offset; - const auto res_data_ptr = res_data + result_offset; - - bool use_gpu = false; - - if (use_gpu) { - // TODO: implementation of matrix multiplication in GPU - throw std::runtime_error("GPU implementation of Matrix Multiple is not implemented."); - } else { - - Eigen::Map> input_matrix( - (float *)lhs_data_ptr, 1, num_rows); - - Eigen::Matrix result_matrix = - input_matrix * weight_matrix; - - // dispatch results to multiple rows - - std::memcpy((float *)res_data_ptr, result_matrix.row(0).data(), num_columns); - } - } - } - - static void RegisterByArray(ExtensionLoader &loader, int num_features, int num_neurons) { - - FunctionBuilder::RegisterScalar(loader, "matmul", [&](ScalarFunctionBuilder &func) { - func.AddVariant([&](ScalarFunctionVariantBuilder &variant) { - variant.AddParameter("input", LogicalType::ARRAY(LogicalType::FLOAT, num_features)); - variant.AddParameter("weight", LogicalType::ARRAY(LogicalType::FLOAT, num_features * num_neurons)); - variant.AddParameter("num_rows", LogicalType::INTEGER); - variant.AddParameter("num_columns", LogicalType::INTEGER); - variant.SetReturnType(LogicalType::ARRAY(LogicalType::FLOAT, num_neurons)); - variant.SetFunction(Execute); - }); - - func.SetDescription(R"( - Returns matrix results multiplying each input with a pre-defined weight matrix. - )"); - - func.SetTag("ext", "cactusdb"); - func.SetTag("category", "relation"); - }); - } -}; - +// This is the symbol your extension’s init code should call. void RegisterMLScalarFunctions(ExtensionLoader &loader) { - - ML_MatrixMultiply::RegisterByArray(loader, 8, 2); + ML_MatrixMultiply::Register(loader); + ML_MinMaxScaler::Register(loader); + // RegisterSoftmax(loader); + // RegisterSigmoid(loader); } } // namespace duckdb diff --git a/src/ml_functions/one_hot_encoder.cpp b/src/ml_functions/one_hot_encoder.cpp new file mode 100644 index 0000000..e69de29 diff --git a/test/sql/cactusdb.test b/test/sql/cactusdb.test index 36cab74..3744f60 100644 --- a/test/sql/cactusdb.test +++ b/test/sql/cactusdb.test @@ -4,28 +4,52 @@ require cactusdb -#Create table statement ok -CREATE TABLE array_data (id INTEGER, features FLOAT[8]); +LOAD cactusdb; -#Insert data +# ------------------------------------------------------------------ +# Create weights file_1.csv: 3x2 matrix +# [[0.1, 0.2], +# [0.3, 0.4], +# [0.5, 0.6]] +# ------------------------------------------------------------------ statement ok -INSERT INTO array_data VALUES - (1, [1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1]), - (2, [2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2, 2.2]), - (3, [3.3, 3.3, 3.3, 3.3, 3.3, 3.3, 3.3, 3.3]), - (4, [4.4, 4.4, 4.4, 4.4, 4.4, 4.4, 4.4, 4.4]), - (5, [5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5]), - (6, [6.6, 6.6, 6.6, 6.6, 6.6, 6.6, 6.6, 6.6]); +CREATE TEMP TABLE w1(c1 DOUBLE, c2 DOUBLE); -#Test query statement ok -SELECT id, features, FROM array_data ORDER BY id +INSERT INTO w1 VALUES (0.1,0.2),(0.3,0.4),(0.5,0.6); -#Test query statement ok -SELECT id, array_inner_product(features, array_value(1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT)), FROM array_data ORDER BY id +COPY w1 TO 'file_1.csv' (FORMAT CSV, HEADER FALSE); -#Test query +# ------------------------------------------------------------------ +# Create weights file_2.csv: 2x2 matrix (scale by 10) +# [[10.0, 0.0], +# [0.0, 10.0]] +# ------------------------------------------------------------------ statement ok -SELECT id, matmul(features, array_value(1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT, 1.0::FLOAT), 8, 2), FROM array_data ORDER BY id +CREATE TEMP TABLE w2(c1 DOUBLE, c2 DOUBLE); + +statement ok +INSERT INTO w2 VALUES (10.0,0.0),(0.0,10.0); + +statement ok +COPY w2 TO 'file_2.csv' (FORMAT CSV, HEADER FALSE); + +# ------------------------------------------------------------------ +# Inputs: three rows of vectors +# ------------------------------------------------------------------ +statement ok +CREATE TABLE inputs(a DOUBLE[]); + +statement ok +INSERT INTO inputs VALUES ([1,2,3]), ([4,5,6]), ([7,8,9]); + +query I +SELECT matmul(matmul(a, 'file_1.csv'), 'file_2.csv') AS y +FROM inputs +ORDER BY 1; +---- +[22.0, 28.0] +[49.0, 64.0] +[76.0, 100.0] From 884e69aba1ce28020d4c9aceaf36129212a1f558 Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Mon, 22 Sep 2025 14:49:47 -0700 Subject: [PATCH 02/18] min_max_scaler one_hot_encoder decision_tree(w/o test) --- src/ml_functions/CMakeLists.txt | 1 + src/ml_functions/decision_tree.cpp | 410 +++++++++++++++++++++ src/ml_functions/matrix_multiplication.cpp | 4 +- src/ml_functions/min_max_scaler.cpp | 139 ++++++- src/ml_functions/ml_functions_scalar.cpp | 5 +- src/ml_functions/one_hot_encoder.cpp | 169 +++++++++ test/sql/{cactusdb.test => matmul.test} | 2 +- test/sql/min_max_scaler.test | 64 ++++ test/sql/one_hot_encoder.test | 95 +++++ 9 files changed, 879 insertions(+), 10 deletions(-) create mode 100644 src/ml_functions/decision_tree.cpp rename test/sql/{cactusdb.test => matmul.test} (98%) create mode 100644 test/sql/min_max_scaler.test create mode 100644 test/sql/one_hot_encoder.test diff --git a/src/ml_functions/CMakeLists.txt b/src/ml_functions/CMakeLists.txt index e113310..e8efb0e 100644 --- a/src/ml_functions/CMakeLists.txt +++ b/src/ml_functions/CMakeLists.txt @@ -3,6 +3,7 @@ set(ML_FUNCTIONS_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/matrix_multiplication.cpp ${CMAKE_CURRENT_SOURCE_DIR}/min_max_scaler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/one_hot_encoder.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/decision_tree.cpp ) set(EXTENSION_SOURCES diff --git a/src/ml_functions/decision_tree.cpp b/src/ml_functions/decision_tree.cpp new file mode 100644 index 0000000..058e314 --- /dev/null +++ b/src/ml_functions/decision_tree.cpp @@ -0,0 +1,410 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "duckdb.hpp" +#include "functions.hpp" +#include "duckdb/function/function.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" + +namespace duckdb{ + struct ML_DecisionTree{ + #define MAX_NUM_NODES_PER_TREE 512 + class Tree; + typedef std::shared_ptr TreePtr; + + // Definition of Node (tree node) in our decision forest implementation + + typedef struct { + // returnClass will be the vaule to compare while this is not a leaf node + union { + float threshold; + float leafValue; + }; + int indexID; + int leftChild; + int rightChild; + bool isLeaf; + // When feature value is missing, whether track/traverseTo the left node + bool isMissTrackLeft; + } Node; + + // Implementation of Tree + class Tree { + public: + // An array of tree nodes + Node tree[MAX_NUM_NODES_PER_TREE]; + + // The ID of the tree in the forest + int treeId; + + // Default constructor + Tree() {} + + // Constructor by parsing xgboost model dump + Tree(int id, std::string treePath) : treeId{id} { + this->constructTreeFromPath(treePath, this->tree); + } + + // Construct a tree from a file dumped from an xgboost model + static void constructTreeFromPath(std::string treePathIn, Node* tree) { + std::vector relationships; + std::vector innerNodes; + std::vector leafNodes; + constructTreeFromPathHelper( + treePathIn, relationships, innerNodes, leafNodes); + processInnerNodes(innerNodes, tree); + processLeafNodes(leafNodes, tree); + processRelationships(relationships, tree); + } + + // Parsing the file and categorize the lines from the file + static void constructTreeFromPathHelper( + std::string treePathIn, + std::vector& relationships, + std::vector& innerNodes, + std::vector& leafNodes) { + std::ifstream inputFile; + inputFile.open(treePathIn.data()); + assert(inputFile.is_open()); + + std::string line; + while (getline(inputFile, line)) { + if ((line.size() == 0) || (line.find("graph") != std::string::npos) || + (line.find("}") != std::string::npos)) { + } else { + if (line.find("->") != std::string::npos) { + relationships.push_back(line); + } else if (line.find("leaf") != std::string::npos) { + leafNodes.push_back(line); + } else if (line.find("label") != std::string::npos) { + innerNodes.push_back(line); + } else { + // skip the case of empty line, somehow it won't be captured by the + // first condition + } + } + } + + inputFile.close(); + } + + // Parsing the lines corresponding to tree inner nodes + static void processInnerNodes( + std::vector& innerNodes, + Node* tree) { + int findStartPosition; + int findMidPosition; + int findEndPosition; + + // Constructing inner nodes + for (int i = 0; i < innerNodes.size(); ++i) { + const std::string& currentLine = innerNodes[i]; + int nodeID; + int indexID; + float threshold; + + // To get nodeID + if ((findEndPosition = currentLine.find("[ label")) != + std::string::npos) { + nodeID = std::stoi(currentLine.substr(4, findEndPosition - 1 - 4)); + } else { + throw std::runtime_error("[ERROR] Error in extracting inner node nodeID\n"); + } + + // To get nodeIndex + if ((findStartPosition = currentLine.find("f")) != std::string::npos && + (findEndPosition = currentLine.find("<")) != std::string::npos) { + indexID = std::stoi(currentLine.substr( + findStartPosition + 1, findEndPosition - findStartPosition - 1)); + } else { + throw std::runtime_error("[Error] Error in extracting inner node indexID\n"); + } + + // To get threshold + if ((findStartPosition = currentLine.find("<")) != std::string::npos && + (findEndPosition = currentLine.find("\" ]")) != std::string::npos) { + threshold = std::stod(currentLine.substr( + findStartPosition + 1, findEndPosition - findStartPosition - 1)); + } else { + throw std::runtime_error("[ERROR] Error in extracting inner node threshold\n"); + } + tree[nodeID].isMissTrackLeft = + false; // XGBoost default is noMissing/right + + tree[nodeID].indexID = indexID; + tree[nodeID].isLeaf = false; + tree[nodeID].leftChild = -1; + tree[nodeID].rightChild = -1; + tree[nodeID].threshold = threshold; + } + } + + static void processLeafNodes( + std::vector& leafNodes, + Node* tree) { + int findStartPosition; + int findMidPosition; + int findEndPosition; + + // Constructing leaf nodes + for (int i = 0; i < leafNodes.size(); ++i) { + // Construct leaf nodes + const std::string& currentLine = leafNodes[i]; + int nodeID; + float leafValue = -1.0f; + + if ((findEndPosition = currentLine.find("[")) != std::string::npos) { + nodeID = std::stoi(currentLine.substr(4, findEndPosition - 1 - 4)); + } else { + throw std::runtime_error( "[ERROR] Error in extracting leaf node nodeID\n"); + } + + // Output Class of XGBoost always a Double/Float. ProbabilityValue for + // Classification, ResultValue for Regression + if ((findStartPosition = currentLine.find("leaf=")) != + std::string::npos && + (findEndPosition = currentLine.find("\" ]")) != std::string::npos) { + leafValue = std::stod(currentLine.substr( + findStartPosition + 5, + findEndPosition - 3 - findStartPosition - 5)); + } else { + throw std::runtime_error("Error in extracting leaf node leafValue\n"); + exit(1); + } + + tree[nodeID].indexID = -1; + tree[nodeID].isLeaf = true; + tree[nodeID].leftChild = -1; + tree[nodeID].rightChild = -1; + tree[nodeID].leafValue = leafValue; + tree[nodeID].isMissTrackLeft = true; // Doesn't matter to leave nodes + } + } + + static void processRelationships( + std::vector& relationships, + Node* tree) { + int findStartPosition; + int findMidPosition; + int findEndPosition; + + // Constructing edges + for (int i = 0; i < relationships.size(); ++i) { + // Construct Directed Edges between Nodes + const std::string& currentLine = relationships[i]; + int parentNodeID; + int childNodeID; + + if ((findMidPosition = currentLine.find("->")) != std::string::npos) { + parentNodeID = + std::stoi(currentLine.substr(4, findMidPosition - 1 - 4)); + } else { + std::cout << "Error in extracting parentNodeID\n"; + exit(1); + } + + if ((findEndPosition = currentLine.find("[")) != std::string::npos) { + childNodeID = std::stoi(currentLine.substr( + findMidPosition + 3, findEndPosition - 1 - findMidPosition - 3)); + } else { + std::cout << "Error in extracting childNodeID\n"; + exit(1); + } + + if (currentLine.find("yes, missing") != std::string::npos) { + tree[parentNodeID].isMissTrackLeft = + true; // in processInnerNodes(), default value is set to no/right + } + + if (tree[parentNodeID].leftChild == -1) { + tree[parentNodeID].leftChild = childNodeID; + } else if (tree[parentNodeID].rightChild == -1) { + tree[parentNodeID].rightChild = childNodeID; + } else { + std::cout + << "Error in parsing trees: children nodes were updated again: " + << parentNodeID << "->" << childNodeID << std::endl; + } + } + } + inline float predictSingle(const float *row_base) const { + int cur = 0; + while (!tree[cur].isLeaf) { + const int idx = tree[cur].indexID; + const float fv = row_base[idx]; + cur = (fv < tree[cur].threshold) ? tree[cur].leftChild : tree[cur].rightChild; + } + return tree[cur].leafValue; + } + + inline float predictSingleMissing(const float *row_base) const { + int cur = 0; + while (!tree[cur].isLeaf) { + const int idx = tree[cur].indexID; + const float fv = row_base[idx]; + if (std::isnan(fv)) { + cur = tree[cur].isMissTrackLeft ? tree[cur].leftChild : tree[cur].rightChild; + } else { + cur = (fv < tree[cur].threshold) ? tree[cur].leftChild : tree[cur].rightChild; + } + } + return tree[cur].leafValue; + } + }; //End of Tree + + // --------------------------------- + // Bind: build the tree once + // --------------------------------- + + // ------------------------- +// Bind Data (same shape/style) +// ------------------------- +struct BindData final : public FunctionData { + std::shared_ptr tree; + bool has_missing; + + BindData() = default; + BindData(const std::shared_ptr &t, bool hm) + : tree(t), has_missing(hm) {} + + unique_ptr Copy() const override { + // shared_ptr copy is fine (trees are immutable after load) + return make_uniq(tree, has_missing); + } + bool Equals(const FunctionData &other_p) const override { + auto &o = other_p.Cast(); + // pointer equality is sufficient; both point to the same parsed tree + return tree.get() == o.tree.get() && has_missing == o.has_missing; + } + }; + +// ------------------------- +// Bind Function (same skeleton) +// ------------------------- +static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + // Expecting 3 arguments: features, tree_file, has_missing + if (args.size() != 3) { + throw InvalidInputException( + "tree_predict expects 3 arguments: features LIST(FLOAT), tree_file VARCHAR, has_missing BOOLEAN"); + } + + // Ensure first arg is LIST(FLOAT) + const auto &feat_type = args[0]->return_type; + if (feat_type.id() != LogicalTypeId::LIST || + ListType::GetChildType(feat_type).id() != LogicalTypeId::FLOAT) { + throw InvalidInputException("tree_predict: first argument must be LIST(FLOAT)"); + } + + // Evaluate constants like in your example + auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); + auto vHasMissing = ExpressionExecutor::EvaluateScalar(context, *args[2]); + + const std::string tree_path = vFile.ToString(); + const bool has_missing = vHasMissing.GetValue(); + + // Try loading/parsing once at bind time + std::shared_ptr tree_ptr; + try { + tree_ptr = std::make_shared(/*treeId=*/0, tree_path); + } catch (const std::exception &e) { + throw InvalidInputException("tree_predict: failed to load/parse tree file '%s': %s", + tree_path.c_str(), e.what()); + } + + return make_uniq(tree_ptr, has_missing); + } + + + + static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { + const idx_t count = args.size(); + + // Access bind data (holds the parsed tree) + const auto &func_expr = state.expr.Cast(); + auto &bd = func_expr.bind_info->Cast(); + const bool has_missing = bd.has_missing; + const Tree &tree = *bd.tree; + + // Input + Vector &features_vec = args.data[0]; // LIST(FLOAT) + auto *entries = FlatVector::GetData(features_vec); + auto &features_valid = FlatVector::Validity(features_vec); + + // Child holds concatenated float values for all rows + Vector &child = ListVector::GetEntry(features_vec); + const float *vals = FlatVector::GetData(child); + auto &child_valid = FlatVector::Validity(child); + + // Prepare result + result.SetVectorType(VectorType::FLAT_VECTOR); + auto out = FlatVector::GetData(result); + auto &out_valid = FlatVector::Validity(result); + + for (idx_t i = 0; i < count; ++i) { + // If the whole LIST is NULL -> output NULL + if (!features_valid.RowIsValid(i)) { + out_valid.SetInvalid(i); + continue; + } + const auto ent = entries[i]; // {offset, length} + const float *row_base = vals + ent.offset; + + // If any element is NULL and has_missing=false, we treat it as NaN only if has_missing=true. + // Here we map child nulls to NaN so the "missing" path triggers only when has_missing==true. + // Quick pass: if there are nulls and has_missing==false, they’ll be read as NaN and go right branch by threshold (std::isnan is false in plain predict). + // To properly honor missing path only when enabled, we do missing-aware predict when has_missing==true. + float pred; + if (has_missing) { + // Create a small stack buffer with NaNs for nulls so predictSingleMissing sees them + // (avoid mutating child vector). We only copy when there are nulls. + bool any_null = false; + for (idx_t k = 0; k < ent.length; ++k) { + if (!child_valid.RowIsValid(ent.offset + k)) { any_null = true; break; } + } + if (any_null) { + // Minimal scratch: copy row into a temp and fill nulls with NaN + std::vector tmp(ent.length); + for (idx_t k = 0; k < ent.length; ++k) { + tmp[k] = child_valid.RowIsValid(ent.offset + k) ? row_base[k] : std::numeric_limits::quiet_NaN(); + } + pred = tree.predictSingleMissing(tmp.data()); + } else { + pred = tree.predictSingleMissing(row_base); + } + } else { + // Fast path, no special missing handling + pred = tree.predictSingle(row_base); + } + out[i] = pred; + } + } + + // ---------------------------- + // Register + // ---------------------------- + static void Register(ExtensionLoader &loader) { + ScalarFunction fn( + "tree_predict", + { + LogicalType::LIST(LogicalType::FLOAT), // features + LogicalType::VARCHAR, // tree file path + LogicalType::BOOLEAN // has_missing + }, + LogicalType::FLOAT, // prediction + Execute + ); + fn.bind = Bind; + loader.RegisterFunction(fn); + } +}; //End of Decision Tree struct +}// end of duckdb namespace diff --git a/src/ml_functions/matrix_multiplication.cpp b/src/ml_functions/matrix_multiplication.cpp index 72db1de..e282ada 100644 --- a/src/ml_functions/matrix_multiplication.cpp +++ b/src/ml_functions/matrix_multiplication.cpp @@ -148,7 +148,7 @@ struct ML_MatrixMultiply { ParseCSVWeights(path, W, K, N); // Erase filename argument so execution only receives x - Function::EraseArgument(bound_function, args, 1); + // Function::EraseArgument(bound_function, args, 1); return make_uniq(W, K, N, path, /*bound*/ true); } @@ -159,7 +159,7 @@ struct ML_MatrixMultiply { static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { idx_t count = args.size(); //number of tuples in a DataChunk - + // Read Left Matrix from the argument Vector &lhs = args.data[0]; UnifiedVectorFormat lhs_uvf; diff --git a/src/ml_functions/min_max_scaler.cpp b/src/ml_functions/min_max_scaler.cpp index 8b94247..0020947 100644 --- a/src/ml_functions/min_max_scaler.cpp +++ b/src/ml_functions/min_max_scaler.cpp @@ -1,5 +1,14 @@ #include "functions.hpp" #include "duckdb.hpp" +#include "duckdb/function/function.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include +#include +#include +#include +#include +#include namespace duckdb { struct ML_MinMaxScaler { @@ -50,7 +59,23 @@ namespace duckdb { throw InvalidInputException("min_max_scaler with list arguments expects 4 arguments: x, min_list, max_list, no_of_columns"); } //TODO + auto vmin_list = ExpressionExecutor::EvaluateScalar(context, *args[1]); + auto vmax_list = ExpressionExecutor::EvaluateScalar(context, *args[2]); + auto vcols = ExpressionExecutor::EvaluateScalar(context, *args[3]); + + std::vector min; + std::vector max; + + const auto &min_children = ListValue::GetChildren(vmin_list); + const auto &max_children = ListValue::GetChildren(vmax_list); + min.reserve(min_children.size()); + max.reserve(max_children.size()); + + for (const auto &child : min_children) min.push_back(child.GetValue()); + for (const auto &child : max_children) max.push_back(child.GetValue()); + std::string path = "from_arguments"; + return make_uniq(min, max, min.size(), path, /*bound*/ true); } static unique_ptr Bind_File(ClientContext &context, @@ -60,14 +85,116 @@ namespace duckdb { if (args.size() != 2) { throw InvalidInputException("min_max_scaler with file argument expects 2 arguments: x, min_max_file"); } - //TODO + auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); + if (vFile.IsNull()) { + throw BinderException("matmul: weights_file is NULL"); + } + const std::string path = vFile.ToString(); + // const std::string path = args.data[1]->ToString(); + // // std::cout << "Min-Max file: " << path << std::endl; + + if(!std::filesystem::exists(path)){ + throw InvalidInputException("min_max_scaler: File does not exist - " + path); + } + + std::vector min; + std::vector max; + std::ifstream file(path); + + std::string line; + int line_count = 0; + + while(std::getline(file,line)){ + std::istringstream iss(line); + double value; + while (iss>>value){ + // std::cout << "Read value: " << value << std::endl; + if(line_count == 0){ + min.push_back(value); + } + else if(line_count == 1){ + max.push_back(value); + } + else { + throw InvalidInputException("min_max_scaler: File should contain only two lines - first line for min values and second line for max values"); + } + } + line_count++; + // std::cout << "Read line " << line_count << ": " << line << std::endl; + } + file.close(); + + // std::cout << "Min values: "; + // for(auto v : min) // std::cout << v << " "; + // std::cout << std::endl; + // std::cout << "Max values: "; + // for(auto v : max) // std::cout << v << " "; + // std::cout << std::endl; + + return make_uniq(min, max, min.size(), path, /*bound*/ true); } // ------------------------- // Execute // ------------------------- static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { - //TODO + idx_t count = args.size(); //number of tuples in a DataChunk + + // Read the feature vector from the argument + Vector &f = args.data[0]; + UnifiedVectorFormat f_uvf; + f.ToUnifiedFormat(count, f_uvf); + const auto *entries = UnifiedVectorFormat::GetData(f_uvf); + auto &child = ListVector::GetEntry(f); + UnifiedVectorFormat child_uvf; + child.ToUnifiedFormat(count, child_uvf); + const double *x_data = UnifiedVectorFormat::GetData(child_uvf); + + //read the bound data + const auto &func_expr = state.expr.Cast(); + const auto &info = func_expr.bind_info->Cast(); + if (!info.has_bound_min_max) { + throw InvalidInputException("min_max_scaler: min and max values are not bound"); + } + const idx_t cols = info.cols; + const std::vector &min = info.min; + const std::vector &max = info.max; + + // Prepare result in a FlatVector + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + const idx_t total_out = count * cols; + ListVector::Reserve(result, total_out); + ListVector::SetListSize(result, total_out); + double *out = FlatVector::GetData(res_child); + auto &res_valid = FlatVector::Validity(result); + + //main loop + idx_t cursor = 0; + for(idx_t i = 0;iget_index(i); + if(f_uvf.validity.RowIsValid(idx)){ + const auto ent = entries[idx]; + if(ent.length != cols){ + throw InvalidInputException("min_max_scaler: Input vector length %llu does not match the bound min/max length %llu, %llu", (unsigned long long)ent.length, (unsigned long long)cols, (unsigned long long)min.size()); + } + // std::cout << " Input length: " << ent.length << ", cols: " << cols << std::endl; + res_entries[i] = {cursor, cols}; + const double *row = x_data + ent.offset; + for (idx_t j = 0;j +#include +#include +#include +#include +#include +#include + +namespace duckdb { + struct ML_OneHotEncoder { + public: + // ------------------------- + // BindData + // ------------------------- + struct BindData final : public FunctionData { + std::map str_to_index; + std::map int_to_index; + bool is_string; + + BindData() = default; + BindData(const std::map &s2i, const std::map &i2i, bool str) + : str_to_index(s2i), int_to_index(i2i), is_string(str) {} + + unique_ptr Copy() const override { + // deep copy (map copy is deep) + return make_uniq(str_to_index, int_to_index, is_string); + } + bool Equals(const FunctionData &other_p) const override { + auto &o = other_p.Cast(); + return str_to_index == o.str_to_index && + int_to_index == o.int_to_index && + is_string == o.is_string; + } + }; + // ------------------------- + // Bind Functions + // ------------------------- + static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + // Expecting 3 arguments: x, categories_list, is_string + if (args.size() != 3) { + throw InvalidInputException("one_hot_encoder expects 3 arguments: x, categories_list, is_string"); + } + + auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); + auto vis_string = ExpressionExecutor::EvaluateScalar(context, *args[2]); + + const std::string path = vFile.ToString(); + const bool is_string = vis_string.GetValue(); + + std::ifstream in(path); + if (!in) { + throw std::runtime_error("OneHot mapping file not found: " + path); + } + std::string line; + std::getline(in, line); // skip header + + std::map str_map; + std::map int_map; + + if(is_string){ + + while (std::getline(in, line)) { + std::istringstream ss(line); + std::string valStr, posStr; + if (!std::getline(ss, valStr, ',')) continue; + if (!std::getline(ss, posStr, ',')) continue; + // int64_t value = std::stoll(valStr); + int position = std::stoi(posStr); + str_map[valStr] = position; + } + } + else{ + + while (std::getline(in, line)) { + std::istringstream ss(line); + std::string valStr, posStr; + if (!std::getline(ss, valStr, ',')) continue; + if (!std::getline(ss, posStr, ',')) continue; + int64_t value = std::stoll(valStr); + int position = std::stoi(posStr); + int_map[value] = position; + } + + } + + in.close(); + return make_uniq(str_map, int_map, is_string); + + } + + // ------------------------- + // Execute + // ------------------------- + static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { + idx_t count = args.size(); + + const auto &func_expr = state.expr.Cast(); + const auto &bd = func_expr.bind_info->Cast(); + const idx_t k = bd.is_string ? (idx_t)bd.str_to_index.size() + : (idx_t)bd.int_to_index.size(); + + Vector &f = args.data[0]; + UnifiedVectorFormat f_uvf; + f.ToUnifiedFormat(count, f_uvf); + + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + const idx_t total_out = count * k; + ListVector::Reserve(result, total_out); + ListVector::SetListSize(result, total_out); + double *out = FlatVector::GetData(res_child); + auto &res_valid = FlatVector::Validity(result); + + idx_t cursor = 0; + for (idx_t i = 0; i < count; i++) { + idx_t idx = f_uvf.sel->get_index(i); + if (f_uvf.validity.RowIsValid(idx)) { + res_entries[i] = {cursor, k}; + const auto sref = UnifiedVectorFormat::GetData(f_uvf)[idx]; + idx_t pos = -1; + if (bd.is_string) { + std::string key = sref.GetString(); + auto it = bd.str_to_index.find(key); + if(it!=bd.str_to_index.end()) pos = it->second; + } else { + idx_t key = stoi(sref.GetString()); + auto it = bd.int_to_index.find(key); + if(it!=bd.int_to_index.end())pos = it->second; + } + if (pos != -1) { + for (idx_t j = 0; j < k; j++) { + out[cursor++] = (j == pos) ? 1.0 : 0.0; + } + } else { + // Unknown category, all zeros + for (idx_t j = 0; j < k; j++) { + out[cursor++] = 0.0; + } + } + } else { + // null entry + res_entries[i] = {0, 0}; + res_valid.SetInvalid(i); + } + } + } + + static void Register(ExtensionLoader &loader) { + // Logical signature with filename; Bind erases it so Exec sees only x. + ScalarFunction fn( + "one_hot_encode", + { LogicalType::VARCHAR, // x + LogicalType::VARCHAR, // categories_file + LogicalType::BOOLEAN }, // is_string + LogicalType::LIST(LogicalType::DOUBLE), // return type + Execute + ); + fn.bind = Bind; + loader.RegisterFunction(fn); + } + }; +} \ No newline at end of file diff --git a/test/sql/cactusdb.test b/test/sql/matmul.test similarity index 98% rename from test/sql/cactusdb.test rename to test/sql/matmul.test index 3744f60..054789e 100644 --- a/test/sql/cactusdb.test +++ b/test/sql/matmul.test @@ -51,5 +51,5 @@ FROM inputs ORDER BY 1; ---- [22.0, 28.0] -[49.0, 64.0] +[49.0, 63.99999999999999] [76.0, 100.0] diff --git a/test/sql/min_max_scaler.test b/test/sql/min_max_scaler.test new file mode 100644 index 0000000..78422ec --- /dev/null +++ b/test/sql/min_max_scaler.test @@ -0,0 +1,64 @@ +# name: test/sql/minmaxscaler.test +# description: test min_max_scaler (file + constants) in cactusdb extension +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +# ------------------------------------------------------------------ +# Inputs: three rows of REAL vectors +# ------------------------------------------------------------------ +statement ok +CREATE TABLE inputs(a REAL[]); + +statement ok +INSERT INTO inputs VALUES ([1,5,9]), ([4,5,6]), ([7,8,9]); + +# ================================================================== +# A) FILE-BASED STATS (2 x k): mins on row 1, maxs on row 2 +# mins = [0,0,0], maxs = [10,10,10] +# Expected scaling: +# [1,5,9] -> [0.1,0.5,0.9] +# [4,5,6] -> [0.4,0.5,0.6] +# [7,8,9] -> [0.7,0.8,0.9] +# ================================================================== + +statement ok +CREATE TEMP TABLE s1(c1 REAL, c2 REAL, c3 REAL); + +statement ok +INSERT INTO s1 VALUES (0.0,0.0,0.0), (10.0,10.0,10.0); + +statement ok +COPY s1 TO 'scaler_2xk.csv' (FORMAT CSV, HEADER FALSE, DELIMITER ' '); + +query I +SELECT min_max_scaler(a, 'scaler_2xk.csv') AS y +FROM inputs +ORDER BY 1; +---- +[0.1, 0.5, 0.9] +[0.4, 0.5, 0.6] +[0.7, 0.8, 0.9] + +# ================================================================== +# F) LIST PARAMS OVERLOAD: +# (a DOUBLE[], min DOUBLE[], max DOUBLE[], cols INTEGER) +# mins/maxs = [0,0,0]/[10,10,10] -> same expected output as A/B/C +# ================================================================== + +query I +SELECT min_max_scaler( + a, -- cast input to DOUBLE[] + [0.0, 0.0, 0.0]::DOUBLE[], -- min list (DOUBLE[]) + [10.0, 10.0, 10.0]::DOUBLE[], -- max list (DOUBLE[]) + 3 -- number of columns + ) AS y +FROM inputs +ORDER BY 1; +---- +[0.1, 0.5, 0.9] +[0.4, 0.5, 0.6] +[0.7, 0.8, 0.9] diff --git a/test/sql/one_hot_encoder.test b/test/sql/one_hot_encoder.test new file mode 100644 index 0000000..7b5ae99 --- /dev/null +++ b/test/sql/one_hot_encoder.test @@ -0,0 +1,95 @@ +# name: test/sql/one_hot_encoder.test +# description: tests for one_hot_encode UDF (string & integer categories) +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +# =============================================================== +# STRING categories mapping CSV: red->0, green->1, blue->2 +# We emulate a header by adding a first dummy row and writing with HEADER FALSE. +# =============================================================== + +statement ok +CREATE TEMP TABLE str_map(value VARCHAR, position INTEGER); + +statement ok +INSERT INTO str_map VALUES + ('value', NULL), -- dummy header row to be skipped by Bind (getline once) + ('red', 0), + ('green', 1), + ('blue', 2); + +statement ok +COPY str_map TO 'str_map.csv' (FORMAT CSV, HEADER FALSE); + +# Inputs (includes an unknown 'yellow') +statement ok +CREATE TEMP TABLE inputs_str(x VARCHAR); + +statement ok +INSERT INTO inputs_str VALUES ('red'), ('green'), ('blue'), ('yellow'); + +# Order by x -> blue, green, red, yellow +# Expected one-hot (k=3): +# blue -> [0,0,1] +# green -> [0,1,0] +# red -> [1,0,0] +# yellow -> [0,0,0] (unknown) + +query I +SELECT one_hot_encode(x, 'str_map.csv', TRUE) AS oh +FROM inputs_str +ORDER BY x; +---- +[0.0, 0.0, 1.0] +[0.0, 1.0, 0.0] +[1.0, 0.0, 0.0] +[0.0, 0.0, 0.0] + +# =============================================================== +# INTEGER categories mapping CSV: 10->0, 20->1, 30->2, 50->3 +# Again, add a dummy header row and write with HEADER FALSE. +# =============================================================== + +statement ok +CREATE TEMP TABLE int_map(value BIGINT, position INTEGER); + +statement ok +INSERT INTO int_map VALUES + (NULL, NULL), -- dummy header + (10, 0), + (20, 1), + (30, 2), + (50, 3); + +statement ok +COPY int_map TO 'int_map.csv' (FORMAT CSV, HEADER FALSE); + +statement ok +CREATE TEMP TABLE inputs_int(v INTEGER); + +statement ok +INSERT INTO inputs_int VALUES (10), (20), (30), (40), (50); + +# Your UDF takes VARCHAR for the first arg, so CAST(v AS VARCHAR) +# Order by v: 10,20,30,40,50 +# Expected (k=4): +# 10 -> [1,0,0,0] +# 20 -> [0,1,0,0] +# 30 -> [0,0,1,0] +# 40 -> [0,0,0,0] (unknown) +# 50 -> [0,0,0,1] + +query I +SELECT one_hot_encode(CAST(v AS VARCHAR), 'int_map.csv', FALSE) AS oh +FROM inputs_int +ORDER BY v; +---- +[1.0, 0.0, 0.0, 0.0] +[0.0, 1.0, 0.0, 0.0] +[0.0, 0.0, 1.0, 0.0] +[0.0, 0.0, 0.0, 0.0] +[0.0, 0.0, 0.0, 1.0] From d234338283ed57985559dd551e933d4fbc7faef4 Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 1 Oct 2025 14:20:25 -0700 Subject: [PATCH 03/18] optimizer test --- .gitignore | 4 +- CMakeLists.txt | 1 + queries/expedia_query.sql | 88 +++++++++++ queries/results.txt | 183 +++++++++++++++++++++++ src/cactusdb_extension.cpp | 4 + src/optimization/CMakeLists.txt | 8 + src/optimization/add5_rule.cpp | 57 +++++++ src/optimization/add5_rule.hpp | 7 + src/optimization/register_optimizers.cpp | 21 +++ src/optimization/register_optimizers.hpp | 7 + test/sql/decision_tree.test | 110 ++++++++++++++ 11 files changed, 489 insertions(+), 1 deletion(-) create mode 100644 queries/expedia_query.sql create mode 100644 queries/results.txt create mode 100644 src/optimization/CMakeLists.txt create mode 100644 src/optimization/add5_rule.cpp create mode 100644 src/optimization/add5_rule.hpp create mode 100644 src/optimization/register_optimizers.cpp create mode 100644 src/optimization/register_optimizers.hpp create mode 100644 test/sql/decision_tree.test diff --git a/.gitignore b/.gitignore index ca1efe4..2e396f8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ testext test/python/__pycache__/ .Rhistory *.csv -vcpkg/ \ No newline at end of file +vcpkg/ +resources/* +duckdb/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index dbc450d..1d6e310 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ include_directories(${EIGEN3_INCLUDE_DIR}) set(EXTENSION_SOURCES src/cactusdb_extension.cpp) add_subdirectory(src/ml_functions) add_subdirectory(src/util) +add_subdirectory(src/optimization) message(STATUS "EXTENSION_SOURCES include ${EXTENSION_SOURCES}") build_static_extension(${TARGET_NAME} ${EXTENSION_SOURCES}) diff --git a/queries/expedia_query.sql b/queries/expedia_query.sql new file mode 100644 index 0000000..bce1fba --- /dev/null +++ b/queries/expedia_query.sql @@ -0,0 +1,88 @@ +-- Attach the database file and use its schema +ATTACH '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/data/expedia_imbridge2.db' + AS expedia_db (READ_ONLY); +SET schema 'expedia_db.main'; + +-- Optimizer Config +PRAGMA disable_optimizer; +PRAGMA explain_output='optimized_only'; +-- SET enable_profiling = 'query_tree_optimizer'; +-- SET profiling_mode = 'detailed'; + +LOAD 'cactusdb'; + +set threads = 8; + +-- Now query the tables +-- SELECT 'Expedia_S_listings_extension2' AS which, * FROM Expedia_S_listings_extension2 LIMIT 10; +-- SELECT 'Expedia_R1_hotels2' AS which, * FROM Expedia_R1_hotels2 LIMIT 10; +-- SELECT 'Expedia_R2_searches' AS which, * FROM Expedia_R2_searches LIMIT 10; + +--EXPLAIN ANALYZE +SELECT + s.prop_id, + s.srch_id, + tree_predict( + list_transform( + list_concat( + /* 1) NUMERICALS — per-column scaling (exact order) */ + min_max_scaler(list_value(CAST(s.prop_location_score1 AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score1.txt'), + min_max_scaler(list_value(CAST(s.prop_location_score2 AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score2.txt'), + min_max_scaler(list_value(CAST(s.prop_log_historical_price AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_log_historical_price.txt'), + min_max_scaler(list_value(CAST(s.price_usd AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/price_usd.txt'), + min_max_scaler(list_value(CAST(s.orig_destination_distance AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/orig_destination_distance.txt'), + min_max_scaler(list_value(CAST(h.prop_review_score AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_review_score.txt'), + min_max_scaler(list_value(CAST(h.avg_bookings_usd AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/avg_bookings_usd.txt'), + min_max_scaler(list_value(CAST(h.stdev_bookings_usd AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/stdev_bookings_usd.txt'), + + /* 2) CATEGORICALS — one-hot, exact order of your Python */ + -- stringEncoderSpecs (string→int): TRUE + one_hot_encode(CAST(s.position AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/position.csv', TRUE), + one_hot_encode(CAST(h.prop_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_country_id.csv', TRUE), + + -- encoderSpecs (int→int): FALSE + one_hot_encode(CAST(h.prop_starrating AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_starrating.csv', FALSE), + one_hot_encode(CAST(h.prop_brand_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_brand_bool.csv', FALSE), + one_hot_encode(CAST(h.count_clicks AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_clicks.csv', FALSE), + one_hot_encode(CAST(h.count_bookings AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_bookings.csv', FALSE), + + -- stringEncoderSpecs (string→int): TRUE + one_hot_encode(CAST(r.year AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/year.csv', TRUE), + one_hot_encode(CAST(r.month AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/month.csv', TRUE), + one_hot_encode(CAST(r.weekofyear AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/weekofyear.csv', TRUE), + one_hot_encode(CAST(r.time AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/time.csv', TRUE), + one_hot_encode(CAST(r.site_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/site_id.csv', TRUE), + one_hot_encode(CAST(r.visitor_location_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/visitor_location_country_id.csv', TRUE), + one_hot_encode(CAST(r.srch_destination_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_destination_id.csv', TRUE), + + -- encoderSpecs (int→int): FALSE + one_hot_encode(CAST(r.srch_length_of_stay AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_length_of_stay.csv', FALSE), + one_hot_encode(CAST(r.srch_booking_window AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_booking_window.csv', FALSE), + one_hot_encode(CAST(r.srch_adults_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_adults_count.csv', FALSE), + one_hot_encode(CAST(r.srch_children_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_children_count.csv', FALSE), + one_hot_encode(CAST(r.srch_room_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_room_count.csv', FALSE), + one_hot_encode(CAST(r.srch_saturday_night_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_saturday_night_bool.csv', FALSE), + one_hot_encode(CAST(r.random_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/random_bool.csv', FALSE) + ), + x -> CAST(x AS FLOAT) -- tree_predict expects LIST + ), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/tree/0.txt', + FALSE + ) AS prediction +FROM Expedia_S_listings_extension2 AS s +JOIN Expedia_R1_hotels2 AS h ON s.prop_id = h.prop_id +JOIN Expedia_R2_searches AS r ON s.srch_id = r.srch_id +WHERE s.prop_location_score1 > 1 + AND s.prop_location_score2 > 0.1 + AND s.prop_log_historical_price > 4 + AND h.count_bookings > 5 + AND r.srch_booking_window > 10 + AND r.srch_length_of_stay > 1; diff --git a/queries/results.txt b/queries/results.txt new file mode 100644 index 0000000..4a5c3ed --- /dev/null +++ b/queries/results.txt @@ -0,0 +1,183 @@ +Expedia query + +Settings : +thread count = 1 +with default optimizer | no default optimizer +3.66s | 3.70s + +thread count = 8 +with default optimizer | no default optimizer +0.622s | 0.637s + + +Query plan without optimizer : +┌────────────────────────────────────────────────┐ +│┌──────────────────────────────────────────────┐│ +││ Total Time: 0.637s ││ +│└──────────────────────────────────────────────┘│ +└────────────────────────────────────────────────┘ +┌───────────────────────────┐ +│ QUERY │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ EXPLAIN_ANALYZE │ +│ ──────────────────── │ +│ 0 rows │ +│ (0.00s) │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ PROJECTION │ +│ ──────────────────── │ +│ prop_id │ +│ srch_id │ +│ prediction │ +│ │ +│ 79,756 rows │ +│ (4.22s) │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ FILTER │ +│ ──────────────────── │ +│ ((prop_location_score1 > │ +│ CAST(1 AS DOUBLE)) AND │ +│ (prop_location_score2 > │ +│ CAST(0.1 AS DOUBLE)) AND │ +│ (prop_log_historical_price│ +│ > CAST(4 AS DOUBLE)) AND │ +│ (count_bookings > CAST(5 │ +│ AS BIGINT)) AND │ +│ (srch_booking_window > │ +│ CAST(10 AS BIGINT)) AND │ +│ (srch_length_of_stay > │ +│ CAST(1 AS BIGINT))) │ +│ │ +│ 79,756 rows │ +│ (0.04s) │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ HASH_JOIN │ +│ ──────────────────── │ +│ Join Type: INNER │ +│ │ +│ Conditions: ├───────────────────────────────────────────┐ +│ srch_id = srch_id │ │ +│ │ │ +│ 942,142 rows │ │ +│ (0.10s) │ │ +└─────────────┬─────────────┘ │ +┌─────────────┴─────────────┐ ┌─────────────┴─────────────┐ +│ HASH_JOIN │ │ TABLE_SCAN │ +│ ──────────────────── │ │ ──────────────────── │ +│ Join Type: INNER │ │ Table: │ +│ │ │ Expedia_R2_searches │ +│ Conditions: ├──────────────┐ │ │ +│ prop_id = prop_id │ │ │ Type: Sequential Scan │ +│ │ │ │ │ +│ 942,142 rows │ │ │ 37,021 rows │ +│ (0.12s) │ │ │ (0.00s) │ +└─────────────┬─────────────┘ │ └───────────────────────────┘ +┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +│ TABLE_SCAN ││ TABLE_SCAN │ +│ ──────────────────── ││ ──────────────────── │ +│ Table: ││ Table: │ +│Expedia_S_listings_extensio││ Expedia_R1_hotels2 │ +│ n2 ││ │ +│ ││ Type: Sequential Scan │ +│ Type: Sequential Scan ││ │ +│ ││ │ +│ 942,142 rows ││ 11,939 rows │ +│ (0.08s) ││ (0.00s) │ +└───────────────────────────┘└───────────────────────────┘ + +Query Plan with optimizer : + +┌───────────────────────────┐ +│ QUERY │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ EXPLAIN_ANALYZE │ +│ ──────────────────── │ +│ 0 rows │ +│ (0.00s) │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ PROJECTION │ +│ ──────────────────── │ +│ prop_id │ +│ srch_id │ +│ prediction │ +│ │ +│ 79,756 rows │ +│ (4.26s) │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ HASH_JOIN │ +│ ──────────────────── │ +│ Join Type: INNER │ +│ │ +│ Conditions: ├───────────────────────────────────────────┐ +│ srch_id = srch_id │ │ +│ │ │ +│ 79,756 rows │ │ +│ (0.03s) │ │ +└─────────────┬─────────────┘ │ +┌─────────────┴─────────────┐ ┌─────────────┴─────────────┐ +│ HASH_JOIN │ │ TABLE_SCAN │ +│ ──────────────────── │ │ ──────────────────── │ +│ Join Type: INNER │ │ Table: │ +│ │ │ Expedia_R2_searches │ +│ Conditions: │ │ │ +│ prop_id = prop_id │ │ Type: Sequential Scan │ +│ │ │ │ +│ │ │ Projections: │ +│ │ │ srch_id │ +│ │ │ srch_booking_window │ +│ │ │ srch_length_of_stay │ +│ │ │ year │ +│ │ │ month │ +│ │ │ weekofyear │ +│ │ │ time │ +│ ├──────────────┐ │ site_id │ +│ │ │ │visitor_location_country_id│ +│ │ │ │ srch_destination_id │ +│ │ │ │ srch_adults_count │ +│ │ │ │ srch_children_count │ +│ │ │ │ srch_room_count │ +│ │ │ │ srch_saturday_night_bool │ +│ │ │ │ random_bool │ +│ │ │ │ │ +│ │ │ │ Filters: │ +│ │ │ │ srch_booking_window>10 │ +│ │ │ │ srch_length_of_stay>1 │ +│ │ │ │ │ +│ 212,022 rows │ │ │ 11,052 rows │ +│ (0.04s) │ │ │ (0.00s) │ +└─────────────┬─────────────┘ │ └───────────────────────────┘ +┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +│ TABLE_SCAN ││ TABLE_SCAN │ +│ ──────────────────── ││ ──────────────────── │ +│ Table: ││ Table: │ +│Expedia_S_listings_extensio││ Expedia_R1_hotels2 │ +│ n2 ││ │ +│ ││ Type: Sequential Scan │ +│ Type: Sequential Scan ││ │ +│ ││ Projections: │ +│ Projections: ││ prop_id │ +│ prop_id ││ count_bookings │ +│ srch_id ││ prop_review_score │ +│ prop_location_score1 ││ avg_bookings_usd │ +│ prop_location_score2 ││ stdev_bookings_usd │ +│ prop_log_historical_price ││ prop_country_id │ +│ price_usd ││ prop_starrating │ +│ orig_destination_distance ││ prop_brand_bool │ +│ position ││ count_clicks │ +│ ││ │ +│ Filters: ││ Filters: │ +│ prop_location_score1>1.0 ││ count_bookings>5 │ +│ prop_location_score2>0.1 ││ │ +│ prop_log_historical_price ││ │ +│ >4.0 ││ │ +│ ││ │ +│ 247,416 rows ││ 7,170 rows │ +│ (0.11s) ││ (0.00s) │ +└───────────────────────────┘└───────────────────────────┘ \ No newline at end of file diff --git a/src/cactusdb_extension.cpp b/src/cactusdb_extension.cpp index f872cba..142969f 100644 --- a/src/cactusdb_extension.cpp +++ b/src/cactusdb_extension.cpp @@ -1,6 +1,8 @@ #include "cactusdb_extension.hpp" #include "duckdb.hpp" #include "functions.hpp" +#include "optimization/register_optimizers.hpp" +#include "duckdb/main/database.hpp" // OpenSSL linked through vcpkg #include @@ -10,6 +12,8 @@ namespace duckdb { static void LoadInternal(ExtensionLoader &loader) { RegisterMLScalarFunctions(loader); + auto &db = loader.GetDatabaseInstance(); + RegisterCactusOptimizers(db); } diff --git a/src/optimization/CMakeLists.txt b/src/optimization/CMakeLists.txt new file mode 100644 index 0000000..8d63670 --- /dev/null +++ b/src/optimization/CMakeLists.txt @@ -0,0 +1,8 @@ +# Append optimizer sources to the extension's global list +list(APPEND EXTENSION_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/add5_rule.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/register_optimizers.cpp +) + +# Expose back to parent +set(EXTENSION_SOURCES "${EXTENSION_SOURCES}" PARENT_SCOPE) diff --git a/src/optimization/add5_rule.cpp b/src/optimization/add5_rule.cpp new file mode 100644 index 0000000..38c5f18 --- /dev/null +++ b/src/optimization/add5_rule.cpp @@ -0,0 +1,57 @@ +#include "add5_rule.hpp" + +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/planner/expression/bound_operator_expression.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/common/types/value.hpp" +#include "duckdb/common/enums/expression_type.hpp" + +using namespace duckdb; + +namespace { + +// Wrap FLOAT/DOUBLE expr as COALESCE(expr, default_value) +static unique_ptr WrapCoalesceDefault(unique_ptr expr) { + const auto &rt = expr->return_type; + + if (rt.id() == LogicalTypeId::FLOAT) { + auto defv = make_uniq(Value::FLOAT(0.0f)); // pick any default you want + auto op = make_uniq(ExpressionType::OPERATOR_COALESCE, LogicalType::FLOAT); + op->children.push_back(std::move(expr)); + op->children.push_back(std::move(defv)); + return std::move(op); + } + if (rt.id() == LogicalTypeId::DOUBLE) { + auto defv = make_uniq(Value::DOUBLE(0.0)); + auto op = make_uniq(ExpressionType::OPERATOR_COALESCE, LogicalType::DOUBLE); + op->children.push_back(std::move(expr)); + op->children.push_back(std::move(defv)); + return std::move(op); + } + + // leave other types untouched + return expr; +} + +static void RewriteOp(LogicalOperator &op) { + if (op.type == LogicalOperatorType::LOGICAL_PROJECTION) { + auto &proj = op.Cast(); + for (auto &e : proj.expressions) { + std::cout << "Before: " << e->ToString() << std::endl; + e = WrapCoalesceDefault(std::move(e)); + std::cout << " After: " << e->ToString() << std::endl; + } + } + for (auto &child : op.children) { + RewriteOp(*child); + } +} + +} // namespace + +void Add5Rule::Apply(ClientContext &, unique_ptr &plan) { + if (!plan) return; + RewriteOp(*plan); + // optional: plan->ResolveOperatorTypes(); // helpful after edits +} diff --git a/src/optimization/add5_rule.hpp b/src/optimization/add5_rule.hpp new file mode 100644 index 0000000..4238b1e --- /dev/null +++ b/src/optimization/add5_rule.hpp @@ -0,0 +1,7 @@ +#pragma once +#include "duckdb.hpp" + +struct Add5Rule { + static void Apply(duckdb::ClientContext &ctx, + duckdb::unique_ptr &plan); +}; \ No newline at end of file diff --git a/src/optimization/register_optimizers.cpp b/src/optimization/register_optimizers.cpp new file mode 100644 index 0000000..0e02d70 --- /dev/null +++ b/src/optimization/register_optimizers.cpp @@ -0,0 +1,21 @@ +#include "register_optimizers.hpp" +#include "duckdb/optimizer/optimizer_extension.hpp" +#include "add5_rule.hpp" +#include "duckdb/main/database.hpp" + +namespace duckdb { + +struct CactusAdd5Opt : public OptimizerExtension { + CactusAdd5Opt() { optimize_function = Run; } + static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { + Add5Rule::Apply(in.context, plan); // always-on + } +}; + +void RegisterCactusOptimizers(DatabaseInstance &db) { + auto &cfg = DBConfig::GetConfig(db); + cfg.optimizer_extensions.push_back(CactusAdd5Opt{}); + // add more custom optimizer extensions here later +} + +} // namespace duckdb diff --git a/src/optimization/register_optimizers.hpp b/src/optimization/register_optimizers.hpp new file mode 100644 index 0000000..c71f4f0 --- /dev/null +++ b/src/optimization/register_optimizers.hpp @@ -0,0 +1,7 @@ +#pragma once +#include "duckdb.hpp" +#include "duckdb/main/database.hpp" + +namespace duckdb { +void RegisterCactusOptimizers(DatabaseInstance &db); +} // namespace duckdb diff --git a/test/sql/decision_tree.test b/test/sql/decision_tree.test new file mode 100644 index 0000000..737d4ff --- /dev/null +++ b/test/sql/decision_tree.test @@ -0,0 +1,110 @@ +# name: test/sql/tree_predict.test +# description: test tree_predict (file + has_missing) in cactusdb extension +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +# ------------------------------------------------------------------ +# Inputs: three rows of REAL vectors (no NULLs) +# ------------------------------------------------------------------ +statement ok +CREATE TABLE inputs(a REAL[]); + +statement ok +INSERT INTO inputs VALUES ([0,0,0]), ([1,1,1]), ([10,10,10]); + +# ------------------------------------------------------------------ +# A) BASIC: call tree_predict with has_missing = FALSE +# We don't assert exact numeric values (model-dependent). +# Instead we assert row count and deterministic equality on repeat. +# ------------------------------------------------------------------ + +# Should produce 3 rows +query I +SELECT COUNT(*) FROM ( + SELECT tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) AS y + FROM inputs +); +---- +3 + +# Deterministic: same call equals itself +query I +SELECT y_eq_self +FROM ( + SELECT + tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) + = + tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) + AS y_eq_self + FROM inputs + ORDER BY 1 +); +---- +true +true +true + +# ------------------------------------------------------------------ +# B) MISSING-HANDLING: include NULLs and use has_missing = TRUE +# We only assert that the function returns a non-NULL prediction. +# ------------------------------------------------------------------ + +statement ok +CREATE TABLE inputs_with_nulls(a REAL[]); + +statement ok +INSERT INTO inputs_with_nulls VALUES + ([NULL, 0.0, 1.0]), + ([2.0, NULL, 3.0]), + ([4.0, 5.0, NULL]); + +# Ensure all predictions are NOT NULL when has_missing = TRUE +query I +SELECT y_is_not_null +FROM ( + SELECT + tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', TRUE) IS NOT NULL AS y_is_not_null + FROM inputs_with_nulls + ORDER BY 1 +); +---- +true +true +true + +# ------------------------------------------------------------------ +# C) SANITY: stable across ORDER BY / re-evaluation +# Compare predictions from two identical queries (join on rowid) +# ------------------------------------------------------------------ + +statement ok +CREATE TEMP TABLE preds1 AS +SELECT row_number() OVER () AS rid, + tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) AS y +FROM inputs +ORDER BY 1; + +statement ok +CREATE TEMP TABLE preds2 AS +SELECT row_number() OVER () AS rid, + tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) AS y +FROM inputs +ORDER BY 1; + +# All rows should match exactly +query I +SELECT all_match +FROM ( + SELECT p1.y = p2.y AS all_match + FROM preds1 p1 + JOIN preds2 p2 USING (rid) + ORDER BY 1 +); +---- +true +true +true From 582eb30f8be6ddccaa96f691fd0c680f3e17f1a8 Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 8 Oct 2025 12:16:46 -0700 Subject: [PATCH 04/18] Replacing One hot encoder-1 with another using optimization extension --- .gitignore | 3 +- queries/expedia_query.sql | 6 +- queries/expedia_udf_filter_query.sql | 99 +++++++ src/include/ml_functions/one_hot_encoder.hpp | 82 ++++++ src/{ => include}/optimization/add5_rule.hpp | 0 .../optimization/register_optimizers.hpp | 0 .../optimization/replace_binding_rule.hpp | 26 ++ src/ml_functions/ml_functions_scalar.cpp | 2 +- src/ml_functions/one_hot_encoder.cpp | 263 +++++++----------- src/optimization/CMakeLists.txt | 1 + src/optimization/add5_rule.cpp | 3 +- src/optimization/register_optimizers.cpp | 74 ++++- src/optimization/replace_binding_rule.cpp | 135 +++++++++ test/sql/one_hot_encoder_rewrite_rule.test | 26 ++ 14 files changed, 550 insertions(+), 170 deletions(-) create mode 100644 queries/expedia_udf_filter_query.sql create mode 100644 src/include/ml_functions/one_hot_encoder.hpp rename src/{ => include}/optimization/add5_rule.hpp (100%) rename src/{ => include}/optimization/register_optimizers.hpp (100%) create mode 100644 src/include/optimization/replace_binding_rule.hpp create mode 100644 src/optimization/replace_binding_rule.cpp create mode 100644 test/sql/one_hot_encoder_rewrite_rule.test diff --git a/.gitignore b/.gitignore index 2e396f8..ca48c4e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ test/python/__pycache__/ *.csv vcpkg/ resources/* -duckdb/ \ No newline at end of file +duckdb/ +temp_dir/ diff --git a/queries/expedia_query.sql b/queries/expedia_query.sql index bce1fba..be618c2 100644 --- a/queries/expedia_query.sql +++ b/queries/expedia_query.sql @@ -4,8 +4,8 @@ ATTACH '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgex SET schema 'expedia_db.main'; -- Optimizer Config -PRAGMA disable_optimizer; -PRAGMA explain_output='optimized_only'; +PRAGMA enable_optimizer; +PRAGMA explain_output='json'; -- SET enable_profiling = 'query_tree_optimizer'; -- SET profiling_mode = 'detailed'; @@ -18,7 +18,7 @@ set threads = 8; -- SELECT 'Expedia_R1_hotels2' AS which, * FROM Expedia_R1_hotels2 LIMIT 10; -- SELECT 'Expedia_R2_searches' AS which, * FROM Expedia_R2_searches LIMIT 10; ---EXPLAIN ANALYZE +EXPLAIN ANALYZE SELECT s.prop_id, s.srch_id, diff --git a/queries/expedia_udf_filter_query.sql b/queries/expedia_udf_filter_query.sql new file mode 100644 index 0000000..b960ad4 --- /dev/null +++ b/queries/expedia_udf_filter_query.sql @@ -0,0 +1,99 @@ +-- Attach the database file and use its schema +ATTACH '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/data/expedia_imbridge2.db' + AS expedia_db (READ_ONLY); +SET schema 'expedia_db.main'; + +-- Optimizer Config +PRAGMA disable_optimizer; +-- PRAGMA explain_output='optimized_only'; +-- SET enable_profiling = 'query_tree_optimizer'; +-- SET profiling_mode = 'detailed'; + +LOAD 'cactusdb'; + +set threads = 8; + +EXPLAIN ANALYZE +SELECT + b.prop_id, + b.srch_id, + b.prediction, + r2.weekofyear, + r2.srch_booking_window +FROM ( + -- Inner: compute prediction after joining S+H+R and doing basic selective filters + SELECT + s.prop_id, + s.srch_id, + tree_predict( + list_transform( + list_concat( + /* 1) NUMERICALS — per-column scaling (exact order) */ + min_max_scaler(list_value(CAST(s.prop_location_score1 AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score1.txt'), + min_max_scaler(list_value(CAST(s.prop_location_score2 AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score2.txt'), + min_max_scaler(list_value(CAST(s.prop_log_historical_price AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_log_historical_price.txt'), + min_max_scaler(list_value(CAST(s.price_usd AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/price_usd.txt'), + min_max_scaler(list_value(CAST(s.orig_destination_distance AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/orig_destination_distance.txt'), + min_max_scaler(list_value(CAST(h.prop_review_score AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_review_score.txt'), + min_max_scaler(list_value(CAST(h.avg_bookings_usd AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/avg_bookings_usd.txt'), + min_max_scaler(list_value(CAST(h.stdev_bookings_usd AS DOUBLE)), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/stdev_bookings_usd.txt'), + + /* 2) CATEGORICALS — one-hot, exact order of your Python */ + -- stringEncoderSpecs (string→int): TRUE + one_hot_encode(CAST(s.position AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/position.csv', TRUE), + one_hot_encode(CAST(h.prop_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_country_id.csv', TRUE), + + -- encoderSpecs (int→int): FALSE + one_hot_encode(CAST(h.prop_starrating AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_starrating.csv', FALSE), + one_hot_encode(CAST(h.prop_brand_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_brand_bool.csv', FALSE), + one_hot_encode(CAST(h.count_clicks AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_clicks.csv', FALSE), + one_hot_encode(CAST(h.count_bookings AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_bookings.csv', FALSE), + + -- stringEncoderSpecs (string→int): TRUE + one_hot_encode(CAST(r.year AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/year.csv', TRUE), + one_hot_encode(CAST(r.month AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/month.csv', TRUE), + one_hot_encode(CAST(r.weekofyear AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/weekofyear.csv', TRUE), + one_hot_encode(CAST(r.time AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/time.csv', TRUE), + one_hot_encode(CAST(r.site_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/site_id.csv', TRUE), + one_hot_encode(CAST(r.visitor_location_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/visitor_location_country_id.csv', TRUE), + one_hot_encode(CAST(r.srch_destination_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_destination_id.csv', TRUE), + + -- encoderSpecs (int→int): FALSE + one_hot_encode(CAST(r.srch_length_of_stay AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_length_of_stay.csv', FALSE), + one_hot_encode(CAST(r.srch_booking_window AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_booking_window.csv', FALSE), + one_hot_encode(CAST(r.srch_adults_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_adults_count.csv', FALSE), + one_hot_encode(CAST(r.srch_children_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_children_count.csv', FALSE), + one_hot_encode(CAST(r.srch_room_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_room_count.csv', FALSE), + one_hot_encode(CAST(r.srch_saturday_night_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_saturday_night_bool.csv', FALSE), + one_hot_encode(CAST(r.random_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/random_bool.csv', FALSE) + ), + x -> CAST(x AS FLOAT) + ), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/tree/0.txt', + FALSE + ) AS prediction + FROM Expedia_S_listings_extension2 AS s + JOIN Expedia_R1_hotels2 AS h ON s.prop_id = h.prop_id + JOIN Expedia_R2_searches AS r ON s.srch_id = r.srch_id + WHERE s.prop_location_score1 > 1 + AND s.prop_location_score2 > 0.1 + AND s.prop_log_historical_price > 4 + AND h.count_bookings > 5 + AND r.srch_booking_window > 10 + AND r.srch_length_of_stay > 1 +) AS b +-- Outer: extra join layer (gives optimizer a place to push the prediction filter below) +JOIN Expedia_R2_searches AS r2 + ON b.srch_id = r2.srch_id +WHERE + -- This is the UDF in the WHERE filter (not just as a projected column) + b.prediction > 0.01 + AND r2.weekofyear IN ('10','11'); -- an extra selective filter on the outer side diff --git a/src/include/ml_functions/one_hot_encoder.hpp b/src/include/ml_functions/one_hot_encoder.hpp new file mode 100644 index 0000000..17b8c8e --- /dev/null +++ b/src/include/ml_functions/one_hot_encoder.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include "duckdb.hpp" +#include "duckdb/function/function.hpp" +#include +#include +#include +#include + +namespace duckdb { + +// --------------------------- +// Helper Definition +// --------------------------- +static void one_hot_encoder_bind_constructor( + const std::string path, + bool is_string, + std::map &str_map, + std::map &int_map +) { + std::ifstream in(path); + if (!in.is_open()) { + throw std::runtime_error("OneHot mapping file not found: " + path); + } + + std::string line; + std::getline(in, line); // optional header skip + + if (is_string) { + while (std::getline(in, line)) { + std::istringstream ss(line); + std::string valStr, posStr; + if (!std::getline(ss, valStr, ',')) continue; + if (!std::getline(ss, posStr, ',')) continue; + int position = std::stoi(posStr); + str_map[valStr] = position; + } + } else { + while (std::getline(in, line)) { + std::istringstream ss(line); + std::string valStr, posStr; + if (!std::getline(ss, valStr, ',')) continue; + if (!std::getline(ss, posStr, ',')) continue; + long long value = std::stoll(valStr); + int position = std::stoi(posStr); + int_map[(duckdb::idx_t)value] = position; + } + } +} + +struct ML_OneHotEncoder { + // ------------------------- + // BindData + // ------------------------- + struct BindData final : public FunctionData { + std::map str_to_index; + std::map int_to_index; + bool is_string; + + BindData() = default; + BindData(const std::map &s2i, + const std::map &i2i, + bool str) + : str_to_index(s2i), int_to_index(i2i), is_string(str) {} + + unique_ptr Copy() const override; + bool Equals(const FunctionData &other_p) const override; + }; + + // ------------------------- + // Lifecycle + // ------------------------- + static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args); + + static void Execute(DataChunk &args, ExpressionState &state, Vector &result); + + static void Register(ExtensionLoader &loader); +}; + +} // namespace duckdb diff --git a/src/optimization/add5_rule.hpp b/src/include/optimization/add5_rule.hpp similarity index 100% rename from src/optimization/add5_rule.hpp rename to src/include/optimization/add5_rule.hpp diff --git a/src/optimization/register_optimizers.hpp b/src/include/optimization/register_optimizers.hpp similarity index 100% rename from src/optimization/register_optimizers.hpp rename to src/include/optimization/register_optimizers.hpp diff --git a/src/include/optimization/replace_binding_rule.hpp b/src/include/optimization/replace_binding_rule.hpp new file mode 100644 index 0000000..d7308de --- /dev/null +++ b/src/include/optimization/replace_binding_rule.hpp @@ -0,0 +1,26 @@ +#pragma once +#include "duckdb.hpp" +#include +#include + +using namespace duckdb; + +struct ReplaceBindingRule { + static constexpr const char *kFuncName = "one_hot_encode"; + + std::string from_path; + std::string to_path; + std::optional require_third_bool; // std::nullopt = don't care + + ReplaceBindingRule(std::string fromp, std::string top, std::optional third = std::nullopt) + : from_path(std::move(fromp)), to_path(std::move(top)), require_third_bool(third) {} + + static void Optimize(OptimizerExtensionInput &input, + duckdb::unique_ptr &plan, + const ReplaceBindingRule &cfg); + +private: + static duckdb::unique_ptr RewriteExpr(duckdb::unique_ptr expr, + const ReplaceBindingRule &cfg); + static void RewriteOp(LogicalOperator &op, const ReplaceBindingRule &cfg); +}; diff --git a/src/ml_functions/ml_functions_scalar.cpp b/src/ml_functions/ml_functions_scalar.cpp index 49c18d5..eeae32c 100644 --- a/src/ml_functions/ml_functions_scalar.cpp +++ b/src/ml_functions/ml_functions_scalar.cpp @@ -1,7 +1,7 @@ #include "duckdb.hpp" #include "matrix_multiplication.cpp" #include "min_max_scaler.cpp" -#include "one_hot_encoder.cpp" +#include "ml_functions/one_hot_encoder.hpp" #include "decision_tree.cpp" namespace duckdb { diff --git a/src/ml_functions/one_hot_encoder.cpp b/src/ml_functions/one_hot_encoder.cpp index ea4f98f..760d8a1 100644 --- a/src/ml_functions/one_hot_encoder.cpp +++ b/src/ml_functions/one_hot_encoder.cpp @@ -1,169 +1,122 @@ -#include "duckdb.hpp" -#include "duckdb/function/function.hpp" +#include "ml_functions/one_hot_encoder.hpp" #include "duckdb/execution/expression_executor.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" -#include +#include "duckdb/common/types/value.hpp" +#include "duckdb/common/types/validity_mask.hpp" +#include #include +#include #include -#include -#include #include -#include namespace duckdb { - struct ML_OneHotEncoder { - public: - // ------------------------- - // BindData - // ------------------------- - struct BindData final : public FunctionData { - std::map str_to_index; - std::map int_to_index; - bool is_string; - - BindData() = default; - BindData(const std::map &s2i, const std::map &i2i, bool str) - : str_to_index(s2i), int_to_index(i2i), is_string(str) {} - - unique_ptr Copy() const override { - // deep copy (map copy is deep) - return make_uniq(str_to_index, int_to_index, is_string); - } - bool Equals(const FunctionData &other_p) const override { - auto &o = other_p.Cast(); - return str_to_index == o.str_to_index && - int_to_index == o.int_to_index && - is_string == o.is_string; - } - }; - // ------------------------- - // Bind Functions - // ------------------------- - static unique_ptr Bind(ClientContext &context, - ScalarFunction &bound_function, - vector> &args) { - // Expecting 3 arguments: x, categories_list, is_string - if (args.size() != 3) { - throw InvalidInputException("one_hot_encoder expects 3 arguments: x, categories_list, is_string"); - } - - auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); - auto vis_string = ExpressionExecutor::EvaluateScalar(context, *args[2]); - const std::string path = vFile.ToString(); - const bool is_string = vis_string.GetValue(); - std::ifstream in(path); - if (!in) { - throw std::runtime_error("OneHot mapping file not found: " + path); - } - std::string line; - std::getline(in, line); // skip header - - std::map str_map; - std::map int_map; - - if(is_string){ - - while (std::getline(in, line)) { - std::istringstream ss(line); - std::string valStr, posStr; - if (!std::getline(ss, valStr, ',')) continue; - if (!std::getline(ss, posStr, ',')) continue; - // int64_t value = std::stoll(valStr); - int position = std::stoi(posStr); - str_map[valStr] = position; - } - } - else{ - - while (std::getline(in, line)) { - std::istringstream ss(line); - std::string valStr, posStr; - if (!std::getline(ss, valStr, ',')) continue; - if (!std::getline(ss, posStr, ',')) continue; - int64_t value = std::stoll(valStr); - int position = std::stoi(posStr); - int_map[value] = position; - } +// ---------- BindData impl ---------- +unique_ptr ML_OneHotEncoder::BindData::Copy() const { + return make_uniq(str_to_index, int_to_index, is_string); +} +bool ML_OneHotEncoder::BindData::Equals(const FunctionData &other_p) const { + auto &o = other_p.Cast(); + return str_to_index == o.str_to_index && + int_to_index == o.int_to_index && + is_string == o.is_string; +} + +// ---------- Bind ---------- +unique_ptr ML_OneHotEncoder::Bind(ClientContext &context, + ScalarFunction & /*bound_function*/, + vector> &args) { + // Expecting 3 arguments: x, categories_file, is_string + if (args.size() != 3) { + throw InvalidInputException("one_hot_encode expects 3 arguments: x, categories_file, is_string"); + } + + auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); + auto vIsString = ExpressionExecutor::EvaluateScalar(context, *args[2]); + + const std::string path = vFile.ToString(); + const bool is_string = vIsString.GetValue(); + + std::map str_map; + std::map int_map; + + // Load mapping (single helper function defined elsewhere) + one_hot_encoder_bind_constructor(path, is_string, str_map, int_map); + + return make_uniq(str_map, int_map, is_string); +} + +// ---------- Execute ---------- +void ML_OneHotEncoder::Execute(DataChunk &args, ExpressionState &state, Vector &result) { + const idx_t count = args.size(); + + const auto &func_expr = state.expr.Cast(); + const auto &bd = func_expr.bind_info->Cast(); + const idx_t k = bd.is_string ? (idx_t)bd.str_to_index.size() + : (idx_t)bd.int_to_index.size(); + + Vector &f = args.data[0]; + UnifiedVectorFormat f_uvf; + f.ToUnifiedFormat(count, f_uvf); + + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + const idx_t total = count * k; + ListVector::Reserve(result, total); + ListVector::SetListSize(result, total); + + auto *out = FlatVector::GetData(res_child); + auto &res_valid = FlatVector::Validity(result); + + idx_t cursor = 0; + for (idx_t i = 0; i < count; i++) { + const idx_t sel_idx = f_uvf.sel->get_index(i); + if (f_uvf.validity.RowIsValid(sel_idx)) { + res_entries[i] = {cursor, k}; + const auto sref = UnifiedVectorFormat::GetData(f_uvf)[sel_idx]; + + idx_t pos = DConstants::INVALID_INDEX; + if (bd.is_string) { + std::string key = sref.GetString(); + auto it = bd.str_to_index.find(key); + if (it != bd.str_to_index.end()) pos = it->second; + } else { + idx_t key = (idx_t)std::stoll(sref.GetString()); + auto it = bd.int_to_index.find(key); + if (it != bd.int_to_index.end()) pos = it->second; + } + if (pos != DConstants::INVALID_INDEX) { + for (idx_t j = 0; j < k; j++) { + out[cursor++] = (j == pos) ? 1.0 : 0.0; } - - in.close(); - return make_uniq(str_map, int_map, is_string); - - } - - // ------------------------- - // Execute - // ------------------------- - static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { - idx_t count = args.size(); - - const auto &func_expr = state.expr.Cast(); - const auto &bd = func_expr.bind_info->Cast(); - const idx_t k = bd.is_string ? (idx_t)bd.str_to_index.size() - : (idx_t)bd.int_to_index.size(); - - Vector &f = args.data[0]; - UnifiedVectorFormat f_uvf; - f.ToUnifiedFormat(count, f_uvf); - - result.SetVectorType(VectorType::FLAT_VECTOR); - auto *res_entries = FlatVector::GetData(result); - auto &res_child = ListVector::GetEntry(result); - const idx_t total_out = count * k; - ListVector::Reserve(result, total_out); - ListVector::SetListSize(result, total_out); - double *out = FlatVector::GetData(res_child); - auto &res_valid = FlatVector::Validity(result); - - idx_t cursor = 0; - for (idx_t i = 0; i < count; i++) { - idx_t idx = f_uvf.sel->get_index(i); - if (f_uvf.validity.RowIsValid(idx)) { - res_entries[i] = {cursor, k}; - const auto sref = UnifiedVectorFormat::GetData(f_uvf)[idx]; - idx_t pos = -1; - if (bd.is_string) { - std::string key = sref.GetString(); - auto it = bd.str_to_index.find(key); - if(it!=bd.str_to_index.end()) pos = it->second; - } else { - idx_t key = stoi(sref.GetString()); - auto it = bd.int_to_index.find(key); - if(it!=bd.int_to_index.end())pos = it->second; - } - if (pos != -1) { - for (idx_t j = 0; j < k; j++) { - out[cursor++] = (j == pos) ? 1.0 : 0.0; - } - } else { - // Unknown category, all zeros - for (idx_t j = 0; j < k; j++) { - out[cursor++] = 0.0; - } - } - } else { - // null entry - res_entries[i] = {0, 0}; - res_valid.SetInvalid(i); + } else { + for (idx_t j = 0; j < k; j++) { + out[cursor++] = 0.0; } } + } else { + // null input → null list + res_entries[i] = {0, 0}; + res_valid.SetInvalid(i); } - - static void Register(ExtensionLoader &loader) { - // Logical signature with filename; Bind erases it so Exec sees only x. - ScalarFunction fn( - "one_hot_encode", - { LogicalType::VARCHAR, // x - LogicalType::VARCHAR, // categories_file - LogicalType::BOOLEAN }, // is_string - LogicalType::LIST(LogicalType::DOUBLE), // return type - Execute - ); - fn.bind = Bind; - loader.RegisterFunction(fn); - } - }; -} \ No newline at end of file + } +} + +// ---------- Register ---------- +void ML_OneHotEncoder::Register(ExtensionLoader &loader) { + // (x VARCHAR, categories_file VARCHAR, is_string BOOLEAN) -> DOUBLE[] + ScalarFunction fn( + "one_hot_encode", + { LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::BOOLEAN }, + LogicalType::LIST(LogicalType::DOUBLE), + Execute + ); + fn.bind = Bind; + fn.stability = FunctionStability::VOLATILE; // reads a file; avoid constant folding if desired + loader.RegisterFunction(fn); +} + +} // namespace duckdb \ No newline at end of file diff --git a/src/optimization/CMakeLists.txt b/src/optimization/CMakeLists.txt index 8d63670..caeb4b7 100644 --- a/src/optimization/CMakeLists.txt +++ b/src/optimization/CMakeLists.txt @@ -1,6 +1,7 @@ # Append optimizer sources to the extension's global list list(APPEND EXTENSION_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/add5_rule.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/replace_binding_rule.cpp ${CMAKE_CURRENT_SOURCE_DIR}/register_optimizers.cpp ) diff --git a/src/optimization/add5_rule.cpp b/src/optimization/add5_rule.cpp index 38c5f18..2fcb641 100644 --- a/src/optimization/add5_rule.cpp +++ b/src/optimization/add5_rule.cpp @@ -1,4 +1,4 @@ -#include "add5_rule.hpp" +#include "optimization/add5_rule.hpp" #include "duckdb/planner/logical_operator.hpp" #include "duckdb/planner/operator/logical_projection.hpp" @@ -51,6 +51,7 @@ static void RewriteOp(LogicalOperator &op) { } // namespace void Add5Rule::Apply(ClientContext &, unique_ptr &plan) { + std::cout << plan->ToString() << "\n\n\n"; if (!plan) return; RewriteOp(*plan); // optional: plan->ResolveOperatorTypes(); // helpful after edits diff --git a/src/optimization/register_optimizers.cpp b/src/optimization/register_optimizers.cpp index 0e02d70..ddad37d 100644 --- a/src/optimization/register_optimizers.cpp +++ b/src/optimization/register_optimizers.cpp @@ -1,21 +1,77 @@ -#include "register_optimizers.hpp" +// register_optimizers.cpp +#include "optimization/register_optimizers.hpp" + +#include "duckdb/main/database.hpp" #include "duckdb/optimizer/optimizer_extension.hpp" + #include "add5_rule.hpp" -#include "duckdb/main/database.hpp" +#include "replace_binding_rule.hpp" // <-- from the code I shared earlier + +#include +#include +#include namespace duckdb { +// ----------------------------- +// Pass 1: your existing Add5Rule +// ----------------------------- struct CactusAdd5Opt : public OptimizerExtension { - CactusAdd5Opt() { optimize_function = Run; } - static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { - Add5Rule::Apply(in.context, plan); // always-on - } + CactusAdd5Opt() { optimize_function = Run; } + + static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { + Add5Rule::Apply(in.context, plan); // always-on + } +}; + +// ----------------------------- +// Pass 2: binding-file replacement for one_hot_encode +// ----------------------------- +struct CactusReplaceBindingOpt : public OptimizerExtension { + CactusReplaceBindingOpt() { optimize_function = Run; } + + // Adjust these mappings however you like. You can add many. + // Each entry: { from_path, to_path, require_third_bool } + using MapEntry = std::tuple>; + + static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { + if (!plan) return; + + // Example mappings (fill with your real paths): + // If you don't want to constrain the 3rd argument, use std::nullopt. + const std::vector mappings = { + { + "/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/test/resources/month.csv", + "/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/test/resources/month_alt.csv", + /*require_third_bool=*/std::optional{true} // only when the 3rd arg is TRUE + }, + // Add more file swaps here: + // { "", "", std::nullopt }, // don't care about 3rd arg + // { "", "", std::optional{false} }, // only when 3rd arg is FALSE + }; + + for (const auto &m : mappings) { + const auto &from_file = std::get<0>(m); + const auto &to_file = std::get<1>(m); + const auto &third_req = std::get<2>(m); + + ReplaceBindingRule cfg(from_file, to_file, third_req); + ReplaceBindingRule::Optimize(in, plan, cfg); + } + // No type changes; ResolveOperatorTypes() not required. + } }; +// ----------------------------- +// Registration hook +// ----------------------------- void RegisterCactusOptimizers(DatabaseInstance &db) { - auto &cfg = DBConfig::GetConfig(db); - cfg.optimizer_extensions.push_back(CactusAdd5Opt{}); - // add more custom optimizer extensions here later + auto &cfg = DBConfig::GetConfig(db); + + // Order matters if passes depend on one another. + // Typically do argument/string rewrites early, then other expression rewrites. + cfg.optimizer_extensions.push_back(CactusReplaceBindingOpt{}); + cfg.optimizer_extensions.push_back(CactusAdd5Opt{}); } } // namespace duckdb diff --git a/src/optimization/replace_binding_rule.cpp b/src/optimization/replace_binding_rule.cpp new file mode 100644 index 0000000..505b583 --- /dev/null +++ b/src/optimization/replace_binding_rule.cpp @@ -0,0 +1,135 @@ +#include "optimization/replace_binding_rule.hpp" + +#include "duckdb/common/string_util.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/planner/expression_iterator.hpp" +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/planner/operator/logical_filter.hpp" +#include "duckdb/planner/operator/logical_aggregate.hpp" +#include "duckdb/planner/operator/logical_comparison_join.hpp" +#include "duckdb/planner/operator/logical_join.hpp" + +#include "duckdb/planner/operator/logical_filter.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/planner/operator/logical_aggregate.hpp" +#include "duckdb/planner/operator/logical_comparison_join.hpp" +#include "duckdb/common/enums/expression_type.hpp" +#include "ml_functions/one_hot_encoder.hpp" +// #include "bind_utils/one_hot_encoder_bind_util.hpp" +// no need for if we use a template helper + + +using namespace duckdb; + +static bool ArgIsVarcharConstant(const duckdb::unique_ptr &arg, string &out) { + if (!arg || arg->expression_class != ExpressionClass::BOUND_CONSTANT) return false; + auto &c = arg->Cast(); + if (c.value.type().id() != LogicalTypeId::VARCHAR) return false; + out = StringValue::Get(c.value); + return true; +} + +static bool ArgIsBoolConstant(const duckdb::unique_ptr &arg, bool &out) { + if (!arg || arg->expression_class != ExpressionClass::BOUND_CONSTANT) return false; + auto &c = arg->Cast(); + if (c.value.type().id() != LogicalTypeId::BOOLEAN) return false; + out = BooleanValue::Get(c.value); + return true; +} + +duckdb::unique_ptr +ReplaceBindingRule::RewriteExpr(duckdb::unique_ptr expr, const ReplaceBindingRule &cfg) { + if (!expr) return expr; + + std::cout << "Examining expr: " << ExpressionTypeToString(expr->type) << " " << ExpressionClassToString(expr->expression_class) << "\n"; + + // Recurse first + ExpressionIterator::EnumerateChildren(*expr, [&](duckdb::unique_ptr &child) { + child = RewriteExpr(std::move(child), cfg); + }); + + // std::cout << expr.ToString() << "\n\n"; + + // Match function node + if (expr->expression_class == ExpressionClass::BOUND_FUNCTION) { + std::cout << "\nBound function found\n"; + auto &f = expr->Cast(); + std::cout << f.function.name << " " << cfg.kFuncName << "\n"; + if (f.function.name == cfg.kFuncName) { + auto &bd = f.bind_info->Cast(); + + //change the argument from the path to another path + f.children[1] = make_uniq(Value(cfg.to_path)); + + //change the bind data to reflect data from new path + std::map str_map; + std::map int_map; + const bool is_string = bd.is_string; + + one_hot_encoder_bind_constructor(cfg.to_path, is_string, str_map, int_map); + f.bind_info = make_uniq(str_map, int_map, is_string); + + + } + } + return expr; +} + +// ---- Polyfill: enumerate/mutate expressions for common operator types ---- +// Visit & mutate expressions held by common logical operators in your query +template +static void ForEachExpression(LogicalOperator &op, Fn &&fn) { + switch (op.type) { + case LogicalOperatorType::LOGICAL_PROJECTION: { + auto &proj = op.Cast(); + for (auto &e : proj.expressions) fn(e); + break; + } + case LogicalOperatorType::LOGICAL_FILTER: { + auto &fil = op.Cast(); + for (auto &e : fil.expressions) fn(e); + break; + } + case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: { + auto &agg = op.Cast(); + for (auto &e : agg.expressions) fn(e); + for (auto &g : agg.groups) fn(g); + break; + } + case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: { + auto &cj = op.Cast(); + for (auto &cond : cj.conditions) { + fn(cond.left); + fn(cond.right); + } + break; + } + default: + // Add more operator cases as needed (WINDOW/ORDER/etc) for other queries + break; + } +} + + +void ReplaceBindingRule::RewriteOp(LogicalOperator &op, const ReplaceBindingRule &cfg) { + // Mutate expressions of this operator + ForEachExpression(op, [&](duckdb::unique_ptr &e) { + e = RewriteExpr(std::move(e), cfg); + }); + + // Recurse into children + for (auto &child : op.children) { + RewriteOp(*child, cfg); + } +} + + +void ReplaceBindingRule::Optimize(OptimizerExtensionInput &input, + duckdb::unique_ptr &plan, + const ReplaceBindingRule &cfg) { + if (!plan) return; + RewriteOp(*plan, cfg); + // plan->ResolveOperatorTypes(); // not needed +} diff --git a/test/sql/one_hot_encoder_rewrite_rule.test b/test/sql/one_hot_encoder_rewrite_rule.test new file mode 100644 index 0000000..632467d --- /dev/null +++ b/test/sql/one_hot_encoder_rewrite_rule.test @@ -0,0 +1,26 @@ +# name: test/sql/replace_binding_rule.test +# group: [sql] +require cactusdb + +statement ok +LOAD cactusdb; + +statement ok +PRAGMA disable_optimizer; + +# If you want to assert a value, use a query block with expected output: +# (adjust the expected list to match your CSV) +query I +SELECT one_hot_encode('red', '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/test/resources/month.csv', TRUE) AS y; +---- +[1.0, 0.0, 0.0, 0.0] + +statement ok +PRAGMA enable_optimizer; + +query I +SELECT one_hot_encode('red', '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/test/resources/month.csv', TRUE) AS y; +---- +[0.0, 0.0, 0.0, 1.0] + + From 122511745e6205fb2d4f48de8d16719445b743fa Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 8 Oct 2025 12:22:32 -0700 Subject: [PATCH 05/18] Removing unnecessary rules --- src/optimization/replace_binding_rule.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/optimization/replace_binding_rule.cpp b/src/optimization/replace_binding_rule.cpp index 505b583..39682d2 100644 --- a/src/optimization/replace_binding_rule.cpp +++ b/src/optimization/replace_binding_rule.cpp @@ -70,8 +70,6 @@ ReplaceBindingRule::RewriteExpr(duckdb::unique_ptr expr, const Repla one_hot_encoder_bind_constructor(cfg.to_path, is_string, str_map, int_map); f.bind_info = make_uniq(str_map, int_map, is_string); - - } } return expr; @@ -92,12 +90,6 @@ static void ForEachExpression(LogicalOperator &op, Fn &&fn) { for (auto &e : fil.expressions) fn(e); break; } - case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: { - auto &agg = op.Cast(); - for (auto &e : agg.expressions) fn(e); - for (auto &g : agg.groups) fn(g); - break; - } case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: { auto &cj = op.Cast(); for (auto &cond : cj.conditions) { From 55e9536e69211e9fbbf1f3d312865ab939c33505 Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Fri, 10 Oct 2025 12:59:14 -0700 Subject: [PATCH 06/18] Matrix Multiplication Dense To Sparse Rule Check and Application --- .../ml_functions/matrix_multiplication.hpp | 131 +++++ .../MatMulDense2SparseRewriteAction.hpp | 10 + .../optimization/dynamic_optimizer.hpp | 7 + src/ml_functions/matrix_multiplication.cpp | 528 +++++++++++------- src/ml_functions/ml_functions_scalar.cpp | 2 +- src/optimization/CMakeLists.txt | 4 + .../MatMulDense2SparseRewriteAction.cpp | 118 ++++ src/optimization/dynamic_optimizer.cpp | 29 + src/optimization/register_optimizers.cpp | 22 +- src/optimization/replace_binding_rule.cpp | 16 - test/sql/matmul.test | 4 +- 11 files changed, 647 insertions(+), 224 deletions(-) create mode 100644 src/include/ml_functions/matrix_multiplication.hpp create mode 100644 src/include/optimization/actions/MatMulDense2SparseRewriteAction.hpp create mode 100644 src/include/optimization/dynamic_optimizer.hpp create mode 100644 src/optimization/actions/MatMulDense2SparseRewriteAction.cpp create mode 100644 src/optimization/dynamic_optimizer.cpp diff --git a/src/include/ml_functions/matrix_multiplication.hpp b/src/include/ml_functions/matrix_multiplication.hpp new file mode 100644 index 0000000..7e7e1cc --- /dev/null +++ b/src/include/ml_functions/matrix_multiplication.hpp @@ -0,0 +1,131 @@ +#pragma once + +#include +#include +#include + +#include "duckdb.hpp" // umbrella header (brings in FunctionData, ScalarFunction, DataChunk, etc.) +#include "duckdb/function/function.hpp" + +#include +#include +#include + +namespace duckdb { + +struct ML_MatrixMultiply { + // TODO + // 2 and 3, only Dense and InputSparse supported + enum class MulMode : uint8_t { Dense = 0, InputSparse = 1, WeightSparse = 2, BothSparse = 3 }; + + // ------------------------- + // Bind Data + // ------------------------- + struct BindData final : public FunctionData { + std::vector weights; // row-major [k * n] + idx_t k = 0; // rows in weights (input length) + idx_t n = 0; // cols in weights (output length) + std::string weights_file; + bool has_bound_weights = false; + + // MatMul Mode + MulMode mode = MulMode::Dense; + + BindData() = default; + BindData(const std::vector &w, idx_t k_, idx_t n_, + const std::string &file, bool bound, MulMode mode_); + + unique_ptr Copy() const override; + bool Equals(const FunctionData &other) const override; + }; + + // ------------------------- + // Registration + // ------------------------- + static void Register(ExtensionLoader &loader); + + // ------------------------- + // DuckDB hooks + // ------------------------- + static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args); + + static void Execute(DataChunk &args, ExpressionState &state, Vector &result); + + // ------------------------- + // Helpers + // ------------------------- + static void ParseCSVWeights(const std::string &path, + std::vector &W, + idx_t &k, + idx_t &n){ + std::ifstream f(path); + if (!f.is_open()) { + throw InvalidInputException("matmul: cannot open weights file: %s", path.c_str()); + } + W.clear(); + k = 0; + + bool have_n = false; // <- replace the sentinel + n = 0; + + std::string line; + while (std::getline(f, line)) { + if (line.empty()) continue; + + std::stringstream ss(line); + std::string cell; + idx_t col_count = 0; + + while (std::getline(ss, cell, ',')) { + auto l = cell.find_first_not_of(" \t\r\n"); + auto r = cell.find_last_not_of(" \t\r\n"); + std::string trimmed = (l == std::string::npos) ? "" : cell.substr(l, r - l + 1); + + if (trimmed.empty()) { + throw InvalidInputException("matmul: empty field in weights file: %s", path.c_str()); + } + try { + W.emplace_back(std::stod(trimmed)); + } catch (...) { + throw InvalidInputException("matmul: non-numeric weight '%s' in %s", + trimmed.c_str(), path.c_str()); + } + col_count++; + } + + if (col_count == 0) continue; + + if (!have_n) { + n = col_count; + have_n = true; + } else if (n != col_count) { + throw InvalidInputException( + "matmul: ragged row in weights file %s (got %llu cols, expected %llu)", + path.c_str(), + (unsigned long long)col_count, + (unsigned long long)n + ); + } + k++; + } + + if (k == 0 || !have_n) { + throw InvalidInputException("matmul: empty weights file: %s", path.c_str()); + } + if (W.size() != (size_t)(k * n)) { + throw InternalException("matmul: internal size mismatch after parsing %s", path.c_str()); + } + } // end of ParseCSVWeights + + static ML_MatrixMultiply::MulMode ParseModeValue(const Value &v) { + auto s = StringUtil::Lower(v.ToString()); + if (s == "dense") return ML_MatrixMultiply::MulMode::Dense; + if (s == "sparse") return ML_MatrixMultiply::MulMode::InputSparse; + throw BinderException("matmul: unknown mode '%s' (expected 'dense' or 'input_sparse')", s.c_str()); + } + +}; + +} // namespace duckdb diff --git a/src/include/optimization/actions/MatMulDense2SparseRewriteAction.hpp b/src/include/optimization/actions/MatMulDense2SparseRewriteAction.hpp new file mode 100644 index 0000000..a08a6cf --- /dev/null +++ b/src/include/optimization/actions/MatMulDense2SparseRewriteAction.hpp @@ -0,0 +1,10 @@ +#include "duckdb.hpp" + +namespace duckdb { + struct MatMulDense2SparseRewriteAction { + // It needs to have a check method and a rewrite method + static bool check(OptimizerExtensionInput &input, unique_ptr &plan); + + static bool apply(OptimizerExtensionInput &input, unique_ptr &plan); + }; +} \ No newline at end of file diff --git a/src/include/optimization/dynamic_optimizer.hpp b/src/include/optimization/dynamic_optimizer.hpp new file mode 100644 index 0000000..60beb25 --- /dev/null +++ b/src/include/optimization/dynamic_optimizer.hpp @@ -0,0 +1,7 @@ +#include "duckdb.hpp" + +namespace duckdb{ + struct DynamicOpt { + static void Optimize(OptimizerExtensionInput &input, duckdb::unique_ptr &plan); + }; +} \ No newline at end of file diff --git a/src/ml_functions/matrix_multiplication.cpp b/src/ml_functions/matrix_multiplication.cpp index e282ada..bae2c97 100644 --- a/src/ml_functions/matrix_multiplication.cpp +++ b/src/ml_functions/matrix_multiplication.cpp @@ -1,255 +1,381 @@ -#include -#include -#include +#include "ml_functions/matrix_multiplication.hpp" + +#include #include #include -#include "functions.hpp" -#include "duckdb.hpp" -#include "duckdb/common/types/value.hpp" -#include "duckdb/common/types.hpp" + +#include +#include + +#include "duckdb/common/constants.hpp" #include "duckdb/common/enum_util.hpp" #include "duckdb/common/exception.hpp" #include "duckdb/common/string_util.hpp" -#include "duckdb/function/scalar_function.hpp" -#include -#include "duckdb/common/constants.hpp" +#include "duckdb/common/types.hpp" #include "duckdb/common/types/blob.hpp" -#include "duckdb/common/vector_operations/generic_executor.hpp" +#include "duckdb/common/types/value.hpp" #include "duckdb/execution/expression_executor.hpp" +#include "duckdb/function/scalar_function.hpp" +#include "duckdb/parser/parsed_data/create_scalar_function_info.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/common/vector_operations/generic_executor.hpp" #include "duckdb/common/vector_operations/septenary_executor.hpp" -#include "duckdb/planner/expression/bound_constant_expression.hpp" namespace duckdb { -struct ML_MatrixMultiply { - -public: - // ------------------------- - // Helpers - // ------------------------- - static void ParseCSVWeights(const std::string &path, - std::vector &W, idx_t &k, idx_t &n) { - std::ifstream f(path); - if (!f.is_open()) { - throw InvalidInputException("matmul: cannot open weights file: %s", path.c_str()); - } - W.clear(); - k = 0; - - bool have_n = false; // <- replace the sentinel - n = 0; - - std::string line; - while (std::getline(f, line)) { - if (line.empty()) continue; - - std::stringstream ss(line); - std::string cell; - idx_t col_count = 0; - - while (std::getline(ss, cell, ',')) { - auto l = cell.find_first_not_of(" \t\r\n"); - auto r = cell.find_last_not_of(" \t\r\n"); - std::string trimmed = (l == std::string::npos) ? "" : cell.substr(l, r - l + 1); - - if (trimmed.empty()) { - throw InvalidInputException("matmul: empty field in weights file: %s", path.c_str()); - } - try { - W.emplace_back(std::stod(trimmed)); - } catch (...) { - throw InvalidInputException("matmul: non-numeric weight '%s' in %s", - trimmed.c_str(), path.c_str()); - } - col_count++; - } +// ========================= +// BindData impl +// ========================= - if (col_count == 0) continue; - - if (!have_n) { - n = col_count; - have_n = true; - } else if (n != col_count) { - throw InvalidInputException( - "matmul: ragged row in weights file %s (got %llu cols, expected %llu)", - path.c_str(), - (unsigned long long)col_count, - (unsigned long long)n - ); - } - k++; - } +ML_MatrixMultiply::BindData::BindData(const std::vector &w, + idx_t k_, + idx_t n_, + const std::string &file, + bool bound, + MulMode mode_) + : weights(w), k(k_), n(n_), weights_file(file), has_bound_weights(bound), mode(mode_) {} - if (k == 0 || !have_n) { - throw InvalidInputException("matmul: empty weights file: %s", path.c_str()); - } - if (W.size() != (size_t)(k * n)) { - throw InternalException("matmul: internal size mismatch after parsing %s", path.c_str()); - } - } +unique_ptr ML_MatrixMultiply::BindData::Copy() const { + return std::make_unique(weights, k, n, weights_file, has_bound_weights,mode); +} +bool ML_MatrixMultiply::BindData::Equals(const FunctionData &other_p) const { + auto &o = other_p.Cast(); + return has_bound_weights == o.has_bound_weights && + k == o.k && n == o.n && + weights_file == o.weights_file && + weights == o.weights && + mode == o.mode; +} +// ========================= +// Bind +// ========================= - // ------------------------- - // Bind Data - // ------------------------- - // add binding structure here - struct BindData final : public FunctionData { - std::vector weights; // row-major [k * n] - idx_t k = 0; // rows in weights (input length) - idx_t n = 0; // cols in weights (output length) - std::string weights_file; - bool has_bound_weights = false; +unique_ptr ML_MatrixMultiply::Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + // Expect: x LIST, filename VARCHAR + if (args.size() != 3) { + throw BinderException("matmul expects 3 arguments: (x LIST, weights_file VARCHAR, mode VARCHAR)"); + } - BindData() = default; + // Force filename to be constant; fold it at bind time + if (!args[1]->IsFoldable()) { + throw BinderException("matmul: weights_file must be a constant string"); + } - BindData(const std::vector &w, idx_t k_, idx_t n_, - const std::string &file, bool bound) - : weights(w), k(k_), n(n_), weights_file(file), has_bound_weights(bound) {} + auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); + if (vFile.IsNull()) { + throw BinderException("matmul: weights_file is NULL"); + } + const std::string path = vFile.ToString(); - unique_ptr Copy() const override { - // deep copy (vector/string copy is deep) - return make_uniq(weights, k, n, weights_file, has_bound_weights); - } + std::vector W; + idx_t K = 0, N = 0; + ParseCSVWeights(path, W, K, N); - bool Equals(const FunctionData &other_p) const override { - auto &o = other_p.Cast(); - return has_bound_weights == o.has_bound_weights && - k == o.k && n == o.n && - weights_file == o.weights_file && - weights == o.weights; - } - }; + auto vMode = ExpressionExecutor::EvaluateScalar(context, *args[2]); + MulMode mode = ParseModeValue(vMode); + // If you want execution to only receive the input vector, uncomment + // the following line to erase the filename argument at bind-time. + // Function::EraseArgument(bound_function, args, 1); - // add binding method here - static unique_ptr Bind(ClientContext &context, - ScalarFunction &bound_function, - vector> &args) { - // Expect: x LIST, filename VARCHAR - if (args.size() != 2) { - throw BinderException("matmul expects 2 arguments: (x LIST, weights_file VARCHAR)"); - } + return std::make_unique(W, K, N, path, /*bound*/ true, mode); +} - // Force filename to be constant; fold it at bind time - if (!args[1]->IsFoldable()) { - throw BinderException("matmul: weights_file must be a constant string"); - } +// ========================= +// Execute +// ========================= + +// void ML_MatrixMultiply::Execute(DataChunk &args, ExpressionState &state, Vector &result) { +// idx_t count = args.size(); // number of tuples in a DataChunk + +// // Read left-hand side matrix from the argument +// Vector &lhs = args.data[0]; +// UnifiedVectorFormat lhs_uvf; +// lhs.ToUnifiedFormat(count, lhs_uvf); +// const auto *entries = UnifiedVectorFormat::GetData(lhs_uvf); // {offset, length} per row + +// auto &child = ListVector::GetEntry(lhs); // the child that holds the list payload +// const idx_t total_elems = ListVector::GetListSize(lhs); +// UnifiedVectorFormat child_uvf; +// child.ToUnifiedFormat(total_elems, child_uvf); +// const double *child_data = UnifiedVectorFormat::GetData(child_uvf); + +// // Build a dense row-major Eigen matrix X from the selected rows +// Eigen::Matrix X; +// idx_t columns = (idx_t)-1; + +// for (idx_t i = 0; i < count; i++) { +// const idx_t idx = lhs_uvf.sel->get_index(i); +// if (lhs_uvf.validity.RowIsValid(idx)) { +// const idx_t row_len = entries[idx].length; +// if (i == 0) { +// columns = row_len; +// X.resize((Eigen::Index)count, (Eigen::Index)columns); +// } else { +// if (columns != row_len) { +// throw InvalidInputException("Input Matrix has uneven rows. Error at row %llu", +// (unsigned long long)i); +// } +// } +// const double *row_ptr = child_data + entries[idx].offset; +// std::memcpy(X.data() + i * columns, row_ptr, sizeof(double) * (size_t)columns); +// } +// } + +// // Prepare weight matrix using the bound data +// const auto &func_expr = state.expr.Cast(); +// const auto &bd = func_expr.bind_info->Cast(); +// using RowMat = Eigen::Matrix; +// Eigen::Map W(bd.weights.data(), (Eigen::Index)bd.k, (Eigen::Index)bd.n); + +// // X (count x k) * W (k x n) = Y (count x n) +// Eigen::Matrix Y = X * W; + +// // Materialize result as LIST with one list per input row (length = n) +// result.SetVectorType(VectorType::FLAT_VECTOR); +// auto *res_entries = FlatVector::GetData(result); +// auto &res_child = ListVector::GetEntry(result); + +// const idx_t n = bd.n; +// const idx_t total = count * n; +// ListVector::Reserve(result, total); +// ListVector::SetListSize(result, total); +// double *out = FlatVector::GetData(res_child); +// auto &res_valid = FlatVector::Validity(result); + +// idx_t cursor = 0; +// for (idx_t i = 0; i < count; ++i) { +// const idx_t idx = lhs_uvf.sel->get_index(i); +// if (!lhs_uvf.validity.RowIsValid(idx)) { +// res_entries[i] = {0, 0}; +// res_valid.Set(i, false); +// continue; +// } +// res_entries[i].offset = cursor; +// res_entries[i].length = n; +// std::memcpy(out + cursor, Y.data() + i * n, sizeof(double) * (size_t)n); +// cursor += n; +// } +// } - auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); - if (vFile.IsNull()) { - throw BinderException("matmul: weights_file is NULL"); +void ML_MatrixMultiply::Execute(DataChunk &args, ExpressionState &state, Vector &result) { + const idx_t count = args.size(); // tuples in this chunk + + // Input LIST + Vector &lhs = args.data[0]; + UnifiedVectorFormat lhs_uvf; + lhs.ToUnifiedFormat(count, lhs_uvf); + const auto *entries = UnifiedVectorFormat::GetData(lhs_uvf); + + auto &child = ListVector::GetEntry(lhs); + const idx_t total_elems = ListVector::GetListSize(lhs); + UnifiedVectorFormat child_uvf; + child.ToUnifiedFormat(total_elems, child_uvf); + const double *child_data = UnifiedVectorFormat::GetData(child_uvf); + + // Bind data and dense weights mapping + const auto &func_expr = state.expr.Cast(); + const auto &bd = func_expr.bind_info->Cast(); + using RowMat = Eigen::Matrix; + Eigen::Map W(bd.weights.data(), (Eigen::Index)bd.k, (Eigen::Index)bd.n); + + // Determine width (k) and handle all-null case + idx_t columns = (idx_t)-1; + + if (bd.mode == MulMode::Dense) { + // -------- DENSE PATH (build X_dense then Y = X_dense * W) -------- + RowMat X_dense; + for (idx_t i = 0; i < count; i++) { + const idx_t sel = lhs_uvf.sel->get_index(i); + if (!lhs_uvf.validity.RowIsValid(sel)) continue; + + const idx_t row_len = entries[sel].length; + if (columns == (idx_t)-1) { + columns = row_len; + X_dense.resize((Eigen::Index)count, (Eigen::Index)columns); + } else if (columns != row_len) { + throw InvalidInputException("Input Matrix has uneven rows. Error at row %llu", + (unsigned long long)i); + } + const double *row_ptr = child_data + entries[sel].offset; + std::memcpy(X_dense.data() + i * columns, row_ptr, sizeof(double) * (size_t)columns); } - const std::string path = vFile.ToString(); - - std::vector W; - idx_t K = 0, N = 0; - ParseCSVWeights(path, W, K, N); - // Erase filename argument so execution only receives x - // Function::EraseArgument(bound_function, args, 1); - - return make_uniq(W, K, N, path, /*bound*/ true); - } - - // ------------------------- - // Execute - // ------------------------- - static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { - - idx_t count = args.size(); //number of tuples in a DataChunk - - // Read Left Matrix from the argument - Vector &lhs = args.data[0]; - UnifiedVectorFormat lhs_uvf; - lhs.ToUnifiedFormat(count,lhs_uvf); - const auto *entries = UnifiedVectorFormat::GetData(lhs_uvf); // Holds the entries {offset, length}for each row - - auto &child = ListVector::GetEntry(lhs); // pointer to child reference that actually holds the list - const idx_t total_elems = ListVector::GetListSize(lhs); - UnifiedVectorFormat child_uvf; - child.ToUnifiedFormat(total_elems, child_uvf); - const double *child_data = UnifiedVectorFormat::GetData(child_uvf); // from this child using the offset and length of the parent unified vector we can get the individual elements. - - Eigen::Matrix X; - idx_t columns = -1; - - // Check the selectivity and create matrix of only selected rows - for(idx_t i = 0; i < count; i++){ - idx_t idx = lhs_uvf.sel->get_index(i); - if(lhs_uvf.validity.RowIsValid(idx)){ - idx_t c_ = entries[idx].length; - if(i == 0){ - columns = c_; - X.resize((Eigen::Index)count, (Eigen::Index)columns); - } - else { - if(columns != c_){ - throw InvalidInputException("Input Matrix has uneven rows. Error at row %lld",(unsigned long long) i); - } - } - const double *row_ptr = child_data + entries[idx].offset; - std::memcpy(X.data() + i * columns, row_ptr, sizeof(double) * (size_t)columns); + if (columns == (idx_t)-1) { + // all rows NULL → return all NULL lists + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + ListVector::Reserve(result, 0); + ListVector::SetListSize(result, 0); + auto &res_valid = FlatVector::Validity(result); + for (idx_t i = 0; i < count; ++i) { + res_entries[i] = {0, 0}; + res_valid.Set(i, false); } + return; } - // Prepare weight matrix using the Bound Data - const auto &func_expr = state.expr.Cast(); - const auto &bd = func_expr.bind_info->Cast(); - const idx_t k = bd.k, n = bd.n; - const double *Wbuf = bd.weights.data(); - using RowMat = Eigen::Matrix; - Eigen::Map W(bd.weights.data(), (Eigen::Index)bd.k, (Eigen::Index)bd.n); + if (columns != bd.k) { + throw InvalidInputException("matmul: input width (%llu) != weights rows k (%llu)", + (unsigned long long)columns, + (unsigned long long)bd.k); + } - // Matrix Multiplication of a chunk of rows - Eigen::Matrix Y = X * W; + RowMat Y = X_dense * W; // (count x k) * (k x n) - // Prepare result in a FlatVector - // Prepare its parent vector by setting the offset and length in the entries and set the data in child - // Use the Left matrix to check if the row should be null or not using similar selectivity logic. + // ---- materialize LIST ---- result.SetVectorType(VectorType::FLAT_VECTOR); auto *res_entries = FlatVector::GetData(result); auto &res_child = ListVector::GetEntry(result); + const idx_t n = bd.n; const idx_t total = count * n; ListVector::Reserve(result, total); ListVector::SetListSize(result, total); double *out = FlatVector::GetData(res_child); auto &res_valid = FlatVector::Validity(result); + idx_t cursor = 0; for (idx_t i = 0; i < count; ++i) { - idx_t idx = lhs_uvf.sel->get_index(i); - if(!lhs_uvf.validity.RowIsValid(idx)){ - res_entries[i] = {0,0}; - res_valid.Set(i,false); + const idx_t sel = lhs_uvf.sel->get_index(i); + if (!lhs_uvf.validity.RowIsValid(sel)) { + res_entries[i] = {0, 0}; + res_valid.Set(i, false); + continue; } res_entries[i].offset = cursor; res_entries[i].length = n; std::memcpy(out + cursor, Y.data() + i * n, sizeof(double) * (size_t)n); cursor += n; } - } - - static void Register(ExtensionLoader &loader) { - // Logical signature with filename; Bind erases it so Exec sees only x. - ScalarFunction fn( - "matmul", - { LogicalType::LIST(LogicalType::DOUBLE), // x - LogicalType::VARCHAR }, // weights_file - LogicalType::LIST(LogicalType::DOUBLE), - Execute - ); - fn.bind = Bind; - loader.RegisterFunction(fn); -} + return; + } -}; + // -------- INPUT-SPARSE PATH (Velox-style) -------- + // Deduplicate selected base rows → compact indices + std::unordered_map raw_to_compact; + raw_to_compact.reserve((size_t)count * 2); -// void RegisterMLScalarFunctions(ExtensionLoader &loader) { + std::vector unique_raw; unique_raw.reserve((size_t)count); + std::vector row_to_compact(count, (idx_t)-1); + idx_t num_unique = 0; -// ML_MatrixMultiply::Register(loader); + for (idx_t i = 0; i < count; ++i) { + const idx_t sel = lhs_uvf.sel->get_index(i); + if (!lhs_uvf.validity.RowIsValid(sel)) continue; -// } + const idx_t row_len = entries[sel].length; + if (columns == (idx_t)-1) columns = row_len; + else if (columns != row_len) { + throw InvalidInputException("Input Matrix has uneven rows. Error at row %llu", + (unsigned long long)i); + } + + auto it = raw_to_compact.find(sel); + if (it == raw_to_compact.end()) { + raw_to_compact.emplace(sel, num_unique); + unique_raw.push_back(sel); + row_to_compact[i] = num_unique; + ++num_unique; + } else { + row_to_compact[i] = it->second; + } + } + + if (columns == (idx_t)-1) { + // all rows NULL → return all NULL lists + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + ListVector::Reserve(result, 0); + ListVector::SetListSize(result, 0); + auto &res_valid = FlatVector::Validity(result); + for (idx_t i = 0; i < count; ++i) { + res_entries[i] = {0, 0}; + res_valid.Set(i, false); + } + return; + } + + if (columns != bd.k) { + throw InvalidInputException("matmul: input width (%llu) != weights rows k (%llu)", + (unsigned long long)columns, + (unsigned long long)bd.k); + } + + using SpMat = Eigen::SparseMatrix; + std::vector> trips; + trips.reserve((size_t)num_unique * 16); // heuristic; adjust if you know nnz/row, it can grow if needed + + for (idx_t compact_row = 0; compact_row < num_unique; ++compact_row) { + const idx_t raw = unique_raw[compact_row]; + const idx_t len = entries[raw].length; + const double *row_ptr = child_data + entries[raw].offset; + for (idx_t c = 0; c < len; ++c) { + const double v = row_ptr[c]; + if (v != 0.0) trips.emplace_back((int)compact_row, (int)c, v); + } + } + + SpMat X_sparse((int)num_unique, (int)bd.k); + X_sparse.setFromTriplets(trips.begin(), trips.end()); + // std::cout << "\n\nSparse Multiplication executed!!\n\n"; + RowMat Y_compact = X_sparse * W; // (num_unique x n) + + // ---- materialize LIST, scatter compact → logical rows ---- + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + + const idx_t n = bd.n; + const idx_t total_vals = count * n; + ListVector::Reserve(result, total_vals); + ListVector::SetListSize(result, total_vals); + double *out = FlatVector::GetData(res_child); + auto &res_valid = FlatVector::Validity(result); + + idx_t cursor = 0; + for (idx_t i = 0; i < count; ++i) { + const idx_t sel = lhs_uvf.sel->get_index(i); + if (!lhs_uvf.validity.RowIsValid(sel)) { + res_entries[i] = {0, 0}; + res_valid.Set(i, false); + continue; + } + const idx_t compact = row_to_compact[i]; + res_entries[i].offset = cursor; + res_entries[i].length = n; + + std::memcpy(out + cursor, + Y_compact.data() + (ptrdiff_t)compact * n, + sizeof(double) * (size_t)n); + cursor += n; + } +} + +// ========================= +// Register +// ========================= + +void ML_MatrixMultiply::Register(ExtensionLoader &loader) { + // Logical signature with filename; Bind may erase it so Exec sees only x. + ScalarFunction fn( + "mat_mul", + { LogicalType::LIST(LogicalType::DOUBLE), // x + LogicalType::VARCHAR, // weights_file + LogicalType::VARCHAR }, // MODE + LogicalType::LIST(LogicalType::DOUBLE), + Execute + ); + fn.bind = Bind; + loader.RegisterFunction(fn); + fn.stability = FunctionStability::VOLATILE; // reads a file; avoid constant folding if desired +} -} // namespace duckdb \ No newline at end of file +} // namespace duckdb diff --git a/src/ml_functions/ml_functions_scalar.cpp b/src/ml_functions/ml_functions_scalar.cpp index eeae32c..699d057 100644 --- a/src/ml_functions/ml_functions_scalar.cpp +++ b/src/ml_functions/ml_functions_scalar.cpp @@ -1,5 +1,5 @@ #include "duckdb.hpp" -#include "matrix_multiplication.cpp" +#include "ml_functions/matrix_multiplication.hpp" #include "min_max_scaler.cpp" #include "ml_functions/one_hot_encoder.hpp" #include "decision_tree.cpp" diff --git a/src/optimization/CMakeLists.txt b/src/optimization/CMakeLists.txt index caeb4b7..ec55916 100644 --- a/src/optimization/CMakeLists.txt +++ b/src/optimization/CMakeLists.txt @@ -3,6 +3,10 @@ list(APPEND EXTENSION_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/add5_rule.cpp ${CMAKE_CURRENT_SOURCE_DIR}/replace_binding_rule.cpp ${CMAKE_CURRENT_SOURCE_DIR}/register_optimizers.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_optimizer.cpp + + #All Actions + ${CMAKE_CURRENT_SOURCE_DIR}/actions/MatMulDense2SparseRewriteAction.cpp ) # Expose back to parent diff --git a/src/optimization/actions/MatMulDense2SparseRewriteAction.cpp b/src/optimization/actions/MatMulDense2SparseRewriteAction.cpp new file mode 100644 index 0000000..376b172 --- /dev/null +++ b/src/optimization/actions/MatMulDense2SparseRewriteAction.cpp @@ -0,0 +1,118 @@ +#include "duckdb.hpp" +#include "optimization/actions/MatMulDense2SparseRewriteAction.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/planner/expression_iterator.hpp" +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/planner/operator/logical_filter.hpp" +#include "duckdb/planner/operator/logical_aggregate.hpp" +#include "duckdb/planner/operator/logical_comparison_join.hpp" +#include "duckdb/planner/operator/logical_join.hpp" + +#include "duckdb/planner/operator/logical_filter.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/planner/operator/logical_aggregate.hpp" +#include "duckdb/planner/operator/logical_comparison_join.hpp" +#include "duckdb/common/enums/expression_type.hpp" +#include "ml_functions/matrix_multiplication.hpp" +#include "duckdb/common/enums/logical_operator_type.hpp" + +using namespace duckdb; + +bool checkExpression(OptimizerExtensionInput &input, unique_ptr &e){ + if(e->expression_class == ExpressionClass::BOUND_FUNCTION){ + auto &f = e->Cast(); + if(f.function.name == "mat_mul"){ + // Check if the first argument is dense and the second is sparse + // This is a placeholder; actual implementation would involve checking the data types or properties + std::cout << "MatMul function found: " << f.ToString() << "\n"; + return true; + } + } + return false; +} + +bool applyExpressionRewrite(OptimizerExtensionInput &input, unique_ptr &e){ + if(e->expression_class == ExpressionClass::BOUND_FUNCTION){ + auto &f = e->Cast(); + if(f.function.name == "mat_mul"){ + // Rewrite logic: change the argument to use a sparse representation + // change the binding data to reflect sparse matrix multiplication + f.children[2] = make_uniq(Value("sparse")); // Example change + auto &bd = f.bind_info->Cast(); + bd.mode = ML_MatrixMultiply::MulMode::InputSparse; + return true; + } + } + return false; +} + +bool MatMulDense2SparseRewriteAction::check(OptimizerExtensionInput &input, unique_ptr &plan) { + // Check if the plan contains a MatMul operation with a dense matrix on the left and a sparse matrix on the right + // This is a placeholder implementation; actual implementation would involve traversing the plan tree + if (!plan) return false; + + // Overall Logic + // check if this node is a success + // if yes return true; + // else return false | check child; + bool ans = false; + switch (plan->type){ + std::cout << "Checking plan node of type: " << LogicalOperatorToString(plan->type) << "\n"; + case LogicalOperatorType::LOGICAL_PROJECTION : { + auto &proj = plan->Cast(); + for (auto &e : proj.expressions) { + ans |= checkExpression(input, e); + } + } + break; + case LogicalOperatorType::LOGICAL_FILTER : { + auto &fil = plan->Cast(); + for (auto &e : fil.expressions) { + ans |= checkExpression(input, e); + } + } + break; + default : break; + } + + // check children + for(auto &child : plan->children){ + ans |= check(input, child); + } + + return ans; + +} + +bool MatMulDense2SparseRewriteAction::apply(OptimizerExtensionInput &input, unique_ptr &plan) { + if (!plan) return false; + + switch (plan->type){ + case LogicalOperatorType::LOGICAL_PROJECTION : { + auto &proj = plan->Cast(); + for (auto &e : proj.expressions) { + applyExpressionRewrite(input, e); + } + } + break; + case LogicalOperatorType::LOGICAL_FILTER : { + auto &fil = plan->Cast(); + for (auto &e : fil.expressions) { + applyExpressionRewrite(input, e); + } + } + break; + default : break; + } + + // Recurse into children + for(auto &child : plan->children){ + apply(input, child); + } + + // Indicate that the plan was modified + return true; +} \ No newline at end of file diff --git a/src/optimization/dynamic_optimizer.cpp b/src/optimization/dynamic_optimizer.cpp new file mode 100644 index 0000000..c78d363 --- /dev/null +++ b/src/optimization/dynamic_optimizer.cpp @@ -0,0 +1,29 @@ +#include "duckdb.hpp" +#include "optimization/dynamic_optimizer.hpp" +#include "optimization/actions/MatMulDense2SparseRewriteAction.hpp" + +namespace duckdb{ + void DynamicOpt::Optimize(OptimizerExtensionInput &in, unique_ptr &plan) { + if (!plan) return; + // else return; + + // first step : check all rules and see which ones apply + // TODO Decompose this properly later with Catalog + if(MatMulDense2SparseRewriteAction::check(in, plan)){ + std::cout << "\nMatMulDense2SparseRewriteAction is applicable \n"; + MatMulDense2SparseRewriteAction::apply(in, plan); + } + + + // translate the rules in language that ReuableMCTS understands + // The language that we're using for the velox. + + // send all applicable rules to ReusableMCTS python runtime + + // recieve the rule that is applicable here + + // apply the rule on the plan + + // No type changes; ResolveOperatorTypes() not required. + }; +} \ No newline at end of file diff --git a/src/optimization/register_optimizers.cpp b/src/optimization/register_optimizers.cpp index ddad37d..512a74c 100644 --- a/src/optimization/register_optimizers.cpp +++ b/src/optimization/register_optimizers.cpp @@ -4,8 +4,9 @@ #include "duckdb/main/database.hpp" #include "duckdb/optimizer/optimizer_extension.hpp" -#include "add5_rule.hpp" -#include "replace_binding_rule.hpp" // <-- from the code I shared earlier +#include "optimization/add5_rule.hpp" +#include "optimization/replace_binding_rule.hpp" +#include "optimization/dynamic_optimizer.hpp" #include #include @@ -62,6 +63,18 @@ struct CactusReplaceBindingOpt : public OptimizerExtension { } }; + +// ----------------------------- +// Dynamic optimizer pass +// ----------------------------- +struct CactusDynamicOpt : public OptimizerExtension { + CactusDynamicOpt() { optimize_function = Run; } + + static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { + DynamicOpt::Optimize(in, plan); + } +}; + // ----------------------------- // Registration hook // ----------------------------- @@ -70,8 +83,9 @@ void RegisterCactusOptimizers(DatabaseInstance &db) { // Order matters if passes depend on one another. // Typically do argument/string rewrites early, then other expression rewrites. - cfg.optimizer_extensions.push_back(CactusReplaceBindingOpt{}); - cfg.optimizer_extensions.push_back(CactusAdd5Opt{}); + // cfg.optimizer_extensions.push_back(CactusReplaceBindingOpt{}); + // cfg.optimizer_extensions.push_back(CactusAdd5Opt{}); + cfg.optimizer_extensions.push_back(CactusDynamicOpt{}); } } // namespace duckdb diff --git a/src/optimization/replace_binding_rule.cpp b/src/optimization/replace_binding_rule.cpp index 39682d2..1d9ad8f 100644 --- a/src/optimization/replace_binding_rule.cpp +++ b/src/optimization/replace_binding_rule.cpp @@ -23,22 +23,6 @@ using namespace duckdb; -static bool ArgIsVarcharConstant(const duckdb::unique_ptr &arg, string &out) { - if (!arg || arg->expression_class != ExpressionClass::BOUND_CONSTANT) return false; - auto &c = arg->Cast(); - if (c.value.type().id() != LogicalTypeId::VARCHAR) return false; - out = StringValue::Get(c.value); - return true; -} - -static bool ArgIsBoolConstant(const duckdb::unique_ptr &arg, bool &out) { - if (!arg || arg->expression_class != ExpressionClass::BOUND_CONSTANT) return false; - auto &c = arg->Cast(); - if (c.value.type().id() != LogicalTypeId::BOOLEAN) return false; - out = BooleanValue::Get(c.value); - return true; -} - duckdb::unique_ptr ReplaceBindingRule::RewriteExpr(duckdb::unique_ptr expr, const ReplaceBindingRule &cfg) { if (!expr) return expr; diff --git a/test/sql/matmul.test b/test/sql/matmul.test index 054789e..87257dd 100644 --- a/test/sql/matmul.test +++ b/test/sql/matmul.test @@ -43,10 +43,10 @@ statement ok CREATE TABLE inputs(a DOUBLE[]); statement ok -INSERT INTO inputs VALUES ([1,2,3]), ([4,5,6]), ([7,8,9]); +INSERT INTO inputs VALUES ([1,2,3]), ([4,5,6]), ([7,8,9]); query I -SELECT matmul(matmul(a, 'file_1.csv'), 'file_2.csv') AS y +SELECT mat_mul(mat_mul(a, 'file_1.csv', 'dense'), 'file_2.csv', 'dense') AS y FROM inputs ORDER BY 1; ---- From ad1cbf8bc873e73d56d50000f72b0d9c3b7d4aab Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 15 Oct 2025 16:25:20 -0700 Subject: [PATCH 07/18] sparse to dense matrix multiplication --- .gitignore | 2 + queries/expedia_query.sql | 9 +-- src/include/optimization/add5_rule.hpp | 2 +- src/include/optimization/catalog.hpp | 19 ++++++ src/include/optimization/plan_dump.hpp | 67 +++++++++++++++++++ src/include/optimization/rule_manager.hpp | 16 +++++ src/include/optimization/translator.hpp | 9 +++ src/ml_functions/matrix_multiplication.cpp | 4 ++ src/optimization/CMakeLists.txt | 1 + .../MatMulDense2SparseRewriteAction.cpp | 18 +++-- src/optimization/catalog.cpp | 24 +++++++ src/optimization/dynamic_optimizer.cpp | 15 ++++- src/optimization/register_optimizers.cpp | 7 ++ test/sql/matmul.test | 1 + 14 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 src/include/optimization/catalog.hpp create mode 100644 src/include/optimization/plan_dump.hpp create mode 100644 src/include/optimization/rule_manager.hpp create mode 100644 src/include/optimization/translator.hpp create mode 100644 src/optimization/catalog.cpp diff --git a/.gitignore b/.gitignore index ca48c4e..3c620aa 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ vcpkg/ resources/* duckdb/ temp_dir/ +mydb.duckdb +plans/ diff --git a/queries/expedia_query.sql b/queries/expedia_query.sql index be618c2..08e1cb1 100644 --- a/queries/expedia_query.sql +++ b/queries/expedia_query.sql @@ -4,8 +4,10 @@ ATTACH '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgex SET schema 'expedia_db.main'; -- Optimizer Config -PRAGMA enable_optimizer; -PRAGMA explain_output='json'; +PRAGMA enable_profiling=json; +PRAGMA profiling_output='/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/plans/profile.json'; +-- PRAGMA enable_optimizer; +-- PRAGMA explain_output='json'; -- SET enable_profiling = 'query_tree_optimizer'; -- SET profiling_mode = 'detailed'; @@ -17,8 +19,7 @@ set threads = 8; -- SELECT 'Expedia_S_listings_extension2' AS which, * FROM Expedia_S_listings_extension2 LIMIT 10; -- SELECT 'Expedia_R1_hotels2' AS which, * FROM Expedia_R1_hotels2 LIMIT 10; -- SELECT 'Expedia_R2_searches' AS which, * FROM Expedia_R2_searches LIMIT 10; - -EXPLAIN ANALYZE +EXPLAIN (FORMAT TEXT) SELECT s.prop_id, s.srch_id, diff --git a/src/include/optimization/add5_rule.hpp b/src/include/optimization/add5_rule.hpp index 4238b1e..9dc6e14 100644 --- a/src/include/optimization/add5_rule.hpp +++ b/src/include/optimization/add5_rule.hpp @@ -2,6 +2,6 @@ #include "duckdb.hpp" struct Add5Rule { - static void Apply(duckdb::ClientContext &ctx, + static void Apply(duckdb::ClientContext &, duckdb::unique_ptr &plan); }; \ No newline at end of file diff --git a/src/include/optimization/catalog.hpp b/src/include/optimization/catalog.hpp new file mode 100644 index 0000000..0ef21a3 --- /dev/null +++ b/src/include/optimization/catalog.hpp @@ -0,0 +1,19 @@ +#include "duckdb.hpp" +#include + +namespace duckdb { + + class Catalog_optimization { + public: + Catalog_optimization() = default; + idx_t cacheQueryPlan(ClientContext &ctx,unique_ptr &plan); + unique_ptr resetQueryPlanFromCache(ClientContext &ctx,idx_t cacheId); + unique_ptr resetQueryPlan(ClientContext &ctx); + + + private: + std::map > queryPlanCaches_; + idx_t initQueryPlanCacheId = 0; + idx_t currentCacheId = 0; + }; //end of class Catalog +} //end of duckdb namespace \ No newline at end of file diff --git a/src/include/optimization/plan_dump.hpp b/src/include/optimization/plan_dump.hpp new file mode 100644 index 0000000..4df9071 --- /dev/null +++ b/src/include/optimization/plan_dump.hpp @@ -0,0 +1,67 @@ +#pragma once +#include "duckdb/common/serializer/binary_serializer.hpp" +#include "duckdb/common/serializer/buffered_file_writer.hpp" +#include "duckdb/common/file_system.hpp" +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb/main/client_context.hpp" +// #include "duckdb/common/base64.hpp" +#include "duckdb/common/serializer/memory_stream.hpp" +#include "duckdb/common/types/blob.hpp" +#include "duckdb/common/types/string_type.hpp" + + +#include +#include + +namespace duckdb { + +inline void DumpPlanToFile(duckdb::ClientContext &ctx, + LogicalOperator &op, + const std::string &path) { + + // open a buffered writer to the target file + auto &fs = FileSystem::GetFileSystem(ctx); + BufferedFileWriter writer(fs, path, FileFlags::FILE_FLAGS_WRITE | + FileFlags::FILE_FLAGS_FILE_CREATE | + FileFlags::FILE_FLAGS_APPEND); + + SerializationOptions options; + options.serialization_compatibility = SerializationCompatibility::Latest(); + + BinarySerializer serializer(writer, options); + serializer.Begin(); + op.Serialize(serializer); + serializer.End(); + + writer.Sync(); + writer.Close(); +} + +inline void DumpPlanBase64(duckdb::ClientContext &ctx, + duckdb::LogicalOperator &plan, + const std::string &txt_path) { + using namespace duckdb; + + // 1) serialize plan into memory + MemoryStream ms(Allocator::Get(ctx)); + SerializationOptions opts; + opts.serialization_compatibility = SerializationCompatibility::Latest(); + BinarySerializer ser(ms, opts); + ser.Begin(); + plan.Serialize(ser); + ser.End(); + + // 2) wrap the raw bytes in a string_t (no copy) + const_data_ptr_t bytes = ms.GetData(); + idx_t nbytes = ms.GetPosition(); // current size written + string_t blob_view(const_char_ptr_cast(bytes), nbytes); + + // 3) Base64 encode using Blob helpers + std::string b64 = Blob::ToBase64(blob_view); + + // 4) write text-safe output + std::ofstream out(txt_path, std::ios::out | std::ios::trunc); + out << b64; +} + +} // namespace duckdb diff --git a/src/include/optimization/rule_manager.hpp b/src/include/optimization/rule_manager.hpp new file mode 100644 index 0000000..c8da6cc --- /dev/null +++ b/src/include/optimization/rule_manager.hpp @@ -0,0 +1,16 @@ +#include "duckdb.hpp" + +namespace duckdb{ + enum class RewriteRule : uint8_t { + MatMulDense2Sparse = 0, + // NextRuleGoesHere, + }; + + // Human-readable name + inline const char *ToString(RewriteRule r) { + switch (r) { + case RewriteRule::MatMulDense2Sparse: return "MatMulDense2Sparse"; + default: return "Unknown"; + } + } +} //end of duckdb namespace \ No newline at end of file diff --git a/src/include/optimization/translator.hpp b/src/include/optimization/translator.hpp new file mode 100644 index 0000000..f4b714c --- /dev/null +++ b/src/include/optimization/translator.hpp @@ -0,0 +1,9 @@ +#include "duckdb.hpp" +#include "rule_manager.hpp" + +namespace duckdb{ + class translator { + public : + private : + }; +} \ No newline at end of file diff --git a/src/ml_functions/matrix_multiplication.cpp b/src/ml_functions/matrix_multiplication.cpp index bae2c97..7a46d7d 100644 --- a/src/ml_functions/matrix_multiplication.cpp +++ b/src/ml_functions/matrix_multiplication.cpp @@ -189,6 +189,7 @@ void ML_MatrixMultiply::Execute(DataChunk &args, ExpressionState &state, Vector if (bd.mode == MulMode::Dense) { // -------- DENSE PATH (build X_dense then Y = X_dense * W) -------- + std::cout << "\n\nDense Execution\n\n"; RowMat X_dense; for (idx_t i = 0; i < count; i++) { const idx_t sel = lhs_uvf.sel->get_index(i); @@ -259,6 +260,9 @@ void ML_MatrixMultiply::Execute(DataChunk &args, ExpressionState &state, Vector // -------- INPUT-SPARSE PATH (Velox-style) -------- // Deduplicate selected base rows → compact indices + + std::cout << "\n\nSparse Execution\n\n"; + std::unordered_map raw_to_compact; raw_to_compact.reserve((size_t)count * 2); diff --git a/src/optimization/CMakeLists.txt b/src/optimization/CMakeLists.txt index ec55916..2e8ed86 100644 --- a/src/optimization/CMakeLists.txt +++ b/src/optimization/CMakeLists.txt @@ -4,6 +4,7 @@ list(APPEND EXTENSION_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/replace_binding_rule.cpp ${CMAKE_CURRENT_SOURCE_DIR}/register_optimizers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_optimizer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/catalog.cpp #All Actions ${CMAKE_CURRENT_SOURCE_DIR}/actions/MatMulDense2SparseRewriteAction.cpp diff --git a/src/optimization/actions/MatMulDense2SparseRewriteAction.cpp b/src/optimization/actions/MatMulDense2SparseRewriteAction.cpp index 376b172..296cb5c 100644 --- a/src/optimization/actions/MatMulDense2SparseRewriteAction.cpp +++ b/src/optimization/actions/MatMulDense2SparseRewriteAction.cpp @@ -18,23 +18,28 @@ #include "duckdb/common/enums/expression_type.hpp" #include "ml_functions/matrix_multiplication.hpp" #include "duckdb/common/enums/logical_operator_type.hpp" - using namespace duckdb; bool checkExpression(OptimizerExtensionInput &input, unique_ptr &e){ + bool found = false; if(e->expression_class == ExpressionClass::BOUND_FUNCTION){ auto &f = e->Cast(); if(f.function.name == "mat_mul"){ // Check if the first argument is dense and the second is sparse // This is a placeholder; actual implementation would involve checking the data types or properties std::cout << "MatMul function found: " << f.ToString() << "\n"; - return true; + found = true; } } - return false; + + ExpressionIterator::EnumerateChildren(*e, [&](unique_ptr &child) { + found |= checkExpression(input, child); + }); + return found; } bool applyExpressionRewrite(OptimizerExtensionInput &input, unique_ptr &e){ + bool modified = false; if(e->expression_class == ExpressionClass::BOUND_FUNCTION){ auto &f = e->Cast(); if(f.function.name == "mat_mul"){ @@ -43,10 +48,13 @@ bool applyExpressionRewrite(OptimizerExtensionInput &input, unique_ptr(Value("sparse")); // Example change auto &bd = f.bind_info->Cast(); bd.mode = ML_MatrixMultiply::MulMode::InputSparse; - return true; + modified = true; } } - return false; + ExpressionIterator::EnumerateChildren(*e, [&](unique_ptr &child) { + modified |= applyExpressionRewrite(input, child); + }); + return modified; } bool MatMulDense2SparseRewriteAction::check(OptimizerExtensionInput &input, unique_ptr &plan) { diff --git a/src/optimization/catalog.cpp b/src/optimization/catalog.cpp new file mode 100644 index 0000000..fa7764f --- /dev/null +++ b/src/optimization/catalog.cpp @@ -0,0 +1,24 @@ +#include "duckdb.hpp" +#include "optimization/catalog.hpp" + +namespace duckdb { + idx_t Catalog_optimization::cacheQueryPlan(ClientContext &ctx,unique_ptr &plan) { + auto plan_to_cache = plan->Copy(ctx); + queryPlanCaches_[currentCacheId++] = std::move(plan_to_cache); + return currentCacheId-1; + } + + unique_ptr Catalog_optimization::resetQueryPlanFromCache(ClientContext &ctx,idx_t cacheId) { + auto it = queryPlanCaches_.find(cacheId); + if (it == queryPlanCaches_.end() || !it->second) { + throw std::runtime_error("Cache ID not found"); + } + // Return a fresh deep copy so caller owns an independent tree + return it->second->Copy(ctx); + } + + unique_ptr Catalog_optimization::resetQueryPlan(ClientContext &ctx) { + auto it = queryPlanCaches_.find(initQueryPlanCacheId); + return it->second->Copy(ctx); + } +} //end of duckdb namespace \ No newline at end of file diff --git a/src/optimization/dynamic_optimizer.cpp b/src/optimization/dynamic_optimizer.cpp index c78d363..ce9e739 100644 --- a/src/optimization/dynamic_optimizer.cpp +++ b/src/optimization/dynamic_optimizer.cpp @@ -1,19 +1,30 @@ #include "duckdb.hpp" #include "optimization/dynamic_optimizer.hpp" #include "optimization/actions/MatMulDense2SparseRewriteAction.hpp" +#include "optimization/catalog.hpp" namespace duckdb{ void DynamicOpt::Optimize(OptimizerExtensionInput &in, unique_ptr &plan) { if (!plan) return; // else return; + Catalog_optimization cat; + // // first step : check all rules and see which ones apply + // // TODO Decompose this properly later with Catalog + idx_t id = cat.cacheQueryPlan(in.context,plan); + + // unique_ptr initial_plan = plan->Copy(in.context); + + // std::cout << "\nCached the initial plan with cacheId: " << id << "\n"; - // first step : check all rules and see which ones apply - // TODO Decompose this properly later with Catalog if(MatMulDense2SparseRewriteAction::check(in, plan)){ std::cout << "\nMatMulDense2SparseRewriteAction is applicable \n"; MatMulDense2SparseRewriteAction::apply(in, plan); } + // plan = std::move(initial_plan); + + // plan = cat.resetQueryPlanFromCache(in.context,0); + // translate the rules in language that ReuableMCTS understands // The language that we're using for the velox. diff --git a/src/optimization/register_optimizers.cpp b/src/optimization/register_optimizers.cpp index 512a74c..f3b187d 100644 --- a/src/optimization/register_optimizers.cpp +++ b/src/optimization/register_optimizers.cpp @@ -7,6 +7,7 @@ #include "optimization/add5_rule.hpp" #include "optimization/replace_binding_rule.hpp" #include "optimization/dynamic_optimizer.hpp" +// #include "optimization/plan_dump.hpp" #include #include @@ -71,7 +72,13 @@ struct CactusDynamicOpt : public OptimizerExtension { CactusDynamicOpt() { optimize_function = Run; } static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { + // DumpPlanBase64(in.context, *plan, "./plans/initial_plan.duckdbplan"); + std::string pretty = plan->ToString(); + std::cout << "\nInitial Plan:\n" << pretty << "\n"; DynamicOpt::Optimize(in, plan); + // DumpPlanBase64(in.context, *plan, "./plans/final_plan.duckdbplan"); + pretty = plan->ToString(); + std::cout << "\nFinal Plan:\n" << pretty << "\n"; } }; diff --git a/test/sql/matmul.test b/test/sql/matmul.test index 87257dd..25f566c 100644 --- a/test/sql/matmul.test +++ b/test/sql/matmul.test @@ -45,6 +45,7 @@ CREATE TABLE inputs(a DOUBLE[]); statement ok INSERT INTO inputs VALUES ([1,2,3]), ([4,5,6]), ([7,8,9]); + query I SELECT mat_mul(mat_mul(a, 'file_1.csv', 'dense'), 'file_2.csv', 'dense') AS y FROM inputs From 39d6c6ae6bab6cbb3ea0acfc873940bf8f8bc7a2 Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 29 Oct 2025 12:49:42 -0700 Subject: [PATCH 08/18] Added Cost Model code translating it from the Cactusdb Optimizer --- CMakeLists.txt | 1 + queries/expedia_query.sql | 6 +- src/cost_model/CMakeLists.txt | 9 ++ src/cost_model/cost_model.cpp | 133 ++++++++++++++++++++++ src/cost_model/estimator.cpp | 32 ++++++ src/cost_model/udf_cost_coeff.cpp | 47 ++++++++ src/include/cost_model/cost_estimate.hpp | 11 ++ src/include/cost_model/cost_model.hpp | 38 +++++++ src/include/cost_model/estimator.hpp | 26 +++++ src/include/cost_model/stat_source.hpp | 29 +++++ src/include/cost_model/udf_cost_coeff.hpp | 17 +++ src/optimization/dynamic_optimizer.cpp | 5 + 12 files changed, 351 insertions(+), 3 deletions(-) create mode 100644 src/cost_model/CMakeLists.txt create mode 100644 src/cost_model/cost_model.cpp create mode 100644 src/cost_model/estimator.cpp create mode 100644 src/cost_model/udf_cost_coeff.cpp create mode 100644 src/include/cost_model/cost_estimate.hpp create mode 100644 src/include/cost_model/cost_model.hpp create mode 100644 src/include/cost_model/estimator.hpp create mode 100644 src/include/cost_model/stat_source.hpp create mode 100644 src/include/cost_model/udf_cost_coeff.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d6e310..9f24ba3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ set(EXTENSION_SOURCES src/cactusdb_extension.cpp) add_subdirectory(src/ml_functions) add_subdirectory(src/util) add_subdirectory(src/optimization) +add_subdirectory(src/cost_model) message(STATUS "EXTENSION_SOURCES include ${EXTENSION_SOURCES}") build_static_extension(${TARGET_NAME} ${EXTENSION_SOURCES}) diff --git a/queries/expedia_query.sql b/queries/expedia_query.sql index 08e1cb1..97145ae 100644 --- a/queries/expedia_query.sql +++ b/queries/expedia_query.sql @@ -4,9 +4,9 @@ ATTACH '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgex SET schema 'expedia_db.main'; -- Optimizer Config -PRAGMA enable_profiling=json; -PRAGMA profiling_output='/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/plans/profile.json'; --- PRAGMA enable_optimizer; +-- PRAGMA enable_profiling=json; +-- PRAGMA profiling_output='/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/plans/profile.json'; +PRAGMA disable_optimizer; -- PRAGMA explain_output='json'; -- SET enable_profiling = 'query_tree_optimizer'; -- SET profiling_mode = 'detailed'; diff --git a/src/cost_model/CMakeLists.txt b/src/cost_model/CMakeLists.txt new file mode 100644 index 0000000..029bffd --- /dev/null +++ b/src/cost_model/CMakeLists.txt @@ -0,0 +1,9 @@ +# Append optimizer sources to the extension's global list +list(APPEND EXTENSION_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/cost_model.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/estimator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/udf_cost_coeff.cpp +) + +# Expose back to parent +set(EXTENSION_SOURCES "${EXTENSION_SOURCES}" PARENT_SCOPE) diff --git a/src/cost_model/cost_model.cpp b/src/cost_model/cost_model.cpp new file mode 100644 index 0000000..1e4fa70 --- /dev/null +++ b/src/cost_model/cost_model.cpp @@ -0,0 +1,133 @@ +#include "duckdb.hpp" +#include "cost_model/cost_model.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/planner/operator/logical_filter.hpp" +#include "duckdb/planner/operator/logical_join.hpp" +#include "duckdb/planner/operator/logical_aggregate.hpp" +#include "duckdb/planner/operator/logical_order.hpp" +#include "duckdb/common/types/vector.hpp" +#include + +// using namespace duckdb; +namespace duckdb { + +CostModel::Node CostModel::MapNode(const LogicalOperator &op) { + switch (op.type) { + case LogicalOperatorType::LOGICAL_FILTER: return Node::Filter; + case LogicalOperatorType::LOGICAL_PROJECTION: return Node::Projection; + case LogicalOperatorType::LOGICAL_GET: return Node::Get; + case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: + case LogicalOperatorType::LOGICAL_ANY_JOIN: return Node::HashJoin; // refine below if needed + case LogicalOperatorType::LOGICAL_ORDER_BY: return Node::Order; + case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: return Node::Aggregate; + case LogicalOperatorType::LOGICAL_DELIM_JOIN: + case LogicalOperatorType::LOGICAL_CROSS_PRODUCT: return Node::NestedLoopJoin; + default: return Node::Unknown; + } +} + +CostEstimate SimpleCostModel::GetCost(LogicalOperator &op, const std::vector &inputs) { + if (op.children.empty()) return HandleLeaf(op); + return HandleInternal(op, inputs); +} + +CostEstimate SimpleCostModel::HandleLeaf(LogicalOperator &op) { + // LOGICAL_GET: use table stats if available (row_count); cols from types.size() + if (op.type == LogicalOperatorType::LOGICAL_GET) { + auto &get = op.Cast(); + idx_t rows = get.estimated_cardinality; // DuckDB keeps this updated + if (rows == DConstants::INVALID_INDEX) rows = 0; + idx_t cols = get.types.size(); + return CostEstimate(0.0, rows, cols); + } + // Default leaf + return CostEstimate(0.0, 1, op.types.size()); +} + +CostEstimate SimpleCostModel::HandleInternal(LogicalOperator &op, const std::vector &inputs) { + auto node = MapNode(op); + switch (node) { + case Node::Aggregate: + case Node::Order: { + // cost = c0 * rows_in ; rows_out ≈ λ * rows_in + auto stat = std::static_pointer_cast(inputs[0].stats); + auto coeff = UdfCostCoeff::Get("Aggregation"); // or "Order" + double c0 = coeff.empty() ? 1.0 : coeff[0]; + double lambda = 0.2; + return CostEstimate(c0 * stat->rows, (idx_t)(lambda * stat->rows), stat->cols); + } + case Node::Filter: { + auto stat = std::static_pointer_cast(inputs[0].stats); + double lambda = 0.5; // configurable selectivity + return CostEstimate(lambda * stat->rows, (idx_t)(lambda * stat->rows), stat->cols); + } + case Node::HashJoin: { + // Left (M×N), Right (O×P) + auto l = std::static_pointer_cast(inputs[0].stats); + auto r = std::static_pointer_cast(inputs[1].stats); + auto coeff = UdfCostCoeff::Get("HashJoin"); + double a = coeff.size() > 0 ? coeff[0] : 1.0; + double b = coeff.size() > 1 ? coeff[1] : 0.0; + double g = coeff.size() > 2 ? coeff[2] : 0.0; + double cost = a * l->rows + b * l->rows * l->cols + g * r->rows * r->cols; + return CostEstimate(cost, std::max(l->rows, r->rows), l->cols + r->cols); + } + case Node::NestedLoopJoin: { + auto l = std::static_pointer_cast(inputs[0].stats); + auto r = std::static_pointer_cast(inputs[1].stats); + auto coeff = UdfCostCoeff::Get("NestedLoopJoin"); + double a = coeff.size() > 0 ? coeff[0] : 1.0; + double b = coeff.size() > 1 ? coeff[1] : 0.0; + double g = coeff.size() > 2 ? coeff[2] : 0.0; + double cost = a * l->rows + b * l->rows * l->cols + g * r->rows * r->cols; + return CostEstimate(cost, std::max(l->rows, r->rows), r->cols); + } + case Node::Projection: + return HandleProjection(op, inputs); + default: + // passthrough + auto stat = std::static_pointer_cast(inputs[0].stats); + return CostEstimate(0.0, stat->rows, stat->cols); + } +} + +CostEstimate SimpleCostModel::HandleProjection(LogicalOperator &op, const std::vector &inputs) { + auto &proj = op.Cast(); + // Very similar to your Velox logic: parse UDFs from expressions and sum costs + std::vector udfs; udfs.reserve(proj.expressions.size()); + for (auto &expr : proj.expressions) { + // naive: use expr->ToString() and parse func names between identifier and '(' + std::cout << "\nProjection Expr: " << expr->ToString() << "\n"; + udfs.push_back(expr->ToString()); // parse later inside UDFChainCost + } + return UDFChainCost(udfs, inputs); +} + +CostEstimate SimpleCostModel::UDFChainCost(const std::vector &udfs_raw, + const std::vector &inputs) { + auto stat = std::static_pointer_cast(inputs[0].stats); + CostEstimate out(0.0, stat->rows, stat->cols); + + // (A) extract UDF ids inner→outer + std::vector udf_ids; + udf_ids.reserve(udfs_raw.size()); + for (auto &s : udfs_raw) { + // very simple tokenization: split by '(' and drop last token + auto pos = s.find('('); + if (pos != std::string::npos) udf_ids.push_back(s.substr(0, pos)); + } + std::reverse(udf_ids.begin(), udf_ids.end()); + + // (B) accumulate via UdfCostCoeff map + for (auto &u : udf_ids) { + std::cout << "\nUDF detected: " << u << "\n"; + auto coeff = UdfCostCoeff::Get(u); + // Plug your learned model here; as placeholder, linear in rows + double c = coeff.empty() ? 0.0 : coeff[0] * out.output_rows; + out.cost += c; + } + return out; +} + +} // namespace duckdb diff --git a/src/cost_model/estimator.cpp b/src/cost_model/estimator.cpp new file mode 100644 index 0000000..07bfe9d --- /dev/null +++ b/src/cost_model/estimator.cpp @@ -0,0 +1,32 @@ +#include "duckdb.hpp" +#include "cost_model/estimator.hpp" +#include "cost_model/stat_source.hpp" +#include "duckdb/planner/logical_operator.hpp" + +namespace duckdb { + +CostEstimate Estimator::Estimate(LogicalOperator &root) { + return SimpleEstimator(std::move(model)).Estimate(root); +} + +CostEstimate SimpleEstimator::Estimate(LogicalOperator &node) { + // 1) visit children first, accumulate their costs + double child_cost_sum = 0.0; + std::vector inputs; inputs.reserve(node.children.size()); + for (auto &child_ptr : node.children) { + auto &child = *child_ptr; + auto est = Estimate(child); + child_cost_sum += est.cost; + inputs.emplace_back(node.GetName(), Source::Type::NODE, + std::make_shared(est.output_rows, est.output_cols)); + } + + // 2) ask model for current op's cost given inputs + auto cur = model->GetCost(node, inputs); + + // 3) add child costs + cur.cost += child_cost_sum; + return cur; +} + +} // namespace duckdb diff --git a/src/cost_model/udf_cost_coeff.cpp b/src/cost_model/udf_cost_coeff.cpp new file mode 100644 index 0000000..d6b9f09 --- /dev/null +++ b/src/cost_model/udf_cost_coeff.cpp @@ -0,0 +1,47 @@ +// .cpp +#include "cost_model/udf_cost_coeff.hpp" +#include +#include +#include "duckdb.hpp" + +namespace duckdb { +static std::unordered_map> *g_map = nullptr; +static bool g_init = false; + +std::unordered_map> &UdfCostCoeff::Map() { + if (!g_map) g_map = new std::unordered_map>(); + return *g_map; +} +bool &UdfCostCoeff::Initialized() { return g_init; } + +void UdfCostCoeff::InitFromFile(const std::string &path) { + if (Initialized()) return; + auto p = path; + if (p.empty()) { + + p = "/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/cost_model/udf_coefficient_aws.txt"; + } + std::ifstream in(p); + if (!in.is_open()) { Initialized() = true; return; } // empty map ok + std::string line; + while (std::getline(in, line)) { + auto pos = line.find(':'); + if (pos == std::string::npos) continue; + auto k = line.substr(0, pos); + auto v = std::stod(line.substr(pos + 1)); + Map()[k].push_back(v); + } + Initialized() = true; +} + +const std::vector& UdfCostCoeff::Get(const std::string &key) { + if (!Initialized()) InitFromFile(); + auto &m = Map(); + auto it = m.find(key); + static std::vector empty; + if (it == m.end()){ + throw std::runtime_error("UDF Cost Coefficient not found for key: " + key); + } + return it == m.end() ? empty : it->second; +} +} // namespace duckdb diff --git a/src/include/cost_model/cost_estimate.hpp b/src/include/cost_model/cost_estimate.hpp new file mode 100644 index 0000000..395ce7f --- /dev/null +++ b/src/include/cost_model/cost_estimate.hpp @@ -0,0 +1,11 @@ +#include "duckdb.hpp" + +namespace duckdb { +struct CostEstimate { + double cost; + idx_t output_rows; + idx_t output_cols; + CostEstimate(double c=0, idx_t r=0, idx_t c2=0) + : cost(c), output_rows(r), output_cols(c2) {} +}; +} // namespace duckdb diff --git a/src/include/cost_model/cost_model.hpp b/src/include/cost_model/cost_model.hpp new file mode 100644 index 0000000..0a5e910 --- /dev/null +++ b/src/include/cost_model/cost_model.hpp @@ -0,0 +1,38 @@ +#pragma once +#include "cost_model/stat_source.hpp" +#include "cost_model/cost_estimate.hpp" +#include "cost_model/udf_cost_coeff.hpp" +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb.hpp" + +namespace duckdb { + +class CostModel { +public: + enum class Node { + Filter, Projection, Aggregate, HashJoin, Order, Get, LocalPartition, + Unnest, RowNumber, NestedLoopJoin, Unknown + }; + virtual ~CostModel() = default; + virtual CostEstimate GetCost(duckdb::LogicalOperator &op, + const std::vector &inputs) = 0; + + static Node MapNode(const duckdb::LogicalOperator &op); +}; + +class SimpleCostModel : public CostModel { +public: + CostEstimate GetCost(duckdb::LogicalOperator &op, + const std::vector &inputs) override; + +private: + CostEstimate HandleLeaf(duckdb::LogicalOperator &op); + CostEstimate HandleInternal(duckdb::LogicalOperator &op, + const std::vector &inputs); + CostEstimate HandleProjection(duckdb::LogicalOperator &op, + const std::vector &inputs); + CostEstimate UDFChainCost(const std::vector &udfs, + const std::vector &inputs); +}; + +} // namespace cactusdb diff --git a/src/include/cost_model/estimator.hpp b/src/include/cost_model/estimator.hpp new file mode 100644 index 0000000..0a74d31 --- /dev/null +++ b/src/include/cost_model/estimator.hpp @@ -0,0 +1,26 @@ +#pragma once +#include "cost_model/cost_model.hpp" +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb.hpp" + +namespace duckdb { + +class Estimator { +protected: + std::unique_ptr model; + +public: + explicit Estimator(std::unique_ptr m) : model(std::move(m)) {} + virtual ~Estimator() = default; + + // Recursively compute cost from a logical root + virtual CostEstimate Estimate(duckdb::LogicalOperator &root); +}; + +class SimpleEstimator : public Estimator { +public: + using Estimator::Estimator; + CostEstimate Estimate(duckdb::LogicalOperator &root) override; +}; + +} // namespace duckdb diff --git a/src/include/cost_model/stat_source.hpp b/src/include/cost_model/stat_source.hpp new file mode 100644 index 0000000..f13d698 --- /dev/null +++ b/src/include/cost_model/stat_source.hpp @@ -0,0 +1,29 @@ +#pragma once +#include "duckdb.hpp" +#include "duckdb/common/types.hpp" +#include +#include + +namespace duckdb { + +struct Stat { + explicit Stat(std::string n) : name(std::move(n)) {} + std::string name; + virtual ~Stat() = default; +}; + +struct OutputStat : public Stat { + duckdb::idx_t rows, cols; + OutputStat(duckdb::idx_t r, duckdb::idx_t c) : Stat(""), rows(r), cols(c) {} +}; + +struct Source { + enum class Type { NODE, FILE, VECTOR, DATABASE }; + std::string name; + Type type; + std::shared_ptr stats; + Source(std::string n, Type t, std::shared_ptr s) + : name(std::move(n)), type(t), stats(std::move(s)) {} +}; + +} // namespace duckdb diff --git a/src/include/cost_model/udf_cost_coeff.hpp b/src/include/cost_model/udf_cost_coeff.hpp new file mode 100644 index 0000000..6377d09 --- /dev/null +++ b/src/include/cost_model/udf_cost_coeff.hpp @@ -0,0 +1,17 @@ +// .hpp +#pragma once +#include +#include +#include +#include "duckdb.hpp" + +namespace duckdb { +class UdfCostCoeff { +public: + static const std::vector& Get(const std::string &key); + static void InitFromFile(const std::string &path = ""); +private: + static std::unordered_map> &Map(); + static bool &Initialized(); +}; +} // namespace cactusdb diff --git a/src/optimization/dynamic_optimizer.cpp b/src/optimization/dynamic_optimizer.cpp index ce9e739..2f0f352 100644 --- a/src/optimization/dynamic_optimizer.cpp +++ b/src/optimization/dynamic_optimizer.cpp @@ -2,6 +2,7 @@ #include "optimization/dynamic_optimizer.hpp" #include "optimization/actions/MatMulDense2SparseRewriteAction.hpp" #include "optimization/catalog.hpp" +#include "cost_model/estimator.hpp" namespace duckdb{ void DynamicOpt::Optimize(OptimizerExtensionInput &in, unique_ptr &plan) { @@ -21,6 +22,10 @@ namespace duckdb{ MatMulDense2SparseRewriteAction::apply(in, plan); } + SimpleEstimator est(std::make_unique()); + auto total = est.Estimate(*plan); + std::cout << "\n Final plan cost after Dynamic Optimization: " << total.cost; + // plan = std::move(initial_plan); // plan = cat.resetQueryPlanFromCache(in.context,0); From 2a1ea601d7ee0402a716faf45dde774954d4ee11 Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 12 Nov 2025 13:17:27 -0700 Subject: [PATCH 09/18] Feature Extraction Framework Added for Query2Vec --- .../one_hot_encoder_rewrite_rule.test | 0 expedia.json | 185 ++++++++++++++++++ queries/expedia_query.sql | 7 +- src/cost_model/cost_model.cpp | 5 +- src/include/ml_functions/argmax.hpp | 25 +++ src/include/ml_functions/matrix_addition.hpp | 107 ++++++++++ src/include/ml_functions/sigmoid.hpp | 22 +++ src/include/ml_functions/softmax.hpp | 25 +++ .../query2vec/query_annotation.hpp | 24 +++ .../query2vec/query_feature_extraction.hpp | 15 ++ src/ml_functions/CMakeLists.txt | 4 + src/ml_functions/argmax.cpp | 103 ++++++++++ src/ml_functions/matrix_addition.cpp | 127 ++++++++++++ src/ml_functions/matrix_multiplication.cpp | 4 +- src/ml_functions/ml_functions_scalar.cpp | 8 + src/ml_functions/sigmoid.cpp | 113 +++++++++++ src/ml_functions/softmax.cpp | 132 +++++++++++++ src/optimization/CMakeLists.txt | 4 + src/optimization/dynamic_optimizer.cpp | 10 + .../query2vec/query_annotation.cpp | 47 +++++ .../query2vec/query_feature_extraction.cpp | 138 +++++++++++++ test/sql/argmax.test | 54 +++++ test/sql/matadd.test | 62 ++++++ test/sql/matmul.test | 2 +- test/sql/sigmoid.test | 53 +++++ test/sql/softmax.test | 57 ++++++ 26 files changed, 1323 insertions(+), 10 deletions(-) rename {test/sql => archived_tests}/one_hot_encoder_rewrite_rule.test (100%) create mode 100644 expedia.json create mode 100644 src/include/ml_functions/argmax.hpp create mode 100644 src/include/ml_functions/matrix_addition.hpp create mode 100644 src/include/ml_functions/sigmoid.hpp create mode 100644 src/include/ml_functions/softmax.hpp create mode 100644 src/include/optimization/feature_extraction/query2vec/query_annotation.hpp create mode 100644 src/include/optimization/feature_extraction/query2vec/query_feature_extraction.hpp create mode 100644 src/ml_functions/argmax.cpp create mode 100644 src/ml_functions/matrix_addition.cpp create mode 100644 src/ml_functions/sigmoid.cpp create mode 100644 src/ml_functions/softmax.cpp create mode 100644 src/optimization/feature_extraction/query2vec/query_annotation.cpp create mode 100644 src/optimization/feature_extraction/query2vec/query_feature_extraction.cpp create mode 100644 test/sql/argmax.test create mode 100644 test/sql/matadd.test create mode 100644 test/sql/sigmoid.test create mode 100644 test/sql/softmax.test diff --git a/test/sql/one_hot_encoder_rewrite_rule.test b/archived_tests/one_hot_encoder_rewrite_rule.test similarity index 100% rename from test/sql/one_hot_encoder_rewrite_rule.test rename to archived_tests/one_hot_encoder_rewrite_rule.test diff --git a/expedia.json b/expedia.json new file mode 100644 index 0000000..e35bd95 --- /dev/null +++ b/expedia.json @@ -0,0 +1,185 @@ +{ + "total_bytes_written": 0, + "total_bytes_read": 0, + "rows_returned": 79756, + "latency": 0.681805286, + "result_set_size": 2871216, + "query_name": "SELECT\n s.prop_id,\n s.srch_id,\n tree_predict(\n list_transform(\n list_concat(\n /* 1) NUMERICALS — per-column scaling (exact order) */\n min_max_scaler(list_value(CAST(s.prop_location_score1 AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score1.txt'),\n min_max_scaler(list_value(CAST(s.prop_location_score2 AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score2.txt'),\n min_max_scaler(list_value(CAST(s.prop_log_historical_price AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_log_historical_price.txt'),\n min_max_scaler(list_value(CAST(s.price_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/price_usd.txt'),\n min_max_scaler(list_value(CAST(s.orig_destination_distance AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/orig_destination_distance.txt'),\n min_max_scaler(list_value(CAST(h.prop_review_score AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_review_score.txt'),\n min_max_scaler(list_value(CAST(h.avg_bookings_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/avg_bookings_usd.txt'),\n min_max_scaler(list_value(CAST(h.stdev_bookings_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/stdev_bookings_usd.txt'),\n\n /* 2) CATEGORICALS — one-hot, exact order of your Python */\n -- stringEncoderSpecs (string→int): TRUE\n one_hot_encode(CAST(s.position AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/position.csv', TRUE),\n one_hot_encode(CAST(h.prop_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_country_id.csv', TRUE),\n\n -- encoderSpecs (int→int): FALSE\n one_hot_encode(CAST(h.prop_starrating AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_starrating.csv', FALSE),\n one_hot_encode(CAST(h.prop_brand_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_brand_bool.csv', FALSE),\n one_hot_encode(CAST(h.count_clicks AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_clicks.csv', FALSE),\n one_hot_encode(CAST(h.count_bookings AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_bookings.csv', FALSE),\n\n -- stringEncoderSpecs (string→int): TRUE\n one_hot_encode(CAST(r.year AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/year.csv', TRUE),\n one_hot_encode(CAST(r.month AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/month.csv', TRUE),\n one_hot_encode(CAST(r.weekofyear AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/weekofyear.csv', TRUE),\n one_hot_encode(CAST(r.time AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/time.csv', TRUE),\n one_hot_encode(CAST(r.site_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/site_id.csv', TRUE),\n one_hot_encode(CAST(r.visitor_location_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/visitor_location_country_id.csv', TRUE),\n one_hot_encode(CAST(r.srch_destination_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_destination_id.csv', TRUE),\n\n -- encoderSpecs (int→int): FALSE\n one_hot_encode(CAST(r.srch_length_of_stay AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_length_of_stay.csv', FALSE),\n one_hot_encode(CAST(r.srch_booking_window AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_booking_window.csv', FALSE),\n one_hot_encode(CAST(r.srch_adults_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_adults_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_children_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_children_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_room_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_room_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_saturday_night_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_saturday_night_bool.csv', FALSE),\n one_hot_encode(CAST(r.random_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/random_bool.csv', FALSE)\n ),\n x -> CAST(x AS FLOAT) -- tree_predict expects LIST\n ),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/tree/0.txt',\n FALSE\n ) AS prediction\nFROM Expedia_S_listings_extension2 AS s\nJOIN Expedia_R1_hotels2 AS h ON s.prop_id = h.prop_id\nJOIN Expedia_R2_searches AS r ON s.srch_id = r.srch_id\nWHERE s.prop_location_score1 > 1\n AND s.prop_location_score2 > 0.1\n AND s.prop_log_historical_price > 4\n AND h.count_bookings > 5\n AND r.srch_booking_window > 10\n AND r.srch_length_of_stay > 1;", + "blocked_thread_time": 0.0, + "system_peak_buffer_memory": 41531392, + "system_peak_temp_dir_size": 0, + "cpu_time": 4.6555288699999995, + "extra_info": {}, + "cumulative_cardinality": 637172, + "cumulative_rows_scanned": 7586096, + "children": [ + { + "total_bytes_written": 0, + "total_bytes_read": 0, + "result_set_size": 2871216, + "operator_name": "PROJECTION", + "cpu_time": 4.6555288699999995, + "extra_info": { + "Projections": [ + "prop_id", + "srch_id", + "prediction" + ], + "Estimated Cardinality": "7220" + }, + "cumulative_cardinality": 637172, + "operator_type": "PROJECTION", + "operator_cardinality": 79756, + "cumulative_rows_scanned": 7586096, + "operator_rows_scanned": 0, + "operator_timing": 4.481584809999999, + "children": [ + { + "total_bytes_written": 0, + "total_bytes_read": 0, + "result_set_size": 26798016, + "operator_name": "HASH_JOIN", + "cpu_time": 0.17394405999999998, + "extra_info": { + "Join Type": "INNER", + "Conditions": "srch_id = srch_id", + "Estimated Cardinality": "7220" + }, + "cumulative_cardinality": 557416, + "operator_type": "HASH_JOIN", + "operator_cardinality": 79756, + "cumulative_rows_scanned": 7586096, + "operator_rows_scanned": 0, + "operator_timing": 0.026865787000000002, + "children": [ + { + "total_bytes_written": 0, + "total_bytes_read": 0, + "result_set_size": 35619696, + "operator_name": "HASH_JOIN", + "cpu_time": 0.14224183099999999, + "extra_info": { + "Join Type": "INNER", + "Conditions": "prop_id = prop_id", + "Estimated Cardinality": "36103" + }, + "cumulative_cardinality": 466608, + "operator_type": "HASH_JOIN", + "operator_cardinality": 212022, + "cumulative_rows_scanned": 7549075, + "operator_rows_scanned": 0, + "operator_timing": 0.03631979799999999, + "children": [ + { + "total_bytes_written": 0, + "total_bytes_read": 0, + "result_set_size": 21772608, + "operator_name": "SEQ_SCAN ", + "cpu_time": 0.104767166, + "extra_info": { + "Table": "Expedia_S_listings_extension2", + "Type": "Sequential Scan", + "Projections": [ + "prop_id", + "srch_id", + "prop_location_score1", + "prop_location_score2", + "prop_log_historical_price", + "price_usd", + "orig_destination_distance", + "position" + ], + "Filters": [ + "prop_location_score1>1.0", + "prop_location_score2>0.1", + "prop_log_historical_price>4.0" + ], + "Estimated Cardinality": "188428" + }, + "cumulative_cardinality": 247416, + "operator_type": "TABLE_SCAN", + "operator_cardinality": 247416, + "cumulative_rows_scanned": 7537136, + "operator_rows_scanned": 7537136, + "operator_timing": 0.104767166, + "children": [] + }, + { + "total_bytes_written": 0, + "total_bytes_read": 0, + "result_set_size": 688320, + "operator_name": "SEQ_SCAN ", + "cpu_time": 0.0011548670000000002, + "extra_info": { + "Table": "Expedia_R1_hotels2", + "Type": "Sequential Scan", + "Projections": [ + "prop_id", + "count_bookings", + "prop_review_score", + "avg_bookings_usd", + "stdev_bookings_usd", + "prop_country_id", + "prop_starrating", + "prop_brand_bool", + "count_clicks" + ], + "Filters": "count_bookings>5", + "Estimated Cardinality": "2387" + }, + "cumulative_cardinality": 7170, + "operator_type": "TABLE_SCAN", + "operator_cardinality": 7170, + "cumulative_rows_scanned": 11939, + "operator_rows_scanned": 11939, + "operator_timing": 0.0011548670000000002, + "children": [] + } + ] + }, + { + "total_bytes_written": 0, + "total_bytes_read": 0, + "result_set_size": 2033568, + "operator_name": "SEQ_SCAN ", + "cpu_time": 0.004836442, + "extra_info": { + "Table": "Expedia_R2_searches", + "Type": "Sequential Scan", + "Projections": [ + "srch_id", + "srch_booking_window", + "srch_length_of_stay", + "year", + "month", + "weekofyear", + "time", + "site_id", + "visitor_location_country_id", + "srch_destination_id", + "srch_adults_count", + "srch_children_count", + "srch_room_count", + "srch_saturday_night_bool", + "random_bool" + ], + "Filters": [ + "srch_booking_window>10", + "srch_length_of_stay>1" + ], + "Estimated Cardinality": "7404" + }, + "cumulative_cardinality": 11052, + "operator_type": "TABLE_SCAN", + "operator_cardinality": 11052, + "cumulative_rows_scanned": 37021, + "operator_rows_scanned": 37021, + "operator_timing": 0.004836442, + "children": [] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/queries/expedia_query.sql b/queries/expedia_query.sql index 97145ae..e3bff95 100644 --- a/queries/expedia_query.sql +++ b/queries/expedia_query.sql @@ -4,9 +4,11 @@ ATTACH '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgex SET schema 'expedia_db.main'; -- Optimizer Config --- PRAGMA enable_profiling=json; +PRAGMA enable_profiling; +SET enable_profiling = 'json'; +SET profiling_output = '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/expedia.json'; -- PRAGMA profiling_output='/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/plans/profile.json'; -PRAGMA disable_optimizer; +-- PRAGMA disable_optimizer; -- PRAGMA explain_output='json'; -- SET enable_profiling = 'query_tree_optimizer'; -- SET profiling_mode = 'detailed'; @@ -19,7 +21,6 @@ set threads = 8; -- SELECT 'Expedia_S_listings_extension2' AS which, * FROM Expedia_S_listings_extension2 LIMIT 10; -- SELECT 'Expedia_R1_hotels2' AS which, * FROM Expedia_R1_hotels2 LIMIT 10; -- SELECT 'Expedia_R2_searches' AS which, * FROM Expedia_R2_searches LIMIT 10; -EXPLAIN (FORMAT TEXT) SELECT s.prop_id, s.srch_id, diff --git a/src/cost_model/cost_model.cpp b/src/cost_model/cost_model.cpp index 1e4fa70..053cd2d 100644 --- a/src/cost_model/cost_model.cpp +++ b/src/cost_model/cost_model.cpp @@ -18,7 +18,7 @@ CostModel::Node CostModel::MapNode(const LogicalOperator &op) { case LogicalOperatorType::LOGICAL_PROJECTION: return Node::Projection; case LogicalOperatorType::LOGICAL_GET: return Node::Get; case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: - case LogicalOperatorType::LOGICAL_ANY_JOIN: return Node::HashJoin; // refine below if needed + case LogicalOperatorType::LOGICAL_ANY_JOIN: return Node::HashJoin; case LogicalOperatorType::LOGICAL_ORDER_BY: return Node::Order; case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: return Node::Aggregate; case LogicalOperatorType::LOGICAL_DELIM_JOIN: @@ -97,7 +97,6 @@ CostEstimate SimpleCostModel::HandleProjection(LogicalOperator &op, const std::v // Very similar to your Velox logic: parse UDFs from expressions and sum costs std::vector udfs; udfs.reserve(proj.expressions.size()); for (auto &expr : proj.expressions) { - // naive: use expr->ToString() and parse func names between identifier and '(' std::cout << "\nProjection Expr: " << expr->ToString() << "\n"; udfs.push_back(expr->ToString()); // parse later inside UDFChainCost } @@ -109,7 +108,6 @@ CostEstimate SimpleCostModel::UDFChainCost(const std::vector &udfs_ auto stat = std::static_pointer_cast(inputs[0].stats); CostEstimate out(0.0, stat->rows, stat->cols); - // (A) extract UDF ids inner→outer std::vector udf_ids; udf_ids.reserve(udfs_raw.size()); for (auto &s : udfs_raw) { @@ -119,7 +117,6 @@ CostEstimate SimpleCostModel::UDFChainCost(const std::vector &udfs_ } std::reverse(udf_ids.begin(), udf_ids.end()); - // (B) accumulate via UdfCostCoeff map for (auto &u : udf_ids) { std::cout << "\nUDF detected: " << u << "\n"; auto coeff = UdfCostCoeff::Get(u); diff --git a/src/include/ml_functions/argmax.hpp b/src/include/ml_functions/argmax.hpp new file mode 100644 index 0000000..498e75b --- /dev/null +++ b/src/include/ml_functions/argmax.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +#include "duckdb.hpp" +#include "duckdb/function/function.hpp" + +namespace duckdb { + +struct ML_Argmax { + // We don't need bind state; this just enforces arity (optionally types) + static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args); + + // Executor: argmax over each LIST row + static void Execute(DataChunk &args, ExpressionState &state, Vector &result); + + // Registration + static void Register(ExtensionLoader &loader); +}; + +} // namespace duckdb diff --git a/src/include/ml_functions/matrix_addition.hpp b/src/include/ml_functions/matrix_addition.hpp new file mode 100644 index 0000000..5fc25de --- /dev/null +++ b/src/include/ml_functions/matrix_addition.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include + +#include "duckdb.hpp" // umbrella header (brings in FunctionData, ScalarFunction, DataChunk, etc.) +#include "duckdb/function/function.hpp" + +#include +#include +#include + +namespace duckdb { + struct ML_MatrixAddition { + struct BindData final : public FunctionData { + vector biases; // length n + idx_t n = 0; // length of biases + std::string biases_file; + bool has_bound_biases = false; + BindData() = default; + BindData(const vector &b, idx_t n_, + const std::string &file, bool bound) + : biases(b), n(n_), biases_file(file), has_bound_biases(bound) {} + unique_ptr Copy() const override { + // deep copy (vector/string copy is deep) + return make_uniq(biases, n, biases_file, has_bound_biases); + } + bool Equals(const FunctionData &other_p) const override { + auto &o = other_p.Cast(); + return has_bound_biases == o.has_bound_biases && + n == o.n && + biases_file == o.biases_file && + biases == o.biases; + } + }; + + static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args); + static void Execute(DataChunk &args, ExpressionState &state, Vector &result); + static void Register(ExtensionLoader &loader); + + static void ParseCSVBiases(const std::string &path, + std::vector &b, + idx_t &n) { + std::ifstream f(path); + if (!f.is_open()) { + throw InvalidInputException("mat_add: cannot open biases file: %s", path.c_str()); + } + + b.clear(); + n = 0; + + std::string line; + // read first non-empty line + while (std::getline(f, line)) { + // trim whitespace + auto l = line.find_first_not_of(" \t\r\n"); + if (l == std::string::npos) continue; // skip blank line + auto r = line.find_last_not_of(" \t\r\n"); + line = line.substr(l, r - l + 1); + break; + } + + if (line.empty()) { + throw InvalidInputException("mat_add: empty biases file: %s", path.c_str()); + } + + std::stringstream ss(line); + std::string cell; + while (std::getline(ss, cell, ',')) { + // trim token + auto l = cell.find_first_not_of(" \t\r\n"); + auto r = cell.find_last_not_of(" \t\r\n"); + std::string tok = (l == std::string::npos) ? "" : cell.substr(l, r - l + 1); + if (tok.empty()) { + throw InvalidInputException("mat_add: empty field in biases file: %s", path.c_str()); + } + try { + b.emplace_back(std::stod(tok)); + } catch (...) { + throw InvalidInputException("mat_add: non-numeric bias '%s' in %s", + tok.c_str(), path.c_str()); + } + } + + if (b.empty()) { + throw InvalidInputException("mat_add: no values found in %s", path.c_str()); + } + + n = static_cast(b.size()); + + // if there are more non-empty lines, treat as error (we expect exactly one row) + std::string extra; + while (std::getline(f, extra)) { + auto l2 = extra.find_first_not_of(" \t\r\n"); + if (l2 != std::string::npos) { + throw InvalidInputException("mat_add: multiple rows found in %s; expected a single 1xN row", + path.c_str()); + } + } + } + + + }; +} // namespace duckdb end \ No newline at end of file diff --git a/src/include/ml_functions/sigmoid.hpp b/src/include/ml_functions/sigmoid.hpp new file mode 100644 index 0000000..46c4a92 --- /dev/null +++ b/src/include/ml_functions/sigmoid.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +#include "duckdb.hpp" +#include "duckdb/function/function.hpp" + +namespace duckdb { + +struct ML_Sigmoid { + static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args); + + static void Execute(DataChunk &args, ExpressionState &state, Vector &result); + + static void Register(ExtensionLoader &loader); +}; + +} // namespace duckdb diff --git a/src/include/ml_functions/softmax.hpp b/src/include/ml_functions/softmax.hpp new file mode 100644 index 0000000..9f66e02 --- /dev/null +++ b/src/include/ml_functions/softmax.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +#include "duckdb.hpp" +#include "duckdb/function/function.hpp" + +namespace duckdb { + +struct ML_Softmax { + // No bind state required + static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args); + + // Execute softmax over each LIST row + static void Execute(DataChunk &args, ExpressionState &state, Vector &result); + + // Register the function with a unique name to avoid collisions + static void Register(ExtensionLoader &loader); +}; + +} // namespace duckdb diff --git a/src/include/optimization/feature_extraction/query2vec/query_annotation.hpp b/src/include/optimization/feature_extraction/query2vec/query_annotation.hpp new file mode 100644 index 0000000..9a6c4d1 --- /dev/null +++ b/src/include/optimization/feature_extraction/query2vec/query_annotation.hpp @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include +#include "duckdb.hpp" +#include "duckdb/planner/logical_operator.hpp" + +namespace duckdb { + +struct AnnotatedPlanNode { + idx_t node_id{0}; + const LogicalOperator *plan_node{nullptr}; // non-owning pointer + std::vector> children; + vector features; // placeholder for extracted features +}; + +// Call with: AnnotatePlanTree(*logical_plan_unique_ptr); +std::unique_ptr AnnotatePlanTree(const LogicalOperator &root); + +void DisplayAnnotatedPlan(const AnnotatedPlanNode &node, idx_t depth = 0); + +AnnotatedPlanNode* FindNodeById(AnnotatedPlanNode &node, idx_t target_id); + +} // namespace duckdb diff --git a/src/include/optimization/feature_extraction/query2vec/query_feature_extraction.hpp b/src/include/optimization/feature_extraction/query2vec/query_feature_extraction.hpp new file mode 100644 index 0000000..8040306 --- /dev/null +++ b/src/include/optimization/feature_extraction/query2vec/query_feature_extraction.hpp @@ -0,0 +1,15 @@ +#include "duckdb.hpp" +#include "optimization/feature_extraction/query2vec/query_annotation.hpp" + +namespace duckdb{ + + std::string filter_feature_extract(const AnnotatedPlanNode &node); + std::string get_filters_feature_extract(const AnnotatedPlanNode &node); + std::string get_table_feature_extract(const AnnotatedPlanNode &node); + std::string aggregate_feature_extract(const AnnotatedPlanNode &node); + + void traverse_and_extract(const AnnotatedPlanNode &node); + + void extract_features(const AnnotatedPlanNode &node); + +} \ No newline at end of file diff --git a/src/ml_functions/CMakeLists.txt b/src/ml_functions/CMakeLists.txt index e8efb0e..d5ba2f8 100644 --- a/src/ml_functions/CMakeLists.txt +++ b/src/ml_functions/CMakeLists.txt @@ -4,6 +4,10 @@ set(ML_FUNCTIONS_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/min_max_scaler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/one_hot_encoder.cpp ${CMAKE_CURRENT_SOURCE_DIR}/decision_tree.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/matrix_addition.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/argmax.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/softmax.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sigmoid.cpp ) set(EXTENSION_SOURCES diff --git a/src/ml_functions/argmax.cpp b/src/ml_functions/argmax.cpp new file mode 100644 index 0000000..a58751a --- /dev/null +++ b/src/ml_functions/argmax.cpp @@ -0,0 +1,103 @@ +#include "ml_functions/argmax.hpp" + +#include + +#include "duckdb/common/exception.hpp" +#include "duckdb/common/types.hpp" +#include "duckdb/common/vector.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/function/scalar_function.hpp" +#include "duckdb/parser/parsed_data/create_scalar_function_info.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" + +namespace duckdb { + +// ---------------- Bind ---------------- +unique_ptr ML_Argmax::Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + if (args.size() != 1) { + throw BinderException("argmax: expects exactly 1 argument: LIST"); + } + // If you want to enforce the element type strictly at bind time: + // if (args[0]->return_type != LogicalType::LIST(LogicalType::DOUBLE)) { ... } + return nullptr; // no bind info needed +} + +// ---------------- Execute ---------------- +void ML_Argmax::Execute(DataChunk &args, ExpressionState &state, Vector &result) { + const idx_t count = args.size(); + + // Input: LIST + Vector &in = args.data[0]; + UnifiedVectorFormat in_uvf; + in.ToUnifiedFormat(count, in_uvf); + const auto *entries = UnifiedVectorFormat::GetData(in_uvf); + + // Child payload for the list (flat array of doubles) + auto &child = ListVector::GetEntry(in); + const idx_t total_elems = ListVector::GetListSize(in); + UnifiedVectorFormat child_uvf; + child.ToUnifiedFormat(total_elems, child_uvf); + const double *child_data = UnifiedVectorFormat::GetData(child_uvf); + const auto &child_valid = child_uvf.validity; + + // Output: INTEGER + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *out = FlatVector::GetData(result); + auto &out_valid = FlatVector::Validity(result); + + for (idx_t i = 0; i < count; ++i) { + const idx_t sel = in_uvf.sel->get_index(i); + + // NULL row → NULL result + if (!in_uvf.validity.RowIsValid(sel)) { + out_valid.Set(i, false); + continue; + } + + const auto le = entries[sel]; + const idx_t len = le.length; + const idx_t off = le.offset; + + if (len == 0) { + throw InvalidInputException("argmax: empty list at row %llu", + (unsigned long long)i); + } + + // Disallow NULL elements inside the list (strict mode) + if (!child_valid.AllValid()) { + for (idx_t j = 0; j < len; ++j) { + if (!child_valid.RowIsValid(off + j)) { + throw InvalidInputException( + "argmax: NULL element in list at row %llu (position %llu)", + (unsigned long long)i, (unsigned long long)j + ); + } + } + } + + // Map this row as an Eigen row-vector and get argmax + using RowVec = Eigen::Matrix; + Eigen::Map row(child_data + off, (Eigen::Index)len); + Eigen::Index max_row, max_col; + row.maxCoeff(&max_row, &max_col); // max_row will be 0 for a row-vector + + out[i] = static_cast(max_col); // 0-based index + } +} + +// ---------------- Register ---------------- +void ML_Argmax::Register(ExtensionLoader &loader) { + ScalarFunction fn( + "ml_argmax", + { LogicalType::LIST(LogicalType::DOUBLE) }, // x + LogicalType::INTEGER, // returns index + Execute + ); + fn.bind = Bind; + fn.stability = FunctionStability::VOLATILE; + loader.RegisterFunction(fn); +} + +} // namespace duckdb diff --git a/src/ml_functions/matrix_addition.cpp b/src/ml_functions/matrix_addition.cpp new file mode 100644 index 0000000..8851324 --- /dev/null +++ b/src/ml_functions/matrix_addition.cpp @@ -0,0 +1,127 @@ +#include "ml_functions/matrix_addition.hpp" + +#include +#include +#include + +#include +#include + +#include "duckdb/common/constants.hpp" +#include "duckdb/common/enum_util.hpp" +#include "duckdb/common/exception.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/common/types.hpp" +#include "duckdb/common/types/blob.hpp" +#include "duckdb/common/types/value.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/function/scalar_function.hpp" +#include "duckdb/parser/parsed_data/create_scalar_function_info.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/common/vector_operations/generic_executor.hpp" +#include "duckdb/common/vector_operations/septenary_executor.hpp" + +namespace duckdb { +// ========================= BindData impl ========================= +unique_ptr ML_MatrixAddition::Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + if (args.size() != 2) { + throw InvalidInputException("mat_add: expects 2 arguments: x, biases_file"); + } + + // (Optional) enforce constant filename at bind time + if (!args[1]->IsFoldable()) { + throw BinderException("mat_add: biases_file must be a constant string"); + } + + auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); + if (vFile.IsNull()) { + throw BinderException("mat_add: biases_file is NULL"); + } + const std::string path = vFile.ToString(); + + // Parse into std::vector because ParseCSVBiases takes std::vector& + std::vector biases_std; + idx_t n = 0; + ParseCSVBiases(path, biases_std, n); + + // Convert to duckdb::vector expected by BindData + vector biases_duck(biases_std.begin(), biases_std.end()); + + return make_uniq(biases_duck, n, path, /*bound*/ true); +} + +// ========================= Execute ========================= +void ML_MatrixAddition::Execute(DataChunk &args, ExpressionState &state, Vector &result) { + const idx_t count = args.size(); // tuples in this chunk + + // Input LIST + Vector &lhs = args.data[0]; + UnifiedVectorFormat lhs_uvf; + lhs.ToUnifiedFormat(count, lhs_uvf); + const auto *entries = UnifiedVectorFormat::GetData(lhs_uvf); + + auto &child = ListVector::GetEntry(lhs); + const idx_t total_elems = ListVector::GetListSize(lhs); + UnifiedVectorFormat child_uvf; + child.ToUnifiedFormat(total_elems, child_uvf); + const double *child_data = UnifiedVectorFormat::GetData(child_uvf); + + //read the bound data + const auto &func_expr = state.expr.Cast(); + const auto &info = func_expr.bind_info->Cast(); + if (!info.has_bound_biases) { + throw InvalidInputException("mat_add: biases are not bound"); + } + const idx_t n = info.n; + const std::vector &biases = info.biases; + + // Prepare result in a FlatVector + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + const idx_t total_out = count * n; + ListVector::Reserve(result, total_out); + ListVector::SetListSize(result, total_out); + double *out = FlatVector::GetData(res_child); + auto &res_valid = FlatVector::Validity(result); + + //main loop + idx_t cursor = 0; + for(idx_t i = 0;iget_index(i); + if(lhs_uvf.validity.RowIsValid(idx)){ + const auto ent = entries[idx]; + if(ent.length != n){ + throw InvalidInputException("mat_add: Input vector length %llu does not match the bound biases length %llu", (unsigned long long)ent.length, (unsigned long long)n); + } + res_entries[i] = {cursor, n}; + const double *row = child_data + ent.offset; + for (idx_t j = 0;j + LogicalType::VARCHAR // biases_file VARCHAR + }, + LogicalType::LIST(LogicalType::DOUBLE), // RETURNS LIST + Execute + ); + fn.bind = Bind; + loader.RegisterFunction(fn); + fn.stability = FunctionStability::VOLATILE; // reads a file; avoid constant folding if desired +} // register end +}//duckdb namespace end \ No newline at end of file diff --git a/src/ml_functions/matrix_multiplication.cpp b/src/ml_functions/matrix_multiplication.cpp index 7a46d7d..ba455bc 100644 --- a/src/ml_functions/matrix_multiplication.cpp +++ b/src/ml_functions/matrix_multiplication.cpp @@ -189,7 +189,7 @@ void ML_MatrixMultiply::Execute(DataChunk &args, ExpressionState &state, Vector if (bd.mode == MulMode::Dense) { // -------- DENSE PATH (build X_dense then Y = X_dense * W) -------- - std::cout << "\n\nDense Execution\n\n"; + // std::cout << "\n\nDense Execution\n\n"; RowMat X_dense; for (idx_t i = 0; i < count; i++) { const idx_t sel = lhs_uvf.sel->get_index(i); @@ -261,7 +261,7 @@ void ML_MatrixMultiply::Execute(DataChunk &args, ExpressionState &state, Vector // -------- INPUT-SPARSE PATH (Velox-style) -------- // Deduplicate selected base rows → compact indices - std::cout << "\n\nSparse Execution\n\n"; + // std::cout << "\n\nSparse Execution\n\n"; std::unordered_map raw_to_compact; raw_to_compact.reserve((size_t)count * 2); diff --git a/src/ml_functions/ml_functions_scalar.cpp b/src/ml_functions/ml_functions_scalar.cpp index 699d057..68ab223 100644 --- a/src/ml_functions/ml_functions_scalar.cpp +++ b/src/ml_functions/ml_functions_scalar.cpp @@ -3,6 +3,10 @@ #include "min_max_scaler.cpp" #include "ml_functions/one_hot_encoder.hpp" #include "decision_tree.cpp" +#include "ml_functions/matrix_addition.hpp" +#include "ml_functions/argmax.hpp" +#include "ml_functions/softmax.hpp" +#include "ml_functions/sigmoid.hpp" namespace duckdb { @@ -12,6 +16,10 @@ void RegisterMLScalarFunctions(ExtensionLoader &loader) { ML_MinMaxScaler::Register(loader); ML_OneHotEncoder::Register(loader); ML_DecisionTree::Register(loader); + ML_MatrixAddition::Register(loader); + ML_Argmax::Register(loader); + ML_Softmax::Register(loader); + ML_Sigmoid::Register(loader); // RegisterSoftmax(loader); // RegisterSigmoid(loader); } diff --git a/src/ml_functions/sigmoid.cpp b/src/ml_functions/sigmoid.cpp new file mode 100644 index 0000000..22adb82 --- /dev/null +++ b/src/ml_functions/sigmoid.cpp @@ -0,0 +1,113 @@ +#include "ml_functions/sigmoid.hpp" + +#include +#include + +#include "duckdb/common/exception.hpp" +#include "duckdb/common/types.hpp" +#include "duckdb/common/vector.hpp" +#include "duckdb/function/scalar_function.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" + +namespace duckdb { + +// -------- Bind -------- +unique_ptr ML_Sigmoid::Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + if (args.size() != 1) { + throw BinderException("cdb_sigmoid: expects exactly 1 argument: LIST"); + } + return nullptr; +} + +// -------- Execute -------- +void ML_Sigmoid::Execute(DataChunk &args, ExpressionState &state, Vector &result) { + const idx_t count = args.size(); + + // Input: LIST + Vector &in = args.data[0]; + UnifiedVectorFormat in_uvf; + in.ToUnifiedFormat(count, in_uvf); + const auto *entries = UnifiedVectorFormat::GetData(in_uvf); + + // Child payload + auto &child = ListVector::GetEntry(in); + const idx_t total_elems = ListVector::GetListSize(in); + UnifiedVectorFormat child_uvf; + child.ToUnifiedFormat(total_elems, child_uvf); + const double *child_data = UnifiedVectorFormat::GetData(child_uvf); + const auto &child_valid = child_uvf.validity; + + // Output LIST + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + auto &res_valid = FlatVector::Validity(result); + + idx_t out_cursor = 0; + ListVector::Reserve(result, total_elems); + + for (idx_t i = 0; i < count; ++i) { + const idx_t sel = in_uvf.sel->get_index(i); + + if (!in_uvf.validity.RowIsValid(sel)) { + res_entries[i] = {0, 0}; + res_valid.Set(i, false); + continue; + } + + const auto le = entries[sel]; + const idx_t len = le.length; + const idx_t off = le.offset; + + if (len == 0) { + throw InvalidInputException("cdb_sigmoid: empty list at row %llu", + (unsigned long long)i); + } + if (!child_valid.AllValid()) { + for (idx_t j = 0; j < len; ++j) { + if (!child_valid.RowIsValid(off + j)) { + throw InvalidInputException( + "cdb_sigmoid: NULL element in list at row %llu (position %llu)", + (unsigned long long)i, (unsigned long long)j + ); + } + } + } + + using RowArr = Eigen::Array; + using RowVec = Eigen::Matrix; + + Eigen::Map row(child_data + off, (Eigen::Index)len); + + // Sigmoid: 1 / (1 + exp(-x)), computed vectorized with Eigen + RowArr probs = 1.0 / (1.0 + (-row.array()).exp()); + + // Materialize + const idx_t prev_total = ListVector::GetListSize(result); + ListVector::SetListSize(result, prev_total + len); + double *out = FlatVector::GetData(res_child); + + res_entries[i].offset = out_cursor; + res_entries[i].length = len; + std::memcpy(out + out_cursor, probs.data(), sizeof(double) * (size_t)len); + out_cursor += len; + } +} + +// -------- Register -------- +void ML_Sigmoid::Register(ExtensionLoader &loader) { + // Unique name to avoid built-in collisions + ScalarFunction fn( + "sigmoid", + { LogicalType::LIST(LogicalType::DOUBLE) }, + LogicalType::LIST(LogicalType::DOUBLE), + Execute + ); + fn.bind = Bind; + fn.stability = FunctionStability::VOLATILE; + loader.RegisterFunction(fn); +} + +} // namespace duckdb diff --git a/src/ml_functions/softmax.cpp b/src/ml_functions/softmax.cpp new file mode 100644 index 0000000..182e9c3 --- /dev/null +++ b/src/ml_functions/softmax.cpp @@ -0,0 +1,132 @@ +#include "ml_functions/softmax.hpp" + +#include + +#include "duckdb/common/exception.hpp" +#include "duckdb/common/types.hpp" +#include "duckdb/common/vector.hpp" +#include "duckdb/function/scalar_function.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" + +namespace duckdb { + +// -------- Bind -------- +unique_ptr ML_Softmax::Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + if (args.size() != 1) { + throw BinderException("cdb_softmax: expects exactly 1 argument: LIST"); + } + // Type checking can be left to the binder; no bind info needed + return nullptr; +} + +// -------- Execute -------- +void ML_Softmax::Execute(DataChunk &args, ExpressionState &state, Vector &result) { + const idx_t count = args.size(); + + // Input: LIST + Vector &in = args.data[0]; + UnifiedVectorFormat in_uvf; + in.ToUnifiedFormat(count, in_uvf); + const auto *entries = UnifiedVectorFormat::GetData(in_uvf); + + // Child payload vector for the list + auto &child = ListVector::GetEntry(in); + const idx_t total_elems = ListVector::GetListSize(in); + UnifiedVectorFormat child_uvf; + child.ToUnifiedFormat(total_elems, child_uvf); + const double *child_data = UnifiedVectorFormat::GetData(child_uvf); + const auto &child_valid = child_uvf.validity; + + // Prepare result LIST + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + auto &res_valid = FlatVector::Validity(result); + + // We will append all outputs contiguously + idx_t out_cursor = 0; + + // We don’t yet know total size; reserve a heuristic to reduce reallocs + ListVector::Reserve(result, total_elems); + + for (idx_t i = 0; i < count; ++i) { + const idx_t sel = in_uvf.sel->get_index(i); + + if (!in_uvf.validity.RowIsValid(sel)) { + // NULL row -> NULL result + res_entries[i] = {0, 0}; + res_valid.Set(i, false); + continue; + } + + const auto le = entries[sel]; + const idx_t len = le.length; + const idx_t off = le.offset; + + if (len == 0) { + throw InvalidInputException("cdb_softmax: empty list at row %llu", + (unsigned long long)i); + } + + // Disallow NULL elements inside list (strict). If you prefer to treat + // NULLs as -inf or error differently, we can change this. + if (!child_valid.AllValid()) { + for (idx_t j = 0; j < len; ++j) { + if (!child_valid.RowIsValid(off + j)) { + throw InvalidInputException( + "cdb_softmax: NULL element in list at row %llu (position %llu)", + (unsigned long long)i, (unsigned long long)j + ); + } + } + } + + using RowVec = Eigen::Matrix; + using RowArr = Eigen::Array; + + // Map current row as Eigen vector + Eigen::Map row(child_data + off, (Eigen::Index)len); + + // Numerical stability: subtract row max before exp + const double row_max = row.maxCoeff(); + RowArr exps = (row.array() - row_max).exp(); + const double denom = exps.sum(); + if (denom == 0.0 || !std::isfinite(denom)) { + throw InvalidInputException("cdb_softmax: invalid denominator (sum(exp(.))=%lf) at row %llu", + denom, (unsigned long long)i); + } + RowArr probs = exps / denom; + + // Materialize into result child + const idx_t prev_total = ListVector::GetListSize(result); + ListVector::SetListSize(result, prev_total + len); + double *out = FlatVector::GetData(res_child); + + res_entries[i].offset = out_cursor; + res_entries[i].length = len; + + std::memcpy(out + out_cursor, + probs.data(), + sizeof(double) * (size_t)len); + out_cursor += len; + } +} + +// -------- Register -------- +void ML_Softmax::Register(ExtensionLoader &loader) { + // Unique name to avoid built-in name collisions + ScalarFunction fn( + "cdb_softmax", + { LogicalType::LIST(LogicalType::DOUBLE) }, + LogicalType::LIST(LogicalType::DOUBLE), + Execute + ); + fn.bind = Bind; + fn.stability = FunctionStability::VOLATILE; // avoid constant folding + + loader.RegisterFunction(fn); +} + +} // namespace duckdb diff --git a/src/optimization/CMakeLists.txt b/src/optimization/CMakeLists.txt index 2e8ed86..a21c7ca 100644 --- a/src/optimization/CMakeLists.txt +++ b/src/optimization/CMakeLists.txt @@ -8,6 +8,10 @@ list(APPEND EXTENSION_SOURCES #All Actions ${CMAKE_CURRENT_SOURCE_DIR}/actions/MatMulDense2SparseRewriteAction.cpp + + #Feature Extraction Helpers + ${CMAKE_CURRENT_SOURCE_DIR}/feature_extraction/query2vec/query_annotation.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/feature_extraction/query2vec/query_feature_extraction.cpp ) # Expose back to parent diff --git a/src/optimization/dynamic_optimizer.cpp b/src/optimization/dynamic_optimizer.cpp index 2f0f352..1e7a09a 100644 --- a/src/optimization/dynamic_optimizer.cpp +++ b/src/optimization/dynamic_optimizer.cpp @@ -4,6 +4,9 @@ #include "optimization/catalog.hpp" #include "cost_model/estimator.hpp" +#include "optimization/feature_extraction/query2vec/query_annotation.hpp" +#include "optimization/feature_extraction/query2vec/query_feature_extraction.hpp" + namespace duckdb{ void DynamicOpt::Optimize(OptimizerExtensionInput &in, unique_ptr &plan) { if (!plan) return; @@ -26,6 +29,13 @@ namespace duckdb{ auto total = est.Estimate(*plan); std::cout << "\n Final plan cost after Dynamic Optimization: " << total.cost; + auto annotated = AnnotatePlanTree(*plan); // pass by const-ref + DisplayAnnotatedPlan(*annotated); + + traverse_and_extract(*annotated); + + + // plan = std::move(initial_plan); // plan = cat.resetQueryPlanFromCache(in.context,0); diff --git a/src/optimization/feature_extraction/query2vec/query_annotation.cpp b/src/optimization/feature_extraction/query2vec/query_annotation.cpp new file mode 100644 index 0000000..4e02ce5 --- /dev/null +++ b/src/optimization/feature_extraction/query2vec/query_annotation.cpp @@ -0,0 +1,47 @@ +#include "optimization/feature_extraction/query2vec/query_annotation.hpp" +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb/common/to_string.hpp" + +namespace duckdb { + +static std::unique_ptr +AnnotateRec(const LogicalOperator &op, idx_t &counter) { + auto node = std::make_unique(); + node->node_id = ++counter; // pre-order id + node->plan_node = &op; // non-owning raw pointer + + node->children.reserve(op.children.size()); + for (idx_t i = 0; i < op.children.size(); ++i) { + const auto &child_op = *op.children[i]; // LogicalOperator& + auto child_node = AnnotateRec(child_op, counter); + node->children.push_back(std::move(child_node)); + } + return node; +} + +std::unique_ptr AnnotatePlanTree(const LogicalOperator &root) { + idx_t counter = 0; + return AnnotateRec(root, counter); +} + +void DisplayAnnotatedPlan(const AnnotatedPlanNode &node, idx_t depth) { + // guard + std::string name = LogicalOperatorToString(node.plan_node->type); + for (idx_t i = 0; i < depth; ++i) std::cout << " "; + std::cout << "Node ID: " << node.node_id << " Type: " << name << "\n"; + for (const auto &ch : node.children) { + DisplayAnnotatedPlan(*ch, depth + 1); + } +} + +AnnotatedPlanNode* FindNodeById(AnnotatedPlanNode &node, idx_t target_id) { + if (node.node_id == target_id) return &node; + for (auto &ch : node.children) { + if (auto *res = FindNodeById(*ch, target_id)) { + return res; + } + } + return nullptr; +} + +} // namespace duckdb diff --git a/src/optimization/feature_extraction/query2vec/query_feature_extraction.cpp b/src/optimization/feature_extraction/query2vec/query_feature_extraction.cpp new file mode 100644 index 0000000..ed089ec --- /dev/null +++ b/src/optimization/feature_extraction/query2vec/query_feature_extraction.cpp @@ -0,0 +1,138 @@ +#include "duckdb.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/planner/operator/logical_filter.hpp" +#include "duckdb/planner/expression/bound_cast_expression.hpp" +#include "duckdb/planner/expression/bound_columnref_expression.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression/bound_comparison_expression.hpp" +#include "duckdb/planner/expression/bound_between_expression.hpp" +#include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/common/enums/expression_type.hpp" + +#include "optimization/feature_extraction/query2vec/query_annotation.hpp" +#include "optimization/feature_extraction/query2vec/query_feature_extraction.hpp" + +namespace duckdb{ + + void extract_features(const AnnotatedPlanNode &node){ + switch (node.plan_node->type){ + case LogicalOperatorType::LOGICAL_PROJECTION : { + //ml features will go here! + std::cout << "Extracting features from PROJECTION node ID: " << node.node_id << "\n"; + } + break; + case LogicalOperatorType::LOGICAL_FILTER : { + std::string ffe = filter_feature_extract(node); + std::cout << "Extracting features from FILTER node ID: " << node.node_id << "\n"; + } + break; + case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY : { + std::string afe = aggregate_feature_extract(node); + std::cout << "Extracting features from AGGREGATE node ID: " << node.node_id << "\n"; + } + break; + case LogicalOperatorType::LOGICAL_JOIN : + case LogicalOperatorType::LOGICAL_COMPARISON_JOIN : + case LogicalOperatorType::LOGICAL_ANY_JOIN : { + std::cout << "Extracting features from JOIN node ID: " << node.node_id << "\n"; + } + break; + case LogicalOperatorType::LOGICAL_GET : { + std::string gffe = get_filters_feature_extract(node); + std::string gtfe = get_table_feature_extract(node); + std::cout << "Extracting features from GET node ID: " << node.node_id << "\n"; + std::cout << " Filters Features: " << gffe << "\n"; + std::cout << " Table Features: " << gtfe << "\n"; + } + break; + default : { + // extract generic features + std::cout << "Extracting generic features from node ID: " << node.node_id << "\n"; + } + break; + } + } + + std::string filter_feature_extract(const AnnotatedPlanNode &node){ + // it should have "input_column operator constant" structure + std::string filter_features = ""; + if(!node.plan_node->expressions.empty()){ + for(auto &expr : node.plan_node->expressions){ + if(expr->expression_class == ExpressionClass::BOUND_COMPARISON){ + auto &comp = expr->Cast(); + std::string left, right, op; + // left + if(comp.left->expression_class == ExpressionClass::BOUND_COLUMN_REF){ + auto &colref = comp.left->Cast(); + left = colref.GetName(); + } + // right + if(comp.right->expression_class == ExpressionClass::BOUND_CONSTANT){ + auto &const_expr = comp.right->Cast(); + right = const_expr.value.ToString(); + } + // operator + op = EnumUtil::ToString(comp.type); + // Combine features + filter_features += left + " " + op + " " + right + ","; + } + } + } + // #TODO Change later to proper edge case handling + return "empty empty empty,"; + } //end of filter_feature_extract + + std::string get_filters_feature_extract(const AnnotatedPlanNode &node) { + // Only for LOGICAL_GET + if (!node.plan_node || node.plan_node->type != LogicalOperatorType::LOGICAL_GET) { + return "No Node"; + } + + const auto &get = node.plan_node->Cast(); + if (get.table_filters.filters.empty()) { + return ""; + } + + std::vector atoms; + atoms.reserve(get.table_filters.filters.size()); + + // Each entry in the filter set is (column_idx -> root filter tree) + for (const auto &kv : get.table_filters.filters) { + const idx_t col_idx = kv.first; + const auto &filter = kv.second; // unique_ptr + if (!filter) continue; + + // Resolve the bound column name for this logical index + const std::string col_name = get.GetColumnName(ColumnIndex(col_idx)); + + // Let the filter render itself as "col OP value" (and/or nested trees) + atoms.push_back(filter->ToString(col_name)); + } + + // Join with ", " + std::string result; + for (idx_t i = 0; i < atoms.size(); ++i) { + if (i) result += ", "; + result += atoms[i]; + } + return result; + } //end of get_filters_feature_extract + + + std::string get_table_feature_extract(const AnnotatedPlanNode &node){ + // Placeholder implementation + return "get_table_features"; + } + + std::string aggregate_feature_extract(const AnnotatedPlanNode &node){ + // Placeholder implementation + return "aggregate_features"; + } + + void traverse_and_extract(const AnnotatedPlanNode &node){ + extract_features(node); + for (const auto &child : node.children) { + traverse_and_extract(*child); + } + } +}// end of namespace duckdb \ No newline at end of file diff --git a/test/sql/argmax.test b/test/sql/argmax.test new file mode 100644 index 0000000..7f80018 --- /dev/null +++ b/test/sql/argmax.test @@ -0,0 +1,54 @@ +# name: test/sql/ml_argmax.test +# description: test ml_argmax scalar function (LIST -> INTEGER index) +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +# ------------------------------------------------------------------ +# Inputs: several rows of DOUBLE[] with varying patterns +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE inputs(a DOUBLE[]); + +# [1,2,3] -> 2 +# [10,5,10] -> 0 (tie: first max) +# [-1,-5,-3] -> 0 (max is -1 at index 0) +# [7,7,7] -> 0 (all equal: first index) +statement ok +INSERT INTO inputs VALUES + ([1,2,3]), + ([10,5,10]), + ([-1,-5,-3]), + ([7,7,7]); + +# ------------------------------------------------------------------ +# Basic ml_argmax on valid rows +# ------------------------------------------------------------------ +query I +SELECT ml_argmax(a) AS idx +FROM inputs; +---- +2 +0 +0 +0 + +# ------------------------------------------------------------------ +# NULL row handling: result should be NULL +# ------------------------------------------------------------------ +statement ok +INSERT INTO inputs VALUES (NULL); + +query I +SELECT ml_argmax(a) AS idx +FROM inputs +ORDER BY 1 NULLS LAST; +---- +0 +0 +0 +2 +NULL \ No newline at end of file diff --git a/test/sql/matadd.test b/test/sql/matadd.test new file mode 100644 index 0000000..3be2f5e --- /dev/null +++ b/test/sql/matadd.test @@ -0,0 +1,62 @@ +# name: test/sql/mat_add.test +# description: test mat_add scalar function (broadcast 1xN biases from CSV) +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +# ------------------------------------------------------------------ +# Create biases.csv: a single 1x3 row +# [0.5, -1.0, 2.5] +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE bias_row(c1 DOUBLE, c2 DOUBLE, c3 DOUBLE); + +statement ok +INSERT INTO bias_row VALUES (0.5, -1.0, 2.5); + +statement ok +COPY bias_row TO 'biases.csv' (FORMAT CSV, HEADER FALSE); + +# ------------------------------------------------------------------ +# Inputs: three rows of equal-length vectors (length = 3) +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE inputs(a DOUBLE[]); + +statement ok +INSERT INTO inputs VALUES ([1,2,3]), ([4,5,6]), ([7,8,9]); + +# ------------------------------------------------------------------ +# Basic broadcast add: y = a + biases +# Expect: +# [1,2,3] + [0.5,-1.0,2.5] = [1.5, 1.0, 5.5] +# [4,5,6] + [0.5,-1.0,2.5] = [4.5, 4.0, 8.5] +# [7,8,9] + [0.5,-1.0,2.5] = [7.5, 7.0, 11.5] +# ------------------------------------------------------------------ +query I +SELECT mat_add(a, 'biases.csv') AS y +FROM inputs +ORDER BY 1; +---- +[1.5, 1.0, 5.5] +[4.5, 4.0, 8.5] +[7.5, 7.0, 11.5] + +# ------------------------------------------------------------------ +# NULL row handling: result should be NULL for that row +# ------------------------------------------------------------------ +statement ok +INSERT INTO inputs VALUES (NULL); + +query I +SELECT mat_add(a, 'biases.csv') AS y +FROM inputs +ORDER BY 1 NULLS LAST; +---- +[1.5, 1.0, 5.5] +[4.5, 4.0, 8.5] +[7.5, 7.0, 11.5] +NULL diff --git a/test/sql/matmul.test b/test/sql/matmul.test index 25f566c..5d6bcc6 100644 --- a/test/sql/matmul.test +++ b/test/sql/matmul.test @@ -47,7 +47,7 @@ INSERT INTO inputs VALUES ([1,2,3]), ([4,5,6]), ([7,8,9]); query I -SELECT mat_mul(mat_mul(a, 'file_1.csv', 'dense'), 'file_2.csv', 'dense') AS y +SELECT mat_mul(mat_mul(a, 'file_1.csv', 'dense'), 'file_2.csv', 'sparse') AS y FROM inputs ORDER BY 1; ---- diff --git a/test/sql/sigmoid.test b/test/sql/sigmoid.test new file mode 100644 index 0000000..ffaf4ba --- /dev/null +++ b/test/sql/sigmoid.test @@ -0,0 +1,53 @@ +# name: test/sql/sigmoid.test +# description: test sigmoid scalar function (LIST -> LIST) +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +# ------------------------------------------------------------------ +# Inputs +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE inputs(a DOUBLE[]); + +# Known cases: +# [0,0] -> [0.5, 0.5] +# [-1,1] -> [~0.268941, ~0.731059] +# [-5,0,5] -> [~0.006693, 0.5, ~0.993307] +# [7,7,7] -> [sigmoid(7)] * 3 +statement ok +INSERT INTO inputs VALUES + ([0,0]), + ([-1,1]), + ([-5,0,5]), + ([7,7,7]); + +# Round for deterministic output +query I +SELECT list_transform(sigmoid(a), x -> round(x::DOUBLE, 6)) AS y +FROM inputs; +---- +[0.5, 0.5] +[0.268941, 0.731059] +[0.006693, 0.5, 0.993307] +[0.999089, 0.999089, 0.999089] + +# ------------------------------------------------------------------ +# NULL row -> NULL +# ------------------------------------------------------------------ +statement ok +INSERT INTO inputs VALUES (NULL); + +query I +SELECT sigmoid(a) AS y +FROM inputs +ORDER BY 1 NULLS LAST; +---- +[0.0066928509242848554, 0.5, 0.9933071490757153] +[0.2689414213699951, 0.7310585786300049] +[0.5, 0.5] +[0.9990889488055994, 0.9990889488055994, 0.9990889488055994] +NULL diff --git a/test/sql/softmax.test b/test/sql/softmax.test new file mode 100644 index 0000000..c82dcc5 --- /dev/null +++ b/test/sql/softmax.test @@ -0,0 +1,57 @@ +# name: test/sql/softmax.test +# description: test cdb_softmax scalar function (LIST -> LIST) +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +# ------------------------------------------------------------------ +# Inputs +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE inputs(a DOUBLE[]); + +# Exact or easy-to-check cases: +# [0,0] -> [0.5, 0.5] +# [0,1] -> [~0.26894, ~0.73106] +# [1,2,3] -> [~0.09003, ~0.24473, ~0.66524] +# [-5, 0, 5] -> [~0.000045, ~0.006693, ~0.993262] (well-known sigmoid-ish spread) +# [7,7,7] -> [1/3, 1/3, 1/3] +statement ok +INSERT INTO inputs VALUES + ([0,0]), + ([0,1]), + ([1,2,3]), + ([-5,0,5]), + ([7,7,7]); + +# Round results to 6 decimals for deterministic comparison +query I +SELECT list_transform(cdb_softmax(a), x -> round(x::DOUBLE, 6)) AS y +FROM inputs; +---- +[0.5, 0.5] +[0.268941, 0.731059] +[0.090031, 0.244728, 0.665241] +[4.5e-05, 0.006693, 0.993262] +[0.333333, 0.333333, 0.333333] + +# ------------------------------------------------------------------ +# NULL row -> NULL +# ------------------------------------------------------------------ +statement ok +INSERT INTO inputs VALUES (NULL); + +query I +SELECT cdb_softmax(a) AS y +FROM inputs +ORDER BY 1 NULLS LAST; +---- +[4.509404123635488e-05, 0.006692549116589288, 0.9932623568421745] +[0.09003057317038048, 0.24472847105479764, 0.6652409557748219] +[0.2689414213699951, 0.7310585786300049] +[0.3333333333333333, 0.3333333333333333, 0.3333333333333333] +[0.5, 0.5] +NULL From 90629b27a1ab86789d974a0f5f0309f3e6b829f0 Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 12 Nov 2025 15:05:39 -0700 Subject: [PATCH 10/18] more feature collections added --- expedia.json | 30 +++++++++---------- .../query2vec/query_feature_extraction.hpp | 1 + .../query2vec/query_feature_extraction.cpp | 22 ++++++++++++-- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/expedia.json b/expedia.json index e35bd95..a6b42a0 100644 --- a/expedia.json +++ b/expedia.json @@ -2,13 +2,13 @@ "total_bytes_written": 0, "total_bytes_read": 0, "rows_returned": 79756, - "latency": 0.681805286, + "latency": 0.666635768, "result_set_size": 2871216, "query_name": "SELECT\n s.prop_id,\n s.srch_id,\n tree_predict(\n list_transform(\n list_concat(\n /* 1) NUMERICALS — per-column scaling (exact order) */\n min_max_scaler(list_value(CAST(s.prop_location_score1 AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score1.txt'),\n min_max_scaler(list_value(CAST(s.prop_location_score2 AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score2.txt'),\n min_max_scaler(list_value(CAST(s.prop_log_historical_price AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_log_historical_price.txt'),\n min_max_scaler(list_value(CAST(s.price_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/price_usd.txt'),\n min_max_scaler(list_value(CAST(s.orig_destination_distance AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/orig_destination_distance.txt'),\n min_max_scaler(list_value(CAST(h.prop_review_score AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_review_score.txt'),\n min_max_scaler(list_value(CAST(h.avg_bookings_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/avg_bookings_usd.txt'),\n min_max_scaler(list_value(CAST(h.stdev_bookings_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/stdev_bookings_usd.txt'),\n\n /* 2) CATEGORICALS — one-hot, exact order of your Python */\n -- stringEncoderSpecs (string→int): TRUE\n one_hot_encode(CAST(s.position AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/position.csv', TRUE),\n one_hot_encode(CAST(h.prop_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_country_id.csv', TRUE),\n\n -- encoderSpecs (int→int): FALSE\n one_hot_encode(CAST(h.prop_starrating AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_starrating.csv', FALSE),\n one_hot_encode(CAST(h.prop_brand_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_brand_bool.csv', FALSE),\n one_hot_encode(CAST(h.count_clicks AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_clicks.csv', FALSE),\n one_hot_encode(CAST(h.count_bookings AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_bookings.csv', FALSE),\n\n -- stringEncoderSpecs (string→int): TRUE\n one_hot_encode(CAST(r.year AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/year.csv', TRUE),\n one_hot_encode(CAST(r.month AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/month.csv', TRUE),\n one_hot_encode(CAST(r.weekofyear AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/weekofyear.csv', TRUE),\n one_hot_encode(CAST(r.time AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/time.csv', TRUE),\n one_hot_encode(CAST(r.site_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/site_id.csv', TRUE),\n one_hot_encode(CAST(r.visitor_location_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/visitor_location_country_id.csv', TRUE),\n one_hot_encode(CAST(r.srch_destination_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_destination_id.csv', TRUE),\n\n -- encoderSpecs (int→int): FALSE\n one_hot_encode(CAST(r.srch_length_of_stay AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_length_of_stay.csv', FALSE),\n one_hot_encode(CAST(r.srch_booking_window AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_booking_window.csv', FALSE),\n one_hot_encode(CAST(r.srch_adults_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_adults_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_children_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_children_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_room_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_room_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_saturday_night_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_saturday_night_bool.csv', FALSE),\n one_hot_encode(CAST(r.random_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/random_bool.csv', FALSE)\n ),\n x -> CAST(x AS FLOAT) -- tree_predict expects LIST\n ),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/tree/0.txt',\n FALSE\n ) AS prediction\nFROM Expedia_S_listings_extension2 AS s\nJOIN Expedia_R1_hotels2 AS h ON s.prop_id = h.prop_id\nJOIN Expedia_R2_searches AS r ON s.srch_id = r.srch_id\nWHERE s.prop_location_score1 > 1\n AND s.prop_location_score2 > 0.1\n AND s.prop_log_historical_price > 4\n AND h.count_bookings > 5\n AND r.srch_booking_window > 10\n AND r.srch_length_of_stay > 1;", "blocked_thread_time": 0.0, - "system_peak_buffer_memory": 41531392, + "system_peak_buffer_memory": 41269248, "system_peak_temp_dir_size": 0, - "cpu_time": 4.6555288699999995, + "cpu_time": 4.4477316799999995, "extra_info": {}, "cumulative_cardinality": 637172, "cumulative_rows_scanned": 7586096, @@ -18,7 +18,7 @@ "total_bytes_read": 0, "result_set_size": 2871216, "operator_name": "PROJECTION", - "cpu_time": 4.6555288699999995, + "cpu_time": 4.4477316799999995, "extra_info": { "Projections": [ "prop_id", @@ -32,14 +32,14 @@ "operator_cardinality": 79756, "cumulative_rows_scanned": 7586096, "operator_rows_scanned": 0, - "operator_timing": 4.481584809999999, + "operator_timing": 4.292808378999999, "children": [ { "total_bytes_written": 0, "total_bytes_read": 0, "result_set_size": 26798016, "operator_name": "HASH_JOIN", - "cpu_time": 0.17394405999999998, + "cpu_time": 0.15492330099999999, "extra_info": { "Join Type": "INNER", "Conditions": "srch_id = srch_id", @@ -50,14 +50,14 @@ "operator_cardinality": 79756, "cumulative_rows_scanned": 7586096, "operator_rows_scanned": 0, - "operator_timing": 0.026865787000000002, + "operator_timing": 0.023363864, "children": [ { "total_bytes_written": 0, "total_bytes_read": 0, "result_set_size": 35619696, "operator_name": "HASH_JOIN", - "cpu_time": 0.14224183099999999, + "cpu_time": 0.12976801899999998, "extra_info": { "Join Type": "INNER", "Conditions": "prop_id = prop_id", @@ -68,14 +68,14 @@ "operator_cardinality": 212022, "cumulative_rows_scanned": 7549075, "operator_rows_scanned": 0, - "operator_timing": 0.03631979799999999, + "operator_timing": 0.035053763, "children": [ { "total_bytes_written": 0, "total_bytes_read": 0, "result_set_size": 21772608, "operator_name": "SEQ_SCAN ", - "cpu_time": 0.104767166, + "cpu_time": 0.091947722, "extra_info": { "Table": "Expedia_S_listings_extension2", "Type": "Sequential Scan", @@ -101,7 +101,7 @@ "operator_cardinality": 247416, "cumulative_rows_scanned": 7537136, "operator_rows_scanned": 7537136, - "operator_timing": 0.104767166, + "operator_timing": 0.091947722, "children": [] }, { @@ -109,7 +109,7 @@ "total_bytes_read": 0, "result_set_size": 688320, "operator_name": "SEQ_SCAN ", - "cpu_time": 0.0011548670000000002, + "cpu_time": 0.0027665339999999997, "extra_info": { "Table": "Expedia_R1_hotels2", "Type": "Sequential Scan", @@ -132,7 +132,7 @@ "operator_cardinality": 7170, "cumulative_rows_scanned": 11939, "operator_rows_scanned": 11939, - "operator_timing": 0.0011548670000000002, + "operator_timing": 0.0027665339999999997, "children": [] } ] @@ -142,7 +142,7 @@ "total_bytes_read": 0, "result_set_size": 2033568, "operator_name": "SEQ_SCAN ", - "cpu_time": 0.004836442, + "cpu_time": 0.0017914180000000001, "extra_info": { "Table": "Expedia_R2_searches", "Type": "Sequential Scan", @@ -174,7 +174,7 @@ "operator_cardinality": 11052, "cumulative_rows_scanned": 37021, "operator_rows_scanned": 37021, - "operator_timing": 0.004836442, + "operator_timing": 0.0017914180000000001, "children": [] } ] diff --git a/src/include/optimization/feature_extraction/query2vec/query_feature_extraction.hpp b/src/include/optimization/feature_extraction/query2vec/query_feature_extraction.hpp index 8040306..737f0c6 100644 --- a/src/include/optimization/feature_extraction/query2vec/query_feature_extraction.hpp +++ b/src/include/optimization/feature_extraction/query2vec/query_feature_extraction.hpp @@ -7,6 +7,7 @@ namespace duckdb{ std::string get_filters_feature_extract(const AnnotatedPlanNode &node); std::string get_table_feature_extract(const AnnotatedPlanNode &node); std::string aggregate_feature_extract(const AnnotatedPlanNode &node); + std::string join_features_extract(const AnnotatedPlanNode &node); void traverse_and_extract(const AnnotatedPlanNode &node); diff --git a/src/optimization/feature_extraction/query2vec/query_feature_extraction.cpp b/src/optimization/feature_extraction/query2vec/query_feature_extraction.cpp index ed089ec..453d12c 100644 --- a/src/optimization/feature_extraction/query2vec/query_feature_extraction.cpp +++ b/src/optimization/feature_extraction/query2vec/query_feature_extraction.cpp @@ -7,6 +7,7 @@ #include "duckdb/planner/expression/bound_comparison_expression.hpp" #include "duckdb/planner/expression/bound_between_expression.hpp" #include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/planner/operator/logical_join.hpp" #include "duckdb/common/enums/expression_type.hpp" #include "optimization/feature_extraction/query2vec/query_annotation.hpp" @@ -21,22 +22,28 @@ namespace duckdb{ std::cout << "Extracting features from PROJECTION node ID: " << node.node_id << "\n"; } break; + case LogicalOperatorType::LOGICAL_FILTER : { std::string ffe = filter_feature_extract(node); std::cout << "Extracting features from FILTER node ID: " << node.node_id << "\n"; } break; + case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY : { std::string afe = aggregate_feature_extract(node); std::cout << "Extracting features from AGGREGATE node ID: " << node.node_id << "\n"; } break; + case LogicalOperatorType::LOGICAL_JOIN : case LogicalOperatorType::LOGICAL_COMPARISON_JOIN : case LogicalOperatorType::LOGICAL_ANY_JOIN : { + std::string jfe = join_features_extract(node); std::cout << "Extracting features from JOIN node ID: " << node.node_id << "\n"; + std::cout << " Join Features: " << jfe << "\n"; } break; + case LogicalOperatorType::LOGICAL_GET : { std::string gffe = get_filters_feature_extract(node); std::string gtfe = get_table_feature_extract(node); @@ -120,8 +127,11 @@ namespace duckdb{ std::string get_table_feature_extract(const AnnotatedPlanNode &node){ - // Placeholder implementation - return "get_table_features"; + auto &get = node.plan_node->Cast(); + idx_t rows = get.estimated_cardinality; // DuckDB keeps this updated + if (rows == DConstants::INVALID_INDEX) rows = 0; + idx_t cols = get.types.size(); + return "Rows:" + std::to_string(rows) + ",Cols:" + std::to_string(cols); } std::string aggregate_feature_extract(const AnnotatedPlanNode &node){ @@ -129,6 +139,14 @@ namespace duckdb{ return "aggregate_features"; } + std::string join_features_extract(const AnnotatedPlanNode &node){ + // Placeholder implementation + const auto &lj = node.plan_node->Cast(); + JoinType jt = lj.join_type; + std::string jt_str = EnumUtil::ToString(jt); + return jt_str; + } + void traverse_and_extract(const AnnotatedPlanNode &node){ extract_features(node); for (const auto &child : node.children) { From 6925710d47a7ae7e0e951fef5b4219491ba01428 Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 19 Nov 2025 15:05:10 -0700 Subject: [PATCH 11/18] torch udfs and rewrite rules --- .gitignore | 1 + CMakeLists.txt | 9 +- expedia.json | 32 +- queries/expedia_query.sql | 2 +- queries/forest_query.sql | 30 + queries/q1.sql | 24 + src/include/ml_functions/decision_forest.hpp | 78 ++ src/include/ml_functions/decision_tree.hpp | 88 ++ .../ml_functions/ml_decision_forest_table.hpp | 73 ++ src/include/ml_functions/torch_dnn.hpp | 91 +++ ...ecisionForestUDF2RelationRewriteAction.hpp | 27 + .../MultiLayerUDF2TorchNNRewriteAction.hpp | 18 + src/ml_functions/CMakeLists.txt | 3 + src/ml_functions/decision_forest.cpp | 268 +++++++ src/ml_functions/decision_tree.cpp | 758 ++++++++---------- src/ml_functions/ml_decision_forest_table.cpp | 135 ++++ src/ml_functions/ml_functions_scalar.cpp | 8 +- src/ml_functions/torch_dnn.cpp | 459 +++++++++++ src/optimization/CMakeLists.txt | 2 + ...ecisionForestUDF2RelationRewriteAction.cpp | 436 ++++++++++ .../MultiLayerUDF2TorchNNRewriteAction.cpp | 371 +++++++++ src/optimization/dynamic_optimizer.cpp | 38 +- src/optimization/register_optimizers.cpp | 2 +- test/sql/decision_forest.test | 25 + test/sql/nn_test.test | 114 +++ test/sql/torch.test | 79 ++ 26 files changed, 2728 insertions(+), 443 deletions(-) create mode 100644 queries/forest_query.sql create mode 100644 queries/q1.sql create mode 100644 src/include/ml_functions/decision_forest.hpp create mode 100644 src/include/ml_functions/decision_tree.hpp create mode 100644 src/include/ml_functions/ml_decision_forest_table.hpp create mode 100644 src/include/ml_functions/torch_dnn.hpp create mode 100644 src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp create mode 100644 src/include/optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp create mode 100644 src/ml_functions/decision_forest.cpp create mode 100644 src/ml_functions/ml_decision_forest_table.cpp create mode 100644 src/ml_functions/torch_dnn.cpp create mode 100644 src/optimization/actions/DecisionForestUDF2RelationRewriteAction.cpp create mode 100644 src/optimization/actions/MultiLayerUDF2TorchNNRewriteAction.cpp create mode 100644 test/sql/decision_forest.test create mode 100644 test/sql/nn_test.test create mode 100644 test/sql/torch.test diff --git a/.gitignore b/.gitignore index 3c620aa..a32763e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ duckdb/ temp_dir/ mydb.duckdb plans/ +*.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f24ba3..40b1708 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,12 @@ set(TARGET_NAME cactusdb) # used in cmake with find_package. Feel free to remove or replace with other dependencies. # Note that it should also be removed from vcpkg.json to prevent needlessly installing it.. + + find_package(OpenSSL REQUIRED) find_package(Eigen3 REQUIRED) +set(Torch_DIR "/home/local/ASUAD/jrtandel/libtorch/share/cmake/Torch") +find_package(Torch REQUIRED) set(EXTENSION_NAME ${TARGET_NAME}_extension) @@ -19,6 +23,7 @@ set(LOADABLE_EXTENSION_NAME ${TARGET_NAME}_loadable_extension) project(${TARGET_NAME}) include_directories(src/include) include_directories(${EIGEN3_INCLUDE_DIR}) +include_directories(${TORCH_INCLUDE_DIRS}) set(EXTENSION_SOURCES src/cactusdb_extension.cpp) add_subdirectory(src/ml_functions) @@ -31,8 +36,8 @@ build_static_extension(${TARGET_NAME} ${EXTENSION_SOURCES}) build_loadable_extension(${TARGET_NAME} " " ${EXTENSION_SOURCES}) # Link OpenSSL in both the static library as the loadable extension -target_link_libraries(${EXTENSION_NAME} OpenSSL::SSL OpenSSL::Crypto Eigen3::Eigen) -target_link_libraries(${LOADABLE_EXTENSION_NAME} OpenSSL::SSL OpenSSL::Crypto Eigen3::Eigen) +target_link_libraries(${EXTENSION_NAME} OpenSSL::SSL OpenSSL::Crypto Eigen3::Eigen ${TORCH_LIBRARIES}) +target_link_libraries(${LOADABLE_EXTENSION_NAME} OpenSSL::SSL OpenSSL::Crypto Eigen3::Eigen ${TORCH_LIBRARIES}) install( TARGETS ${EXTENSION_NAME} diff --git a/expedia.json b/expedia.json index a6b42a0..cce837e 100644 --- a/expedia.json +++ b/expedia.json @@ -2,13 +2,13 @@ "total_bytes_written": 0, "total_bytes_read": 0, "rows_returned": 79756, - "latency": 0.666635768, + "latency": 0.619100106, "result_set_size": 2871216, - "query_name": "SELECT\n s.prop_id,\n s.srch_id,\n tree_predict(\n list_transform(\n list_concat(\n /* 1) NUMERICALS — per-column scaling (exact order) */\n min_max_scaler(list_value(CAST(s.prop_location_score1 AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score1.txt'),\n min_max_scaler(list_value(CAST(s.prop_location_score2 AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score2.txt'),\n min_max_scaler(list_value(CAST(s.prop_log_historical_price AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_log_historical_price.txt'),\n min_max_scaler(list_value(CAST(s.price_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/price_usd.txt'),\n min_max_scaler(list_value(CAST(s.orig_destination_distance AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/orig_destination_distance.txt'),\n min_max_scaler(list_value(CAST(h.prop_review_score AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_review_score.txt'),\n min_max_scaler(list_value(CAST(h.avg_bookings_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/avg_bookings_usd.txt'),\n min_max_scaler(list_value(CAST(h.stdev_bookings_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/stdev_bookings_usd.txt'),\n\n /* 2) CATEGORICALS — one-hot, exact order of your Python */\n -- stringEncoderSpecs (string→int): TRUE\n one_hot_encode(CAST(s.position AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/position.csv', TRUE),\n one_hot_encode(CAST(h.prop_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_country_id.csv', TRUE),\n\n -- encoderSpecs (int→int): FALSE\n one_hot_encode(CAST(h.prop_starrating AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_starrating.csv', FALSE),\n one_hot_encode(CAST(h.prop_brand_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_brand_bool.csv', FALSE),\n one_hot_encode(CAST(h.count_clicks AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_clicks.csv', FALSE),\n one_hot_encode(CAST(h.count_bookings AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_bookings.csv', FALSE),\n\n -- stringEncoderSpecs (string→int): TRUE\n one_hot_encode(CAST(r.year AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/year.csv', TRUE),\n one_hot_encode(CAST(r.month AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/month.csv', TRUE),\n one_hot_encode(CAST(r.weekofyear AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/weekofyear.csv', TRUE),\n one_hot_encode(CAST(r.time AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/time.csv', TRUE),\n one_hot_encode(CAST(r.site_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/site_id.csv', TRUE),\n one_hot_encode(CAST(r.visitor_location_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/visitor_location_country_id.csv', TRUE),\n one_hot_encode(CAST(r.srch_destination_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_destination_id.csv', TRUE),\n\n -- encoderSpecs (int→int): FALSE\n one_hot_encode(CAST(r.srch_length_of_stay AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_length_of_stay.csv', FALSE),\n one_hot_encode(CAST(r.srch_booking_window AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_booking_window.csv', FALSE),\n one_hot_encode(CAST(r.srch_adults_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_adults_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_children_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_children_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_room_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_room_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_saturday_night_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_saturday_night_bool.csv', FALSE),\n one_hot_encode(CAST(r.random_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/random_bool.csv', FALSE)\n ),\n x -> CAST(x AS FLOAT) -- tree_predict expects LIST\n ),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/tree/0.txt',\n FALSE\n ) AS prediction\nFROM Expedia_S_listings_extension2 AS s\nJOIN Expedia_R1_hotels2 AS h ON s.prop_id = h.prop_id\nJOIN Expedia_R2_searches AS r ON s.srch_id = r.srch_id\nWHERE s.prop_location_score1 > 1\n AND s.prop_location_score2 > 0.1\n AND s.prop_log_historical_price > 4\n AND h.count_bookings > 5\n AND r.srch_booking_window > 10\n AND r.srch_length_of_stay > 1;", + "query_name": "SELECT\n s.prop_id,\n s.srch_id,\n tree_predict(\n list_transform(\n list_concat(\n /* 1) NUMERICALS — per-column scaling (exact order) */\n min_max_scaler(list_value(CAST(s.prop_location_score1 AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score1.txt'),\n min_max_scaler(list_value(CAST(s.prop_location_score2 AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score2.txt'),\n min_max_scaler(list_value(CAST(s.prop_log_historical_price AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_log_historical_price.txt'),\n min_max_scaler(list_value(CAST(s.price_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/price_usd.txt'),\n min_max_scaler(list_value(CAST(s.orig_destination_distance AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/orig_destination_distance.txt'),\n min_max_scaler(list_value(CAST(h.prop_review_score AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_review_score.txt'),\n min_max_scaler(list_value(CAST(h.avg_bookings_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/avg_bookings_usd.txt'),\n min_max_scaler(list_value(CAST(h.stdev_bookings_usd AS DOUBLE)),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/stdev_bookings_usd.txt'),\n\n /* 2) CATEGORICALS — one-hot, exact order of your Python */\n -- stringEncoderSpecs (string→int): TRUE\n one_hot_encode(CAST(s.position AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/position.csv', TRUE),\n one_hot_encode(CAST(h.prop_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_country_id.csv', TRUE),\n\n -- encoderSpecs (int→int): FALSE\n one_hot_encode(CAST(h.prop_starrating AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_starrating.csv', FALSE),\n one_hot_encode(CAST(h.prop_brand_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_brand_bool.csv', FALSE),\n one_hot_encode(CAST(h.count_clicks AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_clicks.csv', FALSE),\n one_hot_encode(CAST(h.count_bookings AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_bookings.csv', FALSE),\n\n -- stringEncoderSpecs (string→int): TRUE\n one_hot_encode(CAST(r.year AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/year.csv', TRUE),\n one_hot_encode(CAST(r.month AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/month.csv', TRUE),\n one_hot_encode(CAST(r.weekofyear AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/weekofyear.csv', TRUE),\n one_hot_encode(CAST(r.time AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/time.csv', TRUE),\n one_hot_encode(CAST(r.site_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/site_id.csv', TRUE),\n one_hot_encode(CAST(r.visitor_location_country_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/visitor_location_country_id.csv', TRUE),\n one_hot_encode(CAST(r.srch_destination_id AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_destination_id.csv', TRUE),\n\n -- encoderSpecs (int→int): FALSE\n one_hot_encode(CAST(r.srch_length_of_stay AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_length_of_stay.csv', FALSE),\n one_hot_encode(CAST(r.srch_booking_window AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_booking_window.csv', FALSE),\n one_hot_encode(CAST(r.srch_adults_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_adults_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_children_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_children_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_room_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_room_count.csv', FALSE),\n one_hot_encode(CAST(r.srch_saturday_night_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_saturday_night_bool.csv', FALSE),\n one_hot_encode(CAST(r.random_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/random_bool.csv', FALSE)\n ),\n x -> CAST(x AS FLOAT) -- tree_predict expects LIST\n ),\n '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/tree/0.txt',\n FALSE\n )\nFROM Expedia_S_listings_extension2 AS s\nJOIN Expedia_R1_hotels2 AS h ON s.prop_id = h.prop_id\nJOIN Expedia_R2_searches AS r ON s.srch_id = r.srch_id\nWHERE s.prop_location_score1 > 1\n AND s.prop_location_score2 > 0.1\n AND s.prop_log_historical_price > 4\n AND h.count_bookings > 5\n AND r.srch_booking_window > 10\n AND r.srch_length_of_stay > 1;", "blocked_thread_time": 0.0, "system_peak_buffer_memory": 41269248, "system_peak_temp_dir_size": 0, - "cpu_time": 4.4477316799999995, + "cpu_time": 4.15678951, "extra_info": {}, "cumulative_cardinality": 637172, "cumulative_rows_scanned": 7586096, @@ -18,12 +18,12 @@ "total_bytes_read": 0, "result_set_size": 2871216, "operator_name": "PROJECTION", - "cpu_time": 4.4477316799999995, + "cpu_time": 4.15678951, "extra_info": { "Projections": [ "prop_id", "srch_id", - "prediction" + "tree_predict(list_transform(list_concat(min_max_scaler(list_value(prop_location_score1), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score1.txt'), min_max_scaler(list_value(prop_location_score2), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_location_score2.txt'), min_max_scaler(list_value(prop_log_historical_price), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_log_historical_price.txt'), min_max_scaler(list_value(price_usd), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/price_usd.txt'), min_max_scaler(list_value(orig_destination_distance), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/orig_destination_distance.txt'), min_max_scaler(list_value(CAST(prop_review_score AS DOUBLE)), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/prop_review_score.txt'), min_max_scaler(list_value(avg_bookings_usd), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/avg_bookings_usd.txt'), min_max_scaler(list_value(stdev_bookings_usd), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/scaler_files/stdev_bookings_usd.txt'), one_hot_encode(position, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/position.csv', true), one_hot_encode(prop_country_id, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_country_id.csv', true), one_hot_encode(CAST(prop_starrating AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_starrating.csv', false), one_hot_encode(CAST(prop_brand_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/prop_brand_bool.csv', false), one_hot_encode(CAST(count_clicks AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_clicks.csv', false), one_hot_encode(CAST(count_bookings AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/count_bookings.csv', false), one_hot_encode(year, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/year.csv', true), one_hot_encode(month, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/month.csv', true), one_hot_encode(weekofyear, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/weekofyear.csv', true), one_hot_encode(time, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/time.csv', true), one_hot_encode(site_id, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/site_id.csv', true), one_hot_encode(visitor_location_country_id, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/visitor_location_country_id.csv', true), one_hot_encode(srch_destination_id, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_destination_id.csv', true), one_hot_encode(CAST(srch_length_of_stay AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_length_of_stay.csv', false), one_hot_encode(CAST(srch_booking_window AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_booking_window.csv', false), one_hot_encode(CAST(srch_adults_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_adults_count.csv', false), one_hot_encode(CAST(srch_children_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_children_count.csv', false), one_hot_encode(CAST(srch_room_count AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_room_count.csv', false), one_hot_encode(CAST(srch_saturday_night_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/srch_saturday_night_bool.csv', false), one_hot_encode(CAST(random_bool AS VARCHAR), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/onehotencoders/random_bool.csv', false))), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/tree/0.txt', false)" ], "Estimated Cardinality": "7220" }, @@ -32,14 +32,14 @@ "operator_cardinality": 79756, "cumulative_rows_scanned": 7586096, "operator_rows_scanned": 0, - "operator_timing": 4.292808378999999, + "operator_timing": 3.9706238020000004, "children": [ { "total_bytes_written": 0, "total_bytes_read": 0, "result_set_size": 26798016, "operator_name": "HASH_JOIN", - "cpu_time": 0.15492330099999999, + "cpu_time": 0.18616570799999999, "extra_info": { "Join Type": "INNER", "Conditions": "srch_id = srch_id", @@ -50,14 +50,14 @@ "operator_cardinality": 79756, "cumulative_rows_scanned": 7586096, "operator_rows_scanned": 0, - "operator_timing": 0.023363864, + "operator_timing": 0.027968030999999997, "children": [ { "total_bytes_written": 0, "total_bytes_read": 0, "result_set_size": 35619696, "operator_name": "HASH_JOIN", - "cpu_time": 0.12976801899999998, + "cpu_time": 0.153371983, "extra_info": { "Join Type": "INNER", "Conditions": "prop_id = prop_id", @@ -68,14 +68,14 @@ "operator_cardinality": 212022, "cumulative_rows_scanned": 7549075, "operator_rows_scanned": 0, - "operator_timing": 0.035053763, + "operator_timing": 0.040581439999999996, "children": [ { "total_bytes_written": 0, "total_bytes_read": 0, "result_set_size": 21772608, "operator_name": "SEQ_SCAN ", - "cpu_time": 0.091947722, + "cpu_time": 0.11156367, "extra_info": { "Table": "Expedia_S_listings_extension2", "Type": "Sequential Scan", @@ -101,7 +101,7 @@ "operator_cardinality": 247416, "cumulative_rows_scanned": 7537136, "operator_rows_scanned": 7537136, - "operator_timing": 0.091947722, + "operator_timing": 0.11156367, "children": [] }, { @@ -109,7 +109,7 @@ "total_bytes_read": 0, "result_set_size": 688320, "operator_name": "SEQ_SCAN ", - "cpu_time": 0.0027665339999999997, + "cpu_time": 0.0012268730000000003, "extra_info": { "Table": "Expedia_R1_hotels2", "Type": "Sequential Scan", @@ -132,7 +132,7 @@ "operator_cardinality": 7170, "cumulative_rows_scanned": 11939, "operator_rows_scanned": 11939, - "operator_timing": 0.0027665339999999997, + "operator_timing": 0.0012268730000000003, "children": [] } ] @@ -142,7 +142,7 @@ "total_bytes_read": 0, "result_set_size": 2033568, "operator_name": "SEQ_SCAN ", - "cpu_time": 0.0017914180000000001, + "cpu_time": 0.004825693999999999, "extra_info": { "Table": "Expedia_R2_searches", "Type": "Sequential Scan", @@ -174,7 +174,7 @@ "operator_cardinality": 11052, "cumulative_rows_scanned": 37021, "operator_rows_scanned": 37021, - "operator_timing": 0.0017914180000000001, + "operator_timing": 0.004825693999999999, "children": [] } ] diff --git a/queries/expedia_query.sql b/queries/expedia_query.sql index e3bff95..0918b3c 100644 --- a/queries/expedia_query.sql +++ b/queries/expedia_query.sql @@ -78,7 +78,7 @@ SELECT ), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/expedia/tree/0.txt', FALSE - ) AS prediction + ) FROM Expedia_S_listings_extension2 AS s JOIN Expedia_R1_hotels2 AS h ON s.prop_id = h.prop_id JOIN Expedia_R2_searches AS r ON s.srch_id = r.srch_id diff --git a/queries/forest_query.sql b/queries/forest_query.sql new file mode 100644 index 0000000..e3cee32 --- /dev/null +++ b/queries/forest_query.sql @@ -0,0 +1,30 @@ +-- queries/test_decision_forest.sql + + + +Load cactusdb; + +-- Build 3 rows of 6756-dimensional feature vectors +WITH feature_rows AS ( + SELECT + id, + list(CAST(i AS FLOAT)) AS features + FROM ( + -- three ids + SELECT * FROM (VALUES (1), (2), (3)) AS ids(id), + -- 0 .. 6755 + range(0, 6756) AS r(i) + ) + GROUP BY id +) +SELECT + id, + features, + decision_forest_predict( + features, + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/flights/rf_dot_trees_custom', + 6756, + TRUE + ) AS pred +FROM feature_rows +ORDER BY id; diff --git a/queries/q1.sql b/queries/q1.sql new file mode 100644 index 0000000..217b128 --- /dev/null +++ b/queries/q1.sql @@ -0,0 +1,24 @@ +-- q1.sql + +LOAD cactusdb; + +-- create the inputs table +CREATE TABLE inputs( + id INTEGER, + a DOUBLE[] +); + +-- data +INSERT INTO inputs VALUES + (1, [2.0, 1.0]), + (2, [1.0, 3.0]), + (3, [5.0, 5.0]); + +-- run the NN pipeline +SELECT + mat_add( + mat_mul(a, 'w_nn.csv', 'dense'), + 'b_zero.csv' + ) , id +FROM inputs +ORDER BY id; diff --git a/src/include/ml_functions/decision_forest.hpp b/src/include/ml_functions/decision_forest.hpp new file mode 100644 index 0000000..361d7c6 --- /dev/null +++ b/src/include/ml_functions/decision_forest.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include "duckdb.hpp" +#include "duckdb/function/function.hpp" +#include "ml_functions/decision_tree.hpp" + +#include +#include +#include + +namespace duckdb { + +struct ML_DecisionForest { + // Max number of trees (same spirit as Velox code) + static constexpr idx_t MAX_NUM_TREES = 1600; + + // ------------------------- + // Forest implementation + // ------------------------- + class Forest { + public: + // We reuse your Tree implementation from ML_DecisionTree + std::vector trees; + bool is_classification; + + Forest() : is_classification(false) { + } + + Forest(const std::string &folder_path, bool is_cls); + + // Build forest from a folder of .dot tree files + void ConstructFromFolder(const std::string &folder_path); + + // For explicit list of tree paths (if ever needed) + void ConstructFromPaths(const std::vector &tree_paths); + + // Predict for a single row (features is a pointer to length num_features) + float PredictRow(const float *row_base, idx_t num_features) const; + }; + + using ForestPtr = std::shared_ptr; + + // ------------------------- + // Bind data + // ------------------------- + struct BindData final : public FunctionData { + ForestPtr forest; + idx_t num_features; + std::string forest_path; + bool is_classification; + + BindData(); + BindData(const ForestPtr &f, + idx_t num_features_p, + const std::string &forest_path_p, + bool is_classification_p); + + unique_ptr Copy() const override; + bool Equals(const FunctionData &other_p) const override; + }; + + // ------------------------- + // Scalar function hooks + // ------------------------- + static unique_ptr Bind( + ClientContext &context, + ScalarFunction &bound_function, + vector> &args); + + static void Execute( + DataChunk &args, + ExpressionState &state, + Vector &result); + + static void Register(ExtensionLoader &loader); +}; + +} // namespace duckdb diff --git a/src/include/ml_functions/decision_tree.hpp b/src/include/ml_functions/decision_tree.hpp new file mode 100644 index 0000000..b7e1c63 --- /dev/null +++ b/src/include/ml_functions/decision_tree.hpp @@ -0,0 +1,88 @@ +#pragma once + +#include "duckdb.hpp" +#include "duckdb/function/function.hpp" + +#include +#include +#include + +namespace duckdb { + +struct ML_DecisionTree { + // ------------------------- + // Constants & basic types + // ------------------------- + static constexpr idx_t MAX_NUM_NODES_PER_TREE = 512; + + struct Node { + union { + float threshold; + float leafValue; + }; + int indexID; + int leftChild; + int rightChild; + bool isLeaf; + bool isMissTrackLeft; // When feature value is missing, whether to traverse left + }; + + // ------------------------- + // Tree implementation + // ------------------------- + class Tree { + public: + Node tree[MAX_NUM_NODES_PER_TREE]; + int treeId; + + Tree(); + Tree(int id, const std::string &tree_path); + + static void constructTreeFromPath(const std::string &tree_path_in, Node *tree); + static void constructTreeFromPathHelper( + const std::string &tree_path_in, + std::vector &relationships, + std::vector &innerNodes, + std::vector &leafNodes); + + static void processInnerNodes(std::vector &innerNodes, Node *tree); + static void processLeafNodes(std::vector &leafNodes, Node *tree); + static void processRelationships(std::vector &relationships, Node *tree); + + float predictSingle(const float *row_base) const; + float predictSingleMissing(const float *row_base) const; + }; + + using TreePtr = std::shared_ptr; + + // ------------------------- + // Bind data + // ------------------------- + struct BindData final : public FunctionData { + TreePtr tree; + bool has_missing; + + BindData(); + BindData(const TreePtr &t, bool hm); + + unique_ptr Copy() const override; + bool Equals(const FunctionData &other_p) const override; + }; + + // ------------------------- + // Scalar function hooks + // ------------------------- + static unique_ptr Bind( + ClientContext &context, + ScalarFunction &bound_function, + vector> &args); + + static void Execute( + DataChunk &args, + ExpressionState &state, + Vector &result); + + static void Register(ExtensionLoader &loader); +}; + +} // namespace duckdb diff --git a/src/include/ml_functions/ml_decision_forest_table.hpp b/src/include/ml_functions/ml_decision_forest_table.hpp new file mode 100644 index 0000000..a24f0c0 --- /dev/null +++ b/src/include/ml_functions/ml_decision_forest_table.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "duckdb.hpp" +#include "duckdb/function/table_function.hpp" +#include "duckdb/common/vector.hpp" + +#include +#include + +namespace duckdb { + +struct ML_ForestTable { + // ------------------------- + // Global scan state + // ------------------------- + struct GlobalState : public GlobalTableFunctionState { + vector tree_paths; + idx_t current_row; + idx_t total_rows; + + GlobalState() : current_row(0), total_rows(0) { + } + + idx_t MaxThreads() const override { + // Single threaded scan is fine for this helper + return 1; + } + }; + + // ------------------------- + // Bind data + // ------------------------- + struct BindData final : public FunctionData { + std::string forest_path; + vector tree_paths; + + BindData() = default; + BindData(std::string forest_path_p, vector tree_paths_p) + : forest_path(std::move(forest_path_p)), tree_paths(std::move(tree_paths_p)) { + } + + unique_ptr Copy() const override { + return make_uniq(forest_path, tree_paths); + } + + bool Equals(const FunctionData &other_p) const override { + auto &o = other_p.Cast(); + return forest_path == o.forest_path && tree_paths == o.tree_paths; + } + }; + + // ------------------------- + // Hook signatures + // ------------------------- + static unique_ptr Bind( + ClientContext &context, + TableFunctionBindInput &input, + duckdb::vector &return_types, + duckdb::vector &names); + + static unique_ptr InitGlobal( + ClientContext &context, + TableFunctionInitInput &input); + + static void Function( + ClientContext &context, + TableFunctionInput &data, + DataChunk &output); + + static void Register(ExtensionLoader &loader); +}; + +} // namespace duckdb diff --git a/src/include/ml_functions/torch_dnn.hpp b/src/include/ml_functions/torch_dnn.hpp new file mode 100644 index 0000000..dc7af54 --- /dev/null +++ b/src/include/ml_functions/torch_dnn.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include "duckdb.hpp" +#include "duckdb/function/function.hpp" + +// libtorch +#include + +#include +#include +#include + +namespace duckdb { + +struct ML_TorchDNN { + // Must match what the .cpp expects + enum class KernelType { + MatMul, + MatAdd, + BatchNorm, + ReLU, + Sigmoid, + Softmax, + Argmax + }; + + struct BindData final : public FunctionData { + // Fully materialized model (ModuleHolder) + torch::nn::Sequential model; + // dims[0] = input_dim, dims.back() = output_dim + std::vector dims; + bool has_argmax; + // Optional metadata-only field; may be empty for inline/fused cases + std::string model_file; + + BindData(torch::nn::Sequential model_p, + std::vector dims_p, + bool has_argmax_p, + std::string file = std::string()) + : model(std::move(model_p)), + dims(std::move(dims_p)), + has_argmax(has_argmax_p), + model_file(std::move(file)) { + } + + unique_ptr Copy() const override { + // torch::nn::Sequential (ModuleHolder) is copyable + return make_uniq(model, dims, has_argmax, model_file); + } + + bool Equals(const FunctionData &other_p) const override { + auto &o = other_p.Cast(); + // We do not attempt deep model-graph equality; config is enough. + return has_argmax == o.has_argmax && + dims == o.dims && + model_file == o.model_file; + } + }; + + // NOTE: For the "file-based" mode, LoadModelFromFile maps a model spec + // string to kernel_types + dims + weight_tensors. + // For fused/inline mode, a rewrite rule can skip this entirely and build + // an ML_TorchDNN::BindData directly from UDF bind_data. + static void LoadModelFromFile( + const std::string &path, + std::vector &kernel_types, + std::vector &dims, + std::vector &weight_tensors, + bool &has_argmax); + + // Default binder: expects last argument to be a constant model_file. + static unique_ptr Bind( + ClientContext &context, + ScalarFunction &bound_function, + vector> &args); + + // Execute on LIST input, returning LIST or INTEGER + // depending on has_argmax + return type. + static void Execute( + DataChunk &args, + ExpressionState &state, + Vector &result); + + // Register three overloads: + // torchdnn(LIST, model_file VARCHAR) -> LIST + // torchdnn(LIST, k INTEGER, model_file VARCHAR) -> INTEGER + // torchdnn(LIST, k BIGINT, model_file VARCHAR) -> INTEGER + static void Register(ExtensionLoader &loader); +}; + +} // namespace duckdb diff --git a/src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp b/src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp new file mode 100644 index 0000000..406a39f --- /dev/null +++ b/src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp @@ -0,0 +1,27 @@ +// src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp +#pragma once + +#include "duckdb.hpp" +#include "duckdb/optimizer/optimizer_extension.hpp" + +namespace duckdb { + +// Optimizer rewrite rule: +// +// decision_forest_predict(features, forest_path, num_features, is_classification) +// ==> CROSS_PRODUCT with per-tree table + tree_predict + AGGREGATE +// +// Current version handles only the simple case: +// * forest UDF is a top-level expression in a LogicalProjection +// * first argument (features) is a BoundReferenceExpression (plain column) +struct DecisionForestUDF2RelationRewriteAction { + // Return true if the plan *contains* a pattern we know how to rewrite + static bool check(OptimizerExtensionInput &input, + unique_ptr &plan); + + // Actually apply the rewrite in-place; return true if modified + static bool apply(OptimizerExtensionInput &input, + unique_ptr &plan); +}; + +} // namespace duckdb diff --git a/src/include/optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp b/src/include/optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp new file mode 100644 index 0000000..0e81809 --- /dev/null +++ b/src/include/optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp @@ -0,0 +1,18 @@ +// optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp +#pragma once + +#include "duckdb.hpp" + +namespace duckdb { + +struct MultiLayerUDF2TorchNNRewriteAction { + // 1) Check if this rule *could* apply on this plan (pattern exists) + static bool check(OptimizerExtensionInput &input, + unique_ptr &plan); + + // 2) Actually apply the rewrite (replace mat_add(mat_mul(...)) with torchdnn) + static bool apply(OptimizerExtensionInput &input, + unique_ptr &plan); +}; + +} // namespace duckdb diff --git a/src/ml_functions/CMakeLists.txt b/src/ml_functions/CMakeLists.txt index d5ba2f8..3d9987f 100644 --- a/src/ml_functions/CMakeLists.txt +++ b/src/ml_functions/CMakeLists.txt @@ -8,6 +8,9 @@ set(ML_FUNCTIONS_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/argmax.cpp ${CMAKE_CURRENT_SOURCE_DIR}/softmax.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sigmoid.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/torch_dnn.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/decision_forest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ml_decision_forest_table.cpp ) set(EXTENSION_SOURCES diff --git a/src/ml_functions/decision_forest.cpp b/src/ml_functions/decision_forest.cpp new file mode 100644 index 0000000..17f6f38 --- /dev/null +++ b/src/ml_functions/decision_forest.cpp @@ -0,0 +1,268 @@ +#include "ml_functions/decision_forest.hpp" + +#include "duckdb/common/exception.hpp" +#include "duckdb/common/list.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" + +#include +#include +#include +#include + +namespace duckdb { + +// ========================= +// Forest methods +// ========================= + +ML_DecisionForest::Forest::Forest(const std::string &folder_path, bool is_cls) + : is_classification(is_cls) { + ConstructFromFolder(folder_path); +} + +void ML_DecisionForest::Forest::ConstructFromFolder(const std::string &folder_path_in) { + std::filesystem::path folder(folder_path_in); + if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder)) { + throw InvalidInputException( + "decision_forest_predict: forest folder '%s' does not exist or is not a directory", + folder_path_in.c_str()); + } + + std::vector tree_paths; + tree_paths.reserve(256); + + for (auto const &entry : std::filesystem::directory_iterator(folder)) { + if (entry.is_regular_file()) { + tree_paths.push_back(entry.path().string()); + } + } + + if (tree_paths.empty()) { + throw InvalidInputException( + "decision_forest_predict: forest folder '%s' contains no tree files", + folder_path_in.c_str()); + } + + // Sort for deterministic loading order + std::sort(tree_paths.begin(), tree_paths.end()); + + ConstructFromPaths(tree_paths); +} + +void ML_DecisionForest::Forest::ConstructFromPaths(const std::vector &tree_paths) { + if (tree_paths.size() > MAX_NUM_TREES) { + throw InvalidInputException( + "decision_forest_predict: forest has %llu trees, exceeds MAX_NUM_TREES=%llu", + (unsigned long long)tree_paths.size(), + (unsigned long long)MAX_NUM_TREES); + } + + trees.clear(); + trees.reserve(tree_paths.size()); + + // Reuse ML_DecisionTree::Tree for each file + for (idx_t i = 0; i < tree_paths.size(); ++i) { + const auto &path = tree_paths[i]; + trees.emplace_back((int)i, path); + } + + // Optional logging hook if you want + // std::cout << "[DecisionForest] Loaded " << trees.size() << " trees\n"; +} + +float ML_DecisionForest::Forest::PredictRow(const float *row_base, idx_t num_features) const { + if (trees.empty()) { + return 0.0f; + } + + double accumulated = 0.0; + for (auto const &tree : trees) { + // We use the non-missing variant (Velox forest didn't handle missing explicitly) + accumulated += (double)tree.predictSingle(row_base); + } + + double avg = accumulated / (double)trees.size(); + + if (is_classification) { + return (avg > 0.0) ? 1.0f : 0.0f; + } + return static_cast(avg); +} + +// ========================= +// BindData methods +// ========================= + +ML_DecisionForest::BindData::BindData() + : num_features(0), forest_path(), is_classification(false) { +} + +ML_DecisionForest::BindData::BindData(const ForestPtr &f, + idx_t num_features_p, + const std::string &forest_path_p, + bool is_classification_p) + : forest(f), + num_features(num_features_p), + forest_path(forest_path_p), + is_classification(is_classification_p) { +} + +unique_ptr ML_DecisionForest::BindData::Copy() const { + // ForestPtr is shared_ptr; copying is cheap and safe (forest is immutable after load) + return make_uniq(forest, num_features, forest_path, is_classification); +} + +bool ML_DecisionForest::BindData::Equals(const FunctionData &other_p) const { + auto &o = other_p.Cast(); + // pointer equality is fine for forest; plus config fields + return forest.get() == o.forest.get() && + num_features == o.num_features && + forest_path == o.forest_path && + is_classification == o.is_classification; +} + +// ========================= +// Bind +// ========================= +// +// decision_forest_predict( +// features LIST(FLOAT), +// forest_folder VARCHAR, +// num_features INTEGER, +// is_classification BOOLEAN +// ) -> FLOAT +// +unique_ptr ML_DecisionForest::Bind( + ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + + if (args.size() != 4) { + throw InvalidInputException( + "decision_forest_predict expects 4 arguments: " + "features LIST(FLOAT), forest_folder VARCHAR, num_features INTEGER, is_classification BOOLEAN"); + } + + // 1) Check features type + const auto &feat_type = args[0]->return_type; + if (feat_type.id() != LogicalTypeId::LIST || + ListType::GetChildType(feat_type).id() != LogicalTypeId::FLOAT) { + throw InvalidInputException( + "decision_forest_predict: first argument must be LIST(FLOAT)"); + } + + // 2) Evaluate forest_folder, num_features, is_classification as constants + auto vForestFolder = ExpressionExecutor::EvaluateScalar(context, *args[1]); + auto vNumFeatures = ExpressionExecutor::EvaluateScalar(context, *args[2]); + auto vIsClass = ExpressionExecutor::EvaluateScalar(context, *args[3]); + + if (vForestFolder.IsNull()) { + throw InvalidInputException("decision_forest_predict: forest_folder cannot be NULL"); + } + if (vNumFeatures.IsNull()) { + throw InvalidInputException("decision_forest_predict: num_features cannot be NULL"); + } + if (vIsClass.IsNull()) { + throw InvalidInputException("decision_forest_predict: is_classification cannot be NULL"); + } + + const std::string forest_folder = vForestFolder.ToString(); + const idx_t num_features = (idx_t)vNumFeatures.GetValue(); + const bool is_classification = vIsClass.GetValue(); + + if (num_features == 0) { + throw InvalidInputException("decision_forest_predict: num_features must be > 0"); + } + + // 3) Load forest once at bind time + ForestPtr forest_ptr; + try { + forest_ptr = std::make_shared(forest_folder, is_classification); + } catch (const std::exception &e) { + throw InvalidInputException( + "decision_forest_predict: failed to load forest from '%s': %s", + forest_folder.c_str(), e.what()); + } + + return make_uniq(forest_ptr, num_features, forest_folder, is_classification); +} + +// ========================= +// Execute +// ========================= + +void ML_DecisionForest::Execute( + DataChunk &args, + ExpressionState &state, + Vector &result) { + + const idx_t count = args.size(); + if (count == 0) { + return; + } + + // Access bind data + const auto &func_expr = state.expr.Cast(); + auto &bd = func_expr.bind_info->Cast(); + const auto &forest = *bd.forest; + const idx_t num_features = bd.num_features; + + // features: LIST(FLOAT) + Vector &features_vec = args.data[0]; + auto &features_valid = FlatVector::Validity(features_vec); + auto *entries = FlatVector::GetData(features_vec); + + Vector &child = ListVector::GetEntry(features_vec); + auto &child_valid = FlatVector::Validity(child); + const float *vals = FlatVector::GetData(child); + + // Prepare result vector + result.SetVectorType(VectorType::FLAT_VECTOR); + auto out = FlatVector::GetData(result); + auto &out_valid = FlatVector::Validity(result); + + for (idx_t i = 0; i < count; ++i) { + if (!features_valid.RowIsValid(i)) { + out_valid.SetInvalid(i); + continue; + } + + const auto ent = entries[i]; + if (ent.length != num_features) { + throw InvalidInputException( + "decision_forest_predict: row %llu feature length %llu != num_features %llu", + (unsigned long long)i, + (unsigned long long)ent.length, + (unsigned long long)num_features); + } + + const float *row_base = vals + ent.offset; + + // (Velox forest didn’t implement explicit missing handling; we do the same here) + float pred = forest.PredictRow(row_base, num_features); + out[i] = pred; + } +} + +// ========================= +// Register +// ========================= + +void ML_DecisionForest::Register(ExtensionLoader &loader) { + ScalarFunction fn( + "decision_forest_predict", + { + LogicalType::LIST(LogicalType::FLOAT), // features + LogicalType::VARCHAR, // forest folder path + LogicalType::INTEGER, // num_features + LogicalType::BOOLEAN // is_classification + }, + LogicalType::FLOAT, // prediction + Execute); + + fn.bind = Bind; + loader.RegisterFunction(fn); +} + +} // namespace duckdb diff --git a/src/ml_functions/decision_tree.cpp b/src/ml_functions/decision_tree.cpp index 058e314..fb8ee3d 100644 --- a/src/ml_functions/decision_tree.cpp +++ b/src/ml_functions/decision_tree.cpp @@ -1,410 +1,354 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "duckdb.hpp" -#include "functions.hpp" -#include "duckdb/function/function.hpp" +#include "ml_functions/decision_tree.hpp" + +#include "duckdb/common/exception.hpp" +#include "duckdb/common/list.hpp" #include "duckdb/execution/expression_executor.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" -namespace duckdb{ - struct ML_DecisionTree{ - #define MAX_NUM_NODES_PER_TREE 512 - class Tree; - typedef std::shared_ptr TreePtr; - - // Definition of Node (tree node) in our decision forest implementation - - typedef struct { - // returnClass will be the vaule to compare while this is not a leaf node - union { - float threshold; - float leafValue; - }; - int indexID; - int leftChild; - int rightChild; - bool isLeaf; - // When feature value is missing, whether track/traverseTo the left node - bool isMissTrackLeft; - } Node; - - // Implementation of Tree - class Tree { - public: - // An array of tree nodes - Node tree[MAX_NUM_NODES_PER_TREE]; - - // The ID of the tree in the forest - int treeId; - - // Default constructor - Tree() {} - - // Constructor by parsing xgboost model dump - Tree(int id, std::string treePath) : treeId{id} { - this->constructTreeFromPath(treePath, this->tree); - } - - // Construct a tree from a file dumped from an xgboost model - static void constructTreeFromPath(std::string treePathIn, Node* tree) { - std::vector relationships; - std::vector innerNodes; - std::vector leafNodes; - constructTreeFromPathHelper( - treePathIn, relationships, innerNodes, leafNodes); - processInnerNodes(innerNodes, tree); - processLeafNodes(leafNodes, tree); - processRelationships(relationships, tree); - } - - // Parsing the file and categorize the lines from the file - static void constructTreeFromPathHelper( - std::string treePathIn, - std::vector& relationships, - std::vector& innerNodes, - std::vector& leafNodes) { - std::ifstream inputFile; - inputFile.open(treePathIn.data()); - assert(inputFile.is_open()); - - std::string line; - while (getline(inputFile, line)) { - if ((line.size() == 0) || (line.find("graph") != std::string::npos) || - (line.find("}") != std::string::npos)) { - } else { - if (line.find("->") != std::string::npos) { - relationships.push_back(line); - } else if (line.find("leaf") != std::string::npos) { - leafNodes.push_back(line); - } else if (line.find("label") != std::string::npos) { - innerNodes.push_back(line); - } else { - // skip the case of empty line, somehow it won't be captured by the - // first condition - } - } - } - - inputFile.close(); - } - - // Parsing the lines corresponding to tree inner nodes - static void processInnerNodes( - std::vector& innerNodes, - Node* tree) { - int findStartPosition; - int findMidPosition; - int findEndPosition; - - // Constructing inner nodes - for (int i = 0; i < innerNodes.size(); ++i) { - const std::string& currentLine = innerNodes[i]; - int nodeID; - int indexID; - float threshold; - - // To get nodeID - if ((findEndPosition = currentLine.find("[ label")) != - std::string::npos) { - nodeID = std::stoi(currentLine.substr(4, findEndPosition - 1 - 4)); - } else { - throw std::runtime_error("[ERROR] Error in extracting inner node nodeID\n"); - } - - // To get nodeIndex - if ((findStartPosition = currentLine.find("f")) != std::string::npos && - (findEndPosition = currentLine.find("<")) != std::string::npos) { - indexID = std::stoi(currentLine.substr( - findStartPosition + 1, findEndPosition - findStartPosition - 1)); - } else { - throw std::runtime_error("[Error] Error in extracting inner node indexID\n"); - } - - // To get threshold - if ((findStartPosition = currentLine.find("<")) != std::string::npos && - (findEndPosition = currentLine.find("\" ]")) != std::string::npos) { - threshold = std::stod(currentLine.substr( - findStartPosition + 1, findEndPosition - findStartPosition - 1)); - } else { - throw std::runtime_error("[ERROR] Error in extracting inner node threshold\n"); - } - tree[nodeID].isMissTrackLeft = - false; // XGBoost default is noMissing/right - - tree[nodeID].indexID = indexID; - tree[nodeID].isLeaf = false; - tree[nodeID].leftChild = -1; - tree[nodeID].rightChild = -1; - tree[nodeID].threshold = threshold; - } - } - - static void processLeafNodes( - std::vector& leafNodes, - Node* tree) { - int findStartPosition; - int findMidPosition; - int findEndPosition; - - // Constructing leaf nodes - for (int i = 0; i < leafNodes.size(); ++i) { - // Construct leaf nodes - const std::string& currentLine = leafNodes[i]; - int nodeID; - float leafValue = -1.0f; - - if ((findEndPosition = currentLine.find("[")) != std::string::npos) { - nodeID = std::stoi(currentLine.substr(4, findEndPosition - 1 - 4)); - } else { - throw std::runtime_error( "[ERROR] Error in extracting leaf node nodeID\n"); - } - - // Output Class of XGBoost always a Double/Float. ProbabilityValue for - // Classification, ResultValue for Regression - if ((findStartPosition = currentLine.find("leaf=")) != - std::string::npos && - (findEndPosition = currentLine.find("\" ]")) != std::string::npos) { - leafValue = std::stod(currentLine.substr( - findStartPosition + 5, - findEndPosition - 3 - findStartPosition - 5)); - } else { - throw std::runtime_error("Error in extracting leaf node leafValue\n"); - exit(1); - } - - tree[nodeID].indexID = -1; - tree[nodeID].isLeaf = true; - tree[nodeID].leftChild = -1; - tree[nodeID].rightChild = -1; - tree[nodeID].leafValue = leafValue; - tree[nodeID].isMissTrackLeft = true; // Doesn't matter to leave nodes - } - } - - static void processRelationships( - std::vector& relationships, - Node* tree) { - int findStartPosition; - int findMidPosition; - int findEndPosition; - - // Constructing edges - for (int i = 0; i < relationships.size(); ++i) { - // Construct Directed Edges between Nodes - const std::string& currentLine = relationships[i]; - int parentNodeID; - int childNodeID; - - if ((findMidPosition = currentLine.find("->")) != std::string::npos) { - parentNodeID = - std::stoi(currentLine.substr(4, findMidPosition - 1 - 4)); - } else { - std::cout << "Error in extracting parentNodeID\n"; - exit(1); - } - - if ((findEndPosition = currentLine.find("[")) != std::string::npos) { - childNodeID = std::stoi(currentLine.substr( - findMidPosition + 3, findEndPosition - 1 - findMidPosition - 3)); - } else { - std::cout << "Error in extracting childNodeID\n"; - exit(1); - } - - if (currentLine.find("yes, missing") != std::string::npos) { - tree[parentNodeID].isMissTrackLeft = - true; // in processInnerNodes(), default value is set to no/right - } - - if (tree[parentNodeID].leftChild == -1) { - tree[parentNodeID].leftChild = childNodeID; - } else if (tree[parentNodeID].rightChild == -1) { - tree[parentNodeID].rightChild = childNodeID; - } else { - std::cout - << "Error in parsing trees: children nodes were updated again: " - << parentNodeID << "->" << childNodeID << std::endl; - } - } - } - inline float predictSingle(const float *row_base) const { - int cur = 0; - while (!tree[cur].isLeaf) { - const int idx = tree[cur].indexID; - const float fv = row_base[idx]; - cur = (fv < tree[cur].threshold) ? tree[cur].leftChild : tree[cur].rightChild; - } - return tree[cur].leafValue; - } - - inline float predictSingleMissing(const float *row_base) const { - int cur = 0; - while (!tree[cur].isLeaf) { - const int idx = tree[cur].indexID; - const float fv = row_base[idx]; - if (std::isnan(fv)) { - cur = tree[cur].isMissTrackLeft ? tree[cur].leftChild : tree[cur].rightChild; - } else { - cur = (fv < tree[cur].threshold) ? tree[cur].leftChild : tree[cur].rightChild; - } - } - return tree[cur].leafValue; - } - }; //End of Tree - - // --------------------------------- - // Bind: build the tree once - // --------------------------------- - - // ------------------------- -// Bind Data (same shape/style) -// ------------------------- -struct BindData final : public FunctionData { - std::shared_ptr tree; - bool has_missing; - - BindData() = default; - BindData(const std::shared_ptr &t, bool hm) - : tree(t), has_missing(hm) {} - - unique_ptr Copy() const override { - // shared_ptr copy is fine (trees are immutable after load) - return make_uniq(tree, has_missing); - } - bool Equals(const FunctionData &other_p) const override { - auto &o = other_p.Cast(); - // pointer equality is sufficient; both point to the same parsed tree - return tree.get() == o.tree.get() && has_missing == o.has_missing; - } - }; - -// ------------------------- -// Bind Function (same skeleton) -// ------------------------- -static unique_ptr Bind(ClientContext &context, - ScalarFunction &bound_function, - vector> &args) { - // Expecting 3 arguments: features, tree_file, has_missing - if (args.size() != 3) { - throw InvalidInputException( - "tree_predict expects 3 arguments: features LIST(FLOAT), tree_file VARCHAR, has_missing BOOLEAN"); - } - - // Ensure first arg is LIST(FLOAT) - const auto &feat_type = args[0]->return_type; - if (feat_type.id() != LogicalTypeId::LIST || - ListType::GetChildType(feat_type).id() != LogicalTypeId::FLOAT) { - throw InvalidInputException("tree_predict: first argument must be LIST(FLOAT)"); - } - - // Evaluate constants like in your example - auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); - auto vHasMissing = ExpressionExecutor::EvaluateScalar(context, *args[2]); - - const std::string tree_path = vFile.ToString(); - const bool has_missing = vHasMissing.GetValue(); - - // Try loading/parsing once at bind time - std::shared_ptr tree_ptr; - try { - tree_ptr = std::make_shared(/*treeId=*/0, tree_path); - } catch (const std::exception &e) { - throw InvalidInputException("tree_predict: failed to load/parse tree file '%s': %s", - tree_path.c_str(), e.what()); - } - - return make_uniq(tree_ptr, has_missing); - } - - - - static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { - const idx_t count = args.size(); - - // Access bind data (holds the parsed tree) - const auto &func_expr = state.expr.Cast(); - auto &bd = func_expr.bind_info->Cast(); - const bool has_missing = bd.has_missing; - const Tree &tree = *bd.tree; - - // Input - Vector &features_vec = args.data[0]; // LIST(FLOAT) - auto *entries = FlatVector::GetData(features_vec); - auto &features_valid = FlatVector::Validity(features_vec); - - // Child holds concatenated float values for all rows - Vector &child = ListVector::GetEntry(features_vec); - const float *vals = FlatVector::GetData(child); - auto &child_valid = FlatVector::Validity(child); - - // Prepare result - result.SetVectorType(VectorType::FLAT_VECTOR); - auto out = FlatVector::GetData(result); - auto &out_valid = FlatVector::Validity(result); - - for (idx_t i = 0; i < count; ++i) { - // If the whole LIST is NULL -> output NULL - if (!features_valid.RowIsValid(i)) { - out_valid.SetInvalid(i); - continue; - } - const auto ent = entries[i]; // {offset, length} - const float *row_base = vals + ent.offset; - - // If any element is NULL and has_missing=false, we treat it as NaN only if has_missing=true. - // Here we map child nulls to NaN so the "missing" path triggers only when has_missing==true. - // Quick pass: if there are nulls and has_missing==false, they’ll be read as NaN and go right branch by threshold (std::isnan is false in plain predict). - // To properly honor missing path only when enabled, we do missing-aware predict when has_missing==true. - float pred; - if (has_missing) { - // Create a small stack buffer with NaNs for nulls so predictSingleMissing sees them - // (avoid mutating child vector). We only copy when there are nulls. - bool any_null = false; - for (idx_t k = 0; k < ent.length; ++k) { - if (!child_valid.RowIsValid(ent.offset + k)) { any_null = true; break; } - } - if (any_null) { - // Minimal scratch: copy row into a temp and fill nulls with NaN - std::vector tmp(ent.length); - for (idx_t k = 0; k < ent.length; ++k) { - tmp[k] = child_valid.RowIsValid(ent.offset + k) ? row_base[k] : std::numeric_limits::quiet_NaN(); - } - pred = tree.predictSingleMissing(tmp.data()); - } else { - pred = tree.predictSingleMissing(row_base); - } - } else { - // Fast path, no special missing handling - pred = tree.predictSingle(row_base); - } - out[i] = pred; - } - } - - // ---------------------------- - // Register - // ---------------------------- - static void Register(ExtensionLoader &loader) { - ScalarFunction fn( - "tree_predict", - { - LogicalType::LIST(LogicalType::FLOAT), // features - LogicalType::VARCHAR, // tree file path - LogicalType::BOOLEAN // has_missing - }, - LogicalType::FLOAT, // prediction - Execute - ); - fn.bind = Bind; - loader.RegisterFunction(fn); - } -}; //End of Decision Tree struct -}// end of duckdb namespace +#include +#include +#include +#include +#include + +namespace duckdb { + +// ========================= +// Tree methods +// ========================= + +ML_DecisionTree::Tree::Tree() : treeId(0) { + // nothing +} + +ML_DecisionTree::Tree::Tree(int id, const std::string &tree_path) : treeId(id) { + constructTreeFromPath(tree_path, this->tree); +} + +void ML_DecisionTree::Tree::constructTreeFromPath(const std::string &tree_path_in, Node *tree) { + std::vector relationships; + std::vector innerNodes; + std::vector leafNodes; + constructTreeFromPathHelper(tree_path_in, relationships, innerNodes, leafNodes); + processInnerNodes(innerNodes, tree); + processLeafNodes(leafNodes, tree); + processRelationships(relationships, tree); +} + +void ML_DecisionTree::Tree::constructTreeFromPathHelper( + const std::string &tree_path_in, + std::vector &relationships, + std::vector &innerNodes, + std::vector &leafNodes) { + + std::ifstream inputFile; + inputFile.open(tree_path_in.data()); + if (!inputFile.is_open()) { + throw InvalidInputException("DecisionTree: failed to open tree file '%s'", tree_path_in.c_str()); + } + + std::string line; + while (getline(inputFile, line)) { + if ((line.size() == 0) || + (line.find("graph") != std::string::npos) || + (line.find("}") != std::string::npos)) { + // skip header/footer + } else { + if (line.find("->") != std::string::npos) { + relationships.push_back(line); + } else if (line.find("leaf") != std::string::npos) { + leafNodes.push_back(line); + } else if (line.find("label") != std::string::npos) { + innerNodes.push_back(line); + } else { + // empty or irrelevant + } + } + } + + inputFile.close(); +} + +void ML_DecisionTree::Tree::processInnerNodes(std::vector &innerNodes, Node *tree) { + int findStartPosition; + int findEndPosition; + + for (idx_t i = 0; i < innerNodes.size(); ++i) { + const std::string ¤tLine = innerNodes[i]; + int nodeID; + int indexID; + float threshold; + + // nodeID + if ((findEndPosition = currentLine.find("[ label")) != std::string::npos) { + nodeID = std::stoi(currentLine.substr(4, findEndPosition - 1 - 4)); + } else { + throw std::runtime_error("[ERROR] Error in extracting inner node nodeID"); + } + + // indexID + if ((findStartPosition = currentLine.find("f")) != std::string::npos && + (findEndPosition = currentLine.find("<")) != std::string::npos) { + indexID = std::stoi( + currentLine.substr(findStartPosition + 1, findEndPosition - findStartPosition - 1)); + } else { + throw std::runtime_error("[ERROR] Error in extracting inner node indexID"); + } + + // threshold + if ((findStartPosition = currentLine.find("<")) != std::string::npos && + (findEndPosition = currentLine.find("\" ]")) != std::string::npos) { + threshold = std::stod( + currentLine.substr(findStartPosition + 1, findEndPosition - findStartPosition - 1)); + } else { + throw std::runtime_error("[ERROR] Error in extracting inner node threshold"); + } + + tree[nodeID].isMissTrackLeft = false; // XGBoost default is noMissing/right + tree[nodeID].indexID = indexID; + tree[nodeID].isLeaf = false; + tree[nodeID].leftChild = -1; + tree[nodeID].rightChild = -1; + tree[nodeID].threshold = threshold; + } +} + +void ML_DecisionTree::Tree::processLeafNodes(std::vector &leafNodes, Node *tree) { + int findStartPosition; + int findEndPosition; + + for (idx_t i = 0; i < leafNodes.size(); ++i) { + const std::string ¤tLine = leafNodes[i]; + int nodeID; + float leafValue = -1.0f; + + // nodeID + if ((findEndPosition = currentLine.find("[")) != std::string::npos) { + nodeID = std::stoi(currentLine.substr(4, findEndPosition - 1 - 4)); + } else { + throw std::runtime_error("[ERROR] Error in extracting leaf node nodeID"); + } + + // leafValue + if ((findStartPosition = currentLine.find("leaf=")) != std::string::npos && + (findEndPosition = currentLine.find("\" ]")) != std::string::npos) { + leafValue = std::stod( + currentLine.substr(findStartPosition + 5, findEndPosition - 3 - findStartPosition - 5)); + } else { + throw std::runtime_error("[ERROR] Error in extracting leaf node leafValue"); + } + + tree[nodeID].indexID = -1; + tree[nodeID].isLeaf = true; + tree[nodeID].leftChild = -1; + tree[nodeID].rightChild = -1; + tree[nodeID].leafValue = leafValue; + tree[nodeID].isMissTrackLeft = true; // doesn't matter for leaf nodes + } +} + +void ML_DecisionTree::Tree::processRelationships(std::vector &relationships, Node *tree) { + int findMidPosition; + int findEndPosition; + + for (idx_t i = 0; i < relationships.size(); ++i) { + const std::string ¤tLine = relationships[i]; + int parentNodeID; + int childNodeID; + + if ((findMidPosition = currentLine.find("->")) != std::string::npos) { + parentNodeID = std::stoi(currentLine.substr(4, findMidPosition - 1 - 4)); + } else { + throw std::runtime_error("[ERROR] Error in extracting parentNodeID"); + } + + if ((findEndPosition = currentLine.find("[")) != std::string::npos) { + childNodeID = std::stoi(currentLine.substr( + findMidPosition + 3, findEndPosition - 1 - findMidPosition - 3)); + } else { + throw std::runtime_error("[ERROR] Error in extracting childNodeID"); + } + + if (currentLine.find("yes, missing") != std::string::npos) { + tree[parentNodeID].isMissTrackLeft = true; + } + + if (tree[parentNodeID].leftChild == -1) { + tree[parentNodeID].leftChild = childNodeID; + } else if (tree[parentNodeID].rightChild == -1) { + tree[parentNodeID].rightChild = childNodeID; + } else { + throw std::runtime_error("[ERROR] children nodes were updated again"); + } + } +} + +float ML_DecisionTree::Tree::predictSingle(const float *row_base) const { + int cur = 0; + while (!tree[cur].isLeaf) { + const int idx = tree[cur].indexID; + const float fv = row_base[idx]; + cur = (fv < tree[cur].threshold) ? tree[cur].leftChild : tree[cur].rightChild; + } + return tree[cur].leafValue; +} + +float ML_DecisionTree::Tree::predictSingleMissing(const float *row_base) const { + int cur = 0; + while (!tree[cur].isLeaf) { + const int idx = tree[cur].indexID; + const float fv = row_base[idx]; + if (std::isnan(fv)) { + cur = tree[cur].isMissTrackLeft ? tree[cur].leftChild : tree[cur].rightChild; + } else { + cur = (fv < tree[cur].threshold) ? tree[cur].leftChild : tree[cur].rightChild; + } + } + return tree[cur].leafValue; +} + +// ========================= +// BindData methods +// ========================= + +ML_DecisionTree::BindData::BindData() : has_missing(false) { +} + +ML_DecisionTree::BindData::BindData(const TreePtr &t, bool hm) + : tree(t), has_missing(hm) { +} + +unique_ptr ML_DecisionTree::BindData::Copy() const { + return make_uniq(tree, has_missing); +} + +bool ML_DecisionTree::BindData::Equals(const FunctionData &other_p) const { + auto &o = other_p.Cast(); + return tree.get() == o.tree.get() && has_missing == o.has_missing; +} + +// ========================= +// Bind +// ========================= + +unique_ptr ML_DecisionTree::Bind( + ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + + if (args.size() != 3) { + throw InvalidInputException( + "tree_predict expects 3 arguments: features LIST(FLOAT), tree_file VARCHAR, has_missing BOOLEAN"); + } + + const auto &feat_type = args[0]->return_type; + if (feat_type.id() != LogicalTypeId::LIST || + ListType::GetChildType(feat_type).id() != LogicalTypeId::FLOAT) { + throw InvalidInputException("tree_predict: first argument must be LIST(FLOAT)"); + } + + // Evaluate constants + auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); + auto vHasMissing = ExpressionExecutor::EvaluateScalar(context, *args[2]); + + const std::string tree_path = vFile.ToString(); + const bool has_missing = vHasMissing.GetValue(); + + TreePtr tree_ptr; + try { + tree_ptr = std::make_shared(0, tree_path); + } catch (const std::exception &e) { + throw InvalidInputException("tree_predict: failed to load/parse tree file '%s': %s", + tree_path.c_str(), e.what()); + } + + return make_uniq(tree_ptr, has_missing); +} + +// ========================= +// Execute +// ========================= + +void ML_DecisionTree::Execute( + DataChunk &args, + ExpressionState &state, + Vector &result) { + + const idx_t count = args.size(); + if (count == 0) { + return; + } + + const auto &func_expr = state.expr.Cast(); + auto &bd = func_expr.bind_info->Cast(); + const bool has_missing = bd.has_missing; + const Tree &tree = *bd.tree; + + // features: LIST(FLOAT) + Vector &features_vec = args.data[0]; + auto &features_valid = FlatVector::Validity(features_vec); + auto *entries = FlatVector::GetData(features_vec); + + Vector &child = ListVector::GetEntry(features_vec); + auto &child_valid = FlatVector::Validity(child); + const float *vals = FlatVector::GetData(child); + + result.SetVectorType(VectorType::FLAT_VECTOR); + auto out = FlatVector::GetData(result); + auto &out_valid = FlatVector::Validity(result); + + for (idx_t i = 0; i < count; ++i) { + if (!features_valid.RowIsValid(i)) { + out_valid.SetInvalid(i); + continue; + } + + const auto ent = entries[i]; + const float *row_base = vals + ent.offset; + + float pred; + if (has_missing) { + bool any_null = false; + for (idx_t k = 0; k < ent.length; ++k) { + if (!child_valid.RowIsValid(ent.offset + k)) { + any_null = true; + break; + } + } + if (any_null) { + std::vector tmp(ent.length); + for (idx_t k = 0; k < ent.length; ++k) { + tmp[k] = child_valid.RowIsValid(ent.offset + k) + ? row_base[k] + : std::numeric_limits::quiet_NaN(); + } + pred = tree.predictSingleMissing(tmp.data()); + } else { + pred = tree.predictSingleMissing(row_base); + } + } else { + pred = tree.predictSingle(row_base); + } + out[i] = pred; + } +} + +// ========================= +// Register +// ========================= + +void ML_DecisionTree::Register(ExtensionLoader &loader) { + ScalarFunction fn( + "tree_predict", + { + LogicalType::LIST(LogicalType::FLOAT), // features + LogicalType::VARCHAR, // tree file path + LogicalType::BOOLEAN // has_missing + }, + LogicalType::FLOAT, + Execute); + fn.bind = Bind; + loader.RegisterFunction(fn); +} + +} // namespace duckdb diff --git a/src/ml_functions/ml_decision_forest_table.cpp b/src/ml_functions/ml_decision_forest_table.cpp new file mode 100644 index 0000000..655d470 --- /dev/null +++ b/src/ml_functions/ml_decision_forest_table.cpp @@ -0,0 +1,135 @@ +#include "ml_functions/ml_decision_forest_table.hpp" + +#include "duckdb/common/constants.hpp" +#include "duckdb/common/types.hpp" +#include "duckdb/common/vector.hpp" +#include "duckdb/function/table_function.hpp" +#include "duckdb/common/exception.hpp" + +#include + +namespace duckdb { + +using std::string; + +// ------------------------- +// Bind +// ------------------------- +unique_ptr ML_ForestTable::Bind( + ClientContext &context, + TableFunctionBindInput &input, + duckdb::vector &return_types, + duckdb::vector &names) { + + if (input.inputs.size() != 1) { + throw InvalidInputException("forest_trees(path) expects exactly 1 VARCHAR argument"); + } + + auto path_val = input.inputs[0]; + if (path_val.IsNull()) { + throw InvalidInputException("forest_trees: path cannot be NULL"); + } + + string path = path_val.ToString(); + if (!std::filesystem::exists(path)) { + throw InvalidInputException("forest_trees: path '%s' does not exist", path.c_str()); + } + + // Normalize: ensure it's a directory + if (!std::filesystem::is_directory(path)) { + throw InvalidInputException("forest_trees: '%s' is not a directory", path.c_str()); + } + + // Collect tree file paths at bind time + vector tree_paths; + for (auto &entry : std::filesystem::directory_iterator(path)) { + if (!entry.is_regular_file()) { + continue; + } + tree_paths.push_back(entry.path().string()); + } + + // Sort for deterministic ordering (optional but nice) + std::sort(tree_paths.begin(), tree_paths.end()); + + // Define output schema: (tree_id INT, tree_path VARCHAR) + return_types.clear(); + names.clear(); + + return_types.push_back(LogicalType::INTEGER); + names.push_back("tree_id"); + + return_types.push_back(LogicalType::VARCHAR); + names.push_back("tree_path"); + + return make_uniq(std::move(path), std::move(tree_paths)); +} + +// ------------------------- +// InitGlobal +// ------------------------- +unique_ptr ML_ForestTable::InitGlobal( + ClientContext &context, + TableFunctionInitInput &input) { + + auto &bind = input.bind_data->Cast(); + + auto state = make_uniq(); + state->tree_paths = bind.tree_paths; + state->total_rows = state->tree_paths.size(); + state->current_row = 0; + + return std::move(state); +} + +// ------------------------- +// Function +// ------------------------- +void ML_ForestTable::Function( + ClientContext &context, + TableFunctionInput &data, + DataChunk &output) { + + auto &gst = data.global_state->Cast(); + + if (gst.current_row >= gst.total_rows) { + output.SetCardinality(0); + return; + } + + idx_t remaining = gst.total_rows - gst.current_row; + idx_t max_rows = std::min(STANDARD_VECTOR_SIZE, remaining); + output.SetCardinality(max_rows); + + auto tree_id_vec = FlatVector::GetData(output.data[0]); + auto tree_path_vec = FlatVector::GetData(output.data[1]); + + for (idx_t i = 0; i < max_rows; i++) { + idx_t row_idx = gst.current_row + i; + + tree_id_vec[i] = static_cast(row_idx); + + const string &path = gst.tree_paths[row_idx]; + tree_path_vec[i] = StringVector::AddString(output.data[1], path); + } + + gst.current_row += max_rows; +} + +// ------------------------- +// Register +// ------------------------- +void ML_ForestTable::Register(ExtensionLoader &loader) { + TableFunction tf( + "forest_trees", + {LogicalType::VARCHAR}, // forest folder path + Function // table_function_t + ); + + tf.bind = Bind; + tf.init_global = InitGlobal; + + loader.RegisterFunction(tf); +} + +} // namespace duckdb diff --git a/src/ml_functions/ml_functions_scalar.cpp b/src/ml_functions/ml_functions_scalar.cpp index 68ab223..7c9d539 100644 --- a/src/ml_functions/ml_functions_scalar.cpp +++ b/src/ml_functions/ml_functions_scalar.cpp @@ -2,11 +2,14 @@ #include "ml_functions/matrix_multiplication.hpp" #include "min_max_scaler.cpp" #include "ml_functions/one_hot_encoder.hpp" -#include "decision_tree.cpp" +#include "ml_functions/decision_tree.hpp" #include "ml_functions/matrix_addition.hpp" #include "ml_functions/argmax.hpp" #include "ml_functions/softmax.hpp" #include "ml_functions/sigmoid.hpp" +#include "ml_functions/torch_dnn.hpp" +#include "ml_functions/decision_forest.hpp" +#include "ml_functions/ml_decision_forest_table.hpp" namespace duckdb { @@ -20,6 +23,9 @@ void RegisterMLScalarFunctions(ExtensionLoader &loader) { ML_Argmax::Register(loader); ML_Softmax::Register(loader); ML_Sigmoid::Register(loader); + ML_TorchDNN::Register(loader); + ML_DecisionForest::Register(loader); + ML_ForestTable::Register(loader); // RegisterSoftmax(loader); // RegisterSigmoid(loader); } diff --git a/src/ml_functions/torch_dnn.cpp b/src/ml_functions/torch_dnn.cpp new file mode 100644 index 0000000..75de36f --- /dev/null +++ b/src/ml_functions/torch_dnn.cpp @@ -0,0 +1,459 @@ +#include "duckdb.hpp" +#include "ml_functions/torch_dnn.hpp" + +#include "duckdb/common/constants.hpp" +#include "duckdb/common/exception.hpp" +#include "duckdb/common/types.hpp" +#include "duckdb/common/list.hpp" +#include "duckdb/common/vector_operations/generic_executor.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/function/scalar_function.hpp" +#include "duckdb/parser/parsed_data/create_scalar_function_info.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" + +#include +#include +#include + +namespace duckdb { + +using KernelType = ML_TorchDNN::KernelType; + +// --------------------------------------------------------------------- +// Helper: build torch::nn::Sequential from kernel spec + tensors +// --------------------------------------------------------------------- +static torch::nn::Sequential BuildSequentialFromKernels( + const std::vector &kernel_types, + const std::vector &dims, + const std::vector &weight_tensors, + bool &has_argmax /* in/out */) { + + const int64_t num_ops = static_cast(kernel_types.size()); + if (2 * num_ops != static_cast(dims.size())) { + throw InvalidInputException( + "torchdnn: mismatched 2*num_ops (%lld) vs dims.size() (%lld)", + (long long)(2 * num_ops), + (long long)dims.size()); + } + + torch::nn::Sequential model; + idx_t weight_idx = 0; + + for (int64_t i = 0; i < num_ops; ++i) { + auto kt = kernel_types[i]; + + if (kt == KernelType::MatMul && + i + 1 < num_ops && + kernel_types[i + 1] == KernelType::MatAdd) { + // Fuse MatMul + MatAdd -> Linear + const int64_t in_dim = dims[2 * i]; + const int64_t out_dim = dims[2 * i + 1]; + + auto denseLayer = torch::nn::Linear(in_dim, out_dim); + + if (weight_idx >= weight_tensors.size()) { + throw InvalidInputException( + "torchdnn: not enough weight tensors for Linear layer"); + } + auto W = weight_tensors[weight_idx++]; + + if (weight_idx >= weight_tensors.size()) { + throw InvalidInputException( + "torchdnn: not enough weight tensors for Linear bias"); + } + auto b = weight_tensors[weight_idx++]; + + if (W.sizes() != torch::IntArrayRef{in_dim, out_dim}) { + throw InvalidInputException( + "torchdnn: Linear W has wrong shape, expected (%lld,%lld)", + (long long)in_dim, (long long)out_dim); + } + if (b.numel() != out_dim) { + throw InvalidInputException( + "torchdnn: Linear b has wrong size, expected %lld", + (long long)out_dim); + } + + denseLayer->weight.set_data(W.t().contiguous()); + denseLayer->bias.set_data(b.contiguous()); + model->push_back(denseLayer); + + } else if (kt == KernelType::MatAdd) { + // Handled together with MatMul; skip + continue; + + } else if (kt == KernelType::BatchNorm) { + const int64_t dim = dims[2 * i]; // same in/out + auto bn = torch::nn::BatchNorm1d(dim); + + if (weight_idx + 1 >= weight_tensors.size()) { + throw InvalidInputException( + "torchdnn: not enough weight tensors for BatchNorm"); + } + auto gamma = weight_tensors[weight_idx++]; + auto beta = weight_tensors[weight_idx++]; + + if (gamma.numel() != dim || beta.numel() != dim) { + throw InvalidInputException( + "torchdnn: BatchNorm params have wrong size, expected %lld", + (long long)dim); + } + + bn->weight.set_data(gamma.contiguous()); + bn->bias.set_data(beta.contiguous()); + model->push_back(bn); + + } else if (kt == KernelType::ReLU) { + model->push_back(torch::nn::ReLU()); + + } else if (kt == KernelType::Sigmoid) { + model->push_back(torch::nn::Sigmoid()); + + } else if (kt == KernelType::Softmax) { + model->push_back(torch::nn::Softmax(1)); + + } else if (kt == KernelType::Argmax) { + // Argmax is handled in Execute + has_argmax = true; + } else { + throw InvalidInputException("torchdnn: unsupported kernel type index %d", (int)kt); + } + } + + model->eval(); + return model; +} + +// ========================= LoadModelFromFile ========================= +// File/spec -> kernel_types, dims, weight_tensors, has_argmax +// For now we keep the simple "identity3" / "identity3_argmax" spec. +void ML_TorchDNN::LoadModelFromFile( + const std::string &path, + std::vector &kernel_types, + std::vector &dims, + std::vector &weight_tensors, + bool &has_argmax) { + + kernel_types.clear(); + dims.clear(); + weight_tensors.clear(); + has_argmax = false; + + bool argmax_mode = false; + std::string spec = path; + + if (spec == "identity3_argmax") { + argmax_mode = true; + spec = "identity3"; + } + + if (spec == "identity3") { + const int64_t in_dim = 3; + const int64_t out_dim = 3; + + // MatMul + MatAdd + kernel_types.push_back(KernelType::MatMul); + kernel_types.push_back(KernelType::MatAdd); + + // dims for 2 operators: [in, out, out, out] + dims.push_back(in_dim); // MatMul in + dims.push_back(out_dim); // MatMul out + dims.push_back(out_dim); // MatAdd in + dims.push_back(out_dim); // MatAdd out + + if (argmax_mode) { + kernel_types.push_back(KernelType::Argmax); + dims.push_back(out_dim); // Argmax in + dims.push_back(out_dim); // Argmax out (logits) + has_argmax = true; + } else { + has_argmax = false; + } + + auto options = torch::TensorOptions().dtype(torch::kFloat32); + auto W = torch::eye(in_dim, options); // (3,3) + auto b = torch::zeros({out_dim}, options); // (3) + + weight_tensors.push_back(W); + weight_tensors.push_back(b); + return; + } + + throw InvalidInputException( + "torchdnn: unsupported model spec '%s'. " + "For tests, use 'identity3' or 'identity3_argmax'.", + path.c_str()); +} + +// ========================= Bind ========================= +unique_ptr ML_TorchDNN::Bind( + ClientContext &context, + ScalarFunction &bound_function, + vector> &args) { + + if (args.empty()) { + throw BinderException("torchdnn: expected at least input and model_file"); + } + + // Last argument is model_file + idx_t model_arg_index = args.size() - 1; + if (!args[model_arg_index]->IsFoldable()) { + throw BinderException("torchdnn: model_file must be a constant string"); + } + + // Evaluate the model file argument at bind time + auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[model_arg_index]); + if (vFile.IsNull()) { + throw BinderException("torchdnn: model_file is NULL"); + } + const std::string model_file = vFile.ToString(); + + // Load kernelTypes, dims, and weights from that file + std::vector kernel_types; + std::vector dims; + std::vector weight_tensors; + bool has_argmax = false; + + ML_TorchDNN::LoadModelFromFile(model_file, kernel_types, dims, weight_tensors, has_argmax); + + // Build libtorch model + auto model = BuildSequentialFromKernels(kernel_types, dims, weight_tensors, has_argmax); + + // BindData stores the model, dims, argmax flag, and file path + return make_uniq(model, dims, has_argmax, model_file); +} + +// ========================= Execute ========================= +void ML_TorchDNN::Execute( + DataChunk &args, + ExpressionState &state, + Vector &result) { + + const idx_t count = args.size(); + if (count == 0) { + return; + } + + // First argument: LIST input + Vector &lhs = args.data[0]; + UnifiedVectorFormat lhs_uvf; + lhs.ToUnifiedFormat(count, lhs_uvf); + const auto *entries = UnifiedVectorFormat::GetData(lhs_uvf); + + auto &child = ListVector::GetEntry(lhs); + const idx_t total_elems = ListVector::GetListSize(lhs); + UnifiedVectorFormat child_uvf; + child.ToUnifiedFormat(total_elems, child_uvf); + const double *child_data = UnifiedVectorFormat::GetData(child_uvf); + + // Get bind data + const auto &func_expr = state.expr.Cast(); + auto &info = func_expr.bind_info->Cast(); + + if (info.dims.empty()) { + throw InvalidInputException("torchdnn: dims are empty in bind data"); + } + + const auto input_dim = info.dims.front(); + const auto output_dim = info.dims.back(); + if (input_dim <= 0 || output_dim <= 0) { + throw InvalidInputException( + "torchdnn: invalid dims; input (%lld) or output (%lld) dim is non-positive", + (long long)input_dim, + (long long)output_dim); + } + + // Collect valid rows into contiguous buffer + std::vector input_buf; + input_buf.reserve(static_cast(count) * (size_t)input_dim); + + std::vector row_valid(count, false); + idx_t num_valid = 0; + + for (idx_t i = 0; i < count; ++i) { + const auto idx = lhs_uvf.sel->get_index(i); + + if (!lhs_uvf.validity.RowIsValid(idx)) { + row_valid[i] = false; + continue; + } + + const auto ent = entries[idx]; + if (ent.length != (idx_t)input_dim) { + throw InvalidInputException( + "torchdnn: input vector length %llu does not match model input dim %lld", + (unsigned long long)ent.length, + (long long)input_dim); + } + + row_valid[i] = true; + num_valid++; + + const double *row_ptr = child_data + ent.offset; + for (idx_t j = 0; j < (idx_t)input_dim; ++j) { + input_buf.push_back(static_cast(row_ptr[j])); + } + } + + if (num_valid == 0) { + // everything is NULL + if (result.GetType().id() == LogicalTypeId::LIST) { + result.SetVectorType(VectorType::FLAT_VECTOR); + auto *res_entries = FlatVector::GetData(result); + auto &res_valid = FlatVector::Validity(result); + for (idx_t i = 0; i < count; ++i) { + res_entries[i] = {0, 0}; + res_valid.Set(i, false); + } + } else { + result.SetVectorType(VectorType::FLAT_VECTOR); + auto &res_valid = FlatVector::Validity(result); + for (idx_t i = 0; i < count; ++i) { + res_valid.Set(i, false); + } + } + return; + } + + // Build torch input tensor: [num_valid, input_dim] + torch::Tensor input_tensor = torch::from_blob( + input_buf.data(), + {static_cast(num_valid), static_cast(input_dim)}, + torch::TensorOptions().dtype(torch::kFloat32)); + + // Forward + torch::Tensor output_tensor = info.model->forward(input_tensor); + output_tensor = output_tensor.contiguous().cpu(); + + const auto &return_type = result.GetType(); + + if (info.has_argmax && return_type.id() == LogicalTypeId::INTEGER) { + // Argmax-style scalar output + result.SetVectorType(VectorType::FLAT_VECTOR); + auto &res_valid = FlatVector::Validity(result); + auto *out_vals = FlatVector::GetData(result); + + torch::Tensor argmax_tensor; + if (output_tensor.dim() == 2) { + argmax_tensor = std::get<1>(output_tensor.max(/*dim=*/1)); + } else { + argmax_tensor = output_tensor; + } + argmax_tensor = argmax_tensor.to(torch::kInt32).contiguous(); + auto *data_int = argmax_tensor.data_ptr(); + + idx_t valid_idx = 0; + for (idx_t i = 0; i < count; ++i) { + if (!row_valid[i]) { + res_valid.Set(i, false); + continue; + } + res_valid.Set(i, true); + out_vals[i] = data_int[valid_idx++]; + } + + } else if (return_type.id() == LogicalTypeId::LIST) { + // Vector output LIST per row + result.SetVectorType(VectorType::FLAT_VECTOR); + + auto *res_entries = FlatVector::GetData(result); + auto &res_child = ListVector::GetEntry(result); + auto &res_valid = FlatVector::Validity(result); + + if (output_tensor.dim() != 2 || output_tensor.size(1) != output_dim) { + throw InvalidInputException( + "torchdnn: model output shape mismatch; expected (?, %lld), got (%lld, %lld)", + (long long)output_dim, + (long long)output_tensor.size(0), + (long long)output_tensor.size(1)); + } + + const idx_t total_out = (idx_t)num_valid * (idx_t)output_dim; + ListVector::Reserve(result, total_out); + ListVector::SetListSize(result, total_out); + + double *out_data = FlatVector::GetData(res_child); + auto *data_float = output_tensor.data_ptr(); + + idx_t cursor = 0; + idx_t valid_idx = 0; + for (idx_t i = 0; i < count; ++i) { + if (!row_valid[i]) { + res_entries[i] = {0, 0}; + res_valid.Set(i, false); + continue; + } + + res_entries[i] = {cursor, static_cast(output_dim)}; + res_valid.Set(i, true); + + const float *src = data_float + (size_t)valid_idx * (size_t)output_dim; + for (idx_t j = 0; j < (idx_t)output_dim; ++j) { + out_data[cursor + j] = static_cast(src[j]); + } + + cursor += (idx_t)output_dim; + valid_idx += 1; + } + } else { + throw InvalidInputException( + "torchdnn: unsupported combination of has_argmax=%d and return type %s", + info.has_argmax ? 1 : 0, + return_type.ToString().c_str()); + } +} + +// ========================= Register ========================= +void ML_TorchDNN::Register(ExtensionLoader &loader) { + // 1) LIST, VARCHAR -> LIST + { + ScalarFunction fn( + "torchdnn", + { + LogicalType::LIST(LogicalType::DOUBLE), // input + LogicalType::VARCHAR // model_file + }, + LogicalType::LIST(LogicalType::DOUBLE), // output + Execute + ); + fn.bind = Bind; + fn.stability = FunctionStability::VOLATILE; + loader.RegisterFunction(fn); + } + + // 2) LIST, INTEGER, VARCHAR -> INTEGER + { + ScalarFunction fn( + "torchdnn", + { + LogicalType::LIST(LogicalType::DOUBLE), + LogicalType::INTEGER, + LogicalType::VARCHAR + }, + LogicalType::INTEGER, + Execute + ); + fn.bind = Bind; + fn.stability = FunctionStability::VOLATILE; + loader.RegisterFunction(fn); + } + + // 3) LIST, BIGINT, VARCHAR -> INTEGER + { + ScalarFunction fn( + "torchdnn", + { + LogicalType::LIST(LogicalType::DOUBLE), + LogicalType::BIGINT, + LogicalType::VARCHAR + }, + LogicalType::INTEGER, + Execute + ); + fn.bind = Bind; + fn.stability = FunctionStability::VOLATILE; + loader.RegisterFunction(fn); + } +} + +} // namespace duckdb diff --git a/src/optimization/CMakeLists.txt b/src/optimization/CMakeLists.txt index a21c7ca..427c006 100644 --- a/src/optimization/CMakeLists.txt +++ b/src/optimization/CMakeLists.txt @@ -8,6 +8,8 @@ list(APPEND EXTENSION_SOURCES #All Actions ${CMAKE_CURRENT_SOURCE_DIR}/actions/MatMulDense2SparseRewriteAction.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/actions/MultiLayerUDF2TorchNNRewriteAction.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/actions/DecisionForestUDF2RelationRewriteAction.cpp #Feature Extraction Helpers ${CMAKE_CURRENT_SOURCE_DIR}/feature_extraction/query2vec/query_annotation.cpp diff --git a/src/optimization/actions/DecisionForestUDF2RelationRewriteAction.cpp b/src/optimization/actions/DecisionForestUDF2RelationRewriteAction.cpp new file mode 100644 index 0000000..bab9ff8 --- /dev/null +++ b/src/optimization/actions/DecisionForestUDF2RelationRewriteAction.cpp @@ -0,0 +1,436 @@ +// src/optimization/actions/DecisionForestUDF2RelationRewriteAction.cpp + +#include "optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp" + +#include "duckdb/catalog/catalog.hpp" +#include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp" +#include "duckdb/common/constants.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/common/types/value.hpp" +#include "duckdb/function/aggregate_function.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/planner/expression/bound_reference_expression.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression/bound_operator_expression.hpp" +#include "duckdb/planner/expression/bound_case_expression.hpp" +#include "duckdb/planner/expression/bound_comparison_expression.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/planner/operator/logical_cross_product.hpp" +#include "duckdb/planner/operator/logical_aggregate.hpp" +#include "duckdb/planner/expression_iterator.hpp" + +#include "ml_functions/decision_forest.hpp" +#include "ml_functions/decision_tree.hpp" +#include "ml_functions/ml_decision_forest_table.hpp" + +#include + +namespace duckdb { + +namespace fs = std::filesystem; + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +// Enumerate tree files in a forest folder (like Velox Forest::vectorizeForestFolder) +static bool ListForestTreeFiles(const string &forest_path, + vector &out_paths) { + std::error_code ec; + if (!fs::exists(forest_path, ec) || !fs::is_directory(forest_path, ec)) { + return false; + } + for (auto &entry : fs::directory_iterator(forest_path, ec)) { + if (ec) { + break; + } + if (!entry.is_regular_file()) { + continue; + } + out_paths.push_back(entry.path().string()); + } + std::sort(out_paths.begin(), out_paths.end()); + return !out_paths.empty(); +} + +// Find a top-level decision_forest_predict(...) call in a LogicalProjection +// Returns pointer to the BoundFunctionExpression and sets expr_idx_out +static BoundFunctionExpression *FindTopLevelForestCall(LogicalProjection &proj, + idx_t &expr_idx_out) { + for (idx_t i = 0; i < proj.expressions.size(); i++) { + auto &expr = *proj.expressions[i]; + if (expr.expression_class != ExpressionClass::BOUND_FUNCTION) { + continue; + } + auto &f = expr.Cast(); + if (StringUtil::CIEquals(f.function.name, "decision_forest_predict")) { + expr_idx_out = i; + return &f; + } + } + expr_idx_out = DConstants::INVALID_INDEX; + return nullptr; +} + +// Build a LogicalGet over the forest_trees(forest_path) table function: +// forest_trees(forest_path) -> columns: (tree_id INT, tree_path VARCHAR) +static unique_ptr BuildForestGet(ClientContext &context, + const string &forest_path) { + // Bind input to ML_ForestTable::Bind + vector bind_inputs; + bind_inputs.emplace_back(Value(forest_path)); + + vector return_types; + vector names; + TableFunctionBindInput tf_input(bind_inputs, {}, nullptr); + + // Reuse the same Bind logic as the registered table function + auto bind_data = ML_ForestTable::Bind(context, tf_input, return_types, names); + + // Define table function (same as in ML_ForestTable::Register) + TableFunction tf( + "forest_trees", + {LogicalType::VARCHAR}, // forest_path + ML_ForestTable::Function, + ML_ForestTable::Bind, + ML_ForestTable::InitGlobal); + + // table_index: arbitrary (extension-local) logical table id + idx_t table_index = 0; + + auto get = make_uniq( + table_index, + std::move(return_types), + std::move(names), + std::move(bind_data), + tf); + + return std::move(get); +} + +// Core rewrite: +// PROJECTION [ ..., decision_forest_predict(features, forest_path, num_feat, is_cls) AS cls ] +// child +// +// becomes: +// +// PROJECTION [ group_keys..., cls ] +// AGGREGATE [ group_keys ] (SUM(pred) AS sum_pred) +// PROJECTION [ group_keys..., pred = tree_predict(features, tree_path, false) ] +// CROSS_PRODUCT +// child +// forest_trees(forest_path) +// +// For now we handle only the case where: +// * the projection has exactly one forest call at top level +// * features arg is a BoundReferenceExpression (column) +static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input, + unique_ptr &plan) { + if (!plan || plan->type != LogicalOperatorType::LOGICAL_PROJECTION) { + return false; + } + + auto &proj = plan->Cast(); + auto &context = input.context; + + // 1) Find the top-level decision_forest_predict(...) + idx_t forest_idx; + auto *forest_func = FindTopLevelForestCall(proj, forest_idx); + if (!forest_func) { + return false; // no forest UDF here + } + + // 2) Get forest bind data (ML_DecisionForest::BindData) + auto *forest_bind_ptr = + dynamic_cast(forest_func->bind_info.get()); + if (!forest_bind_ptr) { + // unexpected bind type + return false; + } + auto &dfb = *forest_bind_ptr; + const string forest_path = dfb.forest_path; + const bool is_classification = dfb.is_classification; + + // 3) Enumerate tree files once to get num_trees + vector tree_paths; + if (!ListForestTreeFiles(forest_path, tree_paths)) { + // Can't enumerate; bail out for now + return false; + } + const idx_t num_trees = tree_paths.size(); + if (num_trees == 0) { + return false; + } + + // 4) Features arg must be present and be a BoundReferenceExpression + if (forest_func->children.empty()) { + return false; + } + if (forest_func->children[0]->expression_class != ExpressionClass::BOUND_REFERENCE) { + // For now only handle simple column ref; can be generalized later + return false; + } + auto &feat_ref = forest_func->children[0]->Cast(); + const idx_t feat_col_idx = feat_ref.index; + + // 5) Build right-hand side GET forest_trees(forest_path) + auto right_get = BuildForestGet(context, forest_path); + + // 6) Original child of projection becomes left side of CROSS_PRODUCT + if (proj.children.empty()) { + // malformed plan + return false; + } + auto left_child = std::move(proj.children[0]); + + // CROSS_PRODUCT(left_child, forest_trees) + auto cross = make_uniq( + std::move(left_child), + std::move(right_get)); + + // After CROSS_PRODUCT schema: + // [ all columns from left_child | tree_id, tree_path ] + idx_t left_cols = cross->children[0]->types.size(); + idx_t tree_id_col_idx = left_cols + 0; + idx_t tree_path_col_idx = left_cols + 1; + + // 7) Build inner PROJECTION on top of CROSS_PRODUCT + // + // - group key columns: original projection expressions except the forest one + // (for now we approximate them as references to the first N columns + // of the left side; you can refine this mapping if you had computed exprs) + // - plus pred = tree_predict(features, tree_path, false) + + vector> inner_proj_exprs; + vector group_types; + + // Keep all original non-forest expressions as group keys + idx_t next_col_idx = 0; + for (idx_t i = 0; i < proj.expressions.size(); i++) { + if (i == forest_idx) { + continue; + } + auto &orig = *proj.expressions[i]; + inner_proj_exprs.push_back(make_uniq( + orig.return_type, + next_col_idx)); + group_types.push_back(orig.return_type); + next_col_idx++; + } + + // Build tree_predict(features, tree_path, false) + + // features: still at feat_col_idx from left side + auto feat_ref_in_cross = make_uniq( + feat_ref.return_type, + feat_col_idx); + + // tree_path: comes from right side + auto tree_path_ref_in_cross = make_uniq( + LogicalType::VARCHAR, + tree_path_col_idx); + + // has_missing = false + auto has_missing_expr = make_uniq(Value::BOOLEAN(false)); + + // Lookup tree_predict(...) function from catalog + auto &catalog = Catalog::GetSystemCatalog(context); + auto &tree_entry = catalog.GetEntry( + context, DEFAULT_SCHEMA, "tree_predict"); + + const ScalarFunction *tree_func_ptr = nullptr; + for (auto &fn : tree_entry.functions.functions) { + if (fn.arguments.size() == 3 && + fn.arguments[0] == LogicalType::LIST(LogicalType::FLOAT) && + fn.arguments[1].id() == LogicalTypeId::VARCHAR && + fn.arguments[2].id() == LogicalTypeId::BOOLEAN && + fn.return_type.id() == LogicalTypeId::FLOAT) { + tree_func_ptr = &fn; + break; + } + } + if (!tree_func_ptr) { + throw InternalException("DecisionForest rewrite: tree_predict(LIST(FLOAT), VARCHAR, BOOLEAN) not found"); + } + auto tree_func = *tree_func_ptr; + + // Prepare children for the bound function expression + vector> tree_children; + tree_children.push_back(feat_ref_in_cross->Copy()); + tree_children.push_back(tree_path_ref_in_cross->Copy()); + tree_children.push_back(has_missing_expr->Copy()); + + // For Bind we need a separate copy of the arguments + vector> args_for_bind; + args_for_bind.push_back(std::move(feat_ref_in_cross)); + args_for_bind.push_back(std::move(tree_path_ref_in_cross)); + args_for_bind.push_back(std::move(has_missing_expr)); + + auto tree_bind = ML_DecisionTree::Bind(context, tree_func, args_for_bind); + + auto tree_pred_expr = make_uniq( + LogicalType::FLOAT, + tree_func, + std::move(tree_children), + std::move(tree_bind)); + + // Append prediction as last column of inner projection + inner_proj_exprs.push_back(std::move(tree_pred_expr)); + + auto inner_proj = make_uniq( + std::move(cross), + std::move(inner_proj_exprs)); + + // 8) Build AGGREGATE on top of inner_proj: + // GROUP BY all group_types, AGG: SUM(pred) AS sum_pred + vector> group_exprs; + vector> aggregate_exprs; + + // group keys: references [0..group_types.size()-1] + for (idx_t i = 0; i < group_types.size(); i++) { + group_exprs.push_back(make_uniq( + group_types[i], + i)); + } + + // prediction column index + idx_t pred_idx = group_types.size(); + aggregate_exprs.push_back(make_uniq( + LogicalType::FLOAT, + pred_idx)); + + // Create LogicalAggregate; we give it the child, group exprs, and aggregate exprs. + // DuckDB will expect the aggregate expressions to be BoundAggregateExpression. + // Here we treat aggregate_exprs as arguments to SUM later; we will fill + // aggregate_functions / aggregate_types to keep the plan consistent. + auto aggregate = make_uniq( + std::move(inner_proj), + std::move(group_exprs), + std::move(aggregate_exprs)); + + // Fill aggregate function metadata: SUM(FLOAT) + vector agg_funcs; + vector agg_types; + + auto sum_fun = AggregateFunction::GetAggregateFunction("sum", {LogicalType::FLOAT}); + agg_funcs.push_back(sum_fun); + agg_types.push_back(LogicalType::FLOAT); + + aggregate->group_types = group_types; + aggregate->aggregate_types = agg_types; + aggregate->aggregate_functions = agg_funcs; + + // 9) Final projection on top: + // - group key columns (restored as they were) + // - forest_result = (is_classification ? (avg > 0 ? 1 : 0) : avg) + vector> final_proj_exprs; + + // group keys: references [0..group_types.size()-1] of aggregate output + for (idx_t i = 0; i < group_types.size(); i++) { + final_proj_exprs.push_back(make_uniq( + group_types[i], + i)); + } + + // sum_pred is at col index = group_types.size() + idx_t sum_idx = group_types.size(); + auto sum_ref = make_uniq( + LogicalType::FLOAT, + sum_idx); + + // avg_pred = sum_pred / num_trees + auto denom_val = Value::FLOAT(static_cast(num_trees)); + auto denom_expr = make_uniq(denom_val); + + vector> div_children; + div_children.push_back(std::move(sum_ref)); + div_children.push_back(std::move(denom_expr)); + + auto avg_expr = make_uniq( + ExpressionType::OPERATOR_DIVIDE, + LogicalType::FLOAT, + std::move(div_children)); + + unique_ptr forest_result_expr; + + if (is_classification) { + // CASE WHEN avg > 0 THEN 1 ELSE 0 + auto zero_val = Value::FLOAT(0.0f); + auto zero_expr = make_uniq(zero_val); + + auto cond = make_uniq( + ExpressionType::COMPARE_GREATER, + avg_expr->Copy(), + std::move(zero_expr)); + + auto one_out = make_uniq(Value::FLOAT(1.0f)); + auto zero_out = make_uniq(Value::FLOAT(0.0f)); + + forest_result_expr = make_uniq( + LogicalType::FLOAT, + std::move(cond), + std::move(one_out), + std::move(zero_out)); + } else { + forest_result_expr = std::move(avg_expr); + } + + final_proj_exprs.push_back(std::move(forest_result_expr)); + + auto final_proj = make_uniq( + std::move(aggregate), + std::move(final_proj_exprs)); + + // Replace whole subtree under this projection with the new rewritten plan + plan = std::move(final_proj); + return true; +} + +// --------------------------------------------------------------------------- +// Public API: check / apply +// --------------------------------------------------------------------------- + +bool DecisionForestUDF2RelationRewriteAction::check(OptimizerExtensionInput &, + unique_ptr &plan) { + if (!plan) { + return false; + } + + bool found = false; + + if (plan->type == LogicalOperatorType::LOGICAL_PROJECTION) { + auto &proj = plan->Cast(); + idx_t dummy; + if (FindTopLevelForestCall(proj, dummy)) { + found = true; + } + } + + // Recursively check children + for (auto &child : plan->children) { + found |= DecisionForestUDF2RelationRewriteAction::check({}, child); + } + return found; +} + +bool DecisionForestUDF2RelationRewriteAction::apply(OptimizerExtensionInput &input, + unique_ptr &plan) { + if (!plan) { + return false; + } + + bool modified = false; + + if (plan->type == LogicalOperatorType::LOGICAL_PROJECTION) { + modified |= RewriteForestProjectionToCrossProduct(input, plan); + } + + // Recurse into children + for (auto &child : plan->children) { + modified |= DecisionForestUDF2RelationRewriteAction::apply(input, child); + } + return modified; +} + +} // namespace duckdb diff --git a/src/optimization/actions/MultiLayerUDF2TorchNNRewriteAction.cpp b/src/optimization/actions/MultiLayerUDF2TorchNNRewriteAction.cpp new file mode 100644 index 0000000..d616e30 --- /dev/null +++ b/src/optimization/actions/MultiLayerUDF2TorchNNRewriteAction.cpp @@ -0,0 +1,371 @@ +// optimization/actions/MultiLayerUDF2TorchNNRewriteAction.cpp +#include "optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp" + +#include "duckdb/common/enums/expression_type.hpp" +#include "duckdb/common/exception.hpp" +#include "duckdb/common/string_util.hpp" + +#include "duckdb/catalog/catalog.hpp" +#include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp" + +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/planner/expression/bound_reference_expression.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression_iterator.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/planner/operator/logical_filter.hpp" + +#include "ml_functions/matrix_multiplication.hpp" +#include "ml_functions/matrix_addition.hpp" +#include "ml_functions/torch_dnn.hpp" + +#include + + +namespace duckdb { + +using KernelType = ML_TorchDNN::KernelType; + +// Try to recognize: mat_add(mat_mul(input, ...), ...) +// and fill kernel_types / dims / weight_tensors / has_argmax. +// Also return the "base input" expression that should become torchdnn's first arg. +static bool CollectSimpleNNFromExpression( + Expression &expr, + std::vector &kernel_types, + std::vector &dims, + std::vector &weight_tensors, + bool &has_argmax, + unique_ptr &base_input_out) { + + // Reset outputs + kernel_types.clear(); + dims.clear(); + weight_tensors.clear(); + has_argmax = false; + base_input_out.reset(); + + if (expr.expression_class != ExpressionClass::BOUND_FUNCTION) { + std::cout << "Returning from here!!\n\n"; + return false; + } + + auto &outer_f = expr.Cast(); + + // We currently only handle mat_add(mat_mul(x, ...), ...) + if (!StringUtil::CIEquals(outer_f.function.name, "mat_add")) { + return false; + } + if (outer_f.children.size() < 1) { + return false; + } + + // First argument to mat_add should be mat_mul(...) + auto &mul_child_expr = *outer_f.children[0]; + if (mul_child_expr.expression_class != ExpressionClass::BOUND_FUNCTION) { + return false; + } + auto &mul_f = mul_child_expr.Cast(); + if (!StringUtil::CIEquals(mul_f.function.name, "mat_mul")) { + return false; + } + + // Extract bind data from mat_mul + auto *mm_bind_ptr = dynamic_cast(mul_f.bind_info.get()); + if (!mm_bind_ptr || !mm_bind_ptr->has_bound_weights) { + return false; + } + auto &mm_bind = *mm_bind_ptr; + + // Extract bind data from mat_add + auto *add_bind_ptr = dynamic_cast(outer_f.bind_info.get()); + if (!add_bind_ptr || !add_bind_ptr->has_bound_biases) { + return false; + } + auto &add_bind = *add_bind_ptr; + + // Sanity: dimensions must match + if (mm_bind.n != add_bind.n) { + // output size of mat_mul != bias length + return false; + } + + const int64_t in_dim = static_cast(mm_bind.k); + const int64_t out_dim = static_cast(mm_bind.n); + + auto options = torch::TensorOptions().dtype(torch::kFloat32); + + // MatMul - weights: row-major (k x n) + if (mm_bind.weights.size() != static_cast(mm_bind.k * mm_bind.n)) { + return false; + } + torch::Tensor W = torch::from_blob( + (void *)mm_bind.weights.data(), // non-owning + { (long)mm_bind.k, (long)mm_bind.n }, + options).clone(); // clone to own memory + + // MatAdd - biases: length n + if (add_bind.biases.size() != static_cast(add_bind.n)) { + return false; + } + torch::Tensor b = torch::from_blob( + (void *)add_bind.biases.data(), + { (long)add_bind.n }, + options).clone(); + + // Fill kernel_types & dims exactly like Velox rule: + // Op 0: MatMul + kernel_types.push_back(KernelType::MatMul); + dims.push_back(in_dim); + dims.push_back(out_dim); + + // Op 1: MatAdd + kernel_types.push_back(KernelType::MatAdd); + dims.push_back(out_dim); + dims.push_back(out_dim); + + // Weight tensors order: [W, b] (to be interpreted by Bind) + weight_tensors.push_back(W); + weight_tensors.push_back(b); + + has_argmax = false; // single layer, no argmax yet + + // base input is the first child to mat_mul (e.g., column "a") + if (mul_f.children.empty()) { + return false; + } + + base_input_out = mul_f.children[0]->Copy(); + + return true; +} + +// torchdnn(base_input, '') with bind_info containing +// the actual Sequential model built from kernel_types/dims/tensors. + +static unique_ptr BuildTorchDNNExpression( + ClientContext &context, + unique_ptr base_input, + const std::vector &kernel_types, + const std::vector &dims, + const std::vector &weight_tensors, + bool has_argmax) { + + // 1) Find the registered "torchdnn" function (we’ll use the 2-arg form). + auto &catalog = Catalog::GetSystemCatalog(context); + auto &torch_entry = catalog.GetEntry( + context, DEFAULT_SCHEMA, "torchdnn"); + + // We chose: torchdnn(LIST, VARCHAR) -> LIST + const ScalarFunction *chosen_func = nullptr; + for (auto &func : torch_entry.functions.functions) { + if (func.arguments.size() == 2 && + func.arguments[0] == LogicalType::LIST(LogicalType::DOUBLE) && + func.arguments[1].id() == LogicalTypeId::VARCHAR) { + chosen_func = &func; + break; + } + } + if (!chosen_func) { + throw InternalException("MultiLayerUDF2TorchNN: could not find torchdnn(LIST, VARCHAR) overload"); + } + + // 2) Build the actual torch::nn::Sequential from the specs + torch::nn::Sequential model; + idx_t weight_idx = 0; + + for (idx_t i = 0; i < kernel_types.size(); i++) { + auto kt = kernel_types[i]; + + if (kt == KernelType::MatMul && + i + 1 < kernel_types.size() && + kernel_types[i + 1] == KernelType::MatAdd) { + + const int64_t in_dim = dims[2 * i]; + const int64_t out_dim = dims[2 * i + 1]; + + auto linear = torch::nn::Linear(in_dim, out_dim); + + // W + if (weight_idx >= weight_tensors.size()) { + throw InternalException("MultiLayerUDF2TorchNN: not enough tensors for Linear weight"); + } + auto W = weight_tensors[weight_idx++]; + + // b + if (weight_idx >= weight_tensors.size()) { + throw InternalException("MultiLayerUDF2TorchNN: not enough tensors for Linear bias"); + } + auto b = weight_tensors[weight_idx++]; + + // Expect W to be (in_dim, out_dim) as per our builder + if (W.sizes() != torch::IntArrayRef{in_dim, out_dim}) { + throw InternalException("MultiLayerUDF2TorchNN: Linear W shape mismatch"); + } + if (b.numel() != out_dim) { + throw InternalException("MultiLayerUDF2TorchNN: Linear b size mismatch"); + } + + linear->weight.set_data(W.t().contiguous()); + linear->bias.set_data(b.contiguous()); + + model->push_back(linear); + + // Skip the MatAdd in the loop + i++; // extra increment + + } else if (kt == KernelType::MatAdd) { + // We only expect MatAdd after MatMul; standalone MatAdd not yet supported. + continue; + + } else if (kt == KernelType::ReLU) { + model->push_back(torch::nn::ReLU()); + + } else if (kt == KernelType::Sigmoid) { + model->push_back(torch::nn::Sigmoid()); + + } else if (kt == KernelType::Softmax) { + model->push_back(torch::nn::Softmax(1)); + + } else if (kt == KernelType::BatchNorm) { + // TODO: handle BatchNorm tensors here if you add them + throw NotImplementedException("BatchNorm not yet wired in BuildTorchDNNExpression"); + } else if (kt == KernelType::Argmax) { + // we handle argmax in Execute, not here + continue; + } + } + + model->eval(); + + // 3) Build BindData + std::vector dims_copy = dims; + std::string model_file = ""; // not actually used by Execute + auto bind_data = make_uniq( + std::move(model), + std::move(dims_copy), + has_argmax, + model_file); + + // 4) Build children: [ base_input , constant model_file ] + vector> children; + children.push_back(std::move(base_input)); + unique_ptr model_arg = make_uniq(Value(model_file)); + children.push_back(std::move(model_arg)); + + // 5) Return new BoundFunctionExpression with our pre-populated bind_data + auto return_type = LogicalType::LIST(LogicalType::DOUBLE); + auto bound = make_uniq( + return_type, + *chosen_func, + std::move(children), + std::move(bind_data)); + + unique_ptr result = std::move(bound); + return result; +} + +static bool CheckExpressionForNN(OptimizerExtensionInput &input, + Expression &expr) { + std::vector kernel_types; + std::vector dims; + std::vector tensors; + bool has_argmax = false; + unique_ptr base_input; + + return CollectSimpleNNFromExpression(expr, kernel_types, dims, tensors, has_argmax, base_input); +} + +bool MultiLayerUDF2TorchNNRewriteAction::check(OptimizerExtensionInput &input, + unique_ptr &plan) { + if (!plan) return false; + + bool found = false; + + switch (plan->type) { + case LogicalOperatorType::LOGICAL_PROJECTION: { + auto &proj = plan->Cast(); + for (auto &expr : proj.expressions) { + found |= CheckExpressionForNN(input, *expr); + } + break; + } + case LogicalOperatorType::LOGICAL_FILTER: { + auto &fil = plan->Cast(); + for (auto &expr : fil.expressions) { + found |= CheckExpressionForNN(input, *expr); + } + break; + } + default: + break; + } + + // Recurse into children + for (auto &child : plan->children) { + found |= check(input, child); + } + + return found; +} + +static bool RewriteExpressionToTorchDNN(OptimizerExtensionInput &input, + unique_ptr &expr) { + std::vector kernel_types; + std::vector dims; + std::vector tensors; + bool has_argmax = false; + unique_ptr base_input; + + if (!CollectSimpleNNFromExpression(*expr, kernel_types, dims, tensors, has_argmax, base_input)) { + // no match: still recurse into children + ExpressionIterator::EnumerateChildren(*expr, [&](unique_ptr &child) { + RewriteExpressionToTorchDNN(input, child); + }); + return false; + } + + // We have a match: build torchdnn(base_input, "") + auto &context = input.context; + expr = BuildTorchDNNExpression(context, + std::move(base_input), + kernel_types, + dims, + tensors, + has_argmax); + return true; +} + +bool MultiLayerUDF2TorchNNRewriteAction::apply(OptimizerExtensionInput &input, + unique_ptr &plan) { + if (!plan) return false; + + bool modified = false; + + switch (plan->type) { + case LogicalOperatorType::LOGICAL_PROJECTION: { + auto &proj = plan->Cast(); + for (auto &expr : proj.expressions) { + modified |= RewriteExpressionToTorchDNN(input, expr); + } + break; + } + case LogicalOperatorType::LOGICAL_FILTER: { + auto &fil = plan->Cast(); + for (auto &expr : fil.expressions) { + modified |= RewriteExpressionToTorchDNN(input, expr); + } + break; + } + default: + break; + } + + // Recurse + for (auto &child : plan->children) { + modified |= apply(input, child); + } + + return modified; +} + +} // namespace duckdb diff --git a/src/optimization/dynamic_optimizer.cpp b/src/optimization/dynamic_optimizer.cpp index 1e7a09a..6646841 100644 --- a/src/optimization/dynamic_optimizer.cpp +++ b/src/optimization/dynamic_optimizer.cpp @@ -1,6 +1,7 @@ #include "duckdb.hpp" #include "optimization/dynamic_optimizer.hpp" #include "optimization/actions/MatMulDense2SparseRewriteAction.hpp" +#include "optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp" #include "optimization/catalog.hpp" #include "cost_model/estimator.hpp" @@ -11,28 +12,35 @@ namespace duckdb{ void DynamicOpt::Optimize(OptimizerExtensionInput &in, unique_ptr &plan) { if (!plan) return; // else return; - Catalog_optimization cat; - // // first step : check all rules and see which ones apply - // // TODO Decompose this properly later with Catalog - idx_t id = cat.cacheQueryPlan(in.context,plan); + // Catalog_optimization cat; + // // // first step : check all rules and see which ones apply + // // // TODO Decompose this properly later with Catalog + // idx_t id = cat.cacheQueryPlan(in.context,plan); - // unique_ptr initial_plan = plan->Copy(in.context); + // // unique_ptr initial_plan = plan->Copy(in.context); - // std::cout << "\nCached the initial plan with cacheId: " << id << "\n"; + // // std::cout << "\nCached the initial plan with cacheId: " << id << "\n"; - if(MatMulDense2SparseRewriteAction::check(in, plan)){ - std::cout << "\nMatMulDense2SparseRewriteAction is applicable \n"; - MatMulDense2SparseRewriteAction::apply(in, plan); + // if(MatMulDense2SparseRewriteAction::check(in, plan)){ + // std::cout << "\nMatMulDense2SparseRewriteAction is applicable \n"; + // MatMulDense2SparseRewriteAction::apply(in, plan); + // } + + if(MultiLayerUDF2TorchNNRewriteAction::check(in, plan)){ + std::cout << "\nMultiLayerUDF2TorchNNRewriteAction is applicable \n"; + MultiLayerUDF2TorchNNRewriteAction::apply(in, plan); } - SimpleEstimator est(std::make_unique()); - auto total = est.Estimate(*plan); - std::cout << "\n Final plan cost after Dynamic Optimization: " << total.cost; + // SimpleEstimator est(std::make_unique()); + // auto total = est.Estimate(*plan); + // std::cout << "\n Final plan cost after Dynamic Optimization: " << total.cost; + + // auto annotated = AnnotatePlanTree(*plan); // pass by const-ref + // DisplayAnnotatedPlan(*annotated); - auto annotated = AnnotatePlanTree(*plan); // pass by const-ref - DisplayAnnotatedPlan(*annotated); + // traverse_and_extract(*annotated); - traverse_and_extract(*annotated); + diff --git a/src/optimization/register_optimizers.cpp b/src/optimization/register_optimizers.cpp index f3b187d..5215083 100644 --- a/src/optimization/register_optimizers.cpp +++ b/src/optimization/register_optimizers.cpp @@ -92,7 +92,7 @@ void RegisterCactusOptimizers(DatabaseInstance &db) { // Typically do argument/string rewrites early, then other expression rewrites. // cfg.optimizer_extensions.push_back(CactusReplaceBindingOpt{}); // cfg.optimizer_extensions.push_back(CactusAdd5Opt{}); - cfg.optimizer_extensions.push_back(CactusDynamicOpt{}); + // cfg.optimizer_extensions.push_back(CactusDynamicOpt{}); } } // namespace duckdb diff --git a/test/sql/decision_forest.test b/test/sql/decision_forest.test new file mode 100644 index 0000000..49d44cf --- /dev/null +++ b/test/sql/decision_forest.test @@ -0,0 +1,25 @@ +-- queries/test_decision_forest.sql + +-- Build 3 rows of 6756-dimensional feature vectors +WITH feature_rows AS ( + SELECT + id, + list(CAST(i AS FLOAT)) AS features + FROM ( + -- three ids + SELECT * FROM (VALUES (1), (2), (3)) AS ids(id), + -- 0 .. 6755 + range(0, 6756) AS r(i) + ) + GROUP BY id +) +SELECT + id, + decision_forest_predict( + features, + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/flights/rf_dot_trees_custom', + 6756, + TRUE + ) AS pred +FROM feature_rows +ORDER BY id; diff --git a/test/sql/nn_test.test b/test/sql/nn_test.test new file mode 100644 index 0000000..37e87b8 --- /dev/null +++ b/test/sql/nn_test.test @@ -0,0 +1,114 @@ +# name: test/sql/cactusdb_nn_project.test +# description: compose mat_mul, mat_add, cdb_softmax, ml_argmax into a simple 1-layer NN in a Project node +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +# ------------------------------------------------------------------ +# Create a 2x2 weight matrix W for a simple classifier: +# +# logits = [x0 - x1, -x0 + x1] +# +# This chooses: +# class 0 if x0 > x1 +# class 1 if x1 > x0 +# class 0 on ties (since both logits equal) +# +# W = [[ 1, -1 ], +# [ -1, 1 ]] +# so that [x0, x1] * W = [x0 - x1, -x0 + x1] +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE w_nn(c1 DOUBLE, c2 DOUBLE); + +statement ok +INSERT INTO w_nn VALUES + ( 1.0, -1.0), + (-1.0, 1.0); + +statement ok +COPY w_nn TO 'w_nn.csv' (FORMAT CSV, HEADER FALSE); + +# ------------------------------------------------------------------ +# Create zero biases b = [0, 0] so mat_add is exercised but +# does not change logits: +# z = mat_add(mat_mul(a, W), b) +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE b_zero(c1 DOUBLE, c2 DOUBLE); + +statement ok +INSERT INTO b_zero VALUES (0.0, 0.0); + +statement ok +COPY b_zero TO 'b_zero.csv' (FORMAT CSV, HEADER FALSE); + +# ------------------------------------------------------------------ +# Inputs: +# id a +# 1 [2,1] -> logits [1,-1] -> softmax ~[0.880797, 0.119203] -> class 0 +# 2 [1,3] -> logits [-2,2] -> softmax ~[0.017986, 0.982014] -> class 1 +# 3 [5,5] -> logits [0,0] -> softmax [0.5, 0.5] -> class 0 (tie) +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE inputs(id INTEGER, a DOUBLE[]); + +statement ok +INSERT INTO inputs VALUES + (1, [2.0, 1.0]), + (2, [1.0, 3.0]), + (3, [5.0, 5.0]); + +# ------------------------------------------------------------------ +# 1) Check the softmax probabilities of the "NN": +# +# probs = softmax( mat_add( mat_mul(a, W), b ) ) +# +# Entire NN is a single project expression: +# cdb_softmax(mat_add(mat_mul(a, 'w_nn.csv','dense'), 'b_zero.csv')) +# ------------------------------------------------------------------ +query I +SELECT list_transform( + cdb_softmax( + mat_add( + mat_mul(a, 'w_nn.csv', 'dense'), + 'b_zero.csv' + ) + ), + x -> round(x::DOUBLE, 6) + ) AS probs +FROM inputs +ORDER BY id; +---- +[0.880797, 0.119203] +[0.017986, 0.982014] +[0.5, 0.5] + +# ------------------------------------------------------------------ +# 2) Full classification pipeline: +# +# pred = argmax( softmax( mat_add( mat_mul(a, W), b ) ) ) +# +# This matches: +# [2,1] -> class 0 +# [1,3] -> class 1 +# [5,5] -> class 0 +# ------------------------------------------------------------------ +query I +SELECT ml_argmax( + cdb_softmax( + mat_add( + mat_mul(a, 'w_nn.csv', 'dense'), + 'b_zero.csv' + ) + ) + ) AS cls +FROM inputs +ORDER BY id; +---- +0 +1 +0 diff --git a/test/sql/torch.test b/test/sql/torch.test new file mode 100644 index 0000000..9244715 --- /dev/null +++ b/test/sql/torch.test @@ -0,0 +1,79 @@ +# name: test/sql/torchdnn_identity.test +# description: test torchdnn scalar function with dummy identity models +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +########################################################### +# Setup: simple input table of 3D vectors +########################################################### + +statement ok +CREATE TEMP TABLE torchdnn_input(v DOUBLE[]); + +statement ok +INSERT INTO torchdnn_input VALUES + ([1.0, 2.0, 3.0]), + ([3.0, 2.0, 1.0]); + +########################################################### +# 1) Vector output variant: torchdnn(v, 'identity3') +# identity3 implements y = x (3D identity layer) +########################################################### + +query I +SELECT torchdnn(v, 'identity3') AS y +FROM torchdnn_input +ORDER BY 1; +---- +[1.0, 2.0, 3.0] +[3.0, 2.0, 1.0] + +########################################################### +# 2) Argmax variant: torchdnn(v, 1, 'identity3_argmax') +# +# identity3_argmax implements y = x + argmax on output: +# [1,2,3] -> 2 +# [3,2,1] -> 0 +# We order results by idx so the output is deterministic. +########################################################### + +query I +SELECT torchdnn(v, 1, 'identity3_argmax') AS idx +FROM torchdnn_input +ORDER BY 1; +---- +0 +2 + +########################################################### +# 3) NULL row handling for vector output +########################################################### + +statement ok +INSERT INTO torchdnn_input VALUES (NULL); + +query I +SELECT torchdnn(v, 'identity3') AS y +FROM torchdnn_input +ORDER BY 1 NULLS LAST; +---- +[1.0, 2.0, 3.0] +[3.0, 2.0, 1.0] +NULL + +########################################################### +# 4) NULL row handling for argmax output +########################################################### + +query I +SELECT torchdnn(v, 1, 'identity3_argmax') AS idx +FROM torchdnn_input +ORDER BY 1 NULLS LAST; +---- +0 +2 +NULL From 0d3e4fafa3684d2b6f500e03ae3fe539fd6b3e8f Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 26 Nov 2025 16:26:00 -0700 Subject: [PATCH 12/18] Optimizer commit first to add DecisionForestUDF2RelationRewriteAction.cpp-not working --- .gitignore | 1 + queries/forest_query.sql | 2 +- src/cactusdb_extension.cpp | 11 +- src/include/ml_functions/decision_tree.hpp | 99 ++-- ...ecisionForestUDF2RelationRewriteAction.hpp | 22 +- src/ml_functions/decision_forest.cpp | 3 +- src/ml_functions/decision_tree.cpp | 444 ++++++++++-------- src/optimization/CMakeLists.txt | 2 +- ...ecisionForestUDF2RelationRewriteAction.cpp | 433 ++++++++++------- src/optimization/dynamic_optimizer.cpp | 12 +- src/optimization/register_optimizers.cpp | 39 +- test/sql/decision_tree.test | 22 +- test/sql/extension_test.test | 24 + 13 files changed, 672 insertions(+), 442 deletions(-) create mode 100644 test/sql/extension_test.test diff --git a/.gitignore b/.gitignore index a32763e..dbaa421 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ temp_dir/ mydb.duckdb plans/ *.json +archived_tests/* diff --git a/queries/forest_query.sql b/queries/forest_query.sql index e3cee32..a54da06 100644 --- a/queries/forest_query.sql +++ b/queries/forest_query.sql @@ -25,6 +25,6 @@ SELECT '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/flights/rf_dot_trees_custom', 6756, TRUE - ) AS pred + ) FROM feature_rows ORDER BY id; diff --git a/src/cactusdb_extension.cpp b/src/cactusdb_extension.cpp index 142969f..c80bfc6 100644 --- a/src/cactusdb_extension.cpp +++ b/src/cactusdb_extension.cpp @@ -11,8 +11,17 @@ namespace duckdb { static void LoadInternal(ExtensionLoader &loader) { - RegisterMLScalarFunctions(loader); auto &db = loader.GetDatabaseInstance(); + auto &config = DBConfig::GetConfig(db); + + // Add New Configs + // + config.AddExtensionOption("cactusdb_enable_optimizers", "Enable All Optimizers", LogicalType::BOOLEAN, + Value::BOOLEAN(true)); + config.AddExtensionOption("cactusdb_enable_optimizer", "Enable Specific Optimizer", LogicalType::VARCHAR, "2"); + + + RegisterMLScalarFunctions(loader); RegisterCactusOptimizers(db); } diff --git a/src/include/ml_functions/decision_tree.hpp b/src/include/ml_functions/decision_tree.hpp index b7e1c63..d3623da 100644 --- a/src/include/ml_functions/decision_tree.hpp +++ b/src/include/ml_functions/decision_tree.hpp @@ -1,87 +1,90 @@ +/* + * Decision tree inference UDF for DuckDB (tree_predict) + * + * Layout: + * - ML_DecisionTree::Node / Tree: in-memory decision tree + * - ML_DecisionTree::BindData: per-binding state + tree cache + * - ML_DecisionTree::Bind / Execute / Register: UDF wiring + */ + #pragma once #include "duckdb.hpp" -#include "duckdb/function/function.hpp" - #include #include +#include #include namespace duckdb { -struct ML_DecisionTree { - // ------------------------- - // Constants & basic types - // ------------------------- +class ML_DecisionTree { +public: + // Match Velox side: enough for typical XGBoost dumps static constexpr idx_t MAX_NUM_NODES_PER_TREE = 512; struct Node { union { float threshold; - float leafValue; + float leaf_value; }; - int indexID; - int leftChild; - int rightChild; - bool isLeaf; - bool isMissTrackLeft; // When feature value is missing, whether to traverse left + int32_t index_id; + int32_t left_child; + int32_t right_child; + bool is_leaf; + bool is_miss_track_left; + + Node() + : threshold(0.0f), index_id(-1), left_child(-1), right_child(-1), + is_leaf(true), is_miss_track_left(true) { + } }; - // ------------------------- - // Tree implementation - // ------------------------- class Tree { public: - Node tree[MAX_NUM_NODES_PER_TREE]; - int treeId; + Node nodes[MAX_NUM_NODES_PER_TREE]; + int32_t tree_id; Tree(); - Tree(int id, const std::string &tree_path); + Tree(int32_t id, const std::string &tree_path); + + static void ConstructTreeFromPath(const std::string &tree_path, Node *nodes); - static void constructTreeFromPath(const std::string &tree_path_in, Node *tree); - static void constructTreeFromPathHelper( - const std::string &tree_path_in, - std::vector &relationships, - std::vector &innerNodes, - std::vector &leafNodes); + static void ConstructTreeFromPathHelper(const std::string &tree_path, + std::vector &relationships, + std::vector &inner_nodes, + std::vector &leaf_nodes); - static void processInnerNodes(std::vector &innerNodes, Node *tree); - static void processLeafNodes(std::vector &leafNodes, Node *tree); - static void processRelationships(std::vector &relationships, Node *tree); + static void ProcessInnerNodes(std::vector &inner_nodes, Node *nodes); + static void ProcessLeafNodes(std::vector &leaf_nodes, Node *nodes); + static void ProcessRelationships(std::vector &relationships, Node *nodes); - float predictSingle(const float *row_base) const; - float predictSingleMissing(const float *row_base) const; + float PredictSingle(const float *row_base) const; + float PredictSingleMissing(const float *row_base) const; }; using TreePtr = std::shared_ptr; - // ------------------------- - // Bind data - // ------------------------- - struct BindData final : public FunctionData { - TreePtr tree; - bool has_missing; + struct BindData : public FunctionData { + bool has_missing_default; + std::unordered_map tree_cache; BindData(); - BindData(const TreePtr &t, bool hm); + explicit BindData(bool hm); unique_ptr Copy() const override; - bool Equals(const FunctionData &other_p) const override; + bool Equals(const FunctionData &other) const override; }; - // ------------------------- - // Scalar function hooks - // ------------------------- - static unique_ptr Bind( - ClientContext &context, - ScalarFunction &bound_function, - vector> &args); +public: + // Bind: validates argument types + captures constant default for has_missing if present. + static unique_ptr Bind(ClientContext &context, + ScalarFunction &bound_function, + vector> &args); - static void Execute( - DataChunk &args, - ExpressionState &state, - Vector &result); + // Execute: evaluates tree_predict over a LIST(FLOAT) + path + has_missing. + static void Execute(DataChunk &args, ExpressionState &state, Vector &result); + // Register: registers "tree_predict" into the extension. static void Register(ExtensionLoader &loader); }; diff --git a/src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp b/src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp index 406a39f..2e506f7 100644 --- a/src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp +++ b/src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp @@ -1,27 +1,17 @@ -// src/include/optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp #pragma once #include "duckdb.hpp" -#include "duckdb/optimizer/optimizer_extension.hpp" namespace duckdb { -// Optimizer rewrite rule: -// -// decision_forest_predict(features, forest_path, num_features, is_classification) -// ==> CROSS_PRODUCT with per-tree table + tree_predict + AGGREGATE -// -// Current version handles only the simple case: -// * forest UDF is a top-level expression in a LogicalProjection -// * first argument (features) is a BoundReferenceExpression (plain column) struct DecisionForestUDF2RelationRewriteAction { - // Return true if the plan *contains* a pattern we know how to rewrite - static bool check(OptimizerExtensionInput &input, - unique_ptr &plan); + // 1) Check if this rule *could* apply on this plan (pattern exists) + static bool check(OptimizerExtensionInput &input, + unique_ptr &plan); - // Actually apply the rewrite in-place; return true if modified - static bool apply(OptimizerExtensionInput &input, - unique_ptr &plan); + // 2) Actually apply the rewrite + static bool apply(OptimizerExtensionInput &input, + unique_ptr &plan); }; } // namespace duckdb diff --git a/src/ml_functions/decision_forest.cpp b/src/ml_functions/decision_forest.cpp index 17f6f38..fbc8cde 100644 --- a/src/ml_functions/decision_forest.cpp +++ b/src/ml_functions/decision_forest.cpp @@ -79,7 +79,7 @@ float ML_DecisionForest::Forest::PredictRow(const float *row_base, idx_t num_fea double accumulated = 0.0; for (auto const &tree : trees) { // We use the non-missing variant (Velox forest didn't handle missing explicitly) - accumulated += (double)tree.predictSingle(row_base); + accumulated += (double)tree.PredictSingle(row_base); } double avg = accumulated / (double)trees.size(); @@ -262,6 +262,7 @@ void ML_DecisionForest::Register(ExtensionLoader &loader) { Execute); fn.bind = Bind; + fn.stability = FunctionStability::VOLATILE; loader.RegisterFunction(fn); } diff --git a/src/ml_functions/decision_tree.cpp b/src/ml_functions/decision_tree.cpp index fb8ee3d..80bddf5 100644 --- a/src/ml_functions/decision_tree.cpp +++ b/src/ml_functions/decision_tree.cpp @@ -1,230 +1,240 @@ +//===----------------------------------------------------------------------===// +// decision_tree.cpp +// Implementation of tree_predict(features, tree_path, has_missing) +//===----------------------------------------------------------------------===// + #include "ml_functions/decision_tree.hpp" #include "duckdb/common/exception.hpp" #include "duckdb/common/list.hpp" +// #include "duckdb/common/types/unified_vector_format.hpp" #include "duckdb/execution/expression_executor.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" -#include #include #include #include #include +#include namespace duckdb { // ========================= -// Tree methods +// Tree implementation // ========================= -ML_DecisionTree::Tree::Tree() : treeId(0) { - // nothing +ML_DecisionTree::Tree::Tree() : tree_id(0) { + for (idx_t i = 0; i < MAX_NUM_NODES_PER_TREE; ++i) { + nodes[i] = Node(); + } } -ML_DecisionTree::Tree::Tree(int id, const std::string &tree_path) : treeId(id) { - constructTreeFromPath(tree_path, this->tree); +ML_DecisionTree::Tree::Tree(int32_t id, const std::string &tree_path) : tree_id(id) { + for (idx_t i = 0; i < MAX_NUM_NODES_PER_TREE; ++i) { + nodes[i] = Node(); + } + ConstructTreeFromPath(tree_path, nodes); } -void ML_DecisionTree::Tree::constructTreeFromPath(const std::string &tree_path_in, Node *tree) { +void ML_DecisionTree::Tree::ConstructTreeFromPath(const std::string &tree_path, Node *nodes) { std::vector relationships; - std::vector innerNodes; - std::vector leafNodes; - constructTreeFromPathHelper(tree_path_in, relationships, innerNodes, leafNodes); - processInnerNodes(innerNodes, tree); - processLeafNodes(leafNodes, tree); - processRelationships(relationships, tree); + std::vector inner_nodes; + std::vector leaf_nodes; + ConstructTreeFromPathHelper(tree_path, relationships, inner_nodes, leaf_nodes); + ProcessInnerNodes(inner_nodes, nodes); + ProcessLeafNodes(leaf_nodes, nodes); + ProcessRelationships(relationships, nodes); } -void ML_DecisionTree::Tree::constructTreeFromPathHelper( - const std::string &tree_path_in, +void ML_DecisionTree::Tree::ConstructTreeFromPathHelper( + const std::string &tree_path, std::vector &relationships, - std::vector &innerNodes, - std::vector &leafNodes) { + std::vector &inner_nodes, + std::vector &leaf_nodes) { - std::ifstream inputFile; - inputFile.open(tree_path_in.data()); - if (!inputFile.is_open()) { - throw InvalidInputException("DecisionTree: failed to open tree file '%s'", tree_path_in.c_str()); + std::ifstream input_file(tree_path); + if (!input_file.is_open()) { + throw InvalidInputException("DecisionTree: failed to open tree file '%s'", tree_path.c_str()); } std::string line; - while (getline(inputFile, line)) { - if ((line.size() == 0) || - (line.find("graph") != std::string::npos) || - (line.find("}") != std::string::npos)) { - // skip header/footer + while (std::getline(input_file, line)) { + if (line.empty() || line.find("graph") != std::string::npos || line.find('}') != std::string::npos) { + continue; // skip header/footer/empty + } + if (line.find("->") != std::string::npos) { + relationships.push_back(line); + } else if (line.find("leaf") != std::string::npos) { + leaf_nodes.push_back(line); + } else if (line.find("label") != std::string::npos) { + inner_nodes.push_back(line); } else { - if (line.find("->") != std::string::npos) { - relationships.push_back(line); - } else if (line.find("leaf") != std::string::npos) { - leafNodes.push_back(line); - } else if (line.find("label") != std::string::npos) { - innerNodes.push_back(line); - } else { - // empty or irrelevant - } + // ignore } } - - inputFile.close(); + input_file.close(); } -void ML_DecisionTree::Tree::processInnerNodes(std::vector &innerNodes, Node *tree) { - int findStartPosition; - int findEndPosition; - - for (idx_t i = 0; i < innerNodes.size(); ++i) { - const std::string ¤tLine = innerNodes[i]; - int nodeID; - int indexID; +void ML_DecisionTree::Tree::ProcessInnerNodes(std::vector &inner_nodes, Node *nodes) { + for (idx_t i = 0; i < inner_nodes.size(); ++i) { + const std::string ¤t = inner_nodes[i]; + int node_id; + int index_id; float threshold; - // nodeID - if ((findEndPosition = currentLine.find("[ label")) != std::string::npos) { - nodeID = std::stoi(currentLine.substr(4, findEndPosition - 1 - 4)); - } else { - throw std::runtime_error("[ERROR] Error in extracting inner node nodeID"); + // node_id + auto pos_label = current.find("[ label"); + if (pos_label == std::string::npos) { + throw std::runtime_error("[DecisionTree] Error extracting inner node id"); + } + node_id = std::stoi(current.substr(4, pos_label - 1 - 4)); + if (node_id < 0 || (idx_t)node_id >= MAX_NUM_NODES_PER_TREE) { + throw std::runtime_error("[DecisionTree] Node id out of range in inner node"); } - // indexID - if ((findStartPosition = currentLine.find("f")) != std::string::npos && - (findEndPosition = currentLine.find("<")) != std::string::npos) { - indexID = std::stoi( - currentLine.substr(findStartPosition + 1, findEndPosition - findStartPosition - 1)); - } else { - throw std::runtime_error("[ERROR] Error in extracting inner node indexID"); + // index_id + auto pos_f = current.find('f'); + auto pos_lt = current.find('<'); + if (pos_f == std::string::npos || pos_lt == std::string::npos || pos_f >= pos_lt) { + throw std::runtime_error("[DecisionTree] Error extracting inner node indexID"); } + index_id = std::stoi(current.substr(pos_f + 1, pos_lt - pos_f - 1)); // threshold - if ((findStartPosition = currentLine.find("<")) != std::string::npos && - (findEndPosition = currentLine.find("\" ]")) != std::string::npos) { - threshold = std::stod( - currentLine.substr(findStartPosition + 1, findEndPosition - findStartPosition - 1)); - } else { - throw std::runtime_error("[ERROR] Error in extracting inner node threshold"); + auto pos_lt2 = current.find('<'); + auto pos_end = current.find("\" ]"); + if (pos_lt2 == std::string::npos || pos_end == std::string::npos || pos_lt2 >= pos_end) { + throw std::runtime_error("[DecisionTree] Error extracting inner node threshold"); } - - tree[nodeID].isMissTrackLeft = false; // XGBoost default is noMissing/right - tree[nodeID].indexID = indexID; - tree[nodeID].isLeaf = false; - tree[nodeID].leftChild = -1; - tree[nodeID].rightChild = -1; - tree[nodeID].threshold = threshold; + threshold = std::stof(current.substr(pos_lt2 + 1, pos_end - pos_lt2 - 1)); + + Node &n = nodes[node_id]; + n.index_id = index_id; + n.is_leaf = false; + n.left_child = -1; + n.right_child = -1; + n.threshold = threshold; + n.is_miss_track_left = false; // default: noMissing/right } } -void ML_DecisionTree::Tree::processLeafNodes(std::vector &leafNodes, Node *tree) { - int findStartPosition; - int findEndPosition; - - for (idx_t i = 0; i < leafNodes.size(); ++i) { - const std::string ¤tLine = leafNodes[i]; - int nodeID; - float leafValue = -1.0f; +void ML_DecisionTree::Tree::ProcessLeafNodes(std::vector &leaf_nodes, Node *nodes) { + for (idx_t i = 0; i < leaf_nodes.size(); ++i) { + const std::string ¤t = leaf_nodes[i]; + int node_id; + float leaf_value = -1.0f; - // nodeID - if ((findEndPosition = currentLine.find("[")) != std::string::npos) { - nodeID = std::stoi(currentLine.substr(4, findEndPosition - 1 - 4)); - } else { - throw std::runtime_error("[ERROR] Error in extracting leaf node nodeID"); + auto pos_bracket = current.find('['); + if (pos_bracket == std::string::npos) { + throw std::runtime_error("[DecisionTree] Error extracting leaf node id"); } - - // leafValue - if ((findStartPosition = currentLine.find("leaf=")) != std::string::npos && - (findEndPosition = currentLine.find("\" ]")) != std::string::npos) { - leafValue = std::stod( - currentLine.substr(findStartPosition + 5, findEndPosition - 3 - findStartPosition - 5)); - } else { - throw std::runtime_error("[ERROR] Error in extracting leaf node leafValue"); + node_id = std::stoi(current.substr(4, pos_bracket - 1 - 4)); + if (node_id < 0 || (idx_t)node_id >= MAX_NUM_NODES_PER_TREE) { + throw std::runtime_error("[DecisionTree] Node id out of range in leaf node"); } - tree[nodeID].indexID = -1; - tree[nodeID].isLeaf = true; - tree[nodeID].leftChild = -1; - tree[nodeID].rightChild = -1; - tree[nodeID].leafValue = leafValue; - tree[nodeID].isMissTrackLeft = true; // doesn't matter for leaf nodes + auto pos_leaf = current.find("leaf="); + auto pos_end = current.find("\" ]"); + if (pos_leaf == std::string::npos || pos_end == std::string::npos || pos_leaf >= pos_end) { + throw std::runtime_error("[DecisionTree] Error extracting leaf node value"); + } + leaf_value = std::stof(current.substr(pos_leaf + 5, pos_end - 3 - (pos_leaf + 5))); + + Node &n = nodes[node_id]; + n.index_id = -1; + n.is_leaf = true; + n.left_child = -1; + n.right_child = -1; + n.leaf_value = leaf_value; + n.is_miss_track_left = true; // doesn't matter for leaf nodes } } -void ML_DecisionTree::Tree::processRelationships(std::vector &relationships, Node *tree) { - int findMidPosition; - int findEndPosition; - +void ML_DecisionTree::Tree::ProcessRelationships(std::vector &relationships, Node *nodes) { for (idx_t i = 0; i < relationships.size(); ++i) { - const std::string ¤tLine = relationships[i]; - int parentNodeID; - int childNodeID; + const std::string ¤t = relationships[i]; + int parent_id; + int child_id; - if ((findMidPosition = currentLine.find("->")) != std::string::npos) { - parentNodeID = std::stoi(currentLine.substr(4, findMidPosition - 1 - 4)); - } else { - throw std::runtime_error("[ERROR] Error in extracting parentNodeID"); + auto pos_arrow = current.find("->"); + if (pos_arrow == std::string::npos) { + throw std::runtime_error("[DecisionTree] Error extracting parentNodeID"); + } + parent_id = std::stoi(current.substr(4, pos_arrow - 1 - 4)); + if (parent_id < 0 || (idx_t)parent_id >= MAX_NUM_NODES_PER_TREE) { + throw std::runtime_error("[DecisionTree] Parent id out of range"); } - if ((findEndPosition = currentLine.find("[")) != std::string::npos) { - childNodeID = std::stoi(currentLine.substr( - findMidPosition + 3, findEndPosition - 1 - findMidPosition - 3)); - } else { - throw std::runtime_error("[ERROR] Error in extracting childNodeID"); + auto pos_bracket = current.find('['); + if (pos_bracket == std::string::npos || pos_bracket <= pos_arrow + 2) { + throw std::runtime_error("[DecisionTree] Error extracting childNodeID"); + } + child_id = std::stoi(current.substr(pos_arrow + 3, pos_bracket - 1 - (pos_arrow + 3))); + if (child_id < 0 || (idx_t)child_id >= MAX_NUM_NODES_PER_TREE) { + throw std::runtime_error("[DecisionTree] Child id out of range"); } - if (currentLine.find("yes, missing") != std::string::npos) { - tree[parentNodeID].isMissTrackLeft = true; + if (current.find("yes, missing") != std::string::npos) { + nodes[parent_id].is_miss_track_left = true; } - if (tree[parentNodeID].leftChild == -1) { - tree[parentNodeID].leftChild = childNodeID; - } else if (tree[parentNodeID].rightChild == -1) { - tree[parentNodeID].rightChild = childNodeID; + Node &p = nodes[parent_id]; + if (p.left_child == -1) { + p.left_child = child_id; + } else if (p.right_child == -1) { + p.right_child = child_id; } else { - throw std::runtime_error("[ERROR] children nodes were updated again"); + throw std::runtime_error("[DecisionTree] children updated more than twice"); } } } -float ML_DecisionTree::Tree::predictSingle(const float *row_base) const { +float ML_DecisionTree::Tree::PredictSingle(const float *row_base) const { int cur = 0; - while (!tree[cur].isLeaf) { - const int idx = tree[cur].indexID; - const float fv = row_base[idx]; - cur = (fv < tree[cur].threshold) ? tree[cur].leftChild : tree[cur].rightChild; + while (!nodes[cur].is_leaf) { + const Node &n = nodes[cur]; + const float fv = row_base[n.index_id]; + cur = (fv < n.threshold) ? n.left_child : n.right_child; } - return tree[cur].leafValue; + return nodes[cur].leaf_value; } -float ML_DecisionTree::Tree::predictSingleMissing(const float *row_base) const { +float ML_DecisionTree::Tree::PredictSingleMissing(const float *row_base) const { int cur = 0; - while (!tree[cur].isLeaf) { - const int idx = tree[cur].indexID; - const float fv = row_base[idx]; + while (!nodes[cur].is_leaf) { + const Node &n = nodes[cur]; + const float fv = row_base[n.index_id]; if (std::isnan(fv)) { - cur = tree[cur].isMissTrackLeft ? tree[cur].leftChild : tree[cur].rightChild; + cur = n.is_miss_track_left ? n.left_child : n.right_child; } else { - cur = (fv < tree[cur].threshold) ? tree[cur].leftChild : tree[cur].rightChild; + cur = (fv < n.threshold) ? n.left_child : n.right_child; } } - return tree[cur].leafValue; + return nodes[cur].leaf_value; } // ========================= -// BindData methods +// BindData implementation // ========================= -ML_DecisionTree::BindData::BindData() : has_missing(false) { +ML_DecisionTree::BindData::BindData() : has_missing_default(false) { } -ML_DecisionTree::BindData::BindData(const TreePtr &t, bool hm) - : tree(t), has_missing(hm) { +ML_DecisionTree::BindData::BindData(bool hm) : has_missing_default(hm) { } unique_ptr ML_DecisionTree::BindData::Copy() const { - return make_uniq(tree, has_missing); + auto copy = make_uniq(has_missing_default); + // share the cache; trees are immutable & read-only + copy->tree_cache = tree_cache; + return std::move(copy); } bool ML_DecisionTree::BindData::Equals(const FunctionData &other_p) const { - auto &o = other_p.Cast(); - return tree.get() == o.tree.get() && has_missing == o.has_missing; + auto &other = other_p.Cast(); + // Only semantics-relevant field is the default flag; cache does not matter. + return has_missing_default == other.has_missing_default; } // ========================= @@ -232,13 +242,14 @@ bool ML_DecisionTree::BindData::Equals(const FunctionData &other_p) const { // ========================= unique_ptr ML_DecisionTree::Bind( - ClientContext &context, - ScalarFunction &bound_function, + ClientContext & /*context*/, + ScalarFunction & /*bound_function*/, vector> &args) { if (args.size() != 3) { throw InvalidInputException( - "tree_predict expects 3 arguments: features LIST(FLOAT), tree_file VARCHAR, has_missing BOOLEAN"); + "tree_predict expects 3 arguments: " + "features LIST(FLOAT), tree_file VARCHAR, has_missing BOOLEAN"); } const auto &feat_type = args[0]->return_type; @@ -246,23 +257,23 @@ unique_ptr ML_DecisionTree::Bind( ListType::GetChildType(feat_type).id() != LogicalTypeId::FLOAT) { throw InvalidInputException("tree_predict: first argument must be LIST(FLOAT)"); } + if (args[1]->return_type.id() != LogicalTypeId::VARCHAR) { + throw InvalidInputException("tree_predict: second argument must be VARCHAR (tree file path)"); + } + if (args[2]->return_type.id() != LogicalTypeId::BOOLEAN) { + throw InvalidInputException("tree_predict: third argument must be BOOLEAN (has_missing)"); + } - // Evaluate constants - auto vFile = ExpressionExecutor::EvaluateScalar(context, *args[1]); - auto vHasMissing = ExpressionExecutor::EvaluateScalar(context, *args[2]); - - const std::string tree_path = vFile.ToString(); - const bool has_missing = vHasMissing.GetValue(); - - TreePtr tree_ptr; - try { - tree_ptr = std::make_shared(0, tree_path); - } catch (const std::exception &e) { - throw InvalidInputException("tree_predict: failed to load/parse tree file '%s': %s", - tree_path.c_str(), e.what()); + // Default has_missing value: only when the 3rd arg is a constant. + bool has_missing_default = false; + if (args[2]->expression_class == ExpressionClass::BOUND_CONSTANT) { + auto &const_expr = args[2]->Cast(); + if (!const_expr.value.IsNull()) { + has_missing_default = const_expr.value.GetValue(); + } } - return make_uniq(tree_ptr, has_missing); + return make_uniq(has_missing_default); } // ========================= @@ -281,53 +292,104 @@ void ML_DecisionTree::Execute( const auto &func_expr = state.expr.Cast(); auto &bd = func_expr.bind_info->Cast(); - const bool has_missing = bd.has_missing; - const Tree &tree = *bd.tree; - // features: LIST(FLOAT) + // ----------------------------------------------------------------- + // 1) features: LIST(FLOAT) in unified format + // ----------------------------------------------------------------- Vector &features_vec = args.data[0]; - auto &features_valid = FlatVector::Validity(features_vec); - auto *entries = FlatVector::GetData(features_vec); - - Vector &child = ListVector::GetEntry(features_vec); - auto &child_valid = FlatVector::Validity(child); - const float *vals = FlatVector::GetData(child); - + UnifiedVectorFormat features_uf; + features_vec.ToUnifiedFormat(count, features_uf); + auto list_entries = UnifiedVectorFormat::GetData(features_uf); + + // Child vector contains the actual FLOAT elements of all lists + Vector &child_vec = ListVector::GetEntry(features_vec); + const idx_t child_count = ListVector::GetListSize(features_vec); + UnifiedVectorFormat child_uf; + child_vec.ToUnifiedFormat(child_count, child_uf); + auto child_vals = UnifiedVectorFormat::GetData(child_uf); + + // ----------------------------------------------------------------- + // 2) tree_path: VARCHAR in unified format + // ----------------------------------------------------------------- + Vector &path_vec = args.data[1]; + UnifiedVectorFormat path_uf; + path_vec.ToUnifiedFormat(count, path_uf); + auto path_data = UnifiedVectorFormat::GetData(path_uf); + + // ----------------------------------------------------------------- + // 3) has_missing: BOOLEAN in unified format + // ----------------------------------------------------------------- + Vector &miss_vec = args.data[2]; + UnifiedVectorFormat miss_uf; + miss_vec.ToUnifiedFormat(count, miss_uf); + auto miss_data = UnifiedVectorFormat::GetData(miss_uf); + + // ----------------------------------------------------------------- + // 4) Output setup + // ----------------------------------------------------------------- result.SetVectorType(VectorType::FLAT_VECTOR); auto out = FlatVector::GetData(result); auto &out_valid = FlatVector::Validity(result); for (idx_t i = 0; i < count; ++i) { - if (!features_valid.RowIsValid(i)) { + const idx_t feat_idx = features_uf.sel->get_index(i); + const idx_t path_idx = path_uf.sel->get_index(i); + const idx_t miss_idx = miss_uf.sel->get_index(i); + + // NULL list or NULL path -> NULL result + if (!features_uf.validity.RowIsValid(feat_idx) || + !path_uf.validity.RowIsValid(path_idx)) { out_valid.SetInvalid(i); continue; } - const auto ent = entries[i]; - const float *row_base = vals + ent.offset; + // list entry for this row + const auto ent = list_entries[feat_idx]; - float pred; - if (has_missing) { - bool any_null = false; - for (idx_t k = 0; k < ent.length; ++k) { - if (!child_valid.RowIsValid(ent.offset + k)) { - any_null = true; - break; - } - } - if (any_null) { - std::vector tmp(ent.length); - for (idx_t k = 0; k < ent.length; ++k) { - tmp[k] = child_valid.RowIsValid(ent.offset + k) - ? row_base[k] - : std::numeric_limits::quiet_NaN(); - } - pred = tree.predictSingleMissing(tmp.data()); + // Build a contiguous row buffer of features using child_uf + std::vector row_buf(ent.length); + for (idx_t k = 0; k < ent.length; ++k) { + const idx_t child_logical = ent.offset + k; + const idx_t child_phys = child_uf.sel->get_index(child_logical); + if (!child_uf.validity.RowIsValid(child_phys)) { + row_buf[k] = std::numeric_limits::quiet_NaN(); } else { - pred = tree.predictSingleMissing(row_base); + row_buf[k] = child_vals[child_phys]; } + } + + // Resolve tree_path + const std::string tree_path = path_data[path_idx].GetString(); + + // has_missing flag for this row (default + per-row override) + bool row_has_missing = bd.has_missing_default; + if (miss_uf.validity.RowIsValid(miss_idx)) { + row_has_missing = miss_data[miss_idx]; + } + + // Per-path tree cache lookup + TreePtr tree_ptr; + auto it = bd.tree_cache.find(tree_path); + if (it == bd.tree_cache.end()) { + TreePtr new_tree; + try { + new_tree = std::make_shared(0, tree_path); + } catch (const std::exception &e) { + throw InvalidInputException( + "tree_predict: failed to load/parse tree file '%s': %s", + tree_path.c_str(), e.what()); + } + it = bd.tree_cache.emplace(tree_path, new_tree).first; + } + tree_ptr = it->second; + const Tree &tree = *tree_ptr; + + // Prediction + float pred; + if (row_has_missing) { + pred = tree.PredictSingleMissing(row_buf.data()); } else { - pred = tree.predictSingle(row_base); + pred = tree.PredictSingle(row_buf.data()); } out[i] = pred; } @@ -347,7 +409,11 @@ void ML_DecisionTree::Register(ExtensionLoader &loader) { }, LogicalType::FLOAT, Execute); + fn.bind = Bind; + // Reads external files and depends on path contents; treat as volatile. + fn.stability = FunctionStability::VOLATILE; + loader.RegisterFunction(fn); } diff --git a/src/optimization/CMakeLists.txt b/src/optimization/CMakeLists.txt index 427c006..3d3a306 100644 --- a/src/optimization/CMakeLists.txt +++ b/src/optimization/CMakeLists.txt @@ -9,7 +9,7 @@ list(APPEND EXTENSION_SOURCES #All Actions ${CMAKE_CURRENT_SOURCE_DIR}/actions/MatMulDense2SparseRewriteAction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/actions/MultiLayerUDF2TorchNNRewriteAction.cpp - # ${CMAKE_CURRENT_SOURCE_DIR}/actions/DecisionForestUDF2RelationRewriteAction.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/actions/DecisionForestUDF2RelationRewriteAction.cpp #Feature Extraction Helpers ${CMAKE_CURRENT_SOURCE_DIR}/feature_extraction/query2vec/query_annotation.cpp diff --git a/src/optimization/actions/DecisionForestUDF2RelationRewriteAction.cpp b/src/optimization/actions/DecisionForestUDF2RelationRewriteAction.cpp index bab9ff8..410ded4 100644 --- a/src/optimization/actions/DecisionForestUDF2RelationRewriteAction.cpp +++ b/src/optimization/actions/DecisionForestUDF2RelationRewriteAction.cpp @@ -4,6 +4,7 @@ #include "duckdb/catalog/catalog.hpp" #include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp" +#include "duckdb/catalog/catalog_entry/aggregate_function_catalog_entry.hpp" #include "duckdb/common/constants.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/common/types/value.hpp" @@ -14,11 +15,14 @@ #include "duckdb/planner/expression/bound_operator_expression.hpp" #include "duckdb/planner/expression/bound_case_expression.hpp" #include "duckdb/planner/expression/bound_comparison_expression.hpp" +#include "duckdb/planner/expression/bound_aggregate_expression.hpp" #include "duckdb/planner/operator/logical_projection.hpp" #include "duckdb/planner/operator/logical_get.hpp" #include "duckdb/planner/operator/logical_cross_product.hpp" #include "duckdb/planner/operator/logical_aggregate.hpp" #include "duckdb/planner/expression_iterator.hpp" +#include "duckdb/parser/tableref/table_function_ref.hpp" +#include "duckdb/function/table_function.hpp" #include "ml_functions/decision_forest.hpp" #include "ml_functions/decision_tree.hpp" @@ -35,8 +39,7 @@ namespace fs = std::filesystem; // --------------------------------------------------------------------------- // Enumerate tree files in a forest folder (like Velox Forest::vectorizeForestFolder) -static bool ListForestTreeFiles(const string &forest_path, - vector &out_paths) { +static bool ListForestTreeFiles(const string &forest_path, vector &out_paths) { std::error_code ec; if (!fs::exists(forest_path, ec) || !fs::is_directory(forest_path, ec)) { return false; @@ -56,15 +59,15 @@ static bool ListForestTreeFiles(const string &forest_path, // Find a top-level decision_forest_predict(...) call in a LogicalProjection // Returns pointer to the BoundFunctionExpression and sets expr_idx_out -static BoundFunctionExpression *FindTopLevelForestCall(LogicalProjection &proj, - idx_t &expr_idx_out) { +static BoundFunctionExpression *FindTopLevelForestCall(LogicalProjection &proj, idx_t &expr_idx_out) { for (idx_t i = 0; i < proj.expressions.size(); i++) { auto &expr = *proj.expressions[i]; if (expr.expression_class != ExpressionClass::BOUND_FUNCTION) { continue; } auto &f = expr.Cast(); - if (StringUtil::CIEquals(f.function.name, "decision_forest_predict")) { + if (f.function.name == "decision_forest_predict") { + std::cout << "Found decision_forest_predict UDF call: " << f.ToString() << "\n"; expr_idx_out = i; return &f; } @@ -75,48 +78,68 @@ static BoundFunctionExpression *FindTopLevelForestCall(LogicalProjection &proj, // Build a LogicalGet over the forest_trees(forest_path) table function: // forest_trees(forest_path) -> columns: (tree_id INT, tree_path VARCHAR) -static unique_ptr BuildForestGet(ClientContext &context, - const string &forest_path) { - // Bind input to ML_ForestTable::Bind +static unique_ptr BuildForestGet(ClientContext &context, const string &forest_path) { + // Bind input (forest_path) vector bind_inputs; bind_inputs.emplace_back(Value(forest_path)); + // Define table function (same as in ML_ForestTable::Register) + TableFunction tf("forest_trees", + {LogicalType::VARCHAR}, // forest_path + ML_ForestTable::Function, ML_ForestTable::Bind, ML_ForestTable::InitGlobal); + + // Return types & names will be populated by Bind vector return_types; vector names; - TableFunctionBindInput tf_input(bind_inputs, {}, nullptr); - // Reuse the same Bind logic as the registered table function + // Newer DuckDB TableFunctionBindInput signature + named_parameter_map_t named_parameters; + vector input_table_types; + vector input_table_names; + optional_ptr info(nullptr); + optional_ptr binder_ptr(nullptr); + TableFunctionRef tf_ref; + + TableFunctionBindInput tf_input(bind_inputs, named_parameters, input_table_types, input_table_names, info, + binder_ptr, tf, tf_ref); + auto bind_data = ML_ForestTable::Bind(context, tf_input, return_types, names); - // Define table function (same as in ML_ForestTable::Register) - TableFunction tf( - "forest_trees", - {LogicalType::VARCHAR}, // forest_path - ML_ForestTable::Function, - ML_ForestTable::Bind, - ML_ForestTable::InitGlobal); - - // table_index: arbitrary (extension-local) logical table id + // logical table id: any extension-local index is fine idx_t table_index = 0; + virtual_column_map_t virtual_columns; - auto get = make_uniq( - table_index, - std::move(return_types), - std::move(names), - std::move(bind_data), - tf); - + auto get = make_uniq(table_index, std::move(tf), std::move(bind_data), std::move(return_types), + std::move(names), std::move(virtual_columns)); + std::cout << "Built forest_trees GET over path: " << forest_path << "\n"; return std::move(get); } +// Look up AVG(FLOAT/DOUBLE) aggregate function from the catalog +static AggregateFunction GetAvgFloatAggregate(ClientContext &context) { + auto &catalog = Catalog::GetSystemCatalog(context); + auto &entry = + catalog.GetEntry(context, DEFAULT_SCHEMA, "avg"); + + // Pick the overload with FLOAT (or DOUBLE) argument + for (auto &fn : entry.functions.functions) { + if (fn.arguments.size() == 1 && + (fn.arguments[0].id() == LogicalTypeId::FLOAT || + fn.arguments[0].id() == LogicalTypeId::DOUBLE)) { + return fn; + } + } + throw InternalException("DecisionForest rewrite: AVG(FLOAT/DOUBLE) aggregate not found"); +} + // Core rewrite: // PROJECTION [ ..., decision_forest_predict(features, forest_path, num_feat, is_cls) AS cls ] // child // -// becomes: +// becomes (conceptually): // // PROJECTION [ group_keys..., cls ] -// AGGREGATE [ group_keys ] (SUM(pred) AS sum_pred) +// AGGREGATE [ group_keys ] (AVG(pred) AS avg_pred) // PROJECTION [ group_keys..., pred = tree_predict(features, tree_path, false) ] // CROSS_PRODUCT // child @@ -124,7 +147,6 @@ static unique_ptr BuildForestGet(ClientContext &context, // // For now we handle only the case where: // * the projection has exactly one forest call at top level -// * features arg is a BoundReferenceExpression (column) static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input, unique_ptr &plan) { if (!plan || plan->type != LogicalOperatorType::LOGICAL_PROJECTION) { @@ -134,6 +156,14 @@ static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input auto &proj = plan->Cast(); auto &context = input.context; + // Preserve the original projection's table index and aliases + auto original_table_index = proj.table_index; + vector original_aliases; + original_aliases.reserve(proj.expressions.size()); + for (auto &expr : proj.expressions) { + original_aliases.push_back(expr->alias); + } + // 1) Find the top-level decision_forest_predict(...) idx_t forest_idx; auto *forest_func = FindTopLevelForestCall(proj, forest_idx); @@ -141,13 +171,18 @@ static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input return false; // no forest UDF here } + std::cout << "Found the decision_forest_predict UDF in projection in application: " + << forest_func->ToString() << "\n"; + // 2) Get forest bind data (ML_DecisionForest::BindData) - auto *forest_bind_ptr = - dynamic_cast(forest_func->bind_info.get()); + auto *forest_bind_ptr = dynamic_cast(forest_func->bind_info.get()); if (!forest_bind_ptr) { - // unexpected bind type + // Not the expected bind data; bail return false; } + + std::cout << "Forest bind data \n"; + auto &dfb = *forest_bind_ptr; const string forest_path = dfb.forest_path; const bool is_classification = dfb.is_classification; @@ -156,23 +191,34 @@ static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input vector tree_paths; if (!ListForestTreeFiles(forest_path, tree_paths)) { // Can't enumerate; bail out for now + std::cout << "Failed to list tree files in forest path: " << forest_path << "\n"; return false; } const idx_t num_trees = tree_paths.size(); if (num_trees == 0) { + std::cout << "No tree files found in forest path: " << forest_path << "\n"; return false; } - // 4) Features arg must be present and be a BoundReferenceExpression + // 4) Features arg must be present (we now accept any bound expression) if (forest_func->children.empty()) { + std::cout << "decision_forest_predict has no arguments\n"; return false; } - if (forest_func->children[0]->expression_class != ExpressionClass::BOUND_REFERENCE) { - // For now only handle simple column ref; can be generalized later - return false; + if (!forest_func->children.empty()) { + std::cout << "forest_func child[0] class = " + << (int)forest_func->children[0]->expression_class + << ", expr = " << forest_func->children[0]->ToString() << "\n"; + } + if (forest_func->children[0]->expression_class != ExpressionClass::BOUND_REF) { + // Original debug logging retained + std::cout << "Features argument is not a BoundReferenceExpression\n"; + } else { + std::cout << "Features argument is a BoundReferenceExpression\n"; } - auto &feat_ref = forest_func->children[0]->Cast(); - const idx_t feat_col_idx = feat_ref.index; + + // Copy the original features expression as a generic bound expression + unique_ptr feat_expr_original = forest_func->children[0]->Copy(); // 5) Build right-hand side GET forest_trees(forest_path) auto right_get = BuildForestGet(context, forest_path); @@ -180,26 +226,28 @@ static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input // 6) Original child of projection becomes left side of CROSS_PRODUCT if (proj.children.empty()) { // malformed plan + std::cout << "Projection has no child\n"; return false; } auto left_child = std::move(proj.children[0]); // CROSS_PRODUCT(left_child, forest_trees) - auto cross = make_uniq( - std::move(left_child), - std::move(right_get)); + auto cross = make_uniq(std::move(left_child), std::move(right_get)); // After CROSS_PRODUCT schema: // [ all columns from left_child | tree_id, tree_path ] idx_t left_cols = cross->children[0]->types.size(); - idx_t tree_id_col_idx = left_cols + 0; + idx_t tree_id_col_idx = left_cols + 0; + (void)tree_id_col_idx; // not used right now idx_t tree_path_col_idx = left_cols + 1; + std::cout << "CROSS_PRODUCT schema: left_cols = " << left_cols + << ", tree_id_col_idx = " << tree_id_col_idx + << ", tree_path_col_idx = " << tree_path_col_idx << "\n"; + // 7) Build inner PROJECTION on top of CROSS_PRODUCT // // - group key columns: original projection expressions except the forest one - // (for now we approximate them as references to the first N columns - // of the left side; you can refine this mapping if you had computed exprs) // - plus pred = tree_predict(features, tree_path, false) vector> inner_proj_exprs; @@ -208,118 +256,153 @@ static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input // Keep all original non-forest expressions as group keys idx_t next_col_idx = 0; for (idx_t i = 0; i < proj.expressions.size(); i++) { + std::cout << "Processing original proj expr[" << i << "]: " + << proj.expressions[i]->ToString() << "\n"; if (i == forest_idx) { continue; } auto &orig = *proj.expressions[i]; - inner_proj_exprs.push_back(make_uniq( - orig.return_type, - next_col_idx)); + inner_proj_exprs.push_back( + make_uniq(orig.return_type, next_col_idx)); group_types.push_back(orig.return_type); next_col_idx++; } + std::cout << "Number of group key columns: " << group_types.size() << "\n"; + + // Build tree_predict(features_expr, tree_path, false) + + // We know the CROSS_PRODUCT schema is: +// [ all columns from left_child | tree_id, tree_path ] +// idx_t left_cols = cross->children[0]->types.size(); +// idx_t tree_path_col_idx = left_cols + 1; + +// 1) Figure out which column is "features" on the left side. +// In your current setup, the projection child is [id, features], +// so features is column index 1. +// For now we hard-code that, since this rule is specialized to your pattern. +idx_t features_col_idx = 1; + +// 2) Lookup tree_predict(...) function from the catalog +auto &catalog = Catalog::GetSystemCatalog(context); +auto &tree_entry = + catalog.GetEntry(context, DEFAULT_SCHEMA, "tree_predict"); + +const ScalarFunction *tree_func_ptr = nullptr; +for (auto &fn : tree_entry.functions.functions) { + if (fn.arguments.size() == 3 && + fn.arguments[0] == LogicalType::LIST(LogicalType::FLOAT) && + fn.arguments[1].id() == LogicalTypeId::VARCHAR && + fn.arguments[2].id() == LogicalTypeId::BOOLEAN && + fn.return_type.id() == LogicalTypeId::FLOAT) { + tree_func_ptr = &fn; + break; + } +} +if (!tree_func_ptr) { + throw InternalException( + "DecisionForest rewrite: tree_predict(LIST(FLOAT), VARCHAR, BOOLEAN) not found"); +} - // Build tree_predict(features, tree_path, false) - - // features: still at feat_col_idx from left side - auto feat_ref_in_cross = make_uniq( - feat_ref.return_type, - feat_col_idx); - - // tree_path: comes from right side - auto tree_path_ref_in_cross = make_uniq( - LogicalType::VARCHAR, - tree_path_col_idx); - - // has_missing = false - auto has_missing_expr = make_uniq(Value::BOOLEAN(false)); - - // Lookup tree_predict(...) function from catalog - auto &catalog = Catalog::GetSystemCatalog(context); - auto &tree_entry = catalog.GetEntry( - context, DEFAULT_SCHEMA, "tree_predict"); - - const ScalarFunction *tree_func_ptr = nullptr; - for (auto &fn : tree_entry.functions.functions) { - if (fn.arguments.size() == 3 && - fn.arguments[0] == LogicalType::LIST(LogicalType::FLOAT) && - fn.arguments[1].id() == LogicalTypeId::VARCHAR && - fn.arguments[2].id() == LogicalTypeId::BOOLEAN && - fn.return_type.id() == LogicalTypeId::FLOAT) { - tree_func_ptr = &fn; - break; - } - } - if (!tree_func_ptr) { - throw InternalException("DecisionForest rewrite: tree_predict(LIST(FLOAT), VARCHAR, BOOLEAN) not found"); - } - auto tree_func = *tree_func_ptr; - - // Prepare children for the bound function expression - vector> tree_children; - tree_children.push_back(feat_ref_in_cross->Copy()); - tree_children.push_back(tree_path_ref_in_cross->Copy()); - tree_children.push_back(has_missing_expr->Copy()); - - // For Bind we need a separate copy of the arguments - vector> args_for_bind; - args_for_bind.push_back(std::move(feat_ref_in_cross)); - args_for_bind.push_back(std::move(tree_path_ref_in_cross)); - args_for_bind.push_back(std::move(has_missing_expr)); - - auto tree_bind = ML_DecisionTree::Bind(context, tree_func, args_for_bind); - - auto tree_pred_expr = make_uniq( - LogicalType::FLOAT, - tree_func, - std::move(tree_children), - std::move(tree_bind)); - +// Make a *non-const* copy so we can pass it to Bind +ScalarFunction tree_func = *tree_func_ptr; + +// 3) Build children for tree_predict(features, tree_path, false) + +// features: directly reference the LIST(FLOAT) column from CROSS_PRODUCT +auto feat_ref_for_child = + make_uniq(LogicalType::LIST(LogicalType::FLOAT), + features_col_idx); +auto feat_ref_for_bind = + make_uniq(LogicalType::LIST(LogicalType::FLOAT), + features_col_idx); + +// tree_path: VARCHAR column from CROSS_PRODUCT +auto tree_path_ref_for_child = + make_uniq(LogicalType::VARCHAR, tree_path_col_idx); +auto tree_path_ref_for_bind = + make_uniq(LogicalType::VARCHAR, tree_path_col_idx); + +// has_missing: FALSE literal +auto has_missing_child = + make_uniq(Value::BOOLEAN(false)); +auto has_missing_bind = + make_uniq(Value::BOOLEAN(false)); + +// Children that will be stored inside the BoundFunctionExpression +vector> tree_children; +tree_children.push_back(std::move(feat_ref_for_child)); +tree_children.push_back(std::move(tree_path_ref_for_child)); +tree_children.push_back(std::move(has_missing_child)); + +// Arguments passed to the Bind function +vector> args_for_bind; +args_for_bind.push_back(std::move(feat_ref_for_bind)); +args_for_bind.push_back(std::move(tree_path_ref_for_bind)); +args_for_bind.push_back(std::move(has_missing_bind)); + +// 4) Call ML_DecisionTree::Bind to produce bind_info +auto tree_bind = ML_DecisionTree::Bind(context, tree_func, args_for_bind); + +// 5) Create the BoundFunctionExpression for tree_predict(...) +auto tree_pred_expr = make_uniq( + tree_func.return_type, // should be FLOAT + tree_func, + std::move(tree_children), + std::move(tree_bind)); // Append prediction as last column of inner projection inner_proj_exprs.push_back(std::move(tree_pred_expr)); - auto inner_proj = make_uniq( - std::move(cross), - std::move(inner_proj_exprs)); + // Build LogicalProjection with the new API (table_index + select_list) + idx_t inner_table_index = 0; + auto inner_proj = + make_uniq(inner_table_index, std::move(inner_proj_exprs)); + inner_proj->children.push_back(std::move(cross)); // 8) Build AGGREGATE on top of inner_proj: - // GROUP BY all group_types, AGG: SUM(pred) AS sum_pred - vector> group_exprs; - vector> aggregate_exprs; + // SELECT group_keys..., AVG(pred) + // + // LogicalAggregate takes a select_list of expressions, where: + // - [0..group_count-1] are group keys + // - [group_count..] are BoundAggregateExpression(s) + vector> aggregate_select; - // group keys: references [0..group_types.size()-1] + // group keys: references [0..group_types.size()-1] of inner_proj output for (idx_t i = 0; i < group_types.size(); i++) { - group_exprs.push_back(make_uniq( - group_types[i], - i)); + aggregate_select.push_back( + make_uniq(group_types[i], i)); } - // prediction column index + // prediction column index in inner_proj idx_t pred_idx = group_types.size(); - aggregate_exprs.push_back(make_uniq( - LogicalType::FLOAT, - pred_idx)); - - // Create LogicalAggregate; we give it the child, group exprs, and aggregate exprs. - // DuckDB will expect the aggregate expressions to be BoundAggregateExpression. - // Here we treat aggregate_exprs as arguments to SUM later; we will fill - // aggregate_functions / aggregate_types to keep the plan consistent. - auto aggregate = make_uniq( - std::move(inner_proj), - std::move(group_exprs), - std::move(aggregate_exprs)); - // Fill aggregate function metadata: SUM(FLOAT) - vector agg_funcs; - vector agg_types; + // children for AVG: just reference the prediction column + vector> avg_children; + avg_children.push_back( + make_uniq(tree_func.return_type, pred_idx)); + + // lookup AVG(FLOAT/DOUBLE) + auto avg_fun = GetAvgFloatAggregate(context); + auto avg_type = avg_fun.return_type; + + // no filter, no bind_info + unique_ptr avg_filter; + unique_ptr avg_bind_info; + AggregateType agg_type = AggregateType::NON_DISTINCT; - auto sum_fun = AggregateFunction::GetAggregateFunction("sum", {LogicalType::FLOAT}); - agg_funcs.push_back(sum_fun); - agg_types.push_back(LogicalType::FLOAT); + auto avg_agg = make_uniq( + avg_fun, std::move(avg_children), std::move(avg_filter), + std::move(avg_bind_info), agg_type); - aggregate->group_types = group_types; - aggregate->aggregate_types = agg_types; - aggregate->aggregate_functions = agg_funcs; + // append AVG(pred) to select list + aggregate_select.push_back(std::move(avg_agg)); + + // group_index = 0, aggregate_index = group_count + idx_t group_index = 0; + idx_t aggregate_index = group_types.size(); + + auto aggregate = make_uniq( + group_index, aggregate_index, std::move(aggregate_select)); + aggregate->children.push_back(std::move(inner_proj)); // 9) Final projection on top: // - group key columns (restored as they were) @@ -328,29 +411,14 @@ static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input // group keys: references [0..group_types.size()-1] of aggregate output for (idx_t i = 0; i < group_types.size(); i++) { - final_proj_exprs.push_back(make_uniq( - group_types[i], - i)); + final_proj_exprs.push_back( + make_uniq(group_types[i], i)); } - // sum_pred is at col index = group_types.size() - idx_t sum_idx = group_types.size(); - auto sum_ref = make_uniq( - LogicalType::FLOAT, - sum_idx); - - // avg_pred = sum_pred / num_trees - auto denom_val = Value::FLOAT(static_cast(num_trees)); - auto denom_expr = make_uniq(denom_val); - - vector> div_children; - div_children.push_back(std::move(sum_ref)); - div_children.push_back(std::move(denom_expr)); - - auto avg_expr = make_uniq( - ExpressionType::OPERATOR_DIVIDE, - LogicalType::FLOAT, - std::move(div_children)); + // avg_pred is at col index = group_types.size() + idx_t avg_idx = group_types.size(); + auto avg_ref = + make_uniq(avg_type, avg_idx); unique_ptr forest_result_expr; @@ -360,29 +428,56 @@ static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input auto zero_expr = make_uniq(zero_val); auto cond = make_uniq( - ExpressionType::COMPARE_GREATER, - avg_expr->Copy(), + ExpressionType::COMPARE_GREATERTHAN, avg_ref->Copy(), std::move(zero_expr)); - auto one_out = make_uniq(Value::FLOAT(1.0f)); + auto one_out = make_uniq(Value::FLOAT(1.0f)); auto zero_out = make_uniq(Value::FLOAT(0.0f)); forest_result_expr = make_uniq( - LogicalType::FLOAT, - std::move(cond), - std::move(one_out), - std::move(zero_out)); + std::move(cond), std::move(one_out), std::move(zero_out)); } else { - forest_result_expr = std::move(avg_expr); + forest_result_expr = std::move(avg_ref); } final_proj_exprs.push_back(std::move(forest_result_expr)); - auto final_proj = make_uniq( - std::move(aggregate), - std::move(final_proj_exprs)); + // Use the same table_index as the original projection so that + // existing bindings (e.g., ORDER BY feature_rows.id) remain valid. + auto final_proj = + make_uniq(original_table_index, std::move(final_proj_exprs)); + final_proj->children.push_back(std::move(aggregate)); + + // Restore column aliases so bindings by name still make sense. + // The final projection has: [all non-forest original expressions..., forest_result_expr] + idx_t new_col = 0; + for (idx_t i = 0; i < proj.expressions.size(); i++) { + if (i == forest_idx) { + continue; + } + if (new_col < final_proj->expressions.size()) { + final_proj->expressions[new_col]->alias = original_aliases[i]; + } + new_col++; + } + + // Alias for the forest result column (last one) + string forest_alias = original_aliases[forest_idx]; + if (forest_alias.empty()) { + // fall back to the original function alias or name + if (!forest_func->alias.empty()) { + forest_alias = forest_func->alias; + } else { + forest_alias = forest_func->function.name; + } + } + if (!final_proj->expressions.empty()) { + final_proj->expressions.back()->alias = forest_alias; + } // Replace whole subtree under this projection with the new rewritten plan + std::cout << "Rewrote decision_forest_predict UDF into CROSS_PRODUCT + AGGREGATE plan\n" + << final_proj->ToString() << "\n"; plan = std::move(final_proj); return true; } @@ -391,7 +486,7 @@ static bool RewriteForestProjectionToCrossProduct(OptimizerExtensionInput &input // Public API: check / apply // --------------------------------------------------------------------------- -bool DecisionForestUDF2RelationRewriteAction::check(OptimizerExtensionInput &, +bool DecisionForestUDF2RelationRewriteAction::check(OptimizerExtensionInput &input, unique_ptr &plan) { if (!plan) { return false; @@ -409,7 +504,7 @@ bool DecisionForestUDF2RelationRewriteAction::check(OptimizerExtensionInput &, // Recursively check children for (auto &child : plan->children) { - found |= DecisionForestUDF2RelationRewriteAction::check({}, child); + found |= DecisionForestUDF2RelationRewriteAction::check(input, child); } return found; } diff --git a/src/optimization/dynamic_optimizer.cpp b/src/optimization/dynamic_optimizer.cpp index 6646841..06b87b6 100644 --- a/src/optimization/dynamic_optimizer.cpp +++ b/src/optimization/dynamic_optimizer.cpp @@ -2,6 +2,7 @@ #include "optimization/dynamic_optimizer.hpp" #include "optimization/actions/MatMulDense2SparseRewriteAction.hpp" #include "optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp" +#include "optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp" #include "optimization/catalog.hpp" #include "cost_model/estimator.hpp" @@ -26,9 +27,14 @@ namespace duckdb{ // MatMulDense2SparseRewriteAction::apply(in, plan); // } - if(MultiLayerUDF2TorchNNRewriteAction::check(in, plan)){ - std::cout << "\nMultiLayerUDF2TorchNNRewriteAction is applicable \n"; - MultiLayerUDF2TorchNNRewriteAction::apply(in, plan); + // if(MultiLayerUDF2TorchNNRewriteAction::check(in, plan)){ + // std::cout << "\nMultiLayerUDF2TorchNNRewriteAction is applicable \n"; + // MultiLayerUDF2TorchNNRewriteAction::apply(in, plan); + // } + + if(DecisionForestUDF2RelationRewriteAction::check(in, plan)){ + std::cout << "\nDecisionForestUDF2RelationRewriteAction is applicable \n"; + DecisionForestUDF2RelationRewriteAction::apply(in, plan); } // SimpleEstimator est(std::make_unique()); diff --git a/src/optimization/register_optimizers.cpp b/src/optimization/register_optimizers.cpp index 5215083..63dabba 100644 --- a/src/optimization/register_optimizers.cpp +++ b/src/optimization/register_optimizers.cpp @@ -13,6 +13,9 @@ #include #include +//delete later +#include "optimization/actions/MatMulDense2SparseRewriteAction.hpp" + namespace duckdb { // ----------------------------- @@ -71,11 +74,42 @@ struct CactusReplaceBindingOpt : public OptimizerExtension { struct CactusDynamicOpt : public OptimizerExtension { CactusDynamicOpt() { optimize_function = Run; } + static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { + // DumpPlanBase64(in.context, *plan, "./plans/initial_plan.duckdbplan"); + auto &db = DatabaseInstance::GetDatabase(in.context); + auto &cfg = DBConfig::GetConfig(db); + auto option = cfg.GetOptionByName("cactusdb_enable_optimizer"); + Value result; + in.context.TryGetCurrentSetting("cactusdb_enable_optimizer",result); + // if(option){ + // std::cout << "What is config value cactusdb_enable_optimizer: " + // << TryGetCurrentSettingInternal(option->name, result) << "\n"; + // } + // db.TryGetCurrentSetting("cactusdb_enable_optimizer", result); + std::cout << "Cactus Dynamic Optimizer - cactusdb_enable_optimizer: " << result.ToString() << "\n"; + std::string pretty = plan->ToString(); + std::cout << "\nInitial Plan:\n" << pretty << "\n"; + std::string opt_Setting = result.ToString(); + if(opt_Setting.find("1") != std::string::npos){ + MatMulDense2SparseRewriteAction::apply(in, plan); + } + if(opt_Setting.find("2") != std::string::npos){ + DynamicOpt::Optimize(in, plan); + } + // DumpPlanBase64(in.context, *plan, "./plans/final_plan.duckdbplan"); + pretty = plan->ToString(); + std::cout << "\nFinal Plan:\n" << pretty << "\n"; + } +}; + +struct CactusDynamicOpt1 : public OptimizerExtension { + CactusDynamicOpt1() { optimize_function = Run; } + static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { // DumpPlanBase64(in.context, *plan, "./plans/initial_plan.duckdbplan"); std::string pretty = plan->ToString(); std::cout << "\nInitial Plan:\n" << pretty << "\n"; - DynamicOpt::Optimize(in, plan); + MatMulDense2SparseRewriteAction::apply(in, plan); // DumpPlanBase64(in.context, *plan, "./plans/final_plan.duckdbplan"); pretty = plan->ToString(); std::cout << "\nFinal Plan:\n" << pretty << "\n"; @@ -92,7 +126,8 @@ void RegisterCactusOptimizers(DatabaseInstance &db) { // Typically do argument/string rewrites early, then other expression rewrites. // cfg.optimizer_extensions.push_back(CactusReplaceBindingOpt{}); // cfg.optimizer_extensions.push_back(CactusAdd5Opt{}); - // cfg.optimizer_extensions.push_back(CactusDynamicOpt{}); + cfg.optimizer_extensions.push_back(CactusDynamicOpt{}); + // cfg.optimizer_extensions.push_back(CactusDynamicOpt1{}); } } // namespace duckdb diff --git a/test/sql/decision_tree.test b/test/sql/decision_tree.test index 737d4ff..8b1e8f7 100644 --- a/test/sql/decision_tree.test +++ b/test/sql/decision_tree.test @@ -44,9 +44,9 @@ FROM ( ORDER BY 1 ); ---- -true -true -true +0 +1 +1 # ------------------------------------------------------------------ # B) MISSING-HANDLING: include NULLs and use has_missing = TRUE @@ -78,22 +78,22 @@ true # ------------------------------------------------------------------ # C) SANITY: stable across ORDER BY / re-evaluation -# Compare predictions from two identical queries (join on rowid) +# Compare predictions from two identical queries (join on stable row_number) # ------------------------------------------------------------------ statement ok CREATE TEMP TABLE preds1 AS -SELECT row_number() OVER () AS rid, +SELECT row_number() OVER (ORDER BY a) AS rid, tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) AS y FROM inputs -ORDER BY 1; +ORDER BY rid; statement ok CREATE TEMP TABLE preds2 AS -SELECT row_number() OVER () AS rid, +SELECT row_number() OVER (ORDER BY a) AS rid, tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) AS y FROM inputs -ORDER BY 1; +ORDER BY rid; # All rows should match exactly query I @@ -105,6 +105,6 @@ FROM ( ORDER BY 1 ); ---- -true -true -true +1 +1 +1 diff --git a/test/sql/extension_test.test b/test/sql/extension_test.test new file mode 100644 index 0000000..17890b1 --- /dev/null +++ b/test/sql/extension_test.test @@ -0,0 +1,24 @@ +# name: test/sql/table_function/duckdb_settings_extension.test +# description: Test duckdb_settings function with extensions +# group: [table_function] + +statement ok +SET default_null_order='nulls_first'; + +require parquet + +statement ok +SELECT * FROM duckdb_settings(); + +query II +SELECT name, value FROM duckdb_settings() WHERE name='default_null_order'; +---- +default_null_order NULLS_FIRST + +statement ok +SET default_null_order='nulls_last' + +query II +SELECT name, value FROM duckdb_settings() WHERE name='default_null_order'; +---- +default_null_order NULLS_LAST \ No newline at end of file From ccab522736caf5de3a692cd9bde5799209618cfc Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Thu, 11 Dec 2025 13:04:46 -0700 Subject: [PATCH 13/18] Catalog and synthetic query added --- .gitignore | 2 + log.txt | 233 +++++++++++ queries/synthetic_query/model_generation.py | 192 +++++++++ queries/synthetic_query/synthetic_query.sql | 42 ++ queries/synthetic_query/table_generation.py | 254 ++++++++++++ src/cactusdb_extension.cpp | 2 +- .../MLDecompositionPushdownRewriteAction.hpp | 22 ++ src/include/optimization/metric_catalog.hpp | 103 +++++ src/ml_functions/matrix_multiplication.cpp | 268 ++++++------- src/optimization/CMakeLists.txt | 1 + .../MLDecompositionPushdownRewriteAction.cpp | 373 ++++++++++++++++++ src/optimization/dynamic_optimizer.cpp | 12 +- src/optimization/register_optimizers.cpp | 91 ++++- test/sql/ml_decomposition_pushdown.test | 251 ++++++++++++ 14 files changed, 1690 insertions(+), 156 deletions(-) create mode 100644 log.txt create mode 100644 queries/synthetic_query/model_generation.py create mode 100644 queries/synthetic_query/synthetic_query.sql create mode 100644 queries/synthetic_query/table_generation.py create mode 100644 src/include/optimization/actions/MLDecompositionPushdownRewriteAction.hpp create mode 100644 src/include/optimization/metric_catalog.hpp create mode 100644 src/optimization/actions/MLDecompositionPushdownRewriteAction.cpp create mode 100644 test/sql/ml_decomposition_pushdown.test diff --git a/.gitignore b/.gitignore index dbaa421..739dac8 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ mydb.duckdb plans/ *.json archived_tests/* +queries/synthetic_query/*.csv +queries/synthetic_query/*.db diff --git a/log.txt b/log.txt new file mode 100644 index 0000000..baa85ee --- /dev/null +++ b/log.txt @@ -0,0 +1,233 @@ + +[CactusDynamicOpt] Initial Plan: +┌───────────────────────────┐ +│ ATTACH │ +│ ──────────────────── │ +└───────────────────────────┘ + + +[CactusDynamicOpt] Final Plan: +┌───────────────────────────┐ +│ ATTACH │ +│ ──────────────────── │ +└───────────────────────────┘ + + +[CactusDynamicOpt] Initial Plan: +┌───────────────────────────┐ +│ SET │ +│ ──────────────────── │ +└───────────────────────────┘ + + +[CactusDynamicOpt] Final Plan: +┌───────────────────────────┐ +│ SET │ +│ ──────────────────── │ +└───────────────────────────┘ + + +[CactusDynamicOpt] Initial Plan: +┌───────────────────────────┐ +│ SET │ +│ ──────────────────── │ +└───────────────────────────┘ + + +[CactusDynamicOpt] Final Plan: +┌───────────────────────────┐ +│ SET │ +│ ──────────────────── │ +└───────────────────────────┘ + + +[CactusDynamicOpt] Initial Plan: +┌───────────────────────────┐ +│ SET │ +│ ──────────────────── │ +└───────────────────────────┘ + + +[CactusDynamicOpt] Final Plan: +┌───────────────────────────┐ +│ SET │ +│ ──────────────────── │ +└───────────────────────────┘ + + +[CactusDynamicOpt] Initial Plan: +┌───────────────────────────┐ +│ ORDER_BY │ +│ ──────────────────── │ +│ s.impression_id │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ PROJECTION │ +│ ──────────────────── │ +│ Expressions: │ +│ impression_id │ +│ listing_row_id │ +│ property_type │ +│ ml_argmax(cdb_softmax │ +│ (mat_add(mat_mul(mat_add │ +│ (mat_mul(list_concat │ +│ (user_profile_vec, │ +│ search_context_vec, │ +│ listing_feature_vec), ' │ +│ /home/local/ASUAD/jrtandel│ +│ /cactusdb-duckdb-extension│ +│ /queries/synthetic_query │ +│ /nn_params_150_512_2/nn_W1│ +│ .csv', 'dense'), '/home │ +│ /local/ASUAD/jrtandel │ +│ /cactusdb-duckdb-extension│ +│ /queries/synthetic_query │ +│ /nn_params_150_512_2/nn_b1│ +│ .csv'), '/home/local/ASUAD│ +│ /jrtandel/cactusdb-duckdb │ +│ -extension/queries │ +│ /synthetic_query │ +│ /nn_params_150_512_2/nn_W2│ +│ .csv', 'dense'), '/home │ +│ /local/ASUAD/jrtandel │ +│ /cactusdb-duckdb-extension│ +│ /queries/synthetic_query │ +│ /nn_params_150_512_2/nn_b2│ +│ .csv'))) │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ COMPARISON_JOIN │ +│ ──────────────────── │ +│ Join Type: INNER │ +│ ├──────────────┐ +│ Conditions: │ │ +│ (listing_id = listing_id) │ │ +└─────────────┬─────────────┘ │ +┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +│ SEQ_SCAN ││ SEQ_SCAN │ +│ ──────────────────── ││ ──────────────────── │ +│ Table: ││ Table: │ +│ search_impressions ││ listing_metadata │ +│ ││ │ +│ Type: Sequential Scan ││ Type: Sequential Scan │ +└───────────────────────────┘└───────────────────────────┘ + + +[CactusDynamicOpt] Final Plan: +┌───────────────────────────┐ +│ ORDER_BY │ +│ ──────────────────── │ +│ s.impression_id │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ PROJECTION │ +│ ──────────────────── │ +│ Expressions: │ +│ impression_id │ +│ listing_row_id │ +│ property_type │ +│ #5 │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ +│ COMPARISON_JOIN │ +│ ──────────────────── │ +│ Join Type: INNER │ +│ ├──────────────┐ +│ Conditions: │ │ +│ (listing_id = listing_id) │ │ +└─────────────┬─────────────┘ │ +┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +│ PROJECTION ││ SEQ_SCAN │ +│ ──────────────────── ││ ──────────────────── │ +│ Expressions: ││ Table: │ +│ #0 ││ listing_metadata │ +│ #1 ││ │ +│ #2 ││ Type: Sequential Scan │ +│ #3 ││ │ +│ #4 ││ │ +│ ml_argmax(cdb_softmax ││ │ +│ (mat_add(mat_mul(mat_add ││ │ +│ (mat_mul(list_concat ││ │ +│ (user_profile_vec, ││ │ +│ search_context_vec, ││ │ +│ listing_feature_vec), ' ││ │ +│ /home/local/ASUAD/jrtandel││ │ +│ /cactusdb-duckdb-extension││ │ +│ /queries/synthetic_query ││ │ +│ /nn_params_150_512_2/nn_W1││ │ +│ .csv', 'sparse'), '/home ││ │ +│ /local/ASUAD/jrtandel ││ │ +│ /cactusdb-duckdb-extension││ │ +│ /queries/synthetic_query ││ │ +│ /nn_params_150_512_2/nn_b1││ │ +│ .csv'), '/home/local/ASUAD││ │ +│ /jrtandel/cactusdb-duckdb ││ │ +│ -extension/queries ││ │ +│ /synthetic_query ││ │ +│ /nn_params_150_512_2/nn_W2││ │ +│ .csv', 'sparse'), '/home ││ │ +│ /local/ASUAD/jrtandel ││ │ +│ /cactusdb-duckdb-extension││ │ +│ /queries/synthetic_query ││ │ +│ /nn_params_150_512_2/nn_b2││ │ +│ .csv'))) ││ │ +└─────────────┬─────────────┘└───────────────────────────┘ +┌─────────────┴─────────────┐ +│ SEQ_SCAN │ +│ ──────────────────── │ +│ Table: │ +│ search_impressions │ +│ │ +│ Type: Sequential Scan │ +└───────────────────────────┘ + +┌───────────────┬────────────────┬───────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ impression_id │ listing_row_id │ property_type │ ml_argmax(cdb_softmax(mat_add(mat_mul(mat_add(mat_mul(list_concat(s.user_profile_vec, s.search_context_vec, s.listing_feature_vec), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_W1.csv', 'dense'), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_b1.csv'), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_W2.csv', 'dense'), '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_b2.csv'))) │ +│ int64 │ int64 │ int64 │ int32 │ +├───────────────┼────────────────┼───────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ 0 │ 74026 │ 34 │ 1 │ +│ 0 │ 146251 │ 9 │ 1 │ +│ 0 │ 120994 │ 41 │ 1 │ +│ 0 │ 138687 │ 31 │ 1 │ +│ 0 │ 124436 │ 45 │ 1 │ +│ 0 │ 148069 │ 19 │ 1 │ +│ 0 │ 122560 │ 36 │ 1 │ +│ 0 │ 163553 │ 22 │ 1 │ +│ 0 │ 191611 │ 6 │ 1 │ +│ 0 │ 140026 │ 8 │ 1 │ +│ 0 │ 112396 │ 32 │ 1 │ +│ 0 │ 91592 │ 6 │ 1 │ +│ 0 │ 182195 │ 41 │ 1 │ +│ 0 │ 141028 │ 7 │ 1 │ +│ 0 │ 105511 │ 40 │ 1 │ +│ 0 │ 63623 │ 0 │ 1 │ +│ 0 │ 192415 │ 37 │ 1 │ +│ 0 │ 97952 │ 8 │ 1 │ +│ 0 │ 181131 │ 31 │ 1 │ +│ 0 │ 172611 │ 39 │ 1 │ +│ · │ · │ · │ · │ +│ · │ · │ · │ · │ +│ · │ · │ · │ · │ +│ 499999 │ 144233 │ 0 │ 1 │ +│ 499999 │ 121415 │ 5 │ 1 │ +│ 499999 │ 69362 │ 9 │ 1 │ +│ 499999 │ 157211 │ 8 │ 1 │ +│ 499999 │ 153869 │ 29 │ 1 │ +│ 499999 │ 128390 │ 17 │ 1 │ +│ 499999 │ 7499 │ 6 │ 1 │ +│ 499999 │ 35630 │ 35 │ 1 │ +│ 499999 │ 68698 │ 1 │ 1 │ +│ 499999 │ 179187 │ 4 │ 1 │ +│ 499999 │ 12742 │ 45 │ 1 │ +│ 499999 │ 136334 │ 19 │ 1 │ +│ 499999 │ 66967 │ 42 │ 1 │ +│ 499999 │ 132220 │ 26 │ 1 │ +│ 499999 │ 63892 │ 19 │ 1 │ +│ 499999 │ 12500 │ 14 │ 1 │ +│ 499999 │ 134088 │ 42 │ 1 │ +│ 499999 │ 181000 │ 36 │ 1 │ +│ 499999 │ 63209 │ 2 │ 1 │ +│ 499999 │ 172703 │ 31 │ 1 │ +├───────────────┴────────────────┴───────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ 20006670 rows (40 shown) 4 columns │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/queries/synthetic_query/model_generation.py b/queries/synthetic_query/model_generation.py new file mode 100644 index 0000000..3273480 --- /dev/null +++ b/queries/synthetic_query/model_generation.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +import argparse +import os +from pathlib import Path + +import numpy as np + + +def parse_layers(s: str): + """ + Parse a comma-separated list of integers into layer sizes. + Example: "150,16,2" -> [150, 16, 2] + """ + parts = [p.strip() for p in s.split(",") if p.strip()] + if len(parts) < 2: + raise ValueError( + "You must specify at least input and output layer, e.g. '150,2' or '150,16,2'" + ) + try: + layers = [int(p) for p in parts] + except ValueError: + raise ValueError(f"Invalid layer sizes in --layers: {s}") + if any(d <= 0 for d in layers): + raise ValueError("All layer sizes must be positive integers") + return layers + + +def init_weights(in_dim, out_dim, init: str, scale: float): + """ + Initialize weight matrix of shape (in_dim, out_dim). + """ + if init == "normal": + # N(0, scale^2) + return np.random.normal(loc=0.0, scale=scale, size=(in_dim, out_dim)) + elif init == "uniform": + # U(-scale, scale) + return np.random.uniform(low=-scale, high=scale, size=(in_dim, out_dim)) + else: + raise ValueError(f"Unknown weight init '{init}'") + + +def init_bias(out_dim, bias_mode: str, scale: float): + """ + Initialize bias vector of shape (1, out_dim). + """ + if bias_mode == "zeros": + return np.zeros((1, out_dim), dtype=float) + elif bias_mode == "normal": + return np.random.normal(loc=0.0, scale=scale, size=(1, out_dim)) + elif bias_mode == "uniform": + return np.random.uniform(low=-scale, high=scale, size=(1, out_dim)) + else: + raise ValueError(f"Unknown bias mode '{bias_mode}'") + + +def save_matrix_csv(matrix: np.ndarray, path: Path, precision: int = 10): + """ + Save matrix to CSV with given precision, no header. + Each row = one line; values comma-separated. + """ + path.parent.mkdir(parents=True, exist_ok=True) + fmt = f"%.{precision}g" # good balance for DuckDB + not too huge + np.savetxt(path, matrix, delimiter=",", fmt=fmt) + + +def generate_params( + layers, + out_dir: Path, + prefix: str, + weight_init: str, + weight_scale: float, + bias_mode: str, + bias_scale: float, + precision: int, +): + """ + layers = [input_dim, hidden1, ..., output_dim] + For each consecutive pair (d_in, d_out) generate: + - weights: (d_in x d_out) -> {prefix}_W{idx}.csv + - bias: (1 x d_out) -> {prefix}_b{idx}.csv + where idx starts at 1. + """ + out_dir.mkdir(parents=True, exist_ok=True) + + print(f"Generating params in '{out_dir}' with prefix '{prefix}'") + print(f"Layers: {layers}") + for i in range(len(layers) - 1): + d_in = layers[i] + d_out = layers[i + 1] + layer_idx = i + 1 + + print(f" Layer {layer_idx}: {d_in} -> {d_out}") + + W = init_weights(d_in, d_out, init=weight_init, scale=weight_scale) + b = init_bias(d_out, bias_mode=bias_mode, scale=bias_scale) + + w_path = out_dir / f"{prefix}_W{layer_idx}.csv" + b_path = out_dir / f"{prefix}_b{layer_idx}.csv" + + save_matrix_csv(W, w_path, precision=precision) + save_matrix_csv(b, b_path, precision=precision) + + print(f" Weights: {w_path} (shape {W.shape})") + print(f" Biases : {b_path} (shape {b.shape})") + + print("Done.") + + +def main(): + parser = argparse.ArgumentParser( + description="Generate random NN weights/biases as CSVs for DuckDB mat_mul/mat_add." + ) + parser.add_argument( + "--layers", + type=str, + required=True, + help="Comma-separated layer sizes including input and output. " + "Example: '150,16,2' for 150→16→2.", + ) + parser.add_argument( + "--out-dir", + type=str, + default="nn_params", + help="Output directory for CSV files (default: nn_params).", + ) + parser.add_argument( + "--prefix", + type=str, + default="nn", + help="Prefix for filenames (default: 'nn').", + ) + parser.add_argument( + "--weight-init", + type=str, + choices=["normal", "uniform"], + default="normal", + help="Weight initialization distribution (default: normal).", + ) + parser.add_argument( + "--weight-scale", + type=float, + default=0.1, + help="Scale (stddev or range) for weight init (default: 0.1).", + ) + parser.add_argument( + "--bias-mode", + type=str, + choices=["zeros", "normal", "uniform"], + default="normal", + help="Bias initialization mode (default: zeros).", + ) + parser.add_argument( + "--bias-scale", + type=float, + default=0.1, + help="Scale for bias init when bias-mode is normal/uniform (default: 0.1).", + ) + parser.add_argument( + "--precision", + type=int, + default=10, + help="Number of significant digits in CSV output (default: 10).", + ) + parser.add_argument( + "--seed", + type=int, + default=None, + help="Random seed for reproducibility (default: None).", + ) + + args = parser.parse_args() + + if args.seed is not None: + np.random.seed(args.seed) + + layers = parse_layers(args.layers) + out_dir = Path(args.out_dir) + + generate_params( + layers=layers, + out_dir=out_dir, + prefix=args.prefix, + weight_init=args.weight_init, + weight_scale=args.weight_scale, + bias_mode=args.bias_mode, + bias_scale=args.bias_scale, + precision=args.precision, + ) + + +if __name__ == "__main__": + main() diff --git a/queries/synthetic_query/synthetic_query.sql b/queries/synthetic_query/synthetic_query.sql new file mode 100644 index 0000000..33f3e5d --- /dev/null +++ b/queries/synthetic_query/synthetic_query.sql @@ -0,0 +1,42 @@ +ATTACH '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/synthetic_database.db' + AS synthetic_db (READ_ONLY); + +SET schema 'synthetic_db.synthetic'; + +SET disabled_optimizers='expression_rewriter, empty_result_pullup, cte_filter_pusher, regex_range, in_clause, join_order, deliminator, unnest_rewriter, unused_columns, statistics_propagation, common_subexpressions, common_aggregate, column_lifetime, limit_pushdown, top_n, build_side_probe_side, compressed_materialization, duplicate_groups, reorder_filter, sampling_pushdown, join_filter_pushdown, materialized_cte, sum_rewriter, late_materialization, cte_inlining'; + +SET enable_extended_optimizer = '2'; + +SELECT + s.impression_id AS impression_id, + m.listing_row_id AS listing_row_id, + m.property_type AS property_type, + ml_argmax( + cdb_softmax( + -- layer 2: (h * W2) + b2 -> 1 x 2 logits + mat_add( + mat_mul( + -- layer 1: (x * W1) + b1 -> 1 x 16 hidden + mat_add( + mat_mul( + list_concat( + s.user_profile_vec, + s.search_context_vec, + s.listing_feature_vec + ), -- 150-dim feature vector + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_W1.csv', + 'dense' + ), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_b1.csv' + ), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_W2.csv', + 'dense' + ), + '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_b2.csv' + ) + ) + ) +FROM search_impressions AS s +JOIN listing_metadata AS m + USING (listing_id) +ORDER BY s.impression_id; diff --git a/queries/synthetic_query/table_generation.py b/queries/synthetic_query/table_generation.py new file mode 100644 index 0000000..db5acdc --- /dev/null +++ b/queries/synthetic_query/table_generation.py @@ -0,0 +1,254 @@ +import numpy as np +import pandas as pd +import duckdb + + +def generate_synthetic_tables_vector( + n_left=10_000, + n_right=5_000, + join_key_distinct=1_000, + feature_cols=("user_profile_vec", "search_context_vec", "listing_feature_vec"), + feature_dim=50, + feature_nnz_ratio=0.3, + zero_row_ratio=0.9, + left_other_distinct=None, + right_other_distinct=None, + overlap_fraction=1.0, # controls join cardinality + random_state=None, +): + """ + Generate two tables for join + sparse feature-vector experiments. + + Table search_impressions: + - impression_id: unique row id + - listing_id: join column + - feature_cols: each is a vector of length `feature_dim` (Python list) + so the full feature vector has len = len(feature_cols) * feature_dim + + Table listing_metadata: + - listing_row_id: unique row id + - listing_id: join column (same domain size as left, but with + controllable overlap) + - optional extra columns with controlled distinct counts. + + Parameters + ---------- + n_left, n_right : int + Number of rows in left / right tables. + join_key_distinct : int + Number of distinct values per table for the join_key domain (K). + overlap_fraction : float in [0,1] + Fraction of those K keys that are shared between left and right. + - 1.0 => full overlap (max join size, original behavior) + - 0.0 => disjoint domains (join cardinality ~ 0) + - in between => approximately linear scaling of join cardinality: + E[|L ⋈ R|] ≈ overlap_fraction * (n_left * n_right / K) + feature_cols : tuple[str] + Names of the feature columns in search_impressions. + feature_dim : int + Length of each feature column vector (e.g., 50). + feature_nnz_ratio : float in [0,1] + Target fraction of non-zero entries across ALL feature positions, + i.e. across shape (n_left, len(feature_cols), feature_dim), + including zero rows. + zero_row_ratio : float in [0,1] + Fraction of rows whose entire feature vector (all dims of all + feature_cols) is zero. + left_other_distinct, right_other_distinct : dict | None + Optional dict: column_name -> #distinct values for extra columns. + random_state : int | None + RNG seed. + + Returns + ------- + search_impressions : pd.DataFrame + listing_metadata : pd.DataFrame + summary : dict + Contains realized stats: + - left_nnz_ratio + - zero_rows_left + - join_key_distinct_left/right + - approx_inner_join_cardinality + - etc. + """ + rng = np.random.default_rng(random_state) + + # --- Left/right ids --- + left_ids = np.arange(n_left) + right_ids = np.arange(n_right) + + # --- Construct join domains with controllable overlap --- + K = int(join_key_distinct) + overlap_fraction = float(np.clip(overlap_fraction, 0.0, 1.0)) + + if overlap_fraction == 1.0: + # Full overlap: original behavior + left_domain = np.arange(K) + right_domain = np.arange(K) + elif overlap_fraction == 0.0: + # Disjoint domains: no key intersection => join cardinality ~ 0 + left_domain = np.arange(K) + right_domain = np.arange(K, 2 * K) + else: + K_overlap = max(1, int(round(overlap_fraction * K))) + # Shared keys: 0 .. K_overlap-1 + overlap_keys = np.arange(K_overlap) + + # Left-only keys: K_overlap .. K-1 + left_exclusive = np.arange(K_overlap, K) + + # Right-only keys: K .. K + (K - K_overlap) - 1 + right_exclusive = np.arange(K, K + (K - K_overlap)) + + left_domain = np.concatenate([overlap_keys, left_exclusive]) + right_domain = np.concatenate([overlap_keys, right_exclusive]) + + left_join = rng.choice(left_domain, size=n_left, replace=True) + right_join = rng.choice(right_domain, size=n_right, replace=True) + + # Real-world column names + left_data = {"impression_id": left_ids, "listing_id": left_join} + right_data = {"listing_row_id": right_ids, "listing_id": right_join} + + # --- Extra non-feature columns with controlled distinct counts --- + def add_extras(data_dict, n_rows, distinct_cfg): + if not distinct_cfg: + return + for col, n_dist in distinct_cfg.items(): + domain = np.arange(n_dist) + data_dict[col] = rng.choice(domain, size=n_rows, replace=True) + + add_extras(left_data, n_left, left_other_distinct) + add_extras(right_data, n_right, right_other_distinct) + + # --- Feature tensor: shape (n_left, num_feature_cols, feature_dim) --- + m = len(feature_cols) + d = feature_dim + total_positions = n_left * m * d + + feature_nnz_ratio = float(np.clip(feature_nnz_ratio, 0.0, 1.0)) + zero_row_ratio = float(np.clip(zero_row_ratio, 0.0, 1.0)) + + # Decide which rows are fully zero + zero_row_mask = rng.random(n_left) < zero_row_ratio + n_zero_rows = int(zero_row_mask.sum()) + n_active_rows = n_left - n_zero_rows + + active_positions = n_active_rows * m * d + if active_positions == 0: + per_pos_prob = 0.0 + else: + target_nnz = feature_nnz_ratio * total_positions + per_pos_prob = float(np.clip(target_nnz / active_positions, 0.0, 1.0)) + + # Initialize feature tensor with zeros + feat_tensor = np.zeros((n_left, m, d), dtype=float) + + # Fill active rows with Bernoulli mask * N(0,1) values + if n_active_rows > 0 and per_pos_prob > 0.0: + active_idx = np.where(~zero_row_mask)[0] + mask = rng.random((n_active_rows, m, d)) < per_pos_prob + values = rng.normal(loc=0.0, scale=1.0, size=(n_active_rows, m, d)) + feat_tensor[active_idx] = mask * values + + # Attach feature columns to left_data as Python lists of length `feature_dim` + for j, col in enumerate(feature_cols): + left_data[col] = [feat_tensor[i, j, :].tolist() for i in range(n_left)] + + search_impressions = pd.DataFrame(left_data) + listing_metadata = pd.DataFrame(right_data) + + # --- Realized stats --- + nnz = int(np.count_nonzero(feat_tensor)) + left_nnz_ratio = nnz / total_positions if total_positions > 0 else 0.0 + + row_sums = np.abs(feat_tensor).sum(axis=(1, 2)) + zero_rows_left = float((row_sums == 0).mean()) + + # still using old summary keys for backwards-compat; now refer to listing_id + join_key_distinct_left = int(search_impressions["listing_id"].nunique()) + join_key_distinct_right = int(listing_metadata["listing_id"].nunique()) + + join_counts_left = search_impressions["listing_id"].value_counts() + join_counts_right = listing_metadata["listing_id"].value_counts() + approx_inner_join_cardinality = int( + ( + join_counts_left.to_frame("l") + .join(join_counts_right.to_frame("r"), how="inner") + .fillna(0) + .eval("l * r") + .sum() + ) + ) + + # theoretical max join cardinality with full overlap, for reference + max_expected_join = (n_left * n_right) / max(1, K) + expected_join_given_overlap = overlap_fraction * max_expected_join + + summary = { + "left_nnz_ratio": left_nnz_ratio, # global nnz over 3×50 vector + "zero_rows_left": zero_rows_left, # fraction of fully-zero rows + "per_pos_prob_active_rows": per_pos_prob, + "n_zero_rows_left": n_zero_rows, + "feature_dim": d, + "join_key_distinct_left": join_key_distinct_left, + "join_key_distinct_right": join_key_distinct_right, + "approx_inner_join_cardinality": approx_inner_join_cardinality, + "max_expected_join_full_overlap": max_expected_join, + "expected_join_given_overlap": expected_join_given_overlap, + "overlap_fraction": overlap_fraction, + } + + return search_impressions, listing_metadata, summary + + +if __name__ == "__main__": + # 1) Generate synthetic tables + search_impressions, listing_metadata, stats = generate_synthetic_tables_vector( + n_left=50_0000, # 500k + n_right=20_0000, # 200k + join_key_distinct=5000, + feature_cols=("user_profile_vec", "search_context_vec", "listing_feature_vec"), + feature_dim=50, + feature_nnz_ratio=0.0002, + zero_row_ratio=0.98, + left_other_distinct={"search_segment": 10}, + right_other_distinct={"property_type": 50}, + overlap_fraction=1000, # will be clipped to 1.0 by np.clip + random_state=42, + ) + + print(stats) + + # Optionally keep CSV names aligned with table names + search_impressions.to_csv("search_impressions.csv", index=False) + listing_metadata.to_csv("listing_metadata.csv", index=False) + + # 2) Path where you want your .db file + db_path = "/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/synthetic_database.db" + + # 3) Create DuckDB file and store tables + con = duckdb.connect(db_path) # this creates the file if it doesn't exist + + # optional: create a separate schema for synthetic data + con.execute("CREATE SCHEMA IF NOT EXISTS synthetic;") + con.execute("SET schema 'synthetic';") + + # register DataFrames as temporary views + con.register("search_impressions_df", search_impressions) + con.register("listing_metadata_df", listing_metadata) + + # create persistent tables inside the .db file + con.execute("DROP TABLE IF EXISTS search_impressions;") + con.execute("DROP TABLE IF EXISTS listing_metadata;") + + con.execute( + "CREATE TABLE search_impressions AS SELECT * FROM search_impressions_df;" + ) + con.execute("CREATE TABLE listing_metadata AS SELECT * FROM listing_metadata_df;") + + # collect stats for better cardinality estimation + con.execute("ANALYZE;") + + con.close() + print("Created DuckDB file at:", db_path) diff --git a/src/cactusdb_extension.cpp b/src/cactusdb_extension.cpp index c80bfc6..186be78 100644 --- a/src/cactusdb_extension.cpp +++ b/src/cactusdb_extension.cpp @@ -18,7 +18,7 @@ static void LoadInternal(ExtensionLoader &loader) { // config.AddExtensionOption("cactusdb_enable_optimizers", "Enable All Optimizers", LogicalType::BOOLEAN, Value::BOOLEAN(true)); - config.AddExtensionOption("cactusdb_enable_optimizer", "Enable Specific Optimizer", LogicalType::VARCHAR, "2"); + config.AddExtensionOption("enable_extended_optimizer", "Enable Specific Optimizer", LogicalType::VARCHAR, ""); RegisterMLScalarFunctions(loader); diff --git a/src/include/optimization/actions/MLDecompositionPushdownRewriteAction.hpp b/src/include/optimization/actions/MLDecompositionPushdownRewriteAction.hpp new file mode 100644 index 0000000..956ab63 --- /dev/null +++ b/src/include/optimization/actions/MLDecompositionPushdownRewriteAction.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "duckdb.hpp" + +namespace duckdb { + +// Push mat_mul(...) closer to the base table: +// - Simple case: PROJECTION(mat_mul(...)) over a single child -> insert a +// projection below that projection that computes mat_mul, and replace the +// expression with a BoundReferenceExpression. +// - Join case: PROJECTION(mat_mul(...), other_cols) over a COMPARISON_JOIN: +// if mat_mul depends on exactly one table (say the left input), insert a +// projection on that join child that computes mat_mul, and replace the +// expression in the top projection with a reference to the new join output +// column. +class MLDecompositionPushdownRewriteAction { +public: + static bool check(OptimizerExtensionInput &input, unique_ptr &plan); + static bool apply(OptimizerExtensionInput &input, unique_ptr &plan); +}; + +} // namespace duckdb diff --git a/src/include/optimization/metric_catalog.hpp b/src/include/optimization/metric_catalog.hpp new file mode 100644 index 0000000..6f90436 --- /dev/null +++ b/src/include/optimization/metric_catalog.hpp @@ -0,0 +1,103 @@ +#pragma once + +#include "duckdb/common/types.hpp" +#include "duckdb/common/unordered_map.hpp" +#include "duckdb/common/string.hpp" + +namespace duckdb { + +// ================================ +// Schema-level metric container +// ================================ + +struct SchemaMetricSet { + // metric_name -> value + unordered_map values; + + bool Has(const string &metric_name) const { + return values.find(metric_name) != values.end(); + } + + // Get metric value or default if not present + double Get(const string &metric_name, double default_value = 0.0) const { + auto it = values.find(metric_name); + if (it == values.end()) { + return default_value; + } + return it->second; + } +}; + +// ================================ +// MetricCatalog: schema -> metrics +// ================================ + +// Simple singleton catalog hard-coded in the extension. +// Granularity: schema. Each schema has a map. +class MetricCatalog { +public: + // Global singleton instance + static const MetricCatalog &Get() { + static MetricCatalog instance; + return instance; + } + + // Get metrics for a specific schema (nullptr if not found) + const SchemaMetricSet *GetSchemaMetrics(const string &schema_name) const { + auto it = schema_metrics.find(schema_name); + if (it == schema_metrics.end()) { + return nullptr; + } + return &it->second; + } + + // Convenience: get single metric for a schema, with default + double GetMetric(const string &schema_name, + const string &metric_name, + double default_value = 0.0) const { + auto schema = GetSchemaMetrics(schema_name); + if (!schema) { + return default_value; + } + return schema->Get(metric_name, default_value); + } + +private: + MetricCatalog() { + Initialize(); + } + + void Initialize() { + // ---- Define metrics for each synthetic schema here ---- + // Example schema 1: synthetic dense features + { + SchemaMetricSet s; + s.values["join_ratio"] = 5e-5; // big joins + s.values["sparsity"] = 0.20; // 95% non-zero -> dense + schema_metrics["synthetic"] = std::move(s); + } + + // Example schema 2: synthetic sparse features + { + SchemaMetricSet s; + s.values["join_ratio"] = 5e-5; + s.values["sparsity"] = 0.10; // 10% non-zero -> sparse + schema_metrics["syn_sparse"] = std::move(s); + } + + // Add more schemas as needed: + // { + // SchemaMetricSet s; + // s.values["join_ratio"] = ...; + // s.values["sparsity"] = ...; + // s.values["some_other_metric"] = ...; + // schema_metrics["my_schema_name"] = std::move(s); + // } + } + +private: + // schema_name -> SchemaMetricSet + unordered_map schema_metrics; +}; + +} // namespace duckdb diff --git a/src/ml_functions/matrix_multiplication.cpp b/src/ml_functions/matrix_multiplication.cpp index ba455bc..d72bde9 100644 --- a/src/ml_functions/matrix_multiplication.cpp +++ b/src/ml_functions/matrix_multiplication.cpp @@ -165,8 +165,11 @@ unique_ptr ML_MatrixMultiply::Bind(ClientContext &context, void ML_MatrixMultiply::Execute(DataChunk &args, ExpressionState &state, Vector &result) { const idx_t count = args.size(); // tuples in this chunk + result.SetVectorType(VectorType::FLAT_VECTOR); - // Input LIST + // ---------------------------- + // 1) Read input LIST + // ---------------------------- Vector &lhs = args.data[0]; UnifiedVectorFormat lhs_uvf; lhs.ToUnifiedFormat(count, lhs_uvf); @@ -178,125 +181,69 @@ void ML_MatrixMultiply::Execute(DataChunk &args, ExpressionState &state, Vector child.ToUnifiedFormat(total_elems, child_uvf); const double *child_data = UnifiedVectorFormat::GetData(child_uvf); - // Bind data and dense weights mapping + // ---------------------------- + // 2) Bind data + weight matrix + // ---------------------------- const auto &func_expr = state.expr.Cast(); const auto &bd = func_expr.bind_info->Cast(); using RowMat = Eigen::Matrix; Eigen::Map W(bd.weights.data(), (Eigen::Index)bd.k, (Eigen::Index)bd.n); - // Determine width (k) and handle all-null case + // ---------------------------- + // 3) Common pre-pass: + // - determine columns (k) + // - detect all-zero rows + // ---------------------------- + struct RowInfo { + idx_t sel = DConstants::INVALID_INDEX; // index into base vector + idx_t offset = 0; + idx_t len = 0; + bool valid = false; + bool all_zero = true; // assume zero until we see a non-zero + }; + + std::vector rows(count); idx_t columns = (idx_t)-1; - if (bd.mode == MulMode::Dense) { - // -------- DENSE PATH (build X_dense then Y = X_dense * W) -------- - // std::cout << "\n\nDense Execution\n\n"; - RowMat X_dense; - for (idx_t i = 0; i < count; i++) { - const idx_t sel = lhs_uvf.sel->get_index(i); - if (!lhs_uvf.validity.RowIsValid(sel)) continue; - - const idx_t row_len = entries[sel].length; - if (columns == (idx_t)-1) { - columns = row_len; - X_dense.resize((Eigen::Index)count, (Eigen::Index)columns); - } else if (columns != row_len) { - throw InvalidInputException("Input Matrix has uneven rows. Error at row %llu", - (unsigned long long)i); - } - const double *row_ptr = child_data + entries[sel].offset; - std::memcpy(X_dense.data() + i * columns, row_ptr, sizeof(double) * (size_t)columns); - } - - if (columns == (idx_t)-1) { - // all rows NULL → return all NULL lists - result.SetVectorType(VectorType::FLAT_VECTOR); - auto *res_entries = FlatVector::GetData(result); - auto &res_child = ListVector::GetEntry(result); - ListVector::Reserve(result, 0); - ListVector::SetListSize(result, 0); - auto &res_valid = FlatVector::Validity(result); - for (idx_t i = 0; i < count; ++i) { - res_entries[i] = {0, 0}; - res_valid.Set(i, false); - } - return; - } - - if (columns != bd.k) { - throw InvalidInputException("matmul: input width (%llu) != weights rows k (%llu)", - (unsigned long long)columns, - (unsigned long long)bd.k); - } - - RowMat Y = X_dense * W; // (count x k) * (k x n) - - // ---- materialize LIST ---- - result.SetVectorType(VectorType::FLAT_VECTOR); - auto *res_entries = FlatVector::GetData(result); - auto &res_child = ListVector::GetEntry(result); - - const idx_t n = bd.n; - const idx_t total = count * n; - ListVector::Reserve(result, total); - ListVector::SetListSize(result, total); - double *out = FlatVector::GetData(res_child); - auto &res_valid = FlatVector::Validity(result); + for (idx_t i = 0; i < count; ++i) { + const idx_t sel = lhs_uvf.sel->get_index(i); + rows[i].sel = sel; - idx_t cursor = 0; - for (idx_t i = 0; i < count; ++i) { - const idx_t sel = lhs_uvf.sel->get_index(i); - if (!lhs_uvf.validity.RowIsValid(sel)) { - res_entries[i] = {0, 0}; - res_valid.Set(i, false); - continue; - } - res_entries[i].offset = cursor; - res_entries[i].length = n; - std::memcpy(out + cursor, Y.data() + i * n, sizeof(double) * (size_t)n); - cursor += n; + if (!lhs_uvf.validity.RowIsValid(sel)) { + rows[i].valid = false; + rows[i].all_zero = true; + continue; } - return; - } - - // -------- INPUT-SPARSE PATH (Velox-style) -------- - // Deduplicate selected base rows → compact indices - - // std::cout << "\n\nSparse Execution\n\n"; - std::unordered_map raw_to_compact; - raw_to_compact.reserve((size_t)count * 2); + rows[i].valid = true; - std::vector unique_raw; unique_raw.reserve((size_t)count); - std::vector row_to_compact(count, (idx_t)-1); - idx_t num_unique = 0; - - for (idx_t i = 0; i < count; ++i) { - const idx_t sel = lhs_uvf.sel->get_index(i); - if (!lhs_uvf.validity.RowIsValid(sel)) continue; + const auto &e = entries[sel]; + rows[i].offset = e.offset; + rows[i].len = e.length; - const idx_t row_len = entries[sel].length; - if (columns == (idx_t)-1) columns = row_len; - else if (columns != row_len) { - throw InvalidInputException("Input Matrix has uneven rows. Error at row %llu", + if (columns == (idx_t)-1) { + columns = e.length; + } else if (columns != e.length) { + throw InvalidInputException("matmul: input matrix has uneven rows. Error at row %llu", (unsigned long long)i); } - auto it = raw_to_compact.find(sel); - if (it == raw_to_compact.end()) { - raw_to_compact.emplace(sel, num_unique); - unique_raw.push_back(sel); - row_to_compact[i] = num_unique; - ++num_unique; - } else { - row_to_compact[i] = it->second; + // Scan for first non-zero to detect all-zero rows + const double *row_ptr = child_data + e.offset; + bool any_nz = false; + for (idx_t c = 0; c < e.length; ++c) { + if (row_ptr[c] != 0.0) { + any_nz = true; + break; + } } + rows[i].all_zero = !any_nz; } if (columns == (idx_t)-1) { - // all rows NULL → return all NULL lists - result.SetVectorType(VectorType::FLAT_VECTOR); + // all rows NULL → return NULL lists auto *res_entries = FlatVector::GetData(result); - auto &res_child = ListVector::GetEntry(result); + auto &res_child = ListVector::GetEntry(result); ListVector::Reserve(result, 0); ListVector::SetListSize(result, 0); auto &res_valid = FlatVector::Validity(result); @@ -313,56 +260,113 @@ void ML_MatrixMultiply::Execute(DataChunk &args, ExpressionState &state, Vector (unsigned long long)bd.k); } - using SpMat = Eigen::SparseMatrix; - std::vector> trips; - trips.reserve((size_t)num_unique * 16); // heuristic; adjust if you know nnz/row, it can grow if needed - - for (idx_t compact_row = 0; compact_row < num_unique; ++compact_row) { - const idx_t raw = unique_raw[compact_row]; - const idx_t len = entries[raw].length; - const double *row_ptr = child_data + entries[raw].offset; - for (idx_t c = 0; c < len; ++c) { - const double v = row_ptr[c]; - if (v != 0.0) trips.emplace_back((int)compact_row, (int)c, v); - } - } - - SpMat X_sparse((int)num_unique, (int)bd.k); - X_sparse.setFromTriplets(trips.begin(), trips.end()); - // std::cout << "\n\nSparse Multiplication executed!!\n\n"; - RowMat Y_compact = X_sparse * W; // (num_unique x n) + const idx_t n = bd.n; + const idx_t total_vals = count * n; - // ---- materialize LIST, scatter compact → logical rows ---- - result.SetVectorType(VectorType::FLAT_VECTOR); auto *res_entries = FlatVector::GetData(result); auto &res_child = ListVector::GetEntry(result); + auto &res_valid = FlatVector::Validity(result); - const idx_t n = bd.n; - const idx_t total_vals = count * n; ListVector::Reserve(result, total_vals); ListVector::SetListSize(result, total_vals); double *out = FlatVector::GetData(res_child); - auto &res_valid = FlatVector::Validity(result); - idx_t cursor = 0; + // We will give every non-NULL row a list of length n at offset i*n. + // Initialize child buffer to zeros so zero rows are basically free. + std::memset(out, 0, sizeof(double) * (size_t)total_vals); + for (idx_t i = 0; i < count; ++i) { - const idx_t sel = lhs_uvf.sel->get_index(i); - if (!lhs_uvf.validity.RowIsValid(sel)) { + if (!rows[i].valid) { res_entries[i] = {0, 0}; res_valid.Set(i, false); + } else { + res_entries[i].offset = i * n; + res_entries[i].length = n; + res_valid.Set(i, true); + } + } + + // -------------------------------------- + // 4) Dense mode: use all rows (like before) + // -------------------------------------- + if (bd.mode == MulMode::Dense) { + RowMat X_dense((Eigen::Index)count, (Eigen::Index)columns); + + for (idx_t i = 0; i < count; ++i) { + if (!rows[i].valid) { + // fill row with zeros (already zero-initialized by Eigen) + X_dense.row((Eigen::Index)i).setZero(); + continue; + } + const double *row_ptr = child_data + rows[i].offset; + std::memcpy(X_dense.data() + (ptrdiff_t)i * columns, + row_ptr, + sizeof(double) * (size_t)columns); + } + + RowMat Y = X_dense * W; // (count x k) * (k x n) + + // write results; we've already set offsets to i*n + for (idx_t i = 0; i < count; ++i) { + if (!rows[i].valid) { + continue; // NULL row already handled + } + std::memcpy(out + (ptrdiff_t)i * n, + Y.data() + (ptrdiff_t)i * n, + sizeof(double) * (size_t)n); + } + return; + } + + // -------------------------------------- + // 5) Sparse mode: row-sparse dense matmul + // - only build X for non-zero rows + // -------------------------------------- + idx_t nz_rows = 0; + for (idx_t i = 0; i < count; ++i) { + if (rows[i].valid && !rows[i].all_zero) { + ++nz_rows; + } + } + + if (nz_rows == 0) { + // all rows are zero (or NULL) → result is already all zeros + // (offsets/validity already set above) + return; + } + + RowMat X_compact((Eigen::Index)nz_rows, (Eigen::Index)columns); + + std::vector logical_to_compact(count, (idx_t)-1); + idx_t compact_idx = 0; + for (idx_t i = 0; i < count; ++i) { + if (!rows[i].valid || rows[i].all_zero) { continue; } - const idx_t compact = row_to_compact[i]; - res_entries[i].offset = cursor; - res_entries[i].length = n; + const double *row_ptr = child_data + rows[i].offset; + std::memcpy(X_compact.data() + (ptrdiff_t)compact_idx * columns, + row_ptr, + sizeof(double) * (size_t)columns); + logical_to_compact[i] = compact_idx; + ++compact_idx; + } - std::memcpy(out + cursor, - Y_compact.data() + (ptrdiff_t)compact * n, + RowMat Y_compact = X_compact * W; // (nz_rows x n) + + // scatter back into full result (zeros already there for zero rows) + for (idx_t i = 0; i < count; ++i) { + if (!rows[i].valid || rows[i].all_zero) { + // NULL rows: handled above; zero rows: already zeroed in 'out' + continue; + } + const idx_t cidx = logical_to_compact[i]; + std::memcpy(out + (ptrdiff_t)i * n, + Y_compact.data() + (ptrdiff_t)cidx * n, sizeof(double) * (size_t)n); - cursor += n; } } + // ========================= // Register // ========================= diff --git a/src/optimization/CMakeLists.txt b/src/optimization/CMakeLists.txt index 3d3a306..adaf6d7 100644 --- a/src/optimization/CMakeLists.txt +++ b/src/optimization/CMakeLists.txt @@ -10,6 +10,7 @@ list(APPEND EXTENSION_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/actions/MatMulDense2SparseRewriteAction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/actions/MultiLayerUDF2TorchNNRewriteAction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/actions/DecisionForestUDF2RelationRewriteAction.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/actions/MLDecompositionPushdownRewriteAction.cpp #Feature Extraction Helpers ${CMAKE_CURRENT_SOURCE_DIR}/feature_extraction/query2vec/query_annotation.cpp diff --git a/src/optimization/actions/MLDecompositionPushdownRewriteAction.cpp b/src/optimization/actions/MLDecompositionPushdownRewriteAction.cpp new file mode 100644 index 0000000..72eaee6 --- /dev/null +++ b/src/optimization/actions/MLDecompositionPushdownRewriteAction.cpp @@ -0,0 +1,373 @@ +#include "duckdb.hpp" +#include "optimization/actions/MLDecompositionPushdownRewriteAction.hpp" + +#include "duckdb/common/assert.hpp" +#include "duckdb/common/string_util.hpp" + +#include "duckdb/planner/expression/bound_columnref_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/planner/expression/bound_reference_expression.hpp" +#include "duckdb/planner/expression_iterator.hpp" + +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/planner/operator/logical_comparison_join.hpp" + +#include +#include + +namespace duckdb { + +namespace { + +// ----------------------------------------------------------------------------- +// Small helpers +// ----------------------------------------------------------------------------- + +// Ensure we know how many columns an operator returns. +static idx_t GetLogicalWidth(LogicalOperator &op) { + if (op.types.empty()) { + op.ResolveOperatorTypes(); + } + return op.types.size(); +} + +// Decide if a function name is an "ML op" that we want to push down. +static bool IsMLFunction(const string &fname) { + auto lname = StringUtil::Lower(fname); + // Explicit list for now – extend as you add more ML functions. + if (lname == "mat_mul" || lname == "mat_add" || lname == "cdb_softmax" || lname == "ml_argmax") { + return true; + } + return false; +} + +// Check if an expression tree (owned by expr_ptr) contains any ML op. +static bool ExprContainsMLOp(unique_ptr &expr_ptr) { + if (!expr_ptr) { + return false; + } + bool found = false; + ExpressionIterator::EnumerateExpression( + expr_ptr, + [&](Expression &sub) { + if (sub.expression_class == ExpressionClass::BOUND_FUNCTION) { + auto &f = sub.Cast(); + if (IsMLFunction(f.function.name)) { + found = true; + } + } + }); + return found; +} + +// Collect all table indexes referenced by BoundColumnRefExpression inside expr_ptr. +static void CollectTableIndexes(unique_ptr &expr_ptr, std::unordered_set &tables) { + if (!expr_ptr) { + return; + } + + ExpressionIterator::EnumerateExpression( + expr_ptr, + [&](Expression &sub) { + if (sub.type == ExpressionType::BOUND_COLUMN_REF) { + auto &bref = sub.Cast(); + tables.insert(bref.binding.table_index); + } + }); +} + +// ----------------------------------------------------------------------------- +// Projection-binding rewrite (learning from FilterPushdown) +// ----------------------------------------------------------------------------- +// +// We have a LogicalProjection "proj" above some child (scan/join/etc). +// Some expression "root_expr" may contain BoundColumnRefExpression that +// refer to *proj's output* (binding.table_index == proj.table_index, +// column_index < proj.expressions.size()). +// +// To push "root_expr" down to the child, we must rewrite those refs to +// directly use the underlying child expressions, exactly like +// FilterPushdown::ReplaceProjectionBindings does for filters. +// +static unique_ptr RewriteProjectionBindingsForChild(LogicalProjection &proj, + unique_ptr root_expr) { + ExpressionIterator::VisitExpressionMutable( + root_expr, [&](BoundColumnRefExpression &colref, unique_ptr &expr) { + if (colref.binding.table_index != proj.table_index) { + // This reference does not point into the projection output; + // leave it alone (it might already reference a base table). + return; + } + D_ASSERT(colref.binding.column_index < proj.expressions.size()); + D_ASSERT(colref.depth == 0); + // replace the binding with a copy of the projection expression at that index + auto copy = proj.expressions[colref.binding.column_index]->Copy(); + if (!colref.alias.empty()) { + copy->alias = colref.alias; + } + expr = std::move(copy); + }); + return root_expr; +} + +// Insert a projection between `parent_op` and its child at `child_idx`. +// +// New projection schema: +// - All existing child columns as BoundReferenceExpression(type[i], i) +// - Plus one extra column: `extra_expr` (copied) appended at the end. +// +// This variant is the "simple" unary case (projection over scan/whatever). +static bool InsertUnaryPushdownProjection(LogicalOperator &parent_op, idx_t child_idx, Expression &extra_expr, + idx_t &new_col_idx) { + if (child_idx >= parent_op.children.size()) { + return false; + } + auto &child_ptr = parent_op.children[child_idx]; + if (!child_ptr) { + return false; + } + + // Make sure child's types are known. + const idx_t child_width = GetLogicalWidth(*child_ptr); + if (child_width == 0) { + return false; + } + + // Try to reuse the child's (single) table index if possible. + auto child_tables = child_ptr->GetTableIndex(); + if (child_tables.size() != 1) { + // Multi-table child: don't rewrite in this generic path. + return false; + } + const idx_t table_index = child_tables[0]; + + vector> select_list; + select_list.reserve(child_width + 1); + + // 1) pass-through all existing columns + for (idx_t i = 0; i < child_width; i++) { + select_list.push_back(make_uniq(child_ptr->types[i], i)); + } + + // 2) append extra_expr + select_list.push_back(extra_expr.Copy()); + + // the new column is at index child_width in the *child* output + new_col_idx = child_width; + + // Create a projection that produces the same table index as the child. + auto new_proj = make_uniq(table_index, std::move(select_list)); + new_proj->children.push_back(std::move(child_ptr)); + child_ptr = std::move(new_proj); + + return true; +} + +// Insert a projection on the LEFT or RIGHT child of a COMPARISON_JOIN. +// We only use this when the expression depends on exactly one table that +// is fully contained in that child subtree. +// +// On success, sets: +// - side_child_new_col_idx: index of the appended column in the side child +// - side (0 = left, 1 = right) +static bool InsertProjectionOnJoinChild(LogicalComparisonJoin &join, idx_t target_table, Expression &extra_expr, + int &side, idx_t &side_child_new_col_idx) { + + // Determine whether target_table lives on the left or right side. + auto left_tables = join.children[0]->GetTableIndex(); + auto right_tables = join.children[1]->GetTableIndex(); + + side = -1; + if (std::find(left_tables.begin(), left_tables.end(), target_table) != left_tables.end()) { + side = 0; + } else if (std::find(right_tables.begin(), right_tables.end(), target_table) != right_tables.end()) { + side = 1; + } else { + // Expression refers to a table that is not directly a join child. + return false; + } + + auto &side_child = join.children[side]; + if (!side_child) { + return false; + } + + // The side child should correspond to exactly one logical table (for now). + auto side_child_tables = side_child->GetTableIndex(); + if (side_child_tables.size() != 1) { + return false; + } + const idx_t table_index = side_child_tables[0]; + + const idx_t side_width_before = GetLogicalWidth(*side_child); + if (side_width_before == 0) { + return false; + } + + vector> select_list; + select_list.reserve(side_width_before + 1); + + // 1) pass-through existing columns + for (idx_t i = 0; i < side_width_before; i++) { + select_list.push_back(make_uniq(side_child->types[i], i)); + } + + // 2) append extra_expr + select_list.push_back(extra_expr.Copy()); + side_child_new_col_idx = side_width_before; // new column is last one + + // New projection with same table_index as the original side child. + auto new_proj = make_uniq(table_index, std::move(select_list)); + new_proj->children.push_back(std::move(side_child)); + side_child = std::move(new_proj); + + return true; +} + +} // anonymous namespace + +// ----------------------------------------------------------------------------- +// check +// ----------------------------------------------------------------------------- + +bool MLDecompositionPushdownRewriteAction::check(OptimizerExtensionInput &input, + unique_ptr &plan) { + if (!plan) { + return false; + } + + bool found = false; + + // Look for any ML op inside projection expressions (simple heuristic). + if (plan->type == LogicalOperatorType::LOGICAL_PROJECTION) { + auto &proj = plan->Cast(); + for (auto &expr_ptr : proj.expressions) { + if (expr_ptr && ExprContainsMLOp(expr_ptr)) { + found = true; + break; + } + } + } + + for (auto &child : plan->children) { + found |= check(input, child); + } + + return found; +} + +// ----------------------------------------------------------------------------- +// apply +// ----------------------------------------------------------------------------- + +bool MLDecompositionPushdownRewriteAction::apply(OptimizerExtensionInput &input, + unique_ptr &plan) { + if (!plan) { + return false; + } + + bool changed = false; + + // Bottom-up: first rewrite children + for (auto &child : plan->children) { + changed |= apply(input, child); + } + + // Now see if we can rewrite this node + if (plan->type != LogicalOperatorType::LOGICAL_PROJECTION) { + return changed; + } + + auto &proj = plan->Cast(); + if (proj.children.size() != 1) { + return changed; + } + auto &child = proj.children[0]; + if (!child) { + return changed; + } + + for (auto &expr_ptr : proj.expressions) { + if (!expr_ptr) { + continue; + } + if (!ExprContainsMLOp(expr_ptr)) { + continue; + } + + // Original expression in this projection (uses current bindings) + Expression &expr = *expr_ptr; + + // ----------------------------------------------------------------- + // Create a child-oriented copy using FilterPushdown-style logic + // ----------------------------------------------------------------- + auto expr_for_child = expr_ptr->Copy(); + expr_for_child = RewriteProjectionBindingsForChild(proj, std::move(expr_for_child)); + + // Use the child-oriented expression for table index analysis + std::unordered_set tables; + CollectTableIndexes(expr_for_child, tables); + + // --------------------------------------------------------------------- + // Case 1: PROJECTION over COMPARISON_JOIN and ML expr depends on one table + // --------------------------------------------------------------------- + if (child->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN && tables.size() == 1) { + auto &join = child->Cast(); + const idx_t target_table = *tables.begin(); + + int side = -1; + idx_t side_child_new_col_idx = 0; + if (!InsertProjectionOnJoinChild(join, target_table, *expr_for_child, side, side_child_new_col_idx)) { + // Could not safely push down on join child; fall through to generic case. + } else { + // We now have a new column on one of the join children. Figure out + // its position in the *join output* so the top projection can + // reference it by index. + + // Ensure widths are known after transformation + const idx_t left_width = GetLogicalWidth(*join.children[0]); + const idx_t right_width = GetLogicalWidth(*join.children[1]); + + idx_t global_idx; + if (side == 0) { + // Left side: its columns occupy [0 .. left_width-1] + global_idx = left_width - 1; + } else { + // Right side: columns occupy [left_width .. left_width+right_width-1] + global_idx = left_width + (right_width - 1); + } + + // Replace original ML expression with a reference into the + // join output at global_idx. + expr_ptr = make_uniq(expr.return_type, global_idx); + + changed = true; + break; // only rewrite first ML expr in this projection + } + } + + // --------------------------------------------------------------------- + // Case 2: generic unary child (scan, filter, etc.) – simple pushdown + // --------------------------------------------------------------------- + { + idx_t new_child_col_idx = 0; + if (!InsertUnaryPushdownProjection(*plan, 0, *expr_for_child, new_child_col_idx)) { + // Could not safely rewrite; leave as-is. + continue; + } + + // The parent projection still sees its child as a unary operator whose + // output columns are [0 .. old_width] with the new column at + // new_child_col_idx, so we can refer to it by index. + expr_ptr = make_uniq(expr.return_type, new_child_col_idx); + + changed = true; + break; // only one ML expr per projection for now + } + } + + return changed; +} + +} // namespace duckdb diff --git a/src/optimization/dynamic_optimizer.cpp b/src/optimization/dynamic_optimizer.cpp index 06b87b6..08cd29f 100644 --- a/src/optimization/dynamic_optimizer.cpp +++ b/src/optimization/dynamic_optimizer.cpp @@ -3,6 +3,7 @@ #include "optimization/actions/MatMulDense2SparseRewriteAction.hpp" #include "optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp" #include "optimization/actions/DecisionForestUDF2RelationRewriteAction.hpp" +#include "optimization/actions/MLDecompositionPushdownRewriteAction.hpp" #include "optimization/catalog.hpp" #include "cost_model/estimator.hpp" @@ -32,9 +33,14 @@ namespace duckdb{ // MultiLayerUDF2TorchNNRewriteAction::apply(in, plan); // } - if(DecisionForestUDF2RelationRewriteAction::check(in, plan)){ - std::cout << "\nDecisionForestUDF2RelationRewriteAction is applicable \n"; - DecisionForestUDF2RelationRewriteAction::apply(in, plan); + // if(DecisionForestUDF2RelationRewriteAction::check(in, plan)){ + // std::cout << "\nDecisionForestUDF2RelationRewriteAction is applicable \n"; + // DecisionForestUDF2RelationRewriteAction::apply(in, plan); + // } + + if(MLDecompositionPushdownRewriteAction::check(in, plan)){ + std::cout << "\nMLDecompositionPushdownRewriteAction is applicable \n"; + MLDecompositionPushdownRewriteAction::apply(in, plan); } // SimpleEstimator est(std::make_unique()); diff --git a/src/optimization/register_optimizers.cpp b/src/optimization/register_optimizers.cpp index 63dabba..c8a7f50 100644 --- a/src/optimization/register_optimizers.cpp +++ b/src/optimization/register_optimizers.cpp @@ -7,6 +7,12 @@ #include "optimization/add5_rule.hpp" #include "optimization/replace_binding_rule.hpp" #include "optimization/dynamic_optimizer.hpp" +#include "optimization/metric_catalog.hpp" + +#include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" +#include "duckdb/catalog/catalog_entry/schema_catalog_entry.hpp" + // #include "optimization/plan_dump.hpp" #include @@ -15,9 +21,33 @@ //delete later #include "optimization/actions/MatMulDense2SparseRewriteAction.hpp" +#include "optimization/actions/MultiLayerUDF2TorchNNRewriteAction.hpp" +#include "optimization/actions/MLDecompositionPushdownRewriteAction.hpp" namespace duckdb { +//helper function to get schema name from LogicalOperator +static string GetQuerySchema(LogicalOperator &op) { + if (op.type == LogicalOperatorType::LOGICAL_GET) { + auto &get = op.Cast(); + auto table_entry = get.GetTable(); + if (table_entry) { + // This line may or may not compile depending on visibility: + return table_entry->schema.name; + + // If that complains about access, just fall back: + // return table_entry->GetName(); // as described above + } + return string(); + } + for (auto &child : op.children) { + auto s = GetQuerySchema(*child); + if (!s.empty()) return s; + } + return string(); +} + + // ----------------------------- // Pass 1: your existing Add5Rule // ----------------------------- @@ -75,31 +105,52 @@ struct CactusDynamicOpt : public OptimizerExtension { CactusDynamicOpt() { optimize_function = Run; } static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { - // DumpPlanBase64(in.context, *plan, "./plans/initial_plan.duckdbplan"); - auto &db = DatabaseInstance::GetDatabase(in.context); - auto &cfg = DBConfig::GetConfig(db); - auto option = cfg.GetOptionByName("cactusdb_enable_optimizer"); - Value result; - in.context.TryGetCurrentSetting("cactusdb_enable_optimizer",result); - // if(option){ - // std::cout << "What is config value cactusdb_enable_optimizer: " - // << TryGetCurrentSettingInternal(option->name, result) << "\n"; - // } - // db.TryGetCurrentSetting("cactusdb_enable_optimizer", result); - std::cout << "Cactus Dynamic Optimizer - cactusdb_enable_optimizer: " << result.ToString() << "\n"; + if (!plan) return; + std::string pretty = plan->ToString(); - std::cout << "\nInitial Plan:\n" << pretty << "\n"; - std::string opt_Setting = result.ToString(); - if(opt_Setting.find("1") != std::string::npos){ - MatMulDense2SparseRewriteAction::apply(in, plan); + std::cout << "\n[CactusDynamicOpt] Initial Plan:\n" << pretty << "\n"; + + // 1) figure out which schema this query uses + string query_schema = GetQuerySchema(*plan); + // std::cout << "[CactusDynamicOpt] query_schema = '" << query_schema << "'\n"; + + // 2) pull metrics from the in-code catalog + const auto &mc = MetricCatalog::Get(); + double join_ratio = mc.GetMetric(query_schema, "join_ratio", 0.0); + double sparsity = mc.GetMetric(query_schema, "sparsity", 1.0); + + const double HIGH_JOIN_RATIO = 1e-5; + const double SPARSE_THRESH = 0.30; + + // std::cout << "[CactusDynamicOpt] join_ratio=" << join_ratio + // << " sparsity=" << sparsity << "\n"; + + // 3) your existing setting to choose profiles + Value setting; + in.context.TryGetCurrentSetting("enable_extended_optimizer", setting); + std::string opt_setting = setting.ToString(); + + if (opt_setting.find("1") != std::string::npos) { + if (join_ratio > HIGH_JOIN_RATIO) { + MLDecompositionPushdownRewriteAction::apply(in, plan); + } + } + + if (opt_setting.find("2") != std::string::npos) { + if (join_ratio > HIGH_JOIN_RATIO && sparsity < SPARSE_THRESH) { + MLDecompositionPushdownRewriteAction::apply(in, plan); + MatMulDense2SparseRewriteAction::apply(in, plan); + } } - if(opt_Setting.find("2") != std::string::npos){ - DynamicOpt::Optimize(in, plan); + + if (opt_setting.find("3") != std::string::npos) { + MultiLayerUDF2TorchNNRewriteAction::apply(in, plan); } - // DumpPlanBase64(in.context, *plan, "./plans/final_plan.duckdbplan"); + pretty = plan->ToString(); - std::cout << "\nFinal Plan:\n" << pretty << "\n"; + std::cout << "\n[CactusDynamicOpt] Final Plan:\n" << pretty << "\n"; } + }; struct CactusDynamicOpt1 : public OptimizerExtension { diff --git a/test/sql/ml_decomposition_pushdown.test b/test/sql/ml_decomposition_pushdown.test new file mode 100644 index 0000000..aa84123 --- /dev/null +++ b/test/sql/ml_decomposition_pushdown.test @@ -0,0 +1,251 @@ +# name: test/sql/ml_decomposition_pushdown.test +# description: test MLDecompositionPushdownRewriteAction with mat_mul pushdown +# group: [sql] + +require cactusdb + +statement ok +LOAD cactusdb; + +# If your optimizer needs explicit enabling, do it here. +# For example: +# statement ok +# PRAGMA enable_ml_decomposition_pushdown = true; + +statement ok +set disabled_optimizers='expression_rewriter, empty_result_pullup, cte_filter_pusher, regex_range, in_clause, join_order, deliminator, unnest_rewriter, unused_columns, statistics_propagation, common_subexpressions, common_aggregate, column_lifetime, limit_pushdown, top_n, build_side_probe_side, compressed_materialization, duplicate_groups, reorder_filter, sampling_pushdown, join_filter_pushdown, materialized_cte, sum_rewriter, late_materialization, cte_inlining'; + + +# ------------------------------------------------------------------ +# Create weights file_1.csv: 3x2 matrix +# [[0.1, 0.2], +# [0.3, 0.4], +# [0.5, 0.6]] +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE w1(c1 DOUBLE, c2 DOUBLE); + +statement ok +INSERT INTO w1 VALUES (0.1,0.2),(0.3,0.4),(0.5,0.6); + +statement ok +COPY w1 TO 'file_1.csv' (FORMAT CSV, HEADER FALSE); + +# ------------------------------------------------------------------ +# Create weights file_2.csv: 2x2 matrix (scale by 10) +# [[10.0, 0.0], +# [0.0, 10.0]] +# ------------------------------------------------------------------ +statement ok +CREATE TEMP TABLE w2(c1 DOUBLE, c2 DOUBLE); + +statement ok +INSERT INTO w2 VALUES (10.0,0.0),(0.0,10.0); + +statement ok +COPY w2 TO 'file_2.csv' (FORMAT CSV, HEADER FALSE); + +# ------------------------------------------------------------------ +# Inputs: three rows of vectors +# ------------------------------------------------------------------ +statement ok +CREATE TABLE inputs(a DOUBLE[]); + +statement ok +INSERT INTO inputs VALUES ([1,2,3]), ([4,5,6]), ([7,8,9]); + +# ================================================================== +# 1) Baseline: single mat_mul (a * file_1.csv, dense) +# Simple projection with one mat_mul. +# ================================================================== +query I +SELECT mat_mul(a, 'file_1.csv', 'dense') +FROM inputs; +---- +[2.2, 2.8] +[4.9, 6.3999999999999995] +[7.6, 10.0] + +# ================================================================== +# 2) Nested pipeline: mat_mul(mat_mul(a, file_1, dense), file_2, sparse) +# This is the original nested test. +# ================================================================== +query I +SELECT mat_mul(mat_mul(a, 'file_1.csv', 'dense'), + 'file_2.csv', 'sparse') AS y +FROM inputs +ORDER BY 1; +---- +[22.0, 28.0] +[49.0, 63.99999999999999] +[76.0, 100.0] + +# ================================================================== +# 3) More complex: subquery + filter + projection +# Shape: PROJECTION (outer) -> FILTER -> PROJECTION (inner) -> SCAN +# +# The rule should push mat_mul down into a lower projection while +# preserving these results. +# ================================================================== + + +# ================================================================== +# 4) Join case: projection above join +# +# - Build an inputs_with_id table with a generated id +# - Join with a small dimension table "meta" +# - Project mat_mul(i.a, ...) and a column from the right side +# +# Plan shape (rough): +# PROJECTION +# JOIN +# PROJECTION (inputs_with_id) +# SEQ_SCAN(meta) +# +# Your pushdown rule will introduce an extra PROJECTION below the +# top PROJECTION. This test just checks result correctness. +# ================================================================== + +statement ok +CREATE TABLE inputs_with_id AS +SELECT + row_number() OVER () AS id, + a +FROM inputs; + +statement ok +CREATE TABLE meta(id INTEGER, category VARCHAR); + +statement ok +INSERT INTO meta VALUES +(1, 'small'), +(2, 'medium'), +(3, 'large'); + + +# nn test +# ================================================================== +# 6) Full NN pipeline pushdown: +# mat_mul + mat_add + cdb_softmax + ml_argmax over JOIN + FILTER +# +# We build a small 2-class NN: +# logits = mat_add( mat_mul(a, W), b ) +# probs = cdb_softmax(logits) +# cls = ml_argmax(probs) +# +# W = [[ 1, -1 ], +# [ -1, 1 ]] +# b = [0, 0] +# +# This yields: +# a = [2,1] -> cls = 0 +# a = [1,3] -> cls = 1 +# a = [5,5] -> cls = 0 +# +# We then join inputs_nn with the existing `meta` table and filter +# by category, so the ML expression sits above a join+filter. +# MLDecompositionPushdownRewriteAction should treat the whole +# pipeline as one ML expression and push it down to the left +# (inputs_nn) side of the join. +# ================================================================== + +# NN weights: w_nn.csv (2x2) +statement ok +CREATE TEMP TABLE w_nn(c1 DOUBLE, c2 DOUBLE); + +statement ok +INSERT INTO w_nn VALUES + ( 1.0, -1.0), + (-1.0, 1.0); + +statement ok +COPY w_nn TO 'w_nn.csv' (FORMAT CSV, HEADER FALSE); + +# Zero biases: b_zero.csv = [0, 0] +statement ok +CREATE TEMP TABLE b_zero(c1 DOUBLE, c2 DOUBLE); + +statement ok +INSERT INTO b_zero VALUES (0.0, 0.0); + +statement ok +COPY b_zero TO 'b_zero.csv' (FORMAT CSV, HEADER FALSE); + +# Inputs for the NN (2D vectors, with ids that match the existing meta table) +# id a expected cls +# 1 [2,1] 0 +# 2 [1,3] 1 +# 3 [5,5] 0 +statement ok +CREATE TEMP TABLE inputs_nn(id INTEGER, a DOUBLE[]); + +statement ok +INSERT INTO inputs_nn VALUES + (1, [2.0, 1.0]), + (2, [1.0, 3.0]), + (3, [5.0, 5.0]); + +# ------------------------------------------------------------------ +# 6.1 Baseline: full NN on a single table (no join) +# ------------------------------------------------------------------ +query I +SELECT + ml_argmax( + cdb_softmax( + mat_add( + mat_mul(a, 'w_nn.csv', 'dense'), + 'b_zero.csv' + ) + ) + ) +FROM inputs_nn +ORDER BY id; +---- +0 +1 +0 + +# ------------------------------------------------------------------ +# 6.2 Full NN pipeline over JOIN + FILTER +# +# Plan shape (conceptually): +# +# PROJECTION (cls, category) +# FILTER (category <> 'small') +# PROJECTION ( +# cls := ml_argmax(cdb_softmax(mat_add(mat_mul(a,W),b))), +# category, +# id +# ) +# JOIN +# SCAN inputs_nn +# SCAN meta +# +# The rewrite should push the *entire* ML pipeline expression down +# to a projection sitting on top of inputs_nn (left side of the join). +# This test only checks correctness; inspect EXPLAIN manually to see +# the pushdown. +# ------------------------------------------------------------------ + + + + + +query I +SELECT + ml_argmax( + cdb_softmax( + mat_add( + mat_mul(n.a, 'w_nn.csv', 'dense'), + 'b_zero.csv' + ) + ) + ), + m.category +FROM inputs_nn n +JOIN meta m ON n.id = m.id +WHERE m.category <> 'small' +ORDER BY n.id; +---- +1 medium +0 large From 89f1037fb061d2d110dd71da3395ef696c79ad1b Mon Sep 17 00:00:00 2001 From: Jay Tandel <120440398+jr18t@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:02:03 -0700 Subject: [PATCH 14/18] Add files via upload --- docs/OPTBench_long_version.pdf | Bin 0 -> 1059516 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/OPTBench_long_version.pdf diff --git a/docs/OPTBench_long_version.pdf b/docs/OPTBench_long_version.pdf new file mode 100644 index 0000000000000000000000000000000000000000..75de065dcbc087cddabfbd7a6a6725410ecc9437 GIT binary patch literal 1059516 zcmeFYV~l0p_wQR~m+f7)jqb8-+qTUv+cvuFsxI5M%`V$@tIzZN@4-E}xvx%gliyBu zW~Rnm^E<~%K4Z)*QaK?JT1Gln7}BoC{0|sbHdX)wz}CP5hKC10FJ*3HtnXm%VQd6o z{Hg&M8CW@48QB2zVgOA56DKPZfSH2_fL`hE z3|0AIuV+yJ&@0&5I(_xB|5H=^5*EPmCE#DP zF8@l!`oG9SFD?Yog$Pmcqd zs1-j@Y_J{>Uj{Lr3>vq~1-L;+h&3`=fj3~j1WxGUCmAw|eIgPDjIiv{hfcTIwggp8u)-M}hw+@E-;KqriU@_>Thre^%fN@&1C;|IMoUHl_dyV;f2Uy|l5D zzLCC@{ufel{DWFD`qsu@0LRAiPgT~=*oNQG$=uckz`?})Z=17|)fetM0@zvqog}Ak zYApTVh)~(lSoXiV>HjwW9rZ88{ezZ*U&~q9ngZxm%#B@*9ln6h#Mr^u#_((8UxXAg zceJz8cNelXR5Ew6G6py~I2-@v$N!GStZaW*{jbgZZ@E+vz{K(ei?RS_<}Y;p7h{@C6wQQJA# zur`C+8BJ;N1h865JZ>hX9MXsNqT4?^GepY4cf*TO3K_uB)VHCSk>yzN~ zyHJS|JbAy*8hY-bk!7n!8nW2DdLiaZTfU7BuWb4)CGjB+bPtgu6oUJy0h4r73;~9_ zyH|NMAN&r%;tUZ^I`x0n{nsALKlZ*N4nbQRCu5thr)6dTH^h+s3Q+U~ zZ2yKKe_Ou7F#!9Qi+qj!3TVED0@(lSolr1#v~_m)>!BPh|GoqN`0`%|{~tZ`znT7j z^~`^L@hj3}|DT*OOH({$O(eeakLnd$DZ4N#6H2+4`AA*yf$54(Ig3hj1!%ZXoS8pR zu<*f6_2n{CZ7s_s9KBFg=y>Fl!3bXsr&YkjCl4(8C%tXXM!Sl6i+otMGOCTuCA<3W zPyLp#`ekEd^+1!e{~nMmVR`a8((E)H1k?-z3-8G4T%J=F3C5o{2HHXkh}J-2NxJs zd{*5|k*4i8>Jg#jjUbBZx2m58_^Y%o;spiP4ZVFS? z8Z&SgpzQE{41g%^-j%+yOBMCd zH~!|EQbx=Rb@$mJ)5f$s-z^l;nAG~I%6v6zhe&TbP$1^fF7KZMUL%%|mrA^to=V&} z*U|FF!|1ntBV`2}8GLZ9I!HoKlQq#cEXNiFYp2Zk;RBeV?t!;Yife<`!S`+rf5mdL zEmtkjOybCj_PR}Z%FEFgx$g!=52yKm#;6Y#AnA^*bw7|W>#1)?;r~SZqC)6?26yB* z+YTxgGtHow>69m&yAwqOSLFh0^&}RcX3wk18ADC4T&RuPl$4g6cwH@lm*qRDj-Er@|``Cnjh&oJ;3HaD~9V)pJ?C zihIvyW`7#)@htrh!C3w(^TPD!liO0Vr_D3*H1Kw}FN(9AoYuQB#VYb92@9~QGOV^zc+d-Bbk@o{HzF^FO3iOLC1 zNROwLi(RL|%I}69xwA$-X2^L8IvF?m<^7fyula{mKD_c9&NKw;v2&^Yo}Z`AKZnj7 z@6T)XAY@d(WdcCS$GgK+*{?S1uzsJ;WZAaoDwO!77D^plq^c^*6G)7$d-r|98QNd3 z<7=W)jJXc((atoGjyNSWl5=gRa=+(x{CcC2byebv??|hkuCsg)zpuFLie;a z^8vzsq`U$eGfM~6XhF%%e-`*Qym{!hs=t4pff7m94JTNQXR*Ax%WWel(FhKFnx4Yy zN>gQEpr9rq2^;7#CYX2dELxVrXsR&L*6zSybchAja?&zIilR>2#?ThdgqXuA|aWwybQU&mO(EY2hN8L$OZ z1#kS&C&RH28E?L5WyZHyF7Z_1EO@%3G_4hQx5~O^qVJ@o*UP}@lL_O*Zt9^v_aG?! z26SfNbm|PM@%<@?Df08t4iymjm4_na*z0pYj`rMt|Cv5$N}{kF&=&Ct6u)HSi+!f(sh0;+e0wy7_Gy zqGqO=`^``{@y|6|X{z)fUdw`^d4_H_`sm~sB|3{@@Y_Z%Jqk;8H$Mg9KKk)yKHS|`?&r+B)=J1SKe%Y{wRA22^n z7wHY{nAGYgJD2C_Fa-*SO$=rMa16;A${OiVbE{Y^Fx=eiWet)XRtmiHfF{5-GqIl) zLIN8p5s4mY067RU$eQnIRf);GLy3?qIo1*07JDXxxhkT)>v?Jh_wN~R2J)*#3Xjp7MyY8 zmQJ0ay{I&H;HKlU7ovBMis@-oeSqY{O5vlVa3mYARO`ba6TbB~OjXaN)o+!2 zxo$b|KqlY31zk=Qx6LAN8j;s^u&e!yOY&`3J^}*#qOYm!*fT&^?3F}Vhh!tqYpShB z@OdIv2_F*d!AVz@n=3sCV`Xde;VFoSO=T=2!MiF6F{|U~B27c#25!KRodQ&5MYHaJ z1(P4M$2dQoLFoxe25e>7H002YI@Mv=PRk9|(NMr8sfv1rI&PC6wKQF1Sa%s$u`&z3 z4I`}GK5gWuv)AF`-Bla2^BlaK(A-OxR?zf?bf+r0Cvgi?gx2QImF;~atK6eL7W@YL zS>6%y8_TShM7x!~$u&mvja>97-afDvGK;KJ+!)6;#-RE#LXkMxQyI=`Cv+KC-03+@ z8-_=QTp9lSs42=4V~X6_Winwcx!9> z^E=c1D%}!K)fcNfl9rq(gBD0`D2`w-U@X9m4V?ugOl$%U9ZoZRuuhHE%7)?+Y*Cex zFjXrP8K!4?<-({~7|aMe33|_{pkNyEGCoYeurhIlG+z|B+&$7V(JSY*Jpi=&BvVpy zZ7DvuaA$XNwdAFQ6Hki?^$g(+TPf9R`Nr^<({eSF1aTZ#jWi+Rfq9qi@I4 z+ehE^&n-r!S3PCZc3??bXbvbSvqXI%#(R_kQZP4Tfy>wCx0kK(=LhgjORmeK0wR1< zL8a^`3j2Jv+_CrhL9}9EBW5_j6r*~66+}T*Ltb79Xs%rY{Gh5&VYKBRz1hIMQ<2@% zLjkSt{Vl&WQY})v>F~Nez&ckF6+Doge&(w~EPG$vi4dKy3OT;$_g5zzZiF?NIOa|{*iyA&)&)Uu2LetwdlXwFK(Pbx$c z74X3}@^D$Lsmvt@NlpA{T%kP9=@4YU?T6jO6f}0nE3uxCiD1-p2N(qQ`#p2?iI1I! zl@wE0eL3-C@);9XkB4i;niWA5I&@nC{L($>e(+@;Ap>^^Kp zG(Sa?_io*Y2PK!RTLn*~Jrn{cPI5>;uCUh|>&TnvAU#h@mn_LYzO(-MiK_KT+js}o z^nR|ka2<6x6MWn9uxKt|qDEXeu|=(C{`5rgR05OrNF!92TtjY7$pGkG>X2Pz>`Nd3 z@AWW83oJ)pu;*B{8lrXvM-7U9Qnj?*xG^sWv2+!M zi$zDViFdh?KQ6|+5ka&QjP1W+twPt-l|^^h;(y5qz?qVyS0GdQAXItme&^zJS_+&F z(MXbMgQ!5fwdye|q@pR%XC9a=rfX%r&)CE!LY;2Nx2MVGA_lclqmdki+|Ex%0@{{} zm&lgd(~wXMwWGh4B7YQqAXX7b9;b;z%Gn`nA&7CeVe?pj4krP=Fo9k5|83R>;BwJszY!dVtY|Df6 z`8ZOJ-2GT#gNE!TUJ!DVrI(d(BnUErHxk`aJCn+dec%9H?MeCu!pOSeQc-oSFKbv2 zOpo?98SAQ?X9GjwZ*=-Lnect^YNh|K$JNk;A614%u*s4+vKV*&fjeVelOI(3kbG{; zs}xscGC+Z@FWe*Mnm0UuCew*pJf1WKPHhd&wP5Bq(IjTBw$l5tlxSRI7?GRIz3pcmd=K2OoHg<5GOJSDg@todAqDxW){D+z&m$y(G{Xv7NSY#q>+@bE`^@6* z)dv4mWhGHk|Bkx^OKgRFt?a^fJ$roHytoSshSZ3*0Z6NEoY1<>3u~A-kxM%VgxW%O zp!rcP)EZ#fG%fhd(=F+fQW2bDkP^3A7`t|O$Qx^f1YxQ>jOp!-;)@R)$Q4OGFP-8k z8fe)1ZdH+~TT>R%`*MTyU$p|s5#sm{O>(}}C_%RUl!g)(om{p)XoyaUWNFn_rz%@w zTIT{{F_*xMoV(*izcDo=9klOuX_qrZub#VlDcLdA2?iHh^~cueL=m8Jo6I#M%u8xT za7vuKn!~vtCTD4zGGoY6py&91sJ_`0tU%37oQyX@bPga<~P59EQ}Zs+xtdb!77 zGYo2T&rOW)iC1;!4w=;|vS61B<#f-L)z&%3XJ*)y843V>lf!5B=v5xaU_nwtte44A z3FEb~)<640lbw2jnkCAWt{|~Z>^0%K4^xD%wiy_8J~aZXd>nYrki(?WiCJBX(s+C? zZqp-~fuZOe|6V61S!gc*4-1h~ zr$&tzfy(hiu&d8LaWR4hZJm&Tek8g$>yW3qU zlg!VbK->ihQ@`0W=;v!5KEJM~N|iX(wSgEA<|FFg=8@H{eeI=QqkC9@l7FR$-w{rruEOd{!4K?7Hin*t1v=DeW zeEafG-8mwW6k-BcDj**SH(47I2{y3-RcMd&ms0a{XM-8fRsK{|oE+3$H{HPXdi zMH1mMg0&zT@fqe+5@*VZxgg+@P<}|M+kJA0&fMeZpx)zAV^-)kFtrH{+?*R`a_GbJ zguCGF_LW4Mj17za`r^+O{wQ@}t9-p+qmVT5-iAD(;+w=~QV&(N{nu*P6OL$PlmzpU z(#cl0`muiVd<`yXv#~)oX zWZgACb1;I zF1C%EeWe6IoQr#;QH9>qRS!1Jp}O}SZ2KJF*vA~RMkCEqdk#TIDD z6I)2uxqyFJV=s=zLAAf{OMaV{jnUT4j>e@K2# z`Ua?f3oHATd8jy9Pkx!BB*>6Qu*^aUBcT{y1T7rV^U0zPG?uEa{{6?00F8Kznlv`r z&nWe1C2K`%>wI`jmN~bz1@?^2+^llAL`^CEnj7v&>dU3*St--Vg2#gxz8!}`~$?ZqV zuHUw5nbqbw%G9IYImGyA(%P}e)e}1%*Z61Aglkf1D}kI*H`kv*Pujf>_t!ewN63@9 zyPY1UjD*~L=WtXzFTGjPvJ@8IiV2aOpKff|Qpx$*<69<46u&-FwBwfOvzmsjA&^ZQ zb?7a&^t>)vRp}Os7|AfE#2Kl>%)FgOVQ4ydF>)$|q1-W-NUKARN{aicmJ#HD>j?Qh&d0werGZCLy8UB-)QMd2>wmfuA@>1k^%#d?7ve8?8 znOL{AsIW|=1r|^vGJ9W=@pHj=;uC;pOr0Oyx=;Wdq?~BtMXR`0L6Lqxa^8D+PGopV zw{w0bE`B<>#yC*a+7Nt!Q_4y)&Wm`c!-~z*JoNz@lR6gg zzqv_Z|C^%!|Bx$Z1aLAi|JNlB6M&VKnd$3l=bt?K-(>uMUGK1dCH7hWr<}S~3#grm zb~7z5Io_I^!J5iYQxU?qQT)gR#VTjyg3oAqO8(n>E3%|CahymTCuJ6DesX%yIAL`X{S(JSIZv?BK zRj*s$Ak=2MUhRO>KYqT*%B^pX;6Aah^$ra9|BSmPV6FEp#>||+JoBUbJzqoRn*>ZF zB~{_{30UhI{-Aewi^%*WTIw2pM_^)pj~I9I-T6GtY$=bL=xTba-h59X1yc44?T9-0 zOtLYuG~avvBzwzg#paWAgv9___>>%)RbQV4HTz|DVsO)JEW$R~{W&h#iurzCR+H5V zhuD3WL)qx7^`Z$T*8U3>>G{>OI?Gb{JqoDW!-1$^=0a_Z_GiYRwm7NATFtIQc~l-D4#l?&Lxk& ziHi32b%h39I2dXz~fRh6`h}o-TezA&}K(B zmxfoa%%7}m^>1sKfN4-OkhVHA+g==lq~zs8xlQ`fVG80?aVbS2)<85v(C&xV3hGJG zBWIRIdEgDL~I-mSFR3*?ycDu zEvY@u`I>Z!v8VGf3HCKctBym&9-3xjH9?KHpfOH7dG$Hc;i^t}JSHk1N`rx}?-GKR z+X80If0pS}iBq)8J ztfy8e36Xnf~0h!eDEm;&en&CVRq( zKQ7AXpVjV~l!vGC-LP-c6u4kiG)30#R*VAmLw!5Oy{2Xdw#lZRI5N$pCFc08vDEPPTo!5ko5#-+&cZ-Szs+KJ+20qh zzvqx15|ZO~t3i>IYYDdVkc;O*?toA3n;&Q`tqzKDCG^+BCB|R;RJ;1QGq?hVelnG< z#cg4@DZz5k9&786`Gzd_nAF(BAzaU@^7YhF)LH-RG9YdKY0xs|Ow|l_#CtqZNp4|| zBC@nXWrrYEx$HSx@Je#IescNEK~l}$j#77-0Kp=B#o&olXcxGICjAsw%n zkDnO@zHCtwH#5Zi_oX*L2nc5dQu0VC7DlGIy5n|zu6nt!0~ zB+Pw8(#E6lu@>RIMk=&WA3H* zH`Br!<#wHT{E#xECPkA9#c6SlgE-e|macb1C>M+It{1QsPM0pgO_Y1L^e)}xy9>+jT2JeN zCP8mB3SyYlinZ>95!HD77SH~1CZLM)gp7le>Uzi4-yk>@Dh2LHVt(3*3?t070Vi*6 z*dND6=)zILeiC1A!gnBUQ2WMb8Y5+hESYWSL|VFcj#WW;mWrxYF_R-AkalvUK~(_f9w(&qmLf>NgxiDQC;yU zOZqX(8fZg75bDZu42S}$88&4rtoJ;}S>n>%9}T)+h0V`bDyw*lSp&h1LQI95&TFcj z7mD#l+Vt#!WG_=T@;B})3g>tTRH!XF^>p5GYB;FPma{$>jwidZJ0T34=m1(NMDp?o zC(f-vtp;RYe)K{d6o1ylN$8$Mx!X){1gP$p3*2WWMrO|MQld8r2CY_b=PS_|r#(s3 z#$m5h_hUkewS|*c*ju~g-ceAf*yrBh?~U)qx7o}?Vr|8^S zi{37+polI$K`}tI7mLte61uMlYg-2)GE8* za+V1{(BOsHOSB5qf<0VVBoQ|fV|dJJa%?F|zymRLdPJ~dx+=q|fL`=P+(&$jv zS#5xaP5Kww%k~@GAZiN+qTQ@pFJ?9#tBY_LPy{oxC4URa+_;n zDa7lyorAjWPgk>N`M{PCX;%TSC|&XhEK$MV##%)PJslT%RO4sq6?=wi?;a1fCHid` z>Nb}&S07F(Ga;i?sWuHnKp&bJd@JI~ej!VZm!RMI$u+nZ81!?>M>7cV^+B;r2Mji0GkppZ>!7m=x5DlW`Eh8JfavygHkT+4DG zjNWUrRp(xR+}DQBZOW_}KbAvJo<3Q+@B~R< zL!(J$^w&Y)zz7EO{o*o0`+#&z-pB|3by9OLE`9ly_66<>wwn1YmOco#^ICZsPb4oM znbfbWOG={{^ZwznHP(}fdfrntdtbBMOlf-t-o6m+SBfKtS_9Q^=g8F1c$|qN21)*b zykD+N6Rt0Bxt<2SAV1#3QyTfs(rPC@_vwlS?Rr?)&K?NjEk`6N-9;#^8QO*UJVFq6 z1U+5SHq4IEV|Pa*I`e%59D?Ml_23FhQmc?@&$?lsI_WiJ{QH{RHzxK`Vj6kRZ36vr z@9dD3P*Y&;8!8HYUy9!vk~m84Ofzt!^LjM=!V}&IjV7W_R#xPwaGsP~WQ9(_leO9_ znBMsskXxwtbLgc9!nL6HQVS*!ww^8_qL}8So-(WGuA1LtoT?;(=-V#by&q9zX18U; zTb3i-Os{Mg|7qU2OKZvM6uF+Sj$gOT};m)X3UZ07&; z7BrjPDzxBa`&fmhTRolrT_i-)nqG!5-*H3o1Hv~FpG?zKV(+v3w(Uj_YN6_QNASSQ zw5*sg^bt%{`WY|+>v~(l;T|rkmPSVxR`+S(LQWkwn zyDtu-YK+}pXrn+Z1X5t)LmBrjb$%vqtb|y?-@i+;VZy zY{;jIiL5rLox!x63iCHZyIL5;5=i+68}AKH2FZ7bj~KGK5d6>vYYfuPstH+O5AlMN zb{n!Hj`Ft`O?Y*}Ron-*TFL$dCWUHUy8Ff(YV`vQ$+Dq3(kc>EKAU@t@SSa3yr?(1 zd#C90Rct{vK2+0IdbDTJO|6WN`6q{M@mPlhgq4IjXk?TC#^5~V2#SyuDY);NSDDND zE!;ixiErH>PPfa5zx;y82uSi3MPwN=FVTnJj(^oAjhEG>(n-a}ztGd9%TJfK>U(m8 zqSS)2t75GU^RZ?uLiDBz^Jv`NNe%e5np0-5z06ZUNc}uAblz$xg8{iEpwSq$)!l5PobO(9)@!O-eUIr!Yh;4nA|T@{7fQgHG}oZ|4eP7I`+( z`_KJl3&Jm3{1NsFB==Na1tw9=_al2abrP{NRyHT#;bEuw1&;~tm4Kan?&O_c~$rJIRIRNtJLGLnXP8N@cM zm^ZW@Ee-1<>d0j@E)^CTR14j3y5{Nb?^`dGozYRy;1tQ1W9huxpDIp8=Zj{)^P@aJ z*V}q#_6>A;ZlCy2MfYRoN}#w9ZqDjLon@DbdJ3>OrGNi}HWA-5(L^?eR1N)#4H}Tb z%1I_f79V=_dXysN&H9>;1T=~|Ubm9EYB$m#VX%9=_H>?FvU1{N($NO3=%dZl0QC$aB?Yy1GRs&ZKC7$n{pfH zJ7RoDYF6`!h^t-mNUiyZiRlGV&5&!>4g^akk$$AN3>$>jFaYPzWpC`8)l*Dw$G1V+ z5G(520WGQx%c-H{>$*Gb;t{m-V}^I9Y30NeVO^kD?XPx2y6f(0O;I3o-{6cdE?LgK zL3GnQHw&?sW!Mmq<^(42de^F+u|ZLTK+4HE)1rfgHILajOJeGNE7H?=w8;00(vC~- zE9hReNm%wb?naj4i>bTvz4QANxD zZcaWsnYj-kjrs{)CoSB^F5xp& zX;I_}Db}VkcB0oyt372 zMwFi|<{s@N@eds9Eb5Ts!;j;0?de5=aOnZ3Ndls88aNlw`ZnTr55%lciNVZPb;?F> z6a~^KS4%&$--ijWFdR!T-MXh zLv5fh7se1h;=-oD_e6z7G6o78A9Apyf244O6+`dkxf6<3b5nbx#h)v@I&UY+p{*b= zy3o(vTRhPXyt2aoY%31e2&J$cYPvh&wJzsAg3)Wm;1CTpD>T^8dvdUGp)xnX8hC^* zWO4wnNe}K3{gq_lp5v~w?)?C*m6Sg?m(ruqhP=hZy?UDaBSR2X!Nkf9-y3}B{^c%z zhem(2@&wVp=n8RPvdOKP^=Gy8X$?DN&(E22PyKNavKa{@gZ7KFvJxd03)S&Z91lPg zubh@jfEs!F$&Ht?@G9)PuI06QaM9r}$>rJ07R8JRq+Y~7D{YZT3kdwKD;S*iUiQ+y z0>6?C+Jd|yBQnc3S5C>in-0D8GcKP(m!T(BSMHqk8AV%&Jbk|J_TtEV$eb^n@@qbw zALAHu)i`rlHIX0>vDhWQ#>LByEpqtMc)y9oKWC69W`zA>xu$IDi9q^pI*Sk0f*;aY6K`Ex>hKh%oH4AtF ztl2%rX2YN$`hEo7XD+eoE8}#UR+3bv!FrvR7CetKM)Cbtg4jmLQ}}czbZJH{3Fd8b z3V5W&yRFMgm;gGS$*RE*2DX6_i#N`6*UQiLUQM5brd?^;{YLG#GAwbNg$`3N)$0pk z29CYe=d>O0_(ZP-)#D#;54T)xVt9l4Y@2XQVj*Sf4CY8wxQXK`2fvn}6FIr13w^)K zHDw;$^fZfXi{$qoH^8^(Xt=4aJP4MO+1u`XoKIse%DR6OX}_0%x{dQ0wmZAUE<4&; zG|f>qe_Pdx$yZeGqkCx%g!U>ZXzy@xoMMiB&v-B_&szB=AUyOy^poX1SBmb$e;;wx zRZ6vO%E5wMzCnA-N2n`+(cAyBekOJQu@T|1c3nY9811&^gE$%H%#f-K1dWj6RluB**Y29oljCricXYsxVf&lHN}N z-WBXoOa#p#j9G(_ge^78Q}P*55F)0%9`hRFb`Lb*Y1Qitmd6@sVjDW8W^WO>AV<8S zp{Tu1+$p#8JSJbc;^kirb2Uj2Bk%6>(uT;`I7?%+d#Gz<-(OzQ(FZcb1VydlHltdK zFG@U+pdEIhx>NXjL@FzOIH=s|hj~UAwkFEOjc{ZkcHXY-z*eOdVLj3amyRUY7?w5Q zW8e?qEsDL8aP#`*7{*H2$tjCp#TN>T;|dS2uhAX-wmLN8fh*wMkcf zqmC+WejrdxslzZ2X;~X2cxKA8dSYBJsM;p2D}{G!1JF7|imO9dL2m2TN>B{muazO z^9kfo$e6PWr1{(S8M1FGd1eq)3C=?|wV$iAzsN(sD|CN(L3|lJp z8y_Y#^;?{fYR-bTo6#1Lh}OjQp<^Ec5IF&TeGUnjLA)@$WIrxfi>CRW@E!DcOIuWL zj>iS4mxt~-P-syfl1rlbhIFY8jl9f>wupe{59S0ZUiEi+uBmR5_(y(J^1Z_zcesvO z7lUarEH|jFL+UBse%~Jw5C~GE^0bkWQa(}I1VrL!_a=fesqc9m&5f9;Wg`Yu>|P9w zEOj14Db_7xl3B{)^7)F42)jdeSt?@HEc={S$TA-K45;emR{8z(Xm>7U?7C%4$(7jp z=9h2w#DTAb7qrDa7e$H7Wf{!@xP3V>-vmwE)>)|nZ^S@9lC+DL?C#8e^N4^13X9)E z^hv?!}pA_;-MP0Ov!t0YLjC- zH-bj~GYA1g49>LoEx=hRwi|rGdc0h-(QL@qCZ~PFhH1eQ)i;0 zPsGRV7n3U7@5J>K9R7|+577PgaZmgun4TYC$uVX4sQjm{gvFS?3t^*#ABW2O0InE+ z7o-fc>;1HcoTaqsO?kcQV@dHher^jW3msT%$ntKp0HO*qY6j;uKcHGHX@Os!BZRyq zyFNe{^Nh0Qe!wL=R;TX=dV{0!x~MRg;xj$1%=1%AzfXFDjUocp|=klE;lAZ6N zKpn7J5m zb7aE8^!9^YB5)zSyhM^s*C|4ujKFW}ZL!9xDXjFkQg^NK^V&C4ynrg;epUdoWnCX1 zV4a9d+C}Fs@4yF(QGu{kB#G>U+?`A-F4npN}FMU4Q*Ec)lAs*$>DS2UOH$@n2UVW9K>;=U1U}`Yo6!_#S0Hz+! zAllT|V$$5xRO=px@|Noj1Gp*|H!AM#FD+8>uFh030oSkiPD0^4HrCX@rI>BeKC31B zj@1hM@o4lbE?iZNmsb+W|Hq$u6ZXg7p!#ngQ5#3@-%$~yZTAxG8-aNuI~*t?=_$+% zE%4R|DbM9J+yf=n1{uBk?H-HYZWK%TjV|dX z`Fl#C7HInJWkpMe8}A0_r5-A8$@PQJs6U3k0DNk1fbI|$eY#ThjzrunzWowFJf)e& z1NF@LL+llkBd%6xSRwN)PXX1HIDh*^?#=2o1FLQn5)UWFG_VX(D-=X z{iB`+Wy_u!kos{Rm$ty(S>u0Cc=(zQ?zwrnMG?GaMw{05g9Uf#;jMX(gQdFXNi{cp z!5*e$gkB1WNa}Vu$1{*cLUoR3x9$P27v`0YWr%~`;aixymtB@UjE9pz&O+b5V1NYh z;82k~)jK|n+jpmIB_Dprmwlf|F{=lg#2=yfnOBB|H!b_G`=zfH55qJ*Ti@?dt?dv@ z2{BpmNm8E3Z-ueFEs{1#lF=uZ~Szsg6hxWv%NeJjIacL z#>dJDXceLQ^&?J+oJG}XTROBVameD57$3*bA_m!ivk8r{o+2}dGYIMHYXxA9Bc6o$ zQ!~_S)f#)Gji@lenN>0Q;B|K12V3G*#~F^sx;-b&;6bBi!nNL(1@_$l5dDc;+A>%;9iHpG^2N+QZU<%mr!|THETr>wK1tN>9 z`+1nG+uqILeb->aMau1v)#9Uk8mGYm++gmdnJ(*Kh>i{Q^&>&EtjlMkf{sO~RBN!v zN2{!nW>5=pgE-A3Pd%Q51^yHX$Kq_J2#9*YNyga+*GIl9RM8RVXR$`jltrjC;pSlYnK9L)PFsUVee8;gIv0FIX~2xo-AuJxUvs;7cT4XZ(9(o0^xx)gk)DaLOkF|xB_Ubi&g%mZoOR^iaKH$ zl&lS098)jrm(E>;0sj{OCP3N0Z>hh~ld)VTFQv!AA2+vXX;hLqFoE6b|7i{fsn&7+ zbLPI`M6FBqr`3xlTn+ofPlk__(Tu)oRu5g**&G4+m*@H?pdeu}L->@|fYgb;;tWn_ ztp9T@qVU?i4cn;+q&^uJgp=t;#}ff&H-hAd%|B5+kPa${zO!)3F#SRv?Xr|@R?LYi z?oYkN11oz5kU&x=+XpxLDLx0b$yIg`!aaCLp&N0(rApt*`#78%wI6!Z8Z66d5L%2b_O!1R-I}d(@ zTIxFv%CZ&Aj(N}W_&EXUAUA98PrCcMgc@C&Eg{;U4HHQA5pORmA7bPwD=f2z(Lgxk z*WAPO`AXE-I?3+RZUG3k~hT zFvO)Y@BwXeb$pg_>Bs3b)kp}no5zZrH$j0DtxDAXMoM5*assz!J>v()5!+pK2ewVr zw}F<-TA1Fz6RHOMAWHFG%6{q)z`z{@6Vv+)X&BW75Bbr+4S{lX%!Z77SR}ys{2cya z29|g<+5zSp@S#na>6_Q^wzqzu&^m-#QhNNa@a`4Rbg`tS9*t8}8TAMv;h3O|a9a{@ zyaQGBNLQp~oc!{bkgF|V!;-Y0q)WT9gwb=Kdf>O@eOso2X0jMH`*)MaG{SNh7xLew zE*|L@C8}mlWCMMavlOj4BtrZZf`oL z*0tK}ml4_R#Y?jwc&Esb25=0Rg^*Y(tEr@ennCS?w;CK2BSF>DXQi%>LUz1hei1T_#~H=)Yi;AC{&aEK^xT`JLV0t@&< z6L&MKi>$vAyjDkR|Eg8P7UE%HW!Ra7)hmCtZ6-720E5pkrA@B?x@%{W_bYyZuSYij z$lcX{+EBYQ;s3fmeJp;o~?jv`djF`SL-}(fMqN0e0?z2sv(un3`M-r%jmu-BP|1| zmP4;TqY{g+jV=Fjxa23ZAoy`hS9w%ss>a#`oN4;kZeJoM9W*7kFH- za{k0U$xj!06qeaT6nM}QfzajD%TmAWWuuj-4!4g~8Hm(t?- z4QJp!l;wfR)*52;kLh(5Sy|G_=EcW-v!|)7^)$hQ2JJhGcppG#g#4;E{^C{-H zaErb<`yLSE_&)_E80ZmjkbGy-%bj5oS^K9~Cb!hO!HEl)9>f)=p1 zJdsbINk6vLzcE)~20tuZbUcumIy3qb{t3HSs$V2mO?rSuMN-}`P})yks?e072_A=b z!!n&H#A;v#L%px-V29TaTKa8c0K;=XRSO-VYJOBKG)#xxD>kk*T8!gV*&EaSvt(xOuD*~TNm{`0t6t%*+qp0~sWjQJ`zKC}H`AI0g;cQNx% z01wg$TZe<2unPm8kk9<%AsEVU)uKx+CipU9VoOlwH#G_X0{jdFbK2;iHB_JI+RWJgWLT%5=Yp>Bc-XVJ(J4)@XN+Gd;!S_rzsU4xqXzg4C!p~q9`|HhTPxx{8P!9lv4xMYgYMsJOzu3dv6C%QELnV_8hrenKnP1&aZpwZ%Yl{-?M_5#DyneIEF(@6 z*2rY$^G!iv1DGRCGpd?#(7ZDq-1$hZd+7nU@;g@019x@LsNPY?z4Mki#kzyR1V0-3 zIMuYtY^18IXrflDiu(td^j)7?fpPK50^Q3nzfTp7_zrWMd?OTBg7SAvwGcg{BKDuL z=%Jvx!+)GpyAndJzDgg5JjG$ve4DN|AYKi=jGsR#aw%BOx2C%iJZGwzG>eNozK$$A zPK4Io!@JVgy!&6#(7p}zn<=eiW;jPb1##;x6W7s!W23An1m_O%lA+Lg_}uM?J@5Au zO!^D%Bd6CS;=lW(zYj3=@De`a; z3bR*|%)QOueOoxFO1Ao#FJjNNAJWxMR~-$nbEfY* z*&n_Jv!%-mJCF@tY`#}hSD&F=T}j?eb%$TxPGbd?_(U#Z7@$X$qMtYS)(MBTQhw5M zr4AzZf~qveOpMVu!%wHj>V43ZgpP(y14|on-Y_mFCC45__n%hVp=la)4t{(C{cxeE z_Mo$hZqtnO-(K64C6@A4s>`@B^mrJapY&*m3pbI>?zZB7URm$mj0jE5%kcoTU60%QzO4Dx{pNyD>sjk6 z;F*j1*NZv6A8?$z=lTg|Rr1B?o{oe4o`?=&OPZAnyrYO8m_TRv>(?ZWs|@u@@M38Sgguu0y|2vto0vK8>%~f^vG1Fvfl& z{tFm3l$d(WiSe#}hIt|8rcqq13I(bqLH2`X`N*jf0d!L3N{aL>O<>oZ>QJm?%JBF0 z*!fUotW^(tSBZA^P5umgA75NttDotFRIpcl7jUuA{90e~9A^QlfUZbzIuca}db&LZ zl~&{@6*0T~d`%GVt4%71jdHwEfcrh#iMUpnK9xs`cI{Km#Vm+vE>z+mLb5?7B>emZ zy9m5;P=X_+F*Wd3Ni)ELwhtKg8rY zOLMT(k#r1G;IG>u<7Dc=NMr|4QPQFdlugo-DK3_lJOE}e#IZz6Ew)A`uy6`-h(R*;hh(73`TjpgJ`)Ly% z{SSsJo4rQ~a>!BHt)wuDpTkahrd=)=D{xg|I@AQRR92O&Y|d9WgQ8E5_`>u{aYATZ za{OgpW4I{a8@mwR43KT8hlahUeK5L}d)zVv%!Ujb(Q#OHALfNKlp;Ro8mu6w$zt)N zESE(LoV$Max3Nf;_M$CFfOis(FCAwwHplc93~OE0ihWWi2gI*#(OHcY*fdd>bX3fc z6DKYNh=KR-+VYWSxY(bMP4My&XY#{tALUfNcm6;+kd8C&j6S@iFjIAjv9p(BC11bM zs;2=RC>tQ-#w~J~67R#0nv6XjX?A2^`QzoSWzAT;=l6MyLd{r3=BOFy;kWq6y5T+0 zgr-RUJ5kNumKk5-%V{pO=q2mWr^mWSpCzo;q_H}!u;$wG;(;;1$U?bGXfn*Hz?2o0|c67ANK zLpep&E#0!am|pT0D|lTI_b!!|!-|q_Rb0%s&8?nlXI3{4J2BC!UFy|w!N-jjdSeOT zh;=lJpn;U!{k%0Bg9=7{=T17+`AF4dv-rc$)UCc_^%|BZ#y3VB4O9Uy9tkQ4D8QA1 ztK6N-dAnFqWqvP`4dQs_Whh5+|0=1i2wCt+|1A|ggF7T0!_W8esDjXkL8y#-(L0Zm zYjc8ts!wKHO**gSWfGJ{VoZG-$&TbufOz zbDTJb{y(N43TG5D4I?f#@waI=QLG~#3qsaQd8;)#_hC0Dy7%m!1MI-?vrYsSr>+}YgQ!(ZqGnpE_&^Zt^lWsUIzDMbtV^GMS#{zRwD-k7E@#@Ntit5s zQE7JslnEct_gC=6<}PW}#$pALE%}Gu0nP3xH8iT^yqq91%>=ecAW3BfGq*B9W&9ZN zEWS1B7XVfFBg{x&VIUqFHdOU5#rz63NRLnxaF@Ai=tDr%4t&`@K9(IpK)4o;I)j!k zC?b?|qLgB{lj{5#%%$S&B6N+Rm*lmcAE)oy;=7ze@3$%93{wJ;>4wNo&v>1RJT$^6 z@-s+Q#vw(ImQ%9Ud0Q*WP-c=?AWTZdUAH0hFJLW=InEh1A&_^ylTE*o29;4|5N{cX z*<0n=Y%ZP+XjLge232;6u>Z0vx`){{Cwx)v0m{B7_Vbr!cPvSa^=I@U*ny+>^Pxl8 zu!#?hOgj;cC`_848_q<1FI>TTYum}Jg7wXQQV(}%sBK|&_sCPzzE&*Hx6qk)4=@$M z@l8z3sc97+}1Cnfr>i8Mdr=_g)Fil|zgi|us(rr!-7;;|L9+^FRFB8g`z#4LUJs;aR^ zz7w*VGfnm`%cJknBRKWgoCU{d(mJ|$eZ!JRvO4&h)?mu2LZv z=04bvlfWpK!Fe2%h-*(ix%de-1faJLUKKA zbttcj42H6?J~b!W^1Jlt8EVN_<`S5RRc_O#-c|o5e1PunSLdp2O~&@;0OTo(6n&#* z3i4)jqZeyCHf%-x#~->t$m?)yq{&ENSU)c6K&*u^mf1FWR zWS;Ga3goQ}ZK#OKgL5MrHp`cqxTXh<%-wjMj1@?SjdN_xs;9oOn@(F<)Nia8tFp(< z$XA2Oft;5FKaVA6;k!M-gQBR0ZHi<07LL>EFirin1vTlg1FT(_D=_640-i3zIKbuY zV?<&9!HH6Io63-HA}1W8*0}THXoP;64>uMK==0(~JnBO-VN*v1HBe#Nd#XFzbPzBS zJR=lmp{dUm$4FOkZi?6a@r6=>C5$z=^S>)Ddey685CR1mY8a@|1;tCDwpX zP}G6xQZfpfFf60c=2Q29COi&lu}(pCV!FSNKM_wJ5n@0QQBVo0RwXMeq%9Lf%2a&EcoT-x#535u+|p;aKF-A14}vf53K zxJjW8gkMFY#n$=acAzezXnd*&-KkjN)d?bH;QTEYd#1@6pt8mlJx%U4t7Er*gf-Kj z-axQ|=dxs#PbXLzYHbH>yctU4t#;2ouB1hJsr?fVHPgwD=JeX*B$=56{j$d7dAcER z(69i^zyc0WMuJm5XML~&p~7asIJyXc6%!ksyN{~a^}C=yN2(9;B(1oQs9k-~EDp`N z@AFHHIQmvv)^TEj3*!BzCKm<+rmmU}^!=s-GRN&oQ_m`-&?!e>$13_-_G?{T>mqtv z!}dqBnt#?Wbw$<(sX0i!2Kp9aZPwxb4(MIG7t=P8QaK~+84clx0dql8hm-=UM76w% z0Fig+DEe}UMRv?-)cig^aT(1C_?3@D#Y4f1IuVdNaTZxin}_OEvfK5xWJG-4e1ON< z<`-CSO>lX!OEWmCze(3k^vEP4 za~-%K{Ta2$Nh$gWsrxg2FD~2RRy0j9ipYb&oL{)g>!~!r_<>^27MX<|aLMZGc`~uLTCmAV_wX6V5tgrPK zN^`{73)40ba!SA8pE&7{N1rLNt&af#L%}p7AqlRft6Zf#C(tjK6bccF2z{iSY}}3M zW^7bhRk2>LOBGjQVZMdAkGO2U(tKr5C0@B$Ufs3|~(L4SZkunEyeR#<>!czf>*cA6cYY#gnx=Y&%&9#X| z%^>rWC??xG56BON?a&I+2S#1u@#K}Jcrc)ZB0r-g?eGQWZO+&{mq}S1vRy=84zI^o zD8j9NR>DU)n^Ly=fB|&2Yh+7H?paFJV#=Uxas_HKK6mM)UKDFCrQiB|Polmi-oX)r zWiRaWZiW5WgYlun>{H4-I_vc~X(|af;~&K8Nf<&%E<|xI{F}mFAwRrfV>_r=@qJZF zMa`h*JqUPvjt;68ZuRxzbzlPo*l83@sKxTB(ir@YNZ9b^r97-p>rXp_{5u@m#DRY( zu8axgSL}=u1^up?V^PRMP+Q%bDG+RJ*ZsKoJ*|OjqIDe@yWty{S}vvi5;bQ~`-SBv z%cAh1SlAyajY1`Q>!T5~f4n59y>{tmw#3Hu&9R_d$A}+>M;`VwFxa$K5T~-bSZscr zNMA%)X7G2mD2sy!+&%i;w)JHd)AH^bGpA)}Vt4zIw$o;4SL2O=d06kUybX&J&-yn8 znI)^32h_`Oijg>^hMbyf!8Bo**g&k#%`5st!tY{sqsN=qvM2XOLMaZxehWxCBeTHE zpc&Rtv~_bo(UTPU?ME166lqAl&CVJn%FZF;L8Ej~lbm;7wIU@>P)4Gnx-t!WQ74%( zjYsFjHDm~HPq;}F&+Vu~Ay^=4&BPDSCFeXAxR!6ts}vBl0dej$4gm-@#UIB7+vkj| zYxpD;S)4VMRn+p=oYgylW`rR>iI9jWv|M;}(AAvH~5;T>QHLTBXqE>a#2svWO zFe_IAMPsIPNY>-GigRcPb(c3=TfU)0ad~0wk`Zipu(~N`$-2wnLbwNJv-WL9f8-Jc zlxZ?M?&M`7o$_X}#k3uujg$w_94TRP8VjGBrt{Y6n@Z@C9Hjt2IOfqNB-BpYnpGnh z=mir}7Csqzksf%#Lik93IBH2LaqVA|7h^ECvHYl44K;*ee3n88mdkT37{JAcJ@C}> zDcIys(|fDt$w3Mhvi0qh3u3{@1nDw;aKgbYWFBv!!R$q4hLr8LUvB)lL4<;u>j!)5 z9a@r=QcYUcJ8O@DM4>0T^?4mh%dwRh8mJ%*QBkhG&?>$l5%$sy#R*T6NULUCUUe!_ zDgk9_;jtY*CzvIFWVe|V_ZF?wU^K_TdWDI!b{LwSwKS-ZLhJ=2Cc5|i*-v`NQYPMb ze`n(ev%e^Z>TD)b4_HQGN8Wf2hoK01E^HyfeIe-MVq|UO9@K?0tTx4ko#s%1ey~T- z;~|1o6;)=fZB5-}fQ0X_MMk%y_HIpFhgis-)z!<&oue@RVGhiFL)kHG z2U&uU;}taslRt6yn2HE=U;zx?b}Q>#pUEJ7O3OBDKFZBho~Y5}_~3bm^T5a(&b#Zi z{gK<@*l)O2Hi8&;L)0}^Hok3@9TU2q#bJ<8)s}so z*s_<0ZxvA5jO&7^Ic|iO?U36Cp$0cP|6o^8QmYFOEI=yLT+I)5$#BBGBkz3e=G_{Sz;7^Vjh9ox2T+qP}nyvDX|+qP}nw(XgHzMNBgzxx+bU7d7SlARSn zhkBJj^JJ79By z03%u=cS>FsMPi<ta6hu4Df_lKeR?TNq(>e^OetQ!0ajglMMAu0zXnyFXFcQ(Xq|w zLZWw>&K0R%-cWq+IkaI1qfhYTy5 zhp8qf)sanaGwLI=+;7c5GB{H93(lR)p*!~P%ayVCMh3$l<@KsGLKp#@d0pig>NXU! z^EsLi#vY9^P-bsrjnn5EYR1lLjnkl~Ht3*Le1n>acT-*f%T8^fC*}1f#Ec4!G z3j%9Np6~C@hIk85m3Ew zmydlK+{b9#V1(?ad6^GLkYDm|l-nKsjHRN_EM2HY!`VGwcIp|#gxRLOY1h@3$J9Bc z(r{~Epx5g#h5qC}0|HAGP0B3pJsf_HS_&@wgo(no^}AMFQk)RT?$}4@=1nZ$?p^d? z=wb;klzl!Tquq%zV+)_*mgR@TT4!2%i(z%C+Ca_3mK+0JGfz*#I&pnpQOZd^cjS?u z+k5*Zgtg|O?wmDM97N(q1T)UQ#OqT3V1HP4AStZ>N-9E~k%z1Q z6AecNN!SyIA&(s9tYU@yhu^D!pL%DV+S9TJ|1xxY2dLvxH!HMTP2~O!QCF@NJ)C@L zs^l96L7v4;!rq5rwV)neQ;zx1sY=A);~z#-*xLalq(rcQR8*M~(qry$m)jRX0EeaS z3ie?!5x47Dfqrim)AeBf#$*2Yg|J8A;#NBFMPvD9M!fjV+VY{^q{1&=F@T+RZFv;F z751ZiE>+-nsNG{Po7f3Yg4G002Tez9ROxc@v&E(@w3W%N*DJ7MwPg8W^pz51Vf%7P zc^5C8U35=$fR$dp9{T=vQiYDJSTlki1KITK$udeLn&Po_=$rn5(?-ifSl^VWfqsw1 zy=iG7Lf@`;n6*FWRe3FnYQdijOHBjAP}-v`dohVV@_}ne*zW<51rjoJ-per|sf+YM zjCG{V@@ ziN0wc1u#|71Vjyx8q4PZjfzI?y2AbYhFD%L1|C&N3yYN0zT<8jX`5#0G9U7F$;_0TxyKKw{5S6$?#~o z<2r4Z31TaV6_Kh~-Q`zhG%cF`hh*1d@-%v$M3tA=y91xdE(M-7hW}3ua zf@O@Vyf{mdN&-Scg)G%**UU63Y3hB2w%#cyP|Hfpg5(^tH(b@vGrn4tNIu>KhIWx+ z0+HVgW)z`A+CN<+C+QXLvR{^FYtl@G`{`9X;qgkb5I>4{dA83tuEQD7eYOwM{y~LIWQR zG5}*hcF-z&PxBouU+zLA$9L?wp>pHD2=gO7NEAI#MI`VaJ3k%Wh_EG^mP0YzSb9(d zuWCctRVwPi{w=Tiz}jiP%EUg->hp4BvCI)yAH5BCNTI86P^Vs8?Ex|K9LbH`2l}O% zgeyX>L=^;;;mnm?6C*%q9ErkxO+ImI^(Dr%nQI(K>0lJ^MH#^3tC~;#L+_!Y4wV&l zbbJ@iW|u~xKh7;m0pPi|39_99J2-sb9ePBnQaKM*y<=GiB1filx*%(u;ZmEi zx1uoy)zjda%V=Wv%Cf(ej$X5SO(6q!EENRN3&yBi?QDItA-_T&u4$MGN9nN5Yg3_j zrdUcJQWvnla#pfzP@wX&e-2m$D<2dAEeHM$LyGugCSxKY z>}Tv$cZJs?Sma7(gny0_xJ^=xJB|I{n+p_mK>&D>Ja)LqfH${EEmBkN%J`$OA16mp z!(TveOvs=P?5b+ucBkNWN=Su;&$~V#7Y7$s&l~=lzV6GR3uyAKnL6o$N zkU!W^&jM0}^f;ZVUvD%$JjW1;ZnZCxUlq8fe)m>YCEa8ngp0r_;s;4}Gom$YP%1n= zz=LEgF^@b-c)16JaOx)o+u4_G9Wj|wnIs$+YA?Z>IY2KldPGObv{vUf!(kz;-T#xY z_-{0$tMh%T_VqRUOcd~*oGpO~ZQ}f%Nb|XDk*JK@BKUZ?$DbFIc9?1JAs!9*m%i@?ML%$nD+mGRRem ze9+*lvyI;f66YlAt{`KETYx`~gW_<=hf}nn$Ii)_m!^a3NjQ7o+;Hv!Ji4==(tm+$ zM{aPFtZ#-D&mminnzp(H9l>AkNp0Tu$l`+ZNFIIcbIr(%U13zJ0jxUf)~V9+Pn8R} z$O%!Bh5MDPxULwq$?;WVjzuw9m)BR0<-FNlUbca3U9?@9QGI;NfCsO`mq|9{2#l}M zAkpV?a!O_=QCXE}X|M7Q);uOcs*56t)$qx5UKesQ+Elabw_7&<LK1N_Q5`kC7jX zd72qN!)VnZ1L2RuS-ZuHwZ66_QGIs`m9@#*bBxphnI$rJOPT2G#)GH34`+I`OXgOQ z0R_o+i!tw$jkVM@WAk%^zUpK}P)s`i09CSedvr_c0&Xa07#(M6YOc(uwQfP-iJW9KW?;Z77dPOkU34ylx}cP?ZC|cvI zDxn-QBvBHFQa2<3hJ1HVlfz*tnZB{<3q3EVq}$Wb!|sN@WR?yW2ai-VD6!xI>M`CA zQ0xF=ax}D%K7q?E%mNIRsH3)u?0q-4*|h&J)K#(nOTd&2ljBkVz+4oa{>Z)(hGy}d zwwfJ#4j0FV7GtH?3bQcYm><4tYSUCQsoBKI{y@gw1@xi29Q4%PncK^}34fGP5&+MS ztcUTQj>!ozUS{H-ZNL*ieqZlX+GD&aXd$c53 zV?y(p7eUxZi`;mq>}P-?OhH?F;hA&LqabRO8o&$+j1J#8$6lP5c;g9Ry6UC@XMBHn z)24YTou8s2_y_oES7wi)Z-)7Wvgl6>x+uUY{w@7&b6l-};vJ)pKy2B-6DH@$LJM7? zE|ReDk!OlJ2t2oKtscV{F52bYA`7xJiWn_Bo$?)@csQs?*ksEFtQ!71WWdCIdd$H8 ztlYqRXO_|4YMhzIWRT3MFs=OW^`EHK`pv431`vEsIIwy9pa1&MON$m{Dc=)$bwm#viF`^QWl0ZHLM5vUSgbx ztTKBcfW367LUn+#_Ya=f2!(LZEFOJ)4uIR=h8Ou_RHLs6`VE<=y@ybFT*C-=D#xOt zqzWK!WUYTet57tMRBb;ZUs0^L0LPAH7GQvtFBk>LAyR$E9%AFWt1EQGMYR@fi-PLS zE-d@!kMYlXq$?aluu*A8fghCRo7|kMR^KSQq|$=L_~UD=lnze7CI%2wcy0?`F%|l? zJASoOw;1HQOP1*#4~CsB3q%9cEeh>2Q~R1CwP0xi7thd3z-mmm?=2?v#FNi@L&ra_ z3XNaHg>D(@8?fB;8zCZ3<-*P zQ?ot)eV{=*==4@az+*~3G9%21;h60HD(|{FqY{B~FUr;b#dp5al{=7Vt=uoEHEJkCT-@2BvL+3D~lP^ZTtxyaX-^Y-woVtY~ z8gvL;UbyK6et{CV47?Sr>jRVEenM}T!;n4Fe?rJs*|Esb@#{=kwc?!>moaN;kFx9E z=}SD=o2D$vMTW3tcY{9|!k_s{x#?>h%`DdCQ=p?xuVh$6opZt#JncmoUYPWiGQn)b zCgS4wG{d4Q?WwpkE0PcsM@JxZSn=)*zmM1Xxfz3eL~)4V&l9NJes~TC zrOfgj-qo_=g`Pryi5?M{?d}0>Pt2mtlXfiKv}g9=iaiUNwF$~b)(t%O^oUQgjebZ2*~fg5!H2>01A1(xsc}dDw0O%!sgq z>NHD=nLY#ad|%6ZTXJK&?|t8p0JoB(S%kmvi0y(P^n{2UYiW6=eNTaNPL0G3Wcf0( zPeR2^S=lvNsOSSPRoIzn4>OlYdxG4!+oFPZO>)wD0HD?S$i{5`y>xKh`tyO$>!Jf1 zDT?bg73G2Ey+#iGVi-7;tnmBQcSk-r4R1r&o-hJ7R+%Z@nw<@mm;Cyi-Qj*Md^ipy zi_%rc=F?IS=|ItBh^k9m*Ib_hH!;D$B>W)6! z`yon^qRhuFUmtFDnm?_xUBc3si#S5{g zvLv%h-qw*3=(Wt@cbQ*XR0_%Hoq=9aDjT5*!dIedl*H2=l7OG(lO^TQ(`4zsDniJM z(o7PF(XZkgd<`w_OS{t>KUS?ou={D`zMIK=y&SX;-7!y|!efnc1m!1*bWbp8H|X8t z@;Eacm77&1^Mk_W66l4QH}81p-#5hpW?kM>-W#wC2ym~D%oo$32IkZujuHVv z$y$Cw>Esk`FlYB63s>jxOP~s=2#dGRqy`4i?@OMCkA=CVtyg*3`t-3!*N@<=>!+pq zEQ1HRf3Vek((gBqsjKI*9Az2%5Zm43N>J$*pq%p~ws6(cSCz~Z{dCS>!hY13yv5ZY zkp-w|6EU4|wK}A{ny}^&)w<}bXdx(Cv|+&3_&q(}d$Y}DszWg7bT7HEXErmk?5mT< zp(5?b_ZSRte#{Ri-3^KBL~vyqH?17JQ%x+*MY(=b(iWIa#~0xu|E4{eA)b2 z&+n)vcTqrytM`&BE>LZdpkh;-m8G|_!^N$ozD$8T`CkjKoHce-9D_w85}@XiE!RC_ zTsm2>Oi#mxE5Rh<9tV8RMU6LbvG~1OJm0n>E@pt(07uD7G`~>ce z;&MYcer|n|*MJy9NhFOo%n*UH-xVmVY4Ptuag1m&kw~}oH@*luKi;~@?;BCc`E^_V zD9UszheM()_wpE-s7e1@!0zBr4B6aSI9Vz=cM8tcv>>7R#;QlKI$^jSXe8~lF=(=h zrzqNvmbU9b>?k3TK%S21QUSfEJQ>4 zuf2mY64g8bqD~D5WX0Jy0}Y0#V^S;|y62bKbV84>onRixF{x>9_4?{4shEy?IKtr? zD2`OIE=Z$Jp!BS+k;Z2BGKq6W}VlkVc~Qa|`h$!)Mx z<+X}F#9~ppP`c&aM|S|;Tr-tqOStFq0`1B^)EDTGq^$9$ex9GJ9aBa-{-ciqr^LYe z=`%te5?WZFzP?oBo@)c?i?W+S1pfx%5)*1g-fGUVBG*>lJ_w#~zyxqq?%^-)Y&847 z4?K20T^(Lca~Q%+q;D@xS-6ZAi|jBJEbDCp)PcWMjqTJan`D$sepFCQBT6k6%s0k^ zH%U&n22c$0m_PF8JEC4kkf$;Z9DT@mtbwPLg*NT&#PFNEUic(V5ERUmNPXq5i#V~X zB1$osm()Cc8(_%DL49+Av=xe)W?=@pOb%sT%IAqW!-d7Pa z%X1}RcH-N8N2uG%Ro6^bX__5yS02tgcx0NkiR=>uX8HxVw{4aOFRAX)z5jn`Vrnt( zgpRRReRf%SZ$(w3<{QPyTc3evR*c;&j=%Sak=V25rwd{hY|}_(wyw8@2kwiNwf%_= z)VZ424*gc&4@)t&W(}lwJLejpIWoPQ4IN>0E|ln8tGk3@&c>6uyQl|1|(Hc7n|G*fO_Lg zH(w9fl*rqo7G2!>47@Blc)Zpf5GE#m;aoXggI(+GObKHaDvV3W%nntx0F#OC3^f%5 z3aBOxr2Fk6FXetV`abu!mWu8l zdG>?)(CMmuyD9vorRY82m=(Tao4)YmkjW23#nCzxCeACEN@_r%7-3+;hAj0-e6?;4 z;0K`J0s%0HFzgl3%7TAOK%*3_4^(gFE1aotCRBnJ5Cgc)Uv1WuIvK;aBp6$2l~|3e z&VI>cd{qt}zcl0(wLOl}Ls;X}pjQPg+-NzuHH#zU_j7F4gcK;S1{|EDM(&Pb#^F~9 z%`l8*&MZjjemN-3@!agW4XSzW9XsGOt1{ehzX~Lk{(3N3K>1s-GS$^veEm$Q7`Z;m zV6rJSYsBtZ>@k@MUra2FM9g+_?p3;ZO#zM%GO2Bt%o*EJ1cayE#OF)RXB^Qo#^ckK z4!v?hx?W}7mk5XdBOCyf$SoCi>mgm?hF+bh*y}zM-&qtH0Id1D+7~fXC5~&ux_(|$ z?TFvTF!Y>l(#Io7$m4v+@x_F30LELJshm5Ej{?V7VU>uo;F_)C-_Qmowown7cww78 z=x4vlgfYCSRzKSX;|69t6F$JdAxrVVq!cBB=FL9#Y@>`D`}m*d+GuZ$Rk%D_`7^a}M^^bkcfhA_At>Y2qFpHh(X=5ZOA9=aR|dhqrRd3XJW2 z)S+(p=jE?*cWD!UPJR%NeM1ym05-BIX0yNSLNX9a8@0Qq$v8*nx5ViodE4J0fp9eH zFCm+$b68b<;|y571YPrsX6~Q_zYeCIQ}^q+#l06LJ;Vu>K&l8Tjtb8@w=VSAB{^;! z5kVm*tj{O?Sw58{A-8R?`X-b}d1yV_v?CSRvC8exO5qMYgyyo-$yRf?+1dCna=0EcQCd z(q#ove249h@w>?farpLXaj2xZr?^ zi>3P1>k!J&&ND9CzKlPrScA6-O$cE8!aT`}?LWq8HTzYBv|F?c8)Ax_7Xws}?L0 zI2OgFEWT~_CP0V@?pqFN&`$LpqB+9q4}Y&QOXO;S%K5^SM8MmHg`l<}5Y!EDD>r%u zF~+Ofv|QRKKUh&M{$tA78z|8s;QqPT38lD_YnbM%CXpuJ1ych42>aW-s~2Cbly3 z0R9RpxD70Pmz(I;<;gXf>ozTe1;l48_Y~r)#>`jUdw611VayTB>#wj73ao(Yti2Ef z2d9Cm+4^8;tM~RIN);Xyp#-LIN>T>NoM0fL8J(sT($SCoimcW%a>_^2 zi#6QBNX}n8wF6^qF9nd&yEB%a?FPa%G14ZuvzsV5t20f?M7+r(W?Q|xBg$V4?$sn( z^1J@NFT`@b#83jwjx9Hfb1lD^Uk*zh4ojwj*WRkf*3;1TXS^4#|88Yf>fmpAi3_u_ zyTL3;_bZVWSh8niHd*KR`OdPy^yQ4!-LnlHayC2+5Ao4%{Uz{PqNwm@;5q2DpVwTa zx9}(}Uvsb}BgLZdwwlaO3R70cE57~=0O7fbg7wflk0zlN%`b}Ax^TZk?gRq|#z6LL zyb2;}lGH@1aUVGkQquMTZh~9&)AW75r{J8bNe&6Z0|%SB#?8;x|AV$%Jny8!BKL@% z_rC&61BiS$G5WkR#EL&wZd?Za&~ogWWy>D54)n$8 zQ*rywWEe#xf8bX~%=}WIi}K@CkwiImVz>tFkc(3fd7a%~2May`ND&(7 z^uFp~GYu+$pD_BdRG|Vlhc_B4=IEl7t+g4<=$E{VQp+2RX_ZEn;EB2Hzi4I7;3I%W zFao?=vX;uU$>sds3BE?3-=OEJ;VypY*H>lcWo~WpNfpR$%AHiwnim31XnN0v(XRxK zSD6Y)!*mOXU1KqrzL-rHOvsP7t&8BKilXLs1=LjK+jv(%xfUFc0CI&$b^7l$z2W3y z6SVfvbfntA6nb@jp=LH=M-{kwPINm)Ib$J&7`OOJLkqQmZ$Nz;TOBFf51u%v6qKHT zN>*wO{FIBN;;0H9pM^{}MmND`V7?t9-B!c%NdJdcDbDz4ai6n5%1*qW#5$j;iF}4c z@>6H){98f(z9e5hGUdUP365ScKpN$6Gl1=a8o*oZ@B8DqVqQVfw__Md33&VuHyqza zyme)gz2_#}Q{U1?!($Biq6&DRJ4=|hReqmXEb#=*FYp#XiR{FR>=vI{E&z!=?BDF( z7!?YVJSDvwx!oROs>b_`GU*1Fh}%o$9O#X1VAp5xt&7)Qy7roK(8JOQl7zQ(YWfBN zty~7=weB48QO#v@yHBP1#{Q^Ob0FqT2PwC8qDaE3959B~zfpYWq!Xy*+gGR%(0!Oi z$k!)RH@@LkUYYp3;#KY-XUj=&q)D9hs15DEjQ@I@xx5{>#6PGHx>s!y<(KIUcweet z?3|bwAI^l_R?Tpt?S+4B%E7afoPB)L@eR~)fptiDwhfV?@g=CW{R7q{`g$m1Uk-$kJ#CTNU<#8?8- zkkF?#ui#1RD?u6=8aC53@W7U5^@zlM$Y1ae(710Sf~#$^t6_BnQN+<{-vp#=hEBEy zR@-D)8A0@@sGCic0iTr#j5Kawxz7t(%>+J#E&GZ`kw=qXT}m?Pq9Ni6c_ByE1a9S!5-}>w zqxJEv-NDYA5ekK2r`$NsZuMX_rjqSV=;$9xJmQ_Q;pLx^=|l}e@a4MG@o9SKp){9< zHHW>^CMHIvjy=!b-dQ0PuewJ+@}4d>VE;g3KnDvSF)<&R)ajXcb1}S1tPBe>m@J{C zJFdm+75@+Ct|cVaDf)EJ^AhC~;vONG7<7PP&`pLpyT-(1Q#cg^Zi!0I5tGhp5g10X zm~!bKv<)R8q^{*J-&WJy;@aZR5v5BkQ9oWts{2KCp5!Cy%%x#zdG3#by#{B zxHrzsSRVM6Vh&N@OE%m4G5sIKc(6#7wt00xm$xhks6+5xI5r2x5cUsG)RBw(kGd8B z8$3cEB8zt(C5zmJ#NH^u`gXu9I@Yh9stnwfj9H}HyzfTgDXO7dy7OeI^B*pacb{Rg>)pMb%y z6#Ys-B{{XyWk>)uJ%C905d4Z8;mwdo6FJ@2@XGN#z??Z#$HbF%m37hy+IJt_+WO|l z?3_g9jcm;$xT1~1KgkK;(K1_9myoN_(}`~Yv`BB1-EJc!=I}|%#0%h?fv|L0|HPR; z%+R?24!aqKe!se5*cB@b>=sEgnH=7PW5Mu%X&75s6d4;iHdh>A6Dv#4aSL~Yh0&TN zkg{i7|GK-!tTAVHwuF0Pc?i!xxN>9r--AdTGRP5=+Q8k|21Zg<6WNt$BB3g?2@Y_R zZys|WheMcB7z(eZ!gs>_HjkzQ1{h67EVk!z(*}_|)LzoJFL$|UHEj=I#a3(uK9SYy znASZ(M7=loC_RI1Hiq77=95eGA&z?=%0xx+(SyO_wTzBN?TIR2i-`Dw^)~C!L?&Fo zp9RKODse6R|a^nfzU&$D;%>NqUH0f1x2~=@~Ek$0^L|uF##^8Nj`9nB>kFxzh)q2Q6A%1!P zAiUCcl#}cQWa?E7@s>)MjGEJ+94$B>(VX3sDYO6yIJw3pGh}lK)+DoSRw8z(Mo6Os zL1$|i3hr^8wX;pjd~@gIkHLw=Rx5B8gem+S(-xbE#2##*kVe|A5g(33gU%0t&W)(K z(?)@2OK0#b-$^vE5)O~xhJKa)(&afU1)491Qw4BQ4C@$V)?xEVyr7=U)X{P?o6ey7&)UDl{0-M z5vL}Pu$p(CIjMbkkbAQ~6sIE4=qe$NA>RJcOU=@ffSMbiivm}{k{2y*NlQB5!BV>s zD`LYpTFCkzN3(xVpLCx=P_M&1pJp?BgqqJ~bNq&`<*s$`{$^Nf8|?Gz$(}<`?;Q%0 zk`kx2kAU^nn+}!KZ%`5*-duODihdA*zbkrMl+?|J8O6oudSZWJ2T1~Ea@CNYiFx2| z3jbj0gw}JZm>N<9%%vGRna#4^6|h0jUKg+$IUKm;bW@{vOEWqd_w!CVWEn)6d(MfC zC)F<;b}}VnPu;iOoMG5}dw0O7e(Se`SQp9hbQcSJ_*KY^kgtpr5U{fcaOz3DMFQco zhjC8>5q^fP)7!`QOTP#YBqj)+igt%?=m}}d_PpX7KRSbJXo=2Go=%_XF&258LHX{u z(Sn(?A4zV#>-QhxLWGE_WJjz!^G-X`#kx(L3C9B3S_)d&-Y6E0=z+^K@nshE1b+Yo zy(nt>L1Vw`mE%OcR!K$B$KPU;p$ZW~cN)5lxOTd{ftgn?Ds?&~BKLg{0G_*zY%Hqs z-xe+@?H8PGXH??fUZE_w6uo5(c#SU{SLp#ZLME`ecBkOP^KkrU9-h`zI}NLed`gLVIyFF?$hf)+c^@M8lcW zB%`BHYw6`#D~S#%p||DdA1eEr^#Pn5N>GV}M=nW0SGU>$K>bRN9zcu*QXd29I7mo{ z=h(fw@c&T&+xX88S5PR^vIQ+##=|_*GQf5R13%8&V^t@bg`@L? z;3bc!?Eg|z7($&0kK2%cwz8M&Gq8tCB^M;QVx)%G&s7BdLZ9Sy@K$k#JeMJtA@~t( zmK#{33pd$JA#DuqWRUz@rFnKFxE}w~ri+p*QUM(9bp6d8u*m0`+w6@Gm6L%;Jwf?e z$0p8}eU;^Tri`WPof0h(;%f_m=#i;fxw_*OK*Eg(<&n7 z9*1cMD2(6JCh>@~(wpb-ps`{T7BxWvL02t|bNgX+sob};A7B&H(Xl0|k`s)oI63m# zL8MV^LrI1K(6@&|{2|+;H@Nws?ILgyMLbABoRoG<4t>K!bT&GaVG?F7g+1W<=gLM9 zk66QG@H0EuifBk`Sznm_RNTzNPyIjzs8E_3y~yH?%n!&broeLJ{W08cH?(i2 z`_@Pd?Brkx!wZKn^8xzTsSK`htvL4L9r$SCbu~P+Wh(Sc$oljV9xXB#H*lGP|8r>Q4K`o*0gm4$Pm@HvR z_Rn=WH34=Z-rQD*tE=NHJXbcDTOr2JeSAo;;7cj@fRv(rJJG}8BWR3pi^OJp8k`!j zsct{1YEW=?oz%iPam(aY$9Ux?^Es9C1=DMs`2nEOPe4Fo5}gFTK;nu{4i_(8ZniS1 z1tRW$cT8*k8?t$P;!lkf2m~iO)j`X!^F6tIxk*CZDtH13#DlAoc7>Gr1s59b9zsf! zx!t*P*_wmxQW!zVwyl6{Ru@A2#jT~@j@I_zZ)$;vVL8w1b-FdMjb5ctB)^n0a^7s% zgE;31iYSfd&{9;!w!AiOPj?Wl!AYc3>JODa=p(e#8_<@lSG7=rGgQFuOs2)cBT$&% zEo**r(j+PQQf(~Af7>O)y~)$mXK|h*(dCRUJjDaG%CW+2+`Du#W=+#EC(bY3oK98c-l*ps)N792P`V@rv)EPo3L)-=f?> zB`BBd^`+uRL_z$~1k*%T{u(xy9o#OMnnv=JEoZeB-%vXjanwvDsSQ?#+S)E#5n1}P zqw9S_{$+5ee+M)|h#FUR0*EdX#s4Fq+QwrCExUM^;e{;v5pQoo(A-&glbp7w#Il0--7ElfIHzCp5=A>y(kcD*K7XA>Kl;&S|b?hW<-3*x(}T0T}s5a(MwqGRDE#qM0MHL+sJH-b1}5 z-R!ePe6g2=wSg@E6_FDOV|oi42RS!|0rkHH6&;#fRK|)Ih^1;QoiU^Cs4Bn^YrNl7 za+aeP>YJ~59&JFsWg$OOf+h7x=KlQK_Oj<&56S;z0}#Dm8u;2Fp}SDTp#2Ctvq#3U z2|?z7zZ4-f;)5qZFcT#_pJTh(+ zbS1qh__3SNrb?rVl~mzNk3vgV2M_rX8CSq0U%++VKso!!!1z7Ro|LN&`=>Kx{iAC840&|5dCo5Ob@P!^Z5Ia&(tO3C`D z)|h|CTHLN+5-sNp8;yY0<-0)AZ%%b~-Zwnx10?8!mE3mgl(w{IdMr2O$&^%wLNAGWH3?_yrQ_s zrbLMjLTlDVHbI?#IUNVJGpjwg(ni%nFoE$o_KoD)luXtj``%zVa&Di2f!Lf)U!}7- z@P-Wf^Xz@WX~0MIZ`3dv5rZVo4+WIx8cZ_fC$l!vaqI1vs&zKX!+l*P8I3H;BXDoL=0ZuIUlZy{2A<`S#1B+xED_C zjdRc^Z1~W(hj0+T*G$Om8NiF_?|o9+(=jsun?gEPa(?xO ze|K~*)<{jz_q8Rtk2!I`WA}SQ4L=b(Ueh^!#3Uwp#DMc>(3lU(Yl= z<1Ud5Y@e5m_lTDGPB=g1wP7@ad!Wx=oVn#N4@4{f7qY5a)b_Rk125oi2!wBRM+0Br4pt<83H=91XcgYg=8 zP{xx7v|4y{Q^+|NTFIw$Cgv>iSQb}@Li0M+A0!T}otz1PId7#}`2oTsPCHCYsdc;0 zR3M*PGp_frR_d5#Q4P^B?f(1%BpSekX`ShRgYHeilOmvMhWk`?UP`X?KKX0XhFUB{ zmpny8#p@Gm$7wQZ_iFb|Q4*kGCnO^>fKm-UU9!}K-Do&hb6>#pV6y7$yiR`DRP3!k zQBGazGM+a(MU^T6`?@Ry#nv5yJy)cMpG6p)*|kD(0CF?Q34yjFz<|5Z{$QJ^2Dp%F zNB=Z`Oe`uav>frS_cZH?aqwl2^_@PaZc<*+wemji)o0Ir}mVQe+(9LoiP+mL73X;0SU`? zN$+luCsF_mAWN1u+WJ3Q9qJL5V4qcENeazHME#lqtFc7kQN@e9qb3YYhlxft%v<7(Yrt^NE zd2b1ViPd_1T=^>T@v9&B4P8LT0*Trx*PfKz_t_~aPKjo=_&R?fd~jbmBtI}d54WxE zTE7`;47fnTQ}zPr2*}iFb|i zcH`E|w4G2+sP7fYLps+nBRp@hcBiB^6-vURblhDj*W(}qJ2^az44E5{i>gY%cEN^a zyJgeEAK}fui-wtAB9S*=P5;!JqK8IL8OuBf%nvems7PZM<=*W#rf4%Ri3#3jDLmD! zIs3YJAsBEM=g-gt3YauC9rbvD+-tLYuoG!`Aq2um2*I=VW*}JG71IbSYow|EnlD5R z>;yP!{3jKJ0PG)nE_C4-iM$92;(qF~Op!D|{nI>JeBgg`!MIAuw}_T?ZJxb7)EF49 zv2kWd*O(P3eK*}8#QnqWh%_A4>M_4!w{bzA9fyd)4WGlJ2_#NbH+4?&bsQZTaiUL=lH^z{tX8MRdma)cLm*XRa)3c~*!SnqAk1Y}N}BFFjMQe8wF zUYuc1X@J9YYx>nfAR9zyF=#uH zbv7udG~E#(lCpCY5N!SKmVoQb8IGRV3#DgN71J0pC|Kk87&aS|C7WqkIihu=$yiq) zUstrDo0Nc5!Byp6ava?VZtaeKwh}tTr6S2BZPjHk!tSNH)HO2ac$l|eg%Ob0!eNKx zGf!YN-0oI)tqSH48_`Mzeav=?Iyv&P2cuQ&>c@o51UJ&b!vIKOiuP@V9&&U0&d%%5 z#cL&)MvhpI9Hch%lF4yIQVskVmw1g*=u!cN2Zj=|;o4Kv(z2x#Tp39Y-7n*8MvQ7@xJ8YEAbh)b&eJH3Q2 z3hK$Ap5)ABvbezO?y4|1ExG;)Do>y zGycgugOEk2`|TpW0IF#KG#I%)U;G{4DVd+tNd3ynokbr=0c;fBYbnoTQHL)u z;$tepvTgHshglLeO}1d8U2e}b?v1mTsd9n79$Qeinfo>_^c82;K@|eb2$Q%!DejcX zAoNWV`<>u>I><5xL)+B9@_|Lp8pNx2*z_pCxMloZANrhknK6v=2k&M5a)Bk2`K_$Q zAQO0@&tMxnQgageS?QvaCR_VVXyC0g|F@Y=fe@EFaI74)_eq?g0 z?X(%{$g@p&~rnf4`(Yr6EI=Myl(r^Y~mJ7F#8Nawj`*_~j%j!fqXM zoh9seth0z^5~`5!+ABamyRLC|-Jetl=b<5?vTY~IKJ{y9EG07g++Nn4x;>BtBk3=3t#L$R;JY`35(^vEnYqf5#0JB(wmM*gf z_T}3FWH)gL%daVKj{eUdi2#bsRN<&D*WK>zV_3}9(Jw{Vxsb!`w!eenymrl7eZOdT zlF8>DLQr7adEd!v1g?K8k2cuzz3so5uLpb(B-91XZEHvUsOEL)YFU$1@ll%p*3Z;P znCXzJSfTl zt~L64VPXsbxKc4*z3_FnaWvR`$w?g~K3&Ei(oB7n+g!(<F@K7_eHk3!C9O8O1LG zDqzKW1g_b*wBWmv*nZ;G4nJml(244YWx2=KUAFaME;xb>=ciuFpQ7+i4fBQKE?f+R z3C5sJ3Mr*WBz+~3Q1ncWZ0+ulcPj+U7aQsei_Z=)e@r+~>T`bL@OB#QsUjT_3n)DS z%4gY;GhL12+gT)}vP?DM7t>zsmwftKw&wr$(CZQHi(e{9>fZQHhO+moAADplv?y7n_tdC(Y;2UD;d14o2KYMLuxMH4mIAG{@fcFamH1EvFU3i5up# z{h2SBOxnh5Ym@c~-NC@`t{ksShJ_B&^18)&$)yizy zdrtKewMR7l9J%wOUPD&0l*5QKn@j<*4!Gww&B(x<=MaSwH|5q5ziJ^CAt7e65TLRsNI)#$I~zNJqQsfD@o|FqPdh- z21ZQuRh(W1L{S3a*&?3Ii<`sAYE%UCHRQ?|;+-ZNEsSsPpQv=`It@8YearT*U(wX` z=K`+Rp{?Gw{r^Mh%}L9~wvuN>h@Z%t(?(7^6}Lf0+tGf>6AVA3n^i*k2$kL-w4nIW zae8t0cBXObn%->a5$wS|1cx>h^<$?#Y=s0iS%E`?!;0lPf8pVb{``{K#vfo^VGcl< zPBp2dkwQX$qjnqKZD^ia4h}7Rwm$b;^ndX2r#c|*u`_FB6%ms(|KHPdt8E<0YZ8YoO&km&c>W?4KxPZahh;4__Nj$d%-PPUo~sPUSZ4dLLnMBc@Ub zJhB3Y+HN&otc0ecJ+88~k}ZaQ=%$UJQJ}(|eZtPfnltIiMWEzLH$JgKRIqJjyt(2! zWBKrF@aWwps#k-XJj(;AaI6VQ2uFIZG5wgE7ylj0Bha%z*1@5TNFPx=yvr%&rQ-=> zI;A~$(uqGIZPy%ZL@e1yQl*L$N^CY8pct(j56;C-TSSD${&7cCJ`b^UgoK3w3IkJ8 zrmfN!Fu#*KD*?NRGaY?44-b6$N#xN#!6maTEq%FVJQo1;z;^tRT=MK3y9rIDvgotg zm)anZPo|3B(zR&anno*B(U}e15{hMpih1B9CoIa&<}=j6r%$(Ybi)$E2&B>3hKv7p zU5WD{r0_5h2!?9zc9pNVPmTz>V-Tiouqp?ascDrW>!L}i+ zGtvR0o*i%j92Z|%$_oP$;u$D7`5WkM(Y`yPK(~N&2{5?*`Lz@fqc=$7e(b7KP}mf| z#v4rZd3Tg)x_+kp{g(p6&nPjw<)vZ5i(_)Sd+F1BptS%4mSuGb#AFSnvI zng@7>6Ak4_R;eajcAt{?SWj;tjM`#QR=7w5PABj+1PVz(MAo6hn2mogqbrK-% zbAA*GO#X@>IoXB+Dhifh?+Qty>&rI@9Bk&0{Hyx(IT5>CQA}1ZA=~i|2o)$8RsQd^ z*9T^dm@pf@YXX9c__{e*sH!Q|#Xj|);D0wW_1rOwiE4K+U(7ggUwu8W4C zsAWqQ;1V;Bs@td_1|vd(L@F;D!XAA#9I?>PDo?p~g6Nb<_!$E67S5BCwWGy=i_sn^ zUYl6yZ)jGmdSQt5?wmTxvgC%#LMcDQ_qzkYX;lR@_B*>)rc%eu(PaxNM|P@Qe9*=Tq zpKTs`9B(s3m}fE1Cw~JS&Mxg3|kzE z1%qH!8xXhdztwS6nd~P+$Ma48(cM6*Ufmttm=tG{VIjJ2b?nI1e%bmNH|XPrk@IJ; zKn;Dm!Wu~4Wihg^V2j@1?>{<>zi-^g<^6j=+2O>1uHR9DOBN@Tad@k^=nq5{yf3t4 z05hz{5OpvJ;)07TuzcQ1-p2f zdV~Y5;97>`U`zjN9WgDBHw+4my>nVHes&okkH zE4u1L$Y*~5yIQUS+=&=rw}4-+Tf9rM;c(Q3Dc=55>R_|K^7tuFw=Uwzf_RFO$4^1l zkfSc5(#HO$Ytz8e#9S=8HMAM}1c-6LQ^|z_5zVh3x@#lJP{Uj$JDoWAw^*Z1V84at z2-ouyZeyjLa}w3-YhM`;6iQziUIzP`OEU~@m5+Rl@=qanq_9KPW-)PvWJCtVFcnKI zL?oeO@4>MN&G1xH$RmZjx|e>6Vy)SdLkg+y4!?~7AHM4VSOmGN%^ipgMhuZ>xd)sh z6NY}{+JKTw@~SHC;}Ui8GSsf_7f2?4E``E@?qE@JLVBhc`NilLn3^NI=|BPoJT^p0 zKvC=>-0{J!1l|D31dQErFzSHs>bhQ1LS@JwPbZK(r6#oFcm^?#f9lpJ!^umXD7R}y zIb+SeGNB{{8+8V1#Sh*OsIzont5`Eudl6BrV{%(!krRNYgdbzs^Mq5c0WSX*&E_nq zc5*%nR_`OXHB;8r=VBEB_Vb6%^qk-UCrZj!Rn6&%EcCOoca@yS6mgo}(Z8N`9{oj}OcE>z*85~IWV8Xz7)n# z-8CwtF>EPHIi<5wrpZn?OimO|7DkOer!c)#1t4}Jt=_0~6>}row^jZ)2Z^WP5KlZ) zZ_aA^`HgoRdnL3X_FZK^5lCrP__Or5Cu{!+4mTTg!K4;|EU^CV%)5Rr zQYP|RK5!Pk1-YG&F&4CBz18D~oRZ6|J!&AbGypDiBHfPhtY{96pa+(ftt8jIkK|=h zsbX5mc&Qfoga_9T4bmxyIyH6{~ z0C5FtVk0Ya;X?z*iXn};BS{AolEpuXWUjD28S3|n%v&P#j#(3!*qW@f=E zP$f2rcvuc^#xmwslUI_a(<5loDg~*aXl#6FF@wHs9Mqm0yO0E-t*&zsNhv$FIhlz!b%dgA6hW(~_!S4^gmFx*Sk@Kw@i82H~Av)bvE=XjZ8@E2yM~lX*&IEf-U@VV|WR!|E*E z-x-F9<@Uq2bI)#M;72zUn!E>yQ*Y^r8|pI8O6btEqlMHkFe!dk0LxSCg`%`h3{8l_1izS2sZ&LsT;H)8KOIc zP@8hbx!oEjoU4}D9Kj~827K~%D8>2UonPB6*Dg2zFTM0M3^&&YdVDK*z%cW=YhJ&d z3?5WdU#aYLeVZ}NtBih8={m~ z^qcKK2sztL0I8;vqhHE1HyyFXnXLC8oq93t^n4AizCva*;p_)Wu%o2dNjb7II`?qoRGE^R!I~nkJ~!UXh8&2CLJzX z<2e)};|$?<@YbT6KN909sFraOrfh2ua01#@W<|^}KSpQYEM4G^0NGz74Nw8$L#ai= z!Fr^Al9`{#{TCz|G%ZC>ABF^xlt3h-T=~8h_}y^5(Nw@&cN2v^=*8t;D|s_&oGn&& zR+V?P6D#K6z?FJKvN@?W1@4XEjX;`}9ME9h3qEP^q3_!Fa7eDx_k(JNe9~WZn4YD) zeQm2>>-$j`RUG`N?U56f@r^t&Ee|8k?f#K6&D5s0(Mfh?FPOM4g)cXWa{SpaNwidz z)(m772j00gL*~uUBSjYLx%F)n3$spN?3WI)?~`sW4U;Ew7s{1qD#xUU1qABeqCvAp z+%Y18@aQxuniaG;C`B{j1+QQY45-3Z_U9yOu>(iSBLb%7LX0^2iRXgzJhtou%}Oid zP&fX^hK&b+)JE_K^SV`A9uIOahbFcg1t2B&n751>dD zz@=u&v(V3FAmf&(d4)pN%M+TSLA?Dq;-zzsBk1r_oUZY7m&I=e3@|svVELM$dhPDtDn{d-vpE9jO+oK6@tw}9M`S;YjaK8Y=aWIxfm}vh}1LYJHTu~6ig%* z_PkF-G{nS%oUy_0+qt(d%PaTANXxn?iLpz?lV)^sD|DY`lw72QDu^*LQ9nFf}` zWH(4w^RX*SjXnwEG`=?UWaYu%$72Gb)58na{c$pAM=_hAI=+#KooUEK5$gxxspC@w zM_3G*u(kh3__7q4;g1FJo~Vo+p}PF8u-EJ~qal8#qi~U5wm?TTn|S*xD1C~PO_91a zaWFMvS;QmjVO>M#bJ>{LU7nNZNZXqX7-zTB=b-E93@HfpU>A5k9i>zNmpHI_zVWOz zGq*&bM_9D7S%10oSxm(3)XVBWHY{hMj1_w4RmRJN7K;D@dT=#L&~F=NzW7E%Ok*%U zJ@M45lmN5MEWfqC)F7$|k5dLc%|7z4+5(#+@CVlp3*mNrrz{SS^0GV%VVw+&{@^8A| z7IHmyJN&DlgN@Kba<3ta2PpCjsn(QlTg11%0J&a5qQZ#l?H+;-f!pFhG{&TEaiL+q zH%Uu5{Xa9i>6YC{_o{#jpqyBw5k~RT)YqxSu^Ps_h2%DqA z&Wr;tQ0zkz<)tk6u?ci3kOGL3!_`Rj;URYq( z)gOg|RntxscyZ>iu<1LOzMIOi08RKM->%7M61)cJ5Z5j_*DHB?XbV`&_P#xp=rW7$ zOt8QG^jGtm1TwEo!@@;GKWS-da66AAWS~N6$)K`PV~4QcZvc2rWOZv+RHAKW_;pwt zzwx3!OdA;XDvyfLlR|eoPGZjb?_F+!%0MQ*X2iS-nBD#0_II?#^`L7ckvG8*sVSWK z^TUy(94M%h6D$%0@Pr~Y^b*zf&*_@Xgv;2SwiR!t&S2NeJsSA~u^A<*cw9yO_Y07> zB=N?%z&?1~jQqr?X^7s-OG(W5QD)d`$&p|N+D&BsRz}f)BiO~jRccY%H6Dfe%P8Kd zJ4BC#VUq+{`;mo>-};=FSg6EOL2zUv=ZBQa1PwWN@eLsST)0m2lc`9c$VD4Ln9MVN z{X1^~Z9WPq^vil3(>2$IVIPT6Z0Kg+h{nhzPG1B}sz(I)nqYQ|nZ4xTo5W==`bxkq z`uZmyd=iWk-GA4E7aEkUCgkQmgO?M72X=VbW83WyE%h)aS|yP}`U199t7{sW11`~} z-cu&sg;Sr06T3U?>kgoV93=cUx#_1$Vt0Lr1Rp+Mt`-v-e=oJ&f>w8b( zw)FM;4!$hxqxJM%uI0!@oT0kmeeoDcNP<}Ag9dV}-BZHy6gAC)l&OKfIwCqm(G2|$ zBWp3}jNVU~`KlWNy~fc<>yt7Ouh}xXcEGmbkllhG6#08bJ9tf%>66r9dQIln(tUyf z*jEOzG&PcMinrtQ34t@YVBFLi!yaCtNP_vLT z<*a?$dT^tEQDkX4A`NN}04`kzY_g1}fu(y+Gm|Zk(o{~zY52zN2}F%Z%`YXdESFef|+rIc_tI9_ZQI|;QRbq~K0Ha_kWHY8a6k7p`KiryFM^~;TlJ3 z{sko2iI!8rbLAEp(pVz695WUY%j)Si$EW96#=1w{LjS0V6Xy-`P5}%dhdg!$ZfGU| za(cx4-e7C2z8A9OoTrz7o2u4-GdX2k34uxWyg*I{PrjR!55~QOHBu*IS;`tf`7Yc% z<)?WUwQ7bQHDwdM-Fzfk8O3Qugq>AzR3Oc!cy+0_b#wH81Y(60vpLq|s*FgUXfQ zcPlynuhJ)gQ{%olh3(@oZcDmqC*$Zb3kha8?piy!e9$}R+?0Lb0SLQR%BvyS>adTzj{c8@NB;Amv5p=H`a^yyeWN&b^E zTm1zT{TYnw$x2Z~jY$1X7Q4`E4F63Q8Wh+iElThVzXk!0Rti$CWJ|9S#XDH<7D&NS zw8qks`QD8Q5WT)pRny5rTl~G)^sfeddrH+g6R?i8T76$~)CsxR6FwIlc}N$YJO22! zbz#b8D;w3Xq3a}yz8FyD2M7@VAsS-}MWY8ovHD2)h>Y0yfgfCAU1rrmdwYjIv)?N| zv%N)2e$bx@0S;=TxxF-Cp=$$$EGhgFbQ+CWhQ1IpD_(9?C4Dz4Ii2A!FM&J3z03jY z1*mzw8R<-xG}1cRc>BL>A+jOyLkGl!)}Q(m0^ziYI9p#M6V;Q2CqbCEuM@@u479%s zD8UGhN!j-9I}0wDL25ajj5JNWcb(REPjH*~lNX_{g3!w=dF1~4?wAtlGHJC_=qIAz z&3&Z-@OJHCd{LA#pua&3=Xx-!@Ifx)yXP7@-@d3nlTy|N-Q%y{MNgXS1J5mv zp;bcQ_@!PilEazgL4f_639jt{UO)e4 zgPe{7i!(+dmU5?SKYQH6Np&*Bfi<~NK)CU<4BC=w?m4)z0%guM-fZM&JrlQAbc;5B zz!{$k;8xq#sWhW{d%O(_bM-EHEyKjVaLE!#_ArC?J;}ew>GvfQz-j0X<4v9jXPG%B z{QQ(`6{RR0#5REl%vCguB34OKF4%&&bJ?HK!SWIDX5$85aUO*CK>q5V7dL6rrIvdkxk-p1x&=e z%M03GE+##byX<>=>u$z%A77%p(I9W?G&et^fwgbAO%cufSxxZqc|p&79a&00X6l@Q zyLYvQAYQSV|g5U+cGe(=g&M+r#_+1M$<}4a4Yut#HN1aujM zB8Bo%OV~va6=`>i-U@I57d?kXx6MAY@>)Cr+XBdE9HCtG3+@Mh%yl*Ki8kc8Mt7;_ zOfzRMf-t{^^>DPi_Aw?2SJ7;wiUwaI1;Q~9B7muN3JkwB5o1B}aQ3YpuBab^ z@O&2tO<-tlq?9a#E3-qlEOF57hN`F=5emK%lCqEqUlP0D(f<&)NT6hlRFIl(ptAXa zFC=Bi#<8KdnIsbP>9*f2!QhYPI77!DDNM8QFpBd0dNdPbq0=d|?rP{s&>ijPe#w&E zXzre=&es$Lb@TBK>DrpI59{|HOd84XqF!+oW#4ITrRf`*$t~mm32ydFf;EmaSrhVM zWT|@fx7xH2;clc-!l@pZii3S1>C?6FF!F+kG^r%$oS6YChnZ(^7klPQ$|||Kj&Bw) z038#>x6K|?-_zCCPGNzY^$-!y{d=%%Ii9oV_4!O3sQfGJIqncz!`O7QNxpff#CjkY9HKD?+DOU5EJ_G@~Jm5%j zVzlTsy&@!Y1#$$-8OBccPMy zeYskbgo7yObGw^L`8ap$9j-JyZfn2f0a1sBo0Y8oFkQIIE5FE+VJqUQy)W`}u5m@W zWXiIqf^d6%aJ}?=pu^Hp=+RIl+RQ-ph6yjnAIQGG!hhs2A* zX#9WHPu;L99@^gcvAjchtf;3)rOw^yKnOERz$-!7AGjfGtwL+gBx8rEJmyN#7n zBh6Fj@QV_unHKi&(+X->+HN*H+X5XfiBZH!n~`FA{@a(*h(-|!i?Nvu4HbD{$zNAuRhZ!hK? zti-tEsjsubP#7eGc}eLAg1QhUDF;{wJv|UJlW$`k;|S0BMVReK4-cpLA(#=7gD z1WsQbR(3_E(gK50)Km8aUH11-Na6Jc%>*YXm6l=hs&2BqBGYPUg2QWeWVL+X%k8D-X~e-(jiGHl&?=JuFD`7$&=xB=;dYI| zamHKT{$jfXy^&5;A@IfFOm8X2xDo@}ji41jaf$L0`}pGk?$Bl~jOdiTQ;=vu*QQxE&nersZQHhO+cr-C}0q(z4t*zP#b%-HVHFh^&Nq!LSYz;{wH)dK{IVN`boo$!wbD9o&qC zMf3~d=FRrQwm&udDr2EnE#0i5h@L|oZRv6|E4~QbqycnpHYmm#!}34P%3gG()Rnplv& zA$@?}uPiyZJ3zx zm?Bzop2(6(jLfp6A+XPbqK4`LI3{nqj23gWJpV$YrGFSl=r$@HbILb$=g$ z-r7G#7wvlr!Zh1Df8OJnfJ>oBRa0MppN-Fh=*=+y5|&WBJ5d@DIP{^gs=ROw^~2aE zbd9$7QL#3^l*fbo*-l;bj@3`IXkX&a=P)UJ;Ps?za7qq0d_7aqj80UnezCH=KB z|3l+^nT5;>kqD6Y4-JRrdi^;G-2CgRdDBenpPMHF{i>@lea{A%KVi_*05_J+lIWN? z4{188cL+Me1Ci>0Im-pAvzt1?UEBCk*l40vhaO_z+DWyvjwW*ZMgP)Jtu@Wd=6UTY zO15ojJ@H=FMfh4+anvba{H6O)j=&_8JggR#kwDw~n%=7S>u2(6?4+=Ipnzk(iA#Vi zO6cf6QGZ(~M+>8$v=2Hc^B79Ds1TeYlGDZXNM%i)ovgu%{E)MinJgDH>v}L3zivwI z-bY(hV^D~ny{g)#YYd1`TWwqjKB-I^38Wmg`apMRw-egp(KlL`mjzbJa%>Odi@F8r zG1vo0rcvTyyEu|~wRyJ%C@v#)EE65=0gFDB79{X9zqEtkY?2vYfCym({538^&v0d! zbZ$iS8LAmp$Ni5mpk+JTpeSu?5So8zCfLvoOOQ4=jeQY9>uPU+m8C&}u(7w=MWhDJ za3A;exe8`O0Ok;K9foKbxuNfEH@!GfA^s-7#s16~OqQH+NhoybvK`UI3d!RD6@_Db zmyly|Ng%u0RZiC+7g@Y1}Yx!uwHajs|ht=;#{uj5t{T zI)FW%tZ=*jjkDx%d`QGAVw|(eAjXdC_23(&UoXt{UVuTB`KEaT7V4CXQ*CtuQa?%I zXBgw)XE7ON1@6Cuq$IU}Y_KB~#AYArxVG3X0g;(EH4ZhP*q}+|bz!_NuqVaC>9@Av zRxYvR_?GLK%e-W22OK$fi&l=afhR*WlPlj7(V)DiZh73-Q~`>r=I&VI0H5rIK>H-6 zdOjEUVv~tswGJ(pK;sXa#f;@t7+FAGtDzQFrs=sVApsyql$oglk33HEp5;7njsz6d zZMlIhnn2^XaB*2SoA8*3hCsr>Z8i`U2m^1B;(iZOJEY2M&)$_Rkx#`1MtWk}@ z!B}`3+Lv@Qn3xpdSeVS>!>qFkW-Qzl?%2Cx-W*k44O3`Qg?G{zfxMyxJXr$qUNfXf z#M|RhsDedWypdtOVrC&C@oS|5*MIbDmn^g~0;;nZE;kx}9rlOEu}+j_Khvn8+I#j^ zxYjP+=h2_*~!};v0=8k%I)2HyvfYoul&N|mw14wLO z+vTssgz#7k=lM06br~DGq{b%#z&`;V9f<;OXO#&gSPBQCqt~l95$S-t#;0MrbLpR^ z{%CC<6=~~X&%ClzE6&urQ*Nfjj%{SqOHx)iD2A(;vM)4rRHMo$P!6?Xy58Zq7sON< z{6M=6|uUDIwT;DQeIYBrYy3kA)+!?NZm{k$i$<01-Y3S~K@ z?q1Q^dwjT&BV)HoCiwZTw_rr&NDjQ|cFJ|>#-FekSfm#l<#A0D@j^oJM#4!(60}n0 zpN}V8f!kw|zT}K3T9Q4tPQ!+9uTL3TIDmw*e`-yGF3LZf$ny#vURDzhlCUj~iV6!y zrY?>)B81Zg@ zm;IRM)$*{1qjK8y15^+7 z*M1naTx6ACYgxOwo7bs>QR+AoOS#12Idmh8Wl5b*nELKTb2;<$D00$@mBW;a{f!y7 zF#RJqSS|dNkP79%(=LpE_4h2 zGV}XZCP+6k1!Y8-O0jRRy=6>W(F8xfD=Y-J&4oYTRnxz|{5bI7n%#4YGTZD8GG$h2 z{B5uC8b`)>5vJhF1FI|I_5opeQ+{5DmH(cpT9I#cAeHRe;?wS!CN{4JL&d*_;KR*I zl)P2JQUCY)dd@Lr^h!mZhjYpB57EbX!YY(^knIoxr}f{PJ@ZT%*NoG7ms4WVJd(k@ zeX%iNbx$A2ahY~p+G~#tQ@_0sl@yu!hw|&1$-=1zfc51xKbcON*DJcp41D+WlG}$} zxIz&Z8EGW(1^>Z>mi(btdU7o5Z0dbs%57d$n#L#&l-*WL(njA1J1x1b?H9x*dd>^Q zj#jjcIrv-B#KxAb?qp7gM_3_McA3C{TdLuXN=47WcXH6N)fuskNCdI@#Oc*N8#q%~ zqxp2~L2MEZCkTo_q9rk=)31``7JnCL4bQLWkiy}>MNT;oWnIK`%^GcMBV;=sLjxv$Ar&&3M8pC z+4%{OVC5w&?mr+va0YB(aDRZ`ML3W@bh5DvUNeGZW2qJE5*gUqx<6DRb6vpcoxqX{ z8yt+At(EI|YFLg{9V)7p4vuX|MG9!I9bUWLEVCo>M#&BlI0%&jNBU!!*}69nD!{tu5?ofy%aMy#LuRq3l4WGwOFR9JE=&53dvYrPXvb#X2SVHI&x zTUD3%AUIKd?sH`RD?28T^gYlpg6wWmo0esRKg@i9t>AWPlhmQm8>^axw=fw4G zG@=kiY}&sc$zVRtAwPS&uWhdfeF=F*z)i=$cWQdc#`u}RZC*6AQ^Lec+ZwT$(;IMg zcK(A)EBZ5F1{0A_ZX?7JV0Zh9Tdv-v`v$$FUEm3>-Bj+Ur|zio;UCFC)qASn%zfPb zEimMA((oyU88ppYXM|W$i!aP0bqY671mCy|lZLn_Jl0e4OpAdKQnHZdGEFhiK-k`l z8DE+f8hom0gYW#4=0lOK_9|&xcrp(z;3MYC(uXq$c5khEZ_xeH3deSvaw8lyDTgbA z3=}a;W+>`p4Tn>#9?-{?Go?e16f_+wC{HkqGiMMxk<}kPY{?e z&szAsKe6y?(>y%2O|M-2PElqkq@*ZdUB|weRT<;|RA-w#mY;&;ns*rguxtsi-tu=S zHx=9QLIHUQX`(8D3qC=lw+eCKmszBQd^yO4>Edof0gL3KsnjF zT-2Mv@ptG?k=&*cl>ZWbH$R)^`?0}E-@%PpS9CMi*+K+MLVKDxC0F$JuT_Sk;Yp^?EWy zZbMuqh~=#JPgV_b)N>W}yO#=$mdC)k0t*VAD}`{zc8hG9?)GI&$|bXB#7b(la*2<7 ztapWktBo$Pne|hCqGwrjl^;p1Qg0=>bUZhw6(kHY*ho%n)*6DqDU~8UR=Clq?;JGh zP)Isy&6H{zsGXJHwZaXd%k?tF_`g#)+Zw-d?BUj%sL)Sl5}c7{|<_qg65an1Trw02eqJe3Kgm|40*;ZeZD4s-Lf{X%6?z+W?yJ~8cUPV zPP&vQx3fLSW?lH$(Bf15Af{Oez@bAKQth$i=Td36(0|Kx`Z(mNF=JxA@7c59n9IcZAeawUs9+v`kUw10SUR_A{o^2NqP zY*pIJOwbxay7Ki?MtQ~G+FK;X1i`f*{?|i!@5sEZe~6K z<9Q9KPYkbr^3J~uhAC_0fN0gaWCR(oZ5M)N4(TtAl@Lu%BHbga#U>={!9z-nlUb_N z^i_}$ISq1IS9%g)d36dEzjtv8a4&VP=BnH)PIM}Mwif#0DcD2Nqx%XTa;NCg3UlptSi6-QifiU77VFS}?Vqj7?e9>mTega{ zkmHMBkUVI1F-1;!-!nHXe{WL+RNPoBF)4(6WfNf%eQ4e5T$a$pj%b+)o*EVBFsd;qz+Ig`i&4v%0iZYk2qMk zkMDWfpKw+tL0FKeJGh5arX^flgg&<4RmRJbnp%rlpMD|%nsTZ7QK;gI7#cf*e@mZL zz51it0LJ1cT61|4yG#yTBxaJYr`wqtZWC4aHEW$H#!f&86jqS4sKNF|*{_h-&3*~O z$XBP0a|FRs|5Ss_V@m)V1}?W+mibu(f5_{)rzWijG(aRJ)3%2kS)m~l%u+4H5m}x2 zcmnIe6{8t!Fw+5OpkOk-xh7z~oYZ&;e zxhGmZ)-YnN7ZCroFN!7Cor2E{4zoCIIPmHg7Gz?p{OPgB}k7ovp%&C z&u*(Va_P~)rONK{nLwYK_Zb9*n5~k>5PbE~3^y5rKmJEn;7W>%tOP6XFa_4<5hR_A z=48Fx@^%HJ`EjfTyQ)4!U(gO^LH;sGK}Gy&Sd?e7=qw;Lh<>XoA7e|QcDvZ54>bWs zk1tn$rJH2)dw-jmd%5P|DtX^ULp(Fxje-o`ai7^Y(w(*izh3u`4)D)OCukoz>_SIG z0NG$h6Kb5rldpRkOTyuj!#M6445h%9j!GYU_q|1Dn@Eha>yES`i+z_0TllfyNx|ZuUfsm=)bD~G(bc_bg)7`EaJE~WveXOhj5~4i z+h3UesyMIR*sDdyNG+o8Id*KfZppTX0?W${L$m~TNatFmEWON>kLK&fVy59f+;k64 zo-{AKUr18W?Kd9Zpni`yVL~4*m%}30Ipio_R(+58VQ#Yj?Om4Xjn8_p;%%8+IsA$Z=-L|0S1dxyxQ+71{Sn=+|beNpn^(+AIRgsMX-`oMm`Vg0rX`bpn=7e-Lh_-y+s3r{Ri05{*P%m^-vVGmZ!n z2FS7AcyrPN^C1HrhfaGQQjXRix1{y!#s1ZiJ7>}^9k+guxcHKv@PR9MFSkYsAS&r| ztvP1Vu7{gUR!muq`#hd4R+NUqB32p7S$#Y7u9*`Fbo6dbU55#eug4-}t6 zJ9$J3m##GAVAk+WiNseVe@TX91PGF3Jmfz+OuUe6)Wxtn1(&)8(A=jJVO5 z(A8ZWn3aEKL^m(Ix28{ncdH0?<2g-qEUeVuPGtT4<`6x0m>}=m>!QyCge0kqw`C(n z2G=bW*4yC#XV}8=`M%IWQ!E-iQv+F)u^IeSS9GKv|NdU&;)@@yZlTA(+GQY(9&KZ+ zE74xMBX%k^P_iPx@0neO;t}iUINDHo$asz;>gtcE6VF%R!>Kk`OVToZ8ps+^idhFS)aSR*M%C(o@gL zWbOf3!*R0%I)KPhmnE-PyZqzXryP^c6ZcZI9!uxeyxjuisYtz?q^IJnB+YkVc7<_4 zAekr+?FJ)Y2Z(J`P>PY18lWh}fnLKhxvoM>T$;=;fK5cLRMSXP$~5SC-&K^4d4pWu zOYR?+;*I>|&;cO^q%}52Tq8nTGV<0rm30aJ`k;4{7lj8_FCU-fsa8)eXLcay$^rmS zT@yxv>MDgQuje=WPPPN9(++c3w}F@TyLZ|TF*yj;DAkLG?$O8lx&kZ>eiH;D! z2fr4FySrdbCl-kQpX5A64pgMnaa-Mf$~1KU8RvUq0;te|2_P58jk(TZUuYM-u-h(Y z-+F@dBhx)XaPU6MV)v>VHij1tND7WIklA5K(?@e1hqh{Fi7-0)0G;bAjV8X{b8 zOa(U2!{a~LS8P?A={^cEqi?k+^`Cm0leBjfg%fa)BP|LAF)l>RN}EhMza@x8M#L3- z4oQ3fJx!5p#4xh>1~viYP#wletvMz&zA*se7w!bVXNsi^!obI%8?Yc-5ux?l$yUrJ z?G*rnj2fN4&8KCLg#WZwLg-e^Y*HGMN=@`>z^RTEdVrHU zMvY#b5Olm`^X%|8|9Vc{<^6eb8!QIQns@98P%u-T03^OdY6J&hK*H4IDYGn+(?WyX z{)cz!M0rL|(ZOS*G%c2=hj1B364Wg>3TP)cjZ4qB52U{UOm*-{y9LJR-z*DlJ~RfY z$-B1g8CRxlMiJ9C)!^}%U|ntd42fXENBeJ|(K%N9LgPB`hg?_$Cgf@S%^n2Wy1Xes z5|=Qcq$?&uLg(knUFbO(f_u$E1)9_|v-q&_+KFm&K0w+4!v8d|&VDBKo-|||5H$8N zSHt^yJD?4jo+FFfO@)LIRnhRoNFGcmLOy3P=@8~!uaJ2BJVnFWKjn=WSP@F-o7T*o zS;&V_;u&T?d1PI?Iv@lUma@FV+it0A}aTQ~D{=U+RC5$Tv1@#9{jsR>p0|z5_vh zNkC9b9Luh|txrTxXjne3SsuLw@dHxUR~*@z7ae3m-4eionCNm@l}(017fS5<5h`zuwB8twU~iQJ<#YSOQ%>Xoa6c;T;I|QL4Rj=8zheu*4v0 zbjq)~Qh)>Q9x6O5ZHVd(qToaf!Jtd|4zI|Oj-POwut2#02zvm^GFIyPkrlm;vH-OK zItH8!(43OjFSkkVEg!gYj_4Xf+mZ!zJ7fz4|8D`I}F zxpFt&MnP!N`N(NXmIx97+ak;%M-R(RRW-z449Fk4kJyiW4pC?C_;C9=+M=;yK>Q7& zES_{VJ9AX`93biwhCb6sQUDmUH`Pxf#tLjVu`Or9g*Rt#r2dQdY|NR48zlVOWQ1gu zFHr8RZp)(J@FQ8l1H6X~GQyC@l3+^ZJ3yL?h-J$<46y_c!GhU*6I@7BPDB)Si+*bY z{c#XL1kU)&ewl9)@8tPKWn7Ob$xuOa01;|N+XyTDJ|b3B@b@uQpSu65sL`d?1&B^l3pWU|2C+ zN!XU*4Gk&p=&lc{yE+pht-ImRJnAjVb^yzbswltuKD);$nR2Lo*iYv{WhB>3M|x0k zLM>U!+aGQ!y|>jOQHX?RZtE$jNVJ1l_C&S`FkbySHu@{VXWS#1{H{Yj{5x5(q`4GWpOAjZS zy>U_lb{xZup_dMo^Tj;^Dp^xlJ=iU6gV7BYaI$8NX3N{xq==-3K%E28#OA^<=1#w$ z6vurPHI?D0;DER8`vdfA+LXm*ptJ5DR}~fg4i!G)obuKN?@mdije!KUBA(tLlx+vJ z1Kbd(uW=r6>a_o7JTG4e_?>2d9bJ-}^n(NX3Y12&0`negE{;I}6{6+Svr zjn$@YZ0OS)T1pe$QOsxVEx)_#gcWTv@N=Zsa}o~mJuk)J>ey90N;$0uY=LwX3<>R$%Ho3L7K2(~t`qa0e`^uw%W)3gIL~{`4K5MkD;|R+ofRcD3dyQ7E}u zBi4GTh>rDF-!U`F?F*B=(HT!`7o23w0(E6LM3%Q1UihNWx*F7jZBKgQ=&C+ z)}F)eH9Y9B{-~Uo#Ae16j$+&Y8pL$3yb$~3i+oRKj%wq^wBTJ2=^Fb*Ohu3%1(c=U zm4WviivV>dBLG(CQyebmpqtW`8%}icENouYqZt7w-?TKGU29vxbAi?rEF!P~d)mUY~NKG2bB7&fi* z(=_jzm!R$32b$dsX2NF`QoX4%1u^jZ!^^|7G}qXTCQF*PpJrLxtud2g|{K&WhWCb=5ST?dQ`3y_u z{5OimsPZ;8a>LrW>B7%pc~VM+e61(7Z#Sh3^Fz;3IXE#3FUHaz2%4u5FS+59QH!RuvB#pIO0(vj=4jL&Q8T&_(*4r0C`yat{ z1G1v_*zZgqN!8Czv5Gynm%t}OoZ$c{S3?%D2$Z8S;}3jI&emdJw7uXt4GkA%xjP+s zHl`ak0d_~+ryDXwXQ#X^5Zh$g!8K7uU$2OOZX&hVo)w$6y&Dg^?CnoLz1+XcF+P7F zQLB?pdf1A3J=+qrK~T#ZjE*g+JKqL~kk706YcQOPf3qaT$79tTqPqM%#jue;D*L`v z+IO)RkWHD^g6V_?ao`vvedNT(fVy>iE>n?cScQb-48ma!*xK_4RPhVQ@nVt7wA9*n zd8YG>-P=th{K0vZv^T&cc{*(qox`iIrhiSifnCHgvVyP=LAYj*Ebk@r1Oe{Fw|c)? z>)^U0bFU8%7H3;u@ukdY#m0cYrPN8~mLQfH`qE!9@|gAlS;wt`D5pQ&mm>EVdS0ht zY=`TJ3go0y6E)L)Lu1}I4e_CS_!PEMvEn9)i7|=Os?e{FZ1x-rVH>@$CjP=(zNjfq zvIdFpI8|yaLvZNqq+ve3u{Q5&w8%yhY~jI0ZRd&3V7_q&UxO@VAv^1o=xsKCeqeX_#lth2mp#k`7pN0 zaMv-+KFBAG-cSVVEGsvRR7K^iqGEa{qua0^98iA#RGpWVBRxBZ z*=<0Htxb&aDLoiGq6!}YW;FMs?r+fyXbu8zn-d|G>7g_dU;n zb&Frc6?5pLsfrJVn1P=!Lsfvqi`s3PbL@Va0pNgv?qB$N?qcjq&_l0?uZMvKCf_dX z9c2~YVmLB$_wPCVpWd0XQFhaLYqv~06Rc4rC?I+P#__?c&yAs)!rVz;Xb%+?e!#^$ zcs0jd$K<$Tk>^D@HOvg=0%{C_UP7VrK;#VJ(WFb5>51I|hQmCOxB7mUVGcSLxSmbD zd)CYX=sy3CFkoYdIYheYY7Y|z~mKy~IEssu>* zQoQetboNTW^qqP8YIErG?RE=}-@UPdLXlc+6eNgp73tDn`J=JFJW#J!stJxXxnMS2 z>f`dfqQx7!H<3>^MT?+0PRS?o5j*+dw%pw&6M1x!JM1K}t+&2VrJom-I(EQ{#e0azhMA&cIpCr`r zbtY{xp4#MFhn~1`>_yRivU!2%o3NTwq={E;DcVTPIpnp9A&gDhvb<4H?`e5IWrcd7Z&nLGVB-*#J3pQ3Q61oO(gaH~3^PIv zf>elF)*D#g`xRl4fZRFU?aBGGLmm+r$?&Iz>=@DE5bfHSYd7ou#C>N2x;e@jk(Ldg z$BG>k8gtBxRbvRQ#{*6Y9U1`awY-C~NCX7a`sGH_wVKL@8#g?7zqr&dV0v1S72gm< z1+OrNY~$2=@kK%dH1&p)2MJ2Up|F`oqnI0EW3w3(*s8#f4K2ApEV#!lkFjbn7^g)^ zp5;Aj?*Dv1)*fYjeQ}l)H>NGf>udgZ=h5Wro(>tYdyrt6b4?9eXb$N#w(iv2 z%(e>N+k0!`cG4{*w7*4pF_w$GCXJ&2!-oG|tHIE0#a$5}Oc09ZOaJRSWn`NHHG-?m zqn^X_z~cwCR$>JIEzl($&#KCE+;ckPM9zmm^^zP}`qX;6T(C<)!pYNeH#|d7E`BYE zyRItX`fysao%w~9eXWd}?OH4b!4JHzY}IvWNOvyl6?%;d2>!K!2!=WPPk3`Jc&I6n zygxm|?uAID*n?R>?H}mvWgyKN?|M|#0*|Th-z=D{xh?6x)cGHkeEqu^h7DAHAdQ?E zM}{^t@}HAjfQe9sajnf5i0oG3+*&j!xX!+$s}aVUN#32WnbV^R4bRPad|g>1^vK~} zJ^88?6+8ZCcEh;&W3n8 z#L|)?TD|0Dh&S&@e?5u;SDR3(y+gxrt257hP5(?GO~%E}8{_jlE`FJgQN`q3#bO+6 zbgo|h_^uB~j4}uEqDUG{FP14*c$l>?>^B9!d0~BVk3L6b{>T|sJ90l6HIVK1u{~Lh z66Is%MDFe8skGcA58%_Bq=HwErT<78;F*mr-0StD?LOUbnfIH`!L}y3-s-FbTRA(PY||g2ojgumZaceE^3)=N0CE4|l-M2Tq=bzRe|SY*)xayVK~9MsFDvvwKOY@W(NK844PdSrAa zk^T#~VQPnZW+`->2}Z%p4k?8JvYx?ZD;xcOd?<$^ka^e?IS;g+Qwu6NgiA&1HoRl2 zW=dw1!cWTw$iLUlx%v2RTjyx7f$JG~yb4h@BB65T+1CPCh+wv$EX@x?!WkYm!obC( zlbkkWjLY_@@y0CU*f0M#2+D)>eZLma)lK#k5hNfDQ)pR+1QB75MkGk}$vVQmjHQ@% zGNUa$z#?z9GP4@pJ{11`_-J1U0#@Q=W$Bcoa`1N@QMfpC;Ky4ScJ|0lmM;hZr)5j| zT3|0Ayuyb^=Qnsxk>myRYzF_A5`k%@NeA?7TN z5}RLT9@fIDqYiq zYUNU@q`Mrv8qJo-gTRcY{GHPymg#yTAcn6=--YmNr03m50OyQH_}s%>R5c@`%=h zYhU;iYdPlU!z8UA9ouXv?e16dlBh@Nrbx(DBDpn#&m&?8@G0#xeUK|Lo5}Y9h7{Ro z#DR}_VJ3a$E8G%&OmCSi?OXx`K^tv{7~ub`kW-|vG|k7)Dp>k--Kb0GE9-mm9D40{CB)}H?aA7`bQ>C5V->;PoUd%G_`;%Ru0+rxH#|+Y9&}&p`-QVqUi{C zop1MPC6ygxux^l9Yt+drHZ3e)i9NC9=ACKru4!BtKzHpT>QPZ9R8B5zGO^zzY${o= zj@N=_abuTbp3(0)(}?}YXBaReh5Z)OHVpooeQ~+biK${L20vDN-yR=Q{X`Ef)9i?x zglpP`QQc@r<)GDUAYyuZBj9(HZ`|j-R1z*yUPj(IBF*-DyJ7uwT574 z=_Br~^D{{@4D&moK?dRsX4PpjH(11)COPXju1KOm|FQu@n?2FmmD#tRrqo!+fw@R1w0$F0VXhgLU7w<8 z*EVz|rE5h{U=3>ssIdX(;GCpKAm+~2g{}e+EnV?Ioz9B)CqK>}x=TEE(meN4=3Av>kS*yFqhvSprk~*-#Bu z$Q-JJ_uZ89rAM|-BZgHxVY<2!T({;6ZCYa>PKdQ#VXXNttGQSGSP_G1+ww@Wcy5cS-pZgG*S9|z2Vib8 zN9&Y*2hMHAl&)S)=(WZS=Pae|;cUtBdFD1QxlY;S{a+jVyeMOQ7DbhV%RV$hDp|qw zB35`JV9mV#-PUTBgWbZ&_}*SHM0a7y=5b=-o$;8@84JpS+e*=|*Cod>~9ii5S8jU4Y1PY)=yPB-{x>=6wfut&#D>DuK1e%+Q~ zkYrIRU)G&$OT{uN6&LKu`$%5!w;BKG^U>r#@16d#^&Co1YfH5;yp;-zD(b#u8Dghb zahGkQ9t7&xlU*5x`-F%<$EpBs!GaWVM4fJ4Tp?CL<*OLXJ()37iL7r9M`Qz1ZICe4 z$tFezcldTxZJmCMKJ5Jrh$P;6&f+6b99p~c3GG~70p{ZK)(r}&}#1=a0Vdt z=NSR9G)`9AlS?uVZ-Z4T=INGTM&&_2ZPUPz>oPaf$|I=2K?eYLhUyMPrIy_278rx2 zCz!pZ;N~Dcv0CDmxB$1PMviDl*_R~~cCjj4lKU*u{tAo^n||DLsn)jgq!YrVk_8x{ z!_W(P7MWrtD#;l*DG~Q6rkuY|D|_7@4$}FpJ}?iFoY>&MU#6KquL3WF@@pXZl?Cy1 zX^?qkY{6X^FfsV0-|o@cozx_Bu{xEuc>=W`ylACCsMO~m(}bi*KNWj^W8&`0G={?t z$Cfp`xMNRo-IoT&%65(xzruuG7x8PKpGtMQ+)Gw%qHfs_I)zbkn5jyC@~YeGsTgb> zq-p6G0pt2RkO@a>8PwnIDmapbsa@R_{uWpdj&9hS|5MawEZ7N-9xm_HXdE*}_asgd z%1>xWAnmOqf|rY-uZSI^phxSiG&%sSKBo=;t7&K129&rF1)3^?DlKE(Ud>V~;4*ss z2-@hv2(_dZUcySr@kL_On)3mf$+82N`#6d`oIoa(3u8gb)&h+Fp=5O-l-#ics}jPN z3Ch^U$kEBcSl{};X0`?vP|U0hcyxIGHRIyKqZKi?ax!-KeOl=|84DR3+8P<-(MlQH zm^zu^v9Yq^@$f+X_i(q&-`pj3g9WMcLbWy&^w)o}(8wD!1W=*g4|JVqlqO;uN;998 z!fGt;XyE(9VcT;XKp1|kZ}`-F`(RQoAIIn89c#mf*yFdq z=i24@;C}66`{ku$MfUuH%X!8}KK4oRfeCIRl+OpFW1;HBb@?YT(-(Uf7pbxUNB2|r z?q=XL;p3O zQ%O$E0F#fxaltYNl8d3Ptm&acw93A8)wNCR!0L>F9JU@S!>_KjO+4lM%{0Cq6K{_; zs;>`5tYYI@=~9c`L;Ixd;iX{XJHv|)&!>q5EU%EOfdyE~Z@$GVO3O{{)h+|$X| zTE$XL$n*C1y~`a%p5=f|d)dp%MEApkkJr7?933bcvx>Q! zNbg)RV8LDrSQK{JtkSCgoPpT{HFZd{nYkrRZjrUzE;``A_m-*gb$7?jhdKe&KAjq7 zzYQ$R0Y{nRZjxOf!ecrc%EW2Z1+3llDiG?XCP1ndsn1Xsb?p&H!g9?R zKXZj^;jLOQ(SHq6@qv43%~Yc3Yjg3(aX+R(oGOyr7Vsq@$$jq>VeE z7yiduj3LJYE?DeINhOeXpjK#vGYtAsX~yGd>*K%od+CnMM{Uy>hd=A}q%sq}1O&;q z&9(1smTwg~hG(^wqvFNa=!)MC*Nj$Q>WyKtkS}IxZHC?%Zz-2$XT*Oer)6rsGF_Ft zp)V0nsDq|o?04#>fK$j9RJF0l7gA-Z&c%xp9I#znnGM0Hl2 zjL$0)(`vtCbU|WzFg|l{OJaJ~me};PF@dpDa}2#reJt%*^1m%P{YE$^Fuuw-fbED+ z&mIt&o+tkXh))luW`^tDZ^)`mW4hTV@OH9|;m+hGewvf?;HH?|ckG$P9Ky>CSQ?M! zA!m+@3z9;|XnCn@!@pm%%xw^_P?+d`#;3C;{OXqe zDJaS`sC zE%?pZNdgbYNSRSw_L|W*9;KiNYBn}9qt4E=kljZ4>Hl0eNc=L}^V}eWG^k(8610VZ zHtei$(o4PvhJVUzPt`n!zJj@%SqDnf+5$k+Ci5BLsi`;NOjLz^Bbk|g0oS@$Nxx9I z8QHE68$)NBMgTs*sCa4VW|Dmn>ipGBvpd7oNVELHT#}qtJ6)SX3Yh)ZD5>&q`w6IJ z!1XV+*84tHP`_Vkcljx6AEr&Vv#uwvG7)+zyjQjqv5qpM&D10t- zAMRAf3!kA0I;t~@&=?Q=J5DrB+}lp2Hax9V^9}K)T+Z>=t@H6vp;*r0mmPX{JU9Mg z?^Lbq!Q;7@37_GBHmg=M_4ib-n@;jjHtbdStKsjgqR zImgmo6BzF#c>p0M(tv4Y?n6;Y-wxQF5_qQ$Uk2u-d|0uj;y?S$-D+Ui8w2ER(-s;X z?q|gV3DI!>y(so{OgX;d&8mh?J7yjZobK={rJe=Qyw9Otf13}VOJaTji&+8z|L@pk z`afisg^m4xW>=}trhpEi>j8ONu;`i3P)Z;#f?y9oq0mN?dCtO?5=aJ>oE|Yw@Z0Ch zL~KL*DvvveD|RQtol#HM+f(Pme9I;pcU$7l;Qe_~d05wnHg02oS`r?PkS_kt(h9BF$i=Ou@beM-pa{)G*8Pj+5 z<}(l8%UAPxc*hp}V~Huy2}dw zpV*D`aP_a=$4PaaGix(Rv)LkaQfY<-n(AXEoJ}J_&CHh`9A$@P*PE7<&ZY^klj-^S za0Zui(;3DGMK$l)n)!0cfxYdnte9;bLepBCg3WO3QD4~D%J37(c4n*ynFjc#_|kGQ zZ%Xo+#D_&^TM{%qZA7rC)z^&9V8oS8;jp4;wCQzTVFI*mHbv+H=S$qYKB^dk7<*i+ zpNI>#9G_r5{v1B2fY{?7|4ekrdV6xV3~d;to{4GorOAjaDFG7YVt>YZq{3eIgV{Yk z`e}c|T|EC#JpHJ9D6l0Z|C-{YoiFxD?Ka-fxi|&DJ>rqn-b)Sq9*WXsq;&)==hOky ze|0EL{h0@7lS%u4M>$*cF@BEEC;+HYd(`=ENO>b{`I#1AQX1&_HEhSKfg1ELWO>nJ zj4v6tQVOq9#g$WjXHCa|T%?GObQ?yGA{x`U{hImYIK7Sx&jIX2hmI+P+4q$SlN3kl zMZ2fyJ)*BGT&B_Nr}Vt%=Rv%Pi}RoS=8x6PGl_IFnfIoM_6&#QXsAJk{qjuTz0?Uk zhHkjR@Ax52KDvn^p8ArQTW!b<7$9?Bk4=@Brn4=d#SqXq9M1-)l*dSO>jD-{} z!4m&>5Thlq3!;j-3^dXW?a!`(CS>e8q7^j8%z!3z>^u4&Zr`#GQv&m$is39ucqB+Q z<+dB02g8HB=gQCe^=X5`{+m)x3)<4oY2)&DA2h@Wv)hr$wNMG7jy{DXcJ_hK9}LOMBBn|)33ss zZ_3-iPVgi_OW+Lk3wJgOz;{RMi{sjDK+;EFzE_#e1@Bj5X)<%tf5&6;7rj-MHqoN3 z%(pl0WM(?9h#5v=+ufBLs)M<8=sb7QrLjSMcT|tDY5TrC6zAaW`QrX~{GO3jz4;NV zSy+o~Sy@3<#a&oii1hvTaJ{>Ki#?lyy(9;qla--eSgYyz$}YEp{U|N74Y23={@NR$ zel3}RPgSkq>GF1^cfI{QJ(*dV(bewhGEvpmo}uB@A>GeGwmJ*BYHr`lajPFld2 z(v*$p!)Tu0gUp`WmANSEFH5g-m-#QrtDk=w~$8g`!)g1!LKO@niv0@#E%zt&6s20HXoWM9A>Bj+I95aKT(n zqjvpwO+UwKhRe4yV&y8-(oN3&VGs z3KRX;%`g`_zspv8pkDuaJ0ChW(F>E9>+e6$-CBrz{p+~`8-o)T4i*wS{zd@oWkkyY!gK$SCi-X@%?>LJI7xlbv)YoxYhj^9R%zHL9L+*&VlRckn>P@g@Do z5i|r(8WBf|DeeN^B|3vUB^hS{{<(ns8v$3!AnrmD&RHZZIgN-rX%u%Zf#nSHSIz@Q zJ;Cp?$3pB!0sf1odABp{cVY)`V*EA$Ph!k%P=d7Sp6d?o!{xXINPN?;UqbNilGF~& zmm7W)AYW$4y}qQm?t2d`xekYsW_`rS44!m{>tfRre?A`suJpp|Vle?6`GfcAV$>JT zm%DyfNX&;MvEn|D8ofk9#eJ$Q{>)qM6+6sU&K~~h-KlSpE!Q^hn{5E6>5wdrc>c#VAOZH{;L3E{RLW&`ll zjPrqi!-w!x)As9hKD{8SvMHtJhVpH|IN3{8L($w}ml~NoU)PKfRdO|#Q~nwA+<_X} z+6MOQbyLj_ue?!O4Sr{h2g&pJt!qX({NpGlK}gXk zTz&H5cNc@Ikz&ojj*%%UsdXe#=Cg5LS`i@(GpQ^WIiYP*7Td;R@O5zR-Dk^!RLTB? zxY;MNZ>6kOdRk@*m5;+b{eoHLanDEJQq^1$3*;}RYYuGk&*(8&PU?*&7K=C%1iV<| zKeIJBYeB12JdrFkA-OcSue@}CZAb6WX`aZn&La-OYpw%kT9Ru2&vEs~GrIo#AgNDR zr9q46Ib2EUq=ix&T31~zgEO&W!TO(Qi~b$^7^ob4X|l7P?>r|^u#vt};go=QS6xM5 zKi-Fb41`CrW<1V$9%TO8me;PDM(o@(U;hjX=#!04OQlGkFA$plX&j-&iwjLOPoGCNX3)$px!$7j zd^I&cqc*Nd&iCb~{RJauCe{wnW52oPy^&i;UzR>3fjbI&b_V*6A;ip2zYG73`5Dh# zhAF+W!W8^dzr4zef|E}Q z2Yvu@$(>yK#T;8>?|DrtJ6#bj126I|0C7^ z*B<(x>*)VFMT`t=oJ{|3c`oSyb=^I ztqx3o$anIk0d}JT-F<9O3@wa+6cJOu(g;<5GN=4Ln7^R+Z?}PDe-Q8Ja@(r|Fc1Yy z?oLfdzn?Glq%wb4h7K&I4S-yVf6>j8`Kf;?iHV`N^i!Yhre9l4f3}>zZ8`qhb$v9* zM}29Ra}dZo{GR~tV`_hsC-Q-R%*lNOG1Jr2f3{Nkf5#$pX2wKD*0w+8u5k`BF#yQW z#^eEr^V5T1w^#awDmym;0AvA>^UwHqPGNFzXm$X$VqjuoWB^C{`Tl$tzm*Y@wXvyR z{(~p5wSfWkk6Be(M3XIllau~NA)&TA0C~?cF*(x!US@1?0Nlvn$N`a&nXvmm^@ymj zw7+{X7=KH;lcURM{V(yuvN<=u#GdK?^H>5e?6sAEe^`>cs~7UhfGU5$VVB>OkAHa? z{+@p$;<#dLqksNVznO-g{Ed(HYkxwceg80ip?>$~@9E3`%5MBSe@{O84)*;YZ}+IA ze)*BV{!)kk)&_s=hrjz0?*F7Z{_q?9P~F>_KDAN)LcOZ~W)&TUt)Z#k{s=XI-`6?; z3Xs}bTfg5pDanWUQ<0h&n?K7PXmCbow*$zc(Bww_qs%N$Ail>sHuYs2KbwP!YKuqq zNK4KRzuPHQouQ4Tu?vcc177eK0{pAK>#3tQFt)P3SENzP`Dqzk7(UMW^_NCx;o$sd zv-?oL#@_gMWodtp!9ltJV-M2MZDKuxde=Z*c~&3}Iv4NagK<$nGDGNojhKgLx)h%> zctZZd$fzHJKL5GWG!RWA24@|S{WuMfEz)M-U13ijXfan$f=BIH0i<^bv^fx1kx3iH z=YT+QIy(OnNsC3Of62Dsbw}7pu6fVJZ;e__i!WW=^D}*Fe|Zf7}mxe2+Sa87jrRzg?x=06a*6nm%*Yx(O?|kUu(kDOCftbiS^he zb!VTgKI0T>8j*i4O(U0nxQ)9lfJNJt#IUL_mHw*K*}mP@j<%(%mM)_RjijgI+z}3D z*3Sq~!-h%y7+S|5rg!w4Ki)Z$WI^@5pRea^2i-x(Kzc#S6V%aV+3g^#Oi910`Yk#l zJ^(%OZ(T0SM_65`o$5dj%cekzh5Ap$MkEZA-x3j~vs;d@B0JLWfv?*9$@^2qUz9Yj{=uV^1*H^ zZVw0cIJM_F2o3RL6?NcV=7|eP_ID;O;^};d70*<(s3vL#liRPEEe~F87UE0w!<#X9 zohZ{B=}p4C908}^3`u9D;oyy&scp`xkd;7y3tP=`wk@@=0=tOA#ChUJVon=`ToG3b zHn~s53L#lW5Pd3>=LW7@Rwo|46WE+h`Wt-42GSf28_f<^6lW8gCnc#B|XYY6bydYbzQT8^~7fl1K0d&nVNR4`S|6#voOtl?dotLFQhu76gH9ej7=A-q%g8BrOxBx&BdUwF5b`o- z$YPOHGK0e)HMOg@R}gHPMZNL04uj7WkYn^eoBxVnV}LiU*B==aMyC_l|>I zr$J(@^Tl}_@|^x%#Fq*nU|Pd-favS?&`zBjbeHKYJJDmJV?grtiwuwPQ>ns108>UQ z&xf5d0zVZCE26CDWwUiE)>Dk+NShuJ#!DE+^J@Or1rqzJ6ibKVkK7RnPOks881FS; z{ZnXyP6*)*O%{F&bis7j)`_9EY!7T!GJ}~~F%djjimdjtnR8HUdJgPXC{8N$7`` zIOM}%mtt~VBo$T$RBn^1Cja%IXxMeu%3ua`FBr&)0cE|L+KGSo0K8s?^0ZtOZt1G! z>DLHj4A2A&qNdBe&AfWcML9OZt^<{s-$CmHAx20+?ZdGAt}qcCS7UIzj&AYfS;r+* z-Bd^?Oz~Zf8gu^U7ES%pEK@ICTW;G1ERo@zZ)ZYNaWSAjBrEGT@?)|t)Evu02i;<^@^@n*(S@hISNoZo!_URcBUdb9w(+XL$ATPsk#we&7 zluX&+)jgkAUDV;(%_}KZCR&%#NY&pyAXCmMVIx1XCAaREJ@l3}B+iz!s1?<)Q*jWd zS(GLgi}tx2cwPlp#3jS^#oJEFPTyQ+^W*LFm#UG?=3ogPLoTJj&01B*YAmGS*#me5 z9Y^Z$H~d$Q5&Ljy(-6vv1-NYDKqBpj4)fkD@;US-HeqqcvId#Aor?oO$*&`f19tUOc-Bxv;w$D3BGnyPbePWQ z=MrwaEH|q_#D++E7gb=nECHE;G1=kDfEShzW2a>U!4ILf@boC)=|lj68#i9)SbN7@ znJu0wg1Dg6XMw~~7uR`oOIbsl`Hghnp9LxT#>6{)ctzRAmH`Js`XlqrsAd8Andsa&)^l1M~9y|4u7O_yu0)m(b7w@ z+o2?#5zGb&WOBewy(u}ewwP!O0Jg!Qv=ckFF3F5ON;$8fAxEiW)qF$`G#C0_Y{w3L z5}C2-+UUOvPU-7%P={T^4MrZ+&0VZw4ItG#?VL2$k|n&l9S|$FkxtfwM;qj@g}kZ; zrxgR61s)<`+*Nynf}rEMk3Q;h4a56;u{<|{*q0U@Iaq3>H#r5$py-o7P>&YqIR`R* z)3fDES-4+Q^RqaGg3gdO!*HOI*!mH&E6hz^9ybC_9`FX*_6U?i*`xylgxP^t`8R^$ zJMp~q)=GW_O?5!Gk@WMb*l8Z=cE$e4L#ZDNcfg?P1=nW`lG9Bxlz*k!cpHQu+ zO)dXJv2?Az7E(I8JR3G(yVF&4`qdAs;9xXH^H1tM=vv{bOtC*AAsKFU(R|!1491X= z!jIDo6-)0z|&&tWT; z=88$`lkILXwIZW57teZF_)px1>DEf%O2G&s>rS+q4T0?Q)NqgfFr*7J4ORxkN}=F6 zU*l2|%cO~j(}PEn&IRw*JXntWn?Ki!!EfQqY^GZklXSIW9<-0*<_IZQ(2+j@|ICJ#q;GLO@%h1|(rVDvBlQ;&QWzv9n1n z2X5=>RWXez)nI2CfO|p@ZCZ!`V@07OYqm(7wZnNoja-(E=kdNdhyuCOI?SY8?S7Vx-X9l zntts~dz9xZe=u=}B-pVao3lZ@8G{I~IdI{0SB3QXG$6kCk%GK{riDvMX(kw#xjtGT7-M|$I*OrKa~c(!9FLS<9|*2_i^ zeZSEW`+0!fN@=b6#u2V{;>G;HZ*e=Su8A7OOU5Bm0(JnKNKx6mcHL5qF-46IP-GYh zAqhh9=u1TI@3yTvNrVIAI};*9zVZ%)9-g1())^{wiCu5q^y;C|TFeA|s{d!Zy8ph_ zU~&VU<1ONH2FgKFpRLsr80-b_bvb2EK-9`)8sNr`0;hjM=<;9Xk&Q;bmL_Xw4fPZD zG6xDR2GX~MY}WQ}+=-bN>YZ4JZW@h>>cN@$q!?kIU~jb`wqq|$S0%VceeIdYk<)ZM z;YNHiD1cF3p9Hx)414)E52qR9nJd(lDfFo3H24bfwwlrwgeT0#2NN?m*2GZ^SBP7Q z))=G2CUQ%nP1{d>L1?3wO+2j8DIs@`tgoxXse11{1lnwIgZ6Y5C1z6JREhLR9-joK z{R_Ut@>MGmu@J0h4#|&Oe^T5OZXZgCpvf8ZLD=h6u5qWjeTa(h{_xZQJBWEu=b(VJ zNtByw=ohBQ@(Npe;|gYo#9bMw z7LvnY6ax3EVHG<(V{%_yxWGCbAM$Xyh?L*_Wfvd>YiE$t5mvxN& z7`faz)TQzuJB%Zibjx__g_|UMLJCXX)XX(LwOS;{Q7N>rG;oTu5_0?^qoK&(t`bx1 zi<`aBR-KzgX(g-G+O@@4nFCs%)HmQ3yAJ`owko=}hrPbNjUwgt5 zR4H@U$SZAZ-D+l-8*brGtT2kt6r{ff<{bR)+&=nM_JKLI5G^bk(k~9ke0q0+Qt4LG zx@vI1RWKnlPO_c3FpoJPrz49ZL3~gsx>j=*$MXTL& z9#vpZG)Fi-dj{ef>oh*u^(*P0dsZoSqK|R~3AvnEfu&+$?PnIm-qXc_DvgLl*Di+ zl!z8C5-X^ztyO&~=Y7*5wKf1zWzRl`c-m9-4W;8te7p05qTdN38DzVjD2yI<$az9$j42AW;!q-U3<0yyiA+_R=TZn29eY~MG0MS+tD8U+thAR^ zGhaJZ%|51g?fGYj709g zF@5)04MK`;#dA2ScH7A3d)$pnR^?_ZVaARGgm>z$=u2l z7(=y>Tg>AKF`eQNAuTca|3Z0HAe~f0t7LpPyBS%ec$%3DJvyv`br~Zi%=(IQxS9d!wPpOS?i>3KX%iHS`V!9>=@sitJoT{0H$Y zt|%_3c}2vKW3=yn>=aLN4u;n$|MMpj`dyKQN94z0Ih(pf5uR2AbSqWzDU27Qt|C`sVpt=N%PeOG+e!yE0u4(`@k<9Bdmtr}l z(wke!_t`JC)ue`{Qc?SQNV4IQ6<^)9nE66_9D`VKXFM}sZMAmV9Q{&224#M$1gOC; zR?ndkvcaW@1ekZmraVV850hYW|H0se`8|+B6j>i+s8w`3Dh=kW=4}^0poPY-9^?^$ zI@D?%I7elp=5IMeanX|G@07(dZD zgUU0Ctwp~k*=a*We_?;r9=Qw7e6SsZ&P2;BN40*XpgaX?vj~ zL9cmczKp-y?vS*Kp&-5p0Gls%FGyIrMrhBa8xY4g{O5?NT&bSc{y6al{I7wpO1S}_ zu9*xvhJhC=VEsbXm6F;%4RHt!@PNJ%8#5GI-=uojtO(FkSICcyu8pcG%YJ1|N_G7S zM*hoViAHguI!Lk)$FknN8pNq?`X4a<1wX0#hIOjLN_nzQug81#QF-&1IbZRWo3+A= zpZQsQ(02s>!F_%ZYhy2ub!v>JbkhL5dtis~4IEsib^O*VL5Oy-Id3;c3CNY4BIon) z%h>EZld3IRZWK5z?b|*r;x^%!7K2bRD=%)LTD$skbx<&yc3nP zSc(fc)py9fohTx5+IWl;l|09fEYMI)=l4Q2fub&CNfi5CW87&Q!S@On!(}n4%ia7x zaglUo)=4&AbXX=`rQX({d;1C*_ZcWmiS_-8rn2+4Ex@&~mC-jOc>2s(898~_Q8N+K z0SfweLtkI4A;wsTAe5f7{5($K64`S2Q7imY4$8Tzm+BX8*V(~l#-FKrzO-MrB@QPK zGV+{IvoFZ!nGQW9^q%#y33YKGH#5^<%f0{J-XD3`MjYoQ9}Iqje_&Z;o<8@v;oHKAB-%>C)V*p)grCp*#-1DEJ3xiS#{95mG! zKWpQPDgloO!dzoZ17cRMH^Vlt`2YLqOK4!E4Em1A&+$=>pyuls9g?B->KI1BE$eSp$iA)KT^C1P?vn6M`=Dw&R4{gvEh^G zEd8XO)2?$N_uyLlPru$-oQkU=I7LJ=igIslM$BG{enVf)@NMT9HsM!27Krs#yd!Pg zKA+ePa4}{xaq#CT6TzgW_qF?Lkp`LvZCJ{UD5U$0Mb}yOHgI|Jbsq5~(SLZsXJv^bA^MR8`vxMj?OKp^<+$DPyJez%n@o!-hra3cQ2JW}8opKgMZSU0%c;SAsy=$-*cM_~ zz7`b%l=L(}4hjGU^hFUqasUw+ds^vql4wcM>8Pdu-}j{DtiYW#p=2Fcikk$}Y;wXV zdtxh6BEzu1Y18T2gqAhAZT3%=%}nus1a7FU@-C~uF5SNH8ZsU&XmDAEQ++3a7SHQe zz%j^0K=idHep^W^I0lM)DFtXx`3~_28#-BUfe_mVMy71$(bAUjJn9Wg>L4`;so=;X=#P0wWhb1{k%4KSa~E zzSnMW3@BgvAo+LPG5WdEHCHV@?94GiU#0Hc0_e<{CveQ#B6Ig8ram z*qp6yAHpPSzHwJ;8k~zxzUE%lu0~ zj|DY@Gpn>M1AU=PZP%}DW4Fzy5qO|9MDBm_co4%yu^*Nm%C2IPsxr8);9k~UpG zjd{!`NDUr^Vw-9VL)s(IF=hiSYLc?#X4bA3;cH+$N{6fQmP*GO{|=5!`Hxc~hTny% zr3SRdqCp%0$a?6hhC6oKM~>tqbxgHg`@)IRCkYsHZUhJ`KOIl<49@hp?{ohHI<)Jq zodB@OXB2DV%55KJzEnEb5s|o4U*7aYy5OPcv9)o}+rRl`tRo`1CV9l=IwI0?@tJuY zhpQbcU-ovj3bWQe9Z4_`0|~TS=294ea|>l#>k*-1o;$q%-b3nNYPAfA>ipp)GJ3=k zbxwN$+USbXC(B?X)0{P8nj;)CA!E+9+pyPO!2X7eh;?m|tv!RQ5;OmIA@;8~wW8WJ zHbDjm?zTgI;sny=C_C6N6Cn$r7_4M4(DV%!z>0bUa0*G;4^O70MXZo3SS#ge8Hes) zFku}k5eF1aESfZ=#tXx+m~e6)Hq~jgs9Is4nN*w6)j!~l@3%>vnR5Yxy~l7VA!|`A zjcrr#M60YzCk?I)4^>1Qb5l(T>ndtFdP=DVO0h5TvNdlSs>2@I==*mYQGlceE!f2|ToFbEP7xVohT$#M<3m?3?U%d;MP7pVf-bx-CYv5u}6J@2V z(}n)tSh5o@l{oZqIU!tIrWC385wJP~938O`l2%6kc5iK^UvwcS(g?Oot5JAM?;>Gj zydy-zO?=VH-ckL$w~tcao$y@^6kj1pKbYWf!06JjimsD!O#Ei*rv=76EJ^cLC4u-v z&4>uUJk(w0k0hFbgOHtcXpJ850G_F^CE|;2{EQ@m@e&jS8*s7$fu=KEa?G}0^$#%g z@h%C~i?tP?WV4RNSXYvjM(Rs~tHuCAe-x}}&E;cE8I|B4HoFv?p&#jHEKJK(xSw0r z`%6hveFY|6Q(@VtmjauuzA+4=xH@pBH@>Hv*VC*<_>YsB@75~9Kt`?Jiqk|`nw-Ow z%yt;*FY+q^+6cI-8?|;c<;@}S1$J&zb!P1MO%WYUH zwNdfIEL857{N6sSDs!4+1INih={_MpNsF;tl_ej3CL3*q=W$O8oSE&|R%S0#lH-wF zR)Kd3JoM6pyAdOe9N>!pn01T=u59bJ`|(_$jl#c zuC|+LEQ?x>7+hG<0Kp+=iC!}xTHAn;h*aS_+UdhM>?5G%vf*};Ipexn8^TO^?l_5U zj_Hxo&?UjBuW6iX_jf_f3-kF9i0=%oElO!(Bc8Oy=>glPry#OFwkTKho4uh> zuPkv#6+|7k8-I0exUhf0UtwlKd}1f;2cO8Xs~X|ZK)7?&}`W@{{;iDspUq*Y{2f< zRUd!m2g>Jr-9t}r_ zZyG@DO8R+vJMtq56xCTtU^l6FnNX9aeMPaRw000!fpjT& zRD5V*&a$zr@Vtu~km-qEat<+K(gx?>g$Oo>R|-GVOX*@0!Belj8%(d1Ddft9CqK)I zYqyxT6A4HZVD^k01UXQ^Jb@dshp{C*YBPipzh2g;NpD*1E-`)Ra1}uY(9MCPYTaE= z3AwVn<)43o5EQi|gF8XRXcU7i0j(T)w}QCxFy!_OR0TX?V_-ug=Tx<)6P4-Yduhv)g6BV zEzwjD1UT^P?(^9d`DxQ3wzj7FM?S$u` zxvrGgJl!7lC>@7M*dT88pgB?YrZZ1zw89Q$yDH_}|DL;FvC``!M(0mhg(*Zp{dmrz z=i6^;KLa3U0ALo3Kesx&4u#`G5v&)9Al&WxEz=OEmxwCH&QlgBpKVoyRQxAB z3RsSLcX~5Y^s^H@RXHTB6)BW}nuN{lCq|3{0|Hk!5`rlFwq$~KpFpbg&g@^nbciOL zp0)ERy_ec*Y1N!wy(J1g<&D~#0=V%IY&u99KdEiAZTzA3HfjL^r1_kwU!?j&G|Q?B z90%u9_IJft1>O#V3KAl;mI-ngBf^Rf?v7iQmthp$3nJEKI0lum#2F^V^=u-Uvd42Y z>#0SAdcgQ7JOp7ewa$7j5n?HELf`#Q0IpOPJLmhOK6~oD&zbW|Vr^0bT-PyH3Xd#q@8U^%ym`v>u$*OguGd{XT__pE%WQ0*#z(vlIG@$7aZbdPM{XCnKa zx^)e&7CSco8j|Y+w5Kyn=v2ys(&gogEAeBSZ57uy81P9Pe7ckdN=gjZQP;P1k4WNJ z9ckVInkE)1!LhueeRTmV#jU-n*mZ3W+c5(Kt(oPNejj_sKI-3)OQ;&E55*gVG1%(> z?4%^*G}!H}q&$j*6*_OatIUy857)1ep0j}}szD8{+HnvBt?s%Sutd2aCG>5$qZCL^ zNbJfMI+hPD={&@$_WwwVv{v+rZMCJ4m`{t*XmFFEV9FD+ebrb_Dt|uyLz+Vx7CJXBu=SswX=fp@URe3^ zHBKd3mZ`s?%b;etT7J%l*3p7p*DdVW`9I-VcQS?;4x9VQlh1`Zwee2y_|Ui?{WtGw zsxnm-mjS>of>i;vx-Elo;hA*37vG&=-a)Y^3$DX?k#?Y`s9qQnu{m;eVa{=LSzH>~ zoh~yh5HIQ6=dd(yZ3K6{-np84HQj0t`;5&I?NvaCBN<1SO{~#p+mG892BIb+Aq&#= z;%|mN_$`(D1@;keP|wt;2V!h11PZmtzb;nd%8pvBu}1NOj3DXQlr_wctgjGyYJ#sA zx_(@LYguN{{CKu2U4BKwc9d;wJIA64&)t+WZc5X9AtX*=wNSQK`k-}=Z7hQT{$G&{7m>XhQJ|Gdgs!Ckj3AI5Nv`9C#!U8?iMbV}k z`n6k=y|~+x?H^%bSAUNeXGrP?@H6Y&RepRF;qw`=xc;fEDZT`grcu?05mf}H=!Yxg zV%NSpQU6)nJ=%U*Mk*t4BwqMfOM2)$^2!jnOpPwI2EQSHOg2A+94?p3?OZH1FU^xL zjrA};bVwM zJRrlg0z#;fG*w&6F420>V~z)q$X?-A2mB*ya~yutNuSyVJcD53Ke~JUO~>89rdbHY zr`#)`@uB-&(ikaSFu?|@+titR$IKeywcqJH52pO3$XRR0w!|PdFft#Cb#n-ljSV02 z_PUcqatu2q=+eJnAMe=vlZpz-K>|W5-;!BjE1^Uf}Q5~L*H=zVa;rswE ztCZdWu#h|_4~F?F(OXBYv0<=dx>`Ft35pgoqU(49RhMruP%8YsEADmB4a1+MYA?c z3I@gN9s*B-A&VQLab+Pc20%p+aC8TKh^n4M&ry+vFEAuwgtkcj;b*;>A(^l2u4 zr3q0{5EHC7Kwv=rJ5GyC;A|S>!*(|lplye&J)xCf%mn#AVkg$djxBpBG+B;+=X;x; zX13Z&yq4>LD${VkF6PY(lIK;~KlMCKVQ6j`85c5Ua{CQ|QTp!TS>&;-qf#}zcl`|PJUyPD6zEfT3Dz%0YL~8V) zSx?ORE*s&}IoZxgJR(mOFO9|9ZshggcV*Xiub*~y{LQm=w-0nXl)+EN7OK*tW(@d$ zpLF&Y76>6fuDY8CheTBH&_Olf>YW0quUD`_o!nW5%6wx%KpF;yP3CnBBkn=;$ z^qzDeZM?HgsgoDWGemG4)96dNU3oYTG~HoGX{L-QP;LlmMJq_Ps47N5+lT0&s20I1 z$#&@-sx63Q$`*~>j=Bty?u6MQmlh!)Xh)LaIjSekkL30rkSBl(#1bXrvc65%6iLsW z08+0!Apq=QoY`Fvzw~NCUv-!p!bf4{AI+go9ubViCn5tVokCy3D)?hL*SmpFEm zO$bT^shJW-1G;*IB1Shkjtoq4{|#Q06Dv5jAIG^C6GF;3i`4(lWHmn}c~@HdUN)oz zZh`6EE#mjQF??arsljs5{x^Dd>-qa%9fqjSR0fswUXuF^79qJ`6XQ4ux@NJad71~Y zm}2cAFvBzH3TWF(l!h|_h6=~Fs;MV}zbNVk)oLb(CW!@gup}h2iuUR5+!WU^@uaNP zTlc99ie1{=on04fc4w<@b=i^V3W$rMR~;B0G|ZiHg)tBR>6B4FLJ=JqB0G`Tp~#&3 zIE?Tev9a!{!!v$TI#o9|V#4~NuM_67=?mbY(CJ||WjY~m_~V_l@+UZ1p#$!PFnc|w zjNtmVmNi1FntwxXK8BZjHKeU=}3tT zVq>uqDKXnGRI)jFp`j5`>mrRV$4~r^Db>GsQqSZDs~>wIZEcS3{7v+Q(THzL5@JsI z{0o%H+$qnBRx;H6hkmDr5Cmpnpb`_X6h9$d>c3KS?ag-rh=O>VqKtJZn%Z)aV}%C_;R_W|50MEk`#^&i?y=^? zNM4yf^<8_h^7F7b*Q{-nt1k2;54@Y^nZtjGXwYc`OX;H}?~Gn5U+~ZxLPHQyrFlto zGdPNjy%;@WF6lQZa|#oT9%t3L~V3^Ow|aZf6pRjjAmt|7y~U!vf6Y)(>Mo)?7m{Vn=uz%=}KAl6Y@vP z2-ibdXJV7vSbF``i(ob!PhvlhO&H^wI! z(+C~e^*ZVr4Let2P%3ktu|HXIRc_+p`*e+JPJ+vkOYzbF5svIw%;>F(5Lj!Xy|A#< zI;a(G<|De_4FQRWU82e`*hgNjRGhpEhiwQ2m2)*$&htW=MZ`w(+!`aB8Lzpv`gpet zyq-MAJ8;E9Nvb_mZH%p_NI8+8dXedjlNQ!CCrXWgoziU0H)yIw{uWcGThX<0D#sJB zY!(8uGdrk^zZl|mMY@ub3_l6mPu2}4sg_aR_Gbbha!HJaSLtqKefHupGYke=C5;yA zN2oAQ_xs&@o02<(^vf>a4R*Pni2+ChsH3ZJE^nYzJeM>Ecg$grb9vH2pWoOivr7mX zvZ}hO+j>Ff**>WLggb151yosD6Ta>kB*_5wqM}KC3pRt)+Z0^$TzC#GT{)CbqyW$3 zX9VJg(F?A8{K+U)RrQ;ro&~)h`+k73?l4r9-WTJFKW&LPF-zAI@c3-BlL+&qWUkBEel{5d4D^8hMLXEA`K>q;XoMQ*D|UCN2&RB4nsn&g;QB!H z(sereMOCji17r*r&rX}d#VRX%Mc6ANHt3*ivJSZ>??HWP;OU6?Ff2gByu}SF8?*Iz zqPiw<|Bi|ZEwt<8YW`CEvs~n-b{hD;s#-E-ggRMU$+;oX6+H5^>O-8~3$+ah$5^T#LFq6%h)W?qVK9&vUayz_R(06FceCR7EnI=%=)kPm+2#eK%?U1CfJcK`i{Ysv5waY9PvkAnVB@?r4T=xl2xYXm__%MvcWdpgV_W~K>jst@%`~_rh6uSx9 z5DJm~WLvA^97F`7|W6eMAD&WWK@2}vXgaq1|GiVTaY zA2v_VuCZ&jJY_$5H%!IcT9CBL9)Wo#sI+Bql;@L6Ox!2T?~3FiYM!2FS6#o)J4J~R zoaV_8l`YeQrV`iA?95bn>%1FRC+DF=ogZ@^ZD~K^)!yy(X{930H~RLk#WhNLTO2t* zmrCVF$$35fcrNE#IRUr92WIq`ydC1!W=353Lz=LGSt;HANs_-J37{n4>-p`W7vB8M z9^DK~U{roLWeA7DVgB2s&plYhHD+NlA#ydnlrl@t-Lj~jtcXQK2IWA&`?-a1!NCXmiT-0 z+T7o5>nCn*F*H)h>F(SpR;t7IY#Srsiq4+l5c)Kx4|8w!Ew7v);>z0=hcOq#;{?TxDm?fT*zEb z@;yKi#mZTt33sR5h__zj4BqtPpSDA-`IAiS1N|MA3S}a(aDo&A*Ls&Lxxd*+*Wj`X zT4wh0{Me1&KV(6dYJpm5qLpTFv<+GG&pbxJ9XdZtALS{`2{DUyTaSB;=_EzU?o!i! zp`p!T#jRcecl`$VP6dAK<>GzNgTuHG$c^1Ix-C!1VPGYK;anMY?(%CFc9rCXC}pPz zr=NZO#2snWw;OS(SMf_W9oN)LJ3+H0YT5*2Bqk*14Q86#1O0kyURd5eu7ecl9eZXS z_!Klh-j>`}`B=`1nmiV{Xb+SZHM(6fp zje$Cx2vahNY*9YVa-6M!qV~yY6+aZSCe;LW2f9#wU69pccByLNUARMc~0Vp5J2hO!1{2Pp;gVQ?|}K0rq2PF1R|4Kq)?! za&z@B?+=j^lc+xga&pA%bEDNHTpM}5h4gt3XH?@@0#rn)K};qmWpCOO=uS|TMKD$zcTp*ZKBNr z?Dt73qXJ2HUl`qHGD-r2gwi(EK7ctz1a>(tP{g**BgY5jM8&8GQh9ZKn>;#x*!PCa zutpsec?A~M?naIb*KwAxEaF)4ilu;hk+I7>*DVndkuv-^7JkgE17tqxjSEq#MP{3w zp88g>#TT!l5pQL4Pq@(SKDuO{)TQ4lRLw6WDM*slx}09p)iZzjo%5SVtGq1XPFuP9 ze1dmbf6(1##INOmJ~L2gQj}DvOOyB0AH-J%u?tLlFZ-*?XuzL8cLHoDJ;-;dgP_oA zAVPXiJF&Um3ZeVe)^Cj+&@|z*=(bhXS}*1*)+R7YLxcO4^W^R>YVvN z+ZSwwy|xAxijuYbmwRweEbNE)e6i34Z`QQubvG&lqg_CB=^qqv6FuB}-EVv5OH*!-JmPpw+c^XQ;?fYt=b6w~c|;}bqV zscbW#m597t^H|vO#`T@~1y!TSOXjc;BL7_Oz*gFfD?y=`aaJ$LM=$R-xI_@n92xO; zqlNa#>9)t=3+-Oac{uBHxnnrvsa+jm$PzAg%r@xi4``sIb=Xv&VyMrR*gEzA4T`i; zj#GooPfvT#M#8(VRia9z8X;RpZ z{7|75erGypQ`O**8?q$qOXUqyRYt+;e8H0v)m8OpLfidoe5K+}M+Yno#1fH5Y<6H6 z@7`3fVH|?8?Euuz&}ri=KC*KV9Jblz_6$W{g1iF|n-8w0I*D7HO;zg|Atdc!45O^c%T1^W zh6x#`HtVqLtnd*Ia-#eaV@$U6S0JavQ%D%03KdV4Wm7>VQ$Mbq37s>i1bqdML6j!A z$0ZKKUVcdk!Po0ydK z&11jdoO(tX6Mm=kr%39cC%F6=;~J@KK|0=TD+J?0KbOc~Zj5(bx6OC&xE(;J&diiHaD29{F)m(=zFnaWMYQ*I zR-Ji9V+-oUyDrBlusCO&(2sq+RZiq&&dG`U7FIn)yAo?9KMgm^lNWT{X#`qN@x6nK zRegKoXI&tzs9oxpf{OrQY=C&R{dyndqCox@xg#Q-g_Z%BR3=tWmhVroeoJOL;ql~R z*n(Z2I4_p3{AU$Ztt(;{T)In9pHq;B5_jCkA&}P!D<0hNcL(`(5vC$jXgpu%I$^M9U zJ}AmJ;t(T)zI<&Kq~nQ#wpf?DKy_-l0C@6UM{ZUQFs%dGd=QI88c52bo92W<*X@L4Rk9e>&@dsRCO|+2VFePPnFVD2 zk8MMQwbXA@Gg$rlROF_ZCBC=Jod7wd=AzsePfq#hxQsv5EOuT})-hMNrdZZv-#pXN zKkpse>bLvZ@HnFoJ$u{bj?LrOF8RS>@BqGkPGgUrDL{bwo*L~AKT+=oUrTK8G_*f% zcHU9qN%J9doi3K1Xj#kR#OuVS^wxf{onBLX@;iYgw(8QX_0*YL$B|@)_>=NF>?%5v z0==Nc?(931GP5_+k%38IK}tL6meP5yZ*er$rCXoJEjmRb6Ed%}<}&MbH#E`iX`jUq zlMmKY6hC;zH9cdWsgd)2o0Pb>GPG>Oq>uQuJsjNn)%=IWmVPT?Nn;;;MB4ySo^P2K}EkyV>36V#EXCS=6-q#AYJXVSDhWxz0eg>C~ zIYT6ViP&GeNh1qrmpdMwm4SVk^DkOH-2df{_QLM7`+(v3C<_0FCNG@)pvt}YM5u4Z ztvDz^j#k0Sjo$(-#XO@^T>_lC(?wC1aw3|wixlp3uZIBR&0Xo6o?Eox(&!_D@O81; z2*Wl9P3!eHtt1IEQ|mS9Lw+jn)K4owDP6Jgi=M#c9taxw(8`jL0ma|{{8W~b7>7Al zsKMWh;O)It&rmFkzcq>_afD=^&yC;{yG#XjL5Cd4m^nngVu1p4t+LF~q^b z^rX(>+A{rkAy^it**fufvH`rtUe+b|9cr*^N+Lk#Hav8dROoBoB!-GfvUkYco?y{PnfB1=wY*b*kM0zjOzv4k_4E0I#C_6s<+q$W`nZ>QC20Fa zg5PKt|JPUaPslNBdWTr=NI`X|WiC3+8IiL3&PHoZ0$s==jDU<$QXk2UYKyr!IH5--Sd6!x!8p&jlmzQ`zyR%0MSH(gV;63It|oBMiGcqC}b9 zo8S+P0oL%SS)rnK8a1zQ)+fJ}oKnA!Eo`hzhn?6lq?>C4o`{=P1 z5H2#ce(IJ(MD|{jh7fEfYa)-C`?+F(o6o?ak$crV2W%Uv_sJx949?s-3u>VTbUZcj zhEr<5#LAyDU{p?BYvseaSRG|bnx^5v8F|(&RgPD6$22+V9fJ+u6t;KTtoYWoyXW@@OtTdfgn%7u5rDIO~^NGXFU8AV)j z=7!bRr|u7H-x~1S7mPZN8W}WQu&X~`Z#jRiQGFpj;^vlSwz2%GNl^{8cs?vPZCyhB zAgvX2XJLD{u`j4|Bw`h|%MNLXSTqi@{_b?*kU8981*Kz!&2z(jipEUrkwsB88eoC8aqnU$=fN zc3N@hWHS9izuri1kH=m-oJwqq5$}C)6Q@tLIU>uvsePIL{wr@K%Mjgz)bKeXBd_<}@rOZYuPK zIsOvv!PzR~c514X2>RVDgkGr0sd0y8Er9U+k1D8aMD1RvNJeKeMV~oc*~nvb^A=1A z)o8VZ^u&_C_#pwXFa3VoCJL-Qp(@&thULJ|W~lcb+R=U+OlBZxIdxur%65|D;q8z%*`r$+;eQhpyOG_+kZ* z>t4WrGvG+KZLBJE`c*h7n%)NR9qBY2UKC?&3j>xsF zz2ID69Wr={@po%a+2(U;nux<@!vX66#=|Ou55h_GPQ(7-!trH)$`>Nda5KWl%%o_0 znXi~CdAb=psi&iCk-dtY&UE@L*PJrKK!dV!^T|EldIzbzKl3MdHiPlPE7Ks3hhHL| zF1NG%g2m7uKWe%`O*1@R@XYTszc=7P*A>aSr>MV+R{HtSyWfTLtm%$d?h4iY!vge8 z?j*B*Xo}oDiimcMlF|~$agrxvU#YagVc(M?FE1`RAqB>^yBUpCe_#~33D-+HNdbiK zKRdgKUATD6u5+9brR`oq_*;3Twn&1&!bITOFi}g>Nf~B;Dmx?X8};@RjA`*7&@?7) zf*(uYcC}mNthGA%8VZ2Z0WQi?+$WB!C_EM6zYq{UXSg*mb>fBNG(6SBq$$F6=P{mys%>6@W^3M z*J~VWR@_5o^^5U3d+VnZXwgP!mYI+>l^bVPQUm9r z(d$uGP``oj8GSwv#cBbqL&VdrnP~lQ!qD`7RZ+SJ5y`qP9iK+J$ugnR!z;0Um?U0l z;Dnb%d+PakjvULpa!{behe~Pw!e`4nTloNowX=|v;ex8mFy5}3w?TTW>)q>g2Iy9* z$*~K0WO|3GVm_zl7jK%oMZp{<1e`vh(-W}zai^0zV2PrqVH;Wow@y%#>A9S`dHwp3 zqP;-kHf9_+ENQu$UGUpv%fb>5_9gtABHCcg3My^f4sVUEl!_9Tdb5(q!kv*e6PKuq zEy!C-|5^K;v$e2zZI-G)Zz`aGbaR2o#9cuApYJ1gC1osP1DukKH&g4e9U@z1d~%i-9U;qCF)iE^kATR6+~7tEHWMl|iK)ZDm1o$zNh-`JDp$4tWRU81%{TFf zr|R3!6pW>AY)prq)q1=QBP3#|GnUy(SgE_6_n6zB@If6tB}KLkyPucqq+VHL^QKKs z=-gcj!@ui(q42Q$_)DU_-=%HMZi%d^e=_-&%6`-q8Tcx41IOsyV?B?^#!rrA4L_c6 z7PLaymBL=1<%9#=sX0@19bZ_e0YRiW-X4I^QBvB9AhuuwUOe649aA5Uv@oId!|3Ay zSq>b7Amr9d1ow5Yd0yq58m9q%0i<}4g7=hnHWs9WBoJBTZq!*Q#?0`yTB&2QJd4T% z;Bw#1rjYvAb15Msfug`M?h^edZMhVO{#eAT?vwKt633Qo8ujnLQs{{k2_pHI=e)O*+ULCXm)E_#C5Ze>N znN)U5TeJTGo=H@-NPwWN@4$Lly7Xl_LtY36d~ZjE|6wl4`8O@@T4K;rBU`ibT*j$6 zj+vL8eCIb^ZslFw%eLzC1tS{0S1SCrVfnN`cc;0ukVwDmn%A$hyyXOa3VB)!^x#3S zymHi0&*!{f*hBF+VtbICrYSmi5^Maa5a*)hb;&A**Vcy*_~`CeS0t~eMu72$4zfo) zhR0m83Zl9fiyg?3S6|wyLvDhJE*32emO;l)ry`zXxciDAFxTKR_Bap}_Be;J^oh~F zwJe$$0qmykQ{j0HT$KkYKTe>O+6zh-^BJpXTeFAUd!#i*!fd%7qXGk8s)S2lt)4Hc zW_LhiJ2fVrhLKgDt4+ zrI~TI!e${k?iHzoY`Y%_8p4oh$H#u<@)_2@I$_$xGCkV#))C}+RETE)3x6hIwof<| z=i0&sbkNOnJmI>8VG0yKm0S+AA#{;LKlg@Yk&i+`>-&$4cf^fO-u?uGV^5xNGxZ?? zys8=5VT6Bvfe%AGwW<6ad{riwT6*Q$1D(o2powwW1Cv#rdRf#>hgEBRH$TjO_bI?5 z8Fh?*_$ra=*oZ7+5&!ms(>Q;)B^`BJ0#c5ubs_R{uCa97BtqUy(Pmt{wxN>N;@w!s z?qh6kwp@ED-aYv21O|CbYZql!cDOb$D%HU0-YRGV=N09A-Y)++3xwm#sdy3klakNE zcBjAYTvy0v7P0#*8z=&vE*~~@m-l&_GnCHeRk4YZIK`4`9DX|`i8SZrV|sAV=$;&5 zOBm9KAwo!ji0qK~JAL@wHSq;fJJ3P_L=j{Sr{^1ghdh;1e1qdHKM{p9;Uh=oK4f_u z%(l0&?0TxzW?&9B+;w+UvOpGMO2i|N7yJqdCRP3r(<}Zk<@Q=K44hiSMV1W2YudI0 zaYWd{;sszI^qZA3Q%UKN;(R(kKc@^f;f{WNF`>z1B3rBMVAnjl)F6+EZG9s_Q!Yqc z20o?|sI0Ms;9AICD-3vmMMKWrUK%ZI)@aP}r-}06Hd_ZN&hCyVPp*0yNJ7~$@_SdX z7|@}bBu2=~2mSD8d?p$7_-%6U+ea7V=D!LvOb}2`O+hLfg_xLh)K+4}dgi{+Xu9AO zn|7XfsV49jd(UYAj*SXF!1HqIDcb;3m9C-hZ66}qqi@HnD0$D({PX|4sls@bLds| z9q?%RA|X@Wv3Q_|Dh$S&oCO!gbm%i$)k)CqoPOn3LLnM^TTz-P2U!cUL*>3YIBlDf)W?g2+_MpcI+j0o_R&_XGS!G&>V3iL?~>S| zy>A(xN`VHJ4HgFTomI_DCMF76TR%GaOC!gIT?*R4gNNvdYP$7XqbZ4L)}i}fCDD$t zn{V|#m>|Lv zu8ElLZ&g_S@E!ACg;_qqQ@#(;YpI*=uwxvO6H-scGz=xi)H=3?s;dr zcLpnWSzHa3AB)P~JkZ=+3$hRHkT{DT=ZW8l5Molh3x$P(`DnJ6K529RbVl@9c<>lE z0Kup0xuVRY87jrdBAoE-30bTv2x`$K1^ z?6;728rkep3(d#3E(0q#DX7<;z z*F$fVHSzvmB}#g1)P;f*T!mn&3aab%!^-~8?6hGu^gn(yIpHNDG{{sk-2K8w zl|nyk*0gnRnP~LnmEL|yddCtQ?$V8xOwcLAUAj|)ir`zGCca@ElM-FwWA?tYGZY0E zTkyb(%1a^VGfp!N7Dy4X>WtwnWulw=Fw8J(7nD4shw{95N>cCBSwAO;+1pwn`h_&V z@?0<|QeGoMF{;F!Ax8Ngl07+xOP2`! zL<2NA3h|4mh6oX+NT_FJ$veOBuuoQSoB!M*o=GUH&;sV*g&2ey(TU5mzWUIu^&%*! zRQ}_DxH&sxoRJ99b9wjJGfO;@A7CuzjaWjzPSR1kosHiY)K%tLhZ6wApB^?5drors z)7G*iBnnTWPEtar8LIEr5F5ks@T9gSd|yFjZ4;jIZGG|UWM#^}8hYgJZtyD)k#-hM zqfaNgRQAP>nTfI@=?bW)-U`% zj=A6>s@emA1ipZW4UqQl)|g^~!$Uh^m^~ciIJ`&nM+0M5!De&ar*BQBzF19zNty6c zskx@-IO%n9u)F)@;2n)cLD#w6e$!B8gT47YT00D4Rs=&<>`ddJcibhoLjX|H#%WC&1E!;{TWF)_fu|1O>8zs zex1TQdA|`S7x~KA_6;2dqixSUC!{%X=YU@x+^W$^6hm7YK=53!j3#w zbnA57`aCT|4Jka#6Xhe)KricjR8%D@53K>>nN8|nEv(4CwnD7AeDiH{kPS38QWZ&Q z`@%*-&n~|G)D`9%FBDwW*j9_r+1ar5Pz4R+A?69W4v<1LT?>L)@YmBF>4HXA^fs9x@%ZarT}E**ZaJSXL&c{{y2 zXJ+?WQ@VPU?AxXk)J|SuK}Q|mZZdm>t$Z_yWs^v@sx4t2N!181URhWePF_W&5< zH5{Z-*K`B;s+Knpi{y)x$p7?YLJ+mIuEQ1e4aDw$6$-DNakjP=-%T#YMA* ztB4ci<*$TfVpmLdoYo6?#>?4KGchHY?rBk6TM!pMtF|gbr^@DEv5dJz&myNB&nbOU z%mllruS)D8gHf~^tz5Q{RM^ZNt5YX3sEi7<#f!vv8Z1hEmV{sVvv;30J`o_%(ys;R zZi7^2h~&VNYq()urdFxnrytU6+^Tf1zUZkHYFb+gN_jGqVI1n> zBZ_8e$NnV#h<&DB54Yu&zB?hZ&Cx0Sow5|+Q>w;*mvxO*)S~g~Lh1A>3 zrzLFT;YR(be06Lja)j1=c5`pp7Fxy9O=8fVh7(|5!D!Sar?I+!OBV|tO?m#|oJH2r zf2ol;_gncAs%pYbACcqzn>!Ja|Zc!_}@g-gw zP0+GJA)48Zf?(MgpostguRqXi^<;SkHqGE=UX@L@BaOIRDl5hu0JnbO9Lcm3rVs8g zXk~DB`WyMSF|(iD`)dsil-%o>kWSZIqc_0rCM;ZeeppSi{s48{mqW0Jpfh~gFgBAK zZ51#A(H8`XzR-pcrBWKb`d-uM;dqr6ZbHv<|L^HuG6YE43w5?_g}_(H6E@mk?*xv*Der|l`Jm$imtTSDVDw_OdT$# z-wrAO03OhFSu-?KEPbLl$lHSduM{BRNZJKg>2t(b9{R11GgVn0@bMqbUC+1l&zxkN zxHbqWI-Wam(^ZX69h;pY^Q0gJ(7*4-N4Sm%UVJ0)kUu8I71T5GE;&t~Im+QfZqf(p zJ4VQfo;y$fqsA4=o+(s#0lV}`r_#xhu#U%(G7O`JR&UDZazeF4{FS6rPs^vFOX;tMTA%AIwaJC)6U>f3w_e*!yE) z+K*t={OaQ(+3FqDaaTpo1+pP_?49zB_kJZ|!T;Dur4;wxBu(}!NFFY0^r~0Jl<;Bj zN#iV%fcR~A=?X>8xkDE;?u_vFC9;+KTWCIGQP=r_|52L@Cb+A#MOy;;y7!zaUeK}j zbCU8mk3@nMQG<8F8xebW?KZJ(C7D7YA1L6}5tA{YvaWS90N@uwJ~*x8S^Dm9`CU`R?)&F}w2~xA z;Dl?QfSjZIsY>Kdn&yVlJ1KrvtJ;8yN52o)%;cx@C$9Kb9%)HnMYJ-@aCd{GXT_CZ zVgL38MRuyK?$Cj!g$zYOmFL|hOlUqW)LZyY*iM&%zd#yuPZjaz>foO+4;BQ?l!Vo2 zt_twS!(+Lo6UnJ#85v+1Uxg*)+jGPxuOj8_K5v9y?_4gVr2%ybHgC1L1BuZjY1|uT z=jc-*T}a1NrAnMsQUz$mh<|DM17Hm`5B^1VoDGr#g1#w>vx3;$(NB=~_xc5L6qPNL z@|P8eZ34AdjRLu%Kp=Z~_WcyqJrT{U6f$0}yz%IY{!bT1PHV;kaH)a!p_23B$5I>U z^jjeP!H|dYH*Jf;9mKGURZ5xXjUaXq&Yn9zaASyLYbv9!v_9zx-r|@(go8%P4&C;s zfc3s1u@ECBq# z55BZa(TpZC-ju!Wn$N_;%#KWoW$pJV*w5+4D+?fjkEx)t^F2eySt^O3c4C+e{Fv-| z+Tu{gCvm{unXsa=Zu79yi64bzP6HCJC|Qp;c?7jzH?*yiCSheu?i!{^yd*dB>VL_R zDoUS;^&cS}VU3 zO6`d6o%p-U9lCP6!C-18Zb!oC4WkAewum%0@*OgDge~`~z+>Q)9q32M_IY!LNh}eB zf4uHntI|~2c+MhYY$L%6$3Vla>H$j&O}yyX1!X|JX=C4#=iCj_zx$b-Ndl_KIt_U+ zFn1p*MoEV}D3OfmT zJomuTAhAZCrwj09J54riD{oef<_EJ{hKJnf=!()D$({wTm*0Qip1)Mg2UZjcPPJrI zS6N9WO;<&Aa%&4edS7=xb51*Kny4s>?Vr06xb9)GEwrT^gAcjoER61Mih^A6SS;^9 zVGwHYRyT{mEyk3?+K*)_lAsqdzzo8bghnU6WnX77jBrq*Qs`!n^@R5RlFM0}a3H$? zkKs^OI@DB(BO+(CmM&5|-sLApohg0D9ZZuazi^T`&@Vpjf)ud+Wj_q*Syie!`OEVZ zV?*r>V$L=F0HRCCy7PD7i`ESmsSe1WqaH}2(Cp;^GGydEHuI#M=SLp@Bf!@rd7S2< z0>$vWAdofY&~5!4;(57_s}fb-G^nZ6@M$^f2P~{oNg&2?Mbs;F$Q&-Hv+vq_AAhza zzjB%L%u8c`v~m=Hu^Jw*KZ-Y8MAqn@RW;zdgLv4y<^(MQ_xkEc-vpA{QUTB7I##IP zkzyIsXg%It!dm-z6zcVqTK3Q+<<$$+QMla$q1>H<{k`!hrw0>|Hn2N;#7uc`O}wV^ z{r|uGnUM`FlhNy6LV|5}o|6a@T0pgs+$T+hOX z4lR*n<+WU#!_Th)nqMb7jTyrA}(JeY#6)GG<~@a58Igpw)_oFps3YU6A*%pl3|bh=lF8NoZ~6(GBbbHe7vlr$G4b-45C_ex4)(8M%WdflYm+M?Qq!+7AUv zayxT~mAzOqwFOp&@8pRzs-q|y!<1Ve)mfhHMEXBeJ^>cW;L{n0sKUTraM4? zaW=$C==B~aEQ_T-`{3vV)QC!t>ydb!(0^x;nbljGQ~8Nrmx#HKSflM1-F(c&=iBgh zU7m(GA>ySO=4F!;-|~J}D`0rMBf^>4pIiL!N@dL100>Mkd|Hs8D<;Wlqc%ZkKqO!^ z+p>=F-%p-UVZU&ol)bM|byi1Pm5Qq|$3R;zQSeZg75kH!kikWDC**mpdhPl8_CC9I zL^TSzSz;GA9eTc(R|xqLGmtMZVIal*Yf%W8yXb)YrU0n6ZfJ+QN{a^TJN77r zR8NlT^EidQC4{(paZU@lYptE-X)T9YeKDhvvSsUJD`s+5qCz|95NQy@E=mFGTL@a@ zv(&M!gbD(A)|fI_%-3gbnmw`53*GZ-?NSYercWUEb4%!!rek1h9i|9dk4oBg? z(cPv}^50$UZYHu8(TecSLX6#f`(815CkAy6-!sfrAW&Ldage-LlD1h zJFR}pNu=n|`I8MNh}pr~3t=VT+}x()mdpU^^l{bjex1kxqf3hm+XltUAj90U9Y?%L zKC^7t%7CUyzN+h790;DbfYL_vbSFs{B8HhwFe)mLA+;ats%l$Nw5&2;ij=!y#=_EA zwYyw$vce~YdZZxbA~rF80_|d@MBPP2{rJhws?#+nLcsn%yfQ`jAuv?P@!4-+rQfuZ ziQ-YPa}_6Q|7y*s{g*$+ABn#6`Xrk7Vfg9ZB`5f7cBSw9)~u{65XJ?m#N&sE&k-4 zo$`naqFN3W4=qAI*CykHt#WXgA-_f1$aJb6PB~-$$#t4JETTDBDpYhjK{KTWQ$=HQ z1%Td$VUAvFI-6Nlo9Z|wq#)L9H*b|Y!B_*Q>qaN1FoW{V7_vy@IQ7L_@ zIj3zoq_V-X7%lM?to<5WRJ>7U%c~FYx#qLUZ`C97D)d!JjD}a2UW^;-$FnH#xW_o1 z;p?A3`;0Ly0LEb9R7RAz}uF*$6+!0x^PKFzxrF6(V98YeVr3gY|IlC;auuSyp zAlrYtZyAb*&`;99>HOzjykwN!9TvVXXQ`A$X#4mQT+-qNLgSys0rCFju^NXbrz*8-jtulVy5PRI+rmUog9#%49ByT|O1l`^5}>MJ zwI_4Lo*a?ey!6x?Cg_HRbz7RhLO=RpdjE-kU-$tM{^)j6=DQM%@9Iq!5uQaQ*UHCh=Rn}eTWak^&)Xy0Ob5)F~P$s4=p1j6_hH|s5Aos~$e=LfsnefyF?+%A( z-P{OezUanW{t`&f(<#&(bp0ZUQ-jKmEX_{g#(RB}^~quPLXs_DB;W!2LGu&e#|m<@ zNr9{T?kb?z`1Az^#rKyM+AdL+dZp0UN5%mPGyMJDf3I{^`J^ zMm|xGimhbj4EicXmf|HFRtH}~wfQ$7HUcMMZIEuIa^(rt=f0Qg0FbwU)DUj^|h~kcv^rBcgu5IK4qsW^R)|of9eh9j)%myAZQ~rzZ4ps-uoQqCs<( z6pRP*+3?ZzbM89#1P$}{hvchhvi1vsQ8K1_2K&RQ1-Z> zL$!Kui+8M1dw#wb)kvIK4ciI2G?!k+ys9j;!M%Kx{vgOm9J~wFGu6Kl3`kG(ybsD$ zD45^|V>QyDnDE1uX3VX|*lU*1ewU=B!LkDv{G?ug3wHvq-e}TePfHM>4)#S zlY+S~2i|gcV{gc@k_!lXKPf5)yWz~vI1z|u~i>ZulEl0jG3ULPYJmSmY$p@VT{Ze)5lN&-}v#Xic7hk)!jgF z-k7V^au-3kBR~G-9gd-=B8;FkxA(-HaZs%(wy$!A5Q_lF;5azFqwqLT+AvPbtK8v$ zY;ZVnH1^^lS8T)|8y2vuS$xwEq1I}Dp<~cXgiEL-0-ScX6;UIgKT89HFwchQ&`=lO zHfwjiVn5CjeK}Lk_y$$BNP^4#z0IZza2~h?^C&h7)|0`|pE;yx7}TOh!0S}m)P=>_ zlBLB@nVEduW2}2(>44ywh>v9X1V^K$)VgP{x_Ea+8MD!btqz4YoW+B#&Kwc}I~R0C zt=KP@9FX^nh0$~=3t9dDn15jD)D23_Z#7uXDk-o_fAda@hV3ZA2z>2i`iEB9u?KJV2r7(ionTyCX`hoxe1%;I%F8+N<`NFMb?F zQUXm<&V#6rLz2+tSI~1|;Wz>KcgNngxC38$NA)2a83aHfb z28J5`Qy`fBUB#px(xdivW6H~ts0r;(7cMp85)z$j zP})C+WP^QDzBN3Nf#uhjDm3{#7w~7TD#fejD=^>Z@%XAS0|v!deUeO_x0~`c?~0J2 zc_t-Z6#XoR-jx%_2uo32RhGtkV-Rq$DDl9b5*%IRx71vn?b2xzH0-$uzCB0JtmQ0c z5U%9>@3$=H(oDL8yQ(^qxaI=6vPSU_^F#EJ6*yqlB{RFFsi43M^3j+(nV2OyR=sGoiMo^FLTAU^8-b++l zTu^#I_TqFKKN--@`oL#7mo`#!MIlw-#KJR3NfJa-EQ%oUpRG9kNj%o30-njf;q3e8 zfp1PCHRl}sWCMzRMYOBahb-B%Jf|t2$(tAQNsn^rClbqyFOHR33&=xNM*fjH`wjF$` zTDZwC50Ov>11XM9F>wN0N#EtSEz67N6$8jLhH}82{y=_acaYKC(jpav`$j0^%O(0@ zK`RWf^3M5XtIVqF-e{-ISpZo?)04Xj2J+08?W0V6VE83!Af>7*ixkAb?Wav4@XA^L zv=?9D7sm!pn1nv>Fx4!s%T9v#+m!9KAp2flt@%$nB z-hJ#XfkKi5gG6}W;?VE|a@piG#GBp_4>e|27)NlkCUiEWR!z#?zognpxDkk;>5tO=bgM11>|vkK0(lQ$L}+gSpSGOzjiIgZvD#d;cX6!%+&F@qjX zsJui@!+kLyWb~;{k^cgqh!6)-rCt}5!Nj1s$VGrPl;-kE{Zb1F^~*< z-HT@#HUPS+^g8?>`e_82v+pqxmXBG#xn7a;i};7cP#6^#1hJ9->2>&~3>Y9r@7LTze^nXD zDA7nNY3}k@qZW7mo;m`mW1&NV@V6t|ERN#707gK$zs@8(MYZpN!`K`sH6HhmqU5w& zbo)Jb5%h87bN1lX;9hnzCyW+YN%9>Q`Trh2>ZGA3Qh`21jq(J)Wllc8gn@itU!i7K zUvCX}Yg*)v3o^hMe%YCmFj8fu#u8u&&Pp7}V2Z_}jN#DtMMdOd9ACX#VKIz%-G*#O zXdr_XkBmG$_L$L}T__;uS=1{Wv+hKnX*G&e!5R!tC^lml3fikhn-)(8dk#fYSsyI< z14HbQYz!*`iXS0fq5@gXYc;mIvLA&Hs5c|uI)C>V-th_yZR3dfrj0B*oiU| z0%80e{aM<4hI|LdqM$-{fP9a_69N(GjlWIFByZncKuPTK z$h;w=4^Javb4a;X1>jFq*ox6NM?27!Nr)ey2yUVu_?x}n7fUH$Tx6so4!VpJUx}5M z+VR_=9C!r(uzU5jvR@vgPl7%9FAr_|b(jVhMg?6q{**U0`0Jy>Av7*}0U-bxO^G!B z_t7m0e$L&eaAdp-+L8hH7=m2xx+Np(14cjm6KNnMRS)coxpbP4Q|QuIM~8ANX_Yj< zv59&tT|DWe7INsYMf-5y6(G|e7(~#f+1P>*(^j}cZlzX9Ex`Gsn(O3k3B@@U%{Xd9 z+>pWw)|W}4&4K6$_YsRO_FXQ)vQf&UJuId`u%Mc0iZYn(uR~Tr{>(1tw`g^Gm z5T!Ox3s2hop4o$J%K!t9CYq>>6~{=Ltjl33;DchYle1fIX6Ub_NovJOWFH?yA}!uR z5M|ioWyeSpr7aF=W=`)|@VABEMud4>4zbgUeglOChjjY&Q;)p&$XqttrEVQr7hc~$8AZN~UusTv?s3{$4pQZ%T@JRyfTw5OUUGoJ4PRO8$xXH zh8x4xACajgJa5Wd)fNz+ALsf z$S7;Bi-jF8K?p0~{KXNCT`W;@GA*Q`5?Imi$q{*agK@kp@=Z`FScRPJSysB_)V^j0 zWp3$Y?!@6Ww=mZe*#fK2uhu-u1i3XaFW3nmQDw~3;h3ek5#?`PS?>$fwjr;cWY$cu z37)auHMT;Wy14{Oy2HW1xP@deT4dLU$);k zt5`H8UR;5$L6%66i^zI&z`dX`Tw|N7V4>S=BfKjMwSc`&&rclmAOU@W=|>2R6OxLy zGm6Ed2QWe-#Fual4kvzNvxHfjAeqa_=GDmja(LQsc*25A$h&4IK_V1GVUFEY&eH>@ zZ9oPSd%dNBA9?t328X0mM2m)Zm9p<;ezJev2EM7ZQJ(TW81cE z+qP}nw(Y#2Z4K(riH7;lmoZX;#4rGR*9Y2}#)q7@GM?}uQ; ztXEz&f?miRMC4^E14l$cM+FwHq5NpjT|YDqu3~dHNs$(V8ES})F`1S)H=L!H^B5|7 z70MHG^?kh@V@VGS=2r4%&!`E;n|u^Y6LFvtNMrXZ(>od{HT(+DPZ?I7hoh__QqU+H zrO%Q~gF74^^D#ykc9qSC%o(yrK)6`QS@LY^h@-#f2y7}fj8z$N8iaij;PQqd^RkAA z4dxN&p51JvRqPNd(HYtOwxAy^GzMKVqNd6y929YT860CIJMTvF1l%o6L;; z{>VlNE8dOkavX=QDvLK7H5A-u_3lM7((IWHl;moA_GTT#0hgx9YL9`(v}`5f|P zJhSha%Igztib{!q50S!rESspEs=22);x0QDsKTf~D`+ubW$&-L-PK-At$Yjv3y2${ zFwjq6W(7L;P*S9?+GWLhy;qz_dwsQM#vaSAS=Hj{<1sSwV`V-O1dB#Nun61#ZTQ^M zkIrV{b1H2T;Ihe48p11@xhaYKhaWX4f8dDO&xXoeoE-u;!v#hU3hfRF7XYEIe}!RQ z2_Gi|y74KjW0q3tL|7(%ln(iRI8v~dG348vru8lOsv8NDEh+y3`g+nrSFevh>7@`X zSaE1gSyalIhWU$6YFzxWj@ogGHs80m^sm%o`E!Bgcx{t>G6vWR>T;g(Le@yV7u)L# z#hFn_4J|}odcZItY*};?m{@An@lji#uxlM~65vPbB2OzMvG&*8(t%@#xe&a6I!G8 z(k}^?q3ALor2FH2?XPy+@r5>y1`;!6DOeKQ^lS{M`Tr5CJ-%mhH5ldN330n;{eptI zh^Vw3T=RqkN`HHgt2XTwGXy!Lis0Bou4z+{Nx}66yl0!$^`qOYC5Nh)hK6han;a`t%)Yq8Tti03wG`puMk_eLU@ZMR&QbuSX9GUmYP#Fh{N0kI8cw zQ}OdWT8hLtYW~FQ(ZMNExkC!3Rsuys00>7++g^Zcgz+;Hf8@VGFVi;J{kgoS8R@3XIuH% zEjI*mQzh$`L}_=2q0-iiQh?J=?kp12@|0v9B^``cm8zy!(N$ig;61cIf~SIQSb7d) zQby2&-(r=q&iU3^)+*rd*U0qmLoBch=O|?O#yAq~$ z?Ev*ej8nU-qVhGef%N3D7P}N9kAqWq)!8i;amonLD*67;zuxrF53cqdyKb9KAd!`@ z&YqsWjmO%L{nc|vv(;dn-m^wr_LVV<-JNG}CN=JD8BpRvZTuHPLAe@&clFeU>bq+R zjF&jv=vdDplL(3#O55DByLq$tUUTt7zjSeznpiG|jO6%MyjO(EZN!O?MASM0ClP;6 z?zV%2tC^#bogjd@T%2%AxdZmNgRUl7e39Q`>W)vS}1S$X=-8%8V(l0!Ru zRU3hFwR-utvtZY=WBJb$-j#*{O~Xm6qYoFy*mApTj6E$GHUthMi=EZ(d#m_ zsqMLT{~kS-07>Q}u8_xwkofKdh0HXD;0rbuG&4uFMhXvdKlfOrZ7$}=TMcHuc3EJ! z(=DL?Uo!6dEf1|z5x8+7p1jM?$+3VC@@S#``v7q%^9gF+n{K(wp|9uo1;6PF=8hzZ zxUL{#IL(i_$>FE73yUk_-YIX<*mN6_l%7X1*%ZnjGf4TE4RYYAIUGxrunpbJZ$ie^ z0r~IJ{^lwoM_TzBz8Wjf#hOWCkf04ahI3|jG(7%B&+>E#32jIT3^&w+@Fp`l?^>26 z7ya3TX!q7+z3wuqS<@k03z9$9)&VXFyQS#kE({@i5E2RmKu-NO`7s<}v150LaYRE& z=R2L|R#X;jXe*-Q>zQ#AadMmS-_@Rm|xt?nuB3$@cBLsy}sM|N#wm`Hvxv2mYwI8 zwNN@L1+6i$8TfWK;_sh2tm{0cSLsq(X_CcCa^y{Z5D#Ca+}FeWsz-vS-(sLt=!Sg!%>k ztx$YE=+_~)%TAWrZxnQ?+Tz!|v9)2j;3vfBV~2DqVQFReu_D4TT<#!_a(|xeOm(Px zm`IP@nUw)I#FG@UT->FxuGhK8o2x{lsL1mCVgxMWoGL6fh1KvBz!f7Os3gns*OSI_ zWije^@CAiR0`@piz7>~>{+i<@%E+Em^2x+{gAG)5IO=blb7!|F{?M+v)G`-!U9k|O zTU8zO%E%vRI?4crE{{s_jv`)N{~d}&K9P!7*OSV32M5p^t;^5USyFsJr%ygCI>5>_ zsIzHZ5;luA--BCRJ03|yv}OipgD?^4r1(N$SX5yW_`hF6g8#E`0t(jO>$6&`?#W~9 z<>rOf{}jF?BP6t=>+PsCYfY+?h_(+PVFS;#)|7?hB58~gukpz8RWJnzjXAMv4 zM&9@*Aa1#OZ6sO5f`ToLN6pfNYW;rSokX{^NM1l3fGb{F7w|LeILauSXG@POTLmw_ zavyJlm{DXURfp5b2ma?WF&n<%Bg6cijBBcGP_s7PCWV^%CFxsP=CNQ*Mf>_kB4Rvc zd{4%=6F2i#J6GOw=>Xz8o4Oyh{|ZXB)f)@tYz@U`YyRUfyk@C%k-S1e4Y%ZZ<>?8r zrnfDH;fSR_RaA|G?@AI!6*gn(?dx_gCfqaQEfLD6?^igLk_AJ^JR(6o?CZEOG z(4{v%u35FsFl=eYaIy%=xGzyJu879AI=~faZ#UH>hjby{f|?ZDLlN0T;%H>6Pa~}C zyKVg}K;zp`ZG~AbxxyPPvky6X)t8-2W3AN<7xcuuW|(;v_CqS+W9t&g;_kvLXJOWb zCNjt*yC~&7OnWZ^UNdXvz+PrON*K{hlolGfICN0|mS3O5gX@y}46){Z;>2-YBto7Z zRMy%jzhA!_;Sukc4KIJc7)+40{&uTa_(E#N3q;!djRFPIMnrWy&t*4)ITIz0V6MxF^JbuV2n&A6VZnr>}E&CfwO=dy=}%kn1L<6#1F5R-bIa4Q|J?-;C`{xpI4Q82mKc9B9Eh5+>q zHzby3J}EwIIXdC0wVRi|&Ts0%5WRMup}b}f`jEHSpo}w%1yNx)5S%9-J*yxtZgL>I z3{Ez(#i6v|SVCxn`Js7B?bWhnuBm3fPNnSANWuSYJ?TFGd^RxJEX^U9uA+ssf>rMB z>tSU}QR@`3XfOv5R;N1#;DFf-!M(*3n|mX>1AG^RK<{X!{djwr^|fF~m3Do~c4DbB zTkjy=XLQ}$w?OjPH$<@oV0jCRzb1-6qw?Z4AoHSsCTEh0R7}d>r^*xG{B4c$;#&J^ z8`|>}sD2m1${T@!)*x}8K6_Z8ZdWDKq1L$#cRJ9P-K$(5VP<~q)fhce_nLZwnE=fM zb85j-#W`{oKTdC~!D zu>7rOrJdDwOz`_g(2!D--55IF+V8Sm12-AXL^rF4-!sTZUW?tI_Fm!14^#Rt#M>L{ z8X)}4|1%|QBl=n>$q&QKD@{S-i;H4P#1iCn7n7~~w+dAKHr+1S_#fvSf(wNya6eB+ zanqfJLKhzaA@ke-`sVO{!ZwpV1Y4460l=nQQSTo>q%jb>5yHgoqaLQTj)jLnF~9v$kEXj@LwzZ*6& zav8(fRoL7s4f>-mY9k~E>KO(uEGOZA;oYTS+1rXxVPiu^2nzdcYwrY4Wc?tuP6_m` zGRtUSccO1(gcKjFUq%}^2+NF%Xp1l50RY&O)l1hqbs61;qjxo})<$(|T{tKJL@!|1 z=U*iJJ8j7RFBCyrxs}mB>1*!de(@wf!qR{di=lRsH7tGS06DM7hP43BboAlbO za(d88+uQ|ec`mqP$f^(BA*9(d2ofMuxy}+`af&i>3H^jJF`Bl7Bn1|>a_>^k8AKp3#DB0< z6j~oTTNy~jUnVvCW-MHQS!G9EtJrM9J^JpxiMbT$nb%Kuc)twv7BUKm zC6k!#6nbr5X_RRl0!fT^F4?aEstM6#BMV>G4+sON!06Q8 zW8JDZPE~@Dag0o3lF2$@Nhl{w>)~Zd^JTx~DVtDNFZb6*4A997TD5(Wp`GZTLL zBFwKZ#k<Erqk7pfjZSC(2N-vwm+e@itdDea4KzQz5?Abv+`X zmZ|Lmc4USx2o^BXJw5|ADW^RbA*u?_)`szESU>Hq#_Sn4#Mv9y254%@;=F+=FYx$A zg7ObQKRz(hHvKz8-|^pbHkK=$M3F9+_^-w6m z=}XW1vsEu5ndO=lE;2P)vgA?4Lu03i*clEwkv7GUIj3nqdv^aJ7YHR2;(a?yKO_Df zGRV*PP1DgBJ2DquEssubN;M_8RzWIO#F<3^HMXJp2_uyc(@LPtg!GYc4d z?UE<>X|Q%DMUe#P&~>YXi+STT+!+*aeW8~V2Rqbg4)ysgywi-tOpe9z0pA#25iG1e z5WR~DMpERM-K^&U(VZJnbEl1hvxuPFeC*{W5GArfxUbSYI}lv7q|nnracf*Q2gy_)g`>ZW?Iz-AK4|f>P`ubGzwxiTh}n+Kz(Jn5fN4&{*3`ujPc5}vp)(*eJuH+8EIRfNvbo%j%{ z@iQYy8+VJF%ed&h00?UkDq+Tk-6y+V@0JQ;q1+R{AgHbG_`Yd{>+YP#5q(Le)|$3v z1Sp%ImuQ&68gAU4f@|uK>O9_rLW{*k0n_P|EpCSkut~|IB?$yk9j9f3k?zAX5sq+{ zvqsKue$MBr#;us1k3|8eM#j;`Y)Jmpy1aRyJKVBmnVedL!?vfXY{j~AN^rwTIHU&i zIJJ|HMpNrxwEIqn^2IqHU{-5Erw{raw{Ng~qiM2m>lX%BAneDA5 zQr-OgYH)_!CsvjL)jxtSv7+8wy%1COev@fEesg6}e3z#P2W8#nG}iobXu)E?O>+g; zNyW3<{eNx-mWo`lnmMx)d90_9Vb5xcTEB`RH8w{sZJz0xCN56AWl2_ zEg}nL^Thpp%MHmyMHu<_O`-byW`6k4n){umYotrlMn9JlqzFNtot~6cSUTpYRqwcF z?(7D*q#(*|=+|vhwzDPw<4wf|SVeo4=ueH6r|(_bkDCVx`{4zOo>2+=%sG*iFH42$qZAi)3O>D;muaR4wK35;FZf_s^$d8x*Us~JImv=({C#@ z+XE=WK>;xF31UILr;v5^vp~*qWLpr&IyS}&8eajABR4qAnW;O3jNvbYYP7~iBI`11 z`Ut;NEIQ@kNEEj1)Sl%e7e;*=c9dXJiISfZ5n@(5CEroJ+S8Cy>u|BuYj3EI#J{g? z7=)eI??K%Rn@%@%V(vanA(F>(*lVa|A4pkQA^^|A@Ml|>?GSym&&)0N1-eWx+r4>A zj9>Dooh4T(%Tv=5P%T(;R4DHOiN{mf(DEV8n&e61U|j|aI7?%4%jU2mW)S1bYTr>p zon~g^!tIuh2>U&Z+ydgpo6W|g2(lF96PIa~OX}kVbw6$JtOwu>s|N}(@8EVFSLuAA zz^`Y}!DT{zqfH9-t(wxlcwmK>!@+@(QlEfoO zl)8X}NMcgr1Jhro;IA;_1sknf`7eVp#|!X@9Q@OI!(L$Yyu~hRpX;rgOmGYMu5(c6U3rzoF)ce-m4#f#)DTC~H9D^lF7H>g?WSWbCX{ zuOMG8zTf%er6mh8AaL8;K>p7-I;Z91NS{Vcp29P1UQ3H_T+!NwcRfrRD6@?;?%@~x zGSm4-gt2XJf~=gD+NY|CVKa1Mz&C^0!FGbKhv6tXj;zwrWVISk!zCl^=8sk}$-5Ch zn7KS9<$DTbKcIKR7Ur5Zm=qi=v`*77m6otOZNA&v3QQ)2AI_jgdEPk0oIuXK|0s^Q+AO@Q87)w04VmSf z=&whRP50+qGHX#eg--dRQEjic{(-`zkw#>w-sIjlJ64BiA;ek?KW(gb7dz=)sDcg> zcgj}U$4hW8sub%v)NUIo$U4uJJ#A2CoY8fb%0D%Qj^;#ht8 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%0AT`)`um^BeKya7K4<}v{ZO=t^93c()&*=g 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

9~h%871L2VsKWUc?`IhWXeX( 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

g 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

F2^i@|obw`qEPRc;^ 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

A z8UH-I`q&`0+n{6>g$c3)!_=u2UIs z_|2!Q2@qlW)|iSY*+tEKOx>Frfa`DgZhm&CZQ-Ys0+-;7YFQ> z*@W*}J|C9$lvKxo73I)BMN=YKn74cpL7l3qkCY?GWk3{(93b4M1Rtj>(W!RLstBP^ z46di^tcLvIrkxVGo$d$gpErS@T&mJHP2b6krO6g=YlOdLs^s_GKn%MDW!_t=&jB)j z0GaUXs3Y0*x}fkWT1HTTO|w>AD!G%H+_)I}08a8<1d<4d=w-+dC9l_m*yi@xN!ICG zf%dY=`eM@C>u#PG!@Nxh7wSge(A_dFgc0LyI``(6Tf#Agp^$^xYP_09_X!)H`47Dl zm4qPu;Klt~Y2>pB5>p6E5yojqyLNXi@AZqM^2G^0Mt6R{O3B*y54n8lUarn1OxoSTh(#a{Apye9k>OJdM;MhXc>^>L=w!V12K`Ltm8N%=5eD5N2t5FkOMHjy#&>=M$UYE?68T{!e@DUg1f z?g(7U_6JIaeg{OT7T(VWQ{3504YWuF=P9TcHsJX&xj=UGGiyA{^fN-NM9geC(425E zmessW?8>-U0$pZ0z{)$ta!7RI5%AD_!}#<7ZJ!M9=_?g?P1Hfs#@H{EDEVgxZJ1`8 zgEe{m3s{i@W(!oBZPeix&-!bSD%UFN?-zHC?(ISV9&DDwoT_MoKR{KC(RV!DZLQXY zW%0aR-PF3>OMDLwkrW?Jm}B zZ|sp@uZ;6svGB-?tC3bK4(WAZFoaJo#)czW3<4|;J{hud?^mGl#{N7;nTl<)ut!@^ zil`_376$cWJi1fgNFa>293c4<1WYSWKA^GA^BdwPRB1>h5h3qbDL^XwH9oFA$}!Rd zAlU($Wsqf~w7!Gp-1mdirEUI%JE%W^5{9fkE=v%R=>}K{CX01q*b>vk81^)Qsq`Yu zL(GVzX9SRa7Dm1yqH-3b1jCMS)LwKFoG%ylSMie{1{tFuHG)~wwvolb<^BrKmb|uE11+0*`IFD+}7QKM{u{(v05atrr z1@;-TFq-X@9uC`VoG^QJCgd{ceQ8sd5{%W(_in)=oO4N^NB}WR|63MnnqbB7is^`8 zE=8#|5&&sAY9zu;@?3ebkfQ7gIZ24GTOQC^7-u!#c*N-|L&aB=8SB$iCX~7aiDyou z5hazdUB1~6ltZ`lsho5tgY9H)^X^LHW!k|ISu6NXCTz`lt#&u#S>(7#RjSW0CC1Zr z-}BC`#fIW($~I+d`Uu8r1Zy5gHu%SMgnQN`d{z1a8Yg&iN9vZ98Kz7TQAq4IkbkvN z9-MX$>c3yB0$BEqs1V-6c#=bzrHnkOq?QdMr< zJO@B@Sea03;tBx?UbmIx-cY>6gXCkuS5!Fk5)QKLU0eh{2W4Xfg!6^0v1?z2zPm#} z{@z{Laj@bo;BCHnNdoCyw*tiwmt=%0CnR<&;sDQ?S5|bV|WWj{J;fXJJE0MkIFyE~`lo-l(2B9IKNycZE@Gf~W zB~>9j29QGK*HPhC2N60TRZm@XA;k*Lv!9YHv6OIGpi6iqxKJk%EKK%I1SIMhE zGmC6Yb$vTbBcMQ7$mDP#noRVIp0yr1D(jG3zJ zAgap#wjP(QB3{J~z8{Ld;@Q&pZQWt+hb^94P;(P>K_#xmG`9VUTDwXgQqCx-hn0u+1IMz4etV68?)}Rj+`)ZqOumX|PQUH^bvC%M1zv5cSD5x&Qa>Z!HxR zABs*u`^{8R%a2=3kr5Q=1M=tYK|!{Ye%~xJyrSW?vnBo^{DyRh#Xd}{+Mr|~%d*&V zNE_XL`#Kv5!2tS78pd>V6?H1(Sz-%NS{F#pq}(7*uqwd>naI;pSMN+4KubJwDClwF z!Yy)vxpoQ=+SWMVdAUth46)8K$Tc86WAIi=rxPBdTQ*cCbrvY%sDABCQ9aC&GP<~S zmmnp>9zHb?)H-4~?BYCgVS$T?64#FR>Hi8G;3gJyB|c<;b9-|l_|(YqF=Xk1kFDMp z9Ov;dkwzz^4eKGFg;sCPamwCA&K|&cP|_F3N3dNM5V&S&RRuO{zJOHuv<#0ME{{~m zu=h3AgnVO4_Z^x-lRnY&R+I;a8BK3}0n2Z20nAGnlkzJTQ@?)y*8D&&RC{)xk1@Ag ztEST0ELJ(8mNnHTYGf@`3;Y%ZyjDd|?>5;{ZKH-x3UesOdXx}8P!d9zX`#c0)z56d z&B9PpxRdt|uR@zoy$qFZXWe8av}71#*Wk(naMNS4%zG}A^gX_S7g)_7RoJUjS7dgk z+`!M)P$NE>&X6M3k{IMA@B}Ht%?T593M#A;WMu2w%9f43G{6^4PfgE?C=soKwcOo@dKg(A8^*RHr z30(X{?4;*Q5sLnHnhK+xF8Rdg1H<^jDu(1~;3V0@J9mFi#!$2$~)Qw3F@ zwiA7_N)zEKlF>$>^*=->V|~)UbiuITFL$PmP$!%Lm0Xq2(;35du{%eT_&o;!f)FDajo-E_^;R4xszi4UJ9Yg6>;?z0;%nV*P?rQc%w6Q_zG=F4$T&7*{pc=cU(U zu!IjP4!|2d8558@2IWv%c6F>u`H&Ar|$tXC)%5B1iQOwOx1b@iw%RN|kWd)jfKqVcBlgwh{Wj_t> zxbjjYfIF^~HJexIe znmvs>zW+zw`Vb-MR|G5rhcSYW#||9Sm&4Od)iN_(bMYD!)Rv`RK8l&?14=@8bGaE} z9ZyoI%=$Pg8$PC*$0c>CjS#+2)^!pB4uq3!?+6j~6Ju5=eoNeCD%5yYw-_oPC89wK z1d9_;C_Lq2)zLn*;@ahRc&=gY?;6LfR_c$Ve^%+@*J7Wcqa*kt#4zD*zOZv5>|CzZ zbN~GI@lck$;GfB#ejB#>w~?s-a`>r~k)?^fDINp!`^?Y35-ByPTSP4n!oPZU2^<8) zOHjM&G)ppk1}3UOB(io3u@hEU;O7gAkE9cxA=SIjs59wmr9VX4fR_k%9dI0w@G%gqT%M#n{G#i-KvaY9~Tf#+{e$5m0yx7&^OcK)8^8)hrs2n@CpZ{viUO4q`}L>8Q_G&*gU zUOmJYubgkEdqZlv6}aS}SFu#AcEnt+cU(7XB+YOth8b~X7dCSV));s5MXV|a82Th` z&<)}4h~tTAWvnWlb1b2s-M{7McqSY>zx0VrWGbrg_UTNuWz|}zqjG)+sSZD-x-$3z z45IoZkm@0?2-Sxm!kWF|^yn(7N(dHH)VXo&u<8MPv3|9R4fM6$lUYY>^R)E?qULh9 z_vP9iy8X(8^v)w2{>|&EvGkbTa``aCP2@RZ=gZY~UDuCm^rm%l>^wK^AD_^sm2Pu~ zm9gu02{RkZSsWM;S_lu*g&dNsuI}54_C7Z{J9KqZ-rq=lt^>q!@Rmk;s-X{`V4&oL z6OSdkc@T3IPtg~2c3J#h3{TfsjuP(JgdWwXHM47xM7u1y(t`lZBfZwbK2keY7P~x_ zFBxifiox zK#x}gD+xjK(NVaXNLbQ(NV~1#gKz1f`q|=l;e>pbmOTx{2W(wc5>U?Z>;(fwPngt1 zE^9JQDv?EghTR%>rFo^a9yDi2KY)k~$h3SH?suMZj)OL*IQHQBNNy`+F4y%lIm#9M z+9+&DkqIP!upB|K&0=fm&dyV`0|R-$Q|W&2VX)q$CH8H``ebd#M^K$ClP?F87_0!5 z3Rm3=VjGU;L@RM^Asge58x!GQw5ed2i9RcyjD1b%YGB<6%8x^ zZLhZq%Qy&6ET26HH73hPYA@@b?urnM=&MMq0f>!HmjbC>vT<`R) zJ3P3yG}1eb`dCQ^{^;qw5MwU%be70zsB(qKb(p6o8ps-M917L@X!%Zv8#}dh04;!n zWL*3cNF&eSnol|W;ex$rWFP|QWU#)04Pph;qIYYsT1uOWS6VNTZ(t^=Fv;|6%?SW zDG#}wgS*}}eNQH~JNAc0truslm*kz5)-(5XxT&CB=BMY?>QY?lkj6fB!L{l8H#)Ox z#3rU919_f41!?Cf5^21dXwJhhsSQmOQYk#&W@r@#pN-}ZVivpy^zF}pr=5k|vul_~ zi=R02?#{nehB$unBdxBV#EHy7_AR~3P4;B@DDVXr1Rc!NP!7v`j2&uc4ZdJXJ{%Bm ziG7-Q+TWBvZ~px@V`7w0j4^%4d^#{~ z0EF}ze+1V^0^XP%gHSGs7!!$kPg$nC%=MBE0`=UrDPvX{(@ zVsq)CIZu&q*ikg#6lhp@!8HqwHSZjyF16iISr3gGfAj3>k`S1g%d+Yjc*M@q?XmY% zxh~oDjbKaYC0i)osMWQj2}4YSKF5Z9Nn+tljaTahCbWwg->+rEuLDUDL?zoQ;e+=| zO{qypj$&b?%t+xEOO?7R@V=*UxH>)ad&n5uLi3y%lC_5u@_?rO{9;MG!0+Kl18ILh zt-InxRTCihl6>>({+8Bfihc&N(=>$eLqQUc^~cc22L}J3tvp;@_p@&DhpC#;RW4kV zAG_g)8~w6-ABV?1ISk;XbkgayMAw?UMGt0@5|`4yYAUojl24*j!8X{J%94DeNBb_! z-kkzf2+auA2DLI)6#r(`#zYV5AP!R{GLk?Pq>{HI5!+WLZ%f=$D2vhY#PpG*M}Vna z_3IEF((s^`jL+0{CM^lRd5lXXN5q| zeE{KJr#0dxF@zGMx$1Q#jo3na<$lh;lSxU@BPI~{1LAcou@b{V9MVu=>%6?yLCXDj z!Rn>fUYQ%%hbP3uY|E=s7dfM&+gKX_$6cl|PPvLC+E3b&bHb*Il$`{Y)U0jG{$LGF z;$~;IyJ6jJIv2rZP~^1It%fniRHiA$1>0?9($b@-dYQ#)JQS|#z_u2#2rAUY-=Z4? zSEKBM&>uZFzo&vL(H?A-s)RL=1>?#hQb=wnRvO@^eV<52qE(CzY{?ZrHS_V->6B_M zuaaKMVG&pA)i60B+;!2PO+p^C*YqH${6fKWcBB?uOeuJ$G)CCa&o5XqrBi@VJ;`^(iWMp>@R zryN+}0fBI9(9TlYk~k*oRYi}Exf`XiL@Q-Qdt0T)oLuFds#HT21wk3gPKHv&DGWyo zCWhMh)wmaNcZU;jAIf2FTw0hR{lJa*ju$q$d0`$dbdKT9K5h5pjujU30c=>LISi_@ z4a}7fnT@5PK$06yrZ_S}>|o!)9&*ti`H^bEbx@BXiP~4KeKejBeIN#T;DUXJF#$AZ z&hn`lr5|Ejhrihdpu4t`s2TfJIEia>)WKw|LOs)ivT8=yf(M6*tAm(FtDAzsxh+*L z(zIFlC2#VjB5Q3K?;Evh-Cb@-Kkp&(Y|A1C|1x?d{}@Yz3_>tgS4K-pA3i{lkF! zzYVtk*VFgKj6R!~zK_mld!LanZfS31Yi(uzbMU>rt%K3~U~_3byDxamzt3y``{{uZJ;OSR-XaE2xV7w39$2qT{G6OsaNYONCbh_Q% zfWTl-zb<|)LU(sxH=q%*nB2cG`k!nE|8qwF2YJJvv;F^_(KEgC7W~cV>FM4X8~#$u z{gc)AYyYzPUmpJ}+WiXo|KtS^&{)7ZD-%m!F zzr{YrcV?V_7y5?9_>{4$vT?MU`N zHkh9bNdI#N^9OU)FN68NYcM})vi|1`<`2@ZUk3Ak*I<5fsr`2v3pDX05~rU~Oa zedxcd9DcP5e|1NHbw~fV=l)-n{C~NU|F16HhSvtbJ%I(=zX<(5JJ|o7p`Ym;8U4pS zqd!=4|5Kr#p5dL@_|K*hGxIwm@?V4h$?9~J;bF$!ZR^lkc<^ZH@VHro1h-m>S_Wt5 z=N2ea>iL%sn&T_fGfRH{{%|wu`u!0V*luu~gutlf{m|QoNAzxf;g0;?1Ebp2#AkfL zU4RAct{B{xi)b@ z;P?Ol|9AiB%KB7wwYgj$^78bbUUTDK0%zR~IKAG4S-oxGHG#j6dD!&2Oj>{18nS}5 ze!kJ*#6fR^|GQSs4?tP%&s}TnZI4eTP99;L5gOE8hc|h7kHQsZ702$E8MrtncdT!Q z2Tg9OfoWX>sJv$!LtXCA1K8`I+FA=-UUvLUs&qQtTOPg9`TxFH8+sph_AV!iY_2Y4 ztPbr>bgtRBTf&#)NV5zFN5+yaw=dPgZ{8T$Ij0n^x=ct_ezfeGf{oeCR>^A+A8O^N5_qOUn`ATRa2 zGj9Si9M2m72;#RNcXrS-t!uXP*YeZX&`1+Qw`(+MqZeqdG#$@d;hS(P(p8p77VIC}0eyWI9pb;E@^)2Ss)+HB3Q++(JA_Yei^_N!)BoW+V-+&pG7 zxLQMTw;PS9SIhS3Jp=grKy?XDJ!kD_Sgf32O7KH9UJAqbP?wpYa-BO1uZ2C^^iCoS zUC;I&Tg2Wb?`s2?9Dm-ZES6lJX%(ed?U(ZN$hU!pVJ&B3TpODlkEW^Uz2mK?zd@9!J(+peq(?a{wFXBP1$ zY%h{e7;s3={J6yOVk}Cen@qM>sh43{s;9X-`fSEM6TkT4@G^jd88^GT@j}2cYnw|t zRA>_BUQhkFqi(5cdvf69S+(38T$f(5cR07hh!n< z9$OX!Fxt-auAA??ue~M?v{GjGU0ieu92ThOlb5+a=Ge!)#finTPjEYUQz?J$Z;j;X z5y9(S?Z3&A-V!^+cpR%rPp_&RceeY|NyR1Ox7ViXmi`j_=k|N^RdxR`$KidT%is`~ z9=hU=I;>isA=TdRDCt=-r)&+GKF{we7@LbNSv)D+@8GXldf1`V%F_txkezBpjMR#2 z#u#&j5AHghbxy}l(;0kTn$cKpEi;)l^4Hpqi_>`Zs7f884xHv1Tzd%{H$LnrI5a%2 zZ4igh>YK3;(us@h2yAf~cd*r+-Zn=QNsIGOa!M`Y>ffXPK^lDT6;_V4-ABn-v4Erj zITU5&GPDId2!*hHSijBCC?`?$W!879*QVt}-=+{bZSpa(h+%)Wb>fZKFp;Kw_pedb z5prc}j~>UdQ=pbpIGKlzlq2}1$l*1jHIcM|Ww%e`%K0gd?Z-&R17gR^6L}XKdEDLL zgV{Et%O!=#6*mvNte0ffiPnpF7FZi^<92E{(ix8Iib{)c%+DJFa8q);&NQys43krb z5?I#H-gsAQ z`CToS$75El%j8O=jvrszmyxq5ZIw7;Ueag^rFcj8okmrNcABPlQ=gfmY(z^Qt_M<@ zO^LQgyAJ}lvJO<+x|VqlQ-_3g!(KYfaGKCWu2m=9sSmcO3kXw(j4+!Yz9#eZ*~_qJ zo+)+gme18>o<2J)nz2L2`Y9l$rwPi(h83#C@3sdkdmXK;_4>v6eezEa3| zflXcSmSpvF!nJix&Ek$c%HFtd8DltX)y}y~>%M4Zuxzbrk9EC&dwis2f@4BEvl}nZ zyGDZ2^iap8Q;J~)7XB;|l|$M2MCuxKYkQ#09Hjw;dhVjx63MEiyrh+f2`zaaCK>oR zZjk;cJvBMv!XhQhuVOYq#}Jk60+s&qy!T2^LmZ)$ggWwd^yKxpUrAkk?2hYwV%rcB zXG?ffHjQ4}$MEaJTX&ENop=Ab5lf_GFXU>GF`0P;|9fut$pE^qbkde>t8 z@kH;%@sMk56ghvlbozzV^<|=cxJZ(CU8M6Rd5UN+hAdWM_r9dVYw>8y-+)K0t{g>p zrho4Fv=UA82O>9+;M>Z3IKbm73AJE{e(`#o}WE!6^$W(g8w#!>8)B}l} zMXg$SMKp;3zPsD^sc>_6zsKNdc=oKzI9`Xn3)sojXzz?60GNfgdO=&eF;)5M%65G? ze@wYe^%1YcmiBN~Gigd5YS3lbna;?_5!bGsjVw{YlGX$}+X(G1>JeG5rw(OINqCNJ zs#EdsF~|s2!W8mOx7{BLcWSn`ViY%EPsD2+z2~UMODhbT_3H$+Eu zFE~k27jbMct*t=k=0;bZgS!gdZv=nl&2R9-6WjB=Z7ti&X-=#*W!IcHO5|R-_orMJ zs%AK_4$o;`xo=lvd-7Q}!-i%!UN3iHUG3KzD~C~C1#f%zE=EUPpyGe}iw|v4cbe?m zrH^G+6L6FyNR!v1ep}m`+GE)H%OUFeYY)FAC+@Nt-dY4&l4xb*%Ju0tE}Wgal4-8B z{REe(EFB!2Kl1tCGy8w}s$0zGVQ>9`r10UX^r0~SLA^k;;yLuF?5r)0W@|a=`&q8l z`SLC*^==icC#FK{ImVbyz60|mFNo)<%p?5Yci`vMh8&QNM+`^*0oJxg?5q>k6z%r) zERXXYhm&tzT-5eQm+PdLMA3yd)_u~Vs;$H(!mO@w*3ca*S?%Z6olnuwf3DDPVtw3b z=)wXockcT2kDm8b>So!rn%O{Ikk)0f{Y>U}Q4d!+BM_6W2T-M)Cbs8J23*YJt=b}C z>>JC~Bx-#Ao>+cfUEqNfnv}St%kYMZK5qu$I(q0}q)ebr7=#Z+$;zTc=)Kz5S*13c zB;6&LsMtyZYgDG zqJy4+T}!)hNej{~o;H}9cglgln)7%hPUmfJ@9m`RN7dW%+cf7S-aqcYH>F$+J2&UE zq3hMr$n6$&gjN`;362$J$01ik;?U5THUkac=`v=@;+3GoICR5+j1 z%HwdJ%SsCV24p{wT~YKpx%ZJwE;mr|nNOn~WGQFJ-A917tmQkkV$1tQE85cM7K^Na zBgd>Cce$-u%h*##7=z!wQ@8eBU$4*&lJ4h!w|xxZu(_gd2m*H7?z8^n=KREASrT(1 zqggmwg!&FLaut`fU2u25o{L?x5iuI46WWBYebrP9G8_!g;}Eejr70C;ARO|+{;ak6;IYM+l7T(;hD z`MSnM$l++}g$t5nFm^4rsd2cz(bypjXwIhc0&k8*7>keUBD)Twa8oof3ZbP$D zX19K3@C2E=47@KAcoGrYY@LmPP2RI1(ml72?Eh!wVWhzw#f-< z-c`^}9y?agUCevW=I5WHTWB3QEyXY+;pn0cf2^%YBrqpJwG&5a2NfZ>{6DPi3xZ6M zi}_`~9Z~L*K(?^-cZyPK5R5s)mPT)3AC8WWl*DgudcXx&Baq34@&C=AIZ;__}z3206tQ zz6Jtg@&L1(;x<5Yttm}tB}EO0`r;9F;f4SJW-Y)}(RZoWPldmWC5|f1-7%JP80hD! z{)<>;D5Wq-s5}Y*cuF9qsDRupFj0Ns@lTL*0`fM%bD_xvNTmU}XJFM1+;+^0?+^Yp zm*mS&J-*q4n&N2D6Hgtd{Vq11t28t=jeiaq@wz)y?oY95^orCp^x>rt!sQTOxllqw zF|k6B=_Sb(KMD^(D^ltwekw)@ZN=>Vemg!V_x|8~VX5Um^^luI&UUdMi07)Z`dzHT zRWZfyD>V*GDe$M*KUWH=hJf!{m5jpDnn<~ys^I-_JTj|XMX;Jgjyl+NkNF3&fE9_g@@Q^y)%`yc;i#1=Ui%sv)?VL$yx{hMLMyE}QOR(el! zdAeQ~&YT{fo8qjJhH`navZw*Sc-eeZR@5jKk=E7d&J8vD=!3$nR#w~ymt9E7cYP2_ z?xMYpM9k_}N?EuguN1!mRa%*x46f{7t6!|HsgI@vKN^~2W)q^PC`_g=?7dg>?pqsT z<-gkwg=Mz-?+*8E6`--wq%!ayp9o+g?_H{khr;h-V?~wZZ5fMO_4RR7|00$$uylYp zP#!ra7#T2i=-s#c2y6au-ew=OKOD{pc%e131*7!+!A<4k8s7B)G;4kL%F5)}{afkZ z#Y*5P36D%++-hGP=;Sc8x#Vr2A z;T%}KD~?mja(->V|KSZN?i+lEn69q2?3^v>nT1~a;EX9cGP0HW?yj~rOgd1BLyJxK z7O0W#t=ukGEWL4xo4J@Rsp(qrhZ-!VI87TT9btqvR;|>C@~gge_cV(4h06@^bJT1G zj)0th;1PpCdF(t^Ce%6n6#DJr$mzDamN?VL@?IU8R9tvggmFp)O*cZe4s}h*0VMo#9!#292 zKzA~t4M|2jc%_7ZZbf-ZV+^)%b1~jdjNGX`BU@WD?gNK$rccJ#%ObQ6@uW?t8Fyz9 zJu_UBt)7g9{kol=%$_l4R67PyVHBw7Wlg$&h~jlScXy`jq6upZ&dIsjO!!(!7{$ZVJR8&%j zp{Dmz2eWO8&Pl|$`D0GG4HzR2{{92oX)2G-_mDGN^o6T0(_EH4i*Bf*TWj_jB)P4i zCg)nkXVOhZ1f?3*gC{_a|BRY{vr;EkyCf4F+NnvN5fA+*!*7*(>62A6x;#D)JL2i? zQm31bF6V1k;uV*A6~CkMy~`VYo;US)iDk<3JglcvQ=Fer+>R)6`ga3Kwox29fSwR` z5HsFktNsTA>6n#2H9}_(J`(G0OTodlkK<@_*T}>g=ib(@ehwY{?8N?sDebbD<$lum zuuf@=+Ec2gZaLDxU3=I5s}S3LzqIeeO*v@p-lC+Z4kqimgAG%heMjO^ ziNBEeZvg)n690w7f0aVNYSCZKfd9WV1G;}yJ>K+%EspHEHO+=OFT_3W-t3sUBD{67 zrRr4vAnL|nSKst>BsQ9;j+cT*5 z>XgMZm15KLNfYYakCnzL0f)9JPdEA1sZ$w~jI622$}5YRTaW2WkBbwBGe8qk+#%ii z#Im1&dQw(KXMoyjC_Z^v`pwxjm1A@pRi(_qwdpgCo04eochsu zeUF^`+RCgwael0pbB?faM$86;iJY6RWpHq{(M07tS#k8S>7;9%qz;uWhACbgJi25q zWUS=7P=z|R_QWjsV*ZP(?>()3qoYY1Qk%CLj7J-v zuL=}&Lb+-jj)r;%nD1!o`ibSAD~*`#?th`wZy^2L^6Azg9X&iu@|s&_?{GD8cTK^- z`8TjU9ABnETJ-tp!e{ImDa|kPNY440YZD5Q_b2BiU@tBcO96q<^I$GO* z*m1X6Gy}0Tf#$WGYpwD}GOGONh zP;>u)ncGscWH=KoZ7$`@!W1HAU7jw|x3}jQqnb8rSs5OG#9l^Ui;r(_pD8$H(jE&r zwOp1|q;=s=Y!{9^z(@992L1-;e&5px$YRS>MRdSM$Zd6a#d*HcmteDh0C`SwL>ZKt zErm=?{c11TnD_*x(Y_g)$7^HI$V6ENS6_uc0y}xN+>U8+B@}W(Tyh-yJ*NPnZ z77l-h!`jn!h5CFK4iAi{K`8JgCzg-#*OaCQ#;46bR&U}Hc%3}#CM%xX^^}L%&Ci?8 z4s>&P7MK^;pw2rxiydKzI?DX#8Dh4hconaDy&s$>BHXv*L%SdWkscsBp#4m`t-844y4yDTE*k^VtWNpv1fZ#C#RKNtNTtX?@2r%31;x-xe8(qC|^0J`4(Z(!TM z(AK}u7Jw}O1OflW7XJlz{{?sdMc4lyD{tKKQzopr+1ta!0o1IosK_;MoY2Ufiu^J% zbjz!FDR5!hGnS3RMk%2z_`F_sp!FAX`+~GGb@OSt7%c1&o8C4zTulME>k*n=|Ao!*eSMGwl_lpinmeJgQON;!QC zC=7_Yeu%!m56WlkJ1m_mdOEHt8YrbQ{2gW%6EBYX6K7^Zgs2NB1^q#}u(Ey+w~h&7 z_;i`prbufS4g%lOLWKGgb znxRWZopXAMrR-|P?t+!#S5HVv=;=4pP^7rn#8iA^W$+kO(&UxoJu1!CO$H@v$N!;Z zZM$v3rO1)eF>C%zJW4PaDFMX@=32Fqx+iW+#N)mK%&VQ5@KW=q4&ME}8RMk_!+^Sp) zjhBtkfp|MnC58kCkFu#V!^G`brMe@L?#xF4B~5{$%z;L=M5!NHk#V$tlrQK0eY_o6 z^FXPqXK$=^!zJZ>3woOY5AE@#$iz0dHBzMu$Ih6A8z??#O-bYo{o(a~=bY4e}EH9TT$PSMihzFh0~sk(2a zEPf$Wtl_Grv9X&QZ=yG+_fw0C$mvSqreTOjV$TBAIwI2K2}SXCR@rGKf`JT$WKTgE zWVXEO8{)k*aDUAZ>HvI5*P*xgJ4TaQ{h}-lo@>zQ>;c(|IXOBsNg!P{yY_YnG z>=bUJjgj)wiVCl#sijk*ANE({W_w({Z4yox5JF2EaH2mAvk!w05*jZE@<;2i~Pi=3#JnEG4l{CC2KayY*AE)^m( z=AN?Et35vd6xs&?Rk`�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


(vBm9#ZibsC1KX*6u`zo@(Ze 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

gw5{#w5Rrwm;!pb$@a9q*R%b! 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

{--lA=Hy6h-n6emuR5iKPyhFLHs4G zcSC-g147zYv2@`6z1=OpI6kGOvCl1(%__|j0YrANYk`d;!@vFGP*|Fczwk}pM*j-K zO!h^?SuB(@Q6{*wY)f0IXpHa=H>d^D3ML4P_@$6Pc-kk=JB9=OO5RIdJ+Wz{7reO;`Sw5v1CxR@wVEN6jW$nV7!T_$|jjL z6Jw6=VtwaT=M3;3zBgU72;jJ1z0n>z3U$Py3NWM(j&-)roD~u%&!B7**~qI$YW9j9 zf#NFSZduK5R}u=^h-oOO6YrTj5;_c&gidp#-EuZ`h!}WwP_C=V6a^vxgs4P5MaFam zL+p@39LTV8G{cCHW@>}MilM?n^HAH=J?6o~qb7=pYA&{HCbXbDWkNt@Y$6^bXV7Nq zRw6KTHDA0Y$2B|__^VBJJY{%ZT>FtaCuHF8fP;}`p~`-3PGHPE6&!^4PaWE-G|Cs) z7$%G7Jwu9(h=>KiD9cEDl>{ooYCt7?Bdua9h48T+iRCvMR{6?KB7y~E-t|TV3j(L1 z5y1sEL8+W5s8<=+N^YtoQ54kLj1{+IUx_*twg#cw2KgEcux%~_*|bqYU*_+^ZT|i- z>*D;D08nQWo&P=kjX02>sA_lSbXfyi9m1oIjkrBa#LxmL%uHxQ%4F8v*wHo?n<;&x z&Qbf6bF<|>Kh3SWG|Orhs*Y=J8^!q7qwM~;<%o`Iv<5HP%tC<;FW8z%{>RT?5+bVW zzEX>PfohxuvxbCzN0Sf`IByF9J<7W*#}y~^>4dB#@c|}C{K%}sKHo-+2rkh%IdVwy zWuK9h4f&ZNb5OmYFRiCB&LE28odUgc0>N=z=!juAIT24R!gR|p;Td^Nzbaq4(8Gik zZt4)Rg^BFo8@>Mfl^xQNHnLD$ zcyKpOY?}Ko2=+gw!C@=M_K56&-Iv2bwQgyn@qUs-Q~ZA&QZ>D?*E7%(rk%FBIdC8+ z%r^ZTB-)Yy+|^o~9o9oEqia=?$IlSp>GJ0Y+R2*i92uI9!fvbBdW*{Mq>Md0`gmxL z*}Ps1_&u!Yryc+vH~IPtL;enm$w9W;;0-Q6zx5!qzFzWN2Ym{%!fH)|Xh-v+M{1tJ zPECJiu$!H(=x=%3Te##(*(^No>j`A)xMruz4bBMFfWIEC`K}yUDyEsv-JXghzggi1W4#mmoc^ zkepV|W|a#|1n<$9CL=1!7BRdJKBp03A*y0e6%S*MN9n)^Lf$mC$P%vqMiRr|a2i>N zjw#zByO%>JW1w`U$M%JSbP)sDos=pJ_QZW7=G|$QE&?20g%#AlRV9jj0J@qaLDET? zE}EIBWiJ98A8FYwf=W`w0gyk+rorlDt0M3qs+0CBz<|-W_7fTQXx;DK)dTxhNm!{^ zqNeED_!VBkwet!c!aQjr(RL?V>(AcI%IV-_Fp-(PYNJqYmW`w&Y`?k z=KS}1W4`R)8b0!eGv<+}%@CM)*@;smjpAVe@5)Z)?mIX4UdenUf+@);UnomSD9tG0ai$eQGm?bCv%#BB!V%n8r!``k9G0Q;;SukD2ej5 zT@os4Y;ALq7cjO_wd%aquNUsLXRSs;-6BDOLO@jYqlr;2N{sc29V2 z0s;#1g7-!Ar~UFTlyAcE#1ssITx4Mu4AfjeRc!~1Y(ff=qhkIfhqopJ0VNa%Z&KVt zZQ|1{e>1o}J-{FCpRboc+(4rn0ZL1L&VRm-4)gPoZt8QtzphrPU-31L+vb9yX6%gmx+kGIzr(k6eFU*O)Cx?i*Q;E4+T=@Zm>|cSRn~R#U2^5lL2C4 z{d?&F2>2kbqFmFKExMZl%F`Ts6xfs%a3}F<&h(GF{u!821c~(tno2E*y-4zUoNk&R zhsNIkHNi=PT{;f>wc7p|AUk$4KK}(7fiVNrA_`g!nIb??AXY?oVJAnc*zl`$c*m0eL354>NCr^%Rq+7+M3*RB_A9F0Et0l84ULF=Me33 >^z8l_ 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 Mtf**gZ8G_P0I*0lHUIzs literal 0 HcmV?d00001 From 6be25f8ba4cc43a882a8837e6e493b9111a9ed5f Mon Sep 17 00:00:00 2001 From: Jay Tandel <120440398+jr18t@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:08:05 -0700 Subject: [PATCH 15/18] Add files via upload --- docs/OPTBench_long_version.pdf | Bin 1059516 -> 1059588 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/OPTBench_long_version.pdf b/docs/OPTBench_long_version.pdf index 75de065dcbc087cddabfbd7a6a6725410ecc9437..85a8449da0d1ad70c833f49d19b7f1e84f751eae 100644 GIT binary patch delta 69961 zcmV(@K-Ry!)j)*SK#(#%I5;3LNFZAvGC4IeATu~HAYC9YParimIUp}ZATu^GGB!CN zFHRsaG9WKhATcmCH90aiAU-|{Wo~3|VrrK`+7B6#fKHLuw*xscHIW>WHIb*h;s-|(7Yhvz!kx?gjo?1a!l?FtZ^q9z~QR&0RRB_Xi5rYZe(+Ga%Ev{ z3T19&Z(?c+H8wdQFd%PYvkVPF0e?3+AU-|{b98cLVQmU{oW(oIcHBmicYQ_O27JQ; zfy~5aUs|%PY57@}+oHy5%Q}EnU=>;@po~Q{{q+-DCbpvby}k^2DCCOB$k-zgYz~`X z^FPmm#qW#TXE(3HRByt>S7Br}xA&VY@r^N?IE#IqM4Q|F=A-xa+`lO5-GA}w)9nwq zAf7Jx=zVjwRZ-wQule_N-4|`X>&q`!saJ5{uUBc{HSOoSt8Ex~v={Z?H?1swee>qW z?Yn>ci0{~hM)@krHrp`sGbK=b*K7fh@>Kqn_hnOCV6sgZ`dJhy1ZErR%nw7e*(&WP zQNk;K$R9rsr(9ljdu1{&uYdPNHEsc~iB(KHq`uA)*a$a`dHwUY{Hv*RUjDAndpXtn zn$OsFW&cQk1Jbfs77N(7SF!er)A?$fc*V7xmN%5v`*+W2aq5REn=k%X+Y_XJ%e%oZ z_QSnfJ*SHNAPE2cLG96iiUJ)i?y}7NznX!MhKu-kE3O34 zvuG0reimdQ!wv_Ig&k76-SfMyM>ZQzo5E>h;z?KwG#tQxxQT!fvUC%{9xBnB+Y?ep z-sg9DN5>7l2RJM6W`EV>`;L2nRfKgzudH{}%Db{YRFBxHyt?T6@+$P|1Gn?GFMkiT z-j#V}m-R(el?UMUf_WM+IDshwQjZelYhYG_>GvQCu9N{u08b%o!d%LDJ>|P&Sr^<} z6?t2i^lE6~x;H<{8kl-6;YMPws9?U(KW_tbNy_l!si7+(Xdq3n-*+&y5F`_70h+8m}K&aS!tu`H@RLk;tfk9Tdk=aJt76@cXXZ-NdQ zA$R{V6m1D_5|~o6fGG-y`3R=|nD@9U@=oQS{6Lphk*MT5F_4im4r?~9td`27TR z*D-(a086pNd;juPhu7?L_wBJ@0!~*1oFD-wOu&g(H}KxF8M^Ax-EX{rQl-90QigJO z%&V%X52YpUzTw}7wNLSly|yR_E!}C4QKASX$rQ=T6MwCD%$-J5UR8dUr@JcOeV$Hi z5EDgr{S-<;`Jy01Sdr|u`$Dd5U(`qiF;G7+V?;>Y^&NLH%45D&|KMM9cX!TN%mE&$ zEAhIblBMOB=}7F6wuavw;TNbmugV^1l&~PshD+WFVjuWNaGT?8n+OE`309N9HO6a) z8c|(!pTd(vYz<|0w;k=1j)OF0Y&z(sKw+2KqA) zj2?@jEkU^LI+hc{StcEYBJ}Q2+L_%@$rzCc^n+{=xx)PnH%gnj0aP8!9rs&OYP)Yo zDW)A7k=++)G^z1pBk~)BtCKSOVJDQTN6yr1GJn*->s2Lm*19G2a4Kl8L1yimZL=`5 zE)bzfKqaLjx|=h-tZDn9CVBvJ(JJ-20qs0|LLSE7d$;L%3ly|}4CR-+A};5?6a)nh>;^_C_MWS}?)Z^#iw{D&3GN`z*j=O0eQDL^fpmp-}H}6x!vd? zSgD;Y;8S1@8IjtkK$-S~C9G&jw4*OF=iN-idq4^ZuseuU%A9TlAacN3lv(ie^SLUz zZQqRdy#y^x{S-P0G@fp`>jVO~1Y^9r9%X*Wm$S=QX-NBtVHlefI|TNr|x=cMlCTVdOGliPK3(k z-Nc;nmjWdQs6ah{DdT5}2;pC^61py(rJk4sxDQ#nD%2B8_an^7Ru1aa7XFC0h8v;k z!O7*qKgBVzAg1mqP9^sg$M1%++JA2^*|CUGoq`h;I@x>>eZf{|>W#aC5Bk}SBSK&# z@<@Cn6P>{0>>I;_vlUHx!B(^sxKL`~y!$~U0@|9Aa1k-aZJF0Kz#N19aQQB9=~wT9W`MTuo=__~Hhz$a7|&7KYA{)*n9(6?c7N>8`Db8J zY-tf^+<{3|kYd4cCQN*MIqW{ae8F>aJ3d;zO(*vDf@L)PhFauzUR#%89p^wgD(?9C z{c9@@b728E5b3whG7R4}&Jh`eW(E!B$nB-^3bO1} z^ex+8&=8@cy$amT=0J8FwNcIS6U%nMYg@7h536=4`^mV17Gc$)RV^6uDN5Q?+Z)*s~Ye{F~nZ$->c>)eP!6@mYPUe6i%ed!u&OhD2M=+%L?SIWi3&?`Z*GtAm zeRV9WVxnM4r8M}sci!@zd&|zLM!ZJ5gL9NY@&kGvzg=`QBFoW1|5A3tQ?8%NQeT_U z@-iR<)}*0Vxm$#W7%M8BI?iCyI=X^6M6mF?!Zq~GgeGj#mHT3Q_qfGha&#^kHyC?R zY2xct(0F?kdwpM=8h^3et7>2iN7&{_tjo{rQs8wuu5!|TZriwV@qAKe=RAqFB=(IG z!EKG9g@)iJ95E-|j6?=9+^Kz%7cfCs1fEF9qb_F}yyjj<)qf0N#+DP7%@zVs#gT7f zk;@|SY%FNT5>YreSQMZXjb*V~*xU%c6IfrRgkW-UN+<+FcYnK+ofZ+0X;j9<$wo!S z2k(-BLSwCz-6f(&0jqh8Yvg>N=e&dquj!sk3)`2HnWW+7&dPgP%f0u_z=8?hCerzv zOPWI&AU7jY_}KU7?wgyNNAkD&!Iv#>j(`8{`RDf^j^F=^vFQgytuC$rKk1KwjM1TH96C8+8l>9`ZFAT^qGk&Io zO5Wt3t^YLGFqU;wD8$egt+gy<45a)h@q1@G%m@OvDEmr~aZj+GxS#1!Hf_tpvG44@ zHCk38HfGW4?{A;|@oYitVPgCw+U!oxK7I-|dl*8#1^apPKod{E4nW2RPhV}`J^P2v zKxG>={(p74CQaHFgimJuyq}BqRCb;7LVID;6Jw2>j{}G@iR<#^hTf4R)ZU`zTo&V{ zFc(*|72y5kZ7%}t-lDtgMl%m6X+b~|ap`QpmG-hW&?4d(Mo2w2;t0&tIpU#PiHs+{ zpb?i(dj}BW6OW67w;)Hjac^l38=^}SC(Oi%vVXRync%=oykmpWQnAAFy>#*U3?LQ+ zWqCJP7%s;;!YBX&myt@;)dYBW z78#n$esW2QPEzjHdq~gyP|53dWj~8_EzK=VMg}&7?X0GwP#f__C!vHh0!>y2HNOK_ zJb&>X9Y?u@C$Sc1j=+SdExRoUjZ}dpG#sYb*wp2=rhL;|LxTdAmNkyWQ+K4n&5Gqn z`2bYZa(EaFC^7DI21=UF1y3$UfsJERH%{8@eeSf`C^0kx8$5xb-8i|F{Yu!+>-br? z=2Z6mxTC=|Z5)vfHpH;7$0IlBu;gbvlz*LzD(P&>ZHwb7@Xs?jE$~g4WE+i>P0wv<_nlgE z9B7zfr?tkPr z?ZF>4}MJO3CY6yr@Yln zbqN?vCJkq={#|j5eW`X>g`y8wHj#+nWo#B>4RqDQ-6jpH8I$ zj1+Y@x$|z5M`xm{r|=xWTjC1hL)8 znCVW|G~G8P-r>y${`2McVxoFXSkJAY2?K&zM+xv~8r>^Sc_|r5##CSlB69>`76f6C zAVf5UHvF_O5osErBm$IN^P-;$aoRwk{qrhOC`|2;kd28v>3RR|xjco6mw%u0dIgR$=2Gw?LR4n~RnbiS;d#Z&7*U&8OAgm& zVob6*n_+ECP^sl4Hno*HUrGFc*+m)6cA{z*bB+(jCj8ZsCwjhItq%^lzDe!Ug$on`K zo*+E~fOZC-S{)+-vke5ueA@MjDCne0k7N@Zkw1%l6jkN35$uxu$z7Jpl*^;WT_lAW(@ z6@$)O%m~eTCk(ADG4*?(qWNZN=);DK-7erg%>bzj_&@n9IbKU_(w3RD(x&Q^M5K9b-UXfPeCs!DCioV9-RFnos()ss(aqGqJC-cw+5Sz#idfN@;;x@g?7p_mp~I ztPeKaKL^i*#s}MBzGbw0F=n=ta53wXB*sfyDpPe5ty)y7*f-bKE;G&nB)YZ5f)}KQ z(UGsM8-C8g&c;Lnn`cU4u#+FCC?dz4i**g5Gv^<4Reu~sDYYnEK@5R$Nv1b#glWO5 zp+iAit{P@wx^xVc>m{Jd_&O1Nz@=4OIe@VusechM!k+pl9`1*F6#B}ud`(=5xgrrr zIdA65T(HZPxh$m2McV{4vu~`N6HkMRYa~22SWjnCriFR`sr`p;3ulS&eE#a%6uc_L zY6ImPTYvubzP=}1!#c1uW4RtzI?}xhqJ}Rk4CSl}-cT6_LNM%CKnD@U?6B?Pj@Y0&rXU*g zs?y!&`_c+q?2tsN!H5U8XZdef&--Au@cg8P(0_5}N47xAQaOgusf=n%rBz|FtoG_C zQlEKmYaVVe+=Oe6AX~2ak(Z`RU4~s^Ej$HMl=`u)(UPh?jdfF(DnGRexM~b0VC5%2 zQ9T9)gd}=KS(w!(>=Ix%YjJ$a&s;Z{w@<=n5kuCU1|u?rPC4iX)cX~|NZ%kyUW#cAzYI<0Zb#zZ95B2?8DRsw+i zB!a@@=i_51iCD9^%{ARyz*OWXHWdF_q*uOYtccW_)}EFVo5@vHvh-?)s<39q+6F?C z5*<9rF?Os)Y(=iK44;G(beR>w5+J^}L4QjfV0AiaNG`^~4k```EE&zKplQGvA6%e~ zT||uVi?DWJ>(R|aTV6;;5L+^``JRG2R&Oj7oDQ^~+PW<9b`{s>O49K&xDjCe@W5C& z;R=;)2GiE`j2#lD?`^K1>1u2 zc@|4k&@k7s&9ShGCFIh1oK-j61|RQ{dmi#f`(78~T2V88187U&mNjqAXtBN(RgNvb zq+v6MHT1DA|KKcld{e%y!;JY7B~|$r0DvBWAKB$ zRCMAbLa^EgmD%)LxNECNL^GB$=~7DG)#c(Ras5=yV47dP5SD6Pf#GSwr;qkTZP-{w zY70|R4)DWUq<@=?;nXa?Nx^B>rbuiJtX_WZg3D(_HrBu{P2~{3&6C^xJJ+|SV~(J; zU;fz--ez^q*+}bD&a$L+tY339iGJxGCd@Z`5?lB|UKrZXZ7FPF7J(q_ky^tk^02$C z`4_mOY=zaa+uVrgnNJYCoi7xyEFVZ%52{LbIPfDtN-i%c-%_S7NYQ42k zn13_Ovup{F`@Aue*!cXbo7|%JVv7Fz+h_j=1Z)y^vpgl}6&;#r#oa_Auktu&f96u(4qsoHDGsdi6} z-!}uWBMnTBoTOo9l%%5QC8_gSlNCN&vdZV0YUVS(F+R76t)nMbjz{vY$#YIk zFwP~lR?$o9Qh(5E>fX>>8ilx;MkUTu$(ZyE?sCl-bPTYJ=aEV=NnSDrVB1T91PUVpj<1#piB;3K-mp!fyLsG*#(rF;&UjYw2sdO zl)K_{0p;HCIo2x!Ko?LRluCM%OtB!kWXgpP1oB`|Fn@r;T?GTE%~g|#0Srk*I>9xG zQZ982C>K;JM!CR>80At>u9V9_xl%3zW$MPEBXPptREA z7LM04D3^_-nUX^LT4+45tEF)U-TL-bqD1JTREs}!?Zgn_e?M-cP;@H>&OIy@-TuydBA5$!ZNhw ztzbY8gtBZ((dfeTK}Z6R;H#R;2{4^N(?^Yh!^vrq5;{B-sHkMug7y?A>#Tz_1BOlMCo{`u?O#mnbErZ+dRrvN}b zIlWA0zy9`nslpDsUKUcLJC_T9zY!Skb^KOdgII=nq_s;;SL zmmd#__-6$k)v(>xbiu}L*k9{OAVP!n){|nfhOKn{1kY%2r}b3fT}{@z^YdGI7)vJN z#edc1yH^*7DeKc`>Fk$_&xfx>^gANz6tN83;MZS?cnaKXQ+P%UTmgptVqmk)uxDdn z1=yo(h;59MF>nFcg4hgfdyHl5+HF)?yhC-5k-kCu0J=V=yCb^wjiD)st{n;q(>9e>6_o%UMJB7=rC!h+p#%gXn&l*8v|Vs?S1PSrVVxX7BxIh@@y)8ty znGB$7ly9j6!6d3~q}tdxQNEGWZsG7MIQmN1ID*3uEr^aK8Ao&nx<%EO&kX@3f0pDQ zx^J2hKa>N1i>&u7@Ib1*hYp!Mkl62`Pbc76f7NRwwmH4I?!UMDjk@Wq7P`-3kg@K>awQW_oI%xW zmep9E9IR3a-wAb{SYT6R-|SgPGsJY^x5%{&XMzpPVpGSRKZVv-=0RnU;hqj?QAnFT+e-}rSeEP`Tet<1g_nfim2b(|CEZgnO{P_}8!75wH%9(Np#A;Hn3N89W9X0`O1_O+hx`m|9? zEWxuLndwjTr8djD)XXfY!UqTa5@WW?x;OuKTJ_nKD#1Uaj42RZjRw8;FQNf=zcDJ1Keo)8_wswv6(|({mad}& ze5~t=8u06h=Yo_w&kdJ~x-4~zSnm+kSsl3zCH zkb0u0&FH5~_DO%(Q3uKjIK0#7FYx}#b+yl^XY>QSr(KN>Ip@b(w|G1fN}g>-Pprjc zfu62&x8T{Ao~5sdy-tGu{j~faoXCu94Sw0Uuk*Y=!B|o+V2zhNh#Shw4eUFHV1#DI zANoJ`8+%^=)V!{n_+869Qm|R)0U+xRjuj|60Q=+dUDu5xZyzgh43*htDCJzk0?K=( zzV4~$@GSChAzpya^NT$Uoqcqxhux={z9dw+LtVlA_oT~Azb*NwY6S>*K*l1 z0e<~GJ(g^(EiY@tB>{wIq|waNPxo~9XvPP_1oOc%E%D=+_xSNlN)$t2($H^YGHT|d zV9KH%B~#QiDyHc*JTrpoh8aV3%S?Lim{SqIo;hdm8<-cke_~`oTNZ?1!Q&E=NueYP z3I&W1gl1A{G!q5|Z&0vIYO7IjCLamt5Ko>OlHJ;jlU}tn< z&m{V^V+aMgjGp0BbQsCPeaNSHY1zk>aR#Nz^53AZ~DkAU#UM&?D;I(j#2nQvu*2 zI1aE6;0np$qN094XtbmzuTUU6^qNISghRII9JR45dJ+d#6+M|BI*rMI(N~P1EqGX+ z5Yd14fBpAtaK?@n`LHU==|8!=#|AIi;8FRiWDg(KkN?Xopa}MY4PO8DhFQ&NT0jXr zLc7!DWWwI2)|dI^r4R;PJ0*nIxC}0o9ouzcEmNZ)k^;aNlMwc5DzKuw) zf9mUg+s{Tf-`h6+Hga=2a#N4cAZQ!0-k?p>Jzq_|gDtI|!mib~YgyZx5m{TI-RLZp z_vpmlE?Lv7uSZk64rM)(+c>oC5$oah7(lHcYj4tJbgiI{4mTp`9Usu@wLPuLyNE6I zld`gn2x}$UjS`a*>UYySb|bo~r@n38e`%W+DaLQwbSl50Y*;JpPUfh0+`^W`jjt73 z%DJq|qZXQNzAsnLz1TRXW>U2s*^V^Z<``NNjGkSzS=lj+J@d=lVr^T#r%_j1g$cmg zC*2IYo!+^n#`MhZQ-RrMbmpefk$-9^PNKIcrID#kYP*e~%lO(xRjZ&;n{OLmf33np zjNZ4UZjI4?e^xy3m5A>Jo(6A`uzy1_+0G)47`n-PB7w{}Nu zv(L>n4Cn(G&@Bc!qJ`UbHV5deNp4lQ!kXZJTfk{~1#Tc4yf*=klha_F<7tH zJOIz1N}&-PR=$C4BbRBJbuetuI4r8153lm664F=YAK84gxD%%$vAP2e3KjwDFRggQ zQW|S>uCT}^&{)fV4Y;d(GRfzQDlZ75y3R(E;-UvcEwLQMTHGqhBh;-G@+BovkKAJE z{S^@3Wz+ZN2cV0id^pMGe_2(0$ooK4mTRpx5VZt*rVqq%wp=W(Cw)L^OjcoApdzPl z5j{Z7viW-@l!BY=1I(z^L}-A)22C%0US`9poEM+-`;+U-tn7o$8t#&D0UMw>1KU%5 zu$`Seeg5EGxtve4$zm}3Fd1D8ep_bKAK$z>`BBL}Se@te#j3&Te?5%O_QCr3s$4?9 zW|7Z76w`4ZY(a4CTQdS7!wcPOMu0Sc)5G!_c33RRX&=950{7N3V;xuYxe|Jh(lJ93 zE*u)$+W72jUVO-gpL&2Z5|P0KW{gFo@Tf=bC9onGEBm+b$)L-6!<4j$ZLmaWS39PZ z;`AZ;FLNyxu|j*@f8esp!RkyOT;I;M7=&2snG#re1qJ0I;tC06oU&bx{>#1lV5g#9}6p`yhOhHViOrh3UOc_HiDl6JX}t2edCh_SjBX}`nNH6_!2NK@0aDdL)%q4!p!6ARC? zs>i+Hf22d|%9yd!~W^e5MFU`-e8ulolW zfZS22m-PFEw$09w^onb>Z7ZkqJR@D75od_+j;^!evzP1_1X8jhiA<48_WRMvvY3pR(vPD4fBhc&&oY}=pBX4Sg^s`(8Pazk z@yY4wNw&yGY{mK88~3EBZzk}^OmJlpuxbn07(gxF_U*wiW3*rkw>D@V(vZo32FLX0 z^k2ubs$ASZDIvz-yg;6CdX>$wU|8ANS-u#~3pAOh9nhqKr&-;|i;XGhW)h|RaXn>leYY^kq9Jx{7^QVfr$<4KOzgP*dGNsDk6iY7{xU;je)H`rTdGk9GicFKJt zk)X7dNR)AQh~zp&T3h*EX%yz^S4gwZe?Cs1oW1;n)yegf>1CM$%QFhQWE4k@QQV_A zJ1!R0{1ZDm9+emAgUxa_o8;F-gGf>A>{mMfAUdXGE$Z5?FebGj>}qS?r9&L6pmx(q z`?cqea6EL;fs?m8nmYb4UJ*sJrKLBA{QsNiEp+Pb{F~~{c(;=}Ul!x#9LaMwf9u!` zJ?v|)RFNB(k|yQo7?tG?9$zDKCQp1=N?&CclMO7}0~T^Oas-sf8(2XUoW6TUmA-rT z0VVJDsb|lpZ;j~g=u@}nmf|9^De}OGVVsU#{e4r*!MUcEO?*4ohR#`uriO^(n+)Mx z)49CHy`x4)v&^~%ENd4`pO*aEe|u>4lj8hLzV*Bx(!TWK_8KhND;U}lBTer zr$cwWW|-*#EFJrz&oka~CFo?N02RoA0v2zsC$K&a$tcT(0aGwQO-C)Y5#$odoivVn zcZcsr{{yeZe7=_vngCJ5o1`;}FH|2cet!!6sChn?!uX z@2lfT(&i(nukl2@F#$b!3OBynMRDN#av7>Opp_FZ{q5QhrD)`r?M`{lM|@8Q!^rtq zl_0X$yW)YjrbWV1jQIUn_0@9)>+zFdT2(`a1EbedMbd-ep4cm3Y1{NN%i`n1!1FnWMM^o3H=Db$ zE@cy*NA`ei%ThWC{GM8^gw0aGapq=0!VG^8r?wXXF4-c|g(TVV+@7gzBeVICi#Ief zh39Cym%7b`&=2`g^+Q$k?oxg+uoJ6I5P>-)DYNr*s_4@JeEQt-=#n!N9Y5y#JsrC5 zS$RI3q2x0J&N08pe$pP-;vbuOAY^m63cFPNBtztFm-=D zl`;EyF;pK#i-C~_TdsHykPoCI7z|zB^p~6?-oUgLJndZlx0EIOvagN}k6Fqvm|l3! zyBFpRJjq{h79_40Gh>6C!T!;+YvRg-tI^-{)`mq zrKC;xJ+~m3d@xo7o1d?167^$OVeo%p`!p7gLJb3O(es&35r*XROohnaRVBGDJXw(e zp1?k)<-NRxlnVotrP3>V9oKMTtm-|ie_RuKIuZ|jMvv$OgFwvOAa7XQa7Pt_&m`i<@N4TbHKp-BZhy#k9mCr;~Y+BRwzp1pc9VqI!riI@RYP93Q|s^Jpe(B z5#U14exlq!dprY{&^hE)#|bb(*O6$$bJfuEpoCNsqFolUQa;Qx5hn%-Z4E?TS#->+ zrXP4=JDgbmY@x;$y`|`4&xM%DOinuW!%XW`+!##?@=nKdMcWL7#_E6C7#5K8q7ZgG zJ~7Zl5B$Qh7;KD_Z$XxO!`o7TAwZ~9V)-I--TEnh0S(U=wZfw|TgsAFAcv`W%ogsO zy*?c(rs`MxY$3)l4FS)kZYVB|4j85;7$$%ot~_|n$<<+!g_F!p0O2QZRXe*jy{wHRqqc)P{6mf{F8(%om;!8gQngJH8=5 zi(Q}KgqgFym$Jh++4w4UBPEgh)ks5S62@Dyn1bMi(prLQpl=VuY&jSuVlY6_vlzLw z6WEG&5{R9^qp=fs$s}!UmC-_+UgSoR=z3p1kH;gYa}&YAg35p9gpnI#`)a86ZbS8< z9rYWAQ$84I+?X%)?YT6ZEs&(jLO04JWNS32IKveJzb_Rhm%3^+*oL4{?PXfFkWg!q zA_H_q?|aTQIIU#wNP+p&#e~B`Kt;URD`+ zI)1iMv2qiYXsC`KzTW010p%^voVoI@4p#%#dBTn|RGfd^q;MqjYkaWp{JGXUJErZc zej*w>y(84fgPK=T4%JWMiGi;%wU0)R1F+7434+r7najcBW$eiMpl({l#<1)&*cd+4 zj~9MXM`;+DscRlU3|xt=3ab26Lt`m>V(>VSPgk`)KR#di_hR}N)m|JrW{-=(kudTH zlgeTps$+k$s82%)ULfKHQuDDQlWs7?JTB`>46Djd-87W2Kd;Say7mNoN2ZVwDwrN6 z?5Unb$A=2(#@Qbi_;qptp1-S?+tO31#7$F41fNkD*qbg*u`(Fg1UW(Z&fBqgdHd#3 zXD*N&AP1JXFB#3pwuC_Sj)R=)w!44Tc4;V+pkfgo zjw9#0FTZ5sKi_^&MHCFB`+-BU92|hHsOI1N{9kmYROA zqh_BY0DI1&Xx>5-I1CjxJ0!3SFsx)!{wHds3>gO+YQdh)rc{CD#Ax2keXhH9V7JzmNI$>?fevEV{Yb39O{#))uxfwX zQDj3}+(otxDc>!>H9(yG-p@lo;tVf;eBBin$teIcxH3#0|x>?2~Qrq+(t) z18MM*6;=46icp7oQpK7<*sZl?CP;sxWhO|Z8iScV7yn%^D~)@@8njhla77)knAMR) zHdF=SuQ6#i)^6(4%tDSmKXZ#?O+Fc8%ShytaTSztyQO^IagD(s2&hsUWs0?Q$cu92 zU>Ub@bj(PW$FRF@R+p~52(E|VGhVQyot_t9XPPiobP4a6B*>A=h{NT@h|GVN9S+Ua ztjk7H&3oO?f1N_oWWxNcQ#7G2-EYxIo{C5lv%RT{ipcM9A0h`q^rwjHj$O=}ZiK~B z6JpbpaXV0K&|Au?oR?7ZqZl5UD3wXsH9}w^!@3hxf7CO>h9Q)NQe|M5(6qKJG-(*L z`){U!qMK=<#736usM}sZZJ>X+D0wWo7Dhd{yEsNgQY;|y7?>a-E+U|`_zq#X~xyFgP%?Z(hU z=Lg+F+V3k}{K6v}>leL713NJZl)H2bLvo}~Totn}v>!)HwyaK@Hkp4~3Xs2Fhf~{p z^^dLeHHPxonKIliP^9g!lS?&vyy`~0VsoYVdMfqJ**SkH@A(dT^%6wQI&PmSWWpGN zs>xf$P)o0nTd9%@!dNauGnaSc02kGgrJLG&!( z3qYmYieCS%g8&4%gOFE2*6Xm-n&?Vs)(bGq+FdvO#}np`z~XVBhmi)4Z<)lXYVp#R4$HhzFA=0I+-rwi&8@P+-Q zFid9U7+p1D|MP$LIy>+cXCj;jC{bZFK_UR2*akdI)i-gt+T3aS{-Vac%a;#PI87IP zamHFER!&Wkb+8ySnKp|cB zyP@6jh^fc%Km!jn@x8#}!9svPfw*#C90s()KnVRL^XT;P$ zqB!DB84YTN!0%^2#m@wZMQDh_MTsO0b(#)@plE#E9_bh>klMOx%Hl}v_8vtLPI}*R z&mfg}hf;~xiBu|`uiw5MNu--s!Mr-BdF$d4KRI^c-0A`$RG6eWHbN0+Bc>JGZDscO zKV%ww{|wWjFwfMKdYONOan4+O!;F%#b}ON~+p6fU9EGN+R&I5jg+O|IRUhhZ}W(bJJ zGk5J>e<(i9O+6!wajrupBrW%Cdps1iGYWC8$bw*FQx{!V{SkjDwK0#cjz#mKYId_s zj58S3iCVj>`p=QGuG$^iYKeJK3e0u&5u1TwIA%m4ea+k+oGwg zb#NZuchzB@#vFf1{Mx)kQ^1>5T^y_a@&A>s;<#H7M0*B)I@&?E)n?eqvF3?W%bX+wi{I z6m@x=-;ESEmzxUTecvC;h0~nk#5Wf*T06lkg9BmLvYyc)%qTcd z7LUJFt5|s<|3Y!psRGc)sPfyUD-VQo({xG}^q?Ryz~P?W$mK-#r&F8TX7lEAyV3%s~IRG^B-6~|% z0DloKOvYEj07pYOQ3H%Xg%RcJhpIbyG8;%?92I|Q>4%RZ={YFkoQcdGg_ zs7tGlYU)M}DvaZGD2^ZKlt6dCFM5k;06ULqlu@W6c3R2?Jr<+UB*K8+%v{%W;4i7a zxQCtWg1!x?W#2yBgD&q#c}nta;JPn+BM|MbY|Jq2sk4wY(i2*u9PBmARZE^BV8ef~ z4@iFiig2A`!Li;QpMh-&R=aU-)5Lac5jeywpDa54BdJB>O65#;L?CT&ZzmX<=~a0K zK1WRSqTkbW{n0{!BnF!R3_VtD_a)sU;T01Ox4&442ZtLD>By0S#}ij;By03WUELlH z#L(+U8qypDxNfWCU?<73Fq^L?3&`L=OV)q*C#zPKaRE)knBrS%8z=mBlaUWD5|PD7SV) z3Q+!%?1n_B7J(c6*!3kV+LNQ`H88r z42`l-3udTQC489BGpK7+;~yP-agJRB;`2hzhk|+k?WZ37wp$z8u;Gj$_+fkit0Pdj zW*BsCwIo<~5M)}!)0`7%%>iGReaB-fJ$WHp8{^OD1wj;kWWz7w3^HJkcZ7dtb}JHO z(9GZfJ;-Yy*|7Q}pDZZ>E1vPb_&`eQDPn;hgXrj-pO}&6y^hQ;v?+qAQN#=CLDdm# zOLR;d18uhS!VuE45d|-1D09FUB2-FDF!wLtTz3So1CgZw1rv=nOk~O0gW=TC?@@N~ zwXW=qV4Ci#p=-gPmGxbK7QKI{oO#4=J{FG`iCACKU3)sx>m>7mvl~->Y5)x>1Do5z zi&I*((zn*IdMMsv7`C-V;~{8Imf=zDOD#dXJ9=WJ-1lbecuPuG${da*V;poqisMyJ zu~{WYVOP8*;ZhQ|A1TBxCu4ZyxnGjPvUnY0H2j*85p4LOv0z3F426H-dg+*v4+8Qo zB+GcSFT0YgsvjMWQOCoGgEMNB{=uRzRAXCb&Tnguck`zlqL5?RU*KH?5Fuxbb6*kH zF+$j(MobYFZ0Zxw1-CYMi0z`@m9UR=Guklzc3brPbjiz`QL-XW!dNkAaZKS*K6%5o zJ-EbYB6B$bmA&U``4WE(kDS6F4Q;kBWttM8DFIg{1GAo{HuR4JvtCwfLA>tvM)&g; z6uePJIBZJ5!06gS3|8UFL1_|wH5LT9K6A_$WK5(wOhjgL0SneL*3Vf>KbG0;t9yIQ zvo&{qtol8**z{>HDPV5D=a{I`H`o{hLQVb+esJjq>YRj%>B4_t6A~L88RbyYbzwbq zJvpKdN!Yv!A}H$FSGzrE^RaiO&wN`=A(g}_p?M82z=KRZ{VtGM;H8DT5EmD*fegF= za+D5oY}!_iJL(t(+ud5=LDAVSy58@1hZ1J9htg6zWu_L!CuSdPdSckcfa{jT)PxU$ z0AxU$zdP$}(=*~!?t&A4@dC;4z>tjB-OfDSxln41f=rV2?Uc8y#m4=$V#{^ z=CK$)0>Uy!m{cBNOQZ7+nPJVv@afbU{l*7WNr_1ywbd*Z z?nM5|CidA;1wOog${CBbr~dwgyvx;kN3jbeEtfnUba%ypTU7(^hSat=1KynS9G(_V zrQ!f3g&ZCziie*R{D@P>V=|L4*K(Dh53iI}gfj9WO6)-tcqZKOH&@;!(;n}1?0L!| zb-aG^8>{rrmo*$z{Cmj9G;FogSn$ zB_nx^J@YmvcIc%G#yi7KI9lR0hStbG9w-4Nd>BAC>SAZ1&$)=_h57gHR8Ihq&*U?! z;fT~=?P9ib{ju8ZY%0{F7@)zvWYd2r;jIm|@BRD>tb@v(?vrLYAOXPL+((R%N|N<+W?Lkii#`f0pZdmwG^i^RFYNZ zeO+yTtQ}O78YMpc3S$?hB1{2Ly?~7!@>3oocor?OoM$}Aq*?~iG**G>M6G|dMH^2g zWkepzRF21_O;f%;cS_DhJ=~HL5vqiJ;e~9q1aWCPE94{+;G@}{gHGBxcHTx}BGwiG zk>*BJ2he?YMaq&7gy%&>HTK>bA3QlbZ452AZdG{LBiQn}Xp|QDgPQ(g}qtdZ2@# zV`y(wKry5r@eyiI(=fi({77J<=TCf;ndt0s9UhWBoNxewz_UD?m7V4s1kf^{B+LNT;{SJnm9LsfrM zlr^Q8J6_TKIrX-RH8uIemRf(dRdeNew!SyaX7i!52`Bs0YUOMw+k4iuD5*tR`2hVUY2A})4NiJoHz7~dS006syeZMokc zO2qb~WQAgj{_7o9N`pfY06jJ`@TGmt=M=c~u>^kQSYm^3eK$84%(n`>e2*Op?uVgN z2*+#Xz4b>FiMcs{$Eg1G0?`0}+h%536e=y^Fa~fv<-D+I9Fq9dI3Rc(Ikx>$f(R6m zJK%VS=Y?8d@NoXwnUlbYM$vH^g4be!Nx_KG>HrWv&>-#<&*_1_59lMbo zk0>7w)}^-(SizW&Nk4R#&WcPCzt%}8ZGjaI&lDK%{NR%*CuK%xNem2s{bY+U8b%C$ z+{}(PmUA{g24X*@Z?uL}n~aJ4`IjFTq{1x@ygo4Clkc9?Y>pi&4wXtR!lek^wJAjU z<(q4174EYt$gk7Yc^pPMACJw2hBbS;lxnDpCwwz4b*NHnI^nZKF9$pmJ*l?C9#{c2 z*tLPyQd|xmc{VPI`3PWt{}=q_Ge-cOycA8!P(hJQSA;crYzaW;x}a5NqirU+je3{T zbJ?0>+kscEMGq**WCQF*5b?JT9*vzHx#W;KsD^16&=D3%Q%X-Bq;as>{jzy;6WpYb ziWtWVZ0Qudpb z#0Im7ZiXb5dHFc=N_V;qrtyJEDe;VPisBGl_7R~sAKN#7#bbFyTk#woj`J{5`S|-6 z;bA4CP$p~$Zm?|o?b{a_Bx{eNEX?5HXq-KqG!x%KeiY7wI9TU__C6Rh^B&{S$L5mm z=)}Fi$SSO<6wZ6-E5|dlnr9%rj^Ko;WHic?eAD30Ntup5cmc=!DO1GLVl)B;xB;>u z(*T=O)kS81ZF0$`YDvDOpSba|saQuSY}IUQ%(TcoctH1Lha`(U_89d+O}6gR>?3xd z5~}&jyHn?)?r=NNFJkzK6d0PRS(Kx+&iI!II(J6flFL>RqiUFF>O0?tY9z(Pc%kL0 z8A7_}pkN%0<1}o1c;cWx-P_uns#(-<(ogb$v=Ui=)-RTk^nO9HFAEdhhfWhG$cJYg zbuXEr=-dqPKxDz7!MQIU$V*F|^La7z6S?GaT~h4E{_4Zkol{t*JsA|>6)U;l0HOQQ zfJ8j0+;k4kW|WRe8K2dKGvihh$4Qu^Vm!o)6rA+4ORV6&{^gt3$Im&kXpiG`Jl5Um z*zXO0%S>t75M70ijB*d@8fLnX+4}W`O4ot;rHS2Sc&9on=X9i>ZvxRgfXt682Li7E zCFY~(C5*;D?TKB?E?$54(?x*Q#B?{Rw=+NAvjqze1vnMAbvX-lq@Qzg?&DeL)K(#F zHo%~xbK&NG-r+D-G>ygm=KxBIBowxC#>TRL*v}dN=8$cb2_mKp$;)7Oq;!~3amGju zpz;}!2Sc1s=La7UX0EAeJ)5KGYeKN)gAKJQ|BHR)P_Yd9KZ$}sEx z6m)S9PS#bT-+Sk?<#*9k(nYQT`tVd!;AF?4BBq>jc~r!n8KgB=CfV3ZO<4WZRRbq~ z!KK@D?rTn=riA$kDvq;&t2cz_yW)=10p}?T^8$u;Q+9hbhnU+xhg8Vn^o{dcC}V-Ghze&jcfcpLU|(3`lbFf(Wz`7^6W^C8-=w^5dK9!b=Z)RuI?{?dP5bTaYU6M@Fgk6$W(}Sd&t68ZM-0 zj`R%FO>=U;7)@;nE8o0^j-anT%6vi+Uu%V=Bjk{r2mBMG!{< z12%Dl`I-eK;wS=mm&;^4i2W%`N^%3o@{YH`rQ{gUW#f#4IVD~U37(^Pc;%pTJLD&| zy4D060r!20Qp7o|nTWFE0!GGTH6F$4-!vV$$Z;C4|9dWu{d=Gj;67~SZ18#*FY_YT zG7l3FtN`Ry#}v92bA#h5^~!sH>(ALqfP`p%A|b*oNkK1!UBDA(lF8a{Dv-3qp)aTftnG2hlV)1g3smn zi*r#(oG7F(5e0W>&vLpdvL$y78m>9k6z4gR$wO-H_D$D>C&WYCl z3E{JfXP$8Io%9m|XP&-)WIvbHQjU;&B8wqPqOwIKr7`z_JuXQ=NA>$>GVPTBOk?*7 z6w<*32IwB)vr^I8`+o;RMFl=E(IMy?$^)>MGivl(U+gH3!d`PKk2@K}h)BWq7?jA*}{VH1h`N`)uPd8c9n&Bl2}|`6vE;n_@`D0tTch2JPS>%RyRlJ{ri&U z({HP0zuu@c3OZUhmX=&ljc9*?CEHWm@l)Rp?Y5_;?aoEjbS)SB7{w7z?c?W08E-~P zrlYkEb(W3ib8{}sZ%(_i{`TBA*f({sxFnt1FjD!rkIh4)%62DN8k$@?BD_6UUHRFz zt4_@$BPylCXwn{5szPq3vfOL;YGd*=xH(ivk~{+@q7nG{?yjy%`jCGIxT{#`5r6Z# zXnAw^(-Ep<0Z_*E)yRjwgWD$^vi#_%jh8>ABrtaApIDvRAczu(c|ZP_4e zB?dO0%ezC#4?p+72pbg#_gsN?SRtdRC$-nj+IMThI8J#+m!%sW z2e$+zM|`ocI_SKp`vTcA`tP`T-#NC&4|gOCXMXAWySn5@Vt;&S?*yyl&#vY2{*HgE36!hg zZPgu4eaA0A$7X*oKyw8WT7`+pd9u7+eciQVz`X#k%3~jJ!YIlw{l&0HNd!7ZJEU9N zJfJ-U=+6TE3IBfHS9P}`(X**+K@z-Os{kR2>oAP8{Nk$O&M@u)4*C#;mHv9yeGUXT z2uO`4$~AV#YSdA&-OLdq&P|vkf_MyLsDJ7T_{*U}oCkkn;(U4Y5hsMJN1z zEV^^`4xe>!1O~1^@oWpXg$fbV-|wMgtHM+Zh!jkkmghpxzZB=HXv7S8ORzUosk(c9 zJC-o^mi1G#+T_4>Vq;Ye>jSPQXxo&iJUT{NC;@+6o5t{+j227NsH^U2%gCPMcfTkiT8?0CXry)y-ivb!UYYvS{l2=e`0kEgeayL!MGma}f+H z=A+PDNFoeeHi8FG;jV8FyFvNUP&=<*Q2L~FA0QO-kVlp{jj}7Uly$YQhEat*?msT} zdm4XdUpSj+mJ)YG2a2Ach{!n5g@68Ws+vD}U6l`$!IAfPH`u$P?1{vlh8W-nESi4n zjDkl90#^MmFJ5S-3y>p@@+)$%trL?ui-Vu)-rvBJs3S1L&$80it@w&Yva1*Ii)O?x zBJDXE8blyLx;CN*=O|R{%L!Y+gi)ND!c%{r(O`?U4{{35>g(d3tREDmn>CnmBqH0x zix*Q>?f}AS0N*%qHuPOxkn|W$+iwJHHnnujWiMXvFAT#Ew69_e4Tgh{MS$@utI*sQ zLl*V-h|O;M)?af|_UEGBG-dY|ckujXX78M)LW%&)WfOvYEhuw3io&RHzrOWlG6#QE zIjuGDjuiB6bH4d{251~v(+OQoo`gD;#ZJjX>}K4yYr+XG!cqHfU@R!8PiS7wVY|ta z(1;=8WOig-qiCJzjZD7@#22@Z3fptolPMohIl1_YPrCNw(~7kheOilwQy zy*qwPcK>6fL0Rn&T{|GCM>sLoXLO7Az1adu@7N}u8J(#xS0ead^lf)K4h*I9l*t6YBc%oJ7elvQazkV~_)0+O+`$&q zV611sQ*M7bPvDD#fIMaP+YCT8Im_u33S&8`gXU?S9f8N$f*<6k1)c7`o!2=S0~Pur z99CHr%JO`R3Iw?RskE(Y0$YFLDQ-z8=7IqQlo}UL>{mCt7?=dk42+^hTh;f2At;7L zeY%?{(Yw0e^Wls12#&spONB@A88@4@c?gP}$N#L}12}XCGJBFh@lSi8_0ck7r~i{+ z51RkX2jc_{=)-9Mjl`j0LjI%s!9!+}e9pxd!)aUR12*ee7ApE5`|f=$L-kG zO`H>J{(P?u9PZNeqFGd)PKl@T1o;BL_#P#E2OFZ{r?xx!c!@$u}VN0 z$ca-%J~i0hu=h%v9Hh3cxdZ`P2_D0Tc9;}=1JH&wocRl{21>X6nPIu(cjgML(uh8g zv05(m&M;7VE3U;Eaz}9}4vhDao(yay6Z@@}M8_K{PeVIugHV6?z#vM2sAV5Iic+cH z;-gl))+3kqs|{F@a12C8Q@7R@F|+*^X*sJSu<`|Ma641LWmGxvfwmPZ6dm>=U*8J9 z!3WxJ$1m}i?kcyS6n)AsOc%gheDRCZ3_fM!7P(40EpK^#v2kpNT0!gqGm<0siN9Q( zJ@~T^EM#nV3k-jyG85{|IB6$-1cdas6yD~%u!-+< zhqtNIeQExw4viKKz7>Omeb!NiJ%hyq0$a1O&e|HkjE})oa^}i~)VN+0mW~!h1>}gw zhA{eOX_ko!O%gkua->-0{<7=F)^2 zEFQu(4~R5+dqL@{I0|j_h|={}n}><6Ctx3-ZYxnmn|2(2FG>UPl2XJj^oC z!;{Y`qWgcK^u{$Te0xf>Y=GwHBc67FA$Ak!%Xq#a(v^)jsBm61owm+Gn`O=bLawnS z82BTjkbO~?G;^D=_h!Eq-#m#Q%c}L&9rn`P^Mf36Diqyu3}^Mh`sdfz{cc}&L;Q8d4A0{*QA5ZDJ9@(*>r8tg zli5(QiU8eXJ?i4xF+USLUbYgg0h40XAsMwW7qWXZafcOjTB4KC{C;PWtiTr70!UyG z{!xFBpa?$>cPxj+#cy5H=Fd(Qz=>FPw@442SH5^eWa6P+^CVGG)vxR0F0*Y>Rm<(cH{*m;uXgylRf!<}3|z4>QSU*0D)V zsBAW-;ACM5FD&yHW@%v&e4i&BoI5n89+=>E4vLWezzF^Po|}kCHQP|7X>eQA?ZT!( zzq3b2*o)Ab_`!ufyo2)#r2~(hO{agtgIng$_4>dx6ZDV5IAOPL?zXqOT@Z~lV_Do7 zg%q<~&5oRzNHIKWqU0eEj*prj1cEwx56HVtVn80GGvAf>)))Z5RifZ;o=;)WfHrY3 z7=h9Xk-A>2empy46)3fIm4ICc>nFM`OxBPsIPBSUk#?4-*DCz_K>SZ3=0ty>q0die z`5Oq9C1bw%BiQ>Q#IxLez26z_cXn+m`1@_awl~*VCNoMd!u9fUC3T>1$uxQ*2ZQ}O ziD}O44d^X9--*!_(Cv!K1%V}C@rd@C5ep#u?zAKnF<8kazlvy#g~G(4PO_0uj5g3% z9cpFa0E_u4YETvrs5JSIczS;+53|eyXMtP^rR`jM1Ew>atuM7i-B~@!CS zVHDfZKD-ahPo@Y*lzH$S0bKsI@QP~9G?dN(!mAF=AAIMB-ods?!1elwgZ8%BVD zzYm;ROzca4JDjR)wD)=*PGf6k;MC}${sc}AO`dL6CE{)i(rV6|R=Q}upuYQkJ+ z9|ETrHvB+1y)?XnQ>}m09|WgMwqRn>nf3n(P4%2WU4g06?+2y;7W%>S$opd{oav4A zGkwq*{(tFj_+YVm*oS5FG{h#q+3&X$bQuPS(=dv}Cp!sm$&~?q+M(;0A1m~B;Ug!K zbAUvuPy#f*(A|hwLiM9oP_gI=ev)jj!FxV4L7Rk;i=lEtZ6SYmZ0J5q!%yfYPm-YP zT`Dns<&((aRPWGL{wWtr!W2AlPf$q}0n&6U2UF}MjJIZ11(ajC|z-f3UXh*X& zm?!UMNi8oyMX5kx+)1Qjm~d*t+~pAQbt|2Dx2tq|l^cJlGk4vxZMnuMh^09wiRHJ& zwyG<+>Y%erJ^nmO^}+zhRg?&4nZ)_ZfMuJf66pJ{b)o`bl2cCs5m?_nv$DJ*o$%ME z6TZ7u;Pb9LyL24RJ4!9yy~^qC6~1_BF;t(hV6Im$_@*TIhV7jgMwI0?p?PdbIB7M* zg$z(_PdR^Dx22ixs-~#%LlU_U!>uYtt7`Y!JP*3K}jdq_u~`SCi9GsGPFEd!#k_kx)}fhxi74+_HkZx~ziVMvHpN)i`?q zANu`~^0TmJC0fuKva>J{<)Io2eDxcMi@ezm|+oPx;qxx12zeGOq0%1B72^UG2=Ke}v~`#TVfx)!!AUd!!Wcpff#YMWf$ zMMACzz^PArX4e!n6$PDJ>BuDkL))sZdrE)S^{%5#?K7PwbTH(Aw4BZ5h9hQ+hg@Q= zuFyIQ7V{^K%MZC(;{{>hsVw#RHOp}8Pv;8OSYq1Zjtku#Gpava?xe;edxG+svQ$hl zc)0B)XKjuRVjCKFtJJtNj#s%_LqdO! zy99d>fb}kHI7N_7S79+8<+cT6sP(YfPktX<%&+f9qp+_f8`l61GkW}aJNQO zFuqISl1)T_7l{oABAcqqMcdQs9`EKE1?sRr9xrAJm3V@V?~+6YPy4>2R3v34x&2r| zm)%_!a_c(Bqy~H{+9l-DT7|I^F!g^eS28f@G=QeZaLo&fudaDP8JjHG*tvV$kBmRE}Q}; zCjcuafM=DTd+J>^m>vzjy1I<=ouI%B+RQ12QR3huKt#D|+q&m70ooZCs=xg1>pzhi zqe`PmLB$I+;id6&@mBWFshfWVAsXlZz2&@otu)~Ej?>IQ20iS6FQfZs@Q(VNGq?to z0&OfOe^Cui4^;d=P@L&rz3K_ST@tXlJg+=Us8N>za8L1#_LNn1L;=j91wXah zN+25J_eJ}Lrk{gR*=!bVAU~ZDxmZ9Uzhv~yrE7ip?ylUqZ2W7HU@LC1_4Ar<-7U7h zvaxcHFm%uG!Yz0`&QE_@9@t@uReq}AzZb`v|JxtyV8pr{yt!2RFV3*s?u+8QTQW!R zNLuvLlT3CkID2w@* zf!_xcw{ZLijs$-}*>c;)vhV&1z8$b4LYM&ti{4^6I>$MV z9mmRY%SpK)5+V^{VF=K&^7XfSx@Rx|K{>bTz6iu%mY&`>1&i$>Sp56N%i9;1H(``4 zVn0j5ba8vXP@$h>=^~MlAFFV2yIFkn-tGIBMYG;5|G0ns{_;kq(wYBpB~{>EEmty= z-nY$CzrJqz;*hWV^7AtF3L5)$nFd~ac(_}xMBwS|^!R;ypda79zWm|M>cjgt^m^T{ z;M}q<|IYieg^fiTsSt*n`{IDxHf!EFU*mh*Jk|96uit*VpkLn~8=ez{zX$MC{6PjH zy>Q`Lt`dLxv*~*MTtD#lxA2I(|G~Sz2pDhE=jDya)FSn>IF1l0iLbJF0qgug5DIUX zQRd}$6@wFA(et}6dA+ZSj^5gPdUnVCUITRK3k?$w_kfA6FV{T1Y=|JC63*E~kTJ=| z(0%m$(QUrFeeu@|0Y8IT5j8B%#ruUs(Kn9 zIBa&Qm(QI01B-G^l2tJ5H*enk_(9JXejtCDv?7iDG!u(hB8`DSHEi&?%$F-*TfGxL zTab&`1Kk4H{8xu#xbMN}8D^S=m~JXUKb0A6x-I%o-7eP>hPV$j{t3{c-?hUwfcDH6 zK{_GJvHrBr4>?RO4&B*%1kw)^>D)sE8C^vG7~MpV{iB0_0syi%*p$jg`dHCjF9Pc-spTQ&xD%FCM#4c`}ee>@lq7I`~3V6`bh%sLQ| zyt<(Ib=&n7@6G{Gn{N^r7DsHT}|n?ulNY2y(~xMqoM)%M3nPb`?`pion;{Lg0F!I3g=b*gC_H zmTYmMUt^E0_%8okni*PQwnvRUctxaYh~ak!^3tKIRH=7C8{}qQ>DqIb@P3_DB^9wlgg5`uFLhiF{MK(i-2 zG;GbLJ*=AI*dH__z%ZOZKfr$(Xf|Y{XkhTG>iqCPWBo4gc{(WxZMI6hyS}T$1)G(@ zC180BV+=}1rpy%Ws%SRGRm1CL-oB)5(TcHC!gS3@%+Qx9`+`P{G3kqj2JVg>F6>so z>OfQ1*Xi@_q4R0luge5@_k`dENTvKVW{p@j>*~1C=cR+8{rNf&EZ=`Xll2i?yqXv} z1ww9X5*H#ZFB34Yf{DNt%@)^QjP?|`XK40>U3$`#Q)^&gj3VFIv@X~FUKlE)e>G8Z za1xsB1$}T&iRcs@rr8OYlVTa8#}tMU%2rLEH$`v!61MIaUGl4T2UQ7dryxA5s0;C*7Z%Ei zRS2`d7lPHiwb*~J-o7>V5{*ixjf&;o$lDvI^>ewgCNyW83y}x7zGPzWj%=Pc1l6Hq zL)zyDU=22^1T5J+uPTeg~ zJ(^7^jO{eXfLTOT!>32Q=-tXStzkU!FnH25T>!I?>269CR-7bR1;Nkuusy5MLiBzk z)@Ti!VUI=s0|S2Cn&ldQg5(rccSSSsNMk?rB?w(0$KyLE-uoj$FO>I0Q$N^9kvQZO zQ=za{8rGL>2nZX0^wRIxG?G;of#;YtIheC^SAuszkDO|X zL8=EU)6VHa)djFT0QO{`2op9Jw>Vk5&W=*ges7Uliq>NA-8?Gl*9>NFVm8a6Uv*#jtD za$Ew3e$LB^^J$SfQJpx0j=4DFG{_|KG4p9}r1(Zcoxc%$mxl=mkAM0NQIi-c56??^ z=xK9jL#1i_EF<9?ZW;_cL>oU99r(uQm?h3!RhU@xf%ZDqun*jm86M*_8-l_2Du*y? z{bYDuQ@uOMMj7bBz*mAzH)#YQ8_RyARXMzmi~@Vy*6Fv-zBtc6F!kqs)#kj+^3vrX z_UD)=vP^_-Ch2M6m4EdRn@-$R&~3g_Z1haFoUu;2;0w4n6je;q7wK3^Xa)zasb}+_ z@O$I%KhI--fvxGp?Tg}MA%oOc8JnpSFXoKL=7*sedu<{6Y(JZf^fe|4=J0n)ZxI7> zLT1O;7zD%;z{Lz$7=v_h>Y~)f4o4oz9OAUcvZ`nhZp!&y5P!bon!optG={%1y`iV- z1O|;!WHEIoKdz!kJ?}MoS94CZP=L)OwO*&CB4FfIVFIqI-D4C#@soc9|F%8Uxvdmk zTO%e1W;fQ@jbz&xjeV3*T5G*AU1#-{#d#ru^7w8*p7$ z7~q7U{axP_-(6LX?{_@TVOng%w2<;i_^8UeLq6W+o}LpQK(AS!^CeR*Z<-W`_O~Nu z9n7j&>*3P?N|Bzi*_0$Wvs{i-z7`vSnW?&#wkxsxM}LJI+MbWsp(XqvX*yeYJXe5p zE*y#ku9_{9An@aeuY9{i-qh}sNK-Gm!e{1v&_>4~7e^4eI79Oe4ouUG_>t)v(;|*8 zcuOo0z-=ygo4k7%Nx6nDNfvRM`EeRKIUE6$Bx{K2z#U8QD7-N-bALQEoelFH1z?wz zCq?5)EtioD2pE3?e>_tl4W;nGRK(!Hi6kPmFp97s;Pze-3UvisawQpaS58Ut-Lc@PC8Sra|rNy$QyLfuK3Ne z5WVO0sCC{78N`Jv3Z$Pza9{`rMkb}ZZf%(;AZNr_iZ$?JxyemF2ZI2c`*|$EBy*uP zH}%s@Q$;g^3$v7sQ%yzBLjjxN#jrOqe zp-Ta#n+RYAEv8I8X3P*6Q=Q?<@%o_%u6Y*S`wRqR1rc8u@fPntAttXK0-(AEeLWr{ zZv=mimO(VS@U^Yv!F4{S#6oaD4D+06H(0r#Nuy%VStgm`DaUggBOMDOm$rs8Az}|Y zvvWH`OkQzD_kdW7Y%JEl2;cujrn6ec^^@n-*td0iZ2EZ>HBeP%asfeMCYdI`EoJ2W z`z2>or_>99dZ{$j!wMmW!db*MTurCc2i$+SDAILLq>%VystSypD+#9Dlq0W)Qe&u` zn#UDcs1dzFWzyq3Z&r;c5d!m=x<}WQ+hz!S#+GL|8{V+eIwxrsgcWxhjr^xQiQEp{ zkJY{9BJja5^KdFDL&HQj)-!17*zLkj3#sb-3rqDnueic`-f;Z)hXT0on{S>KKrDaA zjz}0LNH3FRk`qKmsqj;iOujiO#ICyjsp33|>pWg9ha#nwG|B3CN~|b>Gh*Q+=3LD_ zrrGm0yl)T1oCV($5YP6=0cVZ)NLuyFwB_WKkdywC;FPkKMH&pSD_c@AW*xj-7tTj( z(I1R6ql3^d1JN;qsg*KE$5_i7(;I(SBn(oA-q8%bAq-KW_dyrMwHQn)(Wk0%2J>m) zr`RktGOmTzo|{j);C>d^a9hB_K7M9tR;lC#gLICk+=?EnnKV77-D<%;t{SWveV669XMq;gxgYo)A1zzH}-+Oz=AY6C}ESTG7plNt#R- zJB-aAg2ov##6$+f)Y*R&lSGpeKmR`jlN8ga{r9BGA>{OgAkz(jw)25oIMboM)NT1O zAICisiEbL8FP}&43tW;r!0Pt6-O+p5^DflI!h=rJLNozVWPmpl`E$#St+FZaaaU4? zM{(%|e+{{NdS?p7x;58S7pTX^77=)iJu_?vygP2U#+jHBN2GrVP?I%+?aVxvW*y3B zD)aog@}E-$&`Mu$6-p$hrJF>J3UD-nST43@*Hb&7DbP&&Wl}*+1Rbpcj2-n7YY1?# zq30XQw)ylX&ZX>=7@=EA<=JZEl+kn*%FytctG-Lj`jxCI`#NFVC@I0*!k^ev~?Ca-msaC5HK zJFcl>>y4HZCh2_XBgssKTVbTt&_Y%-d_0){p~~)ZZ4!!w2xC7sY1hxr1%{4tY7=q0 zvNbzIvFUz_=laiJ6x$Tc0*ih8Ftn7u9=cw*F+O(Fp(cNQG%mhql1Syp=06o^sf=b? zwj-wxNmrhLDPJ#z*HA6H;w~LMGpENyl5krHt~#F6(DS5)Pg6!@pUHiOv#kUzjv1UUx5WNz;}?rwi9@W1DPEpDQ(%vj-!M>x-N=t6eh* zVT&3o*P*27q}5FreG>hcf52iyyTQnCufX0b821ljT6eZ^2!{H90kY}gGq-aT2-Q^q zG`C4=2p9nY&9`D}2oC{&8(W4YDO!R%_S$Vt5L8Xqa?iFdswB7i*4IAV8!I(ggGh& zp=}qYjPR|5RmzV-ia;-Z6SEYC(26uLyrYR5_}9LU!dWr<1wz>#gFqq&fYz#09C*EW z$f1|~gB%cQh$}}Wc&Iq=MPM!wL&c%5w7w7v1XC)A&hj*a7~;F0mf>6$d~U!w6ql53 z2(^Dfz5}=zMoWJxT99w7Nck;M24zXKBbpPf`cVZz|L+qXfi3{}y&bLK)#;(t<1}}Y z1eWaIlKtC}{adns>)P*$W<(pB^OV}}hE@G&Nwgi-8uE_5|A$eVpSYzt9gFfAo@&B- zG-(2nhTKVCWCG{1IAH=2#BI2e2?WPYKx%*cL670x4`}x_?V0x8P|udy8MS|>c1^US z9z21ib@p%!tq@eT7sd3mSrA(LAjmNABZJ}qT+U%2_l_uij$#Z5(9Vf2i6%q~8oj1= zO*A9gP(RP<20qlUjPkxBls_ZNDI3E5)g(w3Gz4`n0qI;8Qy_&g@B)zFlqQtWa}E-F-9|_Z@#rY#|gs zCcQu3|K>1ShC2cI?Xg7v)Dp-||8a7H4B?^p=*I`2J8%mAbF6YV&xb{SIb%9F@ss%i zGP9q~SOn7-XH3_T_buQNy7Z-`HYYUK)UI8Ma|X*pEuHF<33UvHbx{s*CWC3ijKMAg z_wp&_|JyE2OhH|e!>dtpCCPu`)hM}=^xE%_V&N3egG{$yxO0rO=BW$m(0(B)I1_w5{8-Lq<`Yzej{dZ#Niat*=D(GNILtItL8XSQ9qN9hJIu)U z3%AxhsCq#cSG`)SMM3;{nowB+r*a(&*|cuvqeMz09f$OH~>#e4*TDE+%qN04A^a3abvur|OK&Bza;h-Lh`SXUt7?S>27(w_)KF!q5!6hz(t;F5MHZJBAp zm()e3mMhHA(>2L58*IHx^3s`g=mIr8GI>>u5Pl#Pyhj;l16%id0|>+XOAU3T zN)Mg4v~4^wtu_f2N}>OCNdx>#g>>x>767hnv69^O=SR;RaHN`Y*4K-{v&?~fv4IRv zx=_WoGi;tS*mkd&9qq)UxK*{;C?f5xiM#~1&g>=quwt*|y@jan;@h^&ahu0md?0D$ zeuIOOKB%Wp{?6rp0b4EGhhuaIhhuaJhhuaKhhuaLw_|h+55NI4w{tWNTLA(MXSdKb z4G#f-gSPGoH5EierbF)AS1>ekgy+KkSP-e?f1;L{q14>GB2xKzusm0Dt~kqq#w%fg#Z|vq^+@m4-e$0NAUDW z%}kQ|I(%q?DmI?spXzQqkG&5SpYaK|Np#qM$f3_!Af6*OGAPq&ODE~JeO6Y0teeUS zTb=O406R7O(yZty+D0wg(Khzh+uLH9t@#oe617kret_p_Pr737#T8#d8^Yg~4bgbT z-9=f;0C%Gs$XbhYZ86YI6#&B+0SuXjRu85DU0=wfbl_co)RBqG?7|_@h4lBwNN-dk}nL1#MNjfHlCIokaS-l|=CTt52`-_UZs~tX< zfw{oPH1mLqS;d1h8C$SwVAliWp$EC{x|?t z1~9-zV$c;C@qA%o?cL;A?d;2d9Z39vo^89Yu6R&U^Dl7e_BP*FJQN`cP|`z~qG+HE zRj3!`5O5lRmoTtAo1YpTnw!*nF$eWzTv-_Kn>X9_nys4z8=*7}I7`%4yxs?YPW|-! zKEt+&of)P5(1tvl7d4yN{!oI7k@8(}PYXZL9?`+S&(?>Gb>Bt~6Jl{n*xKzKJDpjO z3Bv@5&j5%(cfWf+Z@>gNIcOJw^1~z&lRg|REJ#Fsx!sW;cEzG7I1Xm8FS0clPQ^Va zSo&p{fmX)%RGVzQ=APviY#JGuH68Tqe|%u3It~2D1yI*(i4DZNo7k1o6nZB3=U>N$k&j9`T zWph}I!|yop_Vg4eK$zO@y<3LneTJ|i_9C9m!4bCK!z+W!$jbWYhg%X0bvlE{z>mXY z6p99338_3|^9;NE;4b2YF%|V2F45zPz2Cy)9_h#j- zW9ac&houPYL|8V0U-1%oxmwiQMeY!M4Tf1R#Z$N#ouv~e?XZdlBw?Qf-Y!%GcFQz? zwS%`SxfGq=?ftB^?Y|Frlg81|V)wm5GQewqQvYrXvfIlfBxB~5M-?Zzsn5s87b#8EX{!w1Q)MlCo*H`px`sKPDhM@ zJ-64z^*%#*j5wMyF7^T8-f<$LYUB}|pd>6zV7Vxcla=D=axr3e!39VeMa|tyctWvi zJocenIVol`K!$=>-BMVRubo&{oq<(OD89TCej#s9nX3|9p^3|^e_$z6=eMwkPbuyV zmG=!XLVMYYJu&wZeumod>?9zUJD80MEmV0|0}2TDjw+z{r;4A@NJ8RTjfsyQw1X8D ztRJ0Mtw9f}x>#0x3xq3ok~w0k=>E2c^@=aw(raWG%hJ`GY+0;}I&-hoysn4^^rv!Es@P;e58Nx$nzQK3P=t$8|ms$tw$ek+?NlMo}RvCI6@s(hvIOnI=7O zn&{4Q4o=C9;4lBI@?Cwm;4J7CE%CVYJykms_{y>CJ$e`0>2=k z$S(negCpm0BWV}ZzdXqRo)QHrF@%rrVK8kez_Fm?s&gX_3q$WGunt)H(GizZTC8EA zAOin>zQCm#9bpP-h?Jncp(D3{r(;gXJ&pN_+P^h-f4QqA9joTv5NFr)f75F76Av^7 zD8w+8e@CdIHvyBviG~5Y-oEXSqg;)$5a`CU2qG2}>8Geh7%3PxokEXlm>>rALRz?g zqF6cfan0D(ga|}Zkzi^%u23i%cey~k&zS|lqr@UV5<^lp-mlbipmt8jU#MqC?V64V zdjNO;e*rX1;=O{tlr$yrZs}OiaY_9dwbyj~o{l@}&#AqqBaf+Dbnpo}^8Sq59{~vO z0q`|~Nkacg7VE?^?S9^C?6BIZ&<~6TN+1*v7YSuY7PF>fMn}{+6G$2vU+V88FBQY2 zOnk{}O{FlVZE@mTfK_@ib2b!d9h1E?Fpw6Wf8qy##VcmU=kNm>rAaqGLOF)$T2o1?*4 z?{4yxqZE@@387d*whQfBI_3iJZIbS+lyETds&OgDfSr>SkUURHC;-PBI_7lTx7vJlDLqpk!aAMA z0<9mYy>9?HrWYR5@GK>1jlBjtD}UHKPi}PfY;H zJ(`ZMsb|*;DfgX`qw~^FnHMdRlkTxu1C7I;1(DnI5~Z0+VGQ;_Q9?|+pn`;d2*>TIiKweqL|szP?erHsgZ+wtIEu%iL8-{|M+fKxxgZe|$3t-^LR!*s)HPy+^dv*? z3zmn-^jo|EdrdBim#0#gO@u)zorc{%rkW5K?OUHtGey4Uu$C`SI)|hcjwd!2!Q(!xhy2SdX zQWg#NcL0w}FAAcjQW%?b0F%blJ>%L*2Mni)e+baYYr2$o zVhPeRNloksYu4m!GjX{K1@3*pnZ-YIe&@?pNW#|g5z}t6&_NQM0YcCH*)aRVH1uQh zNGf}j{gWw-us=-k`)g5}bPD_F+pvT(wUWz-B(JgVSve5O(12!1%nPELj=!`(Y}>tx z2#A7$m}xlHJw~*|{%aCPe@?Qj=vcEvuUO(mBjx7vPZac+)Dqx%Y%Y=7R0_RP3w;x6 zpaoKkv}_@atg<06@e_3kKuxAFHf{XaKb1VHa$m;uB^O7N+i>!puH*vf6lUJ@2<7}8nE3*xBph1 z?Y}^_|LA1JKY%0=K>8~ee9`z7!^6ri5kxl?2iZ9tTnoOY&qC;3aS)5JEU*n;W%a+Ia%`Gz7BMrWeO(XxJ z;Cw295skGef4od8n;9xP8&61yFU1pc-df%S?qi=FgT-_7_T#=U75(f)nP+{fVH04k zy#((kQy7y^lKRRxypPY8kB$Ba`D88mBxi0h(+2#hWX{MJs=z2t7{`(@?iXha!bmR3 zluxE`Zql<4V`2@?2>*RNh&`5!I&a(lHb334EhV0Re?q=CYX#g-*c3BQ_(6 z{xvcBn46}!nWO3pSWgeC=EqOGf1e+}=;0I%f9++2m=I`Y6FibI7#66Bd}A*1ky9!3 z`o4(vCag()qfPVKZA4#@p0Ax6rV?KiUQeYkrkxsIM#49J{#XB#TnZq?VB*VXJzUO@ zAH=j1-}R}Q-nBdh>F7U50RO-f)_q>V$I6Ul+ZtLh`dvFC3q;P2@N{@qfCuY$8(fkG zf1ga@k^nDJei-7cK`&BCm*2M-nTs2ELQvPY;rWCwYIm*F!+tseis?bY_#YNzt&Bo` zMmz}XbZ`!r2y-fhG2?}mzBSIZ3?$>@AQ??Ox6P`RU=1jR+Q5A=)=l1@RLMSrK&KHRK2|11|&7=#f`~wP9o~!keiS#$E|lmyt^(=xAsg;E`8?HBxj*8geRuu@{0hRuqZ_>hrUZ zFokmf^fB*e+%CoD!7jx|Mt~mEek|Ex2@=h5y_Q&sR_-6BHq5BAgT+rATqLTg6vku) z%cm%HOO9kn`I3oy$Cw@ZoVVjffA^bgbPRyt_}Pqi- zoagHbmDIT;?>L#l7-L~Ykpz-=Gy|W)so)V^2@EVt9+7l^RRkmvMhTIKf6QojHdLCy zD41&)oXoB3!Q2j0S)UMR6SBfkaMT>oR6o?!^ROJN?^;!GTTr&OBmTIvjlTIy$6J|0O9oThGqiDCbfXt)mV*I zT{al4`RRD&Q04o@e@UgKxDgKyJ-Ju8DvflJZse+<^JA4FKM2gpgr`1D)+<1seWVqIJk;n;E%H9eeMc8pO!AVI;p}Z#H3a&XzUe}ZtBW*N4`5L zch|f~0_c-SS-w?PXHwW0Z1J#{sz(tQLyNpa*)7Y9Az7YPe_RU?D@VC|-xpk={@B-4 zvdqiudVNHwZq>lk$;H|?T8i;uVdK2Q!i(G*u+Z3Y2`mClzYho7x(4=_Dy$|3kROHT z;Gl`bK)Gn{9_#sGUrlAuu$_4C3o6W1`F!c?Vqeu)d@1W!4;;ot{;+j?fq^;1fqO<{ z$Pajj^_l{KfA*$Yy3}y1>iuC^ANEue7VvjfP)U4;gfdF7joyr8o|j#qZ){n&s{=l) zp3d%I_n@9|GgnwySS!fh6#KGNb8y)xmUT*GyS1+t-ExF*S!#PqEqmN_ACfs^W9DNnE~7f7yLt@GIZ2N+ewr&5|c;ShtD zmR!C(f9@9YhI5G--6q+;g=iP1q{$$5@S- z0fBg~*jGwzbHrU&BYhs(rf{tkF62sqm5^}YGBi0?4UD6tor5Wqh?c6O`XQK7Z#TXZ zmC#(^aeoim8cC&o?3H5B7Ha~QWmDX=v#oR72a)+-eSg-cAvFHUAd~J*i`c1 z`QGW-6s`6n!!vwG<3pGm?wvK>;~uu8h80F$-Q;x6++#g{={eVRO}=kkc`YEt83u}MYG{&n%A5bQX_$K)Z^Z$0}VoF^^m&< zG|#{}J1!%|oT*sY04lD!)x*{IBZ_nE6wam?8b1g{juY?HZQVXIPa^@+A!#@+(7Gad zw8%^>t$|97?V(M>wME58Tf$yet7onhM$@G3xdbY#TeTe@!f}5wZjJVXM8vo|E}bM^ z)`Gmg>so;VP($b=Yf1?*5a0_1=814>!vZB~>614FCyy06O;f#B0OLLpxX7`lg+7Cr-yrBs? z-Uax8Z-C@TQQ@96W_q`C%$d_fXOH z%i(MY)<%MqBaku0>ftz060MG%K~YPQwDh@vD8|guRI*`3#+QbuycZ2K=@o{758TJI zJk*>Tb-Xxj5PYf^kMgtU^E3YX(lazZ<4jxc6wih_^=&LX`@+l4 z5w;1lVgY}+yFeH&w=5z_h~!Pfb-V1D3w2dWsm&f_K*pDQ!jf19&0SO=@ntaTOYT^m znz>5+NQH;iRn!aO$aq^~XsF^za4F}u+Vy_o$zvTMV4v&Xx(;MGWJDA~T~K+!7h#7% zPtS=uh{4_!4r8W4#Q6lJM(mH8;VP0V*JOOzvc7)-dk{pmbZ)xURysA`aRF@M;Jy~j zTW0%>*fqb`MJ1y|$G~uyZqt)?VyAO8Y2-(#V4(Xvb1I0G)*lW)uG)IvIN;oJqnn;X zWP~wSMOJb%FA-!%*KE0l86+gE()Ef08rH=2)f0*7^@+1LiS@~?K-!NMhYExhMC?{c zl@CbyzRF8DQU&HcY?V3#W9gjRn%7$yv8uaLo-*KL(p%hK37ujUl8B7w!@zD0_xrEn z{?wFXkmYeIQ)cT3%$Y`PPcva%r_NxPzn={@f8yk%cCo2mn8^4Jq$n8@rAHQOV~|48 zr2lVP+poMO0=!|SZvhqj(tBd#M_T{8?}=kyLEF*y9Dr-EGRQwc;Ngt!i9!t+CoDdp zhA6aXpSikl{lo#})Y-9VeWnpFE>bJ&oB0~UudGq4*blXx42w_eg23qlXRwZZ0%)_5 ze^1~PD_HF(k?8q~P`p6#lY9Wcz?$j6>#V)*$}40ceM1cYOHMPm=->SUUuX@GDvYO( zBt0O4ptmjsrHT{88PUB6of!@$RDj2{v&%#}R(PEC!^q)8^{aYMPi$DuS8G9rW+bOi zZHY=Wc`qj~{07-Do-^PBA5LrfjInTVf72hd+YAgD1C^n`2f%jO+UGF<*F~WBtDOKx zT7Fi!ePG9g8<0r{k+i)6F{CcgCM3TfS;?|rQ^+=(BqD`Kw8d8tSy4Gt&N&4S>~%E) z>D2d1yl9T>UcI?}HSl5zKsQ|&uoeIcELOW$|605X7C$V=ll&_14XWX%1y;kqf5-<` z1yT?EV6hu+jUSpA1*BZZ-CTLKc(t6jFXstFh6ncu=qogPPAD36V#dPcXC!pvGbONuJgNCPY0Ag}>u3JwIXiY_j z2R7{m&-%;oE}m>ZS7_mX)neRhf9XzrIXZTl(E%@}y*vV#7|&=GSS2q7=Kn1IYV9>y z55?B!PQ(HiPiY=tXB?!?;YRojfKQKO!gL;yUL?dYkfOV1CH=DM zSz5&s!SdKAhxfeiIP&g!RO4*v*)9XzOPrBPdj^JYe_rBg3gfY>knV9yCRQ@;IIAZL zHmq8%6bm0a4$dqLJM^?Ne}3taQ$muRiD`|Wbot%wCm|`P|i$v`1!wCp5iJUg?tsom6qE@P9*DLPI`XqYLh9eoyi4A>aNA5`& z?O3@BBB@4xRuP57F8hapX~$@RB;|aJ8HqiZox~Dk3{bPoJMCTg(c@kj>JQqaG4*i0fUoeCo0`D&q7yK~@I1*G@zjwWPhsLPJe*S>_c>})9{ zH)b9d1!ka$M5WyHVHp>2IgtD+CE|QrYGx#=FK&$OvvR^2lLM zLvCHX@JYi!2CX;&<(lqRc_UH> zJKeh8e+cQ8ch5@(dsxFnjHN${rh|iZzycp8z?0i|*+bq;a+KV4JXZtcm|8ncPI3Xq ztmH=>hA;7LOuQvXMGUK8KcOouo)qFZa*F1#`^#vq2j?@E!pTRV_$C=lBVnE>7Uo?1 zR|moyS7L}f6V=03C?YOl$iepmj7=ogoH+TLfAq0tD7jekJUZ0xYaD?QY{sr>kQ?Yy zZSvOVyIZ!$P@asifEq>HT*P=wZp8mELd0+A*ov$7?SV%u(QF1bDsq0tdhT&ts~`cuPfKeaU`a&Xu1ESurYhXOUs@h3^lP zDE1vALFm)Ruc1tQ8m?HwD+whjGgUKlY1Pj%uwZYw$P~*cijl!#Q9MKS31M0=6XsG3 zl9{TfOGrWV(*y~M<1JD1rf^T;l|%gie;_bS1ncXUoB|PbKx_x8FK*&C1y~+Av!Pfu z!t%x?Qy4vV<-*$saMi{o$7zMMZ`IUXsFKknK0INEhNddoqFgJ;ZMfAXT^ z4-;4{IsO23{zr~K8-f}@zoVmw<8C(Bt*4u#j=y=YspF3)+t2lsQ=X93Hqm|*%pHV@_HNH2MMemeM?#+~TFIV);tIq|bACdlB<5=>1)lKO zXGsG}Y51v}AS99p1Zq=^QtjqTe~6VIg{fNtxg!Ejk%NL@#Lb!V$TP^G465bP`--B< z!N`)QXf)zz&H-~MlOQPQ`_voq$jku(#c`8pm71$08wGxpPBUg5WF^C}PktP`*`iTe z8bQxVe(od-RV>AK)$9R?2iO`swUa<@u@MmGGM$Z<$O;s?N67^>#&dP`e^iLg{Jz*> z?}VvbR|16LA>;LP>mNlXqVzZd96Qnad7H$KW5I8Kb#t_4aC^MII8)j?8Oi%hJ|={} z35a^K5^4O!J!j2YGdPz=>ENSi)RdaUFLYYv=-5w`OKlrAZ|WlNmBvf)Bcs3SoM!I} zJEzA=tv}X@K4Wk;cA(>!e@#{Zlss@7_6tIY;_@)>x}t2Ch4UUVXpN2}H$}6|-)P9Y z9=QeuETh{|QW~RKPU->bvxr4fJ3-CC5oi1u0sBAa zkBIy*0XQ3r$lsI_MV6BQG07AkdiU9`D4!)O$Ytgn2y2&LWW26o<7ku|Kgmz$UL`xb z9=XHQHb0t{+RrsM6!~Jh8op;Sf#SUBtZTRRK&|4Sn3EcIpBM}-MHoAeSeFvZplzC$ zdN`{H^mjBQrk>7ae-B(#T8)^DT=)(94(2)ELy|EI!rt#h`K4q>JA69Ls-H6LF{Z$L zNEIj-w?<{vR5zI0 zsGU20m_8V~qwgD38oF-`BqJT$@#W$J!P~)C%>$gP8rx9MV_l!zMU|6J0obIZ2Mq-4 zaMA&n1+lN4e%@h+IjS~nn0Ms8~&s4fMgRL3pMBJ7Gq1F2liS*y^SOH#E&mqS_?umQtQ@_h| zQrCu3AC2?KKNa)^MCY{uCxsv0)Lr2 zKt_6Y&UGSEPI&u;v43nmca|o($>1_QV`n-~xRCJABto&XSGVxQUvMPuwgY1D zO>sM$tP}ddQ_kR0XxZJit-*VXx$9NAo(zEs&``5%FkP?jR$tw}UyO@calIL>#>q{& zo^EX4p`$z9O%q{Ucdv&WfRu~-Q-6BzbbULs?*?KH86S*Blhq1eKmN+&o$K?IoimYa zBj%i`L<)U&o&hpF_V^C=Sdy|`>=~X&=DPE|_yGJeD+|kpQV%Xi)7hjPO)Vv5HhApo zzn`rq#eDN6{d!(ZZx@>}wRr&SnOjb1+@{H7$fmtMFeNMN8)D3lw3T9l~ zB3aGg#RNLOoB?%L0E)HXLDGvZpML%P`^WadeDDR!>j!pvMjT{FQh!z}!d~fgoxMS{ z11OIcw|AR$N$h6;2cszv7;Z8(_&C&#`)oId83_1}(53>^wMrAK%jOe@QfDoqFDMfnv=6UL;vFL(|tlP5wzFE!g2Xp5pPfffzwaEA_( zCrVRKpKWFvRQrS1<$uIUnf>+iP%{v<(R5-_Vrzb)nj37O2H!0Fjjut_+*6kekY>7k zQTUcG3sR33bMM?ENQueJwRll3i}^o`xdZaPxOFH;G$)|yw=pebqH>36AlYxwNkFDn z&})^uK5|gbkEX=}$p!B!sp@rERLTS%_!cB$Jw=^`%Dh}%e}5bTH@n*}7poQB0){9j zFb+L(m?1EC5Tf@i>jX|~nRWOppwfR5*4s}X2!x!2GW4JJL!otk(I(qgrJ zCQy69zZVO{u0<+UJRO4om+O!8>oKwZ#!0oU0cl=M+>duKVR=K3c@T-1uoC6B1s1%bblPw#bcO{*UQohnZ5gMF@H&z_01-u>lI+?Ff8^f)alUYsMoDCk#ZYI~u zf^NR?t$!YuD;W3nW?jwKIro~Iemt8L%ehtR%@dL`I>|E6tE=_I8MluotMX=^G_#~o zSvVIbG=Kc{+2e=w@Wp&gN=K)Iq-DN@2bgq>V+ep{JBty^bADkS2vqOKf@V$NuBqc7xCXc2 zL%HyG{xYdNdZ>9~0-dUy zt^T}Rmtexti@>m{ETyNncQip+HYzHE=y|!iE!N~iiGlN}*6)YT_QGMn4P*vqjg6dX zp?|Extjq`eeer>ugbg-nR-Q`9#2D9e9KMjGH?Iq88Q#JhMFCdsAi#Iy2)|29SS$iavJ zjp;ZN>MhHDNtX{m*A~}PYV^2Rx$18gzU}jJ?m#@7IIuqtg&AzVtnS~?{l86XQv_}h zx5I^1){Z^cUcZ6eGuLm>9;x%=h@m%kvvL&L%g9%^)F#lMMLH#=Spw7R5L&x=*CNaOA~_xPf;zJODLU=J*V$G>rpS8sLC zT$bqF!PU1^U;7Zvmc7j3e{Q@Jbq*6CJX6{9_UCuL7R-i?tFvaT{l8;}Gk=hlOv-Jj zd-gR016-S(catR!s+2j2Qcj}mYifzIziNrHze0(!zd>L!6d3zsM__g|qs$qYP3Bl( zaqB37Vir)A?eyxcPW~@%Z7Z7NxJjGRvF=BIuu!AQ{*u z8Oy8yWzJy%IJr6lRh_3fvwwgp#S9ui5`RCiyaTo+E_2=%%eMq+d!9@Omm9lqR>1^C zt+liuIjtU?bBiV?Gta;TbP5%E>lVO%xVrcdOz7y_xKRulR1hl4m7A*5!Md8kCmxTr zE8(4hdl#?n{d&*S3@kFu&ZGn&lv+k3zKBRw0#Evp9wu+e*Lcz+9jA`vD#o1I~CEHXh{g%sTY za$pD1-iKHaxHxY`K!U1e!m=4)LczQ%g|Le*#Abfo#lCBK<6ipGu1yPg$m;Nvk@&FG zpgJ|6F`?8}M?*>1kAJZK)s~WP;wo;Je|zB}5<&+WKz@bJ2@RaYa(B!eUTa5~>%j*o zv%wvf6Ra8Ib%|wxHCK3jiRBg6%z`#6tXT&&bF8_k?)s-Dcuj9y2Q~8m4nbH1_1v0A z+WMfNYi&<6GgxA2XT8kTTwz&aY0a`!(P~s9xtJB@e)Nh3(SJcO29gZc2@*{F;Rv=0 z2sT23P2&lc0=CrwO?7}^u^>7KmIA?~n1fF6bvWEL+_ zF0iDUD=aO&Qdd91vcPhUWf?p*51v{D?H34v;7_n*fMvn0378%Aeh=gH_p{*rspSiL ze+!jG4kXHXAAc%GgP^_ME#euNV7UfRKxN~s7K<8zgW)(Zfi)b5Ef84(>p2RMzO z9j;3(S6H(SS}udTBdjSZXdZI--ms;$dW1$&3M8CCcm`WRIl|KJIw5J`dV}Q(ODk?n zb`Zkg#z-GJL_%m6Heu|4Lu63R!X|YCQbSS*)RBmg9e+{~Qs)8s*8#E@!QBu}O;X>! z2wINt8cC!`+EOG@j=e*vhU+`Lz6$Cmc>NBqOT4C<_d&~*mq?S>5{@m~Xqf>ebk>WQ zu^<|Rilsa;OaUw)r*e}WvTts2N8^U_21`3uW7qF!lvVi_OTx`OXuqnS%8}8HtFesE zji&+OZhwvC*kc^ZcOJh`URQe8mv22ipqyiQgXJoCY7^AhcZ#$_xHSArI}P`P1c?RF zAzm8(=Psf}A8j;CZHT9dn{n)hxE3*7UDMt9_9_WXkF<&gK5Q)+1`RqxHO5hM6x0)C z=UA?Tr#@EgjpGfZyFTs>s|ub$PBc!UmO;%rfPYQzzwvKqqq6-c`^{ysAR5I^B$mqH zd1_J5Wp0qBRz(#8uLBem0m8=t%B}-cQfYU6ct!}dpmUd5*Wu5(D=r(Dj zD~#5ncxn^eU03j>rDxT?^rjuz)NObLmp{u{FTBQrXv3?> z02biYshm~iYmv8>qU*t&butcouvO*7rOt~Zo2J;SUsM*4heP#?S~1h-`9u-vrOrW+yq(DXyC%3egc?c{AR* z&fD;=17g$$DGLlz<_uDL+xtDzjspnq4-k)o|7>)x*(4f7tJ#tRETEoJHIsXHha8}a zLS(DZSjh!|>lt3JJ=>Fmu;V;!ynjhY6yiJ&orQLO2Dc2QvY|j73;wXf7+i&YM8D2krixh(wmXNmrBjbL2e<-ugYoev+bAWVmTy}+*mTo3(1kY5h621BsuSW@BO zL+7&B9ZtQC?#8|ZNhk+wy6;lst z#X@MOmI;!2wSRx{`=J(EpH-MriLUw*ukWy21U2iR4bn_k0ZrRe$`%cU)q6TS)4587 zKFK{$)-A~6AvBPGQKT8LLSE+#>-;X`cSXo?e?m4B&Zy)h>GNcZd%lZk#-RJs72kj0 zV;bSVYnY*8B2~2xlo4HTykasK3`Ji+VEo?-u{Nu4imn{g+*CLv{7Qr&991Sh{tsXf zT<(-&f$!+*0e!*2Tm+)0^DLn19ItNzsuG3k9>}Jk|BAqWnf;pgq{S{z;#dd`%eg{= zwJ8O_GUy(;sQ>m}Yj|h3L3OCtu@JggQ$w$H7#rUd=u*X*78qwr@uw5KX2UAVl()Cy zK`Wd}GuF^b)~y7F>lun<@*(z{AqCpk0r*QSZLFCKw&&=WW$5^2=&EJtK|}ct%L%0t z>LQR*IA!*KAW$rXE&}=VbXBx*3xQUM$Pps441$6`ZXtDb3Q{ZOQ;RziuCj-I!*a20 zCwb9lxW}V07n0WQdOZvRotw!Z0g3V?qu-Mu7D5*pB#=Rv12L8vM#mjNhVhAH7@tmt z>aA3+{F|6a>(HisN5+MCKR~KowmT>l*#scn^is-yu@IV+vIYY>X8;SxmZ|Eag(|=_ z{5Fb$E-CbpLM(l7V>@$l1%6a7B_0c*i#fRge?tV(ik~>#>;Jkr*-j@0Sk@H2i zk~U1dA)vxjSb=MsiIY~O9EGDHG@9Th;i&{zCIJhODEwqtul5sSYDrLmBj;3XQ?XA+5q(1m`VL^CoR?~kI!dyyvBB&XELX`%tan5_qD6tT_&<`x1Gaend_s3CbUsxUX3$^B7q62Q8Sb$e~kMf&<7rPe+^ zw#}1SW+Ktuxp@zfS!Np0+bJf8$b1Bd!({H!4@c&n$UuB*kz}IJB11HUjvWQ5b&~yy z(+pRbu)&MEj~gBhp$iiVFrl)4AkOW0*W?wtCM9m2b>>BCmoh05llC#-qak$RLIN(l z#%YZrtLB|sEEiZ(WXs%d${*N*w`s1;X-T*Juwx-~4O@VI@JY8%%Y_TW{i{7j4Z|fA zZRb{XyrE7s)X9cA)ljD!>avD9(@>Y!bqwn?MYX5)b0?NH-szepIFO-#mncU9=m^k} z9LVUChBpj@w+>LW-jS_$l)uxC8zz$cv<%%IIk6DBn4Hn^aNRj*_4Xij>+rMIJErwc z-f)Mv@*ek3w%lnVCvPPu-zH}}(NckiM-QUKLTF;?jDbe73BQ48K1+8v5Y;-wCX(@1 zlJQ-V2|Px{V4lCW{Fe-W8l4tVf?i3Arh<nk0`MeQ5G#WPU|J}9R4tVG_Tyk-jW#ep1W!$>RZ10vT&QaGvYiI@ z%l1B#b}WD{3YaWOSst6DGjjb)k(^)vg$;3S|2(_GQ3gXiEmgIDM^Y?=E-Yn$C7-GK zlddgD?l8j%Gyg>^32CsBK&uK_2d=bC*rBsqx^Wc?p$k_UaFs^~S;gQ=R9v)+D{*Mm z#iq*!t=h*Ow;=Lv5Qp6HBS0K>$9wdnB6}nu3usKjZMnz509Yak(3OQG8IpTb+SZ%N*+nc6)9OFrJtlTJysnS zpvut#)D0FO7>DRKw{xz|oqJm1d5`H>2wj-A>34nN`Ir@=PqA2rnP^W-67NtE4WR=S zn9J7Zh(A6w2|RQKR<4~LpSqcHcbUvDrL;1X&1Gb9mknMIZO)=sc>NNuAK>*PSHBBd zWCuZ~_Si>%kc#1#E~E9ZovTmt^#P^;J~Z=pi$g4gCih%{IOLQ?IQJ(7l!24{4zJ01 zt`CMl*Q+`_;$u)#U}=-_^Trg))$ncl+|$zH`{BobLg>;4HUY2Cihq1i6>5V^)B`_a zx#$0e-$mwwUx)rk9DmGCczg;SXhPRESqD7uAGCLUH>|%brSBg{LwEiG6XHm&Y?{Ah z?#`*AFLB-v>l3OvPO)nFl)NIXCJVF&X=5RDk=AAy4iBvQ)RgVeXgR9J9JMJL5l}uu zieKP=^(B_nra=eg)%kS(TOf-3xf+IF{?w-^ZG!rF(DK*dZV}wA1GN10M}Jxpa!rc5 zjI>|IG;yPJUpv>_D3LS79yc~KhfPF$+Ia+?IbtE~6Q@NHf-=G6#{PhU)^$Hs9rIO7 zEJ^jUl4^edR-ITCj}EKq?}GLu`6CaL&hBY{N1;tEeA=l19)+A7f(h%-4t>qlUU*@D zBM~^by6sfZP85jo$AK7;pj-t4(GkOlNrO*I;O~(g3!w|yHt(>AUz2--S8BW`75C^2s6w`0)e|2^#-0FS{~2wfPoDTMtw05MCJfUswQ!}FxU{b*Gc zM}@+Oi!Gv(@rIu#rL$-|DH;*5IQ3KY$9M@ zrT#zuvrr*BqThwAm=)t5G3=SU6I{w*1*g_dJfH&$rU-vf$QaYL*l=_Fn7j$&=;FCo z(Q;6&iWrY7-ax;{&1&hdAPU zptLn)83i{T{OS1S)-?z-Bvn~^uqF!3pY}MA`{1pmi)(79olQ}E+JOb0c(D+=sAsbr zpKxHozd@m9PM_|f8a-k6txA`FG0FCf$@K8IDwwYLw1W;jxnd!7k;`U0KIxzXVD+z& z)n6jpe~;ylSo4=7j1`p*9wJG9-nXcwTb-jc_>>r*!dxg}J{@#QZEo>;GW3b`Gq-|A zE#F$#Q}~1MK0PhLahInZYT#)Z3!#gaHoLMv)PS{wk+D=&%fGDCDaVw5!+n-BV*zvx z&E_nwP8VqL$yu5ow{f-%+U%aj&Oh7683SKfo_0KdM`$dBE{uXVEvw@JV!m8*J7=_8 zrcT>AW8kW)(=zjWT*N}?!UZ_Hs>;mYl3+?mqdxO`%Tc*{yRi}rp$jWE&cM$M$2+jN z&P>+zU$OkUV+TP>cUta$WLO_-w!v$vrxf{DK@A;%_I_9&5Oo*ar30l#9%cqFxZfeq z!de@abAJqYnaZbFKG|Qx4%0&JZZ)8WG3@YG!`^B%WBR~4bB{#Ko;zY8#H=%KWoB+& zXU?4|HmQ`a2oBBk>k3yvO?bR!>5RNq9G#w{*`eqYq-gf?vz4PkIVR2iv2mz7h?bQIkKtR7_ z`M*yApx~Ej)eWuzIJX$q4JrWw#?F^S*9|>?!3Ta=JU1+>=D;{B=ab;d#>>M177>@zQOhpd+zbtf9nBzo`SSE5FXzIG`@TJ0-jDQ zKL5+&OsVv2?a=~pw*ZhmP#%R%8?OHQjC)kcfH2zdu;EpXNlL3 z*j`}IEnZ)PDx$V9OQq~2ZBszCBnp^F(@7E)kji4B!su4W{-3eE$JX~>;q?;R3+(xj z^ju;KSTRNm$OssguuaI+k|-b}02#M`Dk3s^^t=JEIL;3-{}x(4|0lMuu;+YNmr%|( zx@1rhQEum-!I$m)OKe|bdk(D$J+H9+H1zK(D{YWb7Dd%M@q~8S_ZVcCMKv5tD5_b3DwjKY7N<(+5pFs`{{>z@?0g#gKP3H^*#DT784e6LZMwF9mPA2j zILM5aL1s*it|jv?fCFUy9k$7 z)`l}JnCk;>tdKK5V|$N1w|ISjh3&GR77V9F?70ja&T*0g8{lsXCu>O*I7xw%VODU` zXyg)jEZeq7)RHKSjKIi1cle>vtf4ECX)AEr3Y@kgVX#0$H|j~>{}Wz6C;D)O?G=9d zp=7?&sphK$_eOKof^ap7Ji-z@B+a7mu#alKO7MrY=1oY{k|-bnPL&3Kx6>n$ajH&k zzQXd>8QP>-s!0?u0p~{B;Aryk&J7n@y7>X^|6==c&oE=s&yq7L#EEPgBt6~Mk{UGz z!QUZBo1n%Zs4-&C3fn7eKV;boZk7?IiLJFH3Ty>W&G4vJ2s_B)B-XZAGu7P#75aNLECZZL%g4!`T=8n#-QcJn;Ro=Q2wa zaP0Rg_I*LIf*4ITkif^Ww#nzLCQ-l>+$3v4e2-VTN$my_RUP4fZOW>aL;(qEJHmpp z5*a^(3yBLRC1l>YXvc}oB?80KP0_w;5(R_^Af!UHPh{K`MCc|#2xp?fnPn&|;g@EU3Gjgj*6ow{XXeNZMMAm#a7T4CeA#;iC8ne^o^+9$v|7o;gH zR867)2^jc)+=j4F+%xT@<0!N*Hz9?jZxA#xKf`tNY&#NhfRvj|EKbt@hAFw3u#d?U zz6$-dPB*`YpPmy;CBTd^gON=`f|)n;l_4R21_ugMdy^2?k{Eh46zpwjw7io} zu)!}AJggRXi?|8sZ7&{dwYwyC{7Vv9_Q8*<#M;}~&b)wBmfP0F=|E6E!}g0qvXum| zv#OPYyCzIiY^|C^UXO5a`GgL!HJNpTgP9dKWLLf66+M+-62r^$`M?{|Zx*>CSz7t9B$Y1m38*i!7dNX$xaXkPZuyfG`s z{_@^)OS|*jL$(jWeQ=6~OCKlpt?&7Mf$1?n?8YE`#DNxL5X{FQcz$W);2}%awAxpb z$Y=m#fRybd2~p8aXp<+Qg&0WK4J~ARV#kDkA7K^Ihjy5_Pju8nJ4`AuPfcQ;+N^mx zgf#fgQZ^Y8)g%g&A6#!Kq7hNGp*%XAajeMo5SZW|OWPE3ttL?b6Fh8bLdaES6Mdrx zmm3qfl!~{l4z(l-V*;;K#jt@KADaPhuGt0Q;DM^9z+Wwe0uJE9Dj8Ig%%sc0tT?TI z2g1R()T9lPS`r0Jz&%wqcx6&e^gvLR{6;+xu=xIljQM7mX46Y`rQK?Z>cCqz= zsyEpB423(qUiLk7ivL7MI1~oKi5|=|UO(aW8n2fD%-SE9DATZzUKf8KES^y&GXtp= zZHm5@L_zSG?Z8q9f}e?JF$OEwTXaEx?h+T|GI3>gQ)PIvk0LO&hKJpeE9_Z2^O^rT z=CcW5aQ`IEe3ocFi;&^58L3PXdt?ZhKP7j1*X|bIo3TugF}31M zZ^cz)fJd8gNPH>Co@v?%s3sAi7%;P4?wl1s62w@CwcR^D@A^1)RD9#sZXolK!Lr`;Uu%eoDB%cKY|TSFhZEV3FH84=OOfP0xRJ zJ&*qX@QFX#xy06YKCSQZTkcq>lY`j~{!GF6E%#4!y?nTQT;DBM;biB{@^bx*UwW`?VSZ_6n!ZQnaW*N@|Wj6uck?754{yDb)12abvH1Y{5SAsUGOX|%p%OamF zd|(%laacA;lM7x=qJSF*+-yvK{HU9NjKL^GQ&_N?L;(l}Y9Q{0=Hk>E4Hut9qcK51 zV=zgh5kqYu2+Alts%{E@%~g{qjF!S^RSeB#w>&WgKZF!8MeUU_8Zjzq&*e;WJ%-aLe7iwWV zvPmselgL9tVR2+4sD+FV%0=&ct$VLaggpFB>XQf?Y}ZN8Zn~3y4By>3@DUDe6p!o@ zR5t`SG6X0S2d#NRFAIjBuc5x-oHZy0$vz(Extt(sPg zY7&J2M<^si!EfL)tQyyg%_*=4Y%dp^^J42h>biYWY~6={Jcdq?-D8_lc2dnrL8`$A z5Tq#*R868F)!;^O8zMmCPfK9ZP@PT}EQp-n^}Fl0ZDS7SP15r|*%S2Q`qt-$ezL$F zT8e9d#C1Vo+hI>(70Rs+!BOzhozIgYeZ7c}Uzi$-?o5q>Ee#W`6HS?gwG@W6zXH*L zRl5@`#KXLQrg`q;w=quZ*ZZ5qCU~E${l0yhe7Z`$^%$t-W&wCdLbvJmS`zu_AO#0Y zsG!?vPKa7I!MB5{_lag+CLz^*9lp*22ws(>ZPHXrq5vQ`W|9QYjAjr1k4s&q;6h2+ zrXg!d6ov*~SX@D9DQIyM;t`t&#k!!4rpG2II91YrwAq!lBnt3=UnX@>B=qA3C%~0b ztSPuvOCgT~_+pBN&=x&KYyw;X7rky6Y%PWSU`4Pxj7*wT8*v+GE_J8bPI1JK>@ML+x{W0& z6H8Q#wnSxOiHaRdw4%I7(U|X9H@%u;WZk4kgqz+TzfHo9 ztHQ*aUd=F$^$5ib`-zuUGi2inR*cVo*&Ghqp*J~@o4G-WftPfEpTn7Cj)YVONvJZ3 zTs|A8FjgtYkjUrNxk7e~u$JfO8D0s-xb#dSc84o8jD_zcXu4cT^GElW`UFkm`}zb; z_rdMn3p>&TO?L-oVqW|IZ6#O!$$$QIf3rT@O495fi>r>g6JPGJ?k;}`^q<#%56|ne z9V{74gF^>+4@eQ`9W9qvI4DJjNsN%9>CX|Rs0|E{C+VhbtM<=OM_^EMfiv#3G~*z` zHk+K;KQo1&lr6qcHHFesQ+R5jrlw~~-1^g)=%8hP>ZdZcklp;~F(WYIX(v7-X0;Sb zm=VCt@RO%zh9d^|y=A?f6?Kh&*UO~G-*b!Y^>#dch$EFLTE$$i>+RJvNzyIlV`VnP zhHsYI37$nEv~Fp4?dRCO#@2uOm*msG?+r#A+T73CiQ$;|8b2z;w}d4fJ#=)TD5}*I z3Zg13Xz9NG*KxyJdD}k-*YC#P?y~>x6YqK>+hTMPhCt?bhs}Fo2pZOZ4Lqu)P~wpR z9!XP7`8~Xi-j7Yg%02C{a2#7Lh0@qG$IZi11}`ozzOv0DwqBRy$`VZ7Nbdns&a`QX zzg1Hx0i-zY({A#4f6HqL*60HjC^3>vC5i9xxbBk=<2yRWW_d9e8=~>hGD>&UvAgGl zTfKTAfp4b8)2*hE^XdhE16siO5O;guM>FEl>$iCAvuk~^se!un{lLIl=hKc|#(~vR zD2cQHqdgwGJi(UApv^gq3x^@dmY8BSg%U2{F>xW2w96(v&)j3Qgs7@16v8%wIY*79 z$#g@5gL(RYsJDy7ctnG82iHiH&z>GarItbo6>zTNSq+*SazVL&dxb8i?K27Rc!ZjC zt|>xMOQ8gXJJBn3Ii(IuOy4JExA{>Ptc2pw^0j>jGfo?8)W)IJn23y-9U8SUw63%k zk);XB!Hk!rMfp@yDBuqhy%ScXDSMf!zwdDF-FgLtT<~Q=R48BtcK)=IWD%rF0ws*VPms!{*@fdV8dD4$ zY~Odi2t}bRS}zfg;%|)hZ%x#9SAl*T>MWzw^$>CH-}9(M_|vL!-T zO`#;tVB0Gp%E_SPZ9NXwxw0)WrD_VL!GV3R3{CSoi?&|Lk#Di}IN0V*d$hF#N|=Cc zuc@7qM|K2%Q;&lsucy__i%`^3C}9D<0I1J$(ioZ=(HGd58b>hrsHdwvU6nQahVDC_ z@dsXnAuU0sY6>NeP*;|PrwMPPIYQ7Ri$$k>fPa;Q`EQeJtT)>m)el?C-_)b3d5FO~ zF``K+)>0@z4E~MbG|i(su8}9UUFSha7&r{3TruZ=03_8E3Xm{xIgB!CrrnWkI)iSA z4#_|pH^d}v2wHZo%KAe&ikN%Z39L|iYC`Z(+1i)s^R>x0rTpUiczh{8|4JlZn|z(z zA59uyEsw81>8DJd#o(A&+M?>KDda3W1EhFoiQFV6u>=dYhefR6yul)UWeYEvcMMz& zD_it`X*GqCWP`V21uy4JjyLZ{RjDcuu9iY+aA2)lQ_g&(q<@vdo6w$SzUQzbuYrOdqmnpw_w%na+)D%;H^czZkMJ$g{@vFx&Dfz{+Wmis^qTf&x zEW&Ywl3+a?X-zPee-F|mQ$3Ht^ip6EgCkS|>oG`6f${NYcJM9duW^m?Z*mu1YLh&nJYFS|>m~G}?-xO3KKJq~y!@&X?;2{B1>PN_WLf0hR?RYh zKHfJ%-hG2y`x4td>pbNhy6*k{x!+5Fy9g(84c1>b#&hk^`#>l!u}zHpp*(jc*9eQu zsU%S1OVmk~t49N7NUlEZb)coopNsE5*s{GE=z3`n(GNXhyqf|C^hi`xX z0l#zE)ADO59;EK?+0j8jW6Z8y)S#t*X)(Q;Sd@ZV3MDB>tBCQeA2im-Yp4Jg2X}-5 zVEy3I3Sc~&bNEpT-1G=du9Ou4no=k$gHKv1i>r_9=rz>IiclP(OjeIYS|^KV9h(z6 zdJSc-A|6Mmde!5Rmc8QRw|da`YxmR|3S~twj!-A72O}wz#ZOvFu(rg@#C;2YE?SN9 zGkvsOq=u?rk=K)oehn0gQDVF5S6Y^Ix8SJ^WrueQp2q&&f~PXPUS_x8soW|xT(yg| z`x2$i!H?|yD(cNftHyRJ?$*V~{`QpK+&mMgEIpb;~t41+BdG>N5Sfv_0QIuCwu*tKV z$&b@-?slKfSJ$s+KR^5G!_TRv!Tmp8P*G1mnqAO_PCr@A@Xs$-yZPqodbjw;Oi$;w z@4sfco~}1ZT?=beqGwX|Md62e_*e^x?j0_YW7nN{|om4t%?31e6HDrvdztQ zhyP!{b)P?h|M>I=Gxi6yh;{xwx2+2nTe^uc!l0otgFGL}yQ#Yc2A;Z>svGveT+B8>!6x?+M@@o{1W z$KVzPf~$!Y9I0V=Kh*+1?i`aA6)zf59)ZMoG>iv6u;Zal80M!ouiS5b|HXr@A!<2& zI=j$f`UqM%eT=QW{tWwnpY=*s!629_;zKTp1SgcPIF*hQtXr~_YG%|~^XVnD_L@yM z*mHx|^PtDxv%nTUr9@3Xi0Xudp{O#g$R&~Bh6HX%XQntGtQV9@Wrix{^a@%v-C;XF z&;_GEz>zpBgs225oAS9N608uq61AW5BB~f_x&=XNR0%bGiPt-Syk6q<6<+@n>@CyA zI@EB*sbN+_reKD_%-i-7d+zXhgY6u9Zt!}6?KSr7ED0p$Bvc9fXQkx+KuHNs4reeZ zz*mFDhSx!bG>!Xo$ z*{d4#?LtwCl4)>%nl>nt2Bp-P;Xu1VS=mpwMplirZ7yZ;F&Qm&ECew2sHY z;K9Pn+B_eqv2iVo8h?Vb^6BxcR6?QN5!5>p=p8}5BYVATd)7{WV{BnCCS7Lab4euT zG6NZv0sg<{Zi$aXFpRfu=_YVXS9ra}>npsz#_Jtk zFYtPe*DJif4El||q9X3j3jrf+id=wf5(y?jWT3To0isNz$P9G7HM-{-U3J%kj=4rx zU875Xu89rsc!CX_f{`l<@UlrH*Z{s}L!E&UgC`AerpC!p8`}ZxQ)hXO<2zO#ge9lu z$K3H6zr4ow9^1`0LT7uT9e#O%?b11NM{!AqB?WWaWl6hl1|J&?b%RE`F+QYeA7T3x zTl?uJ!KdGz42IWTVM+H75*7FN>GUDmyKm5c-aW_bPYb{%|o6MVV~KDGTOlgdcKNKgij zY1x93OCn(;D6kI9F7i%BZ6)SGq*B- zs2o3HSZt`Ii47ZpiiNyskaN&uudlIPV9ym^-(q`-Jv+SKoP28=^jHeJfX+Jjt!-2e zH82sTN{JkDNhIV@gB%pKa?pJ#c1&bN=Mx7bKxmP1$|eyX8E<6e9n~f=us8kIe1zA| zH4H=~qw`)~yK&pOf?+g8v0gTb1Sb@5LUYH7NU+Da+{bjN z^Oaeey@$RDJok6$%X7(a_$8dnC6VBqloh4UQV^QMIdGufM&i(oPt^S!ktl zkJnplcft1IGT1)c1mD_X&s&oRWz+whp<~pw0Bi$8Zw>cN&=Z>Vh5Ixneh5N%ne;O$ zB!mx946j`hkf=iU8N7Nf%2uab5{aQfU;u{M4J{fO=CUb7lQgNfjXMGh`GAie|uj_304s~{m|I> z+7)nEgKbMXR=$9v?YYK(YkTLyd+GL0Yv$ql)*E}cUIy33cco22tPs-3x+ss8O`<#D zDQg9!K&*|+W4#DGnr-VV3FqC+gMQmu&*=4$H)Nez`>FSg)@6hb*IyzL*p8ToDtRcTX0fY~GWWWk}KkmgWNyWaKGS!;fYhzuXT(w8TK%Spo{W??A`PTk_wY|Gq+B=VGShblPYKmXn z*uQt{x1F`BRH({0oaTw!yMIcwP@;+x!*180O7Te>PS3)_~3U1Pg_C)qp7z}VJB?prpA z1m76&t)ahvM;R-nFbZDe5@eG|FoN=mu%0Sbv^VJMRQ5ku7=lI+YvHkpiz+wz1b66kRc@HQ!Zch^s03}YuE2x(;l)xVypX}+8hSY9utN=nwiX|JDZ9dY?>t;;hMmTR>z_d#!+jQ`6u0NN&Y{ows?pA7FploOB zvd^x6lLq7H{eTWk)- zVPJkoqEjRc%!-z-wKn9bvmpl?uCbM`apk0kE1yp{*483lqj}!@7!1`A)2RmryEA}) zBg}u*f@%DMU-d8=CtJ!auvI|>zz&y2@5uT+=rAwZbroAqAT;N7QB^}Wi9xwiQq!v8 z8mNOBH6)!ZB{E(y2ve{s+t19UkeCykSDfmg@PFu>V3Fgk6O=x!}ZCYCbQK8 z_4GduoU!3~d{qzMk#Gj;(^{rB-3EGJtl1n0?^9*!e z%H)|4%ytZ`t?0^v2~_yD_U0|N^Vz5@=DZf%!!eI!E5FQ z8Dg39kJf#%>=I^aGM?5Z$}a+g6=lmsE{O!c2=J@tSjo^rPy!LX&}D&DE{Vj*AlMg5 zr_X(mx}h#lbA|b(ZLmds*=DGy%iP!;)H>)%C7nexHt7uUw4_D3`dkWeK0-h)i3pE- zjL1LY^eV_dej02*Zf6}wu7_lQRt|koo8j7GPktg$HbyZt*0!|9e<6&^e ze9@rovSg9*3J zCc~9c9w|rYps+I&Rrz3I`BgSw`vgvTDM!pqp4Z z&#hI<@rbovF-HN`9_kxRaa73z#9D$wtFWzSIOY#ijAf`jctlTs+x=69NkZOnj6?V` zP@w(ieHs3qZ{xyJ;d~BTb^2ZfjaXj9n6iSNWGTEvf1J$22YDF^|1!j)FXnn3fRp`2U}2kra<|*)vMqn3ncr z(<1QGzvnKvXMWVw`;4zC~g~nQ&%0fKVU*#jo9^3e$H2! zojXg{a+Cl+=!*}`vvE&OG$h3_#}@31v)A=a3*IIFhbBCoEoePJ+H&6^}H7{P$ll@6G~ zk_#Mm)8$kYpk{Wfj6-WKP?=l`UCx_Om8vDs0+o@j&h9n{kX{8rlsy7?7bJt1Cjr>? zVQ^)SoArcP9*ntw6}c2rvj;+C)imL;;6Lo_QSJbL>mFf21+tcbtd)aR*oV`~C19~f-pKyc>EsYx`0c$6jEG*5Ue5od`}h{nvbY$F|>`VpJLAtz-h?_ zfqJ=ria}c|D0(Xf>jVFa$zVH2oYa^|dqjC?Oy7wRLfqb`g%*4}3r#RX%)PdR@a=40 zLb$I%?5Ofrq9Maz-xR?Z-yg27vE@M# zuq_C-J83sT5%BE{<+n@-z#&Z+NFbL&N(2ypzcyNCpT5RqZ4C5|sDtI&7G?23WBvIY zgO|xHa2*w0N?-M9e4Nb=;<|v%xfD`tCQVgSzitdK_(Y5N#fe3Hjy>NF(074VCm^LC zx}+4CHG(?~QYKd!2UlId(_9KEp4Pxq>5E{cDg|CcstS z9#;4G9i()@_;V?w#xI-7!x*xh@Kq1niDL(9!kL4|UAvRG9t?-O9IQRjYhiPjC!b!o zxm>=_&>9HVzt}+XF8C!2#LI$T;sJPnD+^*JcJNE#nc_w8tci^n4{BW?(Oe2Ci3*Tt z`;Mjvu(U95QT;0{JhqCl<(haekteru6DM+uv)G|!7qB>&LRYA+s9AA12M+reJlzIk z+iO|KuS3M`G{5dz-43?_MN<1526h2!aw(*=k2MwZZ+&8!uYLL*Hr=~f>fo(^3s{;< zA;nS(EcNSgPPC>{r32mUbMTg(Ti$h`ogQQ1X6E6~y>;IC`Q3t=9ozT4)r||lK};72 zAeTZ)01!nm|B@p14xqBsdA2E0d>uz^TCO^D>jJLkQb=(X;t1|vhQx-)X28|=lC4rD zXFHrY40d5u93D)2yg0HcB*ejgAOzz6ok(mrv^R?5n?M{7Xa0nw=_w7Bx1FIf{?P#< zw`VPbc&*jR8nG1e4=(N{9iI<7)cd<(Chi%y+ieWLBTeButyzTibJWf3t9ZAHG>HR`xr; zEOxJL-)H!SWVpDqKyU^aZgG8O-h*sz{HbQ__7GF9eKhci8w2lZ9&I<@z>}qu6N4a> zdlU$KdYuNF?^U3F5(5-y{Bw8(Dq{xnb3Bx@e~2?6IkQ?-QZ@%r&ci|J&y(yaK!Em~ zI0FE5%ZUR7=vb~tVOXetggbt;vpX$dlclLRy&yE1@F_rg_9H$6&~rQD5a~Gr{zgr7 z{H9%N7{{^7RCR3uP_rN88E~50L54uhS-9Qr}-kdXLIlp zsW+j6JNWl}yuJTD|4OU<@A-QYnIx(iIB+F;3y zuD?I!m+ILMqzZJ0m#m=K6uMHpOe3ToRkCWB+Zb_^v&PAp2s!R~BvhJ2 zU(_&wM1Ry!@Eol)GMOPvT2O4YIPTc!Ej6?GkkvxU9Cg>(#6m8Yk|)_8z(^z#jHY%%zZGVu&d`eD^&Yk$qxc zWou7E+Y`<9joo|bVPCL6pY4nEZU6mjU%dY!xTif0jc>@y_f4WQDgYIBGCBvQu$R#R zsPMZeJ@zm*H?uvMjg^Z9ydl`uGYgv;=h|psV$ZaHa$Mq;XCW|gW+C!(w~=GK_Ah7q zqrG2ran4SHPf+o{#`fEGLb%;ed?S;Tsr}vpXkpL0TnZ`Xg=oT&L;J(eZ5Dvi`mvn> zleQh(2`Fu3WwbC>7HZW3TP5GhIN}W*ErZ4*uzCjNQb;ixjSRJt<$dOh%vMeW% zIP}4PYqVa@_7&aX(!YNKe`msj9*-;Q#a0e0+e$6OmCbrB@_Sw*#v_w@rkw$p)NeT- zAd}|7ZH`zbBrX#ovP?(<>y*cz5Xr@2JY=co;TaH1TOJ-jmX5~YYzH?UU(^ro4Dh1u z;6i-SXpGUhTEr@Oi&u;BFr}VBXFw@!8FTf@dKLCVAH(#fY_{1A+1X0K9zg z_P1&V4#)umbC)NVH3$wnf1(G4Shh_pC)1Cku~S|TsJ#H4qUW;QN58y_lX9IepYG5+ zOK3b8jg3iPEp4`cMDP$$tQ8?k0!ljwqgWOlC|Q>&VM>%-i^QwI3E{l#W2e(yq9%O~ zTC^Xbf3nsL42fZfX-h1N4kQdAVM>3)^JaaKiZ=d~Y=E&eqaSJ0e=`!+`94SP1MMm3 z96gtHk4@hO{a0wu(0&(;xgaMZbccOuooPPIb;Pphz)ZVLv(j}4)`pqY9;KR+)SP7O zG!jK?RQVt=V_9^FsYpy8oFFEzj3m?eR~Sn92N_GH@$Dn-KhcUWVMHOure7@?OxN@k zH^wEI+n7Sy6!fg5f1C0145at&ibc#IH#dU^oW@Oxe2sMJCs@Y&z)BWqzel^Uwu=~+ z(TgB$T|jl;gT_bFAY z4620aK=e3hhy8QV!?GueeWxV~of$DK&5LEx+Y*_hmpNK?nFyXj7iQ3lYlkS~9HP3; zbvBzp*=39?e`Mv+EOJJy!X7|X3*$VxRfWA%>!2CW@tT6ZxJy&K1pNSd9vI=}(wHdr z*@nYclTh!hmvhjj12gM5oNzKz`W<5Fu`D{Wc20I&##14h&nC*;IL`@Kynw|c^iul- zbPD_9@v@ttJg-`{G;Cb?e*2Kxc+GqnG?RrqMBx1Nj~ z2WNzse*;MvvYUL7BS&K8AYT;AqGz%y$a9gqa^$XzsE>^nN^23LEEJX6G1*!!OHX}U zn@2MuhsWnwMJ}}feZO+t`2>2plxf{rj%7B?vBs8Ry%dUrAgn5%bbXZLJ_r*%1)T*R z>m=|`d{mzKiz^({5st0S93Pa$MYHG#$CmUve=o0bgkGDlh%F>6VqL;wNIc~RAr#A^ z10mxwC##gM<^JwV!ty0y`I4}FjtPqadtd^0tD# z(0evZ)xUPAl4=X3L$y?4?T{23D-dTx3hZhu`d2|zSj2MZ!XhkjkS&)FWH}B=KZ-)A zeHfJaY`dtg#;N}ub%j$bhc2AL8)&KGBIP5vfCr$jKzBEBH@+m=5B{N?vg&S{ecd%e)s70_??z*y-})1arXzxvKLgbrYtgza)oVw(Sw;I_u2w4A>uz;f$)vKG zQ*!BYwJVdAm4we*6|x-Gp&=gLe_a5(5Bhimy;Pzrg|0pZdHObpoJA}>0KEb|^4|g* z@4V}c>3_jnZOj(#cWd7fUhv8`MQrjN_J3r_P1~wvrzPvclFdy^UV92_^cwh{<8mlW z4u#2~Fu7M4qD5Hxi1sKfE)8t<+gEQUa8#De~q~`eRAX? zJN^Z9f3#Za>a|9@Qfo*#zXn~ie;qDB+p^H6_%1pFEslpDgJPV;N*PY`cJ#kAthOVT zL)UhMH-gf}WSpCwv(38yGSduF|7)cRq%GVk)gXn}N^>7Pgl-$MS1p5o8(K( z`y^7zKbp>R{sTR3r*erxe@x(-qa-y)k!s!Z7VV<{3OzHl-=RH4`=Vnv`d?vHyRn5E zta>-XD=fMB2Mz4TkHKy{2Hh=thV4dirK0fp62+gnE|ET}cR;~iz!HcqYV3=rI+$BM zJuSz#yDh6AMwK`fLG)2m5dEfWe?_L&<$5xclquZYU(bRz1T0KvCxj^Gvjz^dNm_5f zK`539)x^VJ69^^-tfJP_NF=T`rup|@Jgy=1mk}lo6StfX4(|hha~ro6{oY@JZ*|6F z5bsAPlNmiC*{L6jq^52fjb=@*B{mePSuSHazrN>!q(m)2X-P?*s-{UUuou{KpSTx< zq*P2WDK#?=Uxr1AFUzE+CfrFFu;qq)`S^wwZU_M7Z-tg6w{V?vKkkjdN8w-)PtFSoueMi>;?5;W^btnGy4cm zEoKhDBAsAH;JyR`BRp;arICctL19Tpn9G=SVVQ}f1&GEfg5f-~J`E4dMndQ!b97%q zM$SMa66$nLfY>Y2B_825bCIMD+yF?#7V33G?3hoA_nvthh&V9sEfGiNBg8L*fbL-k zWH><+)S$?J3NR|bEIdgJ;G%#YWPo9)bc-y5fCZR_m!#?d8=;2=;1<*`BU%_n>c?2& zXa+JP5eRq0ASoiOfF1$6!5wNr_K^&R%$STddNO3PFOoGN5M8oAfK`H=AwtY58LS}F z7i6l!Q=cYdSJX%5uP~nyWZ)+Ckt>))M@DYbSh8+^>(pPq|DJVr*}q|g@V7(O`S`D2 znUsi7DS7Bj@*hS+LOwxpfm4t~;#7<_XPTFwk-;Q~f{ zH|80!19T5lyG^{srbAwI`*q1Li|TiXT9w1zcdT>7I{TyJ5lC5QdsOwx3NwrJI$@oi z)R5DE#%tDj!#am$w?;3#j5~@^%5x3V(Oz*u3e=X9GC_Yd`BZK>IOtj@vi9t2Qc)pux6B@KG*IC0WS-C&99rnXnms;GDX1FeYR{@mEC zg=QQDaRj68!>nN`5i6UEf~%NCy=?t=OdZ++X_$XC`VUO_^t`wjl=VYAAVlsFOq_9l zoWiD#k<*�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 delta 69940 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%0A8&K9GxlKUZ9Ovi2@r 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 From e81b5aaae6b7db13ac760e49e31445a8b61094cd Mon Sep 17 00:00:00 2001 From: Jia Zou Date: Fri, 1 May 2026 15:51:04 -0700 Subject: [PATCH 16/18] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fbf4b46..21029be 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ -# Cactusdb +# OPTBench This repository is based on https://github.com/duckdb/extension-template, check it out if you want to build and ship your own DuckDB extension. --- -This extension, Cactusdb, allow you to ... . +This extension, OPTBench, allows you to ... . ## Building ### Managing dependencies -DuckDB extensions uses VCPKG for dependency management. Enabling VCPKG is very simple: follow the [installation instructions](https://vcpkg.io/en/getting-started) or just run the following: +DuckDB extensions use VCPKG for dependency management. Enabling VCPKG is very simple: follow the [installation instructions](https://vcpkg.io/en/getting-started) or just run the following: ```shell git clone https://github.com/Microsoft/vcpkg.git ./vcpkg/bootstrap-vcpkg.sh export VCPKG_TOOLCHAIN_PATH=`pwd`/vcpkg/scripts/buildsystems/vcpkg.cmake ``` -Note: VCPKG is only required for extensions that want to rely on it for dependency management. If you want to develop an extension without dependencies, or want to do your own dependency management, just skip this step. Note that the example extension uses VCPKG to build with a dependency for instructive purposes, so when skipping this step the build may not work without removing the dependency. +Note: VCPKG is only required for extensions that want to rely on it for dependency management. If you want to develop an extension without dependencies or want to do your own dependency management, just skip this step. Note that the example extension uses VCPKG to build with a dependency for instructive purposes, so when skipping this step, the build may not work without removing the dependency. ### Build steps Now to build the extension, run: @@ -35,7 +35,7 @@ The main binaries that will be built are: ## Running the extension To run the extension code, simply start the shell with `./build/release/duckdb`. -Now we can use the features from the extension directly in DuckDB. The template contains a single scalar function `cactusdb()` that takes a string arguments and returns a string: +Now we can use the features from the extension directly in DuckDB. The template contains a single scalar function `cactusdb()` that takes a string argument and returns a string: ``` D select cactusdb('Jane') as result; ┌───────────────┐ From ba622142ea437e2c7296d76c6b8745f72b88fa80 Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 6 May 2026 12:52:32 -0700 Subject: [PATCH 17/18] make test works on existing tests --- .gitignore | 1 + CMakeLists.txt | 8 +- README.md | 54 ++++- src/optimization/register_optimizers.cpp | 8 +- test/sql/decision_forest.test | 25 --- test/sql/decision_tree.test | 110 ---------- test/sql/ml_decomposition_pushdown.test | 251 ----------------------- 7 files changed, 58 insertions(+), 399 deletions(-) delete mode 100644 test/sql/decision_forest.test delete mode 100644 test/sql/decision_tree.test delete mode 100644 test/sql/ml_decomposition_pushdown.test diff --git a/.gitignore b/.gitignore index 739dac8..9d67701 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ plans/ archived_tests/* queries/synthetic_query/*.csv queries/synthetic_query/*.db +*.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index 40b1708..b00bbb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_minimum_required(VERSION 3.5) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) # Set extension name here set(TARGET_NAME cactusdb) @@ -11,7 +13,11 @@ set(TARGET_NAME cactusdb) find_package(OpenSSL REQUIRED) find_package(Eigen3 REQUIRED) -set(Torch_DIR "/home/local/ASUAD/jrtandel/libtorch/share/cmake/Torch") +if(DEFINED ENV{LIBTORCH_DIR}) + set(Torch_DIR "$ENV{LIBTORCH_DIR}/share/cmake/Torch") +elseif(DEFINED LIBTORCH_DIR) + set(Torch_DIR "${LIBTORCH_DIR}/share/cmake/Torch") +endif() find_package(Torch REQUIRED) set(EXTENSION_NAME ${TARGET_NAME}_extension) diff --git a/README.md b/README.md index 21029be..247b5b4 100644 --- a/README.md +++ b/README.md @@ -4,18 +4,56 @@ This repository is based on https://github.com/duckdb/extension-template, check --- -This extension, OPTBench, allows you to ... . +This extension, OPTBench, is a DuckDB extension for benchmarking query optimizers. ## Building -### Managing dependencies -DuckDB extensions use VCPKG for dependency management. Enabling VCPKG is very simple: follow the [installation instructions](https://vcpkg.io/en/getting-started) or just run the following: -```shell -git clone https://github.com/Microsoft/vcpkg.git -./vcpkg/bootstrap-vcpkg.sh -export VCPKG_TOOLCHAIN_PATH=`pwd`/vcpkg/scripts/buildsystems/vcpkg.cmake +### Prerequisites +Install the following system dependencies before building: + +```sh +# Ubuntu / Debian +sudo apt install libssl-dev libeigen3-dev +``` + +### Clone with submodules +This repo uses git submodules (`duckdb` and `extension-ci-tools`). Always clone with: + +```sh +git clone --recurse-submodules +``` + +If you already cloned without submodules, run: + +```sh +git submodule update --init --recursive +``` + +### LibTorch dependency +This project requires LibTorch (the C++ PyTorch distribution). If you do not have CUDA available, download the CPU-only build: + +```sh +wget https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-2.1.2%2Bcpu.zip +unzip libtorch-cxx11-abi-shared-with-deps-2.1.2+cpu.zip -d ~/ +``` + +> **Note:** LibTorch 2.7.x prebuilt CPU binaries have internal header inconsistencies and will fail to compile. Use 2.1.2. + +Then set `LIBTORCH_DIR` before building: + +```sh +export LIBTORCH_DIR=~/libtorch +``` + +Alternatively, pass it directly to `make`: +```sh +LIBTORCH_DIR=~/libtorch make ``` -Note: VCPKG is only required for extensions that want to rely on it for dependency management. If you want to develop an extension without dependencies or want to do your own dependency management, just skip this step. Note that the example extension uses VCPKG to build with a dependency for instructive purposes, so when skipping this step, the build may not work without removing the dependency. + +> **Note:** If you switch `LIBTORCH_DIR` after a previous build, clear the CMake cache first to avoid picking up stale paths: +> ```sh +> rm -rf build/release/CMakeCache.txt build/release/CMakeFiles +> ``` ### Build steps Now to build the extension, run: diff --git a/src/optimization/register_optimizers.cpp b/src/optimization/register_optimizers.cpp index c8a7f50..594db1d 100644 --- a/src/optimization/register_optimizers.cpp +++ b/src/optimization/register_optimizers.cpp @@ -107,8 +107,8 @@ struct CactusDynamicOpt : public OptimizerExtension { static void Run(OptimizerExtensionInput &in, unique_ptr &plan) { if (!plan) return; - std::string pretty = plan->ToString(); - std::cout << "\n[CactusDynamicOpt] Initial Plan:\n" << pretty << "\n"; + // std::string pretty = plan->ToString(); + // std::cout << "\n[CactusDynamicOpt] Initial Plan:\n" << pretty << "\n"; // 1) figure out which schema this query uses string query_schema = GetQuerySchema(*plan); @@ -147,8 +147,8 @@ struct CactusDynamicOpt : public OptimizerExtension { MultiLayerUDF2TorchNNRewriteAction::apply(in, plan); } - pretty = plan->ToString(); - std::cout << "\n[CactusDynamicOpt] Final Plan:\n" << pretty << "\n"; + // pretty = plan->ToString(); + // std::cout << "\n[CactusDynamicOpt] Final Plan:\n" << pretty << "\n"; } }; diff --git a/test/sql/decision_forest.test b/test/sql/decision_forest.test deleted file mode 100644 index 49d44cf..0000000 --- a/test/sql/decision_forest.test +++ /dev/null @@ -1,25 +0,0 @@ --- queries/test_decision_forest.sql - --- Build 3 rows of 6756-dimensional feature vectors -WITH feature_rows AS ( - SELECT - id, - list(CAST(i AS FLOAT)) AS features - FROM ( - -- three ids - SELECT * FROM (VALUES (1), (2), (3)) AS ids(id), - -- 0 .. 6755 - range(0, 6756) AS r(i) - ) - GROUP BY id -) -SELECT - id, - decision_forest_predict( - features, - '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/imbridgextenx/flights/rf_dot_trees_custom', - 6756, - TRUE - ) AS pred -FROM feature_rows -ORDER BY id; diff --git a/test/sql/decision_tree.test b/test/sql/decision_tree.test deleted file mode 100644 index 8b1e8f7..0000000 --- a/test/sql/decision_tree.test +++ /dev/null @@ -1,110 +0,0 @@ -# name: test/sql/tree_predict.test -# description: test tree_predict (file + has_missing) in cactusdb extension -# group: [sql] - -require cactusdb - -statement ok -LOAD cactusdb; - -# ------------------------------------------------------------------ -# Inputs: three rows of REAL vectors (no NULLs) -# ------------------------------------------------------------------ -statement ok -CREATE TABLE inputs(a REAL[]); - -statement ok -INSERT INTO inputs VALUES ([0,0,0]), ([1,1,1]), ([10,10,10]); - -# ------------------------------------------------------------------ -# A) BASIC: call tree_predict with has_missing = FALSE -# We don't assert exact numeric values (model-dependent). -# Instead we assert row count and deterministic equality on repeat. -# ------------------------------------------------------------------ - -# Should produce 3 rows -query I -SELECT COUNT(*) FROM ( - SELECT tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) AS y - FROM inputs -); ----- -3 - -# Deterministic: same call equals itself -query I -SELECT y_eq_self -FROM ( - SELECT - tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) - = - tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) - AS y_eq_self - FROM inputs - ORDER BY 1 -); ----- -0 -1 -1 - -# ------------------------------------------------------------------ -# B) MISSING-HANDLING: include NULLs and use has_missing = TRUE -# We only assert that the function returns a non-NULL prediction. -# ------------------------------------------------------------------ - -statement ok -CREATE TABLE inputs_with_nulls(a REAL[]); - -statement ok -INSERT INTO inputs_with_nulls VALUES - ([NULL, 0.0, 1.0]), - ([2.0, NULL, 3.0]), - ([4.0, 5.0, NULL]); - -# Ensure all predictions are NOT NULL when has_missing = TRUE -query I -SELECT y_is_not_null -FROM ( - SELECT - tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', TRUE) IS NOT NULL AS y_is_not_null - FROM inputs_with_nulls - ORDER BY 1 -); ----- -true -true -true - -# ------------------------------------------------------------------ -# C) SANITY: stable across ORDER BY / re-evaluation -# Compare predictions from two identical queries (join on stable row_number) -# ------------------------------------------------------------------ - -statement ok -CREATE TEMP TABLE preds1 AS -SELECT row_number() OVER (ORDER BY a) AS rid, - tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) AS y -FROM inputs -ORDER BY rid; - -statement ok -CREATE TEMP TABLE preds2 AS -SELECT row_number() OVER (ORDER BY a) AS rid, - tree_predict(a, '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/resources/expedia/tree/0.txt', FALSE) AS y -FROM inputs -ORDER BY rid; - -# All rows should match exactly -query I -SELECT all_match -FROM ( - SELECT p1.y = p2.y AS all_match - FROM preds1 p1 - JOIN preds2 p2 USING (rid) - ORDER BY 1 -); ----- -1 -1 -1 diff --git a/test/sql/ml_decomposition_pushdown.test b/test/sql/ml_decomposition_pushdown.test deleted file mode 100644 index aa84123..0000000 --- a/test/sql/ml_decomposition_pushdown.test +++ /dev/null @@ -1,251 +0,0 @@ -# name: test/sql/ml_decomposition_pushdown.test -# description: test MLDecompositionPushdownRewriteAction with mat_mul pushdown -# group: [sql] - -require cactusdb - -statement ok -LOAD cactusdb; - -# If your optimizer needs explicit enabling, do it here. -# For example: -# statement ok -# PRAGMA enable_ml_decomposition_pushdown = true; - -statement ok -set disabled_optimizers='expression_rewriter, empty_result_pullup, cte_filter_pusher, regex_range, in_clause, join_order, deliminator, unnest_rewriter, unused_columns, statistics_propagation, common_subexpressions, common_aggregate, column_lifetime, limit_pushdown, top_n, build_side_probe_side, compressed_materialization, duplicate_groups, reorder_filter, sampling_pushdown, join_filter_pushdown, materialized_cte, sum_rewriter, late_materialization, cte_inlining'; - - -# ------------------------------------------------------------------ -# Create weights file_1.csv: 3x2 matrix -# [[0.1, 0.2], -# [0.3, 0.4], -# [0.5, 0.6]] -# ------------------------------------------------------------------ -statement ok -CREATE TEMP TABLE w1(c1 DOUBLE, c2 DOUBLE); - -statement ok -INSERT INTO w1 VALUES (0.1,0.2),(0.3,0.4),(0.5,0.6); - -statement ok -COPY w1 TO 'file_1.csv' (FORMAT CSV, HEADER FALSE); - -# ------------------------------------------------------------------ -# Create weights file_2.csv: 2x2 matrix (scale by 10) -# [[10.0, 0.0], -# [0.0, 10.0]] -# ------------------------------------------------------------------ -statement ok -CREATE TEMP TABLE w2(c1 DOUBLE, c2 DOUBLE); - -statement ok -INSERT INTO w2 VALUES (10.0,0.0),(0.0,10.0); - -statement ok -COPY w2 TO 'file_2.csv' (FORMAT CSV, HEADER FALSE); - -# ------------------------------------------------------------------ -# Inputs: three rows of vectors -# ------------------------------------------------------------------ -statement ok -CREATE TABLE inputs(a DOUBLE[]); - -statement ok -INSERT INTO inputs VALUES ([1,2,3]), ([4,5,6]), ([7,8,9]); - -# ================================================================== -# 1) Baseline: single mat_mul (a * file_1.csv, dense) -# Simple projection with one mat_mul. -# ================================================================== -query I -SELECT mat_mul(a, 'file_1.csv', 'dense') -FROM inputs; ----- -[2.2, 2.8] -[4.9, 6.3999999999999995] -[7.6, 10.0] - -# ================================================================== -# 2) Nested pipeline: mat_mul(mat_mul(a, file_1, dense), file_2, sparse) -# This is the original nested test. -# ================================================================== -query I -SELECT mat_mul(mat_mul(a, 'file_1.csv', 'dense'), - 'file_2.csv', 'sparse') AS y -FROM inputs -ORDER BY 1; ----- -[22.0, 28.0] -[49.0, 63.99999999999999] -[76.0, 100.0] - -# ================================================================== -# 3) More complex: subquery + filter + projection -# Shape: PROJECTION (outer) -> FILTER -> PROJECTION (inner) -> SCAN -# -# The rule should push mat_mul down into a lower projection while -# preserving these results. -# ================================================================== - - -# ================================================================== -# 4) Join case: projection above join -# -# - Build an inputs_with_id table with a generated id -# - Join with a small dimension table "meta" -# - Project mat_mul(i.a, ...) and a column from the right side -# -# Plan shape (rough): -# PROJECTION -# JOIN -# PROJECTION (inputs_with_id) -# SEQ_SCAN(meta) -# -# Your pushdown rule will introduce an extra PROJECTION below the -# top PROJECTION. This test just checks result correctness. -# ================================================================== - -statement ok -CREATE TABLE inputs_with_id AS -SELECT - row_number() OVER () AS id, - a -FROM inputs; - -statement ok -CREATE TABLE meta(id INTEGER, category VARCHAR); - -statement ok -INSERT INTO meta VALUES -(1, 'small'), -(2, 'medium'), -(3, 'large'); - - -# nn test -# ================================================================== -# 6) Full NN pipeline pushdown: -# mat_mul + mat_add + cdb_softmax + ml_argmax over JOIN + FILTER -# -# We build a small 2-class NN: -# logits = mat_add( mat_mul(a, W), b ) -# probs = cdb_softmax(logits) -# cls = ml_argmax(probs) -# -# W = [[ 1, -1 ], -# [ -1, 1 ]] -# b = [0, 0] -# -# This yields: -# a = [2,1] -> cls = 0 -# a = [1,3] -> cls = 1 -# a = [5,5] -> cls = 0 -# -# We then join inputs_nn with the existing `meta` table and filter -# by category, so the ML expression sits above a join+filter. -# MLDecompositionPushdownRewriteAction should treat the whole -# pipeline as one ML expression and push it down to the left -# (inputs_nn) side of the join. -# ================================================================== - -# NN weights: w_nn.csv (2x2) -statement ok -CREATE TEMP TABLE w_nn(c1 DOUBLE, c2 DOUBLE); - -statement ok -INSERT INTO w_nn VALUES - ( 1.0, -1.0), - (-1.0, 1.0); - -statement ok -COPY w_nn TO 'w_nn.csv' (FORMAT CSV, HEADER FALSE); - -# Zero biases: b_zero.csv = [0, 0] -statement ok -CREATE TEMP TABLE b_zero(c1 DOUBLE, c2 DOUBLE); - -statement ok -INSERT INTO b_zero VALUES (0.0, 0.0); - -statement ok -COPY b_zero TO 'b_zero.csv' (FORMAT CSV, HEADER FALSE); - -# Inputs for the NN (2D vectors, with ids that match the existing meta table) -# id a expected cls -# 1 [2,1] 0 -# 2 [1,3] 1 -# 3 [5,5] 0 -statement ok -CREATE TEMP TABLE inputs_nn(id INTEGER, a DOUBLE[]); - -statement ok -INSERT INTO inputs_nn VALUES - (1, [2.0, 1.0]), - (2, [1.0, 3.0]), - (3, [5.0, 5.0]); - -# ------------------------------------------------------------------ -# 6.1 Baseline: full NN on a single table (no join) -# ------------------------------------------------------------------ -query I -SELECT - ml_argmax( - cdb_softmax( - mat_add( - mat_mul(a, 'w_nn.csv', 'dense'), - 'b_zero.csv' - ) - ) - ) -FROM inputs_nn -ORDER BY id; ----- -0 -1 -0 - -# ------------------------------------------------------------------ -# 6.2 Full NN pipeline over JOIN + FILTER -# -# Plan shape (conceptually): -# -# PROJECTION (cls, category) -# FILTER (category <> 'small') -# PROJECTION ( -# cls := ml_argmax(cdb_softmax(mat_add(mat_mul(a,W),b))), -# category, -# id -# ) -# JOIN -# SCAN inputs_nn -# SCAN meta -# -# The rewrite should push the *entire* ML pipeline expression down -# to a projection sitting on top of inputs_nn (left side of the join). -# This test only checks correctness; inspect EXPLAIN manually to see -# the pushdown. -# ------------------------------------------------------------------ - - - - - -query I -SELECT - ml_argmax( - cdb_softmax( - mat_add( - mat_mul(n.a, 'w_nn.csv', 'dense'), - 'b_zero.csv' - ) - ) - ), - m.category -FROM inputs_nn n -JOIN meta m ON n.id = m.id -WHERE m.category <> 'small' -ORDER BY n.id; ----- -1 medium -0 large From 5c8e4dad13a8d99386d8bc9c174e2be5eaaf0eeb Mon Sep 17 00:00:00 2001 From: jrt1899 Date: Wed, 6 May 2026 13:31:31 -0700 Subject: [PATCH 18/18] query prepared for running --- queries/synthetic_query/synthetic_query.sql | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/queries/synthetic_query/synthetic_query.sql b/queries/synthetic_query/synthetic_query.sql index 33f3e5d..b9205d5 100644 --- a/queries/synthetic_query/synthetic_query.sql +++ b/queries/synthetic_query/synthetic_query.sql @@ -1,4 +1,4 @@ -ATTACH '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/synthetic_database.db' +ATTACH 'queries/synthetic_query/synthetic_database.db' AS synthetic_db (READ_ONLY); SET schema 'synthetic_db.synthetic'; @@ -24,15 +24,15 @@ SELECT s.search_context_vec, s.listing_feature_vec ), -- 150-dim feature vector - '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_W1.csv', + 'queries/synthetic_query/nn_params_150_512_2/nn_W1.csv', 'dense' ), - '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_b1.csv' + 'queries/synthetic_query/nn_params_150_512_2/nn_b1.csv' ), - '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_W2.csv', + 'queries/synthetic_query/nn_params_150_512_2/nn_W2.csv', 'dense' ), - '/home/local/ASUAD/jrtandel/cactusdb-duckdb-extension/queries/synthetic_query/nn_params_150_512_2/nn_b2.csv' + 'queries/synthetic_query/nn_params_150_512_2/nn_b2.csv' ) ) )

sAEw1P9^wjvw6=CkfXl=!~g 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�AlLjLP{H9vbZY- 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

f_X7%5%P)538ez-+^5K)Q8A6XX%@CtiA^`ZMhw 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%0ACk0;<`iK}9 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