From 1505021d47aba27a501d2eacd2a878f172ccdd71 Mon Sep 17 00:00:00 2001 From: ajinkyaghonge Date: Wed, 5 Apr 2023 13:10:47 -0700 Subject: [PATCH] Add classes to parse PC Instruction set. Differential Revision: D44618035 fbshipit-source-id: e2536628e08b76ee0adbb484c8d8417bef25ced0 --- fbpcs/pc_translator/PCTranslator.cpp | 58 +++++++++++++++---- fbpcs/pc_translator/PCTranslator.h | 20 +++++-- .../input_processing/FilterConstraint.cpp | 33 +++++++++++ .../input_processing/FilterConstraint.h | 43 ++++++++++++++ .../input_processing/PCInstructionSet.cpp | 51 ++++++++++++++++ .../input_processing/PCInstructionSet.h | 47 +++++++++++++++ .../input_processing/TestPCInstructionSet.cpp | 44 ++++++++++++++ .../test_instruction_set.json | 45 ++++++++++++++ 8 files changed, 324 insertions(+), 17 deletions(-) create mode 100644 fbpcs/pc_translator/input_processing/FilterConstraint.cpp create mode 100644 fbpcs/pc_translator/input_processing/FilterConstraint.h create mode 100644 fbpcs/pc_translator/input_processing/PCInstructionSet.cpp create mode 100644 fbpcs/pc_translator/input_processing/PCInstructionSet.h create mode 100644 fbpcs/pc_translator/tests/input_processing/TestPCInstructionSet.cpp create mode 100644 fbpcs/pc_translator/tests/input_processing/test_instruction_set.json diff --git a/fbpcs/pc_translator/PCTranslator.cpp b/fbpcs/pc_translator/PCTranslator.cpp index abc23e908..6c6ee7e07 100644 --- a/fbpcs/pc_translator/PCTranslator.cpp +++ b/fbpcs/pc_translator/PCTranslator.cpp @@ -6,11 +6,22 @@ */ #include "fbpcs/pc_translator/PCTranslator.h" +#include "fbpcs/pc_translator/input_processing/PCInstructionSet.h" + +#include +#include +#include +#include "folly/String.h" namespace pc_translator { -std::string PCTranslator::encode(const std::string& /* inputDataset */) { - throw std::runtime_error("Unimplemented"); +std::string PCTranslator::encode(const std::string& inputDataset) { + auto validInstructionSetNames = + PCTranslator::retrieveInstructionSetNamesForRun(pcsFeatures_); + auto pcInstructionSets = + PCTranslator::retrieveInstructionSets(validInstructionSetNames); + PCTranslator::transformDataset(inputDataset, pcInstructionSets); + return ""; } std::string PCTranslator::decode( @@ -18,22 +29,47 @@ std::string PCTranslator::decode( throw std::runtime_error("Unimplemented"); } -void PCTranslator::retrieveInstructionSets( - std::vector& /* instructionSetNames */) { - throw std::runtime_error("Unimplemented"); +std::vector> +PCTranslator::retrieveInstructionSets( + std::vector& instructionSetNames) { + std::vector> pcInstructionSets; + for (auto instructionSetName : instructionSetNames) { + auto file_path = instructionSetBasePath + instructionSetName + ".json"; + auto contents = fbpcf::io::FileIOWrappers::readFile(file_path); + pcInstructionSets.push_back(PCTranslator::parseInstructionSet(contents)); + } + return pcInstructionSets; } std::vector PCTranslator::retrieveInstructionSetNamesForRun( - const std::string& /* pcsFeatures */) { - throw std::runtime_error("Unimplemented"); + const std::string& pcsFeatures) { + std::set enabledFeatureFlags; + folly::splitTo( + ',', + pcsFeatures, + std::inserter(enabledFeatureFlags, enabledFeatureFlags.begin()), + true); + + std::vector validPCInstructionSets; + std::copy_if( + enabledFeatureFlags.begin(), + enabledFeatureFlags.end(), + std::back_inserter(validPCInstructionSets), + [](const std::string& feature) { return feature.find("pc_instr") == 0; }); + + return validPCInstructionSets; } -void PCTranslator::transformDataset(const std::string& /* input */) { +void PCTranslator::transformDataset( + const std::string& /* inputData */, + const std::vector>& + pcInstructionSets) { throw std::runtime_error("Unimplemented"); } -void PCTranslator::parseInstructionSet( - const std::string& /* instructionSet */) { - throw std::runtime_error("Unimplemented"); +std::shared_ptr PCTranslator::parseInstructionSet( + const std::string& instructionSet) { + return std::make_shared(PCInstructionSet::fromDynamic( + folly::parseJson(std::move(instructionSet)))); } } // namespace pc_translator diff --git a/fbpcs/pc_translator/PCTranslator.h b/fbpcs/pc_translator/PCTranslator.h index 0107e4025..ed59d6915 100644 --- a/fbpcs/pc_translator/PCTranslator.h +++ b/fbpcs/pc_translator/PCTranslator.h @@ -11,6 +11,7 @@ #include #include #include +#include "fbpcs/pc_translator/input_processing/PCInstructionSet.h" namespace pc_translator { @@ -23,7 +24,7 @@ namespace pc_translator { class PCTranslator { public: explicit PCTranslator(const std::string& pcsFeatures) - : pcsfeatures_(pcsFeatures) {} + : pcsFeatures_(pcsFeatures) {} /* * Method to encode the configurable fields in input dataset as per the active @@ -41,12 +42,19 @@ class PCTranslator { std::string decode(const std::string& aggregatedOutputDataset); private: - std::string pcsfeatures_; - void retrieveInstructionSets(std::vector& instructionSetNames); + std::string pcsFeatures_; + const std::string instructionSetBasePath = + "https://pc-translator.s3.us-west-2.amazonaws.com/"; + std::vector> retrieveInstructionSets( + std::vector& instructionSetNames); std::vector retrieveInstructionSetNamesForRun( - const std::string& pcsfeatures); - void parseInstructionSet(const std::string& instructionSet); - void transformDataset(const std::string& input); + const std::string& pcsFeatures); + std::shared_ptr parseInstructionSet( + const std::string& instructionSet); + void transformDataset( + const std::string& input_data, + const std::vector>& + pcInstructionSets); }; } // namespace pc_translator diff --git a/fbpcs/pc_translator/input_processing/FilterConstraint.cpp b/fbpcs/pc_translator/input_processing/FilterConstraint.cpp new file mode 100644 index 000000000..6bc8a0dac --- /dev/null +++ b/fbpcs/pc_translator/input_processing/FilterConstraint.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "fbpcs/pc_translator/input_processing/FilterConstraint.h" + +#include +#include +#include +#include + +namespace pc_translator { +FilterConstraint::FilterConstraint( + const std::string& name, + const std::string& type, + int value) + : name_(name), type_(type), value_(value) {} + +std::string FilterConstraint::getName() const { + return name_; +} + +std::string FilterConstraint::getType() const { + return type_; +} + +int FilterConstraint::getValue() const { + return value_; +} +} // namespace pc_translator diff --git a/fbpcs/pc_translator/input_processing/FilterConstraint.h b/fbpcs/pc_translator/input_processing/FilterConstraint.h new file mode 100644 index 000000000..00cbbc189 --- /dev/null +++ b/fbpcs/pc_translator/input_processing/FilterConstraint.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include + +namespace pc_translator { + +/* + * Class to store each filter constraint include in the PC instruction set. + */ +class FilterConstraint { + public: + FilterConstraint(const std::string& name, const std::string& type, int value); + + /* + * Name of the filter constraint i.e. the field on which this filter is to be + * applied. + */ + std::string getName() const; + + /* + * Constraint type i.e. LT, LTE, EQ, NEQ etc. + */ + std::string getType() const; + + int getValue() const; + + private: + std::string name_; + std::string type_; + int value_; +}; + +} // namespace pc_translator diff --git a/fbpcs/pc_translator/input_processing/PCInstructionSet.cpp b/fbpcs/pc_translator/input_processing/PCInstructionSet.cpp new file mode 100644 index 000000000..bd1c995d8 --- /dev/null +++ b/fbpcs/pc_translator/input_processing/PCInstructionSet.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "fbpcs/pc_translator/input_processing/PCInstructionSet.h" + +#include +#include +#include +#include +#include + +namespace pc_translator { + +const std::vector& PCInstructionSet::getGroupByIds() const { + return groupByIds; +} + +const std::vector& PCInstructionSet::getFilterConstraints() + const { + return filterConstraints; +} + +PCInstructionSet PCInstructionSet::fromDynamic(const folly::dynamic& obj) { + PCInstructionSet pcInstructionSet; + auto aggregationConfig = obj["aggregated_metrics"]; + auto groupByFields = aggregationConfig["group_by"]; + + for (auto groupByField : groupByFields) { + pcInstructionSet.groupByIds.push_back(groupByField.asString()); + } + + auto filterConstraintsFields = aggregationConfig["filter"]; + + for (auto& [key, constraints] : filterConstraintsFields.items()) { + std::string name = key.asString(); + for (auto constraint : constraints) { + auto constraintType = constraint["constraint_type"].asString(); + auto constraintValue = constraint["value"].asInt(); + FilterConstraint filterConstraint(name, constraintType, constraintValue); + pcInstructionSet.filterConstraints.push_back(filterConstraint); + } + } + + return pcInstructionSet; +} + +} // namespace pc_translator diff --git a/fbpcs/pc_translator/input_processing/PCInstructionSet.h b/fbpcs/pc_translator/input_processing/PCInstructionSet.h new file mode 100644 index 000000000..01e710f54 --- /dev/null +++ b/fbpcs/pc_translator/input_processing/PCInstructionSet.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "fbpcs/pc_translator/input_processing/FilterConstraint.h" + +namespace pc_translator { + +/* + * Class to store PC Instruction set. This class contains a list of group Ids as + * well as list of filter constraints. + */ +class PCInstructionSet { + public: + /* + * Method to all group Ids from the PC instruction set. + */ + const std::vector& getGroupByIds() const; + + /* + * Method to get all filter constraints from PC instruction set. + */ + const std::vector& getFilterConstraints() const; + + /* + * Method to get parse and create PCInstructionSet instance. + */ + static PCInstructionSet fromDynamic(const folly::dynamic& obj); + + private: + std::vector groupByIds; + std::vector filterConstraints; + + void parseJson(const std::string& json); +}; + +} // namespace pc_translator diff --git a/fbpcs/pc_translator/tests/input_processing/TestPCInstructionSet.cpp b/fbpcs/pc_translator/tests/input_processing/TestPCInstructionSet.cpp new file mode 100644 index 000000000..32a38ff3a --- /dev/null +++ b/fbpcs/pc_translator/tests/input_processing/TestPCInstructionSet.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include +#include + +#include +#include +#include "../../../emp_games/common/TestUtil.h" +#include "fbpcs/pc_translator/input_processing/PCInstructionSet.h" +#include "folly/Random.h" + +namespace pc_translator { +class TestPCInstructionSet : public ::testing::Test { + public: + protected: + std::string testInstructionSetPath_; + + void SetUp() override { + std::string baseDir = + private_measurement::test_util::getBaseDirFromPath(__FILE__); + testInstructionSetPath_ = baseDir + "test_instruction_set.json"; + } +}; + +TEST_F(TestPCInstructionSet, TestStandardWorkflowTest) { + auto pcInstructionSet = std::make_shared( + PCInstructionSet::fromDynamic(folly::parseJson( + fbpcf::io::FileIOWrappers::readFile(testInstructionSetPath_)))); + auto groupByIds = pcInstructionSet->getGroupByIds(); + auto filterConstraints = pcInstructionSet->getFilterConstraints(); + EXPECT_EQ(groupByIds.size(), 2); + EXPECT_EQ(filterConstraints.size(), 4); + EXPECT_EQ(filterConstraints[0].getName(), "gender"); + EXPECT_EQ(filterConstraints[0].getType(), "EQ"); + EXPECT_EQ(filterConstraints[0].getValue(), 0); +} + +} // namespace pc_translator diff --git a/fbpcs/pc_translator/tests/input_processing/test_instruction_set.json b/fbpcs/pc_translator/tests/input_processing/test_instruction_set.json new file mode 100644 index 000000000..7a0008b19 --- /dev/null +++ b/fbpcs/pc_translator/tests/input_processing/test_instruction_set.json @@ -0,0 +1,45 @@ +{ + "publisher_input": { + "num_impressions": "int", + "num_clicks": "int", + "total_spend": "int", + "opportunity_timstamp": "int", + "test_flag": "int", + "age": "int", + "gender": "Optional[int]", + "breakdown_id": "Optional[int]" + }, + "partner_input": { + "value": "int", + "event_timestamp": "int", + "partner_cohort_id": "Optional[int]" + }, + "aggregated_metrics": { + "filter": { + "age": [ + { + "constraint_type": "GTE", + "value": "25" + }, + { + "constraint_type": "LTE", + "value": "40" + } + ], + "gender": [ + { + "constraint_type": "EQ", + "value": "0" + }, + { + "constraint_type": "EQ", + "value": "1" + } + ] + }, + "group_by": [ + "age", + "gender" + ] + } +}