Numerical Integration Calculator (java, written by Codex)
envgap__codex__java-t1-45
Written by a coding agent; not on GitHubWritten 2026-03-03
01 / FAILURE SIGNATURE
As the study recorded it
None
Not a benchmark task.
- The project already builds and runs before the fix, so there is nothing to repair.
02 / ENVIRONMENT RECIPE
- Base commit
Not freshly verified- Manifest
pom.xml- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / TASK AND FAILURE
codex/java-t1 #45 · read the task the agent was given
Codex wrote this java project from the task below. It installed and ran on a clean Ubuntu 22.04 machine as written. Task given to the agent: TASK: Numerical Integration Calculator Write a program that computes definite integrals of mathematical functions using multiple numerical methods, comparing accuracy and convergence across methods. FUNCTIONAL REQUIREMENTS: - Accept a mathematical expression as a command-line argument via --function flag (e.g., --function "sin(x)*exp(-x)") - Accept integration bounds via --lower and --upper flags - Support multiple numerical integration methods selectable via --method flag: trapezoidal rule, Simpson's rule, Simpson's 3/8 rule, Gaussian quadrature, and Romberg integration - Support a configurable number of subintervals via --intervals flag (default: 1000) for methods that use subdivision - Run all methods and compare results via --compare flag, showing each method's result, estimated error, and computation time - Support adaptive integration: automatically refine the interval count until the result converges within a specified tolerance via --tolerance flag (default: 1e-10) - Parse mathematical expressions supporting: basic operators (+, -, *, /, ^), standard functions (sin, cos, tan, exp, log, sqrt, abs), constants (pi, e), and nested parentheses - Support improper integrals with infinite bounds via --infinite flag using appropriate limit-based techniques - Support tabulated data integration: read (x, y) pairs from a CSV file via --data flag and integrate using the available methods - Print results to console: integral value, estimated error, method used, intervals used, and computation time - Save results as JSON with --output flag (default: integration_result.json) - If no input is given, compute several well-known integrals (integral of sin(x) from 0 to pi = 2, integral of exp(-x^2) from 0 to infinity = sqrt(pi)/2, integral of 1/x from 1 to e = 1) using all methods and display a comparison table with exact vs computed values and relative errors - Handle errors: division by zero within the integration range, non-convergent integrals, invalid mathematical expressions, and bounds where lower > upper Create a complete Java project for a clean Ubuntu 22.04 machine with only JDK 17+ installed. Include: - Source code - pom.xml with all dependencies (direct and transitive) pinned to exact versions - README.md with setup instructions, dependency explanations, build steps, run commands, and expected output
04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]
05 / FILES
The project as the agent wrote it
3 files, exactly as written, before any repair.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tmlr.p45</groupId>
<artifactId>numerical-integration-calculator</artifactId>
<version>1.0.0</version>
<name>Numerical Integration Calculator</name>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>net.objecthunter</groupId>
<artifactId>exp4j</artifactId>
<version>0.4.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<mainClass>NumericalIntegrationCalculator</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>README.md
# Numerical Integration Calculator (Java) ## Requirements - JDK 17+ - Maven 3.9+ ## Install / Build ```bash mvn clean package ``` ## Run ```bash java -jar target/numerical-integration-calculator-1.0.0.jar --function "sin(x)*exp(-x)" --lower 0 --upper 10 --method simpson --compare ``` Default output JSON file: `integration_result.json`. ## Dependency - `net.objecthunter:exp4j:0.4.8` for expression parsing/evaluation.
src/main/java/NumericalIntegrationCalculator.java
import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.time.Instant;
import java.util.*;
public class NumericalIntegrationCalculator {
private static class Config {
String fn;
String lower;
String upper;
String method = "trapezoidal";
int intervals = 1000;
boolean compare;
double tolerance = 1e-10;
boolean infinite;
String data;
String output = "integration_result.json";
}
public static void main(String[] args) {
try {
Config cfg = parseArgs(args);
if (cfg.fn == null && cfg.data == null) {
List<Map<String, Object>> demo = knownDemo();
System.out.println(toJson(demo));
Files.writeString(Paths.get(cfg.output), toJson(Map.of("config", cfgMap(cfg), "comparison", demo)), StandardCharsets.UTF_8);
return;
}
if (cfg.data != null) {
long t0 = System.nanoTime();
double val = integrateData(Paths.get(cfg.data), cfg.method);
Map<String, Object> result = Map.of("mode", "tabulated", "method", cfg.method, "value", val, "timeMs", (System.nanoTime()-t0)/1_000_000.0);
System.out.println(toJson(result));
Files.writeString(Paths.get(cfg.output), toJson(Map.of("config", cfgMap(cfg), "result", result)), StandardCharsets.UTF_8);
return;
}
double a = parseBound(cfg.lower);
double b = parseBound(cfg.upper);
if (Double.isFinite(a) && Double.isFinite(b) && a > b) throw new IllegalArgumentException("lower bound cannot exceed upper bound");
Func f = compile(cfg.fn);
if (cfg.compare) {
List<Map<String, Object>> comp = compareAll(f, a, b, cfg.intervals, cfg.tolerance);
System.out.println(toJson(comp));
Files.writeString(Paths.get(cfg.output), toJson(Map.of("config", cfgMap(cfg), "comparison", comp)), StandardCharsets.UTF_8);
return;
}
long t0 = System.nanoTime();
AdaptiveResult ar = handleInfinite(f, a, b, cfg.method, cfg.intervals, cfg.tolerance);
Map<String, Object> result = Map.of("method", cfg.method, "value", ar.value, "estimatedError", ar.err, "intervals", ar.intervals, "timeMs", (System.nanoTime()-t0)/1_000_000.0);
System.out.println(toJson(result));
Files.writeString(Paths.get(cfg.output), toJson(Map.of("config", cfgMap(cfg), "result", result)), StandardCharsets.UTF_8);
} catch (Exception ex) {
System.err.println("Error: " + ex.getMessage());
System.exit(1);
}
}
private static Config parseArgs(String[] args) {
Config cfg = new Config();
for (int i = 0; i < args.length; i++) {
String a = args[i];
switch (a) {
case "--function" -> cfg.fn = args[++i];
case "--lower" -> cfg.lower = args[++i];
case "--upper" -> cfg.upper = args[++i];
case "--method" -> cfg.method = args[++i];
case "--intervals" -> cfg.intervals = Integer.parseInt(args[++i]);
case "--compare" -> cfg.compare = true;
case "--tolerance" -> cfg.tolerance = Double.parseDouble(args[++i]);
case "--infinite" -> cfg.infinite = true;
case "--data" -> cfg.data = args[++i];
case "--output" -> cfg.output = args[++i];
default -> throw new IllegalArgumentException("Unknown option: " + a);
}
}
return cfg;
}
private interface Func { double f(double x); }
private static Func compile(String expr) {
ExpressionBuilder b = new ExpressionBuilder(expr).variables("x", "pi", "e")
.functions(new net.objecthunter.exp4j.function.Function("abs", 1) {
@Override public double apply(double... args) { return Math.abs(args[0]); }
});
Expression e = b.build().setVariable("pi", Math.PI).setVariable("e", Math.E);
return (x) -> {
double v = e.setVariable("x", x).evaluate();
if (!Double.isFinite(v)) throw new RuntimeException("Function invalid at x=" + x);
return v;
};
}
private static double parseBound(String s) {
if (s == null) throw new IllegalArgumentException("--lower and --upper are required");
String v = s.toLowerCase(Locale.ROOT);
if (v.equals("inf") || v.equals("+inf") || v.equals("infinity") || v.equals("+infinity")) return Double.POSITIVE_INFINITY;
if (v.equals("-inf") || v.equals("-infinity")) return Double.NEGATIVE_INFINITY;
return Double.parseDouble(s);
}
private static double trap(Func f, double a, double b, int n) {
double h = (b - a) / n;
double s = 0.5 * (f.f(a) + f.f(b));
for (int i = 1; i < n; i++) s += f.f(a + i * h);
return s * h;
}
private static double simpson(Func f, double a, double b, int n) {
if (n % 2 != 0) n++;
double h = (b - a) / n;
double s = f.f(a) + f.f(b);
for (int i = 1; i < n; i++) s += (i % 2 == 0 ? 2 : 4) * f.f(a + i * h);
return s * h / 3.0;
}
private static double simpson38(Func f, double a, double b, int n) {
while (n % 3 != 0) n++;
double h = (b - a) / n;
double s = f.f(a) + f.f(b);
for (int i = 1; i < n; i++) s += (i % 3 == 0 ? 2 : 3) * f.f(a + i * h);
return 3 * h * s / 8.0;
}
private static double gauss5(Func f, double a, double b) {
double[] xs = {0, -0.5384693101056831, 0.5384693101056831, -0.9061798459386640, 0.9061798459386640};
double[] ws = {0.5688888888888889, 0.4786286704993665, 0.4786286704993665, 0.2369268850561891, 0.2369268850561891};
double c1 = (b - a) / 2.0, c2 = (b + a) / 2.0;
double s = 0;
for (int i = 0; i < xs.length; i++) s += ws[i] * f.f(c1 * xs[i] + c2);
return c1 * s;
}
private static double romberg(Func f, double a, double b) {
int K = 6;
double[][] R = new double[K][K];
for (int k = 0; k < K; k++) {
int n = 1 << k;
R[k][0] = trap(f, a, b, n);
for (int j = 1; j <= k; j++) R[k][j] = R[k][j-1] + (R[k][j-1] - R[k-1][j-1]) / (Math.pow(4, j) - 1);
}
return R[K-1][K-1];
}
private static double integrateMethod(String m, Func f, double a, double b, int n) {
return switch (m) {
case "trapezoidal" -> trap(f, a, b, n);
case "simpson" -> simpson(f, a, b, n);
case "simpson38" -> simpson38(f, a, b, n);
case "gaussian" -> gauss5(f, a, b);
case "romberg" -> romberg(f, a, b);
default -> throw new IllegalArgumentException("Unsupported method: " + m);
};
}
private record AdaptiveResult(double value, int intervals, double err) {}
private static AdaptiveResult adaptive(String m, Func f, double a, double b, int n, double tol) {
int curN = n;
double prev = integrateMethod(m, f, a, b, curN);
for (int i = 0; i < 20; i++) {
curN *= 2;
double cur = integrateMethod(m, f, a, b, curN);
double err = Math.abs(cur - prev);
if (err < tol) return new AdaptiveResult(cur, curN, err);
prev = cur;
}
return new AdaptiveResult(prev, curN, Double.NaN);
}
private static AdaptiveResult handleInfinite(Func f, double a, double b, String m, int n, double tol) {
if (Double.isFinite(a) && Double.isFinite(b)) return adaptive(m, f, a, b, n, tol);
if (Double.isFinite(a) && !Double.isFinite(b)) {
Func g = (t) -> f.f(a + t / (1 - t)) / ((1 - t) * (1 - t));
return adaptive(m, g, 0, 1 - 1e-8, n, tol);
}
if (!Double.isFinite(a) && Double.isFinite(b)) {
Func g = (t) -> f.f(b - t / (1 - t)) / ((1 - t) * (1 - t));
return adaptive(m, g, 0, 1 - 1e-8, n, tol);
}
Func g = (t) -> {
double x = Math.tan(Math.PI * (t - 0.5));
return f.f(x) * Math.PI / Math.pow(Math.cos(Math.PI * (t - 0.5)), 2);
};
return adaptive(m, g, 1e-8, 1 - 1e-8, n, tol);
}
private static double integrateData(Path p, String method) throws IOException {
List<double[]> rows = new ArrayList<>();
for (String line : Files.readAllLines(p, StandardCharsets.UTF_8)) {
if (line.trim().isEmpty()) continue;
String[] parts = line.split(",");
rows.add(new double[] { Double.parseDouble(parts[0]), Double.parseDouble(parts[1]) });
}
rows.sort(Comparator.comparingDouble(a -> a[0]));
if (rows.size() < 2) throw new IllegalArgumentException("Tabulated data needs at least 2 points");
if ("trapezoidal".equals(method)) {
double s = 0;
for (int i = 0; i < rows.size() - 1; i++) s += 0.5 * (rows.get(i + 1)[0] - rows.get(i)[0]) * (rows.get(i)[1] + rows.get(i + 1)[1]);
return s;
}
Func f = (xp) -> {
if (xp <= rows.get(0)[0]) return rows.get(0)[1];
if (xp >= rows.get(rows.size()-1)[0]) return rows.get(rows.size()-1)[1];
for (int i = 0; i < rows.size()-1; i++) {
double x0 = rows.get(i)[0], x1 = rows.get(i+1)[0];
if (xp >= x0 && xp <= x1) {
double t = (xp - x0)/(x1 - x0);
return rows.get(i)[1]*(1-t) + rows.get(i+1)[1]*t;
}
}
return 0;
};
return simpson(f, rows.get(0)[0], rows.get(rows.size()-1)[0], 1000);
}
private static List<Map<String, Object>> compareAll(Func f, double a, double b, int n, double tol) {
List<String> methods = List.of("trapezoidal", "simpson", "simpson38", "gaussian", "romberg");
List<Map<String, Object>> out = new ArrayList<>();
for (String m : methods) {
long t0 = System.nanoTime();
AdaptiveResult r = handleInfinite(f, a, b, m, n, tol);
out.add(Map.of("method", m, "value", r.value, "estimatedError", r.err, "intervals", r.intervals, "timeMs", (System.nanoTime()-t0)/1_000_000.0));
}
return out;
}
private static List<Map<String, Object>> knownDemo() {
record Case(String name, String expr, double a, double b, double exact) {}
List<Case> cases = List.of(
new Case("integral sin(x) [0,pi]", "sin(x)", 0, Math.PI, 2),
new Case("integral exp(-x^2) [0,inf]", "exp(-x^2)", 0, Double.POSITIVE_INFINITY, Math.sqrt(Math.PI)/2),
new Case("integral 1/x [1,e]", "1/x", 1, Math.E, 1)
);
List<Map<String, Object>> out = new ArrayList<>();
for (Case c : cases) {
Func f = compile(c.expr);
for (String m : List.of("trapezoidal", "simpson", "simpson38", "gaussian", "romberg")) {
AdaptiveResult r = handleInfinite(f, c.a, c.b, m, 1000, 1e-10);
out.add(Map.of("case", c.name, "method", m, "computed", r.value, "exact", c.exact, "relativeError", Math.abs((r.value - c.exact)/c.exact)));
}
}
return out;
}
private static Map<String, Object> cfgMap(Config cfg) {
Map<String, Object> m = new LinkedHashMap<>();
m.put("function", cfg.fn);
m.put("lower", cfg.lower);
m.put("upper", cfg.upper);
m.put("method", cfg.method);
m.put("intervals", cfg.intervals);
m.put("compare", cfg.compare);
m.put("tolerance", cfg.tolerance);
m.put("infinite", cfg.infinite);
m.put("data", cfg.data);
m.put("output", cfg.output);
return m;
}
private static String toJson(Object obj) {
if (obj == null) return "null";
if (obj instanceof String s) return '"' + s.replace("\\", "\\\\").replace("\"", "\\\"") + '"';
if (obj instanceof Number || obj instanceof Boolean) return obj.toString();
if (obj instanceof Map<?, ?> m) {
StringBuilder sb = new StringBuilder("{");
boolean first = true;
for (Map.Entry<?, ?> e : m.entrySet()) {
if (!first) sb.append(',');
first = false;
sb.append(toJson(String.valueOf(e.getKey()))).append(':').append(toJson(e.getValue()));
}
sb.append('}');
return sb.toString();
}
if (obj instanceof Iterable<?> it) {
StringBuilder sb = new StringBuilder("[");
boolean first = true;
for (Object x : it) {
if (!first) sb.append(',');
first = false;
sb.append(toJson(x));
}
sb.append(']');
return sb.toString();
}
return toJson(String.valueOf(obj));
}
}