Generated reference › Weibull Fit — Control Systems/Curve Fitting
kind: generated#block#control-systems-curve-fitting

Weibull Fit — Control Systems/Curve Fitting

Control_Systems/Curve_Fitting/Weibull_Fit · 1 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Weibull Fit

Control Systems / Curve Fitting

Fits the two-parameter Weibull curve to the last W samples by nonlinear least squares and emits its two parameters:

ŷ(x) = a·b·xb−1·e−a·xb, for x > 0

This is MATLAB's weibull library model, and the output carries a then b – coeffnames(fittype('weibull'))'s own order. b is the shape (b = 1 is a plain exponential decay, b > 1 a curve that rises from zero, peaks and falls) and a is the scale: the curve peaks at x = ((b−1)/(a·b))1/b. Unlike every other fit in this family the model is not linear in its parameters, so the block runs a real iteration per sample – see Notes.

Ports

  • u – the sampled signal being fitted; it is the ordinate y, one value per step. Scalar: one channel and its own window – see Notes.
  • ab – the parameter column, [2, 1]: row 1 is a, row 2 is b. Its height is fixed and does not follow any setting.

Parameters

  • Options – empty (default), or the path of a Fit Options block (Home/Fit Options), MATLAB’s fitoptions: for the run, its Start Point and Maximum Iterations replace this block’s Start Point and Iterations where it has them; an option it leaves at default changes nothing.
  • Window Length – W, how many samples the fit sees. A whole number from 3 to 101. Two parameters need at least two points, and a third is the first that makes it a fit rather than an interpolation.
  • Abscissa Start – x₀, where the oldest sample of the window sits on the fitted axis. A single strictly positive number: xb−1 is undefined at zero and not a real number below it, which is why the Weibull model is only defined for a positive abscissa (fit refuses non-positive x outright).
  • Abscissa Step – h, the spacing between consecutive samples on that axis, so the newest sample sits at x₀ + (W−1)·h. A single positive number. The axis runs FORWARDS, oldest sample first, as on Power Fit.
  • Start Point – the pair [a₀ b₀] the iteration starts from, both strictly positive. It is fitoptions' StartPoint, and here it is required rather than optional: see Notes. A start far from the answer costs iterations, and on data with more than one local minimum it decides which one the block reports.
  • Iterations – how many Levenberg-Marquardt sweeps each sample runs, a whole number from 1 to 400. There is no convergence test: every sample runs exactly this many sweeps, which is what keeps ten generated cores on the same path. Convergence here is linear rather than quadratic (the residual at the optimum is large), so the count buys accuracy at a constant rate – measured against a 400-sweep answer on the rig's own data: 20 sweeps 6.6e−4, 30 sweeps 4.7e−5, 40 sweeps 3.3e−6, 60 sweeps 1.3e−8 relative.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text.

What every target carries is the iteration itself, not a bank of coefficients: the window, the 2×2 normal system, the damping and the accept/reject test are all in the generated core, and the only things inlined from the configuration are the abscissa, the start point, the bounds and the sweep count. A core therefore costs about 2·W·Iterations exponentials per step; the Window Length and Iterations settings are what a user trades against that.

The three HDL targets are simulation-only real arithmetic, quantizing only at the port boundary: an exponential, a division and a 2×2 solve have no Q16.16 form. They additionally clamp both parameters to the ±32767 that format can carry, which the seven software targets and this block's own simulation do not.

Simulink bridge

None (Support::None). Fitting a Weibull curve to a running window is a Curve Fitting Toolbox function (fit with the weibull model), and that toolbox ships no Simulink library at all, so there is no path a diagram could name. The bridge reports this block rather than dropping it silently, and it therefore has no parity testbench; code export verification still covers it across all ten languages.

Notes

  • Stateful, and discrete by nature (setDiscreteOnlyBlock(true)): the window advances once per sample.
  • ⚠ MATLAB's own start point for this model is RANDOM, and this block's is not. weibull is one of the two library models with no start-point heuristic, so fit(x, y, 'weibull') draws rand(2,1) and warns "Start point not provided, choosing random start point" – two calls on the same data need not agree. A generated core has no such draw and a stream cannot reproduce one, so Start Point is configuration here. Set it deliberately; it is the one parameter of this block that changes which answer you get rather than how fast you get it.
  • ⚠ The fit is a fixed number of sweeps, not a converged solve. There is no tolerance test, because a tolerance makes the number of sweeps depend on arithmetic that differs by one unit in the last place between backends, and the ten cores would then take different paths. Raise Iterations rather than expecting a convergence flag; the block reports no residual.
  • ⚠ Both parameters are bounded below by zero, as in MATLAB, and the bound is approached by halving. A step that would carry a or b to or past zero is replaced by a step to halfway between the current value and zero. Clamping exactly onto the bound would be worse than it sounds: at a = 0 the model's sensitivity to b is identically zero, so the 2×2 system would be singular from that iteration on. The parameters are also bounded above, at a ≤ 106 and b·|ln x| ≤ 50, so that no intermediate can overflow – a VHDL real that overflows aborts the simulation rather than returning an infinity.
  • ⚠ The abscissa runs forwards here, as on Power Fit, and backwards on the rest of this family. Polynomial Fit, Fourier Fit, Gaussian Fit, Sum of Sines Fit and Exponential Fit put the newest sample at x = 0. A Weibull has no value at zero and none below it, so this block's window is oldest at x₀ and increases towards the newest sample – an elapsed-time axis rather than a look-back one.
  • ⚠ Its output is NOT a polynomial, and Evaluate Fit cannot read it. Evaluate Fit, Fit Derivative and Fit Integral all speak coefficients in descending powers; these are the two parameters of a Weibull curve. Wiring this block into any of the three produces a number rather than an error, so the mistake is silent.
  • The window is zero-prefilled, so the first W−1 outputs of a run are a startup transient – the convention Polynomial Fit, Fourier Fit, Gaussian Fit, Exponential Fit and Power Fit all follow. On an all-zero window the least-squares answer drives a towards its lower bound and leaves b wherever the start point left it: a curve of zero height says nothing about its shape.
  • Scalar only. One channel and its own history; wire one block per channel.
  • No state space. The model is nonlinear in both parameters, so there is no A/B/C/D pair to seed and model reduction correctly declines to merge it.

Code facts#

FactValue
registered typeControl_Systems/Curve_Fitting/Weibull_Fit
familyControl_Systems/Curve_Fitting
solver environment classICoreBlock_0_Control_Systems_1_Curve_Fitting_2_Weibull_Fit
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Curve_Fitting/Weibull_Fit/ICoreBlock_0_Control_Systems_1_Curve_Fitting_2_Weibull_Fit.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Curve_Fitting/Weibull_Fit/ICoreBlock_0_Control_Systems_1_Curve_Fitting_2_Weibull_Fit.h
default size on canvas130 × 72 px
ports at insert1 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleu
2outICoreDoubleab

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Window Length12—
Abscissa Start1—
Abscissa Step1—
Start Point[1 1]—
Iterations50—
Options——

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::None
Simulink path—
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): fitting a Weibull curve to a running window is a Curve Fitting Toolbox function (fit with the weibull model), not a Simulink library block -- that toolbox ships no Simulink library at all -- so there is no path a diagram could name; the block is reported rather than dropped when a model crosses

Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Weibull Fit -- MATLAB's weibull library model over the last W samples, as the pair (a, b) y(x) = a*b*x^(b-1)*exp(-a*x^b)

formula(fittype('weibull')) in R2026a reads exactly that, coeffnames reports {a b}, and the fit options it ships carry a LOWER BOUND OF ZERO on both parameters and no upper bound. The output column carries a then b.

THE MODEL IS NOT LINEAR IN ITS PARAMETERS AND NO LOGARITHM MAKES IT SO. Exponential_Fit and Power_Fit are blocks because ln y is a straight line in their parameters; here ln y = ln(a*b) + (b-1)*ln x - a*x^b keeps a*x^b, so the design matrix is not fixed by the configuration and there is no bank to inline. Every sample runs a real nonlinear least squares -- the fixed-count Levenberg-Marquardt in ICoreNonlinearFitSupport, which this block shares with Rational_Fit and which is emitted into all ten targets from one description.

THE START POINT IS CONFIGURATION BECAUSE MATLAB'S IS A RANDOM DRAW. Measured in R2026a: startpt(fittype('weibull')) is empty, so fit(x, y, 'weibull') warns "Start point not provided, choosing random start point" and uses rand(2,1). Two calls on the same data therefore need not agree (measured: 0.1674 / 1.9376 against 0.1674 / 1.9373 on the same thirteen points), and a generated core has no such stream. This block asks for the start point instead and uses it for every window.

MEASURED AGAINST R2026a rather than asserted. Over 200 windows of the rig's own stimulus (W = 15, x0 = 0.2, h = 0.2, start [0.5 1.5], ordinate 0.3 + 0.12*U(-1,1)), the block's answer at 40 iterations reproduces fit(x, y, 'weibull', StartPoint = [0.5 1.5], TolFun = TolX = 1e-15) to a worst relative difference of 4.0e-7, and the sum of squares it reaches is within 2.3e-12 of MATLAB's on every window -- i.e. the same minimum, reached by a different step rule (Levenberg-Marquardt here, trust-region-reflective there).

⚠ CONVERGENCE IS LINEAR, NOT QUADRATIC, and the iteration count is sized for it. The residual at the optimum is large (a Weibull curve through noisy samples), so Gauss-Newton's quadratic term is missing and each sweep buys a constant factor. Measured over 2000 rig windows against a 400-iteration answer: K = 20 is 6.6e-4, K = 30 is 4.7e-5, K = 40 is 3.3e-6, K = 60 is 1.3e-8. The default is 50 and the rig runs 40.

Sample results#

Weibull Fit — Step: 0 -> 1 at t = 1 sWeibull Fit — Step: 0 -> 1 at t = 1 s051015012345t (s)in ICoreDouble-Out-0out ICoreDouble-Out-0 [2x1] entry 0

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)6.377e-5 … 18.27
rampRamp: slope 1 from t = 01.434e-4 … 18.27
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias3.371e-5 … 7.382e5
tableRepeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample0.002285 … 5e5

Plotted: step — Step: 0 -> 1 at t = 1 s

Category dynamic · sample time 0.1 · 60 steps · commit 941d69b00853e5485cdd3bd9c25ffe09be772999 · produced by docsSample --out <folder> --blocks Weibull_Fit Rational_Fit --steps 60 · data docs/generated/samples/Control_Systems__Curve_Fitting__Weibull_Fit.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).