Why is it wrong to choose the minimum value in this code

std::cout << “\n-----ArgminViaSchemeSwitching-----\n” << std::endl;
std::cout << “Output precision is only wrt the operations in CKKS after switching back\n” << std::endl;

// Step 1: Setup CryptoContext for CKKS
uint32_t scaleModSize = 50;
uint32_t firstModSize = 60;
uint32_t ringDim      = 8192;
SecurityLevel sl      = HEStd_NotSet;
BINFHE_PARAMSET slBin = TOY;
uint32_t logQ_ccLWE   = 25;
bool arbFunc          = false;
bool oneHot           = true;  // Change to false if the output should not be one-hot encoded

uint32_t slots          = 16;  // sparsely-packed
uint32_t batchSize      = slots;
uint32_t numValues      = 16;
ScalingTechnique scTech = FIXEDMANUAL;
uint32_t multDepth =
        9 + 3 + 1 + static_cast<int>(std::log2(numValues))+5;  // 13 for FHEW to CKKS, log2(numValues) for argmin
if (scTech == FLEXIBLEAUTOEXT)
    multDepth += 1;

CCParams<CryptoContextCKKSRNS> parameters;
parameters.SetMultiplicativeDepth(multDepth);
parameters.SetScalingModSize(scaleModSize);
parameters.SetFirstModSize(firstModSize);
parameters.SetScalingTechnique(scTech);
parameters.SetSecurityLevel(sl);
parameters.SetRingDim(ringDim);
parameters.SetBatchSize(batchSize);

CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);

// Enable the features that you wish to use
cc->Enable(PKE);
cc->Enable(KEYSWITCH);
cc->Enable(LEVELEDSHE);
cc->Enable(ADVANCEDSHE);
cc->Enable(SCHEMESWITCH);
cc->Enable(PRE);

std::cout << "CKKS scheme is using ring dimension " << cc->GetRingDimension();
std::cout << ", and number of slots " << slots << ", and supports a depth of " << multDepth << std::endl
          << std::endl;

// Generate encryption keys
KeyPair<DCRTPoly> keyPaiRserver;
keyPaiRserver=cc->KeyGen();
//auto keys = cc->KeyGen();

// Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
auto FHEWparams     = cc->EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, false, slots);
auto ccLWE          = FHEWparams.first;
auto privateKeyFHEW = FHEWparams.second;

cc->EvalSchemeSwitchingKeyGen(keyPaiRserver, privateKeyFHEW, numValues, oneHot);

std::cout << "FHEW scheme is using lattice parameter " << ccLWE.GetParams()->GetLWEParams()->Getn();
std::cout << ", logQ " << logQ_ccLWE;
std::cout << ", and modulus q " << ccLWE.GetParams()->GetLWEParams()->Getq() << std::endl << std::endl;

// Scale the inputs to ensure their difference is correctly represented after switching to FHEW
double scaleSign = 512.0;
auto modulus_LWE = 1 << logQ_ccLWE;
auto beta        = ccLWE.GetBeta().ConvertToInt();
auto pLWE        = modulus_LWE / (2 * beta);  // Large precision

uint32_t init_level     = 0;
const auto cryptoParams = std::dynamic_pointer_cast<CryptoParametersCKKSRNS>(cc->GetCryptoParameters());
if (cryptoParams->GetScalingTechnique() == FLEXIBLEAUTOEXT)
    init_level = 1;
// This formulation is for clarity
cc->EvalCompareSwitchPrecompute(pLWE, init_level, scaleSign);

KeyPair<DCRTPoly> keyPair1;
keyPair1 = cc->KeyGen();

cc->EvalSumKeyGen(keyPaiRserver.secretKey, keyPaiRserver.publicKey);
cc->EvalMultKeyGen(keyPaiRserver.secretKey);
std::vector x1 = {91, 140, 204, 50, 70, 129, 98, 57, 91, 140, 204, 50, 70, 129,52,52};
Plaintext ptxt1 = cc->MakeCKKSPackedPlaintext(x1);
auto c1 = cc->Encrypt(keyPair1.publicKey, ptxt1);
auto reencrypt1= cc->ReKeyGen(keyPair1.secretKey, keyPaiRserver.publicKey);
auto ct1 = cc->ReEncrypt(c1, reencrypt1);
auto result = cc->EvalMinSchemeSwitching(ct1, keyPaiRserver.publicKey, numValues, slots, oneHot);
cout<<“111”<<endl;
Plaintext ptxtMin;
cc->Decrypt(keyPaiRserver.secretKey, result[0], &ptxtMin);
ptxtMin->SetLength(1);
std::cout << "Minimum value: " << ptxtMin << std::endl;
cc->Decrypt(keyPaiRserver.secretKey, result[1], &ptxtMin);
if (oneHot) {
ptxtMin->SetLength(numValues);
std::cout << "Argmin indicator vector: " << ptxtMin << std::endl;
}
else {
ptxtMin->SetLength(1);
std::cout << "Argmin: " << ptxtMin << std::endl;
}

result = cc->EvalMaxSchemeSwitching(ct1, keyPaiRserver.publicKey, numValues, slots, oneHot);

Plaintext ptxtMax;
cc->Decrypt(keyPaiRserver.secretKey, result[0], &ptxtMax);
ptxtMax->SetLength(1);
std::cout << "Maximum value: " << ptxtMax << std::endl;
cc->Decrypt(keyPaiRserver.secretKey, result[1], &ptxtMax);
if (oneHot) {
    ptxtMax->SetLength(numValues);
    std::cout << "Argmax indicator vector: " << ptxtMax << std::endl;
}
else {
    ptxtMax->SetLength(1);
    std::cout << "Argmax: " << ptxtMax << std::endl;
}

the output is
Minimum value: (204, … ); Estimated precision: 32 bits

Argmin indicator vector: (-1.06807e-12, 2.23187e-13, 5.89118e-07, 2.49577e-12, 8.6444e-12, 1.96647e-12, 2.60188e-12, 1.81553e-12, 3.45485e-12, -1.43813e-12, 0.999998, 5.92664e-07, 7.93075e-10, 3.41856e-12, 5.84236e-07, -7.74684e-13, … ); Estimated precision: 37 bits

Maximum value: (203.999, … ); Estimated precision: 30 bits

Argmax indicator vector: (2.34909e-06, 5.89018e-07, 0.999994, 7.53067e-13, 1.18023e-11, 2.34536e-12, 2.354e-06, 2.9124e-12, 9.45044e-13, -2.82486e-13, 5.89115e-07, -7.60647e-13, -8.32041e-13, -1.97771e-13, -5.45767e-13, 8.5003e-13, … ); Estimated precision: 39 bits

Please format your code properly.

Also, what exactly is your question?

The result of finding the minimum value is incorrect.

The code is as follows:

#include "cnpy.h"
#include "openfhe.h"
#include "ciphertext-ser.h"
#include "cryptocontext-ser.h"
#include <cmath>
#include <vector>
#include <sstream>
#include<algorithm>
#include "binfhecontext.h"
using namespace lbcrypto;
using PT = Plaintext;
using namespace std;
int main() {


    uint32_t scaleModSize = 50;
    uint32_t firstModSize = 60;
    uint32_t ringDim = 8192;
    SecurityLevel sl = HEStd_NotSet;
    BINFHE_PARAMSET slBin = TOY;
    uint32_t logQ_ccLWE = 25;
    bool arbFunc = false;
    bool oneHot = true;  // Change to false if the output should not be one-hot encoded

    uint32_t slots = 16;  // sparsely-packed
    uint32_t batchSize = slots;
    uint32_t numValues = 16;
    ScalingTechnique scTech = FIXEDMANUAL;
    uint32_t multDepth =
            9 + 3 + 1 + static_cast<int>(std::log2(numValues)) + 5;  // 13 for FHEW to CKKS, log2(numValues) for argmin
    if (scTech == FLEXIBLEAUTOEXT)
        multDepth += 1;

    CCParams<CryptoContextCKKSRNS> parameters;
    parameters.SetMultiplicativeDepth(multDepth);
    parameters.SetScalingModSize(scaleModSize);
    parameters.SetFirstModSize(firstModSize);
    parameters.SetScalingTechnique(scTech);
    parameters.SetSecurityLevel(sl);
    parameters.SetRingDim(ringDim);
    parameters.SetBatchSize(batchSize);

    CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);

// Enable the features that you wish to use
    cc->Enable(PKE);
    cc->Enable(KEYSWITCH);
    cc->Enable(LEVELEDSHE);
    cc->Enable(ADVANCEDSHE);
    cc->Enable(SCHEMESWITCH);
    cc->Enable(PRE);

    std::cout << "CKKS scheme is using ring dimension " << cc->GetRingDimension();
    std::cout << ", and number of slots " << slots << ", and supports a depth of " << multDepth << std::endl
              << std::endl;

// Generate encryption keys
    KeyPair<DCRTPoly> keyPaiRserver;
    keyPaiRserver = cc->KeyGen();
//auto keys = cc->KeyGen();

// Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
    auto FHEWparams = cc->EvalSchemeSwitchingSetup(sl, slBin, arbFunc, logQ_ccLWE, false, slots);
    auto ccLWE = FHEWparams.first;
    auto privateKeyFHEW = FHEWparams.second;

    cc->EvalSchemeSwitchingKeyGen(keyPaiRserver, privateKeyFHEW, numValues, oneHot);

    std::cout << "FHEW scheme is using lattice parameter " << ccLWE.GetParams()->GetLWEParams()->Getn();
    std::cout << ", logQ " << logQ_ccLWE;
    std::cout << ", and modulus q " << ccLWE.GetParams()->GetLWEParams()->Getq() << std::endl << std::endl;

// Scale the inputs to ensure their difference is correctly represented after switching to FHEW
    double scaleSign = 512.0;
    auto modulus_LWE = 1 << logQ_ccLWE;
    auto beta = ccLWE.GetBeta().ConvertToInt();
    auto pLWE = modulus_LWE / (2 * beta);  // Large precision

    uint32_t init_level = 0;
    const auto cryptoParams = std::dynamic_pointer_cast<CryptoParametersCKKSRNS>(cc->GetCryptoParameters());
    if (cryptoParams->GetScalingTechnique() == FLEXIBLEAUTOEXT)
        init_level = 1;
// This formulation is for clarity
    cc->EvalCompareSwitchPrecompute(pLWE, init_level, scaleSign);

    KeyPair<DCRTPoly> keyPair1;
    keyPair1 = cc->KeyGen();
    cc->EvalSumKeyGen(keyPaiRserver.secretKey, keyPaiRserver.publicKey);
    cc->EvalMultKeyGen(keyPaiRserver.secretKey);
    std::vector<double>  x1 = {91, 140, 204, 50, 70, 129, 98, 57, 91, 140, 204, 50, 70, 129, 52, 52};
    Plaintext ptxt1 = cc->MakeCKKSPackedPlaintext(x1);
    auto c1 = cc->Encrypt(keyPair1.publicKey, ptxt1);
    auto reencrypt1 = cc->ReKeyGen(keyPair1.secretKey, keyPaiRserver.publicKey);
    auto ct1 = cc->ReEncrypt(c1, reencrypt1);
    auto result = cc->EvalMinSchemeSwitching(ct1, keyPaiRserver.publicKey, numValues, slots, oneHot);
    Plaintext ptxtMin;
    cc->Decrypt(keyPaiRserver.secretKey, result[0], &ptxtMin);
    ptxtMin->SetLength(1);
    std::cout << "Minimum value: " << ptxtMin << std::endl;
    cc->Decrypt(keyPaiRserver.secretKey, result[1], &ptxtMin);
    if (oneHot) {
        ptxtMin->SetLength(numValues);
        std::cout << "Argmin indicator vector: " << ptxtMin << std::endl;
    } else {
        ptxtMin->SetLength(1);
        std::cout << "Argmin: " << ptxtMin << std::endl;
    }
    result = cc->EvalMaxSchemeSwitching(ct1, keyPaiRserver.publicKey, numValues, slots, oneHot);

    Plaintext ptxtMax;
    cc->Decrypt(keyPaiRserver.secretKey, result[0], &ptxtMax);
    ptxtMax->SetLength(1);
    std::cout << "Maximum value: " << ptxtMax << std::endl;
    cc->Decrypt(keyPaiRserver.secretKey, result[1], &ptxtMax);
    if (oneHot) {
        ptxtMax->SetLength(numValues);
        std::cout << "Argmax indicator vector: " << ptxtMax << std::endl;
    } else {
        ptxtMax->SetLength(1);
        std::cout << "Argmax: " << ptxtMax << std::endl;
    }
}

The output is
CKKS scheme is using ring dimension 8192, and number of slots 16, and supports a depth of 22

FHEW scheme is using lattice parameter 32, logQ 25, and modulus q 4096

Minimum value: (203.999, … ); Estimated precision: 25 bits

Argmin indicator vector: (-1.80075e-11, -7.61712e-11, 7.96246e-10, 3.55994e-11, 6.17881e-11, 1.2757e-11, -1.19337e-11, 4.15671e-11, 4.01401e-11, -6.09917e-11, 0.999996, 6.32376e-07, 5.89035e-07, -2.07531e-11, 2.35744e-06, -6.21182e-12, … ); Estimated precision: 34 bits

Maximum value: (204, … ); Estimated precision: 31 bits

Argmax indicator vector: (5.92617e-07, 2.354e-06, 0.999997, 1.60614e-12, -7.82198e-13, 2.1223e-12, 7.87134e-10, 4.59279e-12, -4.95312e-13, 1.76701e-12, 7.87608e-10, -1.90794e-12, 4.75058e-13, -6.04804e-13, -7.80394e-13, 4.18836e-13, … ); Estimated precision: 39 bits

The problem is that result of finding the minimum value is incorrect.

Change the scaleSign to be smaller than 512, e.g., 256, and it will work. Your scaled inputs need to be smaller than the LWE plaintext modulus that you specify. (Not too close because the argmin functionality is iterative and at each iteration there are some errors introduced due to CKKS.) Your choice of inputs along with the scaleSign is cutting it too close to pLWE.