From 9a9065caed9c1d762aff7c8426082fec5605a339 Mon Sep 17 00:00:00 2001 From: cameronosmith Date: Wed, 21 Apr 2021 17:30:01 -0700 Subject: [PATCH] Conditional Embeddings basic implementation --- src/API.cc | 422 +++++++++++++++++++++++++++++++++++++++++- src/API.h | 253 +++++++++++++++++++++++++ src/EDM.h | 1 + src/EDM_Formatting.cc | 33 ++++ src/EDM_Neighbors.cc | 28 +++ src/Parameter.cc | 26 +++ src/Parameter.h | 12 ++ tests/CETest.cc | 38 ++++ tests/makefile | 7 +- 9 files changed, 812 insertions(+), 8 deletions(-) create mode 100644 tests/CETest.cc diff --git a/src/API.cc b/src/API.cc index 160d09e..059e89e 100644 --- a/src/API.cc +++ b/src/API.cc @@ -1,4 +1,3 @@ - //---------------------------------------------------------------- // Functions implemented here: // Embed(), MakeBlock(), Simplex(), SMap(), CCM(), Multiview() @@ -227,13 +226,109 @@ DataFrame Simplex( DataFrame< double > & DF, bool const_predict, bool verbose ) { + + // Pass to CE Simplex + DataFrame< double > simplexProjection = Simplex( std::ref( DF ), + pathOut, + predictFile, + lib, + pred, + E, + Tp, + knn, + tau, + exclusionRadius, + colNames, + targetName, + std::vector>(),//CE assignments + std::vector>(), // CE embeddings + embedded, + const_predict, + verbose ); + + return simplexProjection; +} +//---------------------------------------------------------------------- +// Simplex with path/file input and conditional embedding +//---------------------------------------------------------------------- +DataFrame< double > Simplex( std::string pathIn, + std::string dataFile, + std::string pathOut, + std::string predictFile, + std::string lib, + std::string pred, + int E, + int Tp, + int knn, + int tau, + int exclusionRadius, + std::string colNames, + std::string targetName, + std::vector< std::vector > + embeddingAssignments, + std::vector< std::vector > embeddings, + bool embedded, + bool const_predict, + bool verbose ) +{ + // DataFrame constructor loads data + DataFrame< double > DF( pathIn, dataFile ); + + // Pass data frame to Simplex + DataFrame< double > simplexProjection = Simplex( std::ref( DF ), + pathOut, + predictFile, + lib, + pred, + E, + Tp, + knn, + tau, + exclusionRadius, + colNames, + targetName, + embeddingAssignments, + embeddings, + embedded, + const_predict, + verbose ); + + return simplexProjection; +} + +//---------------------------------------------------------------------- +// Simplex with DataFrame input and conditional embedding +//---------------------------------------------------------------------- +DataFrame Simplex( DataFrame< double > & DF, + std::string pathOut, + std::string predictFile, + std::string lib, + std::string pred, + int E, + int Tp, + int knn, + int tau, + int exclusionRadius, + std::string colNames, + std::string targetName, + std::vector< std::vector > + embeddingAssignments, + std::vector< std::vector > embeddings, + bool embedded, + bool const_predict, + bool verbose ) +{ // Instantiate Parameters Parameters parameters = Parameters( Method::Simplex, "", "", pathOut, predictFile, lib, pred, E, Tp, knn, tau, 0, exclusionRadius, colNames, targetName, embedded, - const_predict, verbose ); + const_predict, verbose, + embeddingAssignments, embeddings + ); + + // Instantiate EDM::SimplexClass object SimplexClass SimplexModel = SimplexClass( DF, std::ref( parameters ) ); @@ -242,7 +337,6 @@ DataFrame Simplex( DataFrame< double > & DF, return SimplexModel.projection; } - //---------------------------------------------------------------------------- // 1) SMap with path/file input // Default SVD (LAPACK) assigned in SMap() overload 2) @@ -307,7 +401,7 @@ SMapValues SMap( DataFrame< double > & DF, lib, pred, E, Tp, knn, tau, theta, exclusionRadius, columns, target, smapFile, derivatives, - & SVD, // LAPACK SVD default + & SVD, // LAPACK SVD default embedded, const_predict, verbose); return SMapOutput; @@ -375,13 +469,173 @@ SMapValues SMap( DataFrame< double > & DF, bool verbose ) { if ( derivatives.size() ) {} // -Wunused-parameter + + // Call overload 8) with DataFrame, solver object, and conditional emb. + SMapValues SMapOutput = SMap( std::ref( DF ), pathOut, predictFile, + lib, pred, E, Tp, knn, tau, theta, + exclusionRadius, + columns, target, smapFile, derivatives, + solver, + std::vector>(),//CE assignments + std::vector>(), // CE embeddings + embedded, const_predict, verbose ); + return SMapOutput; +} +//---------------------------------------------------------------------------- +// 5) SMap with path/file input and conditional embeddings +// Default SVD (LAPACK) assigned in SMap() overload 2) +//---------------------------------------------------------------------------- +SMapValues SMap( std::string pathIn, + std::string dataFile, + std::string pathOut, + std::string predictFile, + std::string lib, + std::string pred, + int E, + int Tp, + int knn, + int tau, + double theta, + int exclusionRadius, + std::string columns, + std::string target, + std::string smapFile, + std::string derivatives, + std::vector< std::vector > embeddingAssignments, + std::vector> conditionalEmbeddings, + bool embedded, + bool const_predict, + bool verbose ) +{ + // DataFrame constructor loads data + DataFrame< double > DF( pathIn, dataFile ); + + // Call overload 6) with DataFrame + SMapValues SMapOutput = SMap( std::ref( DF ), pathOut, predictFile, + lib, pred, E, Tp, knn, tau, theta, + exclusionRadius, + columns, target, smapFile, derivatives, + embeddingAssignments,conditionalEmbeddings, + embedded, const_predict, verbose ); + return SMapOutput; +} + +//---------------------------------------------------------------------------- +// 6) SMap with DataFrame and conditional embeddings +// Default SVD (LAPACK) assigned in Smap.cc overload 2) +//---------------------------------------------------------------------------- +SMapValues SMap( DataFrame< double > & DF, + std::string pathOut, + std::string predictFile, + std::string lib, + std::string pred, + int E, + int Tp, + int knn, + int tau, + double theta, + int exclusionRadius, + std::string columns, + std::string target, + std::string smapFile, + std::string derivatives, + std::vector< std::vector > embeddingAssignments, + std::vector> conditionalEmbeddings, + bool embedded, + bool const_predict, + bool verbose ) +{ + // Call overload 8) with default SVD function + SMapValues SMapOutput = SMap( DF, pathOut, predictFile, + lib, pred, E, Tp, knn, tau, theta, + exclusionRadius, + columns, target, smapFile, derivatives, + & SVD, // LAPACK SVD default + embeddingAssignments,conditionalEmbeddings, + embedded, const_predict, verbose); + + return SMapOutput; +} + +//---------------------------------------------------------------------------- +// 7) Data path/file with external solver object and conditional embeddings +//---------------------------------------------------------------------------- +SMapValues SMap( std::string pathIn, + std::string dataFile, + std::string pathOut, + std::string predictFile, + std::string lib, + std::string pred, + int E, + int Tp, + int knn, + int tau, + double theta, + int exclusionRadius, + std::string columns, + std::string target, + std::string smapFile, + std::string derivatives, + std::valarray< double > (*solver)(DataFrame < double >, + std::valarray < double >), + std::vector< std::vector > embeddingAssignments, + std::vector> conditionalEmbeddings, + bool embedded, + bool const_predict, + bool verbose ) +{ + // DataFrame constructor loads data + DataFrame< double > DF( pathIn, dataFile ); + + // Call overload 8) with DataFrame and solver object + SMapValues SMapOutput = SMap( std::ref( DF ), pathOut, predictFile, + lib, pred, E, Tp, knn, tau, theta, + exclusionRadius, + columns, target, smapFile, derivatives, + solver, + embeddingAssignments,conditionalEmbeddings, + embedded, const_predict, verbose ); + return SMapOutput; +} + +//---------------------------------------------------------------------------- +// 8) DataFrame with external solver object and conditional embeddings +//---------------------------------------------------------------------------- +SMapValues SMap( DataFrame< double > & DF, + std::string pathOut, + std::string predictFile, + std::string lib, + std::string pred, + int E, + int Tp, + int knn, + int tau, + double theta, + int exclusionRadius, + std::string columns, + std::string target, + std::string smapFile, + std::string derivatives, + std::valarray< double > (*solver)(DataFrame < double >, + std::valarray < double >), + std::vector< std::vector > embeddingAssignments, + std::vector> conditionalEmbeddings, + bool embedded, + bool const_predict, + bool verbose ) +{ + if ( derivatives.size() ) {} // -Wunused-parameter Parameters parameters = Parameters( Method::SMap, "", "", pathOut, predictFile, lib, pred, E, Tp, knn, tau, theta, exclusionRadius, - columns, target, embedded, - const_predict, verbose, + columns, target, + embedded, + const_predict, + verbose, + embeddingAssignments, + conditionalEmbeddings, smapFile ); // Instantiate EDM::SMapClass object @@ -395,7 +649,6 @@ SMapValues SMap( DataFrame< double > & DF, return values; } - //---------------------------------------------------------------------- // CCM with path/file input //---------------------------------------------------------------------- @@ -451,6 +704,80 @@ CCMValues CCM( DataFrame< double > & DF, bool includeData, bool verbose ) { + + // Overload to CCM with conditional embeddings + CCMValues ccmValues = CCM( std::ref( DF ), pathOut, predictFile, + E, Tp, knn, tau, exclusionRadius, + colNames, targetName, libSizes_str, + std::vector>(),//CE assignments + std::vector>(), // CE embeddings + sample, random, replacement, + seed, includeData, + verbose ); + return ccmValues; +} + +//---------------------------------------------------------------------- +// CCM with path/file input and conditional embeddings +//---------------------------------------------------------------------- +CCMValues CCM( std::string pathIn, + std::string dataFile, + std::string pathOut, + std::string predictFile, + int E, + int Tp, + int knn, + int tau, + int exclusionRadius, + std::string colNames, + std::string targetName, + std::string libSizes_str, + std::vector> embeddingAssignments, + std::vector> conditionalEmbeddings, + int sample, + bool random, + bool replacement, + unsigned seed, + bool includeData, + bool verbose ) +{ + // DataFrame constructor loads data + DataFrame< double > DF( pathIn, dataFile ); + + CCMValues ccmValues = CCM( std::ref( DF ), pathOut, predictFile, + E, Tp, knn, tau, exclusionRadius, + colNames, targetName, libSizes_str, + embeddingAssignments, conditionalEmbeddings, + sample, random, replacement, + seed, includeData, + verbose ); + + return ccmValues; +} + +//---------------------------------------------------------------------- +// CCM with DataFrame input and conditional embeddings +//---------------------------------------------------------------------- +CCMValues CCM( DataFrame< double > & DF, + std::string pathOut, + std::string predictFile, + int E, + int Tp, + int knn, + int tau, + int exclusionRadius, + std::string colNames, + std::string targetName, + std::string libSizes_str, + std::vector> embeddingAssignments, + std::vector> conditionalEmbeddings, + int sample, + bool random, + bool replacement, + unsigned seed, + bool includeData, + bool verbose ) +{ // Set library and prediction indices to entire library (embedded) std::stringstream ss; ss << "1 " << DF.NRows(); @@ -473,6 +800,8 @@ CCMValues CCM( DataFrame< double > & DF, false, // embedded false, // const_predict verbose, // + embeddingAssignments, // + conditionalEmbeddings,// "", // SmapFile "", // blockFile 0, // multiviewEnsemble @@ -499,6 +828,7 @@ CCMValues CCM( DataFrame< double > & DF, return values; } + //---------------------------------------------------------------------- // Multiview with path/file input //---------------------------------------------------------------------- @@ -556,6 +886,82 @@ MultiviewValues Multiview( DataFrame< double > & DF, bool verbose, unsigned nThreads ) { + + // Multiview overload with conditional embeddings + MultiviewValues mvValues = Multiview( std::ref( DF ), pathOut, predictFile, + lib, pred, D, E, Tp, knn, tau, + columns, target, + std::vector>(),//CE assignments + std::vector>(), // CE embeddings + multiview, exclusionRadius, trainLib, + excludeTarget, verbose, nThreads); + + return mvValues; + +} +//---------------------------------------------------------------------- +// Multiview with path/file input and conditional embeddings +//---------------------------------------------------------------------- +MultiviewValues Multiview( std::string pathIn, + std::string dataFile, + std::string pathOut, + std::string predictFile, + std::string lib, + std::string pred, + int D, + int E, + int Tp, + int knn, + int tau, + std::string columns, + std::string target, + std::vector> embeddingAssignments, + std::vector> conditionalEmbeddings, + int multiview, + int exclusionRadius, + bool trainLib, + bool excludeTarget, + bool verbose, + unsigned nThreads ) +{ + // DataFrame constructor loads data + DataFrame< double > DF( pathIn, dataFile ); + + MultiviewValues mvValues = Multiview( std::ref( DF ), pathOut, predictFile, + lib, pred, D, E, Tp, knn, tau, + columns, target, + embeddingAssignments, + conditionalEmbeddings, + multiview, exclusionRadius, trainLib, + excludeTarget, verbose, nThreads); + + return mvValues; +} + +//---------------------------------------------------------------------- +// Multiview with DataFrame input and conditional embeddings +//---------------------------------------------------------------------- +MultiviewValues Multiview( DataFrame< double > & DF, + std::string pathOut, + std::string predictFile, + std::string lib, + std::string pred, + int D, + int E, + int Tp, + int knn, + int tau, + std::string columns, + std::string target, + std::vector> embeddingAssignments, + std::vector> conditionalEmbeddings, + int multiview, + int exclusionRadius, + bool trainLib, + bool excludeTarget, + bool verbose, + unsigned nThreads ) +{ // Note: Method::Simplex & embedded = false // Parameters constructor calls Validate() // If embedded = true: Validate() will set E to number of columns @@ -578,6 +984,8 @@ MultiviewValues Multiview( DataFrame< double > & DF, false, // embedded false false, // const_predict verbose, // + embeddingAssignments, // + conditionalEmbeddings, // "", // SmapFile "", // blockFile multiview, // multiviewEnsemble, diff --git a/src/API.h b/src/API.h index 5864d9a..d7c1858 100644 --- a/src/API.h +++ b/src/API.h @@ -16,6 +16,9 @@ // file image on disk to be loaded and converted to a data frame. // The second replaces these two arguments with a DataFrame object. // +// Edit: Now we support conditional embeddings so each signature has a paired +// conditional embedding version. +// // NOTE: These are the first declarations seen by the compiler // for the API and provide default argument values //------------------------------------------------------------- @@ -72,6 +75,51 @@ DataFrame< double > Simplex( DataFrame< double > & dataFrameIn, bool const_predict = false, bool verbose = true ); +DataFrame< double > Simplex( std::string pathIn = "./data/", + std::string dataFile = "", + std::string pathOut = "./", + std::string predictFile = "", + std::string lib = "", + std::string pred = "", + int E = 0, + int Tp = 1, + int knn = 0, + int tau = -1, + int exclusionRadius = 0, + std::string colNames = "", + std::string targetName = "", + std::vector> + embeddingAssignments = + std::vector< std::vector >(), + std::vector> + conditionalEmbeddings = + std::vector< std::vector >(), + bool embedded = false, + bool const_predict = false, + bool verbose = true ); + +DataFrame< double > Simplex( DataFrame< double > & dataFrameIn, + std::string pathOut = "./", + std::string predictFile = "", + std::string lib = "", + std::string pred = "", + int E = 0, + int Tp = 1, + int knn = 0, + int tau = -1, + int exclusionRadius = 0, + std::string colNames = "", + std::string targetName = "", + std::vector< std::vector > + embeddingAssignments = + std::vector< std::vector >(), + std::vector> + conditionalEmbeddings = + std::vector< std::vector >(), + bool embedded = false, + bool const_predict = false, + bool verbose = true ); + // SMap is a special case since it can be called with a function pointer // to the SVD solver. This is done so that interfaces such as pybind11 // can provide their own object for the solver. @@ -163,6 +211,114 @@ SMapValues SMap( DataFrame< double > &dataFrameIn, bool const_predict = false, bool verbose = true ); +// 5) Data path/file with default SVD (LAPACK) assigned in Smap.cc 6) and +// conditional embeddings +SMapValues SMap( std::string pathIn = "./data/", + std::string dataFile = "", + std::string pathOut = "./", + std::string predictFile = "", + std::string lib = "", + std::string pred = "", + int E = 0, + int Tp = 1, + int knn = 0, + int tau = -1, + double theta = 0, + int exclusionRadius = 0, + std::string columns = "", + std::string target = "", + std::string smapFile = "", + std::string derivatives = "", + std::vector> embeddingAssignments = + std::vector< std::vector >(), + std::vector> conditionalEmbeddings = + std::vector< std::vector >(), + bool embedded = false, + bool const_predict = false, + bool verbose = true ); + +// 6) DataFrame with default SVD (LAPACK) assigned in Smap.cc and conditional +// embeddings +SMapValues SMap( DataFrame< double > &dataFrameIn, + std::string pathOut = "./", + std::string predictFile = "", + std::string lib = "", + std::string pred = "", + int E = 0, + int Tp = 1, + int knn = 0, + int tau = -1, + double theta = 0, + int exclusionRadius = 0, + std::string columns = "", + std::string target = "", + std::string smapFile = "", + std::string derivatives = "", + std::vector> embeddingAssignments = + std::vector< std::vector >(), + std::vector> conditionalEmbeddings = + std::vector< std::vector >(), + bool embedded = false, + bool const_predict = false, + bool verbose = true ); + +// 7) Data path/file with external solver object, init to default SVD and +// conditional embeddings +SMapValues SMap( std::string pathIn = "./data/", + std::string dataFile = "", + std::string pathOut = "./", + std::string predictFile = "", + std::string lib = "", + std::string pred = "", + int E = 0, + int Tp = 1, + int knn = 0, + int tau = -1, + double theta = 0, + int exclusionRadius = 0, + std::string columns = "", + std::string target = "", + std::string smapFile = "", + std::string derivatives = "", + std::valarray< double > (*solver) + (DataFrame < double >, + std::valarray < double >) = & SVD, + std::vector> embeddingAssignments = + std::vector< std::vector >(), + std::vector> conditionalEmbeddings = + std::vector< std::vector >(), + bool embedded = false, + bool const_predict = false, + bool verbose = true ); + +// 8) DataFrame with external solver object, init to default SVD and conditional +// embeddings and conditional embeddings +SMapValues SMap( DataFrame< double > &dataFrameIn, + std::string pathOut = "./", + std::string predictFile = "", + std::string lib = "", + std::string pred = "", + int E = 0, + int Tp = 1, + int knn = 0, + int tau = -1, + double theta = 0, + int exclusionRadius = 0, + std::string columns = "", + std::string target = "", + std::string smapFile = "", + std::string derivatives = "", + std::valarray< double > (*solver) + (DataFrame < double >, + std::valarray < double >) = & SVD, + std::vector> embeddingAssignments = + std::vector< std::vector >(), + std::vector> conditionalEmbeddings = + std::vector< std::vector >(), + bool embedded = false, + bool const_predict = false, + bool verbose = true ); + CCMValues CCM( std::string pathIn = "./data/", std::string dataFile = "", std::string pathOut = "./", @@ -200,6 +356,91 @@ CCMValues CCM( DataFrame< double > & dataFrameIn, bool includeData = false, bool verbose = true ); +CCMValues CCM( std::string pathIn = "./data/", + std::string dataFile = "", + std::string pathOut = "./", + std::string predictFile = "", + int E = 0, + int Tp = 0, + int knn = 0, + int tau = -1, + int exclusionRadius = 0, + std::string colNames = "", + std::string targetName = "", + std::string libSizes_str = "", + std::vector> embeddingAssignments = + std::vector< std::vector >(), + std::vector> conditionalEmbeddings = + std::vector< std::vector >(), + int sample = 0, + bool random = true, + bool replacement = false, + unsigned seed = 0, // seed=0: use RNG + bool includeData = false, + bool verbose = true ); + +CCMValues CCM( DataFrame< double > & dataFrameIn, + std::string pathOut = "./", + std::string predictFile = "", + int E = 0, + int Tp = 0, + int knn = 0, + int tau = -1, + int exclusionRadius = 0, + std::string colNames = "", + std::string targetName = "", + std::string libSizes_str = "", + std::vector> embeddingAssignments = + std::vector< std::vector >(), + std::vector> conditionalEmbeddings = + std::vector< std::vector >(), + int sample = 0, + bool random = true, + bool replacement = false, + unsigned seed = 0, // seed=0: use RNG + bool includeData = false, + bool verbose = true ); + +MultiviewValues Multiview( std::string pathIn = "./", + std::string dataFile = "", + std::string pathOut = "./", + std::string predictFile = "", + std::string lib = "", + std::string pred = "", + int D = 0, + int E = 1, + int Tp = 1, + int knn = 0, + int tau = -1, + std::string columns = "", + std::string target = "", + int multiview = 0, + int exclusionRadius = 0, + bool trainLib = true, + bool excludeTarget = false, + bool verbose = false, + unsigned nThreads = 4 ); + +MultiviewValues Multiview( DataFrame< double > & dataFrameIn, + std::string pathOut = "./", + std::string predictFile = "", + std::string lib = "", + std::string pred = "", + int D = 0, + int E = 1, + int Tp = 1, + int knn = 0, + int tau = -1, + std::string columns = "", + std::string target = "", + int multiview = 0, + int exclusionRadius = 0, + bool trainLib = true, + bool excludeTarget = false, + bool verbose = false, + unsigned nThreads = 4 ); + + MultiviewValues Multiview( std::string pathIn = "./", std::string dataFile = "", std::string pathOut = "./", @@ -213,6 +454,12 @@ MultiviewValues Multiview( std::string pathIn = "./", int tau = -1, std::string columns = "", std::string target = "", + std::vector> + embeddingAssignments = + std::vector< std::vector >(), + std::vector> + conditionalEmbeddings = + std::vector< std::vector >(), int multiview = 0, int exclusionRadius = 0, bool trainLib = true, @@ -232,6 +479,12 @@ MultiviewValues Multiview( DataFrame< double > & dataFrameIn, int tau = -1, std::string columns = "", std::string target = "", + std::vector> + embeddingAssignments = + std::vector< std::vector >(), + std::vector> + conditionalEmbeddings = + std::vector< std::vector >(), int multiview = 0, int exclusionRadius = 0, bool trainLib = true, diff --git a/src/EDM.h b/src/EDM.h index c2dfcb4..c556f66 100644 --- a/src/EDM.h +++ b/src/EDM.h @@ -67,6 +67,7 @@ class EDM { // EDM_Formatting.cc void CheckDataRows( std::string call ); + void CheckConditionalEmbeddings( std::string call ); void RemovePartialData(); void FormatOutput(); void FillTimes( std::vector< std::string > & timeOut ); diff --git a/src/EDM_Formatting.cc b/src/EDM_Formatting.cc index 128cc43..8b668a8 100644 --- a/src/EDM_Formatting.cc +++ b/src/EDM_Formatting.cc @@ -40,6 +40,39 @@ void EDM::CheckDataRows( std::string call ) } } +//---------------------------------------------------------- +// Validate conditional embeddings +//---------------------------------------------------------- +void EDM::CheckConditionalEmbeddings( std::string call ) +{ + + size_t library_max_i = parameters.library.back(); + + // The embedding assignment should have data.NRows() + if ( parameters.embeddingAssignments.size() < data.NRows() ){ + std::stringstream errMsg; + errMsg << "CheckConditionalEmbeddings(): " << call + << ": The number of elements in the embedding assignment" + << parameters.embeddingAssignments.size() + << " is less than the number of data rows " + << data.NRows(); + throw std::runtime_error( errMsg.str() ); + } + + // Each embedding should have size at least equal to the library + for ( auto embedding : parameters.conditionalEmbeddings ) { + if ( embedding.size() < library_max_i ) { + std::stringstream errMsg; + errMsg << "CheckConditionalEmbeddings(): " << call + << ": A specified conditional embedding of length " + << embedding.size() + << " is less than the maximum library index " + << library_max_i; + throw std::runtime_error( errMsg.str() ); + } + } +} + //---------------------------------------------------------- // Common code for Simplex and Smap output generation //---------------------------------------------------------- diff --git a/src/EDM_Neighbors.cc b/src/EDM_Neighbors.cc index 10cee4b..ec9c67a 100644 --- a/src/EDM_Neighbors.cc +++ b/src/EDM_Neighbors.cc @@ -25,6 +25,9 @@ void EDM::PrepareEmbedding( bool checkDataRows ) { if ( checkDataRows ) { CheckDataRows( "PrepareEmbedding" ); + if ( parameters.embeddingAssignments.size() ) { + CheckConditionalEmbeddings( "PrepareEmbedding" ); + } } // 1) Extract or Embed() data into embedding @@ -184,6 +187,31 @@ void EDM::FindNeighbors() { } } + // Conditional embedding: library point not in embedding + if ( parameters.embeddingAssignments.size() ) { + + auto embIdxs = parameters.embeddingAssignments[predictionRow]; + + bool validRow = true; + + for ( auto embIdx : embIdxs ) { + + auto embedding = parameters.conditionalEmbeddings[embIdx]; + +#ifdef DEBUG_ALL + if ( not embedding[libRow] ) { + std::cout<<"at pred row "< > embeddingAssignments, + std::vector< std::vector > conditionalEmbeddings, + std::string SmapOutputFile, std::string blockOutputFile, @@ -39,6 +42,7 @@ Parameters::Parameters( std::string libSizes_str, int subSamples, + bool randomLib, bool replacement, unsigned seed, @@ -69,6 +73,9 @@ Parameters::Parameters( const_predict ( const_predict ), verbose ( verbose ), + embeddingAssignments (embeddingAssignments), + conditionalEmbeddings (conditionalEmbeddings), + SmapOutputFile ( SmapOutputFile ), blockOutputFile ( blockOutputFile ), @@ -566,6 +573,25 @@ void Parameters::Validate() { } } + //--------------------------------------------------------------- + // Embedding assignments should not exceed number of embeddings + //--------------------------------------------------------------- + for ( size_t i = 0; i < embeddingAssignments.size(); i++ ) { + for ( size_t embeddingIdx : embeddingAssignments[i] ) { + + if ( embeddingIdx > conditionalEmbeddings.size() ) { + std::stringstream errMsg; + errMsg<< "Parameters::Validate(): " + << "Embedding assignment of " << embeddingIdx + << " at index " << i + << " exceeds than the number of conditional embeddings " + << conditionalEmbeddings.size() + << ".\n"; + throw std::runtime_error( errMsg.str() ); + } + } + } + #ifdef DEBUG_ALL PrintIndices( library, prediction ); #endif diff --git a/src/Parameter.h b/src/Parameter.h index 4334cda..ab70bab 100644 --- a/src/Parameter.h +++ b/src/Parameter.h @@ -45,6 +45,11 @@ class Parameters { bool const_predict; // true to compute non "predictor" stats bool verbose; + // maps row to conditional embedding index + std::vector< std::vector > embeddingAssignments; + // list of conditional embeddings + std::vector< std::vector > conditionalEmbeddings; + std::string SmapOutputFile; // std::string blockOutputFile; // Embed() output file @@ -92,6 +97,12 @@ class Parameters { bool const_predict = false, bool verbose = false, + + std::vector< std::vector > + embeddingAssignments = std::vector< std::vector >(), + std::vector< std::vector > conditionalEmbeddings = std::vector< + std::vector >(), + std::string SmapOutputFile = "", std::string blockOutputFile = "", @@ -106,6 +117,7 @@ class Parameters { bool replacement = false, unsigned seed = 0, // 0: Generate random seed in CCM bool includeData = false + ); ~Parameters(); diff --git a/tests/CETest.cc b/tests/CETest.cc new file mode 100644 index 0000000..e181ad6 --- /dev/null +++ b/tests/CETest.cc @@ -0,0 +1,38 @@ +// Program to test the conditional embeddings functionality +// No ground truth to test on, so just checking for valid functionality here + +#include +#include +#include "TestCommon.h" + +int main() { + + DataFrame < double > circleData( "../data/", "circle.csv" ); + + size_t num_rows = 200; + + // The full and partial embeddings + std::vector full_embedding (num_rows,true); + std::vector partial_embedding_1 (num_rows,true); + std::vector partial_embedding_2 (num_rows,true); + for (int i=40;i<42;i++) partial_embedding_1[i] = false; + for (int i=40;i<42;i++) partial_embedding_2[i] = false; + + // The embedding assignment + std::vector> emb_assignment (num_rows); + for (int i=110;i<111;i++) emb_assignment[i] = {1}; + for (int i=101;i<103;i++) emb_assignment[i] = {2}; + for (int i=112;i<115;i++) emb_assignment[i] = {1,2}; + + std::vector> embeddings = + {full_embedding, partial_embedding_1,partial_embedding_2}; + + SMapValues smapVals = SMap ( circleData, + "./data/", "", + " 1 100 ", "101 198", 2, 1, 0, -1, 4, 0, + "x y", "x", "Smap_circle_coef.csv", "", + emb_assignment, + embeddings, + true, false, false ); + +} diff --git a/tests/makefile b/tests/makefile index 42edf73..460330c 100644 --- a/tests/makefile +++ b/tests/makefile @@ -1,7 +1,7 @@ CC = g++ -EXE = SimplexTest TestCommonTest SMapTest CCMTest MultiviewTest DateTimeTest +EXE = SimplexTest TestCommonTest SMapTest CCMTest MultiviewTest DateTimeTest CETest OBJ = $(EXE:=.o) TestCommon.o CFLAGS = -std=c++11 -D PRINT_DIFFERENCE_IN_RESULTS @@ -34,6 +34,10 @@ MultiviewTest: MultiviewTest.cc $(CC) TestCommon.cc -c $(CFLAGS) $(LFLAGS) $(CC) $@.cc -o $@ $(CFLAGS) $(LFLAGS) TestCommon.o +CETest: CETest.cc + $(CC) TestCommon.cc -c $(CFLAGS) $(LFLAGS) + $(CC) $@.cc -o $@ $(CFLAGS) $(LFLAGS) TestCommon.o + clean: rm -f TestCommon.o $(OBJ) $(EXE) @@ -53,3 +57,4 @@ SMapTest.o: TestCommon.h CCMTest.o: TestCommon.h MultiviewTest.o: TestCommon.h DateTimeTest.o: TestCommon.h +CETest.o: TestCommon.h