2222#include " IndexIVF.h"
2323#include " IndexIVFPQ.h"
2424#include " MetaIndexes.h"
25- #include " IndexIVFScalarQuantizer .h"
25+ #include " IndexScalarQuantizer .h"
2626
2727
2828namespace faiss {
@@ -623,18 +623,28 @@ void ParameterSpace::explore (Index *index,
623623 * index_factory
624624 ***************************************************************/
625625
626+ namespace {
626627
628+ struct VTChain {
629+ std::vector<VectorTransform *> chain;
630+ ~VTChain () {
631+ for (int i = 0 ; i < chain.size (); i++) {
632+ delete chain[i];
633+ }
634+ }
635+ };
636+
637+ }
627638
628639Index *index_factory (int d, const char *description_in, MetricType metric)
629640{
630- VectorTransform *vt = nullptr ;
641+ VTChain vts ;
631642 Index *coarse_quantizer = nullptr ;
632643 Index *index = nullptr ;
633644 bool add_idmap = false ;
634645 bool make_IndexRefineFlat = false ;
635646
636647 ScopeDeleter1<Index> del_coarse_quantizer, del_index;
637- ScopeDeleter1<VectorTransform> del_vt;
638648
639649 char description[strlen (description_in) + 1 ];
640650 char *ptr;
@@ -656,18 +666,27 @@ Index *index_factory (int d, const char *description_in, MetricType metric)
656666 Index *index_1 = nullptr ;
657667
658668 // VectorTransforms
659- if (!vt && sscanf (tok, " PCA%d" , &d_out) == 1 ) {
669+ if (sscanf (tok, " PCA%d" , &d_out) == 1 ) {
660670 vt_1 = new PCAMatrix (d, d_out);
661671 d = d_out;
662- } else if (!vt && sscanf (tok, " PCAR%d" , &d_out) == 1 ) {
672+ } else if (sscanf (tok, " PCAR%d" , &d_out) == 1 ) {
663673 vt_1 = new PCAMatrix (d, d_out, 0 , true );
664674 d = d_out;
665- } else if (!vt && sscanf (tok, " OPQ%d_%d" , &opq_M, &d_out) == 2 ) {
675+ } else if (sscanf (tok, " PCAW%d" , &d_out) == 1 ) {
676+ vt_1 = new PCAMatrix (d, d_out, -0.5 , false );
677+ d = d_out;
678+ } else if (sscanf (tok, " PCAWR%d" , &d_out) == 1 ) {
679+ vt_1 = new PCAMatrix (d, d_out, -0.5 , true );
680+ d = d_out;
681+ } else if (sscanf (tok, " OPQ%d_%d" , &opq_M, &d_out) == 2 ) {
666682 vt_1 = new OPQMatrix (d, opq_M, d_out);
667683 d = d_out;
668- } else if (!vt && sscanf (tok, " OPQ%d" , &opq_M) == 1 ) {
684+ } else if (sscanf (tok, " OPQ%d" , &opq_M) == 1 ) {
669685 vt_1 = new OPQMatrix (d, opq_M);
670- // coarse quantizers
686+ } else if (stok == " L2norm" ) {
687+ vt_1 = new NormalizationTransform (d, 2.0 );
688+
689+ // coarse quantizers
671690 } else if (!coarse_quantizer &&
672691 sscanf (tok, " IVF%d" , &ncentroids) == 1 ) {
673692 if (metric == METRIC_L2 ) {
@@ -698,28 +717,25 @@ Index *index_factory (int d, const char *description_in, MetricType metric)
698717 index_1 = index_ivf;
699718 } else {
700719 index_1 = new IndexFlat (d, metric);
701- if (add_idmap) {
702- IndexIDMap *idmap = new IndexIDMap (index_1);
703- idmap->own_fields = true ;
704- index_1 = idmap;
705- add_idmap = false ;
706- }
707720 }
708721 } else if (!index && (stok == " SQ8" || stok == " SQ4" )) {
709- FAISS_THROW_IF_NOT_MSG (coarse_quantizer,
710- " ScalarQuantizer works only with an IVF" );
711722 ScalarQuantizer::QuantizerType qt =
712723 stok == " SQ8" ? ScalarQuantizer::QT_8bit :
713724 stok == " SQ4" ? ScalarQuantizer::QT_4bit :
714725 ScalarQuantizer::QT_4bit;
715- IndexIVFScalarQuantizer *index_ivf = new IndexIVFScalarQuantizer (
716- coarse_quantizer, d, ncentroids, qt, metric);
717- index_ivf->quantizer_trains_alone =
718- dynamic_cast <MultiIndexQuantizer*>(coarse_quantizer)
719- != nullptr ;
720- del_coarse_quantizer.release ();
721- index_ivf->own_fields = true ;
722- index_1 = index_ivf;
726+ if (coarse_quantizer) {
727+ IndexIVFScalarQuantizer *index_ivf =
728+ new IndexIVFScalarQuantizer (
729+ coarse_quantizer, d, ncentroids, qt, metric);
730+ index_ivf->quantizer_trains_alone =
731+ dynamic_cast <MultiIndexQuantizer*>(coarse_quantizer)
732+ != nullptr ;
733+ del_coarse_quantizer.release ();
734+ index_ivf->own_fields = true ;
735+ index_1 = index_ivf;
736+ } else {
737+ index_1 = new IndexScalarQuantizer (d, qt, metric);
738+ }
723739 } else if (!index && sscanf (tok, " PQ%d+%d" , &M, &M2 ) == 2 ) {
724740 FAISS_THROW_IF_NOT_MSG (coarse_quantizer,
725741 " PQ with + works only with an IVF" );
@@ -750,13 +766,6 @@ Index *index_factory (int d, const char *description_in, MetricType metric)
750766 IndexPQ *index_pq = new IndexPQ (d, M, 8 , metric);
751767 index_pq->do_polysemous_training = true ;
752768 index_1 = index_pq;
753- if (add_idmap) {
754- IndexIDMap *idmap = new IndexIDMap (index_1);
755- del_index.set (idmap);
756- idmap->own_fields = true ;
757- index_1 = idmap;
758- add_idmap = false ;
759- }
760769 }
761770 } else if (stok == " RFlat" ) {
762771 make_IndexRefineFlat = true ;
@@ -765,9 +774,16 @@ Index *index_factory (int d, const char *description_in, MetricType metric)
765774 tok, description_in);
766775 }
767776
777+ if (index_1 && add_idmap) {
778+ IndexIDMap *idmap = new IndexIDMap (index_1);
779+ del_index.set (idmap);
780+ idmap->own_fields = true ;
781+ index_1 = idmap;
782+ add_idmap = false ;
783+ }
784+
768785 if (vt_1) {
769- vt = vt_1;
770- del_vt.set (vt);
786+ vts.chain .push_back (vt_1);
771787 }
772788
773789 if (coarse_quantizer_1) {
@@ -793,10 +809,14 @@ Index *index_factory (int d, const char *description_in, MetricType metric)
793809 " IDMap option not used\n " );
794810 }
795811
796- if (vt) {
797- IndexPreTransform *index_pt = new IndexPreTransform (vt, index);
798- del_vt.release ();
812+ if (vts.chain .size () > 0 ) {
813+ IndexPreTransform *index_pt = new IndexPreTransform (index);
799814 index_pt->own_fields = true ;
815+ // add from back
816+ while (vts.chain .size () > 0 ) {
817+ index_pt->prepend_transform (vts.chain .back ());
818+ vts.chain .pop_back ();
819+ }
800820 index = index_pt;
801821 }
802822
0 commit comments