<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>admin &#8211; Aptech</title>
	<atom:link href="https://www.aptech.com/blog/author/admin/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.aptech.com</link>
	<description>GAUSS Software - Fastest Platform for Data Analytics</description>
	<lastBuildDate>Thu, 30 Jul 2026 01:07:10 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>Keyword Arguments in GAUSS: Write Self-Documenting Code</title>
		<link>https://www.aptech.com/blog/keyword-arguments-in-gauss-write-self-documenting-code/</link>
					<comments>https://www.aptech.com/blog/keyword-arguments-in-gauss-write-self-documenting-code/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Thu, 30 Jul 2026 01:07:10 +0000</pubDate>
				<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">https://www.aptech.com/?p=11585859</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[<h3 id="introduction">Introduction</h3>
<p>Keyword procedure arguments, introduced in GAUSS 26.1, give you the ability to write cleaner code that is more concise, easier to write, and easier to read. Just as importantly, they are intuitive enough that you can start using them immediately. Today we'll show you everything you need to know to make your work easier right away.</p>
<h2 id="self-documenting-code-with-keyword-inputs">Self-documenting Code with Keyword Inputs</h2>
<p>GAUSS has long had optional inputs, so you did not have to pass in every possible input. However, they were <strong>positional inputs</strong>. Positional inputs have to be passed in a specific order. So if you wanted to use the seventh input, you would have to pass in all seven--and remember which order to pass them in. </p>
<p>For example, let's consider a hypothetical procedure named <code>myEstimate()</code> that fits an ARDL-style model and takes:</p>
<ul>
<li><strong>y</strong> - Time series vector.</li>
<li><strong>X</strong> - Exogenous variables.</li>
<li><strong>y_lags</strong> - Set of lags of the dependent variable to include in the estimation. Default = {}, no y-lags.</li>
<li><strong>X_lags</strong> - Set of lags of the exogenous variables to include in the estimation. Default = {}, no X-lags.</li>
<li><strong>const</strong> - 0, no constant. 1, include a constant. Default = 1.</li>
<li><strong>trend</strong> - 0, no trend. 1, include a trend. Default = 0.</li>
<li><strong>quiet</strong> - 1, no output report. 0, print an output summary. Default = 0.</li>
</ul>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Before — to set quiet, you have to pass everything ahead of it
result = myEstimate(y, X, {1 2}, {}, 1, 0, 1);</code></pre>
<p>can be written as:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Using keyword inputs
result = myEstimate(y, X, y_lags={1 2}, quiet=1);

// Keyword inputs can be in any order
result = myEstimate(y, X, quiet=1, y_lags={1 2});</code></pre>
<p>As we see above, the keyword input version:</p>
<ol>
<li>Is concise and readable.</li>
<li>Does not require you to remember the input order.</li>
<li>Does not make you set inputs, like <strong>trend</strong>, that you want to leave at the default setting.</li>
</ol>
<h2 id="adding-keyword-inputs-to-your-own-procedures">Adding Keyword Inputs to Your Own Procedures</h2>
<p>Next we'll convert the following simple simulation procedure to use keyword inputs.</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">proc (1) = simulate(nrows, ncols, mu, sd);
    local X;
    X = (rndn(nrows, ncols) * sd) + mu;
    retp(X);
endp;</code></pre>
<h3 id="declaring-keyword-inputs">Declaring Keyword Inputs</h3>
<p>To convert the inputs to <code>simulate()</code> to keyword arguments, all we need to do is add an equals sign and the default value after the input in the procedure definition.</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">proc (1) = simulate(nrows=5, ncols=1, mu=0, sd=1);
    local X;
    X = (rndn(nrows, ncols) * sd) + mu;
    retp(X);
endp;</code></pre>
<p>Now we can call our procedure with no inputs if we want:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Set for repeatable random numbers
rndseed 23423;

print simulate();</code></pre>
<pre>     0.4372582
    -0.3276965
     0.9718211
    -0.0842395
    -0.3505402</pre>
<h3 id="what-can-be-a-default-value">What Can be a Default Value</h3>
<p>Default values can be any literal value of any data type. They can be scalars as in our previous example, matrices, strings, or string arrays.</p>
<table>
<thead>
<tr>
<th>Default Type</th>
<th>Example</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Scalar</td>
<td><code>sd = 1</code>, <code>tol = -2.5e-3</code></td>
<td>Integers, decimals, and scientific notation</td>
</tr>
<tr>
<td>Vector or matrix</td>
<td><code>mu = {0 100}</code>, <code>w = {1 2, 3 4}</code></td>
<td>Spaces separate columns, commas separate rows</td>
</tr>
<tr>
<td>String</td>
<td><code>dist = "normal"</code></td>
<td>Enclosed in double quotes</td>
</tr>
<tr>
<td>String array</td>
<td><code>names = {"y1", "y2"}</code></td>
<td>Produces a true string array</td>
</tr>
<tr>
<td>Empty matrix</td>
<td><code>xreg = {}</code></td>
<td>The standard way to mark an input as &quot;not supplied&quot;</td>
</tr>
</tbody>
</table>
<h3 id="what-cannot-be-a-default-value">What Cannot be a Default Value</h3>
<table>
<thead>
<tr>
<th>Not Allowed</th>
<th>Example</th>
<th>Why</th>
</tr>
</thead>
<tbody>
<tr>
<td>Variables</td>
<td><code>a = n</code></td>
<td>Defaults are stored as source text, so they can't reference other symbols</td>
</tr>
<tr>
<td>Expressions</td>
<td><code>a = n*2</code>, <code>k = 1+1</code></td>
<td>Operators are not permitted in a default</td>
</tr>
<tr>
<td>Reserved words as inputs</td>
<td><code>trim = 0</code>, <code>output = 1</code></td>
<td>Input names can't shadow a GAUSS command or function</td>
</tr>
</tbody>
</table>
<h2 id="calling-a-procedure-with-keyword-inputs">Calling a Procedure with Keyword Inputs</h2>
<h3 id="rules-for-calling-a-procedure-with-keyword-inputs">Rules for Calling a Procedure with Keyword Inputs</h3>
<ol>
<li><strong>Positional inputs come first.</strong> Once you pass an input by name, every input after it must also be passed by name.</li>
<li><strong>Only inputs with a default can be passed by name.</strong> An input declared without a default is positional-only.</li>
<li><strong>Named inputs can appear in any order.</strong></li>
<li><strong>Any named input you leave out uses its default.</strong></li>
</ol>
<h3 id="mixing-positional-and-keyword-inputs">Mixing Positional and Keyword Inputs</h3>
<p>Coming back to our opening example:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">result = myEstimate(y, X, y_lags={1 2}, quiet=1);</code></pre>
<p><code>y</code> and <code>X</code> are passed by position, everything else is by name. Since there is no sensible default for your data, they should be required. Inputs declared without a default are positional inputs. They must be passed in before any keyword inputs and they have to be passed in the order the procedure declares them.</p>
<p>Let's continue with a modified version of our <code>simulate()</code> procedure, because it's short and simple.</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Simulate with 1 required positional input
proc (1) = simulate(nrows, ncols=1, mu=0, sd=1);
    local X;
    X = (rndn(nrows, ncols) * sd) + mu;
    retp(X);
endp;

// For repeatable random numbers
rndseed 23423;

print simulate(3, sd=2.5);</code></pre>
<pre>       1.0931455
     -0.81924125
       2.4295527</pre>
<p>Keyword inputs can also be passed by position, so all of the following calls are equivalent:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">rndseed 23423;
print simulate(3, sd=2.5);

rndseed 23423;
print simulate(3, 1, 0, sd=2.5);

rndseed 23423;
print simulate(3, 1, 0, 2.5);</code></pre>
<pre>       1.0931455
     -0.81924125
       2.4295527

       1.0931455
     -0.81924125
       2.4295527

       1.0931455
     -0.81924125
       2.4295527</pre>
<p>If you misspell the name of a keyword input, GAUSS suggests the closest match:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Incorrect: error G0739 : Unknown keyword argument 'ncol (did you mean ncols?)'
x = simulate(3, ncol=2);</code></pre>
<p>However, here are two things to watch out for. First, once you name an input, everything after must be named:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Incorrect: error G0741 : Positional argument after keyword argument
x = simulate(3, ncols=1, 0);</code></pre>
<p>Second, a positional input can't be passed by name:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Incorrect: error G0739 : Unknown keyword argument 'nrows (did you mean ncols?)'
x = simulate(nrows=10);</code></pre>
<p><code>nrows</code> is an input to <code>simulate()</code>, but it is not a named keyword input, because the procedure did not declare a default value. Therefore, it cannot be called by name.</p>
<h2 id="will-keyword-inputs-slow-down-my-code">Will Keyword Inputs Slow Down My Code?</h2>
<p>No. GAUSS resolves keyword inputs when your code is compiled, not when it runs. The compiler matches each name to its position, fills in the defaults for anything you left out, and rewrites the call as an ordinary positional call. By the time your program executes, the two versions are the same code.</p>
<p>That matters if you are calling a procedure thousands of times inside an estimation loop, so here is a test with ten million calls of each form:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">proc (1) = addup(a, b=1, c=2, d=3);
    retp(a + b + c + d);
endp;

n = 10000000;

t0 = hsec;
for i (1, n, 1);
    x = addup(1, 2, 3, 4);
endfor;
print "positional:" (hsec-t0)/100 "sec";

t0 = hsec;
for i (1, n, 1);
    x = addup(1, b=2, c=3, d=4);
endfor;
print "keyword:   " (hsec-t0)/100 "sec";</code></pre>
<pre>positional:      0.73844300 sec
keyword:         0.73672700 sec</pre>
<p>Your timings will differ from machine to machine, but the two forms will always track each other. Write your calls whichever way reads best.</p>
<h3 id="conclusion">Conclusion</h3>
<p>Keyword inputs are a small addition to the language that makes a large difference in how your code reads. To recap:</p>
<ul>
<li>Give an input a default value in the procedure definition to make it a keyword input.</li>
<li>Call it by name, in any order, and leave out anything you want to keep at its default.</li>
<li>Inputs without a default stay positional, and they come first.</li>
<li>Defaults must be literals — scalars, matrices, strings, string arrays, or an empty matrix.</li>
<li>Naming your inputs costs nothing at runtime.</li>
</ul>
<p>The best part is that there is nothing to migrate. Every procedure you have already written keeps working exactly as it does today, and you can add defaults to them whenever it's convenient. The libraries that ship with GAUSS will adopt the same style in GAUSS 27, so your calls to them will get shorter too.</p>
<p>Keyword inputs are one of several GAUSS 26.1 features aimed at cleaner, more concise code. We'll cover the others in upcoming posts:</p>
<ul>
<li><strong>Struct type inference</strong> — call a procedure that returns a struct without declaring the receiving variable first.</li>
<li><strong>Matrix and string array literals</strong> — use <code>{1, 2, 3}</code> and <code>{"a", "b"}</code> directly in expressions and procedure calls.</li>
</ul>]]></content:encoded>
					
					<wfw:commentRss>https://www.aptech.com/blog/keyword-arguments-in-gauss-write-self-documenting-code/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>MLE with Bounded Parameters: A Cleaner Approach</title>
		<link>https://www.aptech.com/blog/mle-with-bounded-parameters-a-cleaner-approach/</link>
					<comments>https://www.aptech.com/blog/mle-with-bounded-parameters-a-cleaner-approach/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Wed, 08 Apr 2026 17:56:17 +0000</pubDate>
				<category><![CDATA[Econometrics]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">https://www.aptech.com/?p=11585713</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>It's natural in data analysis applications for parameters to have bounds; variances can't be negative, GARCH coefficients must sum to less than one for stationarity, and mixing proportions live between zero and one. </p>
<p>When you estimate these models by maximum likelihood, the optimizer needs to respect those bounds, not just at the solution, but throughout the search. If optimization searches wander into invalid territory, it can impact the reliability and convergence of your results. For example, you may get complex numbers from negative variances, explosive forecasts from non-stationary GARCH, or likelihoods that make no sense.</p>
<p><a href="https://www.aptech.com/blog/gauss26/" target="_blank" rel="noopener">GAUSS 26.0.1</a> introduces <a href="https://docs.aptech.com/gauss/minimize.html#minimize" target="_blank" rel="noopener"><code>minimize</code></a>, the first new GAUSS optimizer in over 10 years, to handle this cleanly. </p>
<p>The <code>minimize</code> optmizer let's you specify bounds directly and GAUSS internally keeps parameters feasible at every iteration. No more log-transforms, no penalty functions, and no doublechecking.</p>
<p>In today's blog, we'll see the new <code>minimize</code> function in action, as we walk through two examples: </p>
<ul>
<li>A GARCH estimation where variance parameters must be positive</li>
<li>A Stochastic frontier models where both variance components must be positive. </li>
</ul>
<p>In both cases, bounded optimization makes estimation easier and aligns results with theory.</p>
<h2 id="why-bounds-matter">Why Bounds Matter</h2>
<p>To see why this matters in practice, let’s look at a familiar example. Consider a GARCH(1,1) model:</p>
<p>$\sigma^2_t = \omega + \alpha \varepsilon^2_{t-1} + \beta \sigma^2_{t-1}$</p>
<p>For this model to be well-defined and economically meaningful:</p>
<ul>
<li>The baseline variance must be positive ($\omega \gt 0$)</li>
<li>Shocks and persistence must contribute non-negatively to variance ($\alpha \geq 0$, $\beta \geq 0$)</li>
<li>The model must be stationary ($\alpha + \beta \lt 1$)</li>
</ul>
<p>The traditional workaround is to estimate transformed parameters, $\log(\omega)$ instead of $\omega$, then convert back. This works, but it distorts the optimization surface and complicates standard error calculations. You're not estimating the parameters you care about; you're estimating transforms and hoping the numerics work out.</p>
<p>With bounded optimization, you estimate $\omega$, $\alpha$, and $\beta$ directly, with the optimizer respecting the constraints throughout.</p>
<h2 id="example-1-garch11-on-commodity-returns">Example 1: GARCH(1,1) on Commodity Returns</h2>
<p>Let's estimate a GARCH(1,1) model on a dataset of 248 observations of commodity price returns (this data is included in the GAUSS 26 examples directory). </p>
<h3 id="step-one-data-and-likelihood">Step One: Data and Likelihood</h3>
<p>First, we load the data and specify our log-likelihood objective function. </p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Load returns data (ships with GAUSS)
fname = getGAUSShome("examples/df_returns.gdat");
returns = loadd(fname, "rcpi");

// GARCH(1,1) negative log-likelihood
proc (1) = garch_negll(theta, y);
    local omega, alpha, beta_, sigma2, ll, t;

    omega = theta[1];
    alpha = theta[2];
    beta_ = theta[3];

    sigma2 = zeros(rows(y), 1);

    // Initialize with sample variance
    sigma2[1] = stdc(y)^2;

    // Variance recursion
    for t (2, rows(y), 1);
        sigma2[t] = omega + alpha * y[t-1]^2 + beta_ * sigma2[t-1];
    endfor;

    // Gaussian log-likelihood
    ll = -0.5 * sumc(ln(2*pi) + ln(sigma2) + (y.^2) ./ sigma2);

    retp(-ll);  // Return negative for minimization
endp;</code></pre>
<h3 id="step-two-setting-up-optimization">Step Two: Setting Up Optimization</h3>
<p>Now we set up the bounded optimization with:</p>
<ul>
<li>$\omega \gt 0$ (small positive lower bound to avoid numerical issues)</li>
<li>$\alpha \geq 0$</li>
<li>$\beta \geq 0$</li>
</ul>
<p>Because <code>minimize</code> handles simple box constraints, we impose individual upper bounds on $\alpha$ and $\beta$ to keep the optimizer in a reasonable region. We'll verify the stationarity condition, $\alpha + \beta \lt 1$ after estimation. </p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Starting values
theta0 = { 0.00001,   // omega (small, let data speak)
           0.05,      // alpha
           0.90 };    // beta

// Set up minimize
struct minimizeControl ctl;
ctl = minimizeControlCreate();

// Bounds: all parameters positive, alpha + beta &lt; 1
ctl.bounds = { 1e-10      1,      // omega in [1e-10, 1]
               0          1,      // alpha in [0, 1]
               0     0.9999 };    // beta in [0, 0.9999]</code></pre>
<div class="alert alert-info" role="alert">We cap $\beta$ slightly below 1 to avoid numerical issues near the boundary, where the likelihood surface can become flat and unstable.</div>
<h3 id="step-three-running-the-model">Step Three: Running the Model</h3>
<p>Finally, we call <code>minimize</code> to run our model.</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Estimate
struct minimizeOut out;
out = minimize(&amp;garch_negll, theta0, returns, ctl);</code></pre>
<h3 id="results-and-visualization">Results and Visualization</h3>
<p>After estimation, we'll extract the conditional variance series and confirm the stationarity condition: </p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Extract estimates
omega_hat = out.x[1];
alpha_hat = out.x[2];
beta_hat = out.x[3];

print "omega = " omega_hat;
print "alpha = " alpha_hat;
print "beta  = " beta_hat;
print "alpha + beta = " alpha_hat + beta_hat;
print "Iterations: " out.iterations;</code></pre>
<p>Output:</p>
<pre>omega = 0.0000070
alpha = 0.380
beta  = 0.588

alpha + beta = 0.968
Iterations: 39</pre>
<p>There are a few noteworthy results:</p>
<ol>
<li>The high persistence ($\alpha + \beta \approx 0.97$) means volatility shocks decay slowly. </li>
<li>The relatively high $\alpha$ (0.38) indicates that recent shocks have substantial immediate impact on variance. </li>
<li>The optimization converged in 39 iterations with all parameters staying inside their bounds throughout. No invalid variance evaluations, no numerical exceptions.</li>
</ol>
<p>Visualizing the conditional variance alongside the original series provides further insight:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Compute conditional variance series for plotting
T = rows(returns);
sigma2_hat = zeros(T, 1);
sigma2_hat[1] = stdc(returns)^2;

for t (2, T, 1);
    sigma2_hat[t] = omega_hat + alpha_hat * returns[t-1]^2 + beta_hat * sigma2_hat[t-1];
endfor;

// Plot returns and conditional volatility
struct plotControl plt;
plt = plotGetDefaults("xy");
plotSetTitle(&amp;plt, "GARCH(1,1): Returns and Conditional Volatility");
plotSetYLabel(&amp;plt, "Returns / Volatility");

plotLayout(2, 1, 1);
plotXY(plt, seqa(1, 1, T), returns);

plotLayout(2, 1, 2);
plotSetTitle(&amp;plt, "Conditional Standard Deviation");
plotXY(plt, seqa(1, 1, T), sqrt(sigma2_hat));</code></pre>
<p><a href="https://www.aptech.com/wp-content/uploads/2026/04/garch-plot-var.png"><img src="https://www.aptech.com/wp-content/uploads/2026/04/garch-plot-var.png" alt="" width="640" height="480" class="aligncenter size-full wp-image-11585776" /></a></p>
<p>The plot shows volatility clustering: periods of high volatility tend to persist, consistent with what we observe in commodity markets.</p>
<h2 id="example-2-stochastic-frontier-model">Example 2: Stochastic Frontier Model</h2>
<p>Stochastic frontier analysis separates random noise from systematic inefficiency. It's widely used in productivity analysis to measure how far firms operate below their production frontier.</p>
<p>The model:</p>
<p>$y = X\beta + v - u$</p>
<p>where:</p>
<ul>
<li>$v \sim N(0, \sigma^2_v)$ — symmetric noise (measurement error, luck)</li>
<li>$u \sim N^+(0, \sigma^2_u)$ — one-sided inefficiency (always reduces output)</li>
</ul>
<p>Both variance components must be positive. If the optimizer tries $\sigma^2_v \lt 0$ or $\sigma^2_u \lt 0$, the likelihood involves square roots of negative numbers.</p>
<h3 id="step-one-data-and-likelihood-1">Step One: Data and Likelihood</h3>
<p>For this example, we'll simulate data from a Cobb-Douglas production function with inefficiency. This keeps the example self-contained and lets you see exactly what's being estimated.</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Simulate production data
rndseed 8675309;
n = 500;

// Inputs (labor, capital, materials)
labor = exp(2 + 0.5*rndn(n, 1));
capital = exp(3 + 0.7*rndn(n, 1));
materials = exp(2.5 + 0.4*rndn(n, 1));

// True parameters
beta_true = { 1.5,    // constant
              0.4,    // labor elasticity
              0.3,    // capital elasticity
              0.25 }; // materials elasticity
sig2_v_true = 0.02;   // noise variance
sig2_u_true = 0.08;   // inefficiency variance

// Generate output with noise (v) and inefficiency (u)
v = sqrt(sig2_v_true) * rndn(n, 1);
u = sqrt(sig2_u_true) * abs(rndn(n, 1));  // half-normal

X = ones(n, 1) ~ ln(labor) ~ ln(capital) ~ ln(materials);
y = X * beta_true + v - u;  // inefficiency reduces output</code></pre>
<p>After simulating our data, we specify the log-likelihood function for minimization:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Stochastic frontier log-likelihood (half-normal inefficiency)
proc (1) = sf_negll(theta, y, X);
    local k, beta_, sig2_v, sig2_u, sigma, lambda;
    local eps, z, ll;

    k = cols(X);
    beta_ = theta[1:k];
    sig2_v = theta[k+1];
    sig2_u = theta[k+2];

    sigma = sqrt(sig2_v + sig2_u);
    lambda = sqrt(sig2_u / sig2_v);

    eps = y - X * beta_;
    z = -eps * lambda / sigma;

    ll = -0.5*ln(2*pi) + ln(2) - ln(sigma)
         - 0.5*(eps./sigma).^2 + ln(cdfn(z));

    retp(-sumc(ll));
endp;</code></pre>
<h3 id="step-two-setting-up-optimization-1">Step Two: Setting Up Optimization</h3>
<p>As we did in our previous example, we begin with our starting values. For this model, we run OLS and use the residual variance as starting values:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// OLS for starting values
beta_ols = invpd(X'X) * X'y;
resid = y - X * beta_ols;
sig2_ols = meanc(resid.^2);

// Starting values: Split residual variance 
// between noise and inefficiency
theta0 = beta_ols | (0.5 * sig2_ols) | (0.5 * sig2_ols);</code></pre>
<p>We leave our coefficients unbounded but constrain the variances to be positive:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Bounds: coefficients unbounded, variances positive
k = cols(X);
struct minimizeControl ctl;
ctl = minimizeControlCreate();
ctl.bounds = (-1e300 * ones(k, 1) | 0.001 | 0.001) ~ (1e300 * ones(k+2, 1));</code></pre>
<h3 id="step-three-running-the-model-1">Step Three: Running the Model</h3>
<p>Finally, we call <code>minimize</code> to estimate our model: </p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Estimate
struct minimizeOut out;
out = minimize(&amp;sf_negll, theta0, y, X, ctl);</code></pre>
<h3 id="results-and-visualization-1">Results and Visualization</h3>
<p>Now that we've estimated our model, let's examine our results. </p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Extract estimates
k = cols(X);
beta_hat = out.x[1:k];
sig2_v_hat = out.x[k+1];
sig2_u_hat = out.x[k+2];

print "Coefficients:";
print "  constant     = " beta_hat[1];
print "  ln(labor)    = " beta_hat[2];
print "  ln(capital)  = " beta_hat[3];
print "  ln(materials)= " beta_hat[4];
print "";
print "Variance components:";
print "  sig2_v (noise)       = " sig2_v_hat;
print "  sig2_u (inefficiency)= " sig2_u_hat;
print "  ratio sig2_u/total   = " sig2_u_hat / (sig2_v_hat + sig2_u_hat);
print "";
print "Iterations: " out.iterations;</code></pre>
<p>This prints out coefficients and variance components:</p>
<pre>Coefficients:
  constant     = 1.51
  ln(labor)    = 0.39
  ln(capital)  = 0.31
  ln(materials)= 0.24

Variance components:
  sig2_v (noise)       = 0.022
  sig2_u (inefficiency)= 0.087
  ratio sig2_u/total   = 0.80

Iterations: 38</pre>
<p>The estimates recover the true parameters reasonably well. The variance ratio ($\approx 0.80$) tells us that most residual variation is systematic inefficiency, not measurement error — an important finding for policy.</p>
<p>We can also compute and plot firm-level efficiency scores:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Compute efficiency estimates (Jondrow et al. 1982)
eps = y - X * beta_hat;
sigma = sqrt(sig2_v_hat + sig2_u_hat);
lambda = sqrt(sig2_u_hat / sig2_v_hat);

mu_star = -eps * sig2_u_hat / (sig2_v_hat + sig2_u_hat);
sig_star = sqrt(sig2_v_hat * sig2_u_hat / (sig2_v_hat + sig2_u_hat));

// E[u|eps] - conditional mean of inefficiency
u_hat = mu_star + sig_star * (pdfn(mu_star/sig_star) ./ cdfn(mu_star/sig_star));

// Technical efficiency: TE = exp(-u)
TE = exp(-u_hat);

// Plot efficiency distribution
struct plotControl plt;
plt = plotGetDefaults("hist");
plotSetTitle(&amp;plt, "Distribution of Technical Efficiency");
plotSetXLabel(&amp;plt, "Technical Efficiency (1 = frontier)");
plotSetYLabel(&amp;plt, "Frequency");
plotHist(plt, TE, 20);

print "Mean efficiency: " meanc(TE);
print "Min efficiency:  " minc(TE);
print "Max efficiency:  " maxc(TE);</code></pre>
<pre>Mean efficiency: 0.80
Min efficiency:  0.41
Max efficiency:  0.95</pre>
<p><a href="https://www.aptech.com/wp-content/uploads/2026/04/stochastic-frontier-histogram.png"><img src="https://www.aptech.com/wp-content/uploads/2026/04/stochastic-frontier-histogram.png" alt="" width="640" height="480" class="aligncenter size-full wp-image-11585777" /></a></p>
<p>The histogram shows substantial variation in efficiency — some firms operate near the frontier (TE $\approx$ 0.95), while others produce 40-50% below their potential. This is the kind of insight that drives productivity research.</p>
<p>Both variance estimates stayed positive throughout optimization. No log-transforms needed, and the estimates apply directly to the parameters we care about.</p>
<h2 id="when-to-use-minimize">When to Use minimize</h2>
<p>The <code>minimize</code> procedure is designed for one thing: optimization with bound constraints. If that's all you need, it's the right tool.</p>
<table>
<thead>
<tr>
<th>Situation</th>
<th>Recommendation</th>
</tr>
</thead>
<tbody>
<tr>
<td>Parameters with simple bounds</td>
<td><a href="https://docs.aptech.com/gauss/minimize.html" target="_blank" rel="noopener"><code>minimize</code></a></td>
</tr>
<tr>
<td>Nonlinear constraints ($g(x) \leq 0$)</td>
<td><a href="https://docs.aptech.com/gauss/sqpsolvemt.html" target="_blank" rel="noopener"><code>sqpSolveMT</code></a></td>
</tr>
<tr>
<td>Equality constraints</td>
<td><code>sqpSolveMT</code></td>
</tr>
<tr>
<td>Algorithm switching, complex problems</td>
<td><a href="https://docs.aptech.com/gauss/optmt/index.html" target="_blank" rel="noopener">OPTMT</a></td>
</tr>
</tbody>
</table>
<p>For the GARCH and stochastic frontier examples above — and most MLE problems where parameters have natural bounds — <code>minimize</code> handles it directly.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Bounded parameters show up constantly in econometric models: variances, volatilities, probabilities, shares. GAUSS 26.0.1 gives you a clean way to handle them with <code>minimize</code>. As we saw today <code>minimize</code>:</p>
<ul>
<li>Set bounds in the control structure</li>
<li>Optimizer respects bounds throughout (not just at the solution)</li>
<li>No log-transforms or penalty functions</li>
<li>Included in base GAUSS</li>
</ul>
<p>If you've been working around parameter bounds with transforms or checking for invalid values inside your likelihood function, this is the cleaner path.</p>
<h2 id="further-reading">Further Reading</h2>
<ul>
<li><a href="https://www.aptech.com/blog/garch-estimation/">GARCH estimation in GAUSS</a></li>
<li><a href="https://www.aptech.com/blog/stochastic-frontier-analysis/">Introduction to stochastic frontier models</a></li>
</ul>
<p>    <!-- MathJax configuration -->
    <style>
        .mjx-svg-href {
            fill: "inherit" !important;
            stroke: "inherit" !important;
        }
    </style>
    <script type="text/x-mathjax-config">
        MathJax.Hub.Config({ TeX: { equationNumbers: {autoNumber: "AMS"} } });
    </script>
    <script type="text/javascript">
window.MathJax = {
  tex2jax: {
    inlineMath: [ ['$','$'] ],
    displayMath: [ ['$$','$$'] ],
    processEscapes: true,
    processEnvironments: true
  },
  // Center justify equations in code and markdown cells. Elsewhere
  // we use CSS to left justify single line equations in code cells.
  displayAlign: 'center',
  "HTML-CSS": {
    styles: {'.MathJax_Display': {"margin": 0}},
    linebreaks: { automatic: false }
  },
  "SVG": {
    styles: {'.MathJax_SVG_Display': {"margin": 0}},
    linebreaks: { automatic: false }
  },
  showProcessingMessages: false,
  messageStyle: "none",
  menuSettings: { zoom: "Click" },
  AuthorInit: function() {
    MathJax.Hub.Register.StartupHook("End", function() {
            var timeout = false, // holder for timeout id
            delay = 250; // delay after event is "complete" to run callback
            var shrinkMath = function() {
              //var dispFormulas = document.getElementsByClassName("formula");
              var dispFormulas = document.getElementsByClassName("MathJax_SVG_Display");
              if (dispFormulas){
                // caculate relative size of indentation
                var contentTest = document.getElementsByTagName("body")[0];
                var nodesWidth = contentTest.offsetWidth;
                // if you have indentation
                var mathIndent = MathJax.Hub.config.displayIndent; //assuming px's
                var mathIndentValue = mathIndent.substring(0,mathIndent.length - 2);
                for (var i=0; i<dispFormulas.length; i++){
                  var dispFormula = dispFormulas[i];
                  var wrapper = dispFormula;
                  //var wrapper = dispFormula.getElementsByClassName("MathJax_Preview")[0].nextSibling;
                  var child = wrapper.firstChild;
                  wrapper.style.transformOrigin = "center"; //or top-left if you left-align your equations
                  var oldScale = child.style.transform;
                  //var newValue = Math.min(0.80*dispFormula.offsetWidth / child.offsetWidth,1.0).toFixed(2);
                  var newValue = Math.min(dispFormula.offsetWidth / child.offsetWidth,1.0).toFixed(2);
                  var newScale = "scale(" + newValue + ")";
                  if(newValue != "NaN" && !(newScale === oldScale)){
                    wrapper.style.transform = newScale;
                    wrapper.style["margin-left"]= Math.pow(newValue,4)*mathIndentValue + "px";
                    var wrapperStyle = window.getComputedStyle(wrapper);
                    var wrapperHeight = parseFloat(wrapperStyle.height);
                    wrapper.style.height = "" + (wrapperHeight * newValue) + "px";
                    if(newValue === "1.00"){
                      wrapper.style.cursor = "";
                      wrapper.style.height = "";
                    }
                    else {
                      wrapper.style.cursor = "zoom-in";
                    }
                  }

                }
            }
            };
            shrinkMath();
            window.addEventListener('resize', function() {
              clearTimeout(timeout);
              timeout = setTimeout(shrinkMath, delay);
            });
          });
  }
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-AMS_SVG"></script></p>

]]></content:encoded>
					
					<wfw:commentRss>https://www.aptech.com/blog/mle-with-bounded-parameters-a-cleaner-approach/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>GAUSS 26: Profiler, L-BFGS-B Optimizer, and 30+ New Features</title>
		<link>https://www.aptech.com/blog/gauss26/</link>
					<comments>https://www.aptech.com/blog/gauss26/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Wed, 04 Feb 2026 21:16:00 +0000</pubDate>
				<category><![CDATA[Releases]]></category>
		<guid isPermaLink="false">https://www.aptech.com/?p=11585667</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[<p>GAUSS 26 introduces a built-in profiler, a new L-BFGS-B optimizer, modern language syntax, and over 30 new features and enhancements. All existing code continues to work unchanged.</p>
<p>Whether you're tracking down a performance bottleneck, estimating a model with bound constraints, or transforming data interactively, this release has something that will change how you work. Here's what's new.</p>
<hr />
<h2 id="find-your-slow-code-in-seconds">Find your slow code in seconds</h2>
<div id="profiler">
<p>GAUSS 26 includes a built-in profiler. Open any program, press <strong>Shift+F5</strong> (or use the run button in the Profiler), and GAUSS profiles every line and procedure call as it runs.</p>
<p>The profiler panel has three tabs:</p>
<ul>
<li><strong>Hot Spots</strong> — every line of code ranked by time spent, so you can see exactly where your program spends the most time</li>
<li><strong>Call Tree</strong> — a hierarchical view of which procedures call which, and how long each takes</li>
<li><strong>Output</strong> — the program's normal output, so you can verify results while profiling</li>
</ul>
<img src="https://www.aptech.com/wp-content/uploads/2026/02/gauss26-profiler-hot-spots.jpg" alt="GAUSS 26 profiler Hot Spots tab showing bootstrap_ols procedure with inv() on line 14 consuming 50.4% of execution time" width="2040" height="1058" class="alignnone size-full wp-image-11585745" />
<p>Double-click any entry to jump directly to that line in the editor.</p>
<p>If you've ever wanted to make your estimation faster, the profiler tells you exactly where to focus. No print statements, no guessing — you see the bottleneck immediately.</p>
<hr />
<h2 id="bound-constrained-optimization-with-l-bfgs-b">Bound-constrained optimization with L-BFGS-B</h2>
<p>The new <code>minimize</code> function brings the L-BFGS-B algorithm to GAUSS — the standard method for smooth unconstrained and bound-constrained optimization problems.</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Define an objective function
proc (1) = rosenbrock(x);
    retp( (1 - x[1])^2 + 100 * (x[2] - x[1]^2)^2 );
endp;

// Set up bounds
x0 = { -1, -1 };

struct minimizeControl ctl;
ctl = minimizeControlCreate();
ctl.bounds = { -5 5, -5 5 };

// Optimize
struct minimizeOut out;
out = minimize(&amp;rosenbrock, x0, ctl);</code></pre>
<pre>Solution:       x = 1.0000, 1.0000
Function value: 5.69e-14
Return code:    0 (converged)</pre>
<p><code>minimize</code> supports passing extra data arguments directly to the objective function, so you don't need globals to get data into your likelihood. This is useful for MLE where parameters must stay positive (e.g., variance components) or bounded (e.g., correlations between -1 and 1).</p>
<p>L-BFGS-B is the standard choice for smooth bound-constrained problems. For nonlinear equality or inequality constraints, use <code>sqpSolveMT</code>. For unconstrained problems, <code>minimize</code> and <code>optmt</code> are both good options — <code>minimize</code> uses less memory for high-dimensional problems.</p>
<hr />
<h2 id="modern-language-syntax">Modern language syntax</h2>
<p>GAUSS 26 adds conveniences that reduce friction in everyday code — sequences, printing, and error messages all work the way you'd expect.</p>
<h3 id="colon-operator">Colon operator</h3>
<p>GAUSS now supports the colon operator for creating sequences:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Before
x = seqa(1, 1, 5);

// Now
x = 1:5;</code></pre>
<pre>1  2  3  4  5</pre>
<p>The stepped form creates sequences with custom increments:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">odds = 1:2:10;
countdown = 10:-2:1;
grid = 0:0.5:2;</code></pre>
<pre>odds:       1  3  5  7  9
countdown:  10  8  6  4  2
grid:       0  0.5  1  1.5  2</pre>
<p>Both forms work with variables and expressions (<code>a:b</code>, <code>(n-1):(n+1)</code>, <code>minc(x):maxc(x)</code>). Inside brackets, the colon continues to work as an index range — <code>x[1:5]</code> selects elements 1 through 5, as it always has.</p>
<h3 id="print-expressions">Print expressions</h3>
<p><code>print</code> now accepts expressions directly without requiring them to be surrounded with parentheses:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">x = 3;
y = 7;
print x + y;
print x .* y;</code></pre>
<pre>10
21</pre>
<p>All arithmetic, comparison, element-wise, and string operators are supported. The existing whitespace-sensitive behavior is preserved — <code>print a -b;</code> still prints two items, while <code>print a - b;</code> prints the difference.</p>
<h3 id="better-error-messages">Better error messages</h3>
<p>Error messages now tell you what went wrong and where to look.</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">x = rndn(10);</code></pre>
<pre>Before:  &quot;Wrong number of arguments&quot;
Now:     &quot;'rndn' requires 2-3 arguments, got 1&quot;</pre>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">rndn = 100;</code></pre>
<pre>Before:  &quot;Syntax error&quot;
Now:     &quot;Illegal use of reserved word 'rndn'&quot;</pre>
<hr />
<h2 id="statistical-testing-functions">Statistical testing functions</h2>
<p>GAUSS 26 adds four statistical testing functions to the base package.</p>
<p><strong><code>ttest</code></strong> — Two-sample and paired t-tests with Welch and pooled variance options, confidence intervals, and F-test for equality of variances.</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">// Compare treatment vs control means
result = ttest(treatment, control);</code></pre>
<p><strong><code>shapiroWilk</code></strong> — The standard test for univariate normality.</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">result = shapiroWilk(residuals);
print result.w;
print result.p;</code></pre>
<pre>W statistic: 0.9788
p-value:     0.1070</pre>
<p><strong><code>mvnTest</code></strong> — Multivariate normality testing using Henze-Zirkler (default), Mardia's skewness and kurtosis, Doornik-Hansen, or Royston methods. Useful for checking VAR residuals or validating distributional assumptions before estimation.</p>
<p><strong><code>contingency</code></strong> — Comprehensive analysis of contingency tables: chi-squared tests, Fisher's exact test, odds ratios, relative risk, and measures of association including Cramer's V, Gamma, Kendall's tau-b, and Cohen's Kappa.</p>
<hr />
<h2 id="transform-data-without-writing-code">Transform data without writing code</h2>
<div id="transform">
<p>The new Transform Tab in the Symbol Editor lets you apply common data transformations interactively — lag, first difference, percent change, moving average, log, standardize, normalize, and more.</p>
<video autoplay loop muted playsinline style="width:100%;">
    <source src="https://www.aptech.com/wp-content/uploads/2026/01/xle-transform-tab.mp4" type="video/mp4">
</video>
<p>Select a column, choose a transformation, and the result appears as a new column. GAUSS generates the equivalent code automatically, so you can incorporate the transformation into your scripts later.</p>
<p>String columns support lowercase, uppercase, trim, and text replacement. Date columns support extracting year, month, day, quarter, week, and time components.</p>
<hr />
<h2 id="data-management">Data management</h2>
<p>New functions for the tasks that bookend every estimation: reshaping data, converting frequencies, and balancing panels.</p>
<h3 id="aggregate-time-series-to-any-frequency">Aggregate time series to any frequency</h3>
<p>The new <code>tsAggregate</code> function converts time series data from higher to lower frequencies:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">data = loadd("daily_prices.csv", "date(Date) + Price + Volume");

// Convert daily to monthly: last price, total volume
monthly = tsAggregate(data, "monthly", "last" $| "sum");</code></pre>
<p>Supports second, minute, hourly, daily, monthly, quarterly, and yearly frequencies. Aggregation methods include last, first, mean, sum, max, min, median, standard deviation, count, and mode.</p>
<h3 id="add-computed-columns-to-dataframes">Add computed columns to dataframes</h3>
<p>The new <code>dfaddcol</code> function adds a named column to a dataframe in one step:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">auto2 = dfaddcol(auto2, "price_k", auto2[., "price"] ./ 1000);
auto2 = dfaddcol(auto2, "log_mpg", ln(auto2[., "mpg"]));</code></pre>
<pre>           make     price       mpg   price_k   log_mpg
    AMC Concord      4099        22     4.099     3.091
      AMC Pacer      4749        17     4.749     2.833
     AMC Spirit      3799        22     3.799     3.091
  Buick Century      4816        20     4.816     2.996
  Buick Electra      7827        15     7.827     2.708</pre>
<p>The new columns are named and ready to use. If you're building derived variables for estimation, this keeps your workflow clean and your column names explicit.</p>
<h3 id="balance-panel-datasets">Balance panel datasets</h3>
<p><code>pdBalance</code> standardizes panel data so each group has identical time coverage:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">balanced = pdBalance(panel_data, "fill");</code></pre>
<p>This fills gaps with missing values so every group spans the full time range — a common preprocessing step before panel estimation. Pairs naturally with <code>pdLag</code> and <code>pdSummary</code> introduced in GAUSS 25.</p>
<h3 id="multicolumn-aggregation">Multicolumn aggregation</h3>
<p>The <code>aggregate</code> function now supports grouping by more than one variable:</p>
<pre class="hljs-container hljs-container-solo"><code class="lang-gauss">method = "max";
variables = "day" $| "time";
max_tips = aggregate(tips, method, variables);</code></pre>
<hr />
<h2 id="editor-and-ide">Editor and IDE</h2>
<h3 id="spot-global-variables-in-your-code">Spot global variables in your code</h3>
<p>Global variables in procedures prevent you from adding <code>threadFor</code> or other parallelization to your code and make maintenance difficult. GAUSS 26 lets you find them instantly — procedures that reference globals now show those variables with an orange highlight in the editor. Hover over any highlighted variable to see its name in a tooltip. Toggle it on or off via <em>Edit &gt; Preferences &gt; Highlight globals in procs</em>.</p>
<h3 id="streamlined-graphics-interface">Streamlined graphics interface</h3>
<p>The Graphics page now combines Graph Settings and Canvas Settings into a single tabbed interface with tabs for Axes, Lines, Symbols, Text, and Canvas. A new toolbar toggle provides quick access.</p>
<h3 id="filter-widgets-for-navigation">Filter widgets for navigation</h3>
<p>New filter widgets on the Command page and Data page let you search through command history and workspace symbols as you type. Press <strong>Ctrl+K</strong> (Cmd+K on Mac) to activate the filter in either view. The Open Symbol dialog on the Data page also includes autocomplete.</p>
<hr />
<h2 id="additional-enhancements">Additional enhancements</h2>
<ul>
<li><strong><code>repmat</code></strong> — tile a matrix: <code>repmat(A, 3, 2)</code> creates a matrix of 3x2 copies of A (MATLAB equivalent: <code>repmat</code>)</li>
<li><strong><code>findIdx</code></strong> — return indices where a condition is true: <code>findIdx(x .&gt; 0)</code> (R equivalent: <code>which()</code>)</li>
<li><strong><code>diagmat</code></strong> — create diagonal or off-diagonal matrices from vectors, with optional offset for super- or subdiagonals</li>
<li><strong><code>sortc</code> and <code>sortmc</code></strong> — new <code>sort_order</code> parameter for ascending (1) or descending (-1) sorting</li>
<li><strong><code>endswith</code></strong> — complements <code>startsWith</code> for string and dataframe filtering</li>
<li><strong><code>strrindx</code></strong> — now accepts vector input for search patterns</li>
<li><strong><code>quantileFit</code></strong> — new convergence diagnostics (<code>qOut.converged</code>, <code>qOut.iterations</code>) and improved input validation with clear error messages</li>
<li><strong><code>sqpSolveMT</code></strong> — improved robustness for challenging optimization problems with better adaptive trust region management</li>
<li><strong><code>eigv</code></strong> — 2.6x faster for 2x2 matrices using closed-form solution, with automatic fallback to the standard algorithm for near-repeated eigenvalues</li>
<li><strong>Symbol Editor</strong> — new &quot;Starts With&quot;, &quot;Does Not Start With&quot;, &quot;Ends With&quot;, &quot;Does Not End With&quot; filters; pending changes shown in blue text; column headers show asterisk for pending filters or transforms</li>
<li><strong>Package Manager</strong> — detailed error messages with categorized troubleshooting steps</li>
<li>New button on Edit and Debug pages opens matrices, strings, and dataframes directly in the Symbol Editor</li>
</ul>
<hr />
<h2 id="whats-coming-next">What's coming next</h2>
<p>Later this year, we'll be shipping new Bayesian VAR estimation with Minnesota priors, conditional forecasting, and hyperparameter optimization — directly from GAUSS, powered by new high-performance computation libraries. Stay tuned.</p>
<hr />
<h2 id="get-started-with-gauss-26">Get started with GAUSS 26</h2>
<p>GAUSS 26 is a free update for users with active maintenance. Download for <a href="http://www.aptech.com/downloads/26/GAUSS_26_Win_64.zip">Windows</a> or <a href="http://www.aptech.com/downloads/26/GAUSS_26_MacOSX_64.zip">macOS</a>, or <a href="https://www.aptech.com/contact/">contact us</a> for a trial license.</p>
<p>New to GAUSS? See our <a href="https://docs.aptech.com/">Getting Started Guide</a>. Coming from another language? See our <a href="https://docs.aptech.com/gauss/coming-to-gauss/">Coming to GAUSS</a> guides for R, MATLAB, Stata, and Python users.</p>
<p>    <!-- MathJax configuration -->
    <style>
        .mjx-svg-href {
            fill: "inherit" !important;
            stroke: "inherit" !important;
        }
    </style>
    <script type="text/x-mathjax-config">
        MathJax.Hub.Config({ TeX: { equationNumbers: {autoNumber: "AMS"} } });
    </script>
    <script type="text/javascript">
window.MathJax = {
  tex2jax: {
    inlineMath: [ ['$','$'] ],
    displayMath: [ ['$$','$$'] ],
    processEscapes: true,
    processEnvironments: true
  },
  // Center justify equations in code and markdown cells. Elsewhere
  // we use CSS to left justify single line equations in code cells.
  displayAlign: 'center',
  "HTML-CSS": {
    styles: {'.MathJax_Display': {"margin": 0}},
    linebreaks: { automatic: false }
  },
  "SVG": {
    styles: {'.MathJax_SVG_Display': {"margin": 0}},
    linebreaks: { automatic: false }
  },
  showProcessingMessages: false,
  messageStyle: "none",
  menuSettings: { zoom: "Click" },
  AuthorInit: function() {
    MathJax.Hub.Register.StartupHook("End", function() {
            var timeout = false, // holder for timeout id
            delay = 250; // delay after event is "complete" to run callback
            var shrinkMath = function() {
              //var dispFormulas = document.getElementsByClassName("formula");
              var dispFormulas = document.getElementsByClassName("MathJax_SVG_Display");
              if (dispFormulas){
                // caculate relative size of indentation
                var contentTest = document.getElementsByTagName("body")[0];
                var nodesWidth = contentTest.offsetWidth;
                // if you have indentation
                var mathIndent = MathJax.Hub.config.displayIndent; //assuming px's
                var mathIndentValue = mathIndent.substring(0,mathIndent.length - 2);
                for (var i=0; i<dispFormulas.length; i++){
                  var dispFormula = dispFormulas[i];
                  var wrapper = dispFormula;
                  //var wrapper = dispFormula.getElementsByClassName("MathJax_Preview")[0].nextSibling;
                  var child = wrapper.firstChild;
                  wrapper.style.transformOrigin = "center"; //or top-left if you left-align your equations
                  var oldScale = child.style.transform;
                  //var newValue = Math.min(0.80*dispFormula.offsetWidth / child.offsetWidth,1.0).toFixed(2);
                  var newValue = Math.min(dispFormula.offsetWidth / child.offsetWidth,1.0).toFixed(2);
                  var newScale = "scale(" + newValue + ")";
                  if(newValue != "NaN" && !(newScale === oldScale)){
                    wrapper.style.transform = newScale;
                    wrapper.style["margin-left"]= Math.pow(newValue,4)*mathIndentValue + "px";
                    var wrapperStyle = window.getComputedStyle(wrapper);
                    var wrapperHeight = parseFloat(wrapperStyle.height);
                    wrapper.style.height = "" + (wrapperHeight * newValue) + "px";
                    if(newValue === "1.00"){
                      wrapper.style.cursor = "";
                      wrapper.style.height = "";
                    }
                    else {
                      wrapper.style.cursor = "zoom-in";
                    }
                  }

                }
            }
            };
            shrinkMath();
            window.addEventListener('resize', function() {
              clearTimeout(timeout);
              timeout = setTimeout(shrinkMath, delay);
            });
          });
  }
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-AMS_SVG"></script></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.aptech.com/blog/gauss26/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://www.aptech.com/wp-content/uploads/2026/01/xle-transform-tab.mp4" length="0" type="video/mp4" />

			</item>
	</channel>
</rss>
