From e53ba270634b8b83140e6cf49a9a1a7f8f426669 Mon Sep 17 00:00:00 2001 From: jaeho Date: Tue, 12 Mar 2024 11:56:19 +0000 Subject: [PATCH] Separate LibconfigGenerator into valid/random --- .../Generate/AbsProgramGenerator.scala | 48 ++++--- .../fhetest/Generate/LibConfigGenerator.scala | 135 +++++++++++------- src/main/scala/fhetest/Phase/Generate.scala | 4 +- 3 files changed, 115 insertions(+), 72 deletions(-) diff --git a/src/main/scala/fhetest/Generate/AbsProgramGenerator.scala b/src/main/scala/fhetest/Generate/AbsProgramGenerator.scala index 44a13bb..9f25af8 100644 --- a/src/main/scala/fhetest/Generate/AbsProgramGenerator.scala +++ b/src/main/scala/fhetest/Generate/AbsProgramGenerator.scala @@ -9,37 +9,45 @@ enum Strategy: case Exhaustive, Random extension (s: Strategy) - def getGenerator: AbsProgramGenerator = s match { - case Strategy.Exhaustive => ExhaustiveGenerator - case Strategy.Random => RandomGenerator + def getGenerator( + encType: ENC_TYPE, + validCheck: Boolean, + ): AbsProgramGenerator = s match { + case Strategy.Exhaustive => + ExhaustiveGenerator(encType: ENC_TYPE, validCheck: Boolean) + case Strategy.Random => + RandomGenerator(encType: ENC_TYPE, validCheck: Boolean) } // AbsProgram Generator -trait AbsProgramGenerator { - def generateAbsPrograms( - encType: ENC_TYPE, - validCheck: Boolean, - ): LazyList[AbsProgram] +trait AbsProgramGenerator(encType: ENC_TYPE, validCheck: Boolean) { + def generateAbsPrograms(): LazyList[AbsProgram] + val lcGen = + if validCheck then ValidLibConfigGenerator(encType) + else RandomLibConfigGenerator(encType) } -object ExhaustiveGenerator extends AbsProgramGenerator { - def generateAbsPrograms( - encType: ENC_TYPE, - validCheck: Boolean, - ): LazyList[AbsProgram] = { +case class ExhaustiveGenerator(encType: ENC_TYPE, validCheck: Boolean) + extends AbsProgramGenerator(encType: ENC_TYPE, validCheck: Boolean) { + def generateAbsPrograms(): LazyList[AbsProgram] = { def allAbsProgramsOfSize(n: Int): LazyList[AbsProgram] = { n match { case 1 => allAbsStmts .map(stmt => List(stmt)) - .map(AbsProgram(_, generateLibConfig(encType, validCheck))) + .map( + AbsProgram( + _, + lcGen.generateLibConfig(), + ), + ) case _ => for { stmt <- allAbsStmts program <- allAbsProgramsOfSize(n - 1) } yield AbsProgram( stmt :: program.absStmts, - generateLibConfig(encType, validCheck), + lcGen.generateLibConfig(), ) } } @@ -48,14 +56,12 @@ object ExhaustiveGenerator extends AbsProgramGenerator { } -object RandomGenerator extends AbsProgramGenerator { - def generateAbsPrograms( - encType: ENC_TYPE, - validCheck: Boolean, - ): LazyList[AbsProgram] = { +case class RandomGenerator(encType: ENC_TYPE, validCheck: Boolean) + extends AbsProgramGenerator(encType: ENC_TYPE, validCheck: Boolean) { + def generateAbsPrograms(): LazyList[AbsProgram] = { def randomAbsProgramOfSize(n: Int): AbsProgram = { val absStmts = (1 to n).map(_ => Random.shuffle(allAbsStmts).head).toList - AbsProgram(absStmts, generateLibConfig(encType, validCheck)) + AbsProgram(absStmts, lcGen.generateLibConfig()) } // Generate Lengths from 1 to inf // LazyList.from(1) diff --git a/src/main/scala/fhetest/Generate/LibConfigGenerator.scala b/src/main/scala/fhetest/Generate/LibConfigGenerator.scala index 474aa45..cf03cb4 100644 --- a/src/main/scala/fhetest/Generate/LibConfigGenerator.scala +++ b/src/main/scala/fhetest/Generate/LibConfigGenerator.scala @@ -4,38 +4,37 @@ import fhetest.LibConfig import fhetest.Utils.* import scala.util.Random -def generateLibConfig(encType: ENC_TYPE, valid: Boolean): LibConfig = { - lazy val randomScheme = - if encType == ENC_TYPE.ENC_INT then Scheme.values(Random.nextInt(2)) - else Scheme.CKKS +trait LibConfigGenerator(encType: ENC_TYPE) { + def generateLibConfig(): LibConfig +} - lazy val randomEncParams = { - // TODO: Currently only MultDepth is random - val randomRingDim = 32768 - val randomMultDepth = - if valid then Random.nextInt(10 + 1) - else Random.between(-10, 10 + 1) - val randomPlainMod = 65537 - EncParams(randomRingDim, randomMultDepth, randomPlainMod) - } - // modSizeIsUpto60bits - lazy val randomFirstModSize: Int = - if valid then +case class ValidLibConfigGenerator(encType: ENC_TYPE) + extends LibConfigGenerator(encType) { + def generateLibConfig(): LibConfig = { + val randomScheme = + if encType == ENC_TYPE.ENC_INT then Scheme.values(Random.nextInt(2)) + else Scheme.CKKS + val randomEncParams = { + // TODO: Currently only MultDepth is random + val randomRingDim = 32768 + val randomMultDepth = + Random.nextInt(10 + 1) + val randomPlainMod = 65537 + EncParams(randomRingDim, randomMultDepth, randomPlainMod) + } + // modSizeIsUpto60bits + val randomFirstModSize: Int = if randomScheme == Scheme.BFV then Random.between(30, 60 + 1) else Random.nextInt(60 + 1) - else Random.between(-100, 100 + 1) - // firstModSizeIsLargest - // openFHEBFVModuli - lazy val randomScalingModSize: Int = - if valid then + // firstModSizeIsLargest + // openFHEBFVModuli + val randomScalingModSize: Int = if randomScheme == Scheme.BFV then Random.between(30, randomFirstModSize + 1) else Random.nextInt(randomFirstModSize + 1) - else Random.between(-100, 100 + 1) - lazy val randomSecurityLevel = - SecurityLevel.values(Random.nextInt(SecurityLevel.values.length)) - lazy val randomScalingTechnique = - if valid then + val randomSecurityLevel = + SecurityLevel.values(Random.nextInt(SecurityLevel.values.length)) + val randomScalingTechnique = // Currently, exclude FLEXIBLEAUTOEXT in valid testing because of the following issue // https://openfhe.discourse.group/t/unexpected-behavior-with-setscalingmodsize-and-flexibleautoext-in-bgv-scheme/1111 // And, exclude NORESCALE in CKKS scheme because it is not supported @@ -58,43 +57,81 @@ def generateLibConfig(encType: ENC_TYPE, valid: Boolean): LibConfig = { scalingTechs( Random.nextInt(scalingTechs.length), ) - else ScalingTechnique.values(Random.nextInt(ScalingTechnique.values.length)) - // len must be larger than 0 - // lenIsLessThanRingDim - lazy val randomLenOpt: Option[Int] = - if valid then + // len must be larger than 0 + // lenIsLessThanRingDim + val randomLenOpt: Option[Int] = val upper = randomScheme match { case Scheme.CKKS => (randomEncParams.ringDim / 2) case _ => randomEncParams.ringDim } Some(Random.between(1, upper + 1)) - else Some(Random.between(1, 100000 + 1)) - lazy val randomBoundOpt: Option[Int | Double] = - if valid then + val randomBoundOpt: Option[Int | Double] = randomScheme match { case Scheme.BFV | Scheme.BGV => Some(Random.between(1, randomEncParams.plainMod + 1)) case Scheme.CKKS => Some(Random.between(1, math.pow(2, randomFirstModSize) + 1)) } - else + val randomRotateBoundOpt: Option[Int] = + Some(Random.between(0, 20 + 1)) + LibConfig( + randomScheme, + randomEncParams, + randomFirstModSize, + randomScalingModSize, + randomSecurityLevel, + randomScalingTechnique, + randomLenOpt, + randomBoundOpt, + randomRotateBoundOpt, + ) + } +} + +case class RandomLibConfigGenerator(encType: ENC_TYPE) + extends LibConfigGenerator(encType) { + def generateLibConfig(): LibConfig = { + val randomScheme = + if encType == ENC_TYPE.ENC_INT then Scheme.values(Random.nextInt(2)) + else Scheme.CKKS + + val randomEncParams = { + // TODO: Currently only MultDepth is random + val randomRingDim = 32768 + val randomMultDepth = + Random.between(-10, 10 + 1) + val randomPlainMod = 65537 + EncParams(randomRingDim, randomMultDepth, randomPlainMod) + } + val randomFirstModSize: Int = + Random.between(-100, 100 + 1) + val randomScalingModSize: Int = + Random.between(-100, 100 + 1) + val randomSecurityLevel = + SecurityLevel.values(Random.nextInt(SecurityLevel.values.length)) + val randomScalingTechnique = + ScalingTechnique.values(Random.nextInt(ScalingTechnique.values.length)) + // len must be larger than 0 + val randomLenOpt: Option[Int] = + Some(Random.between(1, 100000 + 1)) + val randomBoundOpt: Option[Int | Double] = randomScheme match { case Scheme.BFV | Scheme.BGV => Some(Random.between(1, 1000 + 1)) case Scheme.CKKS => Some(Random.between(1, math.pow(2, 64) + 1)) } - lazy val randomRotateBoundOpt: Option[Int] = - if valid then Some(Random.between(0, 20 + 1)) - else Some(Random.between(0, 40 + 1)) - LibConfig( - randomScheme, - randomEncParams, - randomFirstModSize, - randomScalingModSize, - randomSecurityLevel, - randomScalingTechnique, - randomLenOpt, - randomBoundOpt, - randomRotateBoundOpt, - ) + val randomRotateBoundOpt: Option[Int] = + Some(Random.between(0, 40 + 1)) + LibConfig( + randomScheme, + randomEncParams, + randomFirstModSize, + randomScalingModSize, + randomSecurityLevel, + randomScalingTechnique, + randomLenOpt, + randomBoundOpt, + randomRotateBoundOpt, + ) + } } diff --git a/src/main/scala/fhetest/Phase/Generate.scala b/src/main/scala/fhetest/Phase/Generate.scala index 6acdb48..a23a040 100644 --- a/src/main/scala/fhetest/Phase/Generate.scala +++ b/src/main/scala/fhetest/Phase/Generate.scala @@ -32,9 +32,9 @@ case class Generate( val symbolTable = boilerplate()._2 - val absProgGen = strategy.getGenerator + val absProgGen = strategy.getGenerator(encType, checkValid) - val allAbsPrograms = absProgGen.generateAbsPrograms(encType, checkValid) + val allAbsPrograms = absProgGen.generateAbsPrograms() def apply(nOpt: Option[Int]): LazyList[T2Program] = { println(s"Genrating Strategy: $strategy")