text:
# Using JSON Output from the Dynare Preprocessor

We have recently added an option to produce JSON output from the Dynare Preprocessor. If you’re new to Dynare you should know that the Preprocessor is the part of Dynare that transforms your .mod file into a file usable by MATLAB, Octave, Julia, or the C compiler. Providing JSON output allows the preprocessor to communicate everything it knows about the model (e.g. the model equations, variables, static and dynamic derivatives, etc.) in a way that is easily parsed by many programming languages. This makes it possible to use the Dynare Modeling Language in any programming environment that can parse JSON.

In this post, I’d like to walk you through an example of using the JSON output of the Dynare Preprocessor. We will write a routine that parses the JSON output and estimates the parameters, equation by equation, via Ordinary Least Squares. We will then use this routine to estimate the Taylor rule parameters from Smets and Wouters (2007). However, before getting to the example, I’d like to briefly give you some background on the Dynare Preprocessor and the JSON output it produces.

On a final, practical, note, you should know that the OLS routine and the modified .mod file described herein work with Dynare 4.6 and later .

## The Dynare Preprocessor

At the basic level, the Dynare Preprocessor takes as input a Dynare .mod file and outputs the derivatives of the static and dynamic versions of the model and their derivatives in addition to a driver file that guides the back-end actions to be taken. These outputs are provided for use with MATLAB, Octave, C (without the driver), and, as of Dynare 4.6, Julia.

In addition to the aforementioned outputs, Dynare 4.6 provides JSON output that represents the .mod file at every major preprocessing stage: Parsing, Check Pass, Transform Pass, and Computing Pass. To better understand the type of JSON output that can be obtained, it is helpful to see the Dynare Preprocessor Flow Chart and understand, in a general sense, what is done at each stage:

As you can see from the flow chart above, there are 6 preprocessing stages:

1. Macroprocessor: the Dynare Macroprocessing language is used to perform textual manipulations of the .mod file. The output from this stage is a .mod file that is ready to be parsed. You can read more about the Dynare Macroprocessing language here.
2. Parsing: takes a potentially macro-expanded .mod file and parses it into an Abstract Syntax Tree (AST), comprising the internal representation of the .mod file. In doing so, among other cursory checks, it verifies that the .mod file has valid Dynare syntax, commands, and options.
3. Check Pass: verifies the coherence of the .mod file. For example, this is where we ensure that the number of declared endogenous variables equals the number of equations in the model block.
4. Transform Pass: among other transformations, adds auxiliary variables and equations for leaded and lagged variables, thereby transforming the model into t-1, t, t+1 form.
5. Computing Pass: calculates the derivatives of the transformed static and dynamic models using the symbolic derivative engine.
6. Write Output: writes MATLAB, Octave, C, Julia, or JSON files.

## More on JSON

JSON is a data interchange format that is easily understood by humans and easily parsed by many programming languages. In short, it associates keys with values like a dictionary. In JSON, keys are strings whereas values can be strings, numbers, arrays, objects, boolean, or null.

The easiest way to get a sense of what a JSON file looks like is to see it. This declaration of parameters in a .mod file

parameters beta $\beta$ (long_name='discount factor'), rho;

would produce the following lines in JSON

"parameters": [{"name":"beta", "texName":"\\beta", "longName":"discount factor"}
, {"name":"rho", "texName":"rho", "longName":"rho"}]

This tells us that key "parameters" is associated with an array (enclosed by brackets) of objects (enclosed by braces). The array has two entries. The first entry in this array is an object where the key "name" is associated with the string "beta", the key "texName" is associated with the string "\\beta", and the key "longName" is associated with the string "discount factor". The second entry has similar keys but, for the case of rho, no specific $$\LaTeX$$ name or long name was declared, so those keys take the default values. As you can see, understanding the contents of a JSON file and seeing how they correspond to the originating .mod file is straightforward. For more details on JSON visit https://www.json.org.

A JSON representation of the .mod file can be obtained after the Parsing, Check Pass, Transform Pass, and Computing Pass stages outlined above. To obtain JSON output from the Dynare Preprocessor, you must choose where you want that output to be produced by passing the command line option json=parse|check|transform|compute. Note that the output provided varies a bit, depending on where you want that output produced. For example, the JSON representation of the derivatives of the dynamic and static models will only be produced after the derivatives of the model have been calculated in the Computing Pass. Again, the details of what is produced after every stage are outlined in the Dynare manual.

## An Example of Putting the JSON output to use: Ordinary Least Squares

As an example application of how one can use the Dynare JSON output, I will run OLS on the Taylor rule in Smets and Wouters (2007).

The original .mod file, Smets_Wouters_2007.mod, and data file, usmodel_data.mat, were downloaded from Johannes Pfeifer’s DSGE_mod repository.

Below, I show the .mod file and describe the necessary modifications to run OLS. After that, I describe the construction of the MATLAB routine that uses the Dynare Preprocessor JSON output to run OLS (this routine is general and would work with the JSON output provided for any .mod file). Finally, I run OLS on the monetary policy rule.

### The .mod file

The following are the parts of Smets_Wouters_2007.mod that I modified for this post. The entire file used can be found here.

#### First Modification

@@ -1,3 +1,6 @@
+// --+ options: json=compute +--

The first line of the file tells the Dynare Preprocessor to produce JSON output after the Computing Pass. This creates the following files in the Smets_Wouters_2007/model/json directory:

• modfile.json,
• modfile-original.json,
• static.json, and
• dynamic.json.

The first file, modfile.json, is the equivalent of the standard .m driver file output by the Dynare Preprocessor only in JSON format. It contains lists of model variables, the model block (transformed into t-1, t, t+1 format), a list of Dynare statements, the list of equation cross references, and some general information about the model.

The second file, modfile-original.json contains a slightly modified version of the model as written in the model block. It contains no auxiliary variables or auxiliary equations, but it does expand adl nodes, if there are any. Here is what the Taylor rule looks like in JSON format:

{
"model":
[
...
{
"lhs": "r",
"rhs": "pinf*crpiMcrpiXcrr+cryMcryXcrr*ygap+crdy*diff(ygap)+crr*r(-1)+ms",
"line": 141,
"tags": {
"name": "taylor_rule"
}
},
...
]
}

This is the file of interest for the OLS routine as we want to maintain the lag information contained in the model block. This file is written when either json=compute or json=transform is passed as an option to the dynare command.

The final two files, static.json and dynamic.json, contain the derivatives of the dynamic and static models. These files are a byproduct of using json=compute. Our OLS routine doesn’t need them.

#### Second Modification

@@ -1,3 +1,6 @@
// --+ options: json=compute +--
+path(['..' filesep 'ols'], path);

The second change I made to the original .mod file was to add the relative path to the ols folder containing the OLS routine and its helper functions. Since this routine is not part of the official Dynare release, Dynare will not actually take care of adding its folder to the MATLAB/Octave path. Hence, this line.

#### Third Modification

@@ -135,12 +138,13 @@ model(linear);
y = cfc*( calfa*k+(1-calfa)*lab +a );
pinf = (1/(1+cbetabar*cgamma*cindp)) * ( cbetabar*cgamma*pinf(1) +cindp*pinf(-1)+((1-cprobp)*(1-cbetabar*cgamma*cprobp)/cprobp)/((cfc-1)*curvp+1)*(mc)  )  + spinf;
w = (1/(1+cbetabar*cgamma))*w(-1)+(cbetabar*cgamma/(1+cbetabar*cgamma))*w(1)+(cindw/(1+cbetabar*cgamma))*pinf(-1)-(1+cbetabar*cgamma*cindw)/(1+cbetabar*cgamma)*pinf+(cbetabar*cgamma)/(1+cbetabar*cgamma)*pinf(1)+(1-cprobw)*(1-cbetabar*cgamma*cprobw)/((1+cbetabar*cgamma)*cprobw)*(1/((clandaw-1)*curvw+1))*(csigl*lab + (1/(1-chabb/cgamma))*c - ((chabb/cgamma)/(1-chabb/cgamma))*c(-1) -w)+ 1*sw;
+    [name='taylor_rule']

On line 141, I add an equation tag to the monetary policy rule; this will be used to tell the OLS routine which equation to estimate. I make sure not to include any spaces in the equation tag name as the output of the OLS routine is stored in a substructure of oo_.ols with the name of the equation tag. Hence, here, the output will be stored in oo_.ols.taylor_rule.

#### Fourth Modification

@@ -34,15 +37,15 @@
*/

var labobs robs pinfobs dy dc dinve dw ewma epinfma zcapf rkf kf pkf cf
-    invef yf labf wf rrf mc zcap rk k pk c inve y lab pinf w r a b g qs ms
-    spinf sw kpf kp;
+    invef yf labf wf rrf mc zcap rk k pk c inve y lab pinf w r a b g qs
+    spinf sw kpf kp ygap;

-varexo ea eb eg eqs em epinf ew;
+varexo ea eb eg eqs ms epinf ew;

parameters curvw cgy curvp constelab constepinf constebeta cmaw cmap calfa
czcap csadjcost ctou csigma chabb ccs cinvs cfc
cindw cprobw cindp cprobp csigl clandaw
-           crdpi crpi crdy cry crr
+           crdpi crdy crr crpiMcrpiXcrr cryMcryXcrr
crhoa crhoas crhob crhog crhols crhoqs crhoms crhopinf crhow
ctrend cg;

@@ -68,10 +71,10 @@ cprobp=   0.6;
cindw=    0.3243;
cindp=    0.47;
czcap=    0.2696;
-crpi=     1.488;
crr=      0.8762;
-cry=      0.0593;
crdy=     0.2347;
+crpiMcrpiXcrr = 0.1842;
+cryMcryXcrr   = 0.0073;

@@ -135,12 +138,13 @@ model(linear);
y = cfc*( calfa*k+(1-calfa)*lab +a );
pinf = (1/(1+cbetabar*cgamma*cindp)) * ( cbetabar*cgamma*pinf(1) +cindp*pinf(-1)+((1-cprobp)*(1-cbetabar*cgamma*cprobp)/cprobp)/((cfc-1)*curvp+1)*(mc)  )  + spinf;
w = (1/(1+cbetabar*cgamma))*w(-1)+(cbetabar*cgamma/(1+cbetabar*cgamma))*w(1)+(cindw/(1+cbetabar*cgamma))*pinf(-1)-(1+cbetabar*cgamma*cindw)/(1+cbetabar*cgamma)*pinf+(cbetabar*cgamma)/(1+cbetabar*cgamma)*pinf(1)+(1-cprobw)*(1-cbetabar*cgamma*cprobw)/((1+cbetabar*cgamma)*cprobw)*(1/((clandaw-1)*curvw+1))*(csigl*lab + (1/(1-chabb/cgamma))*c - ((chabb/cgamma)/(1-chabb/cgamma))*c(-1) -w)+ 1*sw;
[name='taylor_rule']
-    r = crpi*(1-crr)*pinf+cry*(1-crr)*(y-yf)+crdy*(y-yf-y(-1)+yf(-1))+crr*r(-1)+ms;
+    r = crpiMcrpiXcrr*pinf + cryMcryXcrr*ygap + crdy*diff(ygap) + crr*r(-1) + ms;
+    ygap = y - yf;

In Smets and Wouters (2007), potential output (yf) is calculated elsewhere in the model. But, if we are to run OLS on the Taylor rule equation, we need observations on this variable. Since that is not possible, I add a new equation on line 143, ygap = y - yf, replacing y-yf in the Taylor rule with ygap. This allows us to estimate the model as before while providing observed data on ygap for OLS estimation (more on that later). NB: I could have left y-yf in the equation and provided data for yf but this change makes it more clear that ygap is calculated differently for the call to the Dynare estimation command than for the call to dyn_ols.

I further create two new parameters, crpiMcrpiXcrr and cryMcryXcrr because the parsing algorithm implemented in the OLS routine only accounts for the situation where the linear combination of a single parameter multiplies one or more endogenous variables. This change implies the changes on lines 76 and 77 defining their initial values, and on lines 222 and 223 defining them as parameters to be estimated.

Finally, I redefine ms as an exogenous variable and remove the equation that defined it as well as the definition of the variable em.

#### Last Modification

@@ -227,6 +231,14 @@ end;

varobs dy dc dinve labobs pinfobs dw robs;

-estimation(optim=('MaxIter',200),datafile=usmodel_data,mode_file=usmodel_shock_decomp_mode,mode_compute=0,first_obs=1, presample=4,lik_init=2,prefilter=0,mh_replic=0,mh_nblocks=2,mh_jscale=0.20,mh_drop=0.2, nograph, nodiagnostic, tex);
+ds = dseries('usmodel_dseries.csv');
+ds.ygap = ds.y.detrend(1);
+dyn_ols(ds, {}, {'taylor_rule'});
+crr           = 0.8762;
+crdy          = 0.2347;
+crpiMcrpiXcrr = 0.1842;
+cryMcryXcrr   = 0.0073;
+
+estimation(optim=('MaxIter',200),datafile=usmodel_data,mode_compute=4,first_obs=1, presample=4,lik_init=2,prefilter=0,mh_replic=0,mh_nblocks=2,mh_jscale=0.20,mh_drop=0.2, nograph, nodiagnostic, tex);

I first load the data into a dseries called ds on line 234. As mentioned above, I need data for ygap for the OLS estimation. This is obtained by detrending the output series. I then call the OLS routine, telling it to run OLS using the dataset ds on the equation specified by the equation tag taylor_rule.

As the OLS routine sets the parameter values it estimates in M_.params, I reset their initial values after the call to the routine on lines 238-241, in preparation for the call to the Dynare estimation routine.

### The OLS routine in MATLAB: dyn_ols.m

The OLS routine outlined herein was written in MATLAB but could just as easily have been written in Julia, Python, C, or the language of your choice. There are three main steps involved in writing a routine that makes use of the Dynare JSON output:

2. Parse this structure for your purposes

The files described in this section can be found here.

#### Step 1: Parsing the JSON file

As JSON is widely supported, the first step is often straightforward, regardless of your choice of programming language. In our case, though MATLAB has only provided JSON support since R2016b (via the commands jsonencode/jsondecode), there’s a widely-used and well-tested toolbox called JSONLab that allows one to use JSON with older versions of MATLAB and with Octave. Using the JSONLab distributed with Dynare allows us to access the model block specified as an AST in just two lines:

45 tmp = loadjson(jsonfile);
46 ast = tmp.abstract_syntax_tree;

These lines reside in the function get_ast.m, a utility we wrote that is used by dyn_ols.m.

Line 45 reads in Smets_Wouters_2007/model/json/modfile-original.json (stored in the jsonfile variable) and loads it into a temporary MATLAB structure. Line 46 then selects the abstract_syntax_tree field as that is the only one we’re interested in and sets it to the output variable ast. When finished, ast is a cell array with 40 entries, one for each equation. Entry 23 of this cell array corresponds to the monetary policy equation and looks like:

>> ast{23}

ans =

struct with fields:

number: 22
line: 141
tags: [1x1 struct]
AST: [1x1 struct]

>> ast{23}.tags

ans =

struct with fields:

name: 'taylor_rule'

>> ast{23}.AST

ans =

struct with fields:

node_type: 'BinaryOpNode'
op: '='
arg1: [1x1 struct]
arg2: [1x1 struct]

As you can see, the JSON output contains a lot of information. First, we know the 0-indexed equation number (MATLAB indexing starts at 1, which explains the difference between the index in the structure and the index in the JSON), and the line it was on in the .mod file (line 141). Digging into the structure, we see that there is one tag associated with the equation that has key name and value 'taylor_rule'. We also see the root node of the AST.

As we only want to perform OLS on this equation, we don’t need the AST corresponding to the other equations in the .mod file. Hence, we overwrite it with the aid of a helper function, selecting only the necessary equation:

54     ast = getEquationsByTags(ast, 'name', eqtags);

#### Step 2: Parsing the model block

Below I describe the parsing of an equation as implemented in dyn_ols.m.

Given the pared-down ast variable returned by getEquationsByTags.m, we then call another helper function, common_parsing.m that handles the parsing for OLS-style estimation routines (e.g. SUR, pooled OLS, FGLS, …).

118 [Y, lhssub, X, fp, lp] = common_parsing(ds(ds_range), ast, true, param_names);

In turn, this function calls a helper function, parse_ols_style_equation.m that handles the parsing of one OLS-style equation at a time.

57 for i = 1:neqs
58     [Y{i}, lhssub{i}, X{i}, residnames{i}, startdates{i}, enddates{i}] = ...
59         parse_ols_style_equation(ds, ast{i});
60 end

Together, these functions return matrices corresponding to the observed variable, Y, the regressors, X, the constant term, lhssub, and the first and last periods of the observed data (fp and lp).

Parsing proceeds as follows in parse_ols_style_equation.m. First, the function arguments are verified (lines 38-66). After this, we know that the LHS contains either a VariableNode or a UnaryOpNode.

Note

Several different types of nodes that can appear in the AST, corresponding to the types of operations that are available in a .mod file equation. The nodes are:

1. NumConstNode: non-negative integers or doubles
2. VariableNode: endogenous, exogenous, or parameter
3. UnaryOpNode: unary operation on a node, e.g. log, abs, unary minus, …
4. BinaryOpNode: binary operation on a node, e.g. arithmetic operations, min, max, =, comparison operators, …
5. TrinaryOpNode: trinary operation on a node, e.g. normcdf, normpdf
6. ExternalFunctionNode: external function node

Assured that the type of the LHS is valid for OLS, the value of Y is set by evaluating the LHS of the specified equation. Given that all equations are represented as BinaryOpNode‘s (the two arguments being the LHS, arg1, and the RHS, arg2), the call to evaluate the LHS of the equation is:

69 Y = evalNode(ds, ast.AST.arg1, line, dseries());

evalNode, a local function in parse_ols_style_equation.m then evaluates this node given the dseries contained in ds.

309 function X = evalNode(ds, node, line, X)
310 global M_
311 if strcmp(node.node_type, 'NumConstNode')
312     X = dseries(node.value, ds.dates, 'const');
313 elseif strcmp(node.node_type, 'VariableNode')
314     if strcmp(node.type, 'endogenous') ...
315             || (strcmp(node.type, 'exogenous') && any(strcmp(ds.name, node.name)))
316         if ds.exist(node.name)
317             X = ds.(node.name)(node.lag);
318         else
319             error('Variable %s is not available in the database.', node.name)
320         end
321     elseif strcmp(node.type, 'parameter')
322         X = M_.params(not(cellfun('isempty', strfind(M_.param_names, node.name))));
323         if isnan(X) || isinf(X) || ~isreal(X)
324             parsing_error(['Value incorrectly set for parameter: ' node.name], line);
325         end
326     end
327 elseif strcmp(node.node_type, 'UnaryOpNode')
328     Xtmp = evalNode(ds, node.arg, line, X);
329     % Only works if dseries supports . notation for unary op (true for log/diff)
330     % Otherwise, use: X = eval([node.op '(Xtmp)']);
331     try
332         if strcmp(node.op, 'uminus')
333             X = -Xtmp;
334         else
335             X = Xtmp.(node.op);
336         end
337         if any(isinf(X)) || ~isreal(X)
338             parsing_error(['Error applying ' node.op], line, node);
339         end
340     catch
341         parsing_error(['Error applying ' node.op], line, node);
342     end
343 elseif strcmp(node.node_type, 'BinaryOpNode')
344     Xtmp1 = evalNode(ds, node.arg1, line, X);
345     Xtmp2 = evalNode(ds, node.arg2, line, X);
346     switch node.op
347         case '*'
348             Xtmp = Xtmp1 * Xtmp2;
349         case '/'
350             Xtmp = Xtmp1 / Xtmp2;
351         case '+'
352             Xtmp = Xtmp1 + Xtmp2;
353         case '-'
354             Xtmp = Xtmp1 - Xtmp2;
355         otherwise
356             parsing_error(['got unexpected binary op ' node.op], line, node);
357     end
358     if any(isinf(Xtmp)) || ~isreal(Xtmp)
359         parsing_error(['Error applying ' node.op], line, node);
360     end
361     X = X + Xtmp;
362 else
363     parsing_error(['got unexpected node type ' node.node_type], line, node);
364 end
365 end

In the evaluation of the observed variable (X in this local function, Y in the main routine), what’s important to us is lines 313-342 as we know it’s either a VariableNode or a UnaryOpNode. Regardless of the type of node it is, it’s evaluated using the dseries (ds) and the corresponding dseries vector is returned. In our case, the interest rate r is evaluated on line 317 by looking up its value in ds.

Though our work for Y was easy, computing the matrix of regressors and the vector of constants will be a bit more involved.

Back in the main function, before we can create the matrix of regressors X, we decompose the RHS (arg2) of the equation into additive terms, storing them in a cell array called terms. We do this by calling the locally defined function:

232 function terms = decomposeAdditiveTerms(terms, node, node_sign)
233 if strcmp(node.node_type, 'NumConstNode') || strcmp(node.node_type, 'VariableNode')
234     terms = [terms {{node node_sign}}];
235 elseif strcmp(node.node_type, 'UnaryOpNode')
236     if strcmp(node.op, 'uminus')
237         terms = decomposeAdditiveTerms(terms, node.arg, -node_sign);
238     else
239         terms = [terms {{node node_sign}}];
240     end
241 elseif strcmp(node.node_type, 'BinaryOpNode')
242     if strcmp(node.op, '+') || strcmp(node.op, '-')
243         terms = decomposeAdditiveTerms(terms, node.arg1, node_sign);
244         if strcmp(node.op, '+')
245             terms = decomposeAdditiveTerms(terms, node.arg2, node_sign);
246         else
247             terms = decomposeAdditiveTerms(terms, node.arg2, -node_sign);
248         end
249     else
250         terms = [terms {{node node_sign}}];
251     end
252 else
253     terms = [terms {{node node_sign}}];
254 end
255 end

As you can see, decomposeAdditiveTerms is a recursive, tree-traversal function that breaks down terms separated by + or -, storing them in the return value, terms. Each cell in the return value is comprised of a pair of elements: the root node of the sub-tree representing the additive node and the sign preceding this node (1 or -1).

Given the equation we want to estimate (shown here from Smets_Wouters_2007.mod as a reminder):

141     [name='taylor_rule']
142     r = crpiMcrpiXcrr*pinf + cryMcryXcrr*ygap + crdy*diff(ygap) + crr*r(-1) + ms;

the output of decomposeAdditiveTerms (stored in the variable terms) is a 5-element cell, corresponding to the RHS elements:

1. crpiMcrpiXcrr*pinf
2. cryMcryXcrr*ygap
3. crdy*diff(ygap)
4. crr*r(-1)
5. ms

Hence, in this case, 4 nodes of terms contain BinaryOpNode‘s (corresponding to the binary operation *) and one term contains a VariableNode.

To understand how the terms are stored, one need only look at the following output for the first term, crpiMcrpiXcrr*pinf:

>> terms

terms =

1x5 cell array

{1x2 cell}    {1x2 cell}    {1x2 cell}    {1x2 cell}    {1x2 cell}

>> terms{1}

ans =

1x2 cell array

{1x1 struct}    {[1]}

>> terms{1}{1}

ans =

struct with fields:

node_type: 'BinaryOpNode'
op: '*'
arg1: [1x1 struct]
arg2: [1x1 struct]

>> terms{1}{1}.arg1

ans =

struct with fields:

node_type: 'VariableNode'
name: 'pinf'
type: 'endogenous'
lag: 0

>> terms{1}{1}.arg2

ans =

struct with fields:

node_type: 'VariableNode'
name: 'crpiMcrpiXcrr'
type: 'parameter'
lag: 0

Here, the second element of terms{1} is 1 as it is not preceded by a minus sign. The node itself is a BinaryOpNode as it represents the multiplication of an endogenous variable (the first argument of the node) and a parameter (the second argument of the node).

Note

The elements of terms are not necessarily in the same order as written in the equation in the .mod file. This is because, for efficiency reasons (e.g. node sharing), the AST created by the preprocessor does not guarantee this ordering. By the same token, the elements of a node are not guaranteed to be in the same order as they appear in the .mod file, as you can see above where the first argument of the BinaryOpNode in terms{1}{1} is the endogenous variable pinf whereas pinf appears second in the multiplication as written in the .mod file: crpiMcrpiXcrr*pinf.

Now that we have terms set, we can construct the regressor matrix X by entering the loop on line 75 of parse_ols_style_equation.m:

 75 for i = 1:length(terms)
76     Xtmp = dseries();
77     node_sign = terms{i}{2};
78     node_to_parse = terms{i}{1};
79     if strcmp(node_to_parse.node_type, 'VariableNode')
80         if strcmp(node_to_parse.type, 'parameter')
81             % Intercept
82             Xtmp = dseries(1, ds.dates, node_to_parse.name)*node_sign;
83         elseif strcmp(node_to_parse.type, 'exogenous') && ~any(strcmp(ds.name, node_to_parse.name))
84             % Residual if not contained in ds
85             if isempty(residual)
86                 residual = node_to_parse.name;
87             else
88                 parsing_error(['only one residual allowed per equation; encountered ' residual ' & ' node_to_parse.name], line);
89             end
90         elseif strcmp(node_to_parse.type, 'endogenous') ...
91                 || (strcmp(node_to_parse.type, 'exogenous') && any(strcmp(ds.name, node_to_parse.name)))
92             % Subtract VariableNode from LHS
93             % NB: treat exogenous that exist in ds as endogenous
94             lhssub = lhssub + evalNode(ds, node_to_parse, line, dseries())*node_sign;
95         else
96             parsing_error('unexpected variable type found', line, node_to_parse);
97         end
98     elseif strcmp(node_to_parse.node_type, 'UnaryOpNode')
99         % Subtract UnaryOpNode from LHS
100         % NB: treat exogenous that exist in ds as endogenous
101         lhssub = lhssub + evalNode(ds, node_to_parse, line, dseries());
102     elseif strcmp(node_to_parse.node_type, 'BinaryOpNode') && strcmp(node_to_parse.op, '/')
103         % Subtract Node from LHS
104         % if either arg contains a parameter, it's a parsing error.
105         if containsParameter(node_to_parse, line)
106             parsing_error('unexpected node found', line, node_to_parse)
107         end
108         lhssub = lhssub + evalNode(ds, node_to_parse, line, dseries());
109     elseif strcmp(node_to_parse.node_type, 'BinaryOpNode') && strcmp(node_to_parse.op, '*')
110         % Parse param_expr * endog_expr
111         [Xtmp, names] = parseTimesNode(ds, node_to_parse, line);
112         Xtmp = Xtmp*node_sign;
113         if Xtmp.vobs > 1 || ...
114                 (Xtmp.vobs == 1 && ~isnan(str2double(Xtmp.name)))
115             % Handle constraints
116             % Look through Xtmp names for constant
117             % if found, subtract from LHS
118             for j = 1:length(names)
119                 if strcmp(names{j}{1}.node_type, 'NumConstNode')
120                     pname = num2str(names{j}{1}.value);
121                 elseif strcmp(names{j}{1}.node_type, 'VariableNode')
122                     pname = names{j}{1}.name;
123                 else
124                     parsing_error('unexpected node type', node_to_parse, line);
125                 end
126                 psign = names{j}{2};
127                 if ~isnan(str2double(pname))
128                     lhssub = lhssub + psign * str2double(pname) * Xtmp.(pname);
129                     Xtmp = Xtmp.remove(pname);
130                 else
131                     % Multiply by psign now so that it can be added together below
132                     % Otherwise, it would matter which was encountered first,
133                     % a parameter on its own or a linear constraint
134                     Xtmp.(pname) = psign * Xtmp.(pname);
135                 end
136             end
137         end
138     else
139         parsing_error('didn''t expect to arrive here', line, node_to_parse);
140     end
141
142     names = Xtmp.name;
143     for j = length(names):-1:1
144         % Handle constraits
145         if any(strcmp(X.name, names{j}))
146             X.(names{j}) = X.(names{j}) + Xtmp.(names{j});
147             Xtmp = Xtmp.remove(names{j});
148         end
149     end
150     X = [X Xtmp];
151 end

Entering the loop, we set 3 variables: Xtmp, node_to_parse, and node_sign. Xtmp is where we will construct the regressor column to be appended to X at the end of each loop. node_to_parse and node_sign are simply the corresponding parts of the pair stored in each terms cell, as described above.

With these variables set, we take different actions, depending on the type of node encountered in node_to_parse. The following subsections explain those actions.

##### Condition 1: VariableNode (lines 79-97)

If node_to_parse is a VariableNode it is an additive variable in the equation. If it was declared as a parameter in the .mod file, then it’s the intercept of the equation. It is thus stored in Xtmp with the value of the parameter at every period. If it’s a lone exogenous variable that is not present in ds, we treat it as the residual. If there are more than one such variable, then it’s an error. If it’s an endogenous variable or an exogenous variable present in ds, we add it to the dseries lhssub, a dseries that will be subtracted from the LHS before returning. If the type of the node_to_parse doesn’t fall into any of these categories, parsing ends with an error.

##### Condition 2: UnaryOpNode (lines 98-101)

If node_to_parse is a UnaryOpNode, we evaluate it and add it to the lhssub variable to be subtracted from the LHS.

##### Condition 3: BinaryOpNode with division operator (lines 102-108)

In this case, if a parameter is found in this expression, we end with a parsing error. Otherwise, we evaluate the node and add it to lhssub.

##### Condition 4: BinaryOpNode with multiplication operator (lines 109-137)

In this case, we parse the node_to_parse, by calling the local function parseTimesNode:

257 function [X, pterms] = parseTimesNode(ds, node, line)
258 % Separate the parameter expression from the endogenous expression
259 assert(strcmp(node.node_type, 'BinaryOpNode') && strcmp(node.op, '*'))
260 if isOlsParamExpr(node.arg1, line)
261     pterms = decomposeAdditiveTerms([], node.arg1, 1);
262     X = evalNode(ds, node.arg2, line, dseries());
263 elseif isOlsParamExpr(node.arg2, line)
264     pterms = decomposeAdditiveTerms([], node.arg2, 1);
265     X = evalNode(ds, node.arg1, line, dseries());
266 else
267     parsing_error('expecting (param expr)*(var expr)', line, node);
268 end
269 if strcmp(pterms{1}{1}.node_type, 'NumConstNode')
270     X = X.rename(num2str(pterms{1}{1}.value));
271 elseif strcmp(pterms{1}{1}.node_type, 'VariableNode')
272     X = X.rename(pterms{1}{1}.name);
273 else
274     parsing_error('unexpected type', line, node)
275 end
276 for ii = 2:length(pterms)
277     if strcmp(pterms{ii}{1}.node_type, 'NumConstNode')
278         X = [X dseries(X{1}.data, X{1}.firstdate, num2str(pterms{ii}{1}.value))];
279     elseif strcmp(pterms{ii}{1}.node_type, 'VariableNode')
280         X = [X dseries(X{1}.data, X{1}.firstdate, pterms{ii}{1}.name)];
281     else
282         parsing_error('unexpected type', line, node)
283     end
284 end
285 end

This function returns the dseries vector/matrix X corresponding to the regressors found. It can handle parsing expressions of additively-separated parameters multiplied by an expression of variables. Each of the additively separated parameters in pterms corresponds to one column of the returned vector/matrix X.

Returning from this function, we have Xtmp corresponding to the evaluated variables and names corresponding to the parameter names. In the code that follows (lines 113-137), we add any columns of Xtmp that were multiplied by a constant to lhssub and then remove this column from Xtmp.

##### Condition 5: Otherwise (line 139)

If none of the previous 4 conditions were satisfied, we have encountered a parsing error.

##### End of loop (lines 141-150)

At the end of the loop, we combine the temporary vector/matrix of regressors, Xtmp with the matrix of regressors already created, X. The loop here handles the case where a parameter was used twice in two different terms. If any columns remain in Xtmp once we arrive at line 151, they are concatenated to X. The loop continues until the cell terms has been exhausted. When the loop ends on line 152, our matrix of regressors, X, has been constructed.

After the loop, the Y vector is adjusted, subtracting any constant terms on the RHS:

152 Y = Y - lhssub;

Following that, the first and last observed periods of the dseries are assigned to the variables fp and lp:

154 %% Set start and end dates
155 fp = Y.firstobservedperiod;
156 lp = Y.lastobservedperiod;
157 if ~isempty(X)
158     % X is empty when AR(1) without parameter is encountered
159     fp = max(fp, X.firstobservedperiod);
160     lp = min(lp, X.lastobservedperiod);
161 end
162 if ~isempty(lhssub)
163     fp = max(fp, lhssub.firstobservedperiod);
164     lp = min(lp, lhssub.lastobservedperiod);
165 end

Finally, the Y, X, and lhssub datasets are adjusted given fp and lp:

188 Y = Y(fp:lp);
189 if ~isempty(X)
190     X = X(fp:lp);
191     names = X.name;
192     for i = 1:length(names)
193         if all(X.(names{i}).data == 0)
194             X = X.remove(names{i});
195         end
196     end
197 end
198 if ~isempty(lhssub)
199     lhssub = lhssub(fp:lp);
200 end

#### Step 3: Estimation via OLS

Back in dyn_ols.m, after parsing the equations as discussed above, we have the cell arrays Y, X, and lhssub, where each entry in these cell arrays corresponds to the vector/matrix of observables and regressors in each equation to be estimated. Analogously, fp and lp are cells containing the first and last observed period of the estimation range for each equation.

118 [Y, lhssub, X, fp, lp] = common_parsing(ds(ds_range), ast, true, param_names);

We loop over these cell arrays, running our estimation for each equation: $$\hat{\beta} = (X'X)^{-1}X'Y$$. [1] The output is set to the ols field of the standard Dynare MATLAB/Octave output structure, oo_. Each sub-field of oo_.ols corresponds to an equation tag that was either provided by the user or created by dyn_ols.m. In this case, they will be saved to oo_.ols.taylor_rule. Furthermore, the estimated parameter values are set in M_.

125     if ~isempty(model_name{i})
126         tag = model_name{i};
127     else
128         if isfield(ast{i}, 'tags') && isfield(ast{i}.tags, 'name')
129             tag = ast{i}.tags.('name');
130         else
131             tag = ['eq_line_no_' num2str(ast{i}.line)];
132         end
133     end
134
135     %% Estimation
136     % From LeSage, James P. "Applied Econometrics using MATLAB"
137     oo_.ols.(tag).dof = nobs - nvars;
138
139     % Estimated Parameters
140     [q, r] = qr(X{i}.data, 0);
141     xpxi = (r'*r)\eye(nvars);


text:
# Force proper odd/even margins even with changed numbering

I wrote "a book" and now I want to print it. I though that I'll just use twoside option and everything will be allright but there is always some problem...

Problems:

1) When I use twoside option, the first page is "on the left side in the book". Should be "on the right side in the book", right? Ok, so I added a blank page as the first page - now my "title page" is "on the right side in the book". It's a dirty solution, but it works. I'm using this "trick" further in the book. Is there any nicer solution?

2) The main problem I just can't find any solution to is with odd/even margins combined with start of pagenumbering. Let's see here:

On top left page the content ends. On the top right page, there is something like "First chapter page". On bottom left there is a blank page. So far so good (odd/even margins are on "the right side" and switching with every page). But on the bottom right page, there is a problem.

I want there first numbered page. But when I use \pagenumbering{arabic} in the code, then the page with number 1 is always "on the left side in the book" - right margin is larger than the left and "alternating of margins" is broke in this case.

I read so many answers here on the forum (e.g. using \cleardoublepage) but nothing worked for me. Any advice? I accept even some "dirty tricks" just to make it work.

TL;DR; Basically I want to force odd/even margins no matter what - page numbering, title pages, chapters etc. Just to make sure, that margins are switching with every new page.

My code:

\documentclass[11pt,a4paper,twoside]{report}
\usepackage[top=2.5cm,bottom=2cm]{geometry}
\usepackage[cp1250]{inputenc}
\usepackage[czech]{babel}
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{nameref}
\usepackage{showframe}
\usepackage{lipsum}
\usepackage{url}
\usepackage{graphicx}
\usepackage{float}
\bibliographystyle{plain}

\newcommand{\blankpage}{
\thispagestyle{empty}
\newpage
\mbox{}
\newpage
}

\begin{document}
\pagenumbering{gobble}

\blankpage
% TITLE PAGE
\begin{center}
\centering
{\huge\bfseries Author\par}
\vspace*{8cm}
{\Huge\bfseries Name\dots\par}
\vspace*{13cm}
{\huge\bfseries Year\par}
\newpage
\end{center}

\begin{flushleft}
\vspace*{8cm}
\noindent
{\bfseries Thanks to all ..\par}
\vspace*{13cm}
\noindent
ISBN: 12345678913543
\newpage
\end{flushleft}

\section*{Introduction}
\lipsum[3]

\blankpage

% content
\tableofcontents

\chapter*{\centering \vspace*{8cm} \textbf{First part: lorem ipsum}}
\newpage

\blankpage
\pagenumbering{arabic}% Remove page numbers (and reset to 1)

\section*{First Section of the book}
\lipsum

.......
\end{document}

• your assumption are wrong. first page is always odd page. different story is how you look document with previewer. – Zarko Feb 28 '18 at 18:19
• page number 1 would be expected to have larger margin on the right (the outside edge), isn't that what you are getting? but in latex odd/even margins refer to the value of the page counter not to the number of pages output, so if you reset the page counter you need to make sure you do not change the parity. (easiest to always do \cleardoublepage before setting it back to 1). – David Carlisle Feb 28 '18 at 19:47
• @DavidCarlisle I wonder why this isn't done by flipping a Bool on every page shipout, that would have been more stable and issues like this wouldn't even show up. – Skillmon Feb 28 '18 at 20:25
• @Skillmon things like \includeonly would have been perhaps harder if the link between page side and parity of page count was broken, but really parity of page counter should be enough you never (in left to right languages) want an odd numbered page on the left – David Carlisle Feb 28 '18 at 20:32
• @DavidCarlisle I wouldn't and typographically it would be nonsense, but looking at what I had to do to make my bachelor thesis look almost exactly like the Word template from the professor, I don't believe in a perfect world anymore. – Skillmon Feb 28 '18 at 22:17

The odd/even page is based on the page counter so if you reset the number to one you should first issue \cleardoublepage so that you are on an odd page, so changing the page number does not change the parity.

Here you see the boxed margin is consistently on the outer edge and the book title and part title are on a right hand page.

I started with a blank (even) page 0 to encourage the pdf reader I used here to put the odd numbered pages on the right. That probably needs to be removed if you print double sided as you want to print page 1 then page 2 on the back of that sheet, not page 1 on the back of page 0.

\documentclass[11pt,a4paper,twoside,openright]{report}
\usepackage[top=2.5cm,bottom=2cm]{geometry}
\usepackage[cp1250]{inputenc}
\usepackage[czech]{babel}
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{nameref}
\usepackage{showframe}
\usepackage{lipsum}
\usepackage{url}
\usepackage{graphicx}
\usepackage{float}
\bibliographystyle{plain}

\begin{document}
\pagestyle{empty}

\setcounter{page}{0}
\mbox{} % 0 blank page just for onscreen preview

\clearpage

% TITLE PAGE
\begin{center}
%%%\centering
{\huge\bfseries Author\par}
\vspace*{8cm}
{\Huge\bfseries Name\dots\par}
\vspace*{13cm}
{\huge\bfseries Year\par}
\end{center}

\newpage

\begin{flushleft}
\vspace*{8cm}
\noindent
{\bfseries Thanks to all ..\par}
\vspace*{13cm}
\noindent
ISBN: 12345678913543
\newpage
\end{flushleft}

\section*{Introduction}
\lipsum[3]

\cleardoublepage

% content
\tableofcontents

\chapter*{\centering \vspace*{8cm} \textbf{First part: lorem ipsum}}

\cleardoublepage
\pagenumbering{arabic}% Remove page numbers (and reset to 1)

\section*{First Section of the book}
\lipsum

.......
\end{document}

So I solved the issue looking at it from a different perspective. What I wanted in the end was to "swap odd/even margins" - so the first page (number 1) has larger left margin (in the book on the right side).

That's because I want to print just "a body" of a book, without cover etc.

This behaviour could be achieved by changing hmarginratio in geometry package (default is 2:3 for two side - documentation ref):

 \usepackage[hmarginratio=3:2]{geometry}

This answer here on the forum was really helpful. Thank you for all the help!

• that only addresses the size of the margins, not the fact that your example rests the page number in a way that makes the parity of the page counter not match the number of pages output, so you get two consecutive left hand pages as you commented in your question. – David Carlisle Mar 1 '18 at 19:43
• I don't understand your " "a body" of a book". In a normal book odd pages are at the right and even pages at the left. The outer page margin is usually twice the inner page margin so that when a book is opened you see a left (even) page and a right (odd) page with the white space at the spine being the same as the white space at the outer edges of the two pages. – Peter Wilson Mar 1 '18 at 20:28

format: plain


text:
### Research Areas

##### THE STANDARD MODEL TO THE LIMITS

The Standard Model (SM) is our best construction of the microscopic reality at the most fundamental level. The degree of consistency with experiment is astonishingly good.

Our Institute has played a fundamental role in this broad field of research.

##### COSMIC PARTICLES AND FUNDAMENTAL PHYSICS

Astroparticle Physics, as well as the connections between Particle Physics and Cosmology, are experiencing a new golden age.

Our Institute has been one of the pioneers in the Pierre Auger Observatory, a giant air shower array in Argentina.

##### NUCLEAR PHYSICS FROM THE LAB TO IMPROVE PEOPLE’S HEALTH

The participation of IGFAE in new international facilities such as FAIR offers unprecedented opportunities to contribute to understanding the nature of the strong interaction in the non-perturbative regime, the structure of the nuclear many-body systems and their astrophysical implications.


text:
# American Institute of Mathematical Sciences

March  2017, 37(3): 1295-1321. doi: 10.3934/dcds.2017054

## Modified energy functionals and the NLS approximation

 Department of Mathematics and Statistics, Boston University, Boston, MA 02215, USA

Received  June 2016 Revised  November 2016 Published  December 2016

We consider a model equation from [14] that captures important properties of the water wave equation. We give a new proof of the fact that wave packet solutions of this equation are approximated by the nonlinear Schrödinger equation. This proof both simplifies and strengthens the results of [14] so that the approximation holds for the full interval of existence of the approximate NLS solution rather than just a subinterval. Furthermore, the proof avoids the problems associated with inverting the normal form transform in [14] by working with a modified energy functional motivated by [1] and [8].

Citation: Patrick Cummings, C. Eugene Wayne. Modified energy functionals and the NLS approximation. Discrete & Continuous Dynamical Systems - A, 2017, 37 (3) : 1295-1321. doi: 10.3934/dcds.2017054
##### References:

show all references

##### References:
Partition of k$\ell$ -plane.
 [1] Dario Bambusi, A. Carati, A. Ponno. The nonlinear Schrödinger equation as a resonant normal form. Discrete & Continuous Dynamical Systems - B, 2002, 2 (1) : 109-128. doi: 10.3934/dcdsb.2002.2.109 [2] Nakao Hayashi, Pavel Naumkin. On the reduction of the modified Benjamin-Ono equation to the cubic derivative nonlinear Schrödinger equation. Discrete & Continuous Dynamical Systems - A, 2002, 8 (1) : 237-255. doi: 10.3934/dcds.2002.8.237 [3] D.G. deFigueiredo, Yanheng Ding. Solutions of a nonlinear Schrödinger equation. Discrete & Continuous Dynamical Systems - A, 2002, 8 (3) : 563-584. doi: 10.3934/dcds.2002.8.563 [4] Divyang G. Bhimani. The nonlinear Schrödinger equations with harmonic potential in modulation spaces. Discrete & Continuous Dynamical Systems - A, 2019, 39 (10) : 5923-5944. doi: 10.3934/dcds.2019259 [5] Zhong Wang. Stability of Hasimoto solitons in energy space for a fourth order nonlinear Schrödinger type equation. Discrete & Continuous Dynamical Systems - A, 2017, 37 (7) : 4091-4108. doi: 10.3934/dcds.2017174 [6] J. Colliander, M. Keel, G. Staffilani, H. Takaoka, T. Tao. Polynomial upper bounds for the instability of the nonlinear Schrödinger equation below the energy norm. Communications on Pure & Applied Analysis, 2003, 2 (1) : 33-50. doi: 10.3934/cpaa.2003.2.33 [7] Miaomiao Niu, Zhongwei Tang. Least energy solutions for nonlinear Schrödinger equation involving the fractional Laplacian and critical growth. Discrete & Continuous Dynamical Systems - A, 2017, 37 (7) : 3963-3987. doi: 10.3934/dcds.2017168 [8] Congming Peng, Dun Zhao. Global existence and blowup on the energy space for the inhomogeneous fractional nonlinear Schrödinger equation. Discrete & Continuous Dynamical Systems - B, 2019, 24 (7) : 3335-3356. doi: 10.3934/dcdsb.2018323 [9] Pavel I. Naumkin, Isahi Sánchez-Suárez. On the critical nongauge invariant nonlinear Schrödinger equation. Discrete & Continuous Dynamical Systems - A, 2011, 30 (3) : 807-834. doi: 10.3934/dcds.2011.30.807 [10] Younghun Hong. Scattering for a nonlinear Schrödinger equation with a potential. Communications on Pure & Applied Analysis, 2016, 15 (5) : 1571-1601. doi: 10.3934/cpaa.2016003 [11] Alexander Komech, Elena Kopylova, David Stuart. On asymptotic stability of solitons in a nonlinear Schrödinger equation. Communications on Pure & Applied Analysis, 2012, 11 (3) : 1063-1079. doi: 10.3934/cpaa.2012.11.1063 [12] Tarek Saanouni. Remarks on the damped nonlinear Schrödinger equation. Evolution Equations & Control Theory, 2020, 9 (3) : 721-732. doi: 10.3934/eect.2020030 [13] Mohamad Darwich. On the $L^2$-critical nonlinear Schrödinger Equation with a nonlinear damping. Communications on Pure & Applied Analysis, 2014, 13 (6) : 2377-2394. doi: 10.3934/cpaa.2014.13.2377 [14] Noboru Okazawa, Toshiyuki Suzuki, Tomomi Yokota. Energy methods for abstract nonlinear Schrödinger equations. Evolution Equations & Control Theory, 2012, 1 (2) : 337-354. doi: 10.3934/eect.2012.1.337 [15] Wulong Liu, Guowei Dai. Multiple solutions for a fractional nonlinear Schrödinger equation with local potential. Communications on Pure & Applied Analysis, 2017, 16 (6) : 2105-2123. doi: 10.3934/cpaa.2017104 [16] Xudong Shang, Jihui Zhang. Multiplicity and concentration of positive solutions for fractional nonlinear Schrödinger equation. Communications on Pure & Applied Analysis, 2018, 17 (6) : 2239-2259. doi: 10.3934/cpaa.2018107 [17] Patricio Felmer, César Torres. Radial symmetry of ground states for a regional fractional Nonlinear Schrödinger Equation. Communications on Pure & Applied Analysis, 2014, 13 (6) : 2395-2406. doi: 10.3934/cpaa.2014.13.2395 [18] Olivier Goubet, Wided Kechiche. Uniform attractor for non-autonomous nonlinear Schrödinger equation. Communications on Pure & Applied Analysis, 2011, 10 (2) : 639-651. doi: 10.3934/cpaa.2011.10.639 [19] Wided Kechiche. Regularity of the global attractor for a nonlinear Schrödinger equation with a point defect. Communications on Pure & Applied Analysis, 2017, 16 (4) : 1233-1252. doi: 10.3934/cpaa.2017060 [20] Benjamin Dodson. Improved almost Morawetz estimates for the cubic nonlinear Schrödinger equation. Communications on Pure & Applied Analysis, 2011, 10 (1) : 127-140. doi: 10.3934/cpaa.2011.10.127

2019 Impact Factor: 1.338


text:
# zbMATH — the first resource for mathematics

Erratum to: “Hodge theory of the middle convolution”. (English) Zbl 1408.14036
Summary: We give a correction to the statement of Theorem 3.2.3 of [the authors, ibid. 49, No. 4, 761–800 (2013; Zbl 1307.14015)].

##### MSC:
 14D07 Variation of Hodge structures (algebro-geometric aspects) 32G20 Period matrices, variation of Hodge structure; degenerations 32S40 Monodromy; relations with differential equations and $$D$$-modules (complex-analytic aspects) 34M99 Ordinary differential equations in the complex domain
Full Text:


text:
## My All 2020 Mathematics A to Z: Butterfly Effect

It’s a fun topic today, one suggested by Jacob Siehler, who I think is one of the people I met through Mathstodon. Mathstodon is a mathematics-themed instance of Mastodon, an open-source microblogging system. You can read its public messages here.

# Butterfly Effect.

I take the short walk from my home to the Red Cedar River, and I pour a cup of water in. What happens next? To the water, anyway. Me, I think about walking all the way back home with this empty cup.

Let me have some simplifying assumptions. Pretend the cup of water remains somehow identifiable. That it doesn’t evaporate or dissolve into the riverbed. That it isn’t scooped up by a city or factory, drunk by an animal, or absorbed into a plant’s roots. That it doesn’t meet any interesting ions that turn it into other chemicals. It just goes as the river flows dictate. The Red Cedar River merges into the Grand River. This then moves west, emptying into Lake Michigan. Water from that eventually passes the Straits of Mackinac into Lake Huron. Through the St Clair River it goes to Lake Saint Clair, the Detroit River, Lake Erie, the Niagara River, the Niagara Falls, and Lake Ontario. Then into the Saint Lawrence River, then the Gulf of Saint Lawrence, before joining finally the North Atlantic.

If I pour in a second cup of water, somewhere else on the Red Cedar River, it has a similar journey. The details are different, but the course does not change. Grand River to Lake Michigan to three more Great Lakes to the Saint Lawrence to the North Atlantic Ocean. If I wish to know when my water passes the Mackinac Bridge I have a difficult problem. If I just wish to know what its future is, the problem is easy.

So now you understand dynamical systems. There’s some details to learn before you get a job, yes. But this is a perspective that explains what people in the field do, and why that. Dynamical systems are, largely, physics problems. They are about collections of things that interact according to some known potential energy. They may interact with each other. They may interact with the environment. We expect that where these things are changes in time. These changes are determined by the potential energies; there’s nothing random in it. Start a system from the same point twice and it will do the exact same thing twice.

We can describe the system as a set of coordinates. For a normal physics system the coordinates are the positions and momentums of everything that can move. If the potential energy’s rule changes with time, we probably have to include the time and the energy of the system as more coordinates. This collection of coordinates, describing the system at any moment, is a point. The point is somewhere inside phase space, which is an abstract idea, yes. But the geometry we know from the space we walk around in tells us things about phase space, too.

Imagine tracking my cup of water through its journey in the Red Cedar River. It draws out a thread, running from somewhere near my house into the Grand River and Lake Michigan and on. This great thin thread that I finally lose interest in when it flows into the Atlantic Ocean.

Dynamical systems drops in phase space act much the same. As the system changes in time, the coordinates of its parts change, or we expect them to. So “the point representing the system” moves. Where it moves depends on the potentials around it, the same way my cup of water moves according to the flow around it. “The point representing the system” traces out a thread, called a trajectory. The whole history of the system is somewhere on that thread.

Phase space, like a map, has regions. For my cup of water there’s a region that represents “is in Lake Michigan”. There’s another that represents “is going over Niagara Falls”. There’s one that represents “is stuck in Sandusky Bay a while”. When we study dynamical systems we are often interested in what these regions are, and what the boundaries between them are. Then a glance at where the point representing a system is tells us what it is doing. If the system represents a satellite orbiting a planet, we can tell whether it’s in a stable orbit, about to crash into a moon, or about to escape to interplanetary space. If the system represents weather, we can say it’s calm or stormy. If the system is a rigid pendulum — a favorite system to study, because we can draw its phase space on the blackboard — we can say whether the pendulum rocks back and forth or spins wildly.

Come back to my second cup of water, the one with a different history. It has a different thread from the first. So, too, a dynamical system started from a different point traces out a different trajectory. To find a trajectory is, normally, to solve differential equations. This is often useful to do. But from the dynamical systems perspective we’re usually interested in other issues.

For example: when I pour my cup of water in, does it stay together? The cup of water started all quite close together. But the different drops of water inside the cup? They’ve all had their own slightly different trajectories. So if I went with a bucket, one second later, trying to scoop it all up, likely I’d succeed. A minute later? … Possibly. An hour later? A day later?

By then I can’t gather it back up, practically speaking, because the water’s gotten all spread out across the Grand River. Possibly Lake Michigan. If I knew the flow of the river perfectly and knew well enough where I dropped the water in? I could predict where each goes, and catch each molecule of water right before it falls over Niagara. This is tedious but, after all, if you start from different spots — as the first and the last drop of my cup do — you expect to, eventually, go different places. They all end up in the North Atlantic anyway.

Except … well, there is the Chicago Sanitary and Ship Canal. It connects the Chicago River to the Des Plaines River. The result is that some of Lake Michigan drains to the Ohio River, and from there the Mississippi River, and the Gulf of Mexico. There are also some canals in Ohio which connect Lake Erie to the Ohio River. I don’t know offhand of ones in Indiana or Wisconsin bringing Great Lakes water to the Mississippi. I assume there are, though.

Then, too, there is the Erie Canal, and the other canals of the New York State Canal System. These link the Niagara River and Lake Erie and Lake Ontario to the Hudson River. The Pennsylvania Canal System, too, links Lake Erie to the Delaware River. The Delaware and the Hudson may bring my water to the mid-Atlantic. I don’t know the canal systems of Ontario well enough to say whether some water goes to Hudson Bay; I’d grant that’s possible, though.

Think of my poor cups of water, now. I had been sure their fate was the North Atlantic. But if they happen to be in the right spot? They visit my old home off the Jersey Shore. Or they flow through Louisiana and warmer weather. What is their fate?

I will have butterflies in here soon.

Imagine two adjacent drops of water, one about to be pulled into the Chicago River and one with Lake Huron in its future. There is almost no difference in their current states. Their destinies are wildly separate, though. It’s surprising that so small a difference matters. Thinking through the surprise, it’s fair that this can happen, even for a deterministic system. It happens that there is a border, separating those bound for the Gulf and those for the North Atlantic, between these drops.

But how did those water drops get there? Where were they an hour before? … Somewhere else, yes. But still, on opposite sides of the border between “Gulf of Mexico water” and “North Atlantic water”. A day before, the drops were somewhere else yet, and the border was still between them. This separation goes back to, even, if the two drops came from my cup of water. Within the Red Cedar River is a border between a destiny of flowing past Quebec and of flowing past Saint Louis. And between flowing past Quebec and flowing past Syracuse. Between Syracuse and Philadelphia.

How far apart are those borders in the Red Cedar River? If you’ll go along with my assumptions, smaller than my cup of water. Not that I have the cup in a special location. The borders between all these fates are, probably, a complicated spaghetti-tangle. Anywhere along the river would be as fortunate. But what happens if the borders are separated by a space smaller than a drop? Well, a “drop” is a vague size. What if the borders are separated by a width smaller than a water molecule? There’s surely no subtleties in defining the “size” of a molecule.

That these borders are so close does not make the system random. It is still deterministic. Put a drop of water on this side of the border and it will go to this fate. But how do we know which side of the line the drop is on? If I toss this new cup out to the left rather than the right, does that matter? If my pinky twitches during the toss? If I am breathing in rather than out? What if a change too small to measure puts the drop on the other side?

And here we have the butterfly effect. It is about how a difference too small to observe has an effect too large to ignore. It is not about a system being random. It is about how we cannot know the system well enough for its predictability to tell us anything.

The term comes from the modern study of chaotic systems. One of the first topics in which the chaos was noticed, numerically, was weather simulations. The difference between a number’s representation in the computer’s memory and its rounded-off printout was noticeable. Edward Lorenz posed it aptly in 1963, saying that “one flap of a sea gull’s wings would be enough to alter the course of the weather forever”. Over the next few years this changed to a butterfly. In 1972 Philip Merrilees titled a talk Does the flap of a butterfly’s wings in Brazil set off a tornado in Texas? My impression is that these days the butterflies may be anywhere, and they alter hurricanes.

That we settle on butterflies as agents of chaos we can likely credit to their image. They seem to be innocent things so slight they barely exist. Hummingbirds probably move with too much obvious determination to fit the role. The Big Bad Wolf huffing and puffing would realistically be almost as nothing as a butterfly. But he has the power of myth to make him seem mightier than the storms. There are other happy accidents supporting butterflies, though. Edward Lorenz’s 1960s weather model makes trajectories that, plotted, create two great ellipsoids. The figures look like butterflies, all different but part of the same family. And there is Ray Bradbury’s classic short story, A Sound Of Thunder. If you don’t remember 7th grade English class, in the story time-travelling idiots change history, putting a fascist with terrible spelling in charge of a dystopian world, by stepping on a butterfly.

The butterfly then is metonymy for all the things too small to notice. Butterflies, sea gulls, turning the ceiling fan on in the wrong direction, prying open the living room window so there’s now a cross-breeze. They can matter, we learn.

## Reading the Comics, March 11, 2020: Half Week Edition

There were a good number of comic strips mentioning mathematical subjects last week, as you might expect for one including the 14th of March. Most of them were casual mentions, though, so that’s why this essay looks like this. And is why the week will take two pieces to finish.

Jonathan Lemon and Joey Alison Sayer’s Little Oop for the 8th is part of a little storyline for the Sunday strips. In this the young Alley Oop has … travelled in time to the present. But different from how he does in the weekday strips. What’s relevant about this is Alley Oop hearing the year “2020” and mentioning how “we just got math where I come from” but being confident that’s either 40 or 400. Which itself follows up a little thread in the Sunday strips about new numbers on display and imagining numbers greater than three.

Maria Scrivan’s Half Full for the 9th is the Venn Diagram strip for the week.

Paul Trap’s Thatababy for the 9th is a memorial strip to Katherine Johnson. She was, as described, a NASA mathematician, and one of the great number of African-American women whose work computing was rescued from obscurity by the book and movie Hidden Figures. NASA, and its associated agencies, do a lot of mathematical work. Much of it is numerical mathematics: a great many orbital questions, for example, can not be answered with, like, the sort of formula that describes how far away a projectile launched on a parabolic curve will land. Creating a numerical version of a problem requires insight and thought about how to represent what we would like to know. And calculating that requires further insight, so that the calculation can be done accurately and speedily. (I think about sometime doing a bit about the sorts of numerical computing featured in the movie, but I would hardly be the first.)

I also had thought the Mathematical Moments from the American Mathematical Society had posted an interview with her last year. I was mistaken but in, I think, a forgivable way. In the episode “Winning the Race”, posted the 12th of June, they interviewed Christine Darden, another of the people in the book, though not (really) the movie. Darden joined NASA in the late 60s. But the interview does talk about this sort of work, and how it evolved with technology. And, of course, mentions Johnson and her influence.

Graham Harrop’s Ten Cats for the 9th is another strip mentioning Albert Einstein and E = mc2. And using the blackboard full of symbols to represent deep thought.

Patrick Roberts’s Todd the Dinosaur for the 10th showcases Todd being terrified of fractions. And more terrified of story problems. I can’t call it a false representation of the kinds of mathematics that terrify people.

Stephen Beals’s Adult Children for the 11th has a character mourning that he took calculus as he’s “too stupid to be smart”. Knowing mathematics is often used as proof of intelligence. And calculus is used as the ultimate of mathematics. It’s a fair question why calculus and not some other field of mathematics, like differential equations or category theory or topology. Probably it’s a combination of slightly lucky choices (for calculus). Calculus is old enough to be respectable. It’s often taught as the ultimate mathematics course that people in high school or college (and who aren’t going into a mathematics field) will face. It’s a strange subject. Learning it requires a greater shift in thinking about how to solve problems than even learning algebra does. And the name is friendly enough, without the wordiness or technical-sounding language of, for example, differential equations. The subject may be well-situated.

Tony Rubino and Gary Markstein’s Daddy’s Home for the 11th has the pacing of a logic problem, something like the Liar’s Paradox. It’s also about homework which happens to be geometry, possibly because the cartoonists aren’t confident that kids that age might be taking a logic course.

I’ll have the rest of the week’s strips, including what Comic Strip Master Command ordered done for Pi Day, soon. And again I mention that I’m hosting this month’s Playful Math Education Blog Carnival. If you have come across a web site with some bit of mathematics that brought you delight and insight, please let me know, and mention any creative projects that you have, that I may mention that too. Thank you.

## Reading the Comics, March 9, 2019: In Which I Explain Eleven Edition

I thought I had a flood of mathematically-themed comic strips last week. On reflection, many of them were slight enough not to need further context. You’ll see in the paragraph of not-discussed strips at the end of this. What did rate discussion turned out to get more interesting to me the more I wrote about them.

Stephen Beals’s Adult Children for the 6th uses mathematics as icon of things that are indisputably true. Two plus two equals four is a good example of such. If we take the ordinary meanings of ‘two’ and ‘plus’ and ‘equals’ and ‘four’ there’s no disputing it. The result follows from some uncontroversial-seeming axioms and a lot of deduction. By the rules of logic, the conclusion has to be true, whoever makes it. Even, for that matter, if nobody makes it. It’s difficult to imagine a universe in which nobody ever notices two plus two equals four. But we can imagine that there are mathematical truths that will never be noticed by anyone. (Here’s one. There is some largest finite whole number that any human-created project will ever use in any context. Consider the equation represented by “that number plus two equals (even bigger number)”.)

But you see cards palmed there. What do we mean by ‘two’? Have we got a good definition? Might there be a different definition that’s more useful? Probably not, for ‘two’ anyway. But a part of mathematics, especially as a field develops, is working out what are the important concepts, and what their definitions should be. What a ‘function’ is, for example, went through a lot of debate and change over the 19th century. There is an elusiveness to facts, even in mathematics, where you’d think epistemology would be simpler.

Frank Page’s Bob the Squirrel for the 6th continues the SAT prep questions from earlier in the week. There’s two more problems in shuffling around algebraic expressions here. The first one, problem 5, is probably easiest to do by eliminating wrong answers. $(x^2 y - 3y^2 + 5xy^2) - (-x^2 y + 3xy^2 - 3y^2)$ is a tedious mess. But look at just the $x^2 y$ terms: they have to add up to $2x^2 y$, so, the answer has to be either c or d. So next look at the $3y^2$ terms and oh, that’s nice. They add up to zero. The answer has to be c. If you feel like checking the $5xy^2$ terms, go ahead; that’ll offer some reassurance, if you do the addition correctly.

The second one, problem 8, is probably easier to just think out. If $\frac{a}{b} = 2$ then there’s a lot of places to go. What stands out to me is that $4\frac{b}{a}$ has the reciprocal of $\frac{a}{b}$ in it. So, the reciprocal of $\frac{a}{b}$ has to equal the reciprocal of $2$. So $\frac{a}{b} = \frac{1}{2}$. And $4\frac{b}{a}$ is, well, four times $\frac{b}{a}$, so, four times one-half, or two. There’s other ways to go about this. In honestly, what I did when I looked at the problem was multiply both sides of $\frac{a}{b} = 2$ by $\frac{b}{a}$. But it’s harder to explain why that struck me as an obviously right thing to do. It’s got shortcuts I grew into from being comfortable with the more methodical approach. Someone who does a lot of problems like these will discover shortcuts.

Rick Detorie’s One Big Happy for the 6th asks one of those questions you need to be a genius or a child to ponder. Why don’t the numbers eleven and twelve follow the pattern of the other teens, or for that matter of twenty-one and thirty-two, and the like? And the short answer is that they kind of do. At least, “eleven” and “twelve”, etymologists agree, derive from the Proto-Germanic “ainlif” and “twalif”. If you squint your mouth you can get from “ain” to “one” (it’s probably easier if you go through the German “ein” along the way). Getting from “twa” to “two” is less hard. If my understanding is correct, etymologists aren’t fully agreed on the “lif” part. But they are settled on it means the part above ten. Like, “ainlif” would be “one left above ten”. So it parses as one-and-ten, putting it in form with the old London-English preference for one-and-twenty or two-and-thirty as word constructions.

It’s not hard to figure how “twalif” might over centuries mutate to “twelve”. We could ask why “thirteen” didn’t stay something more Old Germanic. My suspicion is that it amounts to just, well, it worked out like that. It worked out the same way in German, which switches to “-zehn” endings from 13 on. Lithuanian has all the teens end with “-lika”; Polish, similarly, but with “-ście”. Spanish — not a Germanic language — has “custom” words for the numbers up to 15, and then switches to “diecis-” as a prefix to the numbers 6 through 9. French doesn’t switch to a systematic pattern until 17. (And no I am not going to talk about France’s 80s and 90s.) My supposition is that different peoples came to different conclusions about whether they needed ten, or twelve, or fifteen, or sixteen, unique names for numbers before they had to resort to systemic names.

Here’s some more discussion of the teens, though, including some exploration of the controversy and links to other explanations.

Doug Savage’s Savage Chickens for the 6th is a percentages comic. It makes reference to an old series of (American, at least) advertisements in which four out of five dentists would agree that chewing sugarless gum is a good thing. Shifting the four-out-of-five into 80% riffs is not just fun with tautologies. Percentages have this connotation of technical precision; 80% sounds like a more rigorously known number than “four out of five”. It doesn’t sound as scientific as “0.80”, quite. But when applied to populations a percentage seems less bizarre than a decimal.

Oh, now, and what about comic strips I can’t think of anything much to write about?
Ruben Bolling’s Super-Fun-Pak Comix for the 4th featured divisibility, in a panel titled “Fun Facts for the Obsessive-Compulsive”. Olivia James’s Nancy on the 6th was avoiding mathematics homework. Jonathan Mahood’s Bleeker: The Rechargeable Dog for the 7th has Skip avoiding studying for his mathematics test. Bob Scott’s Bear With Me for the 7th has Molly mourning a bad result on her mathematics test. (The comic strip was formerly known as Molly And The Bear, if this seems familiar but the name seems wrong.) These are all different comic strips, I swear. Bill Holbrook’s Kevin and Kell for the 8th has Rudy and Fiona in mathematics class. (The strip originally ran in 2013; Comics Kingdom has started running Holbrook’s web comic, but at several years’ remove.) And, finally, Alex Hallatt’s Human Cull for the 8th talks about “110%” as a phrase. I don’t mind the phrase, but the comic strip has a harder premise.

And that finishes the comic strips from last week. But Pi Day is coming. I’ll be ready for it. Shall see you there.

## Reading the Comics, October 27, 2018: Surprise Rerun Edition

While putting together the last comics from a week ago I realized there was a repeat among them. And a pretty recent repeat too. I’m supposing this is a one-off, but who can be sure? We’ll get there. I figure to cover last week’s mathematically-themed comics in posts on Wednesday and Thursday, subject to circumstances.

Zach Weinersmith’s Saturday Morning Breakfast Cereal for the 26th is a joking reminder that educational texts, including in mathematics, don’t have to be boring. We can have narrative thrust and energy. It’s a good reminder.

As fits the joke, the bit of calculus in this textbook paragraph is wrong. $\int \sqrt{x^2 + x} dx$ does not equal $\left(x^2 + x\right)^{-\frac12}$. This is even ignoring that we should expect, with an indefinite integral like this, a constant of integration. An indefinite integral like this is equal to a family of related functions. But it’s common shorthand to write out one representative function. But the indefinite integral of $\sqrt{x^2 + x}$ is not $\left(x^2 + x\right)^{-\frac12}$. You can confirm that by differentiating $\left(x^2 + x\right)^{-\frac12}$. The result is nothing like $\sqrt{x^2 + x}$. Differentiating an indefinite integral should get the original function back. Here are the rules you need to do that for yourself.

As I make it out, a correct indefinite integral would be:

$\int{\sqrt{x^2 + x} dx} = \frac{1}{4}\left( \left(2x + 1\right)\sqrt{x^2 + x} + \log \left|\sqrt{x} + \sqrt{x + 1} \right| \right)$

Plus that “constant of integration” the value of which we can’t tell just from the function we want to indefinitely-integrate. I admit I haven’t double-checked that I’m right in my work here. I trust someone will tell me if I’m not. I’m going to feel proud enough if I can get the LaTeX there to display.

Stephen Beals’s Adult Children for the 27th has run already. It turned up in late March of this year. Michael Spivak’s Calculus is a good choice for representative textbook. Calculus holds its terrors, too. Even someone who’s gotten through trigonometry can find the subject full of weird, apparently arbitrary rules. And formulas like those in the above paragraph.

Rob Harrell’s Big Top for the 27th is a strip about the difficulties of splitting a restaurant bill. And they’ve not even got to calculating the tip. (Maybe it’s just a strip about trying to push the group to splitting the bill a way that lets you off cheap. I haven’t had to face a group bill like this in several years. My skills with it are rusty.)

Dave Whamond’s Reality Check for the 27th is a Pi Day joke shifted to the Halloween season.

And I have more Reading the Comics post at this link. Since it’s not true that every one of these includes a Saturday Morning Breakfast Cereal mention, you can find those that have one at this link. Essays discussing Adult Children, including the first time this particular strip appeared, are at this link. Essays with a mention of Big Top are at this link. And essays with a mention of Reality Check are at this link. Furthermore, this month and the rest of this year my Fall 2018 Mathematics A-To-Z should continue. And it is open for requests for more of the alphabet.

## Reading the Comics, October 11, 2018: Under Weather Edition

I ended up not finding more comics on-topic on GoComics yesterday. So this past week’s mathematically-themed strips should fit into two posts well. I apologize for any loss of coherence in this essay, as I’m getting a bit of a cold. I’m looking forward to what this cold does for the A To Z essays coming Tuesday and Friday this week, too.

Stephen Beals’s Adult Children for the 7th uses Albert Einstein’s famous equation as shorthand for knowledge. I’m a little surprised it’s written out in words, rather than symbols. This might reflect that $E = mc^2$ is often understood just as this important series of sounds, rather than as an equation relating things to one another. Or it might just reflect the needs of the page composition. It could be too small a word balloon otherwise.

Julie Larson’s The Dinette Set for the 9th continues the thread of tip-calculation jokes around here. I have no explanation for this phenomenon. In this case, Burl is doing the calculation correctly. If the tip is supposed to be 15% of the bill, and the bill is reduced 10%, then the tip would be reduced 10%. If you already have the tip calculated, it might be quicker to figure out a tenth of that rather than work out 15% of the original bill. And, yes, the characters are being rather unpleasantly penny-pinching. That was just the comic strip’s sense of humor.

Todd Clark’s Lola for the 9th take the form of your traditional grumbling about story problems. It also shows off the motif of updating of the words in a story problem to be awkwardly un-hip. The problem seems to be starting in a confounding direction anyway. The first sentence isn’t out and it’s introducing the rate at which Frank is shedding social-media friends over time and the rate at which a train is travelling, some distancer per time. Having one quantity with dimensions friends-per-time and another with dimensions distance-per-time is begging for confusion. Or for some weird gibberish thing, like, determining something to be (say) ninety mile-friends. There’s trouble ahead.

Zach Weinersmith’s Saturday Morning Breakfast Cereal for the 10th proposes naming a particular kind of series. A series is the sum of a sequence of numbers. It doesn’t have to be a sequence with infinitely many numbers in it, but it usually is, if it’s to be an interesting series. Properly, a series gets defined by something like the symbols in the upper caption of the panel:

$\sum_{i = 1}^{\infty} a_i$

Here the ‘i’ is a “dummy variable”, of no particular interest and not even detectable once the calculation is done. It’s not that thing with the square roots of -1 in thise case. ‘i’ is specifically known as the ‘index’, since it indexes the terms in the sequence. Despite the logic of i-index, I prefer to use ‘j’, ‘k’, or ‘n’. This avoids confusion with that square-root-of-minus-1 meaning for i. The index starts at some value, the one to the right of the equals sign underneath the capital sigma; in this case, 1. The sequence evaluates whatever the formula described by $a_i$ is, for each whole number between that lowest ‘i’, in this case 1, and whatever the value above the sigma is. For the infinite series, that’s infinitely large. That is, work out $a_i$ for every counting number ‘i’. For the first sum in the caption, that highest number is 4, and you only need to evaluate four terms and add them together. There’s no rule given for $a_i$ in the caption; that just means that, in this case, we don’t yet have reason to care what the formula is.

This is the way to define a series if we’re being careful, and doing mathematics properly. But there are shorthands, and we fall back on them all the time. On the blackboard is one of them: $24 + 12 + 6 + 3 + \cdots$. The $\cdots$ at the end of a summation like this means “carry on this pattern for infinitely many terms”. If it appears in the middle of a summation, like $2 + 4 + 6 + 8 + \cdots + 20$ it means “carry on this pattern for the appropriate number of terms”. In that case, it would be $10 + 12 + 14 + 16 + 18$.

The flaw with this “carry on this pattern” is that, properly, there’s no such thing as “the” pattern. There are infinitely many ways to continue from whatever the start was, and they’re all equally valid. What lets this scheme work is cultural expectations. We expect the difference between one term and the next to follow some easy patterns. They increase or decrease by the same amount as we’ve seen before (an arithmetic progression, like 2 + 4 + 6 + 8, increasing by two each time). They increase or decrease by the same ratio as we’ve seen before (a geometric progression, like 24 + 12 + 6 + 3, cutting in half each time). Maybe the sign alternates, or changes by some straightforward rule. If it isn’t one of these, then we have to fall back on being explicit. In this case, it would be that $a_i = 24 \cdot \left(\frac{1}{2}\right)^{i - 1}$.

The capital-sigma as shorthand for “sum” traces to Leonhard Euler, because of course. I’m finding it hard, in my copy of Florian Cajori’s History of Mathematical Notations, to find just where the series notation as we use it got started. Also I’m not finding where ellipses got into mathematical notation either. It might reflect everybody realizing this was a pretty good way to represent “we’re not going to write out the whole thing here”.

Norm Feuti’s Retail for the 11th riffs on how many people, fundamentally, don’t know what percentages are. I think it reflects thinking of a percentage as some kind of unit. We get used to measurements of things, like, pounds or seconds or dollars or degrees or such that are fixed in value. But a percentage is relative. It’s a fraction of some original quantity. A difference of (say) two pounds in weight is the same amount of weight whatever the original was; why wouldn’t two percent of the weight behave similarly? … Gads, yes, I feel for the next retailer who gets these customers.

I think I’ve already used the story from when I worked in the bookstore about the customer concerned whether the ten-percent-off sticker applied before or after sales tax was calculated. So I’ll only share if people ask to hear it. (They won’t ask.)

When I’m not getting a bit ill, I put my Reading the Comics posts at this link. Essays which mention Adult Children are at this link. Essays with The Dinette Set discussions should be at this link. The essays inspired by Lola are at this link. There’s some mention of Saturday Morning Breakfast Cereal in essays at link, or pretty much every Reading the Comics post. And Retail gets discussed at this link.

## Reading the Comics, March 31, 2018: A Normal Week Edition

I have a couple loose rules about these Reading the Comics posts. At least one a week, whether there’s much to talk about or not. Not too many comics in one post, because that’s tiring to read and tiring to write. Trying to write up each day’s comics on the day mitigates that some, but not completely. So I tend to break up a week’s material if I can do, say, two posts of about seven strips each. This year, that’s been necessary; I’ve had a flood of comics on-topic or close enough for me to write about. This past week was a bizarre case. There really weren’t enough strips to break up the workload. It was, in short, a normal week, as strange as that is to see. I don’t know what I’m going to do Thursday. I might have to work.

Aaron McGruder’s Boondocks for the 25th of March is formally just a cameo mention of mathematics. There is some serious content to it. Whether someone likes to do a thing depends, to an extent, on whether they expect to like doing a thing. It seems likely to me that if a community encourages people to do mathematics, then it’ll have more people who do mathematics well. Mathematics does at least have the advantage that a lot of its fields can be turned into games. Or into things like games. Is one knot the same as another knot? You can test the laborious but inevitably correct way, trying to turn one into the other. Or you can find a polynomial that describes both knots and see if those two are the same polynomials. There’s fun to be had in this. I swear. And, of course, making arguments and finding flaws in other people’s arguments is a lot of mathematics. And good fun for anybody who likes that sort of thing. (This is a new tag for me.)

Ted Shearer’s Quincy for the 30th of January, 1979 and rerun the 26th names arithmetic as the homework Quincy’s most worried about. Or would like to put off the most. Harmless enough.

Mike Thompson’s Grand Avenue for the 26th is a student-resisting-the-problem joke. A variable like ‘x’ serves a couple of roles. One of them is the name for a number whose value we don’t explicitly know, but which we hope to work out. And that’s the ‘x’ seen here. The other role of ‘x’ is the name for a number whose value we don’t know and don’t particularly care about. Since those are different reasons to use ‘x’ maybe we ought to have different names for the concepts. But we don’t and there’s probably no separating them now.

Tony Cochran’s Agnes for the 27th grumbles that mathematics and clairvoyance are poorly taught. Well, everyone who loves mathematics grumbles that the subject is poorly taught. I don’t know what the clairvoyants think but I’ll bet the same.

Mark Pett’s Lucky Cow rerun for the 28th is about sudoku. As with any puzzle the challenge is having rules that are restrictive enough to be interesting. This is also true of any mathematical field, though. You want ideas that imply a lot of things are true, but that also imply enough interesting plausible things are not true.

Rick DeTorie’s One Big Happy rerun for the 30th has Ruthie working on a story problem. One with loose change, which seems to turn up a lot in story problems. I never think of antes for some reason.

Stephen Beals’s Adult Children for the 31st depicts mathematics as the stuff of nightmares. (Although it’s not clear to me this is meant to recount a nightmare. Reads like it, anyway.) Calculus, too, which is an interesting choice. Calculus seems to be a breaking point for many people. A lot of people even who were good at algebra or trigonometry find all this talk about differentials and integrals and limits won’t cohere into understanding. Isaac Asimov wrote about this several times, and the sad realization that for as much as he loved mathematics there were big important parts of it that he could not comprehend.

I’m curious why calculus should be such a discontinuity, but the reasons are probably straightforward. It’s a field where you’re less interested in doing things to numbers and more interested in doing things to functions. Or to curves that a function might represent. It’s a field where information about a whole region is important, rather than information about a single point. It’s a field where you can test your intuitive feeling for, say, a limit by calculating a couple of values, but for which those calculations don’t give the right answer. Or at least can’t be guaranteed to be right. I don’t know if the choice of what to represent mathematics was arbitrary. But it was a good choice certainly. (This is another newly-tagged strip.)


text:
A magician can make his trick with just a wave of a magic wand, our engineers can make their magic with just one click! Interested how the same winter landscape would look in summer, then keep on reading.   The comprehensive research was completed by our R&D department with the purpose of investigating current possibilities of Machine Learning generators and what quality they can provide for a task of translating winter to summer image as an analogy to automatic language translation. We have conducted the investigation of different generative models and application methods, prepared a solid dataset, and the most suitable model we have adopted to satisfy our requirements. The idea of transitioning the photo taken in winter into a summery image could be applied in a landscape design or related spheres. That would give an opportunity to have a clear vision of the same image in different seasons. The implementation of the same technologies can also enable the various color changes of images.

## Computer Vision Solutions

Give meaning to images, analyze video, and recognize objects with the highest accuracy.

## The secret to our magic is CGAN neural network

A lot of approaches and processing models were researched, analyzed and tested, i.e. neural networks: CGAN, CVAE; pixel-to-pixel translation. CGAN appeared to be the most suitable for our image-to-image translation task because of the following reasons:

• Sharp & realistic image synthesis
• Semi-supervised learning
• Excellent test of our ability to use high-dimensional complicated data
• Bleeding edge ML technology

Conditional GAN is a subset of GANs – Generative adversarial networks. GAN is a type of generative neural networks that consists of two networks: discriminator – D and generator – G. We can easily understand the key concept behind them by imagining a team of counterfeiters as a G and police as D. Counterfeiters (G) is constantly trying to produce fake currency (images), while police (D) is trying to estimate whether it’s real or fake. As time passes both of them are becoming better in their jobs. Conditional GAN has the same principle, but we have some additional info – condition. So now, instead of asking counterfeiters to just produce some fake currency, we ask them to produce, let’s say, fake 100$. Similarly, instead of just asking the police to judge if it’s fake or real, we ask them to judge is it’s 100$. It allows us to teach G to generate even more realistic currency (images in our case).   Figure 1. cGAN Structure

While working on the image-to-image translation of the winter  photos, our image processing engineers have faced numerous challenges, like:

• dataset aggregation and preparation;
• long iterations
• the cost of experiments;
• the complexity of CGAN, the configuration of many knobs

They continued their research on image-to-image translation with the huge and comprehensive dataset of images collection. At first, our R&D team worked with Transient Attribute Dataset. However, due to the lack of images and in order to reach better results and accuracy, the additional image dataset was needed. For this purpose, we selected “Nordland Line” train video footage. The details and samples of both datasets are provided below.

Dataset №1. Annotated photos from 101 webcams with outdoor scenes.

• Filtered: picked ones that have “most summer” and “most winter” as pairs (Pandas)

3000 image pairs of 2 seasons / 640×480 scaled to 256 x 256.

Dataset №2. Four 10-hour Full HD videos of footage recorded from the train during “Nordland Line” trip in Norway in all four seasons.

• Cut into frames (FFmpeg)
• Auto align best nearby frames (Python + Hugin)

9000 image pairs of 2 seasons / 1000×1000, scaled to 256×256.

## Image-to-image translation results

Our engineers have adopted the model to satisfy their requirements and share their best results with you.

 Input Output Ground truth

Training set: 11.500 image pairs, testing set: ~600 image pairs.Here are the best setup details:

• 286×286 -> 256×256 jitter, horizontal mirroring
• Conditional D model
• PatchGAN.

### Variations

We would also like to share some samples of variations that happened during the image-to-image translation process. The most typical were the following:

• Dataset manipulations and mixing
• Jittering, random mirroring, amount of epochs
• Unconditional/conditional D model
• PatchGAN/PixelGAN/ImageGAN
 Input No jitter: Same detailed patterns everywhere Jitter 900×900 -> 256×256: Blurred

 Input Too much dataset №1: Mixed illumination, artifacts Too much dataset №2: railway everywhere!
 Input ImageGAN: a bit distorted PixelGan: Very blurry No L1 term: Loss of low-level features

Technical Information

Hardware:

• AWS p2.xlarge (NVIDIA GK210 GPU)
12Gb GPU memory. CUDA.

Software:

• pix2pix – Lua/Torch implementation of cGAN.
• Hugin – photo-aligning tool
• Python, pandas, numpy.

To get an objective assessment of the output pictures quality, we need a few people as independent experts to compare 2 images and indicate which of them is a real photo, one of the images will be a real photo and another one just a generated picture. Would you like to take part in the experiment? Get in touch with us!

Tools & Technologies: Deep learning, Convolutional neural networks, adversarial networks, Computer vision, lua, torch, OpenCV, Linux, git.

$${}$$