Package jline.api.sym

Class SageRestEngine

java.lang.Object
jline.api.sym.SageRestEngine
All Implemented Interfaces:
SymEngine

public class SageRestEngine extends Object implements SymEngine
SymEngine backed by the line-sage-rest service.

The service is SageMath behind the JSON protocol in io/sage/server.py. Every request is a single POST carrying the whole problem, so nothing is bind-mounted and the client works against a container, a remote host or a hand-started server alike.

Numeric coefficients are sent as decimal strings and read server side as exact rationals, which is what keeps the solve exact: a double coerced by the CAS would carry the binary rational nearest the decimal instead.

Copyright (c) 2012-2026, Imperial College London All rights reserved.
  • Field Details

    • DEFAULT_TIMEOUT_SECONDS

      public static final int DEFAULT_TIMEOUT_SECONDS
      Default per-request timeout, in seconds.
      See Also:
  • Constructor Details

    • SageRestEngine

      public SageRestEngine(String baseUrl)
      Parameters:
      baseUrl - base URL of the service, e.g. "http://localhost:8080"
  • Method Details

    • setTimeoutSeconds

      public SageRestEngine setTimeoutSeconds(int seconds)
      Sets the per-request timeout. The server enforces it too, so a runaway symbolic solve is killed there rather than merely abandoned here.
      Parameters:
      seconds - timeout in seconds; not positive disables it
      Returns:
      this engine
    • getTimeoutSeconds

      public int getTimeoutSeconds()
      Returns:
      the per-request timeout in seconds
    • getBaseUrl

      public String getBaseUrl()
      Returns:
      the base URL this engine posts to
    • name

      public String name()
      Description copied from interface: SymEngine
      Name of the backing engine, e.g. "sage".
      Specified by:
      name in interface SymEngine
    • isAvailable

      public boolean isAvailable()
      Description copied from interface: SymEngine
      True if the engine answers a health probe.
      Specified by:
      isAvailable in interface SymEngine
    • isUsable

      public boolean isUsable()
      Checks that the service can actually EVALUATE, not merely that it answers.

      The line-sage-rest image ships a FLINT built for CPUs that have BMI2 and ADX. On an older host the first multi-limb exact operation raises SIGILL, the worker dies mid-request and the call returns no bytes at all; /api/v1/health is pure Python and keeps answering, so it cannot see this. The canary is the weighted-average softmin form, which is what the fluid export actually sends, and is the smallest expression observed to trigger it. Verdicts are cached per URL, so this costs one small request the first time a service is considered and nothing after. See _kb/11-conventions-and-gotchas.md.

      Returns:
      true if the service returned the canary's value
    • info

      public com.google.gson.JsonObject info() throws IOException
      Reads the service identity, used to tell a line-sage-rest server apart from another service listening on the same conventional port.
      Returns:
      the /api/v1/info document
      Throws:
      IOException - if the service is unreachable
    • missingRoutes

      public List<String> missingRoutes() throws IOException
      Names the routes this client needs that the service does not serve.

      A SERVICE CAN BE HEALTHY AND STILL TOO OLD, and that case used to reach the caller as a request failure rather than as a resolution failure. The roster ran a line-sage-rest image predating the ctmc/measures and ctmc/passage routes on 2026-09-11: it answered /api/v1/health, passed the isUsable() arithmetic canary, and then failed three SolverCTMCSymbolicSageTest cases with "unknown endpoint /api/v1/ctmc/measures" -- an error that reads as a defect in the solver rather than as an out-of-date container. Asking the service what it routes turns that into a named refusal at resolution time, where the caller can act on it.

      Returns:
      the missing routes, empty if the service serves them all or if it is too old to report its route list at all
      Throws:
      IOException - if the service is unreachable
    • solveCTMC

      public SymEngine.CTMCSolution solveCTMC(String[][] Q, List<String> symbols) throws IOException
      Description copied from interface: SymEngine
      Symbolic stationary distribution of a CTMC, pi Q = 0 with sum(pi) = 1.
      Specified by:
      solveCTMC in interface SymEngine
      Parameters:
      Q - generator entries as expression strings, row major
      symbols - the symbols appearing in Q, e.g. x1..xE
      Returns:
      the solution, with pi also split over a common denominator
      Throws:
      IOException - if the engine is unreachable or rejects the request
    • ctmcSensitivity

      public SymEngine.Sensitivity ctmcSensitivity(String[][] Q, List<String> symbols, String theta, List<String> reward) throws IOException
      Description copied from interface: SymEngine
      Exact parametric sensitivity of a steady-state reward.
      Specified by:
      ctmcSensitivity in interface SymEngine
      Parameters:
      Q - generator entries as expression strings, row major
      symbols - the symbols appearing in Q
      theta - the symbol to differentiate with respect to
      reward - reward rate per state, or null for the distribution alone
      Returns:
      the sensitivity of the distribution and, if a reward is given, of its mean
      Throws:
      IOException - if the engine is unreachable or rejects the request
    • simplify

      public List<String> simplify(List<String> exprs, String form) throws IOException
      Description copied from interface: SymEngine
      Rewrites expressions into a normal form.
      Specified by:
      simplify in interface SymEngine
      Parameters:
      exprs - the expressions
      form - one of simplify, factor, together, cancel, expand, latex
      Returns:
      the rewritten expressions, in the input order
      Throws:
      IOException - if the engine is unreachable or rejects the request
    • diff

      public List<String> diff(List<String> exprs, String variable, int order) throws IOException
      Description copied from interface: SymEngine
      Differentiates expressions.
      Specified by:
      diff in interface SymEngine
      Parameters:
      exprs - the expressions
      variable - the differentiation variable
      order - the order of the derivative, at least 1
      Returns:
      the derivatives, in the input order
      Throws:
      IOException - if the engine is unreachable or rejects the request
    • eval

      public double[] eval(List<String> exprs, Map<String,Double> assignment) throws IOException
      Description copied from interface: SymEngine
      Substitutes values for symbols and evaluates.
      Specified by:
      eval in interface SymEngine
      Parameters:
      exprs - the expressions
      assignment - value of each symbol
      Returns:
      the numeric values, NaN where a free symbol remains
      Throws:
      IOException - if the engine is unreachable or rejects the request
    • fluidODEs

      public SymEngine.FluidODEs fluidODEs(List<String> rhs, List<String> vars, List<String> want) throws IOException
      Description copied from interface: SymEngine
      Jacobian, LaTeX form and equilibria of a fluid vector field.
      Specified by:
      fluidODEs in interface SymEngine
      Parameters:
      rhs - the right hand side of dx/dt, one expression per state variable
      vars - the state variable names
      want - any of jacobian, latex, equilibria
      Returns:
      the requested items
      Throws:
      IOException - if the engine is unreachable or rejects the request
    • ctmcMeasures

      public SymEngine.CTMCMeasures ctmcMeasures(String[][] Q, List<String> symbols, String[][] weights, List<String> names, List<SymEngine.RatioSpec> ratios) throws IOException
      Description copied from interface: SymEngine
      Stationary distribution and a set of weighted sums of it.

      Every mean SolverCTMC reports is a NUMERIC linear functional of pi, so the caller builds one weight vector per measure with no algebra at all and this one round trip returns each w . pi as a rational function: a throughput is pi . depRates, a queue length is pi . stateSpaceAggr, a marginal probability is pi . indicator and a mean reward is pi . r.

      Specified by:
      ctmcMeasures in interface SymEngine
      Parameters:
      Q - generator entries as expression strings, row major
      symbols - the symbols appearing in Q
      weights - one row per measure, each of length Q.length; entries are parsed in the same field as Q, so an expression is admissible and not only a number
      names - a name per weight row, or null for w0, w1, ...
      ratios - ratios of two measures, or null for none
      Returns:
      the distribution, the measures and the ratios
      Throws:
      IOException - if the engine is unreachable or rejects the request
    • ctmcPassage

      public SymEngine.Passage ctmcPassage(String[][] S, String[] s0, String[] alpha, String atom, List<String> symbols, String svar, List<String> want, int nmax) throws IOException
      Description copied from interface: SymEngine
      First passage time into a target set: the transform and the moments.

      With A the complement of the target, S = Q(A,A) the sub-generator, s0 = -S*1 the exit vector and alpha the initial law restricted to A, following Harrison and Knottenbelt (2002),

        L(s) = alpha (sI - S)^-1 s0 + atom        Eqs. 1-2
        (-S) M(n) = n M(n-1),  M(0) = 1           Eq. 3

      The MOMENTS come from the recursion, not from differentiating L: it carries no transform symbol, stays in the same fraction field and is nmax right solves against one matrix. Differentiating instead would leave the fraction field, and the evaluation at s = 0 can hit 0/0 where a factor of s failed to cancel.

      Specified by:
      ctmcPassage in interface SymEngine
      Parameters:
      S - the sub-generator on the non-target states, row major
      s0 - the exit vector -S*1
      alpha - the initial law restricted to the non-target states
      atom - the initial mass already inside the target set
      symbols - the rate symbols appearing in S
      svar - the transform symbol; adjoined to the field only when a transform is asked for, and required to differ from every rate symbol
      want - any of lst, lstall, moments, momall
      nmax - highest moment order, at least 1
      Returns:
      the requested items
      Throws:
      IOException - if the engine is unreachable or rejects the request