Skip to content

starting to create examples for ai constraint handling #1247

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package bar.examples.it.spring.aiconstraint.numeric

import io.swagger.v3.oas.annotations.Parameter
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*

@SpringBootApplication(exclude = [SecurityAutoConfiguration::class])
@RequestMapping(path = ["/api"])
@RestController
open class AICNumericApplication {

companion object {
@JvmStatic
fun main(args: Array<String>) {
SpringApplication.run(AICNumericApplication::class.java, *args)
}
}


@GetMapping("/numeric")
open fun getString(
@RequestParam("x", required = true) @Parameter(required=true) x: Int

) : ResponseEntity<String> {

if(x !in 1925..2025){
return ResponseEntity.status(400).build()
}
return ResponseEntity.status(200).build()

}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package bar.examples.it.spring.aiconstraint.numeric

import bar.examples.it.spring.SpringController

class AICNumericController : SpringController(AICNumericApplication::class.java)
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package org.evomaster.core.problem.rest.aiconstraint.numeric

import bar.examples.it.spring.aiconstraint.numeric.AICNumericController
import bar.examples.it.spring.cleanupcreate.CleanUpDeleteApplication
import org.evomaster.core.problem.enterprise.SampleType
import org.evomaster.core.problem.rest.IntegrationTestRestBase
import org.evomaster.core.problem.rest.data.RestCallAction
import org.evomaster.core.problem.rest.data.RestCallResult
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import kotlin.random.Random
import kotlin.math.*


class AICNumericTest : IntegrationTestRestBase() {

companion object {
@BeforeAll
@JvmStatic
fun init() {
initClass(AICNumericController())
}
}

@BeforeEach
fun initializeTest() {
}

@Test
fun testNumeric() {


val pirTest = getPirToRest()
val get = pirTest.fromVerbPath("get", "/api/numeric", mapOf("x" to "5"))!!

val individual0 = createIndividual(listOf(get), SampleType.RANDOM)
val evaluatedAction = individual0.evaluatedMainActions()[0]
val action = evaluatedAction.action as RestCallAction
val result = evaluatedAction.result as RestCallResult
assertEquals(200, result.getStatusCode())

Check failure on line 42 in core-it/src/test/kotlin/org/evomaster/core/problem/rest/aiconstraint/numeric/AICNumericTest.kt

View workflow job for this annotation

GitHub Actions / JUnit Test Report

AICNumericTest.testNumeric

expected: <200> but was: <400>
Raw output
org.opentest4j.AssertionFailedError: expected: <200> but was: <400>
	at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
	at org.junit.jupiter.api.AssertionUtils.failNotEqual(AssertionUtils.java:62)
	at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
	at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
	at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:517)
	at org.evomaster.core.problem.rest.aiconstraint.numeric.AICNumericTest.testNumeric(AICNumericTest.kt:42)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.executeNonConcurrentTasks(ForkJoinPoolHierarchicalTestExecutorService.java:155)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.executeNonConcurrentTasks(ForkJoinPoolHierarchicalTestExecutorService.java:155)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185)
	at java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:189)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)
}

@Test
fun learnValidNumberRangeUsingNaiveGaussian() {
val pirTest = getPirToRest()
val initialMean = Random.nextDouble(0.0, 5000.0)
val model = NaiveGaussianModel1D(initialMean = initialMean, initialVariance = 10.0)
val numIterations = 5000
var result: Int? = 0;
repeat(numIterations) {
val sample = model.sample()
val xValue = sample.toInt().coerceIn(0, 5000)

val get = pirTest.fromVerbPath("get", "/api/numeric", mapOf("x" to xValue.toString()))!!
val individual = createIndividual(listOf(get), SampleType.RANDOM)
result = (individual.evaluatedMainActions()[0].result as RestCallResult).getStatusCode()

println("Sampled x=$xValue, got status=$result")

if (result == 200) {
model.updateAccepted(xValue.toDouble())
} else if (result == 400) {
model.updateRejected(xValue.toDouble())
}
}

println("Final mean: ${model.mean()}, variance: ${model.variance()}")
assertEquals(result, 200)
}


// fun testGaussianModel() {
// val model = NaiveGaussianModel1D(initialMean = 1950.0, initialVariance = 1000.0)
// val checker = CriteriaChecker()
//
// repeat(100) {
// val valList = model.generateRandomNumbers(1)
// val value = valList[0]
// if (checker.check(value) == 400) {
// println("The sample is Invalid.")
// } else {
// println("The sample is valid.")
// model.update(value)
// println(model.values)
// println("The model is updated.")
// }
// }
// }
//
// class NaiveGaussianModel1D(initialMean: Double = 0.0, initialVariance: Double = 1.0) {
// private var n: Int = 1
// private var mu: Double = initialMean
// private var M2: Double = initialVariance
// val values: MutableList<Double> = mutableListOf(initialMean)
//
// fun update(x: Double) {
// values.add(x)
// n += 1
// val delta = x - mu
// mu += delta / n
// val delta2 = x - mu
// M2 += delta * delta2
// }
//
// fun posteriorMean(): Double = mu
//
// fun posteriorVariance(): Double = if (n > 1) M2 / (n - 1) else 1e-6
//
// fun generateRandomNumbers(numberOfSamples: Int = 1): List<Double> {
// val mean = posteriorMean()
// val stddev = sqrt(posteriorVariance())
// return List(numberOfSamples) {
// val random = Random()
// random.nextGaussian() * stddev + mean
// }
// }
// }
//
// class CriteriaChecker {
// fun check(x: Double): Int {
// return if (x in 1925.0..2025.0) 200 else 400
// }
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.evomaster.core.problem.rest.aiconstraint.numeric
import kotlin.math.*
import kotlin.random.Random

class NaiveGaussianModel1D(
initialMean: Double = 0.0,
initialVariance: Double = 1.0
) {
private var n = 1
private var mu = initialMean
private var M2 = initialVariance
private val rng = Random.Default

// Rejection tracking
private val recentRejects = mutableListOf<Double>()
private val maxRejectsStored = 20
private val rejectionWeight = 0.1 // how strongly to move away

fun updateAccepted(x: Double) {
n += 1
val delta = x - mu
mu += delta / n
M2 += delta * (x - mu)
}

fun updateRejected(x: Double) {
if (recentRejects.size >= maxRejectsStored) {
recentRejects.removeAt(0)
}
recentRejects.add(x)

// Apply soft penalty: move mean away from recent rejections
val penalty = recentRejects.sumOf { reject ->
val direction = if (reject < mu) 1 else -1 // push away
direction * rejectionWeight
}
mu += penalty
}

fun mean(): Double = mu
fun variance(): Double = if (n > 1) M2 / (n - 1) else M2

fun sample(): Double {
val stdDev = sqrt(variance().coerceAtLeast(1e-3))
return rng.nextGaussian(mu, stdDev)
}

private fun Random.nextGaussian(mean: Double, stdDev: Double): Double {
val u1 = nextDouble()
val u2 = nextDouble()
val z0 = sqrt(-2.0 * ln(u1)) * cos(2 * Math.PI * u2)
return z0 * stdDev + mean
}
}
Loading