← All tasks
javacodex/java-t1 #45Not a task: already works

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));
    }
}