Matrix Multiplication challenge accuracy

Hello. I want to participate in the matrix multiplication challenge, but I wonder about the way to evaluate accuracy. When I checked my evaluation result for matrix multiplication locally, I obtained high accuracy. Yet, when I uploaded my code, I got low accuracy (about 11.xxx). Can I get assistance in identifying the issue? Below is my code for checking accuracy locally. If you could review my code and suggest better ways to inspect it locally, that would be appreciated.

Below is the code for creating contexts.

int main(){

    int n = 64; // matrix size

    // random matrix generator
    std::random_device rd; 
    std::mt19937 gen(rd());
    std::uniform_real_distribution<double> dis(-1.0, 1.0);
    
    CCParams<CryptoContextCKKSRNS> parameters;
    parameters.SetMultiplicativeDepth(2);
    parameters.SetScalingModSize(50);
    parameters.SetBatchSize(n*n);
    parameters.SetRingDim(1<<13);
    parameters.SetSecurityLevel(HEStd_NotSet); 

    CryptoContext<DCRTPoly> cryptoContext = GenCryptoContext(parameters);
    
    cryptoContext->Enable(PKE);
    cryptoContext->Enable(LEVELEDSHE);

    KeyPair<DCRTPoly> keyPair = cryptoContext->KeyGen();
    cryptoContext->EvalMultKeyGen(keyPair.secretKey);
    cryptoContext->EvalRotateKeyGen(keyPair.secretKey, {1,-1,2,-2,3,-3,4,-4,5,-5});
    
    std::vector<double> vec1 = {};
    std::vector<double> vec2 = {};
    for(int i=0; i < n*n; i++){
        vec1.push_back(dis(gen));
        vec2.push_back(dis(gen));
    }
    std::vector<double> answer = matrixMultiply(vec1, vec2, n);
    serializeVectorToFile(answer, DATAFOLDER + answerLocation);

    Plaintext p1 = cryptoContext->MakeCKKSPackedPlaintext(vec1);
    Plaintext p2 = cryptoContext->MakeCKKSPackedPlaintext(vec2);

    auto c1 = cryptoContext->Encrypt(keyPair.publicKey, p1);
    auto c2 = cryptoContext->Encrypt(keyPair.publicKey, p2);


    if (!Serial::SerializeToFile(DATAFOLDER + ccLocation, cryptoContext, SerType::BINARY)) {
        std::cerr << "Error writing serialization of the crypto context to "
                     "cryptocontext.txt"
                  << std::endl;
        std::exit(1);
    }
    std::cout << "Cryptocontext serialized" << std::endl;

    if (!Serial::SerializeToFile(DATAFOLDER + pubKeyLocation, keyPair.publicKey, SerType::BINARY)) {
        std::cerr << "Exception writing public key to pubkey.txt" << std::endl;
        std::exit(1);
    }
    std::cout << "Public key serialized" << std::endl;

    if (!Serial::SerializeToFile(DATAFOLDER + priKeyLocation, keyPair.secretKey, SerType::BINARY)) {
        std::cerr << "Exception writing private key to prikey.txt" << std::endl;
        std::exit(1);
    }
    std::cout << "Pirvate key serialized" << std::endl;

    std::ofstream multKeyFile(DATAFOLDER + multKeyLocation, std::ios::out | std::ios::binary);
    if (multKeyFile.is_open()) {
        if (!cryptoContext->SerializeEvalMultKey(multKeyFile, SerType::BINARY)) {
            std::cerr << "Error writing eval mult keys" << std::endl;
            std::exit(1);
        }
        std::cout << "EvalMult/ relinearization keys have been serialized" << std::endl;
        multKeyFile.close();
    }
    else {
        std::cerr << "Error serializing EvalMult keys" << std::endl;
        std::exit(1);
    }

    if(!Serial::SerializeToFile(DATAFOLDER + cipherOneLocation, c1, SerType::BINARY)){
      std::cerr << " Error writing matrix 1" << std::endl;
    }
    
    if(!Serial::SerializeToFile(DATAFOLDER + cipherTwoLocation, c2, SerType::BINARY)){
      std::cerr << " Error writing matrix 2" << std::endl;
    }

    std::ofstream rotationKeyFile(DATAFOLDER + rotateLocation, std::ios::out | std::ios::binary);
    if(rotationKeyFile.is_open()){
      if(!cryptoContext->SerializeEvalAutomorphismKey(rotationKeyFile, SerType::BINARY)){
        std::cerr << "Error writing rotation keys" << std::endl;
      }
      std::cout << "Rotation keys have been serialized" << std::endl;
    }

}

std::vector<double> matrixMultiply(const std::vector<double>& matrix1,
                                   const std::vector<double>& matrix2,
                                   int size) {

    std::vector<double> result(size * size, 0.0);


    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size; ++j) {
            for (int k = 0; k < size; ++k) {
                result[i * size + j] += matrix1[i * size + k] * matrix2[k * size + j];
            }
        }
    }

    return result;
}

void serializeVectorToFile(const std::vector<double>& data, const std::string& filename) {
    std::ofstream outFile(filename);
    outFile << std::setprecision(15);
    if (outFile.is_open()) {
        for (double value : data) {
            outFile << value << " ";
        }
        outFile.close();
        std::cout << "Serialization successful." << std::endl;
    } else {
        std::cerr << "Unable to open the file for serialization." << std::endl;
    }
}

After the evaluation is conducted using aforementioned files, i checked the accuracy with the code below.

int main(){

    CryptoContext<DCRTPoly> cc;
    Serial::DeserializeFromFile(DATAFOLDER + ccLocation, cc, SerType::BINARY);    

    PrivateKey<DCRTPoly> m_PrivateKey; 
    Serial::DeserializeFromFile(DATAFOLDER + priKeyLocation,  m_PrivateKey, SerType::BINARY);    

    Ciphertext<DCRTPoly> eval_result;
    Serial::DeserializeFromFile(DATAFOLDER + resultLocation, eval_result, SerType::BINARY);    

    std::vector<double> answer = deserializeVectorFromFile(DATAFOLDER + answerLocation);

    Plaintext eval_result_ptx;
    cc->Decrypt(m_PrivateKey, eval_result, &eval_result_ptx);
    std::vector<double> eval_result_vector = eval_result_ptx->GetRealPackedValue();

    std::cout << "accuracy: " << matrixEuclideanDistance(eval_result_vector, answer) << std::endl;
}

std::vector<double> deserializeVectorFromFile(const std::string& filename) {
    std::vector<double> result;
    std::ifstream inFile(filename);
    if (inFile.is_open()) {
        double value;
        while (inFile >> value) {
            result.push_back(value);
        }
        inFile.close();
        std::cout << "Deserialization successful." << std::endl;
    } else {
        std::cerr << "Unable to open the file for deserialization." << std::endl;
    }
    return result;
}

double matrixEuclideanDistance(const std::vector<double>& matrix1, const std::vector<double>& matrix2){
    if (matrix1.size() != matrix2.size()) {
        std::cerr << "Error: Matrices must have the same size for Euclidean distance calculation." << std::endl;
        return -1.0; 
    }

    double distance = 0.0;

    for (std::size_t i = 0; i < matrix1.size(); ++i) {
        distance += std::pow(matrix1[i] - matrix2[i], 2);
    }

    distance = std::sqrt(distance);

    return distance;
}

The result I obtained is as follows.
image

Thank you.

Hi,
I see (on the screenshot) a pretty low accuracy - 1.0236e-09.

We will publish scripts and instructions for local testing in the coming days.

I see in your code accuracy = error (distance), based on Euclidian norm.
If the error obtained on the encrypted data is as small then the accuracy should be close to 100%.