[ocl] Revised Validity Analysis submission using CEUR 1 col
diff --git a/ocl/docs/publications/OCL2021Validity/.gitignore b/ocl/docs/publications/OCL2021Validity/.gitignore
new file mode 100644
index 0000000..7c7fc53
--- /dev/null
+++ b/ocl/docs/publications/OCL2021Validity/.gitignore
@@ -0,0 +1,7 @@
+/OCLValidity.aux
+/OCLValidity.log
+/OCLValidity.synctex.gz
+/OCLValidity.abs
+/OCLValidity.out
+/OCLValidity.xmpdata
+/pdfa.xmpi
diff --git a/ocl/docs/publications/OCL2021Validity/FixedExample.oclas b/ocl/docs/publications/OCL2021Validity/FixedExample.oclas
new file mode 100644
index 0000000..05e0dd1
--- /dev/null
+++ b/ocl/docs/publications/OCL2021Validity/FixedExample.oclas
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pivot:Model [
+<!ENTITY _0 "http://www.eclipse.org/ocl/2015/Library.oclas">
+]>
+<pivot:Model xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pivot="http://www.eclipse.org/ocl/2015/Pivot"
+    xsi:schemaLocation="http://www.eclipse.org/ocl/2015/Pivot java://org.eclipse.ocl.pivot.PivotPackage" xmi:id="AAAAA" name="FixedExample.oclinecore" externalURI="platform:/resource/mdt/ocl/docs/publications/OCL2021Validity/FixedExample.oclinecore">
+  <ownedPackages xmi:id="kLyA6" name="example">
+    <ownedClasses xmi:id="POGZV" name="FixedExample" superClasses="&_0;#zfDWR">
+      <ownedInvariants xmi:id="h3WD0" name="PositiveCount">
+        <ownedSpecification xsi:type="pivot:ExpressionInOCL" isRequired="false" type="pivot:PrimitiveType &_0;#XEMMs" body="count &lt;> null implies count > 0">
+          <ownedBody xsi:type="pivot:OperationCallExp" name="implies" isRequired="false" type="pivot:PrimitiveType &_0;#XEMMs" referredOperation="&_0;#cIALH">
+            <ownedSource xsi:type="pivot:OperationCallExp" name="&lt;>" type="pivot:PrimitiveType &_0;#XEMMs" referredOperation="&_0;#ZmEtV">
+              <ownedSource xsi:type="pivot:PropertyCallExp" name="count" isRequired="false" type="pivot:PrimitiveType &_0;#tYtCd" referredProperty="#6rL7D">
+                <ownedSource xsi:type="pivot:VariableExp" name="self" type="#POGZV" isImplicit="true" referredVariable="#Z3Uo4"/>
+              </ownedSource>
+              <ownedArguments xsi:type="pivot:NullLiteralExp" isRequired="false" type="pivot:VoidType &_0;#7u3MH"/>
+            </ownedSource>
+            <ownedArguments xsi:type="pivot:OperationCallExp" name=">" type="pivot:PrimitiveType &_0;#XEMMs" referredOperation="&_0;#5+qvY">
+              <ownedSource xsi:type="pivot:PropertyCallExp" name="count" isRequired="false" type="pivot:PrimitiveType &_0;#tYtCd" referredProperty="#6rL7D">
+                <ownedSource xsi:type="pivot:VariableExp" name="self" type="#POGZV" isImplicit="true" referredVariable="#Z3Uo4"/>
+              </ownedSource>
+              <ownedArguments xsi:type="pivot:IntegerLiteralExp" type="pivot:PrimitiveType &_0;#tYtCd" integerSymbol="0"/>
+            </ownedArguments>
+          </ownedBody>
+          <ownedContext xsi:type="pivot:ParameterVariable" xmi:id="Z3Uo4" name="self" type="#POGZV"/>
+        </ownedSpecification>
+      </ownedInvariants>
+      <ownedProperties xmi:id="6rL7D" name="count" isRequired="false" type="pivot:PrimitiveType &_0;#tYtCd"/>
+    </ownedClasses>
+  </ownedPackages>
+</pivot:Model>
diff --git a/ocl/docs/publications/OCL2021Validity/NaiveExample.oclinecore b/ocl/docs/publications/OCL2021Validity/NaiveExample.oclinecore
new file mode 100644
index 0000000..f9ce30e
--- /dev/null
+++ b/ocl/docs/publications/OCL2021Validity/NaiveExample.oclinecore
@@ -0,0 +1,10 @@
+
+
+package example {
+	class NaiveExample {
+		invariant PositiveCount: count > 0;
+		attribute count : Integer;
+	}
+}
+
+
diff --git a/ocl/docs/publications/OCL2021Validity/NaiveExample.png b/ocl/docs/publications/OCL2021Validity/NaiveExample.png
index 73d664c..d249c46 100644
--- a/ocl/docs/publications/OCL2021Validity/NaiveExample.png
+++ b/ocl/docs/publications/OCL2021Validity/NaiveExample.png
Binary files differ
diff --git a/ocl/docs/publications/OCL2021Validity/NaiveExampleWithHovertext.png b/ocl/docs/publications/OCL2021Validity/NaiveExampleWithHovertext.png
deleted file mode 100644
index e657d22..0000000
--- a/ocl/docs/publications/OCL2021Validity/NaiveExampleWithHovertext.png
+++ /dev/null
Binary files differ
diff --git a/ocl/docs/publications/OCL2021Validity/OCLValidity.pdf b/ocl/docs/publications/OCL2021Validity/OCLValidity.pdf
index 2423f75..5fa2f49 100644
--- a/ocl/docs/publications/OCL2021Validity/OCLValidity.pdf
+++ b/ocl/docs/publications/OCL2021Validity/OCLValidity.pdf
Binary files differ
diff --git a/ocl/docs/publications/OCL2021Validity/OCLValidity.tex b/ocl/docs/publications/OCL2021Validity/OCLValidity.tex
index 153d573..f52c1c6 100644
--- a/ocl/docs/publications/OCL2021Validity/OCLValidity.tex
+++ b/ocl/docs/publications/OCL2021Validity/OCLValidity.tex
@@ -1,73 +1,93 @@
-% This is LLNCS.DEM the demonstration file of
-% the LaTeX macro package from Springer-Verlag
-% for Lecture Notes in Computer Science,
-% version 2.4 for LaTeX2e as of 16. April 2010
-%
-\documentclass{llncs}
+% !TeX document-id = {04156f11-6e1c-4c0d-8b85-6e701dbcf684}
+%% The first command in your LaTeX source must be the \documentclass command.
+%%
+%% Options:
+%% twocolumn : Two column layout.
+%% hf: enable header and footer.
+\documentclass[
+% twocolumn,
+% hf,
+]{ceurart}
 %
 \usepackage{makeidx}  % allows for indexgeneration
-\usepackage[pdftex]{graphicx}
+%\usepackage[pdftex]{graphicx}
 \usepackage[T1]{fontenc}
 \usepackage[utf8]{inputenc}
 \usepackage{upquote}
 %
 \begin{document}
-%
-\mainmatter              % start of the contributions
-%
-\title{A Validity Analysis to Reify 2-valued Boolean Constraints\thanks{%
-      Copyright \copyright 2021 for this paper by its authors.
-      Use permitted under Creative Commons License Attribution
-      4.0 International (CC BY 4.0).}}
-%
-\titlerunning{Validity Analysis}  % abbreviated title (for running head)
-%                                     also used for the TOC unless
-%                                     \toctitle is used
-%
-\author{Edward D. Willink}
-%
-\authorrunning{Edward Willink} % abbreviated author list (for running head)
-%
-%%%% list of authors for the TOC (use if author list has to be modified)
-\tocauthor{Edward Willink}
-%
-\institute{Willink Transformations Ltd, Reading, England,\\
-\email{ed\_at\_willink.me.uk}}
 
+%%
+%% Rights management information.
+%% CC-BY is default license.
+\copyrightyear{2021}
+\copyrightclause{Copyright for this paper by its authors.
+	Use permitted under Creative Commons License Attribution 4.0
+	International (CC BY 4.0).}
 
-\maketitle              % typeset the title of the contribution
+%%
+%% This command is for the conference information
+\conference{OCL 2021: 20th International Workshop on OCL and Textual Modeling, June, 2021, Bergen, Norway}
 
+%%
+%% The "title" command
+\title{A Validity Analysis to Reify 2-valued Boolean Constraints}
+
+%%
+%% The "author" command and its associated commands are used to define
+%% the authors and their affiliations.
+\author[1]{Edward D. Willink}[%
+email=ed at willink.me.uk,
+]
+\address[1]{Willink Transformations Ltd, Reading, England}
+
+%%
+%% The abstract is a short summary of the work to be presented in the
+%% article.
 \begin{abstract}
 As an executable specification language, OCL enables metamodel constraints that cannot be sensibly expressed graphically to be resolved textually. However many users have expressed disquiet that although a constraint is obviously either satisfied or not, the OCL formulation is not 2-valued. We argue that this disquiet is the consequence of a misunderstanding emanating from the failure of the OCL specification to address crashing. We introduce an analysis that identifies potentially invalid computations and so guarantees that Constraints are 2-valued and that OCL-based Model Transformations do not malfunction.
-
-\keywords{Program Validation, Model Transformation, OCL, Crash}
 \end{abstract}
-%
+
+%%
+%% Keywords. The author(s) should pick words that accurately describe
+%% the work being presented. Separate the keywords with commas.
+\begin{keywords}
+  Program Validation \sep
+Model Transformation \sep
+OCL \sep
+Crash
+\end{keywords}
+
+%%
+%% This command processes the author and affiliation and title
+%% information and builds the first part of the formatted document.
+\maketitle
+
 \section{Introduction}
 %
 OCL \cite{OCL-2.4} evolved from Syntropy to satisfy the need to elaborate UML \cite{UML-2.5} diagrams with constraint details that could not sensibly be expressed graphically. Within the context of a UML model, OCL specifies what happens within a domain-specific Utopia where nothing bad happens, not even when the user models real problems.
 
-OCL is a specification language that is also executable and so the OCL specification makes some concessions to realizability by prohibiting infinite collections such as \verb|Integer.allInstances()| and tolerating indeterminacy for operations such as \verb|Set::asOrderedSet()|. However there is no concession to 32 bit integers or floating point precision. These details pale in comparison to the major oversight of what happens when things go wrong.
+OCL is a specification language that is also executable and so the OCL specification makes concessions to realizability by prohibiting infinite collections such as \verb|Integer.allInstances()| and tolerating indeterminacy for operations such as \verb|Set::asOrderedSet()|. However there is no concession to 32 bit integers or floating point precision. These details pale in comparison to the major oversight of what happens when things go wrong.
 
 In this paper we review the ways in  which OCL can go wrong and introduce a validity analysis so that we can guarantee that OCL will always crash desirably and never crash undesirably.
 
 We use the emotive term crash for the problem since all programmers understand what a crash is. It avoids any confusion with solutions where terms such as invalid/exception/error/failure are used.
 
-In Section~\ref{Crashes} we review the ways in which OCL can crash so that in Section~\ref{Goal} we outline what we need to achieve and in what respects the OCL specification needs to be tweaked. Section~\ref{Running Example} presents a running example to show how even the simplest of invariants may be unsafe. In Section~\ref{Program Analysis} we introduce the analysis and symbolic evaluation that diagnoses all crash hazards and in Section~\ref{Corollaries} we identify opportunities for better practice that exploits the validity analysis. In Section~\ref{Current Status and Further Work} we describe how far the implementation wok has progressed.  Finally in Section~\ref{Related Work} we review the related work and conclude in Section~\ref{Conclusions}.
+In Section~\ref{Crashes} we review the ways in which OCL can crash so that in Section~\ref{Goal} we outline what we need to achieve and in what respects the OCL specification needs to be tweaked. Section~\ref{Running Example} presents a running example to show how even the simplest of invariants may be unsafe. In Section~\ref{Program Analysis} we introduce the analysis and symbolic evaluation that diagnoses all crash hazards and in Section~\ref{Corollaries} we identify opportunities for better practice that exploits the validity analysis. In Section~\ref{Current Status and Further Work} we describe how far the implementation work has progressed.  Finally in Section~\ref{Related Work} we review the related work and conclude in Section~\ref{Conclusions}.
 
 \section{Crashes}\label{Crashes}
 
-Programmers in all languages are resigned to the need to debug their programs to fix bugs and to handle exceptions where problems are unavoidable. OCL has no exception capability. Rather than throwing an exception at an out-of-band `return', OCL returns the \verb|invalid| singleton as an in-band result. In principle, these two mechanisms are equivalent, particularly if a practical OCL implementation supports a richer \verb|invalid| that includes details of the problem while continuing to behave as a singleton.
+Programmers in most languages are resigned to the need to debug their programs to fix bugs and to handle exceptions where problems are unavoidable. OCL has no exception capability. Rather than throwing an exception as an out-of-band `return', OCL returns the \verb|invalid| singleton value as an in-band result. In principle, these two mechanisms are equivalent, particularly if a practical OCL implementation supports a richer \verb|invalid| that includes details of the problem while continuing to behave as a singleton.
 
-Many OCL programmers are unhappy that the in-band return of \verb|invalid| means that an OCL Constraint is not 2-valued despite being a self-evident arbiter of whether some condition is satisfied or not. This unhappiness is actually a misunderstanding since any non-trivial constraint expressed in almost any language has three possible outcomes; satisfied, not-satisfied and crash. The misunderstanding arises because, when the crash uses an exception mechanism, the crash outcome bypasses the invocation code, which perceives only two outcomes. In contrast, the OCL programmer must ensure that the invocation propagates the \verb|invalid| back to the invocation's caller. The misunderstanding is therefore an ergonomic issue whereby the API provided by the OCL evaluator fails to meet the expectations of the user and fails to alert the programmer to the simple solution of converting an OCL \verb|invalid| result into an exception to propagate the crash.
+Many OCL programmers are unhappy that the in-band return of \verb|invalid| means that an OCL Constraint is not 2-valued despite being a self-evident arbiter of whether some condition is satisfied or not. This unhappiness is actually a misunderstanding \cite{OCLreflections} since any non-trivial constraint expressed in almost any language has three possible outcomes; satisfied, not-satisfied and crash. The misunderstanding arises because, when the crash uses an exception mechanism, the crash outcome bypasses the invocation code, which perceives only two outcomes. In contrast, the OCL programmer must ensure that the invocation propagates the \verb|invalid| back to the invocation's caller. The misunderstanding is therefore an ergonomic issue whereby the API provided by the OCL evaluator fails to meet the expectations of the user and fails to alert the programmer to the simple solution of converting an OCL \verb|invalid| result into an exception to propagate the crash.
 
 It would clearly be better if programs do not crash, but before we look at reasons for OCL to crash, we will look at mechanisms that avoid some crashes.
 
 \subsection{Crash Avoidance}
 
-\subsubsection{Well Formedness Rules} OCL expression terms such as \emph{PropertyCallExp} navigate a model in accordance with its metamodel, which provides a strong type system with which the OCL expressions must comply. Compliance is defined by the Well Formedness Rules that can check that for instance the type of the \emph{ownedSource} of a \emph{PropertyCallExp} conforms to \emph{owningClass} of its \emph{referredProperty}.
+\subsubsection{Well Formedness Rules} OCL expression terms such as \emph{PropertyCallExp} navigate a model in accordance with its metamodel, which provides a strong type system with which the OCL expressions must comply. Compliance is defined by the Well Formedness Rules that can check that for instance the type of the \emph{ownedSource} of a \emph{PropertyCallExp} conforms to the \emph{owningClass} of its \emph{referredProperty}.
 
-An OCL validator should check all the WFRs, preferably at edit time, but at least before execution since execution is likely to fail miserably if a WFR is violated. We may therefore assume that no crash occurs as a consequence of a WFR violation.
+An OCL validator should check all the WFRs, preferably at edit time, but at least before execution, since execution is likely to fail miserably if a WFR is violated. We may therefore assume that no crash occurs as a consequence of a WFR violation.
 
 \subsubsection{Guards}\label{Guards} Where a programmer is aware that a crash may occur, the programmer may guard against it. A substantive guard may use an \verb|if then else endif| to provide alternative functionality, or a more localized guard may use a logical operator.
 
@@ -77,24 +97,24 @@
 
 The Java above uses the short-circuit \verb&||& operator to prevent a \emph{NullPointerException} when \verb|doSomething()| is invoked when \verb|var| is \verb|null|.
 
-As we shall see the equivalent OCL operator is not short-circuit. Rather than preventing a crash, it can allow a crash to happen and then require the crash to be uncrashed.
+As we shall see, the equivalent OCL operator is not short-circuit. Rather than preventing a crash, it can allow a crash to happen and then require the crash to be uncrashed.
 
 \subsection{Catastrophic / Desirable Crashes}
 
-Problems such as Power Failure, Stack Overflow or Memory Allocation Failure can occur almost at any time and there is nothing that a normal OCL program can do about them.
+Problems such as Power Failure, Stack Overflow or Memory Allocation Failure can occur at almost any time and there is nothing that a normal OCL program can do about them.
 
-Problems such File Access, Network or Database failure may occur when a \verb|NavigationCallExp| requires an additional model element to be available. Again there is very little that a normal OCL program can do about them.
+Problems such File Access, Network or Database failure may occur when a \emph{NavigationCallExp} requires an additional model element to be available. Again there is very little that a normal OCL program can do about them.
 
-These problems are pretty catastrophic and so we categorize the consequent crashes as desirable since the most sensible response is to diagnose the problem as helpfully as possible in the hope that the user may understand and resolve the issue.
+These problems are pretty catastrophic. We categorize the consequent crashes as desirable since the most sensible response is to diagnose the problem as helpfully as possible in the hope that the user may understand and resolve the issue.
 
 
 
 
 %An OCL execution results from the collaboration of the execution of each OCL Abstract Syntax Tree element. We must therefore examine each AST element for crash hazards, very few of which are mentioned in the OCL specification.
 
-%Purely declarative elements such as \verb|IntegerLiteralExp| or \verb|Property| or \verb|Variable| involve no execution, however depending on implementation subtleties, it may be while preparing to support the declaration that a generally catastrophic Power Failure, Stack Overflow or Memory Allocation Failure occurs.
+%Purely declarative elements such as \emph{IntegerLiteralExp| or \emph{Property| or \emph{Variable| involve no execution, however depending on implementation subtleties, it may be while preparing to support the declaration that a generally catastrophic Power Failure, Stack Overflow or Memory Allocation Failure occurs.
 
-%Simple execution elements such \verb|IfExp| or \verb|LetExp| or \verb|VariableExp| use only facilities that are likely to be in registers or on the stack and so are again only subject to catastrophic failures.
+%Simple execution elements such \emph{IfExp| or \emph{LetExp| or \emph{VariableExp| use only facilities that are likely to be in registers or on the stack and so are again only subject to catastrophic failures.
 
 %An \verb|IteratorExp| or \verb|OperationCallExp| is much more vulnerable to a Stack Overflow from an imprudent recursion or to a type failure for an unsuitable source or argument input. 
 
@@ -109,18 +129,18 @@
 
 \subsection{Careless / Undesirable Crashes}
 
-OCL supports a \verb|null| value to reify the content of slots with optional multiplicities and a \verb|invalid| value to reify the consequence of an evaluation failure. These values are not suitable for computation and so OCL defines a strict semantics whereby their usage by \verb|IteratorExp| or \verb|OperationCallExp| or \verb|NavigationCallExp| is a failure that results in an \verb|invalid| value result.
+OCL supports a \verb|null| value to reify the content of slots with optional multiplicities and an \verb|invalid| value to reify the consequence of an evaluation failure. These values are not suitable for computation and so OCL defines a strict semantics whereby usage in \emph{IteratorExp}, \emph{OperationCallExp} or \emph{NavigationCallExp} is a failure that results in an \verb|invalid| value result.
 The loose wording in the specification could be formalized by preconditions for the evaluation counterpart of the expression.
 
 \begin{verbatim}
-	context NavigationCallExpEval
-	pre ValidSource: not source.oclIsInvalid();
-	pre NonNullSource: not source.oclIsUndefined();
+    context NavigationCallExpEval
+    pre ValidSource: not source.oclIsInvalid();
+    pre NonNullSource: not source.oclIsUndefined();
 \end{verbatim}
 
 Failure of a precondition is a consequence of careless programming, we therefore categorize it as an undesirable crash. The programmer needs assistance to ensure that such crashes never occur.
 
-The strict execution semantics of the OCL AST elements provides a simple crash-and-stay-crashed behavior. The OCL Standard Library defines
+The strict execution semantics of the OCL Abstract Syntax Tree elements provides a simple crash-and-stay-crashed behavior. The OCL Standard Library defines
 
 \begin{itemize}
 	\item regular operations with preconditions
@@ -134,15 +154,15 @@
 
 \subsubsection{Divide-by-Zero}
 
-The problem of divide by zero exists in many languages, but is relatively rare in practice and often easily avoided. OCL is little used for arithmetic, so the problem hardly exists in practical OCL, but it would nonetheless be nice to avoid the crash.
+The problem of divide-by-zero exists in many languages, but is relatively rare in practice and often easily avoided. OCL is little used for arithmetic, so the problem hardly exists in practical OCL, but it would nonetheless be nice to avoid the crash.
 
 \subsubsection{Index-out-of-bounds}
 
-The \verb|OrderedSet| and \verb|Sequence| collection types support indexing in much the same way as \verb|Array| and \verb|List| in other languages. A crash occurs when an unsuitable index access is used. This problem occurs more often than might be expected since many users accidentally use the 0-based index typical of an execution language, rather than the 1-based index of a specification language.
+The \verb|OrderedSet| and \verb|Sequence| collection types support indexing in much the same way as \verb|Array| and \verb|List| in other languages. A crash occurs when an unsuitable index access is used. This problem occurs more often than might be expected since many users accidentally use the 0-based index typical of an execution language, rather than the 1-based index of a specification.
 
 \subsubsection{Missing Content}
 
-The collection types support reverse indexing using the \verb|indexOf| operation or the \verb|any| iteration and crash when the indexing misses. The crash from \verb|indexOf| is excessive since a \verb|null| or negative return could signal the query miss. It is unreasonable to expect every use of \verb|indexOf| to be guarded by an \verb|includes|.
+The collection types support reverse indexing using the \verb|indexOf| operation or the \verb|any| iteration and crash when the indexing misses. The crash from \verb|indexOf| is excessive since a \verb|null| or negative return could signal the query miss less forcefully. It is unreasonable to expect every use of \verb|indexOf| to be guarded by an \verb|includes|.
 
 \subsubsection{Bad String Content}
 
@@ -157,22 +177,22 @@
 In many languages a crash is propagated by throwing an exception and subsequently catching it. In OCL, the crash is propagated as the \verb|invalid| value and may be `caught' by the \verb|OCLAny::oclIsInvalid()| operation.
 
 \begin{verbatim}
-	let result : OclAny = functionThatMayCrash() in
-	if result.oclIsInvalid() then fixupCrash() else result endif
+    let result : OclAny = functionThatMayCrash() in
+    if result.oclIsInvalid() then fixupCrash() else result endif
 \end{verbatim}
 
-Accommodating \verb|OCLAny::oclIsInvalid()| is inconvenient when realizing OCL by translation to a conventional language, since all usages of the conventional exception passing must be converted back to values wherever \verb|oclIsInvalid()| might be invoked.
+Accommodating \verb|OCLAny::oclIsInvalid()| is inconvenient when realizing OCL by translation to a conventional language, since all usages of the conventional exception passing must convert to values wherever \verb|oclIsInvalid()| might be invoked.
 
 Ideally the usage of \verb|oclIsInvalid()| would be limited to not-invalid preconditions and Operating System level OCL that really wants to catch a catastrophic failure to produce a friendly diagnostic or to perhaps retry on another computer.
 
 \subsubsection{Reverting}
 
-The avoidance of crashes by short-circuit operators in conventional languages was described in Section~\ref{Guards}. Unfortunately the equivalent logical operators in OCL were  specified to be commutative. The incompatibility between commutativity and short-circuiting was `resolved' by making the logical operators not-strict to allow them to handle \verb|null| or \verb|invalid|. The commutativity is mathematically elegant but the consequent 4-valued {\verb|true|, \verb|false|, \verb|null|, \verb|invalid|} Boolean is unpopular with users and has bad implementation consequences.
+The avoidance of crashes by short-circuit operators in conventional languages was described in Section~\ref{Guards}. Unfortunately the equivalent logical operators in OCL were  specified to be commutative. The incompatibility between commutativity and short-circuiting was `resolved' by making the logical operators not-strict to allow them to handle \verb|null| or \verb|invalid|. The commutativity is mathematically elegant but the consequent 4-valued \{\verb|true|, \verb|false|, \verb|null|, \verb|invalid|\} Boolean is unpopular with users and has bad implementation consequences.
 
 The conventional short-circuit suppresses the unwanted evaluation of the second term.
 
 \begin{verbatim}
-	(var != null) || var.doSomething()		// C or Java
+    (var != null) || var.doSomething()		// C or Java
 \end{verbatim}
 
 The hazardous second term is not evaluated; no crash occurs.
@@ -180,14 +200,14 @@
 The OCL short-circuit is
 
 \begin{verbatim}
-	(var <> null) or var.doSomething()
+    (var <> null) or var.doSomething()
 \end{verbatim}
 
-Since the operator is commutative an implementation has a free choice of the evaluation order, and may even use different processors to evaluate the two arguments concurrently. For less obvious OCL expressions, it may be unclear to user or tooling what the best evaluation order is. An implementation cannot in general avoid evaluating the `wrong' argument first before evaluation of the `right' argument provides the guard value that requires the implementation to discard the `erroneous' crash.
+Since the operator is commutative an implementation has a free choice of the evaluation order, and may even use different processors to evaluate the two arguments concurrently. For less obvious OCL expressions, it may be unclear to user or tooling what the best evaluation order is. An implementation cannot in general avoid evaluating the `wrong' argument first before evaluation of the `right' argument provides the guard value and so requires the implementation to discard the `erroneous' crash.
 
 Even if the implementation foregoes the concurrency opportunity and evaluates first argument first, the commutativity allows a programmer to accidentally specify the guard second, so the implementation must still support the uncrash. Of course no sensible programmer will program the guard term second so the implementation is just being forced to implement something that should never happen.
 
-Except that it does. During development, it is not uncommon for the system or at least the OCL exposition to be defective. A user who has set a breakpoint in code associated with a crash may find the debugger stopping at the crash and be confused when that crash fails to propagate as expected. The problem is that  the crash during the first term evaluation may be inhibited by a malfunction in the second input evaluation. The overall execution may be pedantically correct, but at best CPU time has been wasted by crashing. More likely the developer spends significant time understanding the strange behavior possibly concluding that OCL execution is unreliable.
+Except that it does. During development, it is not uncommon for the system or at least the OCL exposition to be defective. A user who has set a breakpoint in code associated with a crash may find the debugger stopping at the crash and be confused when that crash fails to propagate as expected. The problem is that  the crash during the first term evaluation may be inhibited by a malfunction in the second input evaluation. The overall execution may be pedantically correct, but at best CPU time has been wasted by crashing. More likely the developer spends significant time understanding the strange behavior possibly concluding, with some justification, that OCL execution is unreliable.
 %Again, many languages support prevention of a crash by guarding the hazardous invocation. In OCL this idiom is supported by the logical operators.
 
 %\begin{verbatim}
@@ -196,7 +216,7 @@
 
 %The extra \verb|functionWillNotCrash()| functionality predicts the hazard and returns \verb|false| when execution of \verb|functionThatMayCrash()| must be prevented.
 
-Unfortunately the commutative not-strict logical operator functionalities break the simple crash-and-stay-crashed behaviour.
+Unfortunately the commutative not-strict logical operators break the simple crash-and-stay-crashed behavior.
 
 %The violation of strictness by the logical operations causes significant implementation difficulties and, as we shall see, causes significant user difficulties as well. In conventional languages the guard idiom is supported by what is commonly referred to as short-circuit semantics so that after evaluation of just the first logical operator input the input value is examined to determine whether the second logical operator input is also evaluated. The first input guards and so inhibits a redundant and potentially very awkward second input evaluation. Operators such as \verb|&&| and \verb&||& are therefore not commutative.
 
@@ -226,15 +246,15 @@
 
 Many model transformation tools provide a disciplined framework to create or mutate an output model using immutable OCL queries on the input model. OCL crashes pose a difficult problem.
 
-Some transformation languages such as QVTo \cite{QVT-1.3} provide a relatively conventional exception mechanism allowing the users to handle OCL's \verb|invalid| as an exception. This is perhaps the worst of both worlds.
+Some transformation languages such as QVTo \cite{QVT-1.3} provide a relatively conventional exception mechanism allowing the users to handle OCL's \verb|invalid| as an exception. %This is perhaps the worst of both worlds.
 
-For declarative transformations, functionality is modularized by rules within which OCL specifies the matches and conversions. Execution is determined by the successful rule matches, so potentially an OCL crash just loses a rule match and the user is disappointed that some conversion did not happen. This is dishonest. Any crash is a transformation execution failure and any subsequent result is suspect compromise. A declarative model transformation must crash enthusiastically.
+For declarative transformations, functionality is modularized by rules within which OCL specifies the matches and conversions. Execution is determined by the successful rule matches, so potentially an OCL crash just loses a rule match and the user is disappointed that some conversion did not happen. This is dishonest. Any crash is a transformation execution failure and any subsequent result is a suspect compromise. A declarative model transformation must crash enthusiastically.
 
-When interpreting or generating code for a model transformation, the implementation must faithfully realize all possible OCL failures so that no crash is hidden. This requires considerable effort to support a behaviour whose result is going to be thrown away. Much better to alert the programmer to all the undesirable crashes so that only desirable crashes remain allowing for a much simpler execution in which any crash is fatal crash.
+When interpreting or generating code for a model transformation, the implementation must faithfully realize all possible OCL failures so that no crash is hidden. This requires considerable effort to support a behavior whose result is going to be thrown away. Much better to alert the programmer to all the undesirable crashes so that only desirable crashes remain allowing for a much simpler execution in which any crash is a fatal crash.
  
-\subsection{Transitive}
+%\subsection{Transitive}
  
-Operations such as  \verb|Sequence::first()| can crash since they are just a convenience wrapper for \verb|Sequence::at(1)|. Similarly iterations such as \verb|exists| and \verb|forAll| can crash as a consequence of their iteration over the logical \verb|or| / \verb|and| operations. An implementation iterating over the non-strict logical operations must be prepared to crash many times before encountering a guard that inhibits the many crashes.
+%Operations such as  \verb|Sequence::first()| can crash since they are just a convenience wrapper for \verb|Sequence::at(1)|. Similarly iterations such as \verb|exists| and \verb|forAll| can crash as a consequence of their iteration over the logical \verb|or| / \verb|and| operations. An implementation iterating over the non-strict logical operations must be prepared to crash many times before encountering a guard that inhibits the many crashes.
  
 \section{Goal}\label{Goal}
 
@@ -244,9 +264,7 @@
 	\item careless/undesirable crashes never occur
 \end{itemize}
 
-This is fully in accord with the OCL's strict behaviour provided preconditions are always satisfied.
-
-We need a validity analysis that can guarantee that preconditions are always satisfied.
+This is fully in accord with OCL's strict behavior provided preconditions are always satisfied. We need a validity analysis that can guarantee this proviso.
 
 The not-strict commutative specification of the logical operators conflicts with both our goals. A catastrophic crash can be guarded and so not crash. A careless crash may occur before it is guarded and uncrashed.
 
@@ -268,7 +286,7 @@
 
 %For an undesirable crash, the short circuit functionality can prevent the undesirable crash of the second argument. We just require to guarantee that the first argument cannot crash undesirably.
 
-Taking \verb|and| as an example we are changing the result of Table A.2 of the OCL specification from:
+Taking the \verb|and| operation as an example, we are changing the result of Table A.2 of the OCL specification from:
 
 \begin{center}
 	\begin{tabular}{|c||c|c||c||c|}
@@ -276,18 +294,18 @@
 		Use Case & Input 1 & Input 2 & Output \\
 		\hline
 		\hline
-		2-valued & false & false & false \\
-		& false & true & false \\
+		2-valued & true & true & true \\
 		& true & false & false \\
-		& true & true & true \\
+		& false & true & false \\
+		& false & false & false \\
 		\hline
 		Normal Short-Circuit & false & $\epsilon$ & false \\
 		& false & $\bot$ & false \\
 		Commutated Short-Circuit & $\epsilon$ & false & false \\
 		& $\bot$ & false & false \\
 		\hline
-		Residue & true & $\epsilon$ & $\epsilon$ \\
-		 & true & $\bot$ & $\bot$ \\
+		Crash & true & $\epsilon$ & $\epsilon$ \\
+		& true & $\bot$ & $\bot$ \\
 		& $\epsilon$ & true & $\epsilon$ \\
 		& $\bot$ & true & $\bot$ \\
 		& $\epsilon$ & $\epsilon$ & $\epsilon$ \\
@@ -306,12 +324,12 @@
 		Use Case & Input 1 & Input 2 & Revised Output \\
 		\hline
 		\hline
-		Normal Short-Circuit, & false &  & false \\
-		2-valued & true & false & false \\
-		& true & true & true \\
+		2-valued, & true & true & true \\
+		& true & false & false \\
+		Normal Short-Circuit & false &  & false \\
 		\hline
-		Crash, & true & $\epsilon$ & $\bot$ \\
-		Commutated Short-Circuit  & true & $\bot$ & $\bot$ \\
+		Crash & true & $\epsilon$ & $\bot$ \\
+		& true & $\bot$ & $\bot$ \\
 		& $\epsilon$ & & $\bot$ \\
 		& $\bot$ & & $\bot$ \\
 		\hline
@@ -322,18 +340,16 @@
 
 % compute the second ar. The functionality with a $\epsilon$(\verb|null|) or $\bot$(\verb|invalid|) as the first input is detected by the analysis and requires a bug fix or refactoring by the programmer. 
 
-The subtle change that all crashes return $\bot$ rather than sometimes $\epsilon$ is a reversion from the idempotence introduced in OCL 2.4 back to OCL 2.3.
+The subtle change that all crashes return $\bot$ (\verb|invalid|) rather than sometimes $\epsilon$ (\verb|null|) is a reversion from the idempotence introduced in OCL 2.4 back to OCL 2.3.
 
-The significant change is that the Commutated Short Circuit functionality now crashes on the first argument without giving the second argument a chance to discard a crash, The analysis must identify this usage to avoid breaking constraints.
+The significant change is that the Commutated Short Circuit functionality now crashes on the first argument without giving the second argument a chance to discard a crash. Our validity analysis must identify this usage to avoid breaking unwise constraints.
  
 \section{Running Example}\label{Running Example}
 
-Our running example considers the very simple class constraint shown using OCLinEcore\cite{OCLinEcore} in Fig~\ref{fig:NaiveExample}
-
 \begin{figure}
 	\vspace{-10pt}
 	\begin{center}
-		\includegraphics[width=3.0in]{NaiveExample.png}
+		\includegraphics[width=5.0in]{NaiveExample.png}
 	\end{center}
 	\vspace{-10pt}
 	\caption{Naive Example}
@@ -341,39 +357,29 @@
 	\vspace{-10pt}
 \end{figure}
 
-The \verb|NaiveExample| class contains an \verb|Integer| attribute named \verb|count| and an invariant to require a positive value.
+Our running example considers the very simple class constraint shown using OCLinEcore\cite{OCLinEcore} in Fig~\ref{fig:NaiveExample}.
+
+The \verb|NaiveExample| class contains an \emph{Integer} attribute named \verb|count| and an invariant to require a positive value.
 
 It would seem self evident that the invariant is 2-valued corresponding to satisfied/not-satisfied, but it is not. There are two crash hazards.
 
 \subsection{Hazards}
 
-If the host model is served by a cloud network or database, there is a possibility that the \emph{PropertyCallExp} access to \verb|count| may fail with some form of network error. This error is treated as \verb|invalid| by OCL and consequently the evaluation of the constraint yields an \verb|invalid| result. As noted above, this rather pedantic but catastrophic concern is resolved by a strict any crash always crashes philosophy.
+If the host model is served by a cloud network or database, there is a possibility that the \emph{PropertyCallExp} access to \verb|count| may fail with some form of network error. This error is treated as \verb|invalid| by OCL and consequently the evaluation of the constraint yields an \verb|invalid| result. As noted above, this rather pedantic but catastrophic concern is resolved by a strict any-crash-always-crashes philosophy.
 
-If, in the OCLinEcore editor, we hover over the \verb|count| declaration we may see a fuller description as shown in Fig~\ref{fig:NaiveExampleWithHovertext}
+Fig~\ref{fig:NaiveExample} also shows the OCLinEcore editor's hover text to
+reveal the underlying \emph{Property} declaration with a fully qualified name \verb|example::NaiveExample::count|, primitive type \verb|Integer| and multiplicity \verb|[?]|. The optional multiplicity allows the value of \verb|count| to be \verb|null|. In Ecore \cite{EMF}, where the emphasis is on simple default construction of Java objects, the default multiplicity lower bound for all objects is 0. Consequently this is the OCLinEcore default and so a widespread practice. In contrast for UML, the lower bound multiplicity default is unity so that a \verb|null| is only permitted after an explicit user action. Either way, a valid \emph{Property} may specify that \verb|null| is an acceptable value. The \verb|null| value violates the strict precondition of the comparison operation. It crashes the invariant and disappoints the user hoping for a 2-valued outcome.
 
-\begin{figure}
-	\vspace{-10pt}
-	\begin{center}
-		\includegraphics[width=4.5in]{NaiveExampleWithHovertext.png}
-	\end{center}
-	\vspace{-10pt}
-	\caption{Naive Example with hover text}
-	\label{fig:NaiveExampleWithHovertext}
-	\vspace{-10pt}
-\end{figure}
-
-The hover text reveals the underlying \emph{Property} declaration with a fully qualified name \verb|example::NaiveExample::count|, primitive type \verb|Integer| and multiplicity \verb|[?]|. The optional multiplicity allows the value of \verb|count| to be \verb|null|. In Ecore \cite{Ecore}, where the emphasis is on simple default construction of Java objects, the default multiplicity lower bound for all objects is 0 consequently this is the OCLinEcore default and so a widespread practice. In contrast for UML the lower bound multiplicity default is unity so that a \verb|null| is only permitted after an explicit user action. Either way, a valid \emph{Property} may specify that \verb|null| is an acceptable value. The \verb|null| value violates the strict precondition of the comparison operation. It crashes the invariant and disappoints the user hoping for a 2-valued outcome.
-
-We require our tooling to support elimination of this not-2-valued hazard by diagnosing that the required non-null/non-invalid input of the comparison operator \emph{MayBeNull}.
+We require our tooling to support elimination of this not-2-valued hazard by diagnosing that the required non-null/non-invalid input of the comparison operator is \emph{MayBeNull}.
 
 \subsection{Fixes}
 
-The user may then easily fix the problem by correcting the optional \verb|[?]| multiplicity to the non-optional \verb|[1]|. Alternatively, if a \verb|null| value is a required aspect of the design, the user may correct the invariant as shown in Fig~\ref{fig:FixedExample}.
+The user may easily fix the problem by correcting the optional \verb|[?]| multiplicity to the non-optional \verb|[1]|. Alternatively, if a \verb|null| value is a required aspect of the design, the user may correct the invariant as shown in Fig~\ref{fig:FixedExample}.
 
 \begin{figure}
 	\vspace{-10pt}
 	\begin{center}
-		\includegraphics[width=4.5in]{FixedExample.png}
+		\includegraphics[width=6.0in]{FixedExample.png}
 	\end{center}
 	\vspace{-10pt}
 	\caption{Fixed Example}
@@ -381,14 +387,14 @@
 	\vspace{-10pt}
 \end{figure}
 
-The \verb|implies| guards the comparison preventing the crash, but naively the tooling will continue to diagnose the hazard unless the tooling understands the program control flow consequences of the sequentially-strict \verb|implies| operation.
+The \verb|implies| operation guards the comparison preventing the crash, but naively the tooling will continue to diagnose the hazard unless the tooling understands the program control flow consequences of the sequentially-strict \verb|implies| operation.
 
 \section{Program Analysis}\label{Program Analysis}
 
-Our running example shows that even simple OCL code can have a problem that can be fixed. We now introduce an analysis to alert the user for the need for fixes and confirm that sufficient fixes have been applied to guarantee that no undesirable crashes occur and that all crashes always crash. We first review the conventional run-time evaluation of our example OCL expression.
+Our running example shows that even simple OCL code can have a problem that can be fixed. We now introduce an analysis to alert the user for the need for fixes and confirm that sufficient fixes have been applied to guarantee that no undesirable crashes occur and that all desirable crashes always crash. We first review the conventional run-time evaluation of our example OCL expression.
 
 \begin{verbatim}
-	self.count <> null implies self.count > 0
+    self.count <> null implies self.count > 0
 \end{verbatim}
 
 \subsection{Simple Evaluation}\label{Simple Evaluation}
@@ -414,11 +420,11 @@
 
 At run-time this constraint may be used to confirm the well-formedness of each element of a user model. Each instance of \verb|FixedExample| is bound in turn to the \verb|self| \emph{ParameterVariable} and then the \emph{ownedBody} is evaluated by bottom up tree traversal with each descendant returning a result to its ancestor.
 
-Execution therefore starts at the bottom left as a \emph{VariableExp} accesses the \verb|self| value and passes it as the \emph{ownedSource} for its parent \emph{PropertyCallExp} that accesses the \verb|count| slot and passes it as the \emph{ownedSource} of the \verb|<>|. The depth first traversal continues by providing \verb|null| as the \emph{ownedArguments} input of the \verb|<>| from the \emph{NullLiteralExp}. With both inputs computed, the \verb|<>| can pass its result to as  \emph{ownedSource} for the \verb|implies|, which once a similar traversal has computed its \emph{ownedArguments} input can return the overall result to the \emph{ExpressionInOCL}.
+Execution therefore starts at the bottom left as a \emph{VariableExp} accesses the \verb|self| value and passes its value as the \emph{ownedSource} for its parent \emph{PropertyCallExp} that accesses the \verb|count| slot and passes it as the \emph{ownedSource} of the \verb|<>|. The depth first traversal continues by providing \verb|null| as the \emph{ownedArguments} input of the \verb|<>| from the \emph{NullLiteralExp}. With both inputs computed, the \verb|<>| can pass its result to as  \emph{ownedSource} for the \verb|implies|, which once a similar traversal has computed its \emph{ownedArguments} input can return the overall result to the \emph{ExpressionInOCL}.
 
 \subsection{Precondition Evaluation}\label{Precondition Evaluation}
 
-In OCL, operations such as \verb|>| are strict requiring all inputs to be evaluated and to be non-invalid before execution. Whether operations also require non-null inputs is determined by the \verb|[?]| or \verb|[1]| multiplicity of each operation parameter. For the \verb|Integer::>(Integer)| library \emph{Operation}, the specification wording can be formalized by preconditions.
+In OCL, operations such as \verb|>| are strict requiring all inputs to be evaluated and to be non-invalid before execution. Whether operations also require non-null inputs is determined by the \verb|[?]| or \verb|[1]| multiplicity of each operation parameter. The specification wording can be formalized by preconditions.
 
 \begin{verbatim}
     operation Integer::>(arg : Integer[1]) : Boolean {
@@ -431,7 +437,7 @@
     }
 \end{verbatim}
 
-A full evaluation should validate these and other preconditions by evaluating them. Eclipse OCL\cite{Eclipse-OCL} never executes preconditions. USE \cite{USE}can do so when requested.
+A full evaluation should validate these and other preconditions by evaluating them. Eclipse OCL~\cite{Eclipse-OCL} never executes preconditions. USE~\cite{USE} can do so when requested.
 
 The conventional use of the OCL well formedness rules supports a static analysis that ensures that all input values are type compatible. Here we are concerned with a more extensive  static analysis to ensure that all preconditions are satisfied. The static analysis occurs at edit/compile-time making evaluation at run-time redundant.
 
@@ -451,21 +457,21 @@
 %    }
 %\end{verbatim}
 
-At edit/compile-time we have no instances, rather we need to prove that for all possible instances the result will be either 2-valued or a desirable crash. With our revision to strict semantics for everything except for the sequentially-strict logical operations we need to prove that no undesirable crash can occur.
+At edit/compile-time we have no actual instances, rather we need to prove that for all possible instances the result will be either 2-valued or a desirable crash. With our revision to strict semantics for everything except for the sequentially-strict logical operations we `just' need to prove that no undesirable crash can occur.
 
-For our example we have intuitively identified that \verb|self.count > 0| may crash for \verb|invalid| or \verb|null| values of \verb|count|. More rationally, \verb|self| is not \verb|invalid| and instance slots cannot contain \verb|invalid| values, so an \verb|invalid| value is only possible as a consequence of a database/network failure. This would be a desirable crash. However the instance slot can contain a \verb|null| value confirming the intuition.
-
-The \verb|self.count <> null| guard uses \verb|implies| to protect against the \verb|null| value..
+For our example, we have intuitively identified that \verb|self.count > 0| may crash for \verb|invalid| or \verb|null| values of \verb|count|. More rationally, the \verb|self| object is not \verb|invalid| and instance slots cannot contain \verb|invalid| values, so an \verb|invalid| value is only possible as a consequence of a database/network failure. This would be a desirable crash. However the instance slot can contain a \verb|null| value. The \verb|self.count <> null| guard uses \verb|implies| to protect against this \verb|null| value. Confirming this protection requires a \verb|false| value for the \verb|<>| output, enabling us to deduce that the inputs are different.
 %Since \verb|count| is accessed from an instance slot, a desirable crash may occur from a database/network failure. An undesirable crash can occur for a \verb|null| or \verb|invalid| value. Slots cannot have \verb|invalid| values so only the \verb|null| value permitted by the multiplicity lower bound needs to be eliminated. The \verb|implies| guard idiom ensures that any crash while evaluating its second argument is ignored if the first argument evaluates to \verb|false|. The guard is \verb|false| when the \verb|<>| evaluates to \verb|false| which requires the inputs to differ; \verb|x| to differ from \verb|null|.
 
-Intuitively this achieves what we want, but it has required us to deduce properties of the \verb|<>| inputs from its output. This is a reverse evaluation that requires distinct implementation programming and which scales badly since only single input monotonic operations support useful deduction of an input from a known output.
+This achieves what we want, but it has required us to deduce properties of the \verb|<>| inputs from its output. This is a reverse evaluation that requires distinct implementation programming and which scales badly since only single input monotonic operations support useful deduction of an input from a known output.
 
-We can avoid reverse flow deductions by instead hypothesizing that an undesirable crash can occur and examine a hypothesis for which forward evaluation leads to a contradiction. For our example, we consider the hypothesis
+We can avoid reverse flow deductions by instead hypothesizing that an undesirable crash can occur and demonstrate that forward evaluation leads to a contradiction. For our example, we consider the hypothesis
 
-\begin{itemize}
-	\item execution is attempted for: \verb|self.count > 0|
-	\item when: \verb|self.count <> null|
-\end{itemize}  
+\begin{center}
+	\begin{tabular}{c c}
+		when: & self.count <> null \\
+		execution is attempted for: & self.count > 0 \\
+	\end{tabular}
+\end{center}
 
 This evaluation can be performed by a symbolic evaluator that elaborates the standard evaluator to use a symbolic value wherever a constant value is not known.
 
@@ -478,19 +484,21 @@
 	\item MayBeNull : Boolean[1]
 \end{itemize}
 
-The symbolic invalidity and nullity state requires only two values since the third \emph{IsInvalid} or \emph{IsNull} state uses the non-symbolic literal values of types \emph{OclInvalid} and \emph{OclVoid} respectively.
+The symbolic nullity state requires only two \emph{MayBeNull}, \emph{MayNotBeNull} values since the third \emph{IsNull} state uses the constant literal value of type \emph{OclVoid}.
+
+The symbolic careless invalidity state requires only two \emph{MayBeInvalid}, \emph{MayNotBeInvalid} values since the third \emph{IsInvalid} state would be a deliberate and so desirable crash that bypasses our careless invalidity analysis.
 
 For our example:
 
 \begin{verbatim}
-	self.count <> null implies self.count > 0
+    self.count <> null implies self.count > 0
 \end{verbatim}
 
 The symbolic evaluation needs to confirm that no undesirable crash can occur for the \verb|>| \emph{OperationCallExp} in \verb|self.count > 0|.
 
 \subsubsection{Base Symbolic Evaluation}
 
-An overall symbolic evaluation may therefore be performed for the known symbolic value and constraints/preconditions excluding the invariant whose validity is being analyzed.
+An overall symbolic evaluation of an invariant uses the initial symbolic value.
 \begin{center}
 	\begin{tabular}{|c||c|c||c|}
 		\hline
@@ -500,6 +508,7 @@
 		\hline
 	\end{tabular}
 \end{center}
+ and all other constraints and preconditions
 \begin{center}
 	\begin{tabular}{|c|c||c|}
 		\hline
@@ -547,7 +556,7 @@
 giving the symbolic values of each AST node as
 
 \begin{center}
-	\begin{tabular}{|c||c|c||c|}
+	\begin{tabular}{|c||c|c|c|}
 		\hline
 		AST element & Value Type & MayBeInvalid & MayBeNull \\
 		\hline
@@ -558,7 +567,7 @@
 		\hline
 		null & OclVoid & false & true \\ 
 		\hline
-		self.count <> null & Boolean & true & false \\
+		self.count <> null & Boolean & false & false \\
 		\hline
 		0 & Integer & false & false \\
 		\hline
@@ -570,11 +579,9 @@
 	\end{tabular}
 \end{center}
 
-The \emph{MayBeNull} propagates as \emph{MayBeInvalid} after the comparison.
-
 Five of the six \verb|>| preconditions are satisfied by the symbolic values.
 
-The sixth, \verb|not source.oclIsUndefined()| might not be satisfied since its \verb|self.count| source \emph{MayBeNull} is \verb|true|.
+The sixth, \verb|not source.oclIsUndefined()| might not be satisfied since, for its \verb|self.count| source, \emph{MayBeNull} is \verb|true| and propagates as \emph{MayBeInvalid} after the comparison.
 
 \subsubsection{Hypothesized Symbolic Evaluation}
 
@@ -606,13 +613,13 @@
 	\end{tabular}
 \end{center}
 
-Re-evaluating the symbolic values of each AST node for the new known values and checking all constraints finds the required contradiction. verb|self.count <> null| now evaluates to \verb|false| contradicting the new precondition that the verb|self.count <> null| source is \verb|true|.
+Re-evaluating the symbolic values of each AST node for the new known values and checking all constraints finds the required contradiction. \verb|self.count <> null| now evaluates to \verb|false| contradicting the new precondition that the \verb|self.count <> null| source is \verb|true|.
 
 \subsubsection{Intuition}
  
 Our running example is very simple, closely emulating the simplest of guard idioms that most programmers have used many times. The solution is therefore pretty intuitive.
 
-Laboriously working through the example as symbolic values, constraints, hypotheses and contradictions demonstrates how the magic of intuition and reverse evaluation is replaced by predictable rigor that can scale to non-trivial problems.
+Laboriously working through the example as symbolic values, constraints, hypothesis and contradiction demonstrates how the magic of intuition and reverse evaluation is replaced by predictable rigor that can scale to non-trivial problems.
 
 Boolean Symbolic Evaluation is sufficient to cope with the complexities of unsafe usage of \verb|null| or \verb|invalid|.
 
@@ -621,9 +628,9 @@
 Although OCL is not often used for floating point calculations, OCL provides a \emph{Real} type for which division by zero has an undesirable crash hazard.
 
 \begin{verbatim}
-	operation Real::/(den : Real) : Real {
-		precondition: den <> 0;
-	}
+    operation Real::/(den : Real) : Real {
+        precondition: den <> 0;
+    }
 \end{verbatim}
 
 The edit/compile-time analysis should therefore diagnose the rare divide-by-zero hazards.
@@ -634,7 +641,7 @@
     if den <> 0 then num / den else ... endif
 \end{verbatim}
 
-detects that the divide by zero case has been avoided and that the programmer has taken responsibility for solving the problem.
+detects that the divide-by-zero case has been avoided and that the programmer has taken responsibility for solving the problem.
 
 For the general case, it is unlikely that a symbolic analysis can adequately understand non-trivial floating point operations and so the programmer will be forced to adopt the simple-case guard.
 
@@ -653,7 +660,7 @@
     }
 \end{verbatim}
 
-A \emph{SymbolicIntegerValue} needs track any knowledge regarding the \emph{Maximum} or \emph{Minimum} possible values both as absolute values or relative to the \verb|size()| of source \emph{SymbolicCollectionValue}. 
+A \emph{SymbolicIntegerValue} needs to track any knowledge regarding the \emph{Maximum} or \emph{Minimum} possible values both as absolute or relative to the \verb|size()| of a base \emph{SymbolicCollectionValue}. 
 
 \begin{itemize}
 	\item Actual Type : Type[1]
@@ -665,10 +672,10 @@
     \item MinimumBase : SymbolicCollectionValue[?]
 \end{itemize}  
 
-The symbolic evaluation of all collection operations needs to relate the output symbolic value to the input so that for e.g. \verb|Sequence::append| the minimum and maximum output size is one larger than the input size but for e.g.
-\verb|OrderedSet::append| only the maximum output size increases.
+The symbolic evaluation of all collection operations needs to relate the output symbolic value to the input so that for e.g. \verb|Sequence::append|, the minimum and maximum output size is one larger than the input size. But for e.g.
+\verb|OrderedSet::append|, only the maximum output size increases.
 
-The OCL specification provides the preconditions for many of the operations, but omits many others. Thus \verb|Sequence->first| omits an explicit \verb|size() > 0| precondition leaving the \verb|result = self->at(i)| postcondition to provide the undesirable crash from the nested precondition.
+%The OCL specification provides the preconditions for many of the operations, but omits many others. Thus \verb|Sequence->first| omits an explicit \verb|size() > 0| precondition leaving the \verb|result = self->at(i)| postcondition to provide the undesirable crash from the nested precondition.
 
 \subsection{Content Symbolic Evaluation}
 
@@ -682,30 +689,30 @@
 
 \subsection{Preconditions}
 
-Without the analysis, a precondition is an additional expression that if evaluated at run-time on actual model values may cause a crash. Since the precondition often just anticipates a crash that would occur anyway the utility of a precondition is limited to improving the diagnostic that accompanies the crash.
+Without the analysis, a precondition is an additional expression that may cause a crash if evaluated at run-time on actual model values. Since the precondition often just anticipates a crash that would occur anyway, the utility of a precondition is limited to improving the diagnostic that accompanies the crash.
 
 With the analysis, executing preconditions at run-time is redundant. The symbolic execution, at edit/compile-time, on all possible symbolic model values, guarantees that the precondition is satisfied.
 
 Preconditions become an important part of the design and are exploited and checked at edit/compile-time. A too-weak precondition will be diagnosed by a crash hazard within the operation declaring the precondition. A too-strong precondition will be diagnosed by a crash hazard when the operation declaring the precondition is invoked.
 
-Once preconditions are used, it becomes clear that the OCL specification has significant omissions.  For instance the \verb|Sequence::first()| operation requires more than just a \verb|result = self->at(1)| postcondition. There should also be an explicit rather than transitive \verb|self->notEmpty()| precondition.
+%Once preconditions are used, it becomes clear that the OCL specification has significant omissions.  For instance the \verb|Sequence::first()| operation requires more than just a \verb|result = self->at(1)| postcondition. There should also be an explicit rather than transitive \verb|self->notEmpty()| precondition.
 
 \subsection{Bodyconditions and BodyExpressions}
 
-The Object Constraint Language is actually an expression language so that the functionality of an \emph{Operation} or \emph{Property} is characterized by a bodyexpression for the respective \emph{ownedBody} or \emph{ownedDefaultValue}. UML only supports constraints and so requires the \verb|result = bodyexpression| idiom to reformulate the arbitrarily-typed bodyexpression as the Boolean-typed \emph{Constraint}. The UML exposition is indistinguishable from a postcondition.
+The Object Constraint Language is actually an expression language so that the functionality of an \emph{Operation} or \emph{Property} is characterized by a bodyexpression for the respective \emph{ownedBody} or \emph{ownedDefaultValue}. UML only supports constraints and so the \verb|result = bodyexpression| idiom reformulates the arbitrarily-typed bodyexpression as the Boolean-typed \emph{Constraint}. The UML exposition is indistinguishable from a postcondition.
 
 When specifying OCL, the use of a bodyexpression is desirable when the expression represents a sensible implementation that can be used as is.
 
 \subsection{Postconditions}
 
-For an operation such as \verb|sort()| a postcondition is appropriate to specify the generic characteristics of a bubble or quik sort without imposing any particular implementation. 
+For an operation such as \verb|sort()| a postcondition is appropriate to specify the generic characteristics of a bubble or quick sort without imposing any particular implementation. 
 
 In addition to the obvious \verb|result = ...| to specify the final result, it is also necessary to provide postconditions for each of the properties of the \emph{SymbolicCollectionValue} such as 
-\verb|result->size() = self->size() + 1| to be specified.
+\verb|result->size() = self->size() + 1|.
 
 %Similarly \verb|Sequence::including(object:T)| operation requires more than just a postcondition \verb|result = self.append(object)|. There should also be an explicit rather than transitive \verb|self->size() = self@pre->size()+1| postcondition. And once we start to rectify pre and post conditions omissions;, we notice errors in those that are present. The specified postcondition has two errors; it should be \verb|result = self@pre->append(object)| and would be simpler and more useful as a body expression \verb|self->append(object)|. Pedantically we should also provide a nothing-else-changes framing condition, but with OCL inherently immutable perhaps this can be left as read.
 
-Postconditions are never executed by Eclipse OCL. Their execution may be requested in USE. When executed at run-time, they require considerable execution for no benefit, until one fails, at which point a crash must be handled.
+Postconditions are never executed by Eclipse OCL. Their execution may be requested in USE. When executed at run-time, they require execution overheads for no benefit, until one fails, at which point a crash must be handled.
 
 Once postconditions form part of the edit/compile-time analysis many too-weak/too-strong problems may be uncovered in the same way as for preconditions. For library operations at least, a new occasional build-time test could animate each operation with a diverse suite of input values that check the postconditions. For model operations, a similar opportunity exists but work on automated test model generation has revealed challenges. 
 
@@ -716,18 +723,18 @@
 
 \subsection{Assertions}
 
-The new validity analysis benefits from its metamodel focus, but it is never going to be as powerful as a mathematical proof tool and even such specialized tools are unable to prove everything. It is therefore inevitable that a pessimistic validity analysis will have false positives diagnosing a non-hazard. 
+The new validity analysis benefits from its metamodel focus, but it is never going to be as powerful as a mathematical proof tool and even such specialized tools are unable to prove everything. It is therefore inevitable that a pessimistic validity analysis will have false positives diagnosing non-hazards. 
 
-The user will have to provide assistance. An additional invariant or a more explicit guard may solve often the problem. For the harder cases it may be necessary to add an assertion capability.
+The user will have to provide assistance. An additional invariant or a more explicit guard may often solve the problem. For the harder cases it may be necessary to add an assertion capability.
 
 \begin{verbatim}
     OclAny::oclAssert(constraint : Lambda(T) : Boolean[1],
         justification : String[1]) : OclAny = self
 \end{verbatim}
 
-The assertion returns its source as its result while asserting that the \verb|constraint| is true for the result\footnote{The \emph{Lambda} type is the inevitable consequence of modeling the passing of OCL expressions to e.g. iteration bodies.}. The verb|constraint| may link to a possibly formal proof of the verb|constraint| facilitating a QA review of the ad hoc assertions.
+The assertion returns its source as its result and asserts that the \verb|constraint| is true for the result\footnote{The \emph{Lambda} type is the consequence of modeling the passing of OCL expressions to e.g. iteration bodies.}. The \verb|constraint| may link to a possibly formal proof of the \verb|constraint| facilitating a QA review of the ad hoc assertions.
 
-The challenge is therefore to make the program flow analysis powerful enough to reduce the number of false positives to a level where the user effort to provide extra invariants, guards or assertions is small enough in comparison with the benefit of the guarantee that there are zero undesirable crashes; invariants are 2-valued and model transformations crash comprehensively.
+The challenge is therefore to make the program flow analysis powerful enough to reduce the number of false positives to a level where the extra user effort to resolve the hazards is more than repaid by the benefits of no crashes. %to provide extra invariants, guards or assertions is small enough in comparison with the benefit of the guarantee that there are no undesirable crashes so that invariants are 2-valued and model transformations crash comprehensively.
 
 In many cases, the need for an assertion may alert the user to an unjustified optimism as to the true characteristics of all possible models.
 
@@ -743,27 +750,27 @@
 
 Conversely, if each constraint is written in its maximal form, the duplication of each simple constraint makes the more complicated constraint hard to read and so leads to maintenance difficulties.
 
-The bloat of maximal form could be eliminated by refactoring simpler constraints as Boolean-valued operations that can be used as predicates in the complex constraints. This could be supported automatically if named invariants were automatically recognized as definitions of Boolean-valued operations.
+%The bloat of maximal form could be eliminated by refactoring simpler constraints as Boolean-valued operations that can be used as predicates in the complex constraints. This could be supported automatically if named invariants were automatically recognized as definitions of Boolean-valued operations.
 
-Neither UML nor OCL specifications provide any style guidance for this.
+%Neither UML nor OCL specifications provide any style guidance for this.
 
 Once we use symbolic evaluation and associate a distinct symbolic value with each distinct AST element, the dilemma goes away. The multiple constraints are part of a logical conjunction for which common sub-expression elimination removes duplicates. Symbolic evaluation observes expression precedence to only traverse credible paths once. Only the first failure in the depth first traversal will be diagnosed.
 
-The style guidance can therefore be to write constraints in minimal form and to sequence many simple constraints in whatever order is easiest for a human to understand. The tooling doesn't care about the order but humans can most easily understand execute constraints in order.
+%The style guidance can therefore be to write constraints in minimal form and to sequence many simple constraints in whatever order is easiest for a human to understand. The tooling doesn't care about the order but humans can most easily understand execute constraints in order.
 
 \subsection{Exceptions}
 
-Our validity analysis guarantees that no undesirable crashes occur, and that desirable crashes always crash. For the benefit of Operating System level OCL that needs to handle a genuine crash, the ability to use the \verb|OclAny::oclIsInvalid()| library method to catch a crash could usefully be augmented with a \verb|OclAny::oclAsException()| method to unpack the \verb|invalid| singleton into a new \emph{Exception} class instance for comprehensive handling.
+Our validity analysis guarantees that no undesirable crashes occur, and that desirable crashes always crash. For the benefit of Operating System level OCL that needs to handle a genuine crash, the ability to use \verb|OclAny::oclIsInvalid()| to catch a crash could be enhanced by a \verb|OclAny::oclAsException()| method to unpack the \verb|invalid| singleton into a new \emph{Exception} class instance for comprehensive handling.
 
 \section{Current Status and Further Work}\label{Current Status and Further Work}
 
-This phase of work was initially driven by the challenges of faithfully implementing undesirable crashes for the QVTc/QVTr Java code generator. The inconveniences of uncrashing logical operations spiral once the logical operations define complex relation guards; an unmatching capability is required. Since the awkwardness of the implementation corresponds quite closely to surprising behaviour for the user, it is much more appropriate to push back and alert the user to the hazards and so avoid generating any of the difficult code. For model transformation, the no undesirable crashes, no suppressed desirable crashes policy is better, simpler and faster.
+This phase of work was initially driven by the challenges of faithfully implementing undesirable crashes for a QVTc/QVTr Java code generator~\cite{Eclipse-QVTd}. The inconveniences of uncrashing logical operations spiral once the logical operations define complex relation guards; an unmatching capability is required. Since the awkwardness of the implementation corresponds quite closely to surprising behavior for the user, it is much more appropriate to push back and alert the user to the hazards and so avoid generating any of the difficult code. For model transformation, the no undesirable crashes, all-crashes-always-crash policy is better, simpler and faster.
 
 The work continued the null-safe navigation work \cite{Safe OCL} which initially required almost all navigation operators to be changed to their safe counterparts; a widespread effort for no real benefit. Extending the null-safe declarations to support null-free collection reduced the changes to genuine hazards. However limited heuristic program control flow analysis meant that only simple guards were recognized as avoiding the hazard.
 
-The new work expands from just null hazards to all precondition failures with a much more comprehensive program flow analysis to propagate for instance a known symbol collection size or content to discount the hazard.
+The new work expands from just null hazards to all precondition failures with a much more comprehensive program flow analysis to propagate, for instance, a known symbol collection size or content to discount a hazard.
 
-The initial approach of deducing the values of variables backwards from the point at which a guard provides extra knowledge gave way to a forward evaluation of all relevant constraints to contradict may-be-xxx hypotheses at each potential hazard.
+The initial approach of deducing the values of variables backwards from the point at which a guard provides extra knowledge gave way to a forward evaluation of all relevant constraints to contradict \emph{IsXxx} hypotheses at each potential hazard.
 
 Once the focus shifts to a forwards symbolic evaluation, it is then just necessary to improve the formulation of the library operations.
 
@@ -790,17 +797,17 @@
 
 \section{Related Work}\label{Related Work}
 
-Preconditions and postconditions are an essential part of design by contract endorsed by the OCL specification, but because they are not much used in practice, the deficiencies in the OCL specification have not been detected. The USE tool is able to execute preconditions and postconditions at run-time. Eclipse OCL never executes them.
+Preconditions and postconditions are an essential part of design by contract endorsed by the OCL specification~\cite{OCL-2.4}, but because they are not much used in practice, these deficiencies in the OCL specification have not been reported. The USE tool~\cite{USE} is able to execute preconditions and postconditions at run-time. Eclipse OCL~\cite{Eclipse-OCL} never executes them.
 
-The inadequacy of preconditions and postconditions has been highlighted by the proposals to add support for framing conditions that simplistically assert that nothing else changes. It is clear that framing condition are necessary for OCL since the prohibition on side-effects ensures nothing changes that isn't mentioned in a postcondition.  
+The inadequacy of preconditions and postconditions has been highlighted by the proposals to add support for framing conditions \cite{Framing} that simplistically assert that nothing else changes. It is not clear that framing conditions are necessary for OCL since the prohibition on side-effects ensures nothing changes that isn't mentioned in a postcondition.  
 
-Work on automated test model generation produces suites of test models that can be animated. The preconditions can guide the production of good models and motivate the production of bad models.
+Work on automated test model generation \cite{Brucker},\cite{Francisco},\cite{Gogolla} produces suites of test models that can be animated. The preconditions can guide the production of good models and motivate the production of bad models.
 
-Work metamodel consistency may search for example models that contradict some desired quality of the metamodel, such as: there exists a model in which the number of instances of Class X is greater than zero.
+Tools such as EMFtoCSP \cite{EMFtoCSP} and UMLtoCSP establish metamodel consistency by searching for models that demonstrate that all metamodel constraints can be satisfied. An inadequate metamodel is detected if a particular class or constraint is dead with respect to all models searched. The constraints are translated from OCL to a CSP solver where they are repetitively evaluated for candidate models. 
 
-These usages rely on converting the (UML) metamodel and OCL constraints into the language of a SAT solver where searches/syntheses proceed. The precondition is assumed to be internally good and the corollaries are assessed.
+These usages rely on converting the (UML) metamodel and OCL constraints into the language of a CSP or SAT solver where searches/syntheses proceed. The precondition is assumed to be internally good and the corollaries are assessed.
 
-In this work, each precondition is proved to be internally good. Whether the precondition contributes to a usable system is not relevant. We just guarantee that no precondition can ever fail.
+In this work, each precondition is proved to be internally good without needing to synthesize any models. Whether the precondition contributes to a usable system is not relevant. We just guarantee that no precondition can ever fail and so remove an impediment to both normal and automated search usage.
 
 %\subsection{Summary of Changes}\label{Summary of Changes}
 
@@ -833,58 +840,67 @@
 % ---- Bibliography ----
 %
 \begin{thebibliography}{}
-%
-%\bibitem{zzOCL-Determinism}
-%Gogolla, M., Hilken, F.: Making OCL Collection Operations More Deterministic with Restricting Equations, 16th International Workshop in OCL and Textual Modeling, October 2, 2016, Saint-Malo, France.
-%\url{http://www.db.informatik.uni-bremen.de/publications/intern/ocl2016-talk-lightning-mg-fh.pdf}
-
-%\bibitem{zzLazy OCL}
-%Tisi, M., Douence, R., Wagelaar, D.: Lazy Evaluation for OCL.
-%15th International Workshop on OCL and Textual Modeling, September 8, 2015, Ottawa, Canada.
-%\url{https://ocl2015.lri.fr/OCL\_2015\_paper\_1111\_1115.pdf}
-
-%\bibitem{zzOCL-CG}
-%Willink, E.: An extensible OCL Virtual Machine and Code Generator.
-%2012 Workshop on OCL and Textual Modelling (OCL 2012), September 30, 2012, Innsbruck, Austria.
-%\url{http://st.inf.tu-dresden.de/OCL2012/preproceedings/14.pdf}
-
-%\bibitem{zzWillink-EXE2016}
-%Willink, E: Local Optimizations in Eclipse QVTc and QVTr using the Micro-Mapping Model of Computation,
-%2nd International Workshop on Executable Modeling, Exe 2016, Saint-Malo, October 2016.
-%\url{http://eclipse.org/mmt/qvt/docs/EXE2016/MicroMappings.pdf}
-
-\bibitem{Safe OCL}
-Willink, E.: Safe Navigation in OCL.
-15th International Workshop on OCL and Textual Modeling, September 8, 2015, Ottawa, Canada.
-\url{https://ocl2015.lri.fr/OCL\_2015\_paper\_1111\_1400.pdf}
-
-%\bibitem{zzDresden-OCL}
-%Dresden OCL Project.\\
-%\url{http://www.dresden-ocl.org/index.php/DresdenOCL}
-
-\bibitem{Eclipse-OCL}
-Eclipse OCL Project.\\
-\url{https://projects.eclipse.org/projects/modeling.mdt.ocl}
-
-\bibitem{QVT-1.3}
-OMG. Meta Object Facility (MOF) 2.0 Query/View/Transformation Specification, Version 1.3.
-OMG Document Number: ptc/16-06-03, June 2016.
-
-\bibitem{USE}
-USE, The UML-based Specification Environment. \url{http://useocl.sourceforge.net/w/index.php/Main\_Page}
 
 \bibitem{DragonBook}
 Aho, A., Sethi, R., Ullman, J.: Compilers, Principles, Techniques and Tools, Addison Wesley, 1986
 
-\bibitem{UML-2.5}
-OMG Unified Modeling Language (OMG UML), Version 2.5, {OMG Document Number}: formal/15-03-01, Object Management Group (2015), \url{http://www.omg.org/spec/UML/2.5}
+\bibitem{Brucker}
+Brucker, A., Krieger, M., Longuet, D., Wolff, B.: A Specification-based Test Case Generation Method for UML. 10th International Workshop on OCL and Textual Modeling, October, 2010, Oslo, Norway.
+\url{https://modeling-languages.com/events/OCLWorkshop2010/submissions/ocl10\_submission\_7.pdf}
+
+\bibitem{Francisco}
+Francisco, M., Castro, L.: Automatic Generation of Test Models and Propertiesfrom UML Models with OCL Constraints. 12th International Workshop on OCL and Textual Modeling, September, 2010, Innsbruck, Austria.\\
+\url{https://st.inf.tu-dresden.de/OCL2012/preproceedings/07.pdf}
+
+\bibitem{Gogolla}
+Gogolla, M., Burgue\~no, L., Vallecillo, A.: EMFtoCSP: A Tool for the Model Finding and Model Completion with USE. 18th International Workshop on OCL and Textual Modeling. Copenhagen, Denmark, October 14, 2018.
+\url{https://ceur-ws.org/Vol-2245/ocl_paper_9.pdf}
+
+\bibitem{EMFtoCSP}
+Gonz\`alez, C., B\~uttner, F., Claris\'o, R., Cabot, J.: EMFtoCSP: A Tool for the Lightweight Verification of EMF Models. Formal Methods in Software Engineering: Rigorous and Agile Approaches (FormSERA), Jun 2012, Zurich, Switzerland. hal-00688039
+\url{https://hal.inria.fr/file/index/docid/688039/filename/emftocsp.pdf}
+
+\bibitem{Framing}
+Przigoda, N., Filho, J., Niemann, P., Wille, R.: Frame Conditions in Symbolic Representations of UML/OCL Models. 2016 ACM/IEEE International Conference on Formal Methods and Models for System Design (MEMOCODE), 2016, pp. 65-70, doi: 10.1109/MEMCOD.2016.7797747.\\
+\url{https://iic.jku.at/files/eda/
+2016\_memocode\_frame\_conditions\_symbolic\_representation.pdf}
+
+\bibitem{EMF}
+Steinberg, D., Budinsky, F., Paternostro, M., Merks, E.: EMF: Eclipse Modeling Framework. Addison-Wesley, Jun 2008
+
+\bibitem{OCLreflections}
+Willink, E.: Reflections on OCL 2. Journal of Object Technology. Vol.19, No. 3, 2020.\\ \url{https://dx.doi.org/10.5381/jot.2020.19.3.a17}
+
+\bibitem{Safe OCL}
+Willink, E.: Safe Navigation in OCL.
+15th International Workshop on OCL and Textual Modeling, September 8, 2015, Ottawa, Canada.\\
+\url{https://ocl2015.lri.fr/OCL\_2015\_paper\_1111\_1400.pdf}
 
 \bibitem{OCL-2.4}
-Object Constraint Language. Version 2.4., OMG Document Number: formal/2014-02-03, Object Management Group (2009),  \url{http://www.omg.org/spec/OCL/2.4}
+Object Constraint Language. Version 2.4., OMG Document Number: formal/2014-02-03, Object Management Group. February 2014,  \url{https://www.omg.org/spec/OCL/2.4}
+
+\bibitem{QVT-1.3}
+OMG. Meta Object Facility (MOF) 2.0 Query/View/Transformation Specification, Version 1.3.
+OMG Document Number: ptc/16-06-03, June 2016.
+\url{https://www.omg.org/spec/QVT/1.3}
+
+\bibitem{UML-2.5}
+OMG Unified Modeling Language (OMG UML), Version 2.5, {OMG Document Number}: formal/15-03-01, Object Management Group, March 2015,\\ \url{https://www.omg.org/spec/UML/2.5}
+
+\bibitem{Eclipse-OCL}
+Eclipse OCL Project.
+\url{https://projects.eclipse.org/projects/modeling.mdt.ocl}
 
 \bibitem{Eclipse-QVTd}
 Eclipse QVT Declarative Project.\\
 \url{https://projects.eclipse.org/projects/modeling.mmt.qvtd}
 
+\bibitem{OCLinEcore}
+OCLinEcore.
+\url{https://wiki.eclipse.org/OCL/OCLinEcore}
+
+\bibitem{USE}
+USE, The UML-based Specification Environment. \\ \url{https://useocl.sourceforge.net/w/index.php/Main\_Page}
+
 \end{thebibliography}
 \end{document}
diff --git a/ocl/docs/publications/OCL2021Validity/cc-by.pdf b/ocl/docs/publications/OCL2021Validity/cc-by.pdf
new file mode 100644
index 0000000..1edf9f0
--- /dev/null
+++ b/ocl/docs/publications/OCL2021Validity/cc-by.pdf
Binary files differ
diff --git a/ocl/docs/publications/OCL2021Validity/ceur-ws-logo.pdf b/ocl/docs/publications/OCL2021Validity/ceur-ws-logo.pdf
new file mode 100644
index 0000000..514e386
--- /dev/null
+++ b/ocl/docs/publications/OCL2021Validity/ceur-ws-logo.pdf
Binary files differ
diff --git a/ocl/docs/publications/OCL2021Validity/ceurart.cls b/ocl/docs/publications/OCL2021Validity/ceurart.cls
new file mode 100644
index 0000000..b8dfc22
--- /dev/null
+++ b/ocl/docs/publications/OCL2021Validity/ceurart.cls
@@ -0,0 +1,2873 @@
+%% ceurart.cls
+%% Copyright 2019--2020 CEUR Workshop Proceedings (CEUR-WS.org)
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+%   http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Dmitry S. Kulyabov.
+% The code was originally based on 'CAS Bundle' code.
+% 
+
+\def\RCSfile{ceurart}%
+\def\RCSversion{0.4.0}%
+\def\RCSdate{2021/03/18}%
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesClass{\RCSfile}[\RCSdate, \RCSversion: Typesetting articles for CEUR Workshop Proceedings (CEUR-WS.org)]
+
+\RequirePackage{expl3,xparse}
+\@ifundefined{regex_match:nnTF}{\RequirePackage{l3regex}}{}
+
+\ExplSyntaxOn
+
+%%
+%% switches
+%%
+
+\newif\iflongmktitle    \longmktitlefalse
+
+%% twocolumn
+\newif\ifdc             \global\dcfalse
+\newif\ifsc             \global\sctrue
+\newif\ifcasreviewlayout  \global\casreviewlayoutfalse
+\newif\ifcasfinallayout   \global\casfinallayoutfalse
+%% enable header and footer
+\bool_new:N \g_ceur_hf_bool
+\bool_gset_false:N \g_ceur_hf_bool
+
+% \ifhf
+%   \bool_gset_true:N \g_ceur_hf_bool
+% \fi
+%% header and footer
+% \newif\ifhf
+% \global\hffalse
+
+\newcounter{blind}
+\setcounter{blind}{0}
+
+% \def\blstr#1{\gdef\@blstr{#1}}
+% \def\@blstr{1}
+% \newdimen\@bls
+% \@bls=\baselineskip
+
+%\newif\if@twocolumn
+\DeclareOption{twocolumn}{\global\dctrue \global\scfalse}
+\DeclareOption{hf}{\bool_gset_true:N \g_ceur_hf_bool}
+% \DeclareOption{hf}{\global\hftrue}
+
+\DeclareOption{singleblind}{\setcounter{blind}{1}}
+\DeclareOption{doubleblind}{\setcounter{blind}{2}}
+\DeclareOption{longmktitle}{\global\longmktitletrue}
+\DeclareOption{final}{\global\casfinallayouttrue}
+\DeclareOption{review}{\global\casreviewlayouttrue}
+
+% \ExecuteOptions{a4paper,10pt,oneside,review}
+% \ExecuteOptions{a4paper,oneside,10pt,DIV=calc}
+\DeclareOption*{\PassOptionsToClass{\CurrentOption}{scrartcl}}
+\PassOptionsToClass{a4paper,twoside=false}{scrartcl}
+\ProcessOptions\relax
+\LoadClass{scrartcl}
+\KOMAoptions{DIV=10}
+\ifdc
+  \KOMAoptions{fontsize=9pt}
+\else
+  \KOMAoptions{fontsize=11pt}
+\fi
+
+\RequirePackage{graphicx}
+\RequirePackage{amsmath,amsfonts,amssymb}
+\allowdisplaybreaks
+
+\RequirePackage{etoolbox,balance}
+\RequirePackage{booktabs,makecell,multirow,array,colortbl,dcolumn,stfloats}
+\RequirePackage{xspace,xstring}
+\RequirePackage{footmisc}
+\RequirePackage[svgnames,dvipsnames]{xcolor}
+\RequirePackage{iftex}
+\RequirePackage{microtype}
+
+%% PDF/A support
+
+\ifpdftex
+\RequirePackage{cmap}
+\fi
+
+\bool_new:N \g_ceur_pdfx_bool
+\bool_gset_false:N \g_ceur_pdfx_bool
+
+\file_if_exist:nTF { pdfx.sty } {%
+  \RequirePackage[useBOM,pdf17,a-3u]{pdfx}
+  \bool_gset_true:N \g_ceur_pdfx_bool
+}{%
+  \RequirePackage[unicode]{hyperref}
+}
+\hypersetup{%
+  colorlinks,
+  bookmarksnumbered,
+  pdfencoding=unicode,
+  allcolors=DarkSlateGrey
+}
+\pdfstringdefDisableCommands{%
+  \def\addtocounter#1#2{}%
+  \def\unskip{}%
+  \def\textbullet{- }%
+  \def\textrightarrow{ -> }%
+  \def\footnotemark{}%
+}
+\urlstyle{rm}
+\colorlet{scolor}{black}
+\colorlet{hscolor}{DarkSlateGrey}
+% \AtEndDocument{\hypersetup
+%   {pdftitle={\csuse{__short_title:}},
+%   pdfauthor={\csuse{__short_authors:}}}}
+
+\let\comma\@empty
+\let\tnotesep\@empty
+\let\@title\@empty
+
+%
+% Load Common items
+%
+
+%%
+%%
+%%
+
+%%
+%% Bools
+%%
+
+%%
+%% Bells and Whistles
+%%
+
+\bool_new:N \g_ceur_nologo_bool
+\bool_gset_false:N \g_ceur_nologo_bool
+
+\file_if_exist:nTF { fontawesome5.sty } {%
+  \RequirePackage{fontawesome5}
+  % We need orcid icon
+  \@ifpackagelater{fontawesome5}{2020/01/17}{%
+    \bool_gset_false:N \g_ceur_nologo_bool
+  }{%
+    \bool_gset_true:N \g_ceur_nologo_bool
+  }
+}{%
+  \bool_gset_true:N \g_ceur_nologo_bool
+}
+
+%%
+%% PDF/A
+%%
+
+%% allocate a write stream
+\iow_new:N \g_xmpdata_output_iow
+\iow_open:Nn \g_xmpdata_output_iow { \c_sys_jobname_str .xmpdata }
+
+%% User interface
+\NewDocumentCommand{\xmpdatawrite}{ m m } {
+  \xmpdata_write:n { \iow_char:N \\ #1 \iow_char:N \{ #2 \iow_char:N \} }
+}
+
+%% Inner function
+\cs_new_protected:Npn \xmpdata_write:n #1
+{
+  \iow_now:Nx \g_xmpdata_output_iow { #1 }
+}
+
+%%
+%% Utils
+%%
+
+%% Workaround for unwanted '.pdf' to path (provided by hyperref)
+%% https://tex.stackexchange.com/questions/154335/href-adds-unwanted-pdf-to-path-provided
+\providecommand*{\hrefurl}{\hyper@normalise\hrefurl@}
+\providecommand*{\hrefurl@}[2]{\hyper@linkurl{#2}{#1}}
+
+%%
+%%
+%%
+
+% \newcommand\ceurConference[4][]{%
+%   \gdef\ceurConference@shortname{#1}%
+%   \gdef\ceurConference@name{#2}%
+%   \gdef\ceurConference@date{#3}%
+%   \gdef\ceurConference@venue{#4}%
+%   \ifx\ceurConference@shortname\@empty
+%     \gdef\ceurConference@shortname{#2}%
+%   \fi
+% }
+
+\DeclareRobustCommand\conference[1]{%
+  \gdef\ceurConference@name{#1}%
+}
+
+%
+% Specific to Single Column
+%
+
+\RenewDocumentCommand \maketitle {} {
+  \nonumnote{\itshape \ceurConference@name}
+  \logonote{\@copyrightLine}
+  \logonote{\@ceurLogoLine}
+  % \ifbool { usecasgrabsbox }
+  %   {
+  %     \setcounter{page}{0}
+  %     \thispagestyle{empty}
+  %     \unvbox\casgrabsbox
+  %   } { }
+  % \pagebreak
+  % \ifbool { usecashlsbox }
+  %   {
+  %     \setcounter{page}{0}
+  %     \thispagestyle{empty}
+  %     \unvbox\casauhlbox
+  %   } { }
+  %     \pagebreak
+  \thispagestyle{plain}
+  \xdef\firstpage{\thepage}
+  % \thispagestyle{first}
+  % \pagestyle{standard}
+  \ifbool{longmktitle}
+  {
+    \LongMaketitleBox
+    \ProcessLongTitleBox
+  }
+  {
+    \ifbool{dc}
+    { \twocolumn[\MaketitleBox] }
+    { \MaketitleBox }
+    \printFirstPageNotes
+  }
+  \normalcolor \normalfont
+  \setcounter{footnote}{\int_use:N \g_ceur_fnote_int}
+  \renewcommand\thefootnote{\arabic{footnote}}
+  \gdef\@pdfauthor{\infoauthors}
+  % \gdef\@pdfsubject{Complex ~CEUR ~Content}
+
+  %% PDF/A
+  
+  % List of supported metadata fields
+  
+  % General information:
+  
+  % \Author           - the document's human author. Separate multiple authors with \sep.
+  % \Title            - the document's title.
+  % \Keywords         - list of keywords, separated with \sep.
+  % \Subject          - the abstract.
+  % \Org              - publishers.
+
+  % Copyright information:
+
+  % \Copyright        - a copyright statement.
+  % \CopyrightURL     - location of a web page describing the owner and/or rights statement for this document.
+  % \Copyrighted      - 'True' if the document is copyrighted, and
+  % 'False' if it isn't. This is automatically set to 'True' if either
+  % \Copyright or \CopyrightURL is specified, but can be overridden.
+  
+  % Publication information:
+
+  % \PublicationType   - The type of publication. If defined, must be
+  % one of book, catalog, feed, journal, magazine,
+  % manual, newsletter, pamphlet. This is
+  % automatically set to "journal" if \Journaltitle
+  % is specified, but can be overridden.
+  % \Journaltitle      - The title of the journal in which the document
+  % was published.
+  % \Journalnumber     - The ISSN for the publication in which the
+  % document was published.
+  % \Volume            - Journal volume.
+  % \Issue             - Journal issue/number.
+  % \Firstpage         - First page number of the published version of
+  % the document.
+  % \Lastpage          - Last page number of the published version of
+  % the document.
+  % \Doi               - Digital Object Identifier (DOI) for the
+  % document, without the leading "doi:".
+  % \CoverDisplayDate  - Date on the cover of the journal issue, as a
+  % human-readable text string.
+  % \CoverDate         - Date on the cover of the journal issue, in a
+  % format suitable for storing in a database field
+  % with a 'date' data type.
+  
+  \bool_if:NTF \g_ceur_pdfx_bool
+  {
+    \xmpdatawrite{Title}{\casprelimstitle}
+    \xmpdatawrite{Author}{\pdfxauthors}
+    \xmpdatawrite{Subject}{CEUR~Workshop~Proceedings~(CEUR-WS.org)}
+
+    \ifx\@copyrightclause\@empty\else
+      \xmpdatawrite{Copyright}{\iow_char:N \\ copyright\ \@copyrightyear\ \@copyrightclause}
+      \xmpdatawrite{CopyrightURL}{https://creativecommons.org/licenses/by/4.0}
+    \fi
+
+    \xmpdatawrite{Journaltitle}{CEUR~Workshop~Proceedings}
+    \xmpdatawrite{Journalnumber}{1613-0073}
+    \bool_if:NTF \g_ceur_hf_bool {
+        \xmpdatawrite{Firstpage}{\firstpage}
+        \xmpdatawrite{Lastpage}{\lastpage}
+    }{ }
+  }{
+    \hypersetup{%
+      pdfcreator={ceurart.cls},
+      % pdfproducer={pdfTeX;},
+      % pdftitle={\csuse{__short_title:}},
+      % pdfauthor={\csuse{__short_authors:}},
+      % pdfauthor={\csuse{__authors:}},
+      % pdftitle={\@title},
+      pdfsubject={CEUR~Workshop~Proceedings~(CEUR-WS.org)},
+      % pdfkeywords={\@keywords},
+      linkcolor={hscolor},
+      urlcolor={hscolor},
+      citecolor={hscolor},
+      filecolor={hscolor},
+      menucolor={hscolor},
+    }    
+  }
+}
+
+
+  % pdfcreator={ceurart.cls},
+  % % pdfproducer={pdfTeX;},
+  % % pdftitle={\csuse{__short_title:}},
+  % % pdfauthor={\csuse{__short_authors:}},
+  % % pdfauthor={\csuse{__authors:}},
+  % % pdftitle={\@title},
+  % pdfsubject={CEUR Workshop Proceedings (CEUR-WS.org)},
+
+
+%
+% Front matter macros
+%
+% The front matter macros are derived/adopted from stm-prelims.sty
+% written by CV Radhakrishnan <cvr@cvr.cc> and copyrighted by him.
+% Usage of those macros and methods are gratefully acknowledged.
+%
+
+\keys_define:nn { ceur / title } {
+  mode      .choice:     ,
+  mode / title  .meta:n  = {
+    type   = title      ,
+    size   = \LARGE      ,
+    % size   = \huge      ,
+    % shape  = \upshape   ,
+    shape  = \sffamily   ,
+    % weight = \mdseries  ,
+    weight = \bfseries  ,
+    color  = black  ,
+    before = 0pt        ,
+    after  = 0pt        ,
+    align  = \raggedright ,
+  } ,
+  mode / alt  .meta:n  = {
+    type   = alt      ,
+    size   = \large     ,
+    shape  = \upshape   ,
+    weight = \mdseries  ,
+    color  = black  ,
+    before = 6pt        ,
+    after  = 0pt        ,
+    align  = \raggedright ,
+  } ,
+  mode / sub    .meta:n  = {
+    type   = sub           ,
+    size   = \large        ,
+    shape  = \upshape      ,
+    weight = \mdseries     ,
+    color  = black!80  ,
+    before = 6pt          ,
+    after  = 0pt           ,
+    align  = \raggedright  ,
+  } ,
+  mode / trans   .meta:n  =  {
+    type   = trans         ,
+    size   = \normalsize   ,
+    shape  = \upshape      ,
+    weight = \mdseries     ,
+    color  = black!60      ,
+    before = 6pt           ,
+    after  = 0pt           ,
+    align  = \raggedright  ,
+  } ,
+  mode / transsub   .meta:n  = {
+    type   = transsub      ,
+    size   = \small        ,
+    shape  = \upshape      ,
+    weight = \mdseries     ,
+    color  = black!50      ,
+    before = 6pt           ,
+    after  = 0pt           ,
+    align  = \raggedright  ,
+  } ,
+  mode / ascii   .meta:n  = {
+    type   = ascii            ,
+    size   = \small\ttfamily  ,
+    shape  = \upshape         ,
+    weight = \mdseries        ,
+    color  = black            ,
+    before = 12pt             ,
+    after  = 0pt              ,
+    align  = \raggedright     ,
+  } ,
+  type      .tl_set:N    = \l_ceur_title_type_tl      ,
+  size      .tl_set:N    = \l_ceur_title_size_tl      ,
+  shape     .tl_set:N    = \l_ceur_title_shape_tl     ,
+  weight    .tl_set:N    = \l_ceur_title_weight_tl    ,
+  before    .dim_set:N   = \l_ceur_title_before_dim   ,
+  after     .dim_set:N   = \l_ceur_title_after_dim    ,
+  align     .tl_set:N    = \l_ceur_title_align_tl     ,
+  color     .tl_set:N    = \l_ceur_title_color_tl     ,
+}
+
+\NewDocumentCommand \processTmarks { } {
+  \cs_if_free:cTF { mark@title }
+  { \ignorespaces }
+  { \tl_set:Nx \l_tmpa_tl { \cs:w mark@title\cs_end: }
+    \clist_map_inline:cn { mark@title }
+    {
+      \str_case:nn { ##1 }
+      {
+        { 1 }  { $^\star$ }
+        { 2 }  { $^{,\star\star}$ }
+        { 3 }  { $^{,\star\star\star}$ }
+      }
+    }
+  }
+}
+
+\RenewDocumentCommand \title { O{mode = title} m } {
+  \pdfstringdef \@pdftitle { #2 }
+  \csgdef { casprelimstitle } { #2 }
+  \keys_set:nn { ceur / title } { #1 }
+  \tl_if_empty:NTF \__short_title: {
+    \cs_gset:Nn \__short_title: { #2 }
+  }{ }
+  \seq_gput_right:Nn \g_ceur_title_seq {
+    \keys_set:nn { ceur / title } { #1 }
+    % \iow_term:n { MODE:~\l_ceur_title_mode_tl ~ ~ [#1]}
+    \par \vskip \l_ceur_title_before_dim
+    \l_ceur_title_align_tl
+    \l_ceur_title_size_tl
+    \l_ceur_title_shape_tl
+    \l_ceur_title_weight_tl
+    \color { \l_ceur_title_color_tl }
+    #2
+    \tl_set:Nn \l_tmpa_tl { title }
+    \tl_if_eq:NNTF \l_ceur_title_type_tl \l_tmpa_tl
+    { \processTmarks } { }
+    \par \vskip  \l_ceur_title_after_dim
+    \normalcolor \normalsize \normalfont
+  }
+}
+
+%  \gappto\usestmtitle{#1}%
+
+\renewcommand \@title { \seq_use:Nn \g_ceur_title_seq { } }
+
+\NewDocumentCommand \wrAun { m }      %  unexpanded write to aux
+   { \iow_now:Nn \@auxout { #1 } }
+\NewDocumentCommand \wrAux { m }      %  expanded write to aux
+   { \iow_now:Nx \@auxout { #1 } }
+
+\NewDocumentCommand \wrShipAux { m }   % expanded write at shipout
+   { \iow_shipout:Nx \@auxout { #1 } }
+\NewDocumentCommand \wrShipAun { m }   % unexpanded write at shipout
+   { \iow_shipout:Nn \@auxout { #1 } }
+
+\NewDocumentCommand \ceurLabel { m } {
+  \@bsphack \wrAux
+  { \token_to_str:N \NewLabel { #1 }
+    { \@currentlabel }
+  } \@esphack
+}
+
+\NewDocumentCommand \NewLabel { m m } {
+  \cs_if_free:cTF { X@#1: }
+  { \cs_new:cx { X@#1: } { #2 } }
+  { \cs_set:cx { X@#1: } { #2 } }
+}
+
+\NewDocumentCommand \ceurRef { m } {
+  \cs_if_free:cTF { X@#1: }
+  { 0 } {\use:c {X@#1:} }
+}
+
+\seq_clear_new:N \l_fnmk_seq
+\NewDocumentCommand \processFnRef { m } {
+  \seq_clear:N \l_fnmk_seq
+  \clist_map_inline:nn { #1 }
+  { \seq_put_right:Nx \l_fnmk_seq
+    {\cs_if_free:cTF { X@##1: } {0} { \use:c {X@##1:} }}
+  }
+}
+
+\NewDocumentCommand \fnmark { O{} } {
+  \writemarks { fnau\theau@ } { #1 }
+}
+
+
+\NewDocumentCommand  \fnref { m } {
+  \processFnRef { #1 }
+  \wrAux { \token_to_str:N \csxdef {mark@fnau\theau@}
+    { \seq_use:Nn \l_fnmk_seq  { , } } }
+}
+
+\NewDocumentCommand \corref { m } {
+  \str_set:Nx \l_tmpa_str { \ceurRef { #1 } }
+  \wrAux { \token_to_str:N \csxdef { mark@corau\theau@ }
+    {
+      \cs_if_free:cTF { X@#1: } {0} { \use:c {X@#1:} }
+    }
+  }
+}
+
+\NewDocumentCommand \cormark { O{} } {
+  \@cormarktrue
+  \writemarks {corau\theau@} { #1 }
+}
+
+\seq_new:N \l_ceur_au_seq
+\seq_new:N \l_ceur_au_sn_seq
+\seq_new:N \l_ceur_au_fn_seq
+\seq_new:N \l_ceur_au_ead_seq
+\seq_new:N \l_ceur_au_orcid_seq
+\seq_new:N \l_ceur_au_email_seq
+\seq_new:N \l_ceur_au_url_seq
+\seq_new:N \l_ceur_au_contrib_role_seq
+
+\NewDocumentCommand \parsename { m } {
+  \seq_set_split:Nnn \l_ceur_au_seq { ~ } { #1 }
+  \seq_pop_right:NN \l_ceur_au_seq \l_ceur_au_sn_seq
+  \seq_map_inline:Nn \l_ceur_au_seq
+  { \seq_put_right:Nx \l_ceur_au_ead_seq
+    { \tl_head:n { #1 }. }
+  }
+}
+
+\NewDocumentCommand \invparsename { m } {
+  \seq_set_split:Nnn \l_ceur_au_seq { ~ } { #1 }
+  \seq_pop_left:NN \l_ceur_au_seq \l_ceur_au_sn_seq
+  \seq_map_inline:Nn \l_ceur_au_seq
+  { \seq_put_right:Nx \l_ceur_au_ead_seq
+    { \tl_head:n { #1 }. }
+  }
+}
+
+\NewDocumentCommand \surname {} {
+  \l_ceur_au_sn_seq
+}
+
+\NewDocumentCommand \firstname {} {
+  \seq_use:Nn \l_ceur_au_seq { \no_break_space: }
+}
+
+\NewDocumentCommand \eadauthor {} {
+  \seq_map_inline:Nn \l_ceur_au_seq
+  {
+    \regex_match:nnTF { \. } { ##1 }
+    { ##1 \, }
+    { \tl_head:n {##1}. \, }
+  } {\,} \l_ceur_au_sn_seq
+}
+
+\cs_set_eq:NN \shortauthor \eadauthor
+
+\seq_clear_new:N \l_affmk_seq
+\NewDocumentCommand \processAffRef { m }
+   {
+     \seq_clear:N \l_affmk_seq
+     \clist_map_inline:nn { #1 }
+     {
+       \seq_put_right:Nx \l_affmk_seq
+       {\ceurRef{##1}}
+      }
+    }
+
+\NewDocumentCommand \processAffNum { m }
+   {
+     \seq_clear:N \l_affmk_seq
+     \clist_map_inline:nn { #1 }
+     {
+       \seq_put_right:Nn \l_affmk_seq
+       { \int_to_arabic:n {##1} }
+      }
+    }
+
+\NewDocumentCommand \listAff { }
+   {
+     \tl_if_blank:nTF { \l_affmk_seq }
+       { \tl_gset:Nn \g_ceur_comma_tl { 0 } }
+       {
+         \seq_use:Nn \l_affmk_seq { , }
+         \tex_def:D \sep{\unskip,}
+       }
+   }
+
+\NewDocumentCommand \ead { O{} m }
+   {
+     \tl_if_empty:nTF { #1 } { \@ead {#2} } { \@uad[#1]{#2} }
+   }
+
+\NewDocumentCommand \eadsep { } { }
+
+\int_new:N \g_ead_int
+\seq_new:N \g_ceur_ead_seq
+\int_new:N \g_uad_int
+\int_new:N \g_orcid_int
+\seq_new:N \g_ceur_uad_seq
+\seq_new:N \g_ceur_orcid_seq
+\seq_new:N \g_ceur_contrib_role_seq
+
+\newcommand\theead { \int_use:N \g_ead_int }
+
+\NewDocumentCommand \@uad { O{} m }
+   {
+     \group_begin:
+     \wrAux { \token_to_str:N \urlauthor
+       { \exp_not:n {#2}}{\the\@eadauthor}}%
+     \group_end:
+   }
+
+\NewDocumentCommand \urlauthor { m m } {
+  \int_gincr:N \g_uad_int
+  \seq_gput_right:Nn \g_ceur_uad_seq
+  {
+    { %\ttfamily \tl_to_str:n
+      \url{ #1 } }
+    \parsename { #2 }
+    \space(\eadauthor)
+  }
+}
+\NewDocumentCommand \@stmuads { }
+  { \seq_use:Nn \g_ceur_uad_seq { ;~ } }
+
+\NewDocumentCommand \@ead { m }
+   {
+     \group_begin:
+     \wrAux { \token_to_str:N \emailauthor
+       { \exp_not:n { #1 }}{ \the\@eadauthor }}
+     \group_end:
+   }
+
+\newtoks \@eadauthor
+\newbool{@cormark}
+
+\NewDocumentCommand \emailauthor { m m }
+{
+  \int_gincr:N \g_ead_int
+  \seq_gput_right:Nn \g_ceur_ead_seq
+  {
+    % { \ttfamily \tl_to_str:n { #1 } }
+    { \href {mailto: #1 } { #1 } }
+    \parsename { #2 }
+    \space(\eadauthor)%
+  }
+}
+
+\NewDocumentCommand \@elseads { }
+{
+  \seq_use:Nn \g_ceur_ead_seq { ;~ }
+}
+
+\NewDocumentCommand \printemails { } {
+  \group_begin:
+  \int_compare:nNnTF { \int_use:N \g_ead_int } > { 0 } {
+    \tex_let:D \thefootnote \relax \footnotetext {
+      \raggedright
+      \hspace*{-\parindent}
+      % \hspace*{-\labelsep}
+      \hspace*{-\footnotemargin}
+      \bool_if:NTF \g_ceur_nologo_bool {
+        \int_compare:nTF { \g_ead_int = 1 }
+        { \textsc{email:\c_space_token} }
+        { \textsc{email:\c_space_token} }
+      }
+      { \faIcon[regular]{envelope-open}\c_space_token }
+      \seq_use:Nn \g_ceur_ead_seq { ;~ }
+    }
+  } {  }
+  \group_end:
+}
+
+\NewDocumentCommand \printurls { } {
+  \group_begin:
+  \int_compare:nTF { \g_uad_int > 0 } {
+    \tex_let:D \thefootnote \relax \footnotetext {
+      \raggedright
+      \hspace*{-\parindent}
+      % \hspace*{-\labelsep}
+      \hspace*{-\footnotemargin}
+      \bool_if:NTF \g_ceur_nologo_bool
+      { \textsc{url:\c_space_token} }
+      { \faIcon{globe}\c_space_token }
+      \seq_use:Nn \g_ceur_uad_seq { ;~ }
+    }
+  } { }
+  \group_end:
+}
+
+%%
+%% orcid
+%%
+
+\NewDocumentCommand \orcidauthor { m m } {
+  \int_gincr:N \g_orcid_int
+  \seq_gput_right:Nn \g_ceur_orcid_seq {
+    % { \ttfamily \tl_to_str:n { #1 } }
+    { \hrefurl { https://orcid.org/ #1 } { #1 } }
+    \parsename{#2}
+    \space(\eadauthor)
+  }
+}
+
+\NewDocumentCommand \printorcid { } {
+  \group_begin:
+  \int_compare:nTF { \g_orcid_int > 0 } {
+    \tex_let:D \thefootnote \relax \footnotetext {
+      \raggedright
+      \hspace*{-\parindent}
+      % \hspace*{-\labelsep}
+      \hspace*{-\footnotemargin}
+      \bool_if:NTF \g_ceur_nologo_bool
+      { \textsc{orcid:\c_space_token} }
+      { \faIcon{orcid}\c_space_token }
+      \seq_use:Nn \g_ceur_orcid_seq { ;~ }
+    }
+  } { }
+  \group_end:
+}
+
+%
+% Contrib Role
+%
+
+\seq_gclear_new:N \g_ceur_credits_seq
+
+\NewDocumentCommand \ContribRole { m }
+{
+  \wrAux { \token_to_str:N \creditauthor
+    { #1 } { \the\@eadauthor } }
+}
+
+\NewDocumentCommand \creditauthor { m m }
+{
+  \seq_gput_right:Nx \g_ceur_credits_seq
+  { { \exp_not:N\bfseries #2 :}\space #1 }
+}
+
+\cs_set_eq:NN \credit \ContribRole
+
+\NewDocumentCommand \printcredits { }
+{
+  \seq_if_empty:NF \g_ceur_credits_seq
+  {
+    \section*{CRediT ~authorship ~contribution ~statement}
+    \seq_use:Nn \g_ceur_credits_seq { .~ }.
+  }
+}
+
+\NewDocumentCommand \writemarks { m m }
+   { \wrAux { \token_to_str:N \csgdef{mark@#1}{#2} } }
+
+\seq_new:N \g_ceur_title_seq
+
+\NewDocumentCommand \tnotemark { O{} }
+   { \writemarks { title } { #1 } }
+
+\NewDocumentCommand \@tnoteref { m }
+   { \int_set:Nn \l_tmpa_int { 0 }
+     \clist_map_inline:nn { #1 }
+      {
+%        \msg_term:n { ##1 .. [\cs:w X@##1:\cs_end:] }
+        \cs_if_free:cTF { X@##1: }
+          { \csdef{X@##1:}{0} }
+          {
+            \tl_set:Nx \l_tmpa_tl { \cs:w X@##1:\cs_end: }
+            \int_case:nn { \l_tmpa_tl }
+              {
+                 { 1 }  { $^\star$ }
+                 { 2 }  { $^{,\star\star}$ }
+                 { 3 }  { $^{,\star\star\star}$ }
+              }
+          }
+      }
+    }
+
+\seq_new:N \g_ceur_tnote_seq
+\int_new:N \g_ceur_tnote_int
+
+\NewDocumentCommand \tnotetext { O{} m }
+   {
+     \tl_if_head_eq_catcode:nNTF { #1 } a
+       {
+         \msg_term:n { [TNOTE:~alpha] }%
+         \seq_gput_right:Nn \g_ceur_tnote_seq
+           { \int_incr:N \g_ceur_tnote_int
+             \str_set:Nx \@currentlabel { \int_use:N \g_ceur_tnote_int }
+              \ceurLabel { #1 }
+             \renewcommand\thefootnote
+              { \int_case:nn { \g_ceur_tnote_int }
+                 {
+                   { 1 } { $^\star$ }
+                   { 2 }  { $^{\star\star}$ }
+                   { 3 }  { $^{\star\star\star}$ }
+                 }
+              }
+              \footnotetext { #2 }
+            }
+          }
+        {
+          \msg_term:n { [TNOTE:~Number] }
+          \seq_gput_right:Nn \g_ceur_tnote_seq
+          {
+            \int_set:Nn \l_tmpa_int { #1 }
+            \renewcommand\thefootnote
+              { \int_case:nn { \l_tmpa_int }
+                {
+                  { 1 } { $^\star$ }
+                  { 2 }  { $^{\star\star}$ }
+                  { 3 }  { $^{\star\star\star}$ }
+                }
+              }
+             \footnotetext { #2 }
+           }
+         }
+       }
+
+\newcommand \printtnotes { \seq_use:Nn \g_ceur_tnote_seq { \par } }
+
+\seq_new:N \g_ceur_nonumnote_seq
+
+\NewDocumentCommand \nonumnote { m }
+{
+  \group_begin:
+  \seq_gput_right:Nn \g_ceur_nonumnote_seq
+  {
+    \tex_def:D \thefootnote { }
+    \footnotetext{%
+      \raggedright
+      \hspace*{-\parindent}
+      % \hspace*{-\labelsep}
+      \hspace*{-\footnotemargin}
+      #1}
+  }
+  \group_end:
+}
+
+\newcommand \printnonumnotes { \seq_use:Nn \g_ceur_nonumnote_seq { \par } }
+
+\seq_new:N \g_ceur_fnote_seq
+\int_new:N \g_ceur_fnote_int
+
+\NewDocumentCommand \fntext { O{} m }
+{
+  \tl_if_head_eq_catcode:nNTF { #1 } a
+  {
+    \msg_term:n { [FN:~alpha] }%
+    \seq_gput_right:Nn \g_ceur_fnote_seq
+    { \int_incr:N \g_ceur_fnote_int
+      \str_set:Nx \@currentlabel { \int_use:N \g_ceur_fnote_int }
+      \ceurLabel { #1 }
+      \tex_def:D \thefootnote { \int_use:N \g_ceur_fnote_int }
+      \footnotetext { #2 }
+    }
+  }
+  {
+    \msg_term:n { [FN:~Number] }
+    \seq_gput_right:Nn \g_ceur_fnote_seq
+    {
+      \int_set:Nn \l_tmpa_int { #1 }
+      \tex_def:D \thefootnote { \int_use:N \l_tmpa_int }
+      \footnotetext { #2 }
+    }
+  }
+}
+
+\newcommand \printfnotes { \seq_use:Nn \g_ceur_fnote_seq { \par } }
+
+\seq_new:N \g_ceur_cor_seq
+\int_new:N \g_ceur_cor_int
+
+\NewDocumentCommand \cortext { O{} m }
+{
+  \tl_if_head_eq_catcode:nNTF { #1 } a
+  {
+    \msg_term:n { [COR:~alpha] }%
+    \seq_gput_right:Nn \g_ceur_cor_seq
+    { \int_incr:N \g_ceur_cor_int
+      \str_set:Nx \@currentlabel { \int_use:N \g_ceur_cor_int }
+      \ceurLabel { #1 }
+      \tex_def:D \thefootnote
+      { \int_case:nn { \g_ceur_cor_int }
+        {
+          { 1 } { $\ast$ }
+          { 2 } { $\ast\!\ast$ }
+          { 3 } { $\ast\!\ast\!\ast$ }
+        }
+      }
+      \footnotetext { #2 }
+    }
+  }
+  {
+    \msg_term:n { [COR:~Number] }
+    \seq_gput_right:Nn \g_ceur_cor_seq
+    {
+      \int_set:Nn \l_tmpa_int { #1 }
+      \tex_def:D \thefootnote
+      { \int_case:nn { \l_tmpa_int }
+        {
+          { 1 } { $\ast$ }
+          { 2 } { $\ast\!\ast$ }
+          { 3 } { $\ast\!\ast\!\ast$ }
+        }
+      }
+      \footnotetext { #2 }
+    }
+  }
+}
+
+\newcommand \printcornotes { \seq_use:Nn \g_ceur_cor_seq { \par } }
+
+\NewDocumentCommand \process@marks { }
+   {
+     \cs_if_free:cTF { mark@corau\theauthor }
+       { \ignorespaces }
+       { \str_set:Nx \l_tmpa_str { \use:c{ mark@corau\theauthor } }
+         \int_case:nn { \l_tmpa_str }
+           {
+             { 1 } { \sep$\ast$ }
+             { 2 } { \sep$\ast\ast$ }
+             { 3 } { \sep$\ast\!\ast\!\ast$ }
+           }
+           \tex_def:D \sep{\unskip,}
+         }
+      \cs_if_free:cTF { mark@fnau\theauthor }
+        { \ignorespaces }
+        { \sep\use:c { mark@fnau\theauthor }
+          \tex_def:D \sep{\unskip,}
+        }
+      }
+
+
+%%
+%% Author macros
+%%
+
+\seq_new:c { g_ceur_au0_seq }
+\seq_new:c { g_ceur_clau0_seq }
+\int_new:N \g_ceur_au_int
+\int_new:N \g_ceur_aau_int
+
+\NewDocumentCommand \ResetMarks { } {
+  \keys_set:nn { ceur / author } {
+    auid       = {} ,
+    bioid      = {} ,
+    alt        = {} ,
+    style      = { normal } ,
+    prefix     = {} ,
+    suffix     = {} ,
+    degree     = {} ,
+    role       = {} ,
+    orcid      = {} ,
+    collab     = { false }  ,
+    type       = { author } ,
+    anon       = { false }  ,
+    deceased   = { false }  ,
+    twitter    = {} ,
+    facebook   = {} ,
+    linkedin   = {} ,
+    plus       = {} ,
+    gplus      = {} ,
+    email      = {} ,
+    url        = {} ,
+  }
+  \tex_gdef:D \sep{}
+  \tex_gdef:D \ceur@corref{}
+  \tex_gdef:D \@fnmark {}
+}
+
+\int_new:N \l_autype_int
+\keys_define:nn { ceur / author } {
+  auid     .tl_set:N   = \l_ceur_au_id_tl             ,
+  bioid    .tl_set:N   = \l_ceur_au_bioid_tl          ,
+  alt      .tl_set:N   = \l_ceur_au_alt_tl            ,
+  style    .tl_set:N   = \l_ceur_au_style_tl          ,
+  prefix   .tl_set:N   = \l_ceur_au_prefix_tl         ,
+  suffix   .tl_set:N   = \l_ceur_au_suffix_tl         ,
+  degree   .tl_set:N   = \l_ceur_au_degree_tl         ,
+  role     .tl_set:N   = \l_ceur_au_role_tl           ,
+  orcid    .tl_set:N   = \l_ceur_au_orcid_tl          ,
+  collab   .bool_set:N = \l_ceur_au_collab_bool       ,
+  type     .multichoice:                              ,
+  type/author    .code:n = { \int_set:Nn \l_autype_int { 0 } },
+  type/editor    .code:n = { \int_set:Nn \l_autype_int { 1 } },
+  type/collab    .code:n = { \int_set:Nn \l_autype_int { 2 } },
+  type/anon      .code:n = { \int_set:Nn \l_autype_int { 3 } },
+  % type/collab    .bool_set:N = \l_ceur_au_collab_bool          ,
+  % type/anon      .bool_set:N = \l_ceur_au_anon_bool            ,
+  anon      .bool_set:N = \l_ceur_au_anon_bool        ,
+  deceased  .bool_set:N = \l_ceur_au_deceased_bool    ,
+  twitter   .tl_set:N   = \l_ceur_au_twitter_tl       ,
+  facebook  .tl_set:N   = \l_ceur_au_facebook_tl      ,
+  linkedin  .tl_set:N   = \l_ceur_au_linkedin_tl      ,
+  plus      .tl_set:N   = \l_ceur_au_gplus_tl         ,
+  gplus     .tl_set:N   = \l_ceur_au_gplus_tl         ,
+  email     .tl_set:N   = \l_ceur_au_email_tl         ,
+  %% prevent URL expansion (due ~ sign)
+  url       .code:n   = { \tl_set:Nn \l_ceur_au_url_tl { \exp_not:n { #1 } } },
+}
+
+\keys_set:nn { ceur / author } {
+  auid       = {} ,
+  bioid      = {} ,
+  alt        = {} ,
+  style      = { normal } ,
+  prefix     = {} ,
+  suffix     = {} ,
+  degree     = {} ,
+  role       = {} ,
+  orcid      = {} ,
+  collab     = { false }  ,
+  type       = { author } ,
+  anon       = { false }  ,
+  deceased   = { false }  ,
+  twitter    = {} ,
+  facebook   = {} ,
+  linkedin   = {} ,
+  plus       = {} ,
+  gplus      = {} ,
+  email      = {} ,
+  url        = {} ,
+}
+
+\keys_define:nn { ceur / ausetup } {
+  type      .choice: ,
+  type / authors .meta:n = {
+    size   =  \large         ,
+    shape  =  \upshape       ,
+    weight =  \mdseries      ,
+    before =  \bigskipamount ,
+    after  =  0pt            ,
+    align  =  \raggedright   ,
+    color  =  black          ,
+    lskip  =  0pt            ,
+    rskip  =  0pt            ,
+  } ,
+  type / collaboration .meta:n = {
+    size   =  \Large         ,
+    shape  =  \upshape       ,
+    weight =  \mdseries      ,
+    before =  \bigskipamount ,
+    after  =  0pt            ,
+    align  =  \raggedright   ,
+    color  =  black          ,
+    lskip  =  0pt            ,
+    rskip  =  0pt            ,
+  } ,
+  size      .tl_set:N    = \l_ceur_augroup_size_tl      ,
+  shape     .tl_set:N    = \l_ceur_augroup_shape_tl     ,
+  weight    .tl_set:N    = \l_ceur_augroup_weight_tl    ,
+  before    .dim_set:N   = \l_ceur_augroup_before_dim   ,
+  after     .dim_set:N   = \l_ceur_augroup_after_dim    ,
+  align     .tl_set:N    = \l_ceur_augroup_align_tl     ,
+  color     .tl_set:N    = \l_ceur_augroup_color_tl     ,
+  lskip     .dim_set:N   = \l_ceur_augroup_lskip_tl     ,
+  rskip     .dim_set:N   = \l_ceur_augroup_rskip_tl     ,
+}
+
+\DeclareDocumentCommand \ceurAuthorSetup { m } {
+  \keys_set:nn { ceur / ausetup } { #1 }
+}
+\DeclareDocumentCommand \ceurausetup { m } {
+  \tl_set:Nn \l_ceur_au_setup_tl {
+    \keys_set:nn { ceur / ausetup } { #1 } }
+}
+\DeclareDocumentCommand \ceurclbsetup { m } {
+  \tl_set:Nn \l_ceur_clb_setup_tl {
+    \keys_set:nn { ceur / ausetup } { #1 } }
+}
+
+\ceurausetup { }
+\ceurclbsetup { }
+
+\seq_new:N  \g_ceur_maltese_seq
+\seq_new:N  \g_ceur_facebook_seq
+\seq_new:N  \g_ceur_twitter_seq
+\seq_new:N  \g_ceur_gplus_seq
+\seq_new:N  \g_ceur_linkedin_seq
+
+\NewDocumentCommand \twitterauthor { m m } {
+  \seq_gput_right:Nn \g_ceur_twitter_seq {
+    \parsename { #2 }
+    \url{https://twitter.com/\tl_to_str:n{#1}}\space(\eadauthor)
+  }
+}
+\NewDocumentCommand \facebookauthor { m m }
+   {
+     \seq_gput_right:Nn \g_ceur_facebook_seq
+       {
+         \parsename { #2 }
+         \url{https://www.facebook.com/\tl_to_str:n{#1}}\space(\eadauthor) %
+       }
+     }
+\NewDocumentCommand \gplusauthor { m m }
+   {
+     \seq_gput_right:Nn \g_ceur_gplus_seq
+       {
+         \parsename { #2 }
+         \url{https://plus.google.com/\tl_to_str:n{#1}}\space(\eadauthor)%
+       }
+     }
+\NewDocumentCommand \linkedinauthor { m m }
+   {
+     \seq_gput_right:Nn \g_ceur_linkedin_seq
+       {
+         \parsename { #2 }
+         \url{https://www.linkedin.com/profile/view?id=\tl_to_str:n{#1}}%
+         \space(\eadauthor)
+       }
+     }
+
+\NewDocumentCommand \printmaltese { }
+    {
+      \seq_use:Nn { \g_ceur_maltese_seq } { }
+    }
+\NewDocumentCommand \printfacebook { }
+    {
+      \seq_if_empty:NTF \g_ceur_facebook_seq { }
+        {
+          \tex_def:D \thefootnote{}
+          \footnotetext
+          {
+            \bool_if:NTF \g_ceur_nologo_bool
+             { Facebook:\c_space_token }
+             { \faIcon{facebook-f}\c_space_token }
+            \seq_use:Nn \g_ceur_facebook_seq {,\c_space_token }
+          }
+        }
+      }
+\NewDocumentCommand \printtwitter { }
+    {
+      \seq_if_empty:NTF \g_ceur_twitter_seq { }
+        {
+          \tex_def:D \thefootnote{}
+          \footnotetext
+          {
+            \bool_if:NTF \g_ceur_nologo_bool
+             { Twitter:\c_space_token }
+             { \faIcon{twitter}\c_space_token }
+            \seq_use:Nn \g_ceur_twitter_seq {,\c_space_token }
+          }
+        }
+      }
+\NewDocumentCommand \printgplus { }
+    {
+      \seq_if_empty:NTF \g_ceur_gplus_seq { }
+        {
+          \tex_def:D \thefootnote{}
+          \footnotetext
+          {
+            \bool_if:NTF \g_ceur_nologo_bool
+             { Google+:\c_space_token }
+             { \faIcon{google-plus-g}\c_space_token }
+            \seq_use:Nn \g_ceur_gplus_seq {,\c_space_token }
+          }
+        }
+      }
+\NewDocumentCommand \printlinkedin { }
+    {
+      \seq_if_empty:NTF \g_ceur_linkedin_seq { }
+        {
+          \tex_def:D \thefootnote{}
+          \footnotetext
+          {
+            \bool_if:NTF \g_ceur_nologo_bool
+             { LinkedIn:\c_space_token }
+             { \faIcon{linkedin-in}\c_space_token }
+            \seq_use:Nn \g_ceur_linkedin_seq {,\c_space_token }
+          }
+        }
+      }
+
+\seq_new:N \g_ceur_prelimsau_seq
+
+\csxdef { infoauthors } { }
+\csgdef { pdfxauthors } { }
+
+\csgdef { __short_authors_tmp } { }
+% Number of person in short authors list
+\int_new:N \g_num_short_authors
+\g_num_short_authors = 1
+
+\cs_new:Nn \no_break_space: { \nobreak{~} \penalty 10000 }
+
+\RenewDocumentCommand \author { O{} m O{} } {
+  \ResetMarks
+  \tl_if_blank:nTF { #3 } { }
+  { \keys_set:nn { ceur / author } { #3 } }
+  % 
+  \int_gincr:N \g_ceur_au_int
+  \tex_gdef:D \theau@ { \int_use:N \g_ceur_au_int }
+  % 
+  \seq_gput_right:Nn \g_ceur_prelimsau_seq { #2 }
+  \bool_if:NTF \l_ceur_au_collab_bool
+  { \seq_gput_right:cn { g_ceur_clau\int_use:N \g_ceur_augr_int _seq } }
+  { \seq_gput_right:cn { g_ceur_au\int_use:N \g_ceur_augr_int _seq } }
+  {
+    \int_gincr:N \g_ceur_aau_int
+    \tex_gdef:D \theauthor {\int_use:N \g_ceur_aau_int }
+    \keys_set:nn { ceur / author } { #3 }
+    \tl_if_head_eq_catcode:nNTF { #1 } a
+    { \processAffRef { #1 } }
+    { \processAffNum { #1 } }
+    \tl_if_empty:NF \l_ceur_au_prefix
+    { \l_ceur_au_prefix_tl \c_space_token }
+    \str_if_eq:VnTF \l_ceur_au_style_tl  { chinese } {
+      % \msg_term:n {STYLE~T=\l_ceur_au_style_tl........}
+      \invparsename { #2 }
+      \textcolor{\l_ceur_augroup_color_tl}{\surname}
+      \no_break_space:
+      \textcolor{\l_ceur_augroup_color_tl !50}{\firstname}
+    }{
+      % \msg_term:n {STYLE~F=\l_ceur_au_style_tl........}
+      \parsename { #2 }
+      \textcolor{\l_ceur_augroup_color_tl !50}{\firstname}
+      \no_break_space:
+      \textcolor{\l_ceur_augroup_color_tl}{\surname}
+    }
+    \tl_if_empty:NF \l_ceur_au_suffix_tl
+    { \c_space_token \l_ceur_au_suffix_tl }
+    \unskip
+    \textsuperscript
+    {
+      \tl_if_blank:nTF { #1 }
+      { \tex_def:D \sep{} }
+      { {\itshape\listAff} \tex_def:D \sep{\unskip,} }
+      \process@marks
+      \bool_if:NT \l_ceur_au_deceased_bool
+      { \sep \maltese
+        \tex_def:D \sep { \unksip, }
+      }
+    }
+    \tl_if_empty:NF \l_ceur_au_degree_tl
+    { ,\c_space_token \l_ceur_au_degree_tl }
+    \tl_if_empty:NF \l_ceur_au_role_tl
+    { \c_space_token (\l_ceur_au_role_tl) }
+    % 
+    \ResetMarks
+  }
+  % 
+  \bool_if:NT \l_ceur_au_deceased_bool
+  {
+    \seq_gput_right:Nn \g_ceur_maltese_seq
+    {
+      \tex_def:D \thefootnote { \maltese }
+      \footnotetext{Deceased~author.}
+    }
+  }
+  \tl_if_empty:NF \l_ceur_au_email_tl {
+    \wrAux { \token_to_str:N \emailauthor
+      { \l_ceur_au_email_tl } { \exp_not:n {#2} } }
+  }
+  \tl_set:Nx \l_ceur_au_url_tl_tmp { \l_ceur_au_url_tl }
+  \tl_if_empty:NF \l_ceur_au_url_tl_tmp {
+    \wrAux { \token_to_str:N \urlauthor
+      { \l_ceur_au_url_tl } { \exp_not:n {#2} } }
+  }
+  % various social media
+  \tl_if_empty:NTF \l_ceur_au_facebook_tl { }
+  {
+    \wrAux { \token_to_str:N \facebookauthor
+      { \l_ceur_au_facebook_tl } { \exp_not:n {#2} } }
+  }
+  \tl_if_empty:NF \l_ceur_au_twitter_tl
+  {
+    \wrAux { \token_to_str:N \twitterauthor
+      { \l_ceur_au_twitter_tl } { \exp_not:n {#2} } }
+  }
+  \tl_if_empty:NF \l_ceur_au_gplus_tl
+  {
+    \wrAux { \token_to_str:N \gplusauthor
+      { \l_ceur_au_gplus_tl } { \exp_not:n {#2} } }
+  }
+  \tl_if_empty:NF \l_ceur_au_linkedin_tl
+  {
+    \wrAux { \token_to_str:N \linkedinauthor
+      { \l_ceur_au_linkedin_tl } { \exp_not:n {#2} } }
+  }
+  \tl_if_empty:NF \l_ceur_au_orcid_tl
+  {
+    \wrAux { \token_to_str:N \orcidauthor
+      { \l_ceur_au_orcid_tl } { \exp_not:n {#2} } }
+  }
+  % Short authors list
+  \csgdef { __short_authors_tmp } { #2 }
+  \int_compare:nNnTF { \theau@ } = { 1 } {
+    \xappto \__short_authors: { \__short_authors_tmp }
+  }{ 
+    \int_compare:nNnTF { \theau@ } < { \g_num_short_authors + 1 } {
+      \xappto \__short_authors: { , ~ \__short_authors_tmp }
+    }{
+      \int_compare:nNnTF { \theau@ } = { \g_num_short_authors + 1 } {
+        \xappto \__short_authors: { ~et~al. }
+      }{ }
+    }
+  }
+  % 
+  \@eadauthor={#2}
+  \pdfstringdef\__info_au: { #2 }
+  \int_compare:nNnTF { \theau@ } < { 4 }
+  { \xappto \infoauthors { \__info_au: , ~ } }
+  {
+    \int_compare:nNnTF { \theau@ } = { 4 }
+    { \xappto \infoauthors { et~al. } }
+    { }
+  }
+  % Authors list for PDF/A
+  \csgdef { __pdfxauthor } { #2 }
+  \int_compare:nNnTF { \theau@ } = { 1 }
+  { \xappto \pdfxauthors { \__pdfxauthor } }
+  { \xappto \pdfxauthors { \iow_char:N \\ sep ~ \__pdfxauthor } }
+}
+
+\NewDocumentCommand \ceurauthors { } {
+  \group_begin:
+  \ceurAuthorSetup { type = authors }
+  \l_ceur_au_setup_tl
+  \par \vskip\l_ceur_augroup_before_dim
+  \l_ceur_augroup_align_tl
+  \l_ceur_augroup_size_tl
+  \l_ceur_augroup_shape_tl
+  \l_ceur_augroup_weight_tl
+  \color{ \l_ceur_augroup_color_tl }
+  \bool_if:NTF \g_ceur_augr_bool
+  { \seq_use:Nn \g_ceur_augr_seq { \par } }
+  {
+    \seq_use:cnnn { g_ceur_au\int_use:N\g_ceur_augr_int _seq }
+    { ,~ } { ,~ } { ~and~ }
+  }
+  \par\vskip\l_ceur_augroup_after_dim
+  \group_end:
+}
+
+\seq_new:c { g_ceur_collab0_seq }
+\bool_new:N \g_ceur_in_clau_bool
+
+\NewDocumentCommand \ceurcollab { } {
+  \bool_if:NTF \g_ceur_augr_bool
+  { }
+  {
+    \group_begin:
+    \ceurAuthorSetup { type = collaboration }
+    \l_ceur_clb_setup_tl
+    \par \vskip \l_ceur_augroup_before_dim
+    \l_ceur_augroup_align_tl
+    \l_ceur_augroup_size_tl
+    \l_ceur_augroup_shape_tl
+    \l_ceur_augroup_weight_tl
+    \color{ \l_ceur_augroup_color_tl }
+    \seq_use:cn {g_ceur_collab\int_use:N \g_ceur_aaugr_int _seq} { }
+    \seq_use:cnnn {g_ceur_clau\int_use:N \g_ceur_aaugr_int _seq}
+    { ~and~ } { ,~ } { ~and~ }
+    \par \vskip \l_ceur_augroup_after_dim
+    \group_end:
+  }
+}
+
+\newenvironment{collaboration}[1][] {
+  \seq_gput_right:cn {g_ceur_collab\int_use:N \g_ceur_augr_int _seq}
+  { \textit{Collaboration:~} #1 \par \smallskip }
+}{
+}
+
+\NewDocumentCommand \dept  { m } { #1 }
+\NewDocumentCommand \divn  { m } { #1 }
+\NewDocumentCommand \aline { m } { #1 }
+\NewDocumentCommand \city  { m } { #1 }
+\NewDocumentCommand \cnty  { m } { #1 }
+\NewDocumentCommand \phone { m } { #1 }
+\NewDocumentCommand \fax   { m } { #1 }
+\NewDocumentCommand \aurl  { m } { #1 }
+
+\seq_new:c { g_ceur_aff0_seq }
+\int_new:N \g_ceur_aff_int
+\tl_new:N \l_addrtype_tl
+
+\keys_define:nn { ceur / address }
+   {
+     foot     .bool_gset:N  = \g_ceur_addr_foot_bool       ,
+     name     .tl_set:N    = \l_ceur_addr_name_tl          ,
+     type     .multichoice:                               ,
+      type/alt     .code:n = { \tl_set:Nn \l_ceur_addr_type_tl
+          { Alternate~address } }  ,
+      type/addl    .code:n = { \tl_set:Nn \l_ceur_addr_type_tl
+          { Additional~address } } ,
+      type/regular .code:n = { \tl_set:Nn \l_ceur_addr_type_tl
+          {  } } ,
+      type/custom  .code:n = { \tl_set:Nn \l_ceur_addr_type_tl
+          { \l_ceur_addr_name_tl } } ,
+   }
+\DeclareDocumentCommand \ceurAddrSetup { m  }
+   { \keys_set:nn { ceur / address } { #1 } }
+
+\keys_set:nn { ceur / address }
+{
+  foot       = { false }   ,
+  type       = { regular } ,
+  name       = { Alternate~address } ,
+}
+
+\cs_new:Nn \__reset_addr:
+{
+  \bool_gset_false:N \g_ceur_addr_foot_bool
+  \tl_set:Nn \l_ceur_addr_type_tl {  }
+  \tl_set:Nn \l_ceur_addr_name_tl { Alternate~address }
+}
+
+\seq_new:N \g_ceur_aff_foot_seq
+
+\NewDocumentCommand \printaddrinfoot { }
+{
+  { \seq_use:Nn \g_ceur_aff_foot_seq { \par } }
+}
+
+\NewDocumentCommand \address { O{} m O{} }
+{
+  \__reset_addr:
+  \keys_set:nn { ceur / address } { #3 }
+  \bool_if:NTF \g_ceur_addr_foot_bool
+  { \__foot_address:nnn [#1]{#2}[#3] }
+  {
+    \seq_gput_right:cn { g_ceur_aff\int_use:N \g_ceur_augr_int _seq }
+    { \tl_if_blank:nTF { #1 }
+      {
+        \tex_xdef:D \thefootnote{}
+        { #2 }
+      }
+      {
+        \tl_if_head_eq_catcode:nNTF { #1 } a
+        {
+          \int_gincr:N \g_ceur_aff_int
+          \tex_xdef:D \@currentlabel
+          %% label format:
+          %% \int_to_arabic:n
+          %% \int_to_alph:n
+          %% \int_to_symbols:nnn
+          %% \int_to_roman:n
+          { \int_to_arabic:n { \int_use:N \g_ceur_aff_int } }
+          \ceurLabel {#1}
+          \textsuperscript{\itshape\@currentlabel} #2
+        }
+        {
+          \int_gset:Nn \g_ceur_aff_int { #1 }
+          \tex_xdef:D \@currentlabel
+          { \int_to_arabic:n {  \int_use:N \g_ceur_aff_int } }
+          \textsuperscript{\itshape\@currentlabel} #2
+        }
+      }
+    }
+  }
+}
+
+\cs_new:Npn \__foot_address:nnn [#1]#2[#3]
+{
+  \keys_set:nn { ceur / address } { #3 }
+  \seq_gput_right:cn { g_ceur_aff_foot_seq }
+  {
+    \tl_if_empty:nTF { #1 }
+    {
+      \tl_if_empty:NTF \l_ceur_addr_type_tl
+      { \footnotetext{#2} }
+      {
+        \footnotetext{\textit{\l_ceur_addr_type_tl}:
+          \c_space_token #2 }
+      }
+    }
+    {
+      \tl_if_head_eq_catcode:nNTF { #1 } a
+      %
+      {
+        \tex_def:D \thefootnote{\itshape\@currentlabel}
+        \tl_if_empty:NTF \l_ceur_addr_type_tl
+        { \footnotetext{#2} }
+        { \footnotetext{\textit{\l_ceur_addr_type_tl}: \c_space_token #2} }
+      }
+      {
+        \tex_def:D \thefootnote { \itshape\int_to_arabic:n { #1 } }
+        \tl_if_empty:NTF \l_ceur_addr_type_tl
+        { \footnotetext{#2} }
+        { \footnotetext{\textit{\l_ceur_addr_type_tl}:
+            \c_space_token #2 } }
+      }
+    }
+  }
+}
+
+\keys_define:nn { ceur / affsetup }
+   {
+     type      .choice: ,
+     type / normal .code:n =
+       { \tl_set:Nn \l_ceur_aff_type_tl { 0 } } ,
+     type / nonum .code:n =
+       { \tl_set:Nn \l_ceur_aff_type_tl { 1 } } ,
+
+     size      .tl_set:N    = \l_ceur_aff_size_tl      ,
+     shape     .tl_set:N    = \l_ceur_aff_shape_tl     ,
+     weight    .tl_set:N    = \l_ceur_aff_weight_tl    ,
+     before    .dim_set:N   = \l_ceur_aff_before_dim   ,
+     after     .dim_set:N   = \l_ceur_aff_after_dim    ,
+     align     .tl_set:N    = \l_ceur_aff_align_tl     ,
+     color     .tl_set:N    = \l_ceur_aff_color_tl     ,
+     lskip     .dim_set:N   = \l_ceur_aff_lskip_dim    ,
+     rskip     .dim_set:N   = \l_ceur_aff_rskip_dim    ,
+   }
+
+\DeclareDocumentCommand \ceurAffSetup { m }
+   { \keys_set:nn { ceur / affsetup } { #1 } }
+\DeclareDocumentCommand \ceuraffsetup { m }
+   { \tl_set:Nn \l_ceur_aff_setup_tl
+     { \keys_set:nn { ceur / affsetup } { #1 } }
+   }
+\ceuraffsetup {
+    size   = \footnotesize,
+    shape  = \itshape,
+    color  = black,
+    before = 0pt,
+    weight = \mdseries,
+    align  = \raggedright,
+    }
+
+\NewDocumentCommand \ceuraddress { }
+   {
+     \bool_if:NTF \g_ceur_augr_bool
+     { }
+     {
+       \group_begin:
+       \ceurAffSetup { type = normal }
+       \l_ceur_aff_setup_tl
+       \par \vskip\l_ceur_aff_before_dim
+       \l_ceur_aff_align_tl
+       \l_ceur_aff_size_tl
+       \l_ceur_aff_shape_tl
+       \l_ceur_aff_weight_tl
+       \color{ \l_ceur_aff_color_tl }
+       \seq_use:cn { g_ceur_aff\int_use:N \g_ceur_aaugr_int _seq }
+       { \par\vskip2pt  }
+       \par\vskip\l_ceur_aff_after_dim
+       \group_end:
+     }
+   }
+
+\int_new:N \g_ceur_augr_int
+\seq_new:N \g_ceur_augr_seq
+\int_new:N \g_ceur_aaugr_int
+\bool_new:N \g_ceur_augr_bool
+
+\NewDocumentEnvironment { augroup } { }
+{
+  \bool_gset_true:N \g_ceur_augr_bool
+  \int_gincr:N \g_ceur_augr_int
+  \seq_new:c {g_ceur_au\int_use:N \g_ceur_augr_int _seq}
+  \seq_new:c {g_ceur_aff\int_use:N \g_ceur_augr_int _seq}
+  \seq_new:c {g_ceur_collab\int_use:N \g_ceur_augr_int _seq}
+  \seq_new:c {g_ceur_clau\int_use:N \g_ceur_augr_int _seq}
+  \msg_term:n { AUGR:~\int_use:N \g_ceur_augr_int ... }
+}
+{
+  \seq_gput_right:Nn \g_ceur_augr_seq
+  {
+    \int_gincr:N \g_ceur_aaugr_int
+    \group_begin:
+    \ceurAuthorSetup { type = collaboration }
+    \l_ceur_clb_setup_tl
+    \par \vskip \l_ceur_augroup_before_dim
+    \l_ceur_augroup_align_tl
+    \l_ceur_augroup_size_tl
+    \l_ceur_augroup_shape_tl
+    \l_ceur_augroup_weight_tl
+    \color{ \l_ceur_augroup_color_tl }
+    \seq_use:cnnn { g_ceur_au\int_use:N \g_ceur_aaugr_int _seq }
+    { ~and~ } { ,~ } { ~and~ }
+    \par \vskip \l_ceur_augroup_after_dim
+    \group_end:
+    %
+    \group_begin:
+    \ceurAffSetup { type = normal }
+    \l_ceur_aff_setup_tl
+    \par \vskip\l_ceur_aff_before_dim
+    \l_ceur_aff_align_tl
+    \l_ceur_aff_size_tl
+    \l_ceur_aff_shape_tl
+    \l_ceur_aff_weight_tl
+    \color{ \l_ceur_aff_color_tl }
+    \seq_use:cn { g_ceur_aff\int_use:N \g_ceur_aaugr_int _seq }
+    { \par \smallskip }
+    \par\vskip\l_ceur_aff_after_dim
+    \msg_term:n { AAUGR:~\int_use:N \g_ceur_aaugr_int ... }
+    \group_end:
+    %
+    \group_begin:
+    \ceurAuthorSetup { type = collaboration }
+    \l_ceur_clb_setup_tl
+    \par \vskip \l_ceur_augroup_before_dim
+    \l_ceur_augroup_align_tl
+    \l_ceur_augroup_size_tl
+    \l_ceur_augroup_shape_tl
+    \l_ceur_augroup_weight_tl
+    \color{ \l_ceur_augroup_color_tl }
+    \seq_use:cn {g_ceur_collab\int_use:N \g_ceur_aaugr_int _seq} { }
+    \seq_use:cnnn {g_ceur_clau\int_use:N \g_ceur_aaugr_int _seq}
+    { ~and~ } { ,~ } { ~and~ }
+    \par\vskip \l_ceur_augroup_after_dim
+    \group_end:
+  }
+}
+
+%%
+%% Abstract
+%%
+
+\RequirePackage{moreverb}
+
+\tl_new:N \l_ceur_abs_title_tl
+\box_new:N \g_ceur_abs_box
+
+\tex_gdef:D \abstractname { \textbf{\sffamily Abstract} }
+
+\NewDocumentEnvironment { Abstract } { o } {
+  % \global\setbox \g_ceur_abs_box = \vtop \bgroup
+  % \hsize = .65 \textwidth \parindent \z@
+  \group_begin:
+  % Check if abstract exist
+  \file_if_exist:nT { \jobname.abs } { 
+    \IfNoValueTF { #1 } {
+    } { \tex_gdef:D \abstractname { #1 } }
+    \parindent \z@
+    \leftskip = .1 \textwidth
+    % \box_if_empty:NTF \g_ceur_key_box
+    % { \leftskip = .1 \textwidth }
+    % {
+    % \dim_gset:Nn \l_tmpa_dim { \box_ht:N \g_ceur_key_box }
+    % \dim_gadd:Nn \l_tmpa_dim { \box_dp:N \g_ceur_key_box }
+    % \leftskip .1\textwidth
+    % \hspace*{-.1 \textwidth }
+    % \noindent\hbox_to_wd:nn {  \z@ } { \box \g_ceur_key_box }
+    % \skip_vertical:n { - \l_tmpa_dim }
+    % }
+    \skip_vertical:n { \baselineskip }
+    \noindent \abstractname \par
+    % \skip_vertical:n { -4pt}
+    % \noindent \rule{.65\textwidth}{.2pt}\par
+    \footnotesize
+    \ignorespaces \everypar { \parindent=1.5em }
+  } { }
+} {
+  \par
+  \noindent\hbox_to_wd:nn { \z@ } { \box \g_ceur_key_box }
+  \par \group_end:
+}
+
+\NewDocumentEnvironment { PrelimsAbstract } { O{} } {
+  \parindent=0pt
+  { \fontsize{14pt}{16pt}\selectfont #1 }\par
+  \vskip12pt
+  { \fontsize{12pt}{14pt}\bfseries\selectfont\casprelimstitle } \par
+  \vskip6pt
+  \seq_use:Nn \g_ceur_prelimsau_seq { , }
+  \vskip12pt
+  \par
+} { }
+
+\RenewDocumentEnvironment { abstract } { o } {
+  \IfNoValueTF { #1 } {
+  } { \tex_gdef:D \abstracttitle { #1 } }
+  \verbatimwrite{\jobname.abs}
+} { \endverbatimwrite }
+
+\newbox\casgrabsbox
+\newbox\casauhlbox
+\newbool { usecasgrabsbox }
+\newbool { usecashlsbox }
+
+\DeclareDocumentEnvironment { graphicalabstract } { O{Graphical~Abstract} } {
+  \global \booltrue { usecasgrabsbox }
+  \global\setbox\casgrabsbox=\vbox\bgroup
+  \begin{PrelimsAbstract}[#1]
+  \noindent \ignorespaces
+} {
+  \end{PrelimsAbstract}
+  \egroup
+}
+
+\DeclareDocumentEnvironment { highlights } { O{Highlights} } {
+  \global \booltrue { usecashlsbox }
+  \global\setbox\casauhlbox=\vbox\bgroup
+  \begin{PrelimsAbstract}[#1]
+  \noindent \ignorespaces
+  \begin{itemize}
+} {
+  \end{itemize}
+  \end{PrelimsAbstract}
+  \egroup
+}
+
+\NewDocumentCommand \dashrule { O{.4pt} m m }
+   {
+     % \color{black!50}
+     \skip_vertical:n { #2 }
+     % \noindent \rule { \linewidth } { #1}
+     \normalcolor \skip_vertical:n { #3 }
+   }
+
+\NewDocumentCommand \keywordtitle { } { Keywords }
+\NewDocumentCommand \keywordtitlesep { } {:\c_space_token }
+\box_new:N \g_ceur_key_box
+
+\NewDocumentCommand \MSC { O{} m }
+   {
+     \par\noindent \textit { #1\c_space_token MSC:\c_space_token } #2
+   }
+\NewDocumentCommand \JEL { m }
+   {
+     \par\noindent \textit { JEL:\c_space_token } #1
+   }
+\NewDocumentCommand \PACS { m }
+   {
+     \par\noindent \textit { PACS:\c_space_token } #1
+   }
+
+\NewDocumentEnvironment { keywords } { O{ Keywords } } {
+  \tex_global:D \tex_setbox:D \g_ceur_key_box = \vtop \bgroup
+  \hsize=.9 \textwidth
+  \vspace*{0pt}
+  \cs_new:Nn \sep: {\unskip,~}
+  \cs_set_eq:NN \sep \sep:
+  \parindent \z@
+
+  % A\,R\,T\,I\,C\,L\,E\ \ I\,N\,F\,O \par \skip_vertical:n { -3pt }
+  % \rule{.25 \textwidth}{.2pt}\par
+  \noindent \textbf {\sffamily #1 }  \par
+  \footnotesize
+}{
+  \skip_vertical:n { \baselineskip }
+  \egroup
+}
+
+%% Acknowledgments
+
+\NewDocumentEnvironment { acknowledgments } { }
+{
+  \group_begin:
+  \section*{Acknowledgments}
+}
+{ \group_end: }
+
+
+%% Copyright
+
+\def\copyrightyear#1{\def\@copyrightyear{#1}}
+\copyrightyear{\the\year}
+
+\DeclareRobustCommand\copyrightclause[1]{%
+  \def\@copyrightclause{#1}%
+}
+\let\@copyrightclause\@empty
+% \copyrightclause{\textcolor{red}{Author: Please provide a copyright holder}}
+
+
+%% CC-BY logo width
+\newdimen\ccLogoWidth
+
+\def\@copyrightLine{%
+  \setbox\@tempboxa\hbox{\includegraphics[height=\baselineskip,clip]{cc-by}}%
+  \ccLogoWidth=\dimexpr\wd\@tempboxa
+  \@rightskip\@flushglue \rightskip\@rightskip
+  % \hangindent\dimexpr\wd\@tempboxa+0.5em\relax
+  \begin{minipage}[c]{\ccLogoWidth}
+    \href{https://creativecommons.org/licenses/by/4.0}%
+    {\lower\baselineskip\hbox{\unhcopy\@tempboxa}}\enskip
+  \end{minipage}
+  \enskip
+  \begin{minipage}[c]{\linewidth - \ccLogoWidth - 2\footnotemargin}
+    \tiny
+    \textcopyright\ \@copyrightyear\ %
+    \ifx\@copyrightclause\@empty%
+      \textcolor{red}{Author: Please fill in the \string\copyrightclause\space macro}%
+    \else\@copyrightclause%
+    \fi
+  \end{minipage}
+}
+
+\RequirePackage{calc}
+
+\def\@ceurLogoLine{%
+  % set width of ceur-ws logo equals to width of cc-by logo
+  \setbox\@tempboxa\hbox{\includegraphics[height=\baselineskip,clip]{cc-by}}%
+  \ccLogoWidth=\dimexpr\wd\@tempboxa
+  \setbox\@tempboxa\hbox{\includegraphics[width=\ccLogoWidth,clip]{ceur-ws-logo}}
+  \@rightskip\@flushglue \rightskip\@rightskip
+  % \hangindent\dimexpr\wd\@tempboxa+0.5em\relax
+  \begin{minipage}[c]{\ccLogoWidth}
+    \href{http://ceur-ws.org}%
+    % {\lower\baselineskip\hbox{\unhcopy\@tempboxa}}\enskip
+    {\hbox{\unhcopy\@tempboxa}}
+  \end{minipage}
+  \enskip
+  \begin{minipage}[c]{\linewidth - \ccLogoWidth - 2\footnotemargin}
+    {CEUR~Workshop~Proceedings~(\href{http://ceur-ws.org}{CEUR-WS.org})}%
+  \end{minipage}
+}
+
+\seq_new:N \g_ceur_logonote_seq
+
+\NewDocumentCommand \logonote { m }
+{
+  \group_begin:
+  \seq_gput_right:Nn \g_ceur_logonote_seq
+  {
+    \tex_def:D \thefootnote { }
+    \footnotetext{%
+      \raggedright
+      \hspace*{-\parindent}
+      % \hspace*{-\labelsep}
+      \hspace*{-\footnotemargin}
+      #1}
+  }
+  \group_end:
+}
+
+\newcommand \printlogonotes { \seq_use:Nn \g_ceur_logonote_seq { \par } }
+
+%
+% Print all footnotes in the title page
+%
+
+\bool_new:N \g_ceur_longmktitle_bool
+\int_new:N \g_ceur_jtype_int
+\int_new:N \g_ceur_blind_int
+
+\NewDocumentCommand \printFirstPageNotes { } {
+  \bool_if:NTF \g_ceur_longmktitle_bool {
+    \tex_let:D \columnwidth = \textwidth
+  } { }
+  \int_compare:nTF { \g_ceur_jtype_int > 5 } {
+    \ceuraddress
+  } { }
+  \printtnotes
+  \printnonumnotes
+  \bool_if:NTF \g_ceur_blind_bool {
+  } {
+    \printcornotes
+    \printmaltese
+    \printaddrinfoot
+    \printemails
+    \printurls
+    \printorcid
+    \printfacebook
+    \printtwitter
+    \printgplus
+    \printlinkedin
+    \printfnotes
+  }
+  \printlogonotes
+  \bool_if:NTF \g_ceur_longmktitle_bool {
+    \if@twocolumn
+      \tex_let:D \columnwidth = \Columnwidth \fi
+  } { }
+  \normalcolor
+}
+
+%
+% Date History
+%
+\tl_new:N \g_ceur_recd_tl
+\tl_new:N \g_ceur_accd_tl
+\tl_new:N \g_ceur_revd_tl
+\tl_new:N \g_ceur_pub_online_tl
+\tl_new:N \g_ceur_pub_print_tl
+
+\cs_new:Npn \date_parse:n #1 { \date_parse_aux:w #1 \q_stop }
+\cs_new:Npn \date_parse_aux:w #1 / #2 / #3 \q_stop
+{ <do something with the date> }
+
+\NewDocumentCommand \received { m }
+    { \tl_gput_right:Nn \g_ceur_recd_tl { #1 } }
+\NewDocumentCommand \accepted { m }
+    { \tl_gput_right:Nn \g_ceur_accd_tl { #1 } }
+\NewDocumentCommand \revised { m }
+    { \tl_gput_right:Nn \g_ceur_revd_tl { #1 } }
+\NewDocumentCommand \published { O{} m }
+{
+  \tl_if_eq:nnTF { #1 } { online }
+  { \tl_if_gput_right:Nn \g_ceur_pub_online_tl { #2 } }
+  { \tl_if_gput_right:Nn \g_ceur_pub_print_tl { #2 } }
+}
+
+%
+% Verse/Recto
+%
+\tl_new:N \l_ceur_verso_tl
+\tl_new:N \l_ceur_recto_tl
+
+\NewDocumentCommand \verso { m }
+{ \tl_set:Nn \l_ceur_verso_tl { #1 } }
+\NewDocumentCommand \recto { m }
+{ \tl_set:Nn \l_ceur_recto_tl { #1 } }
+
+%
+% Maketitle
+%
+
+\newcounter{au}
+\newcounter{cnote}
+\newcounter{tnote}
+\newcounter{fnote}
+\newcounter{aff}
+
+\cs_new:Nn \__reset_title_counters:
+{
+  \setcounter{cnote}{0}
+  \setcounter{fnote}{0}
+  \setcounter{tnote}{0}
+  \setcounter{footnote}{0}
+}
+
+\keys_define:nn { ceur / mktitle }
+{
+  blind        .bool_gset:N     = \g_ceur_blind_bool        ,
+  footer       .multichoice:,
+       footer/default  .tl_gset:N  = \g_ceur_footer_default_tl ,
+       footer/custom   .tl_gset:N  = \g_ceur_footer_custom_tl  ,
+  longtitle     .bool_gset:N    = \g_ceur_longtitle_bool    ,
+  longabstract  .bool_gset:N    = \g_ceur_longtitle_bool    ,
+  breakafter    .clist_gset:N   = \g_ceur_breakafter_clist  ,
+  nologo        .bool_gset:N    = \g_ceur_nologo_bool       ,
+}
+
+\bool_new:N \g_ceur_breakafter_title_bool
+\bool_new:N \g_ceur_breakafter_auaff_bool
+\bool_new:N \g_ceur_breakafter_abstract_bool
+
+\NewDocumentCommand \processbreakafter { }
+{
+  \clist_if_empty:NTF \g_ceur_breakafter_clist { }
+  {
+    \clist_map_inline:Nn \g_ceur_breakafter_clist
+    { \bool_gset_true:c { g_ceur_breakafter_##1_bool } }
+  }
+}
+
+\NewDocumentCommand \pprintMaketitle { O{} }
+{
+  \tl_if_blank:nTF { #1 } { }
+  { \keys_set:nn { ceur / mktitle } { #1 } }
+  \processbreakafter
+  \clearpage
+  \__reset_title_counters:
+  \tex_def:D \baselinestretch { 1 }
+  \printFirstPageNotes
+  \thispagestyle{pprintTitle}%
+  \group_begin:
+  \@title
+  \group_end:
+  \bool_if:NTF \g_ceur_breakafter_title_bool
+  { \newpage } { }
+  %
+  \bool_if:NTF \g_ceur_blind_bool
+  { \vspace* { 10 mm } }
+  {
+    \group_begin:
+    \normalsize \ceurauthors \par
+    \ceurcollab \par
+    \footnotesize \itshape \ceuraddress \par \vskip36pt
+    \group_end:
+    \bool_if:NTF \g_ceur_breakafter_auaff_bool
+    { \newpage } { }
+  }
+  %
+  \printabsbox
+  \printkeybox
+  \bool_if:NTF \g_ceur_breakafter_abstract_bool
+  { \newpage } { }
+  %
+  \setcounter{footnote}{\c@fnote}
+  \tex_gdef:D \thefootnote { \arabic{footnote} }
+  \tex_def:D \baselinestretch { \@blstr }
+  \normalfont \normalsize
+}
+
+\NewDocumentCommand \MaketitleBox { } {
+  \tex_def:D \baselinestretch{1}
+  \group_begin:
+  \@title
+  \group_end:
+  % 
+  \bool_if:NTF \g_ceur_blind_bool {
+    \vspace* { 10 mm }
+  } {
+    \group_begin:
+    \normalsize \ceurauthors \par
+    \ceurcollab \par
+    \footnotesize \itshape \ceuraddress \par
+    \group_end:
+    \bool_if:NTF \g_ceur_breakafter_auaff_bool
+    { \newpage } { }
+  }
+  % \printFirstPageNotes
+  %
+  \dashrule{0pt}{3pt}
+  \begin{Abstract}
+    \noindent \ignorespaces
+    \file_if_exist:nT { \jobname.abs } { \file_input:n { \jobname.abs } }
+  \end{Abstract}
+  \dashrule{6pt}{3pt}
+  \bool_if:NTF \g_ceur_breakafter_abstract_bool
+  { \newpage } { }
+}
+
+\box_new:N \g_ceur_notes_box
+\box_new:N \g_ceur_front_box
+\cs_set:Npn \__fn_text:n #1
+{ \group_begin:\vbox_top:n { \footnotesize #1 } \group_end:\par}
+
+\NewDocumentCommand \LongMaketitleBox { }
+{
+  \vbox_gset:Nn \g_ceur_front_box
+  {
+    \tex_def:D \baselinestretch{1}
+    \group_begin:
+    \@title
+    \group_end:
+    %
+    \group_begin:
+    \normalsize \ceurauthors \par
+    \ceurcollab \par
+    \footnotesize \itshape \ceuraddress \par
+    \group_end:
+  %
+  \dashrule{0pt}{3pt}
+  \begin{Abstract}
+    \noindent \ignorespaces
+    \file_if_exist:nT { \jobname.abs } { \file_input:n { \jobname.abs } }
+  \end{Abstract}
+  \dashrule{3pt}{3pt}
+  }
+  \vbox_gset:Nn \g_ceur_notes_box
+  {  \cs_set_eq:NN \footnotetext \__fn_text:n  \printFirstPageNotes }
+   \dim_gset:Nn \g_tmpb_dim { \box_ht:N \g_ceur_notes_box }
+   % \iow_term:x { ...~[ht: \dim_use:N \g_tmpb_dim  ] }
+   \dim_gadd:Nn \g_tmpb_dim { \box_dp:N \g_ceur_notes_box }
+   % \iow_term:x { ...~[ht+dp: \dim_use:N \g_tmpb_dim  ] }
+   \ifbool{sc}{\dim_gadd:Nn \g_tmpb_dim { 12pt } } { }
+
+}
+
+\NewDocumentCommand \ProcessLongTitleBox { }
+{
+  % \vbox_gset:Nn \g_ceur_notes_box
+  % {  \cs_set_eq:NN \footnotetext \__fn_text:n \printFirstPageNotes }
+  %  \dim_gset:Nn \g_tmpb_dim { \box_ht:N \g_ceur_notes_box }
+  % % \iow_term:x { ...~[ht: \dim_use:N \g_tmpb_dim  ] }
+  %  \dim_gadd:Nn \g_tmpb_dim { \box_dp:N \g_ceur_notes_box }
+  % % \iow_term:x { ...~[ht+dp: \dim_use:N \g_tmpb_dim  ] }
+  %
+  \dim_gset:Nn \g_tmpa_dim { \textheight }
+%  \vbox_unpack:N \g_ceur_notes_box
+  % \iow_term:x { ...~[tmpa:~ \dim_use:N \g_tmpa_dim ] }
+  % \dim_gsub:Nn \g_tmpa_dim { \box_ht:N \g_ceur_notes_box }
+  % \iow_term:x { ...~[tmpa-noteht:~ \dim_use:N \g_tmpa_dim ] }
+  % \dim_gsub:Nn \g_tmpa_dim { \box_dp:N \g_ceur_notes_box }
+  % \iow_term:x { ...~[tmpa-notedp:~ \dim_use:N \g_tmpa_dim ] }
+  \dim_gsub:Nn \g_tmpa_dim { \g_tmpb_dim }
+  \vbox_set_split_to_ht:NNn \g_tmpb_box \g_ceur_front_box { \g_tmpa_dim }
+  \noindent \vbox_unpack_clear:N \g_tmpb_box
+  \printFirstPageNotes
+  \dim_gzero:N \g_tmpa_dim
+  \dim_gset:Nn \g_tmpa_dim { \box_ht:N \g_ceur_front_box }
+  % \iow_term:x { ...~[tmpa-ht:~ \dim_use:N \g_tmpa_dim ] }
+  \dim_gadd:Nn \g_tmpa_dim { \box_dp:N \g_ceur_front_box }
+  % \iow_term:x { ...~[tmpa-ht+dp:~ \dim_use:N \g_tmpa_dim ~+~\the\textheight] }
+  \dim_compare:nNnTF { \dim_use:N \g_tmpa_dim } > { \the\textheight }
+  {
+    \vbox_set_split_to_ht:NNn \g_tmpb_box \g_ceur_front_box { \textheight }
+    \vbox_unpack_clear:N \g_tmpb_box
+    \ifbool{dc}
+    { \twocolumn[{\vbox_unpack_clear:N \g_ceur_front_box}] }
+    { \vbox_unpack_clear:N \g_ceur_front_box }
+  }
+  {
+    \ifbool{dc}
+    { \twocolumn[{\vbox_unpack_clear:N \g_ceur_front_box}] }
+    { \vbox_unpack_clear:N \g_ceur_front_box }
+  }
+ \normalcolor \normalfont
+}
+\ExplSyntaxOff
+
+%
+% Headings
+%
+\def\@seccntDot{.}
+\def\@seccntformat#1{\csname the#1\endcsname\@seccntDot\hskip 0.5em}
+
+\newdimen\paraindent     \paraindent=\parindent
+\newdimen\subparaindent  \subparaindent=\parindent
+\def\ssssparaindent{}
+\def\sectionfont{\rmfamily\fontsize{12pt}{14pt}%
+  \bfseries}
+\def\ssectionfont{\rmfamily\fontsize{11pt}{13pt}%
+  \bfseries\selectfont}
+\def\sssectionfont{\rmfamily\fontsize{10.5pt}{12pt}%
+  \fontseries{b}\fontshape{it}\selectfont}
+\def\ssssectionfont{\rmfamily\fontsize{11pt}{10pt}\itshape\selectfont}
+\def\sssssectionfont{\rmfamily\fontsize{11pt}{10pt}\selectfont}%
+
+\AtBeginDocument{\global\@afterindentfalse}
+
+% \renewcommand\section{\@startsection{section}{1}{\z@}%
+%     {15pt \@plus 3\p@ \@minus 3\p@}%
+%     {4\p@}%
+%     {%\let\@hangfrom\relax
+%      \sectionfont\raggedright\hst[13pt]}}
+
+% \renewcommand\subsection{\@startsection{subsection}{2}{\z@}%
+%     {10pt \@plus 3\p@ \@minus 2\p@}%
+%     {.1\p@}%
+%     {%\let\@hangfrom\relax
+%      \ssectionfont\raggedright }}
+
+% \renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}%
+%     {10pt \@plus 1\p@ \@minus .3\p@}%
+%     {.1\p@}%
+%     {%\let\@hangfrom\relax
+%      \sssectionfont\raggedright}}
+
+% \renewcommand\paragraph{\@startsection{paragraph}{4}{\parindent}%
+%     {10pt \@plus0.01pt \@minus0.01pt}%
+%     {-6pt}%
+%     {\ssssparaindent%
+%      \ssssectionfont\itshape\raggedright}}
+
+% \renewcommand\subparagraph{\@startsection{subparagraph}{5}{\parindent}%
+%     {0pt \@plus0.1pt \@minus0.1pt}%
+%     {-6pt}%
+%     {\hspace*{\subparaindent}
+%      \sssssectionfont\raggedright}}
+
+\def\thesubsection{\thesection.\arabic{subsection}}
+\def\thesubsubsection{\thesubsection.\arabic{subsubsection}}
+
+%
+% Sundry lengths
+%
+\def\xstrut#1#2{\vrule height#1 depth #2 width\z@}
+\def\hstrut#1{\vrule height#1 depth \z@ width 0pt}
+\def\dstrut#1{\vrule height0pt depth#1 width 0pt}
+\def\hst[#1]{\vrule height#1 depth \z@ width \z@}
+\def\dst[#1]{\vrule height0pt depth#1 width 0pt}
+\def\xst[#1][#2]{\vrule height#1 depth #2 width\z@}
+
+\def\lastpage{100}
+
+\AtEndDocument{%
+%   \clearpage
+   \immediate\write\@auxout{\string\csxdef{lastpage}{\thepage}}
+}
+
+\ExplSyntaxOn
+
+%
+% pagestyle
+%
+
+\RequirePackage{scrlayer-scrpage}
+\clearpairofpagestyles
+
+\setkomafont{pageheadfoot}{\sffamily\small}
+% \setkomafont{pagehead}{\sffamily\small}
+
+\bool_if:NTF \g_ceur_hf_bool {
+  \KOMAoptions{headsepline}
+  % \ofoot[Page~ \thepage {} ~of~ \lastpage]{Page~ \thepage {} ~of~ \lastpage}
+  % \ifoot[\__short_authors: :~ { \rmfamily \itshape CEUR~Workshop~Proceedings}]{\__short_authors: :~ { \rmfamily \itshape CEUR~Workshop~Proceedings}}
+  % \ohead[]{\__short_title:}
+  \cfoot[\thepage]{\thepage}
+  \ohead[]{\firstpage--\lastpage}
+  \ihead[]{\__short_authors:{} ~ { \rmfamily \itshape CEUR~Workshop~Proceedings}}
+}{ }
+
+% \newcommand{\hffont}{\sffamily\small}
+
+% \RequirePackage{scrlayer-fancyhdr}
+
+% \fancypagestyle{first}{%
+%   \fancyhf{}%
+%   \renewcommand{\headrulewidth}{\z@}%
+%   \renewcommand{\footrulewidth}{\z@}%
+%   \fancyfoot[R]{\hffont Page~ \thepage {} ~of~ \lastpage}%
+%   \fancyfoot[L]{\hffont \__short_authors: :~ { \rmfamily \itshape CEUR~Workshop~Proceedings}}%
+% }  
+
+% \fancypagestyle{standard}{%
+%   \fancyhf{}%
+%   \renewcommand{\headrulewidth}{\z@}%
+%   \renewcommand{\footrulewidth}{\z@}%
+%   \fancyfoot[R]{\hffont Page~ \thepage {} ~of~ \lastpage}%
+%   \fancyfoot[L]{\hffont \__short_authors: :~ { \rmfamily \itshape CEUR~Workshop~Proceedings}}%
+%   \fancyhead[L]{\hffont \__short_title:}%
+% }  
+
+\cs_new:Npn \__first_footerline: {
+  \group_begin:
+  \small \sffamily
+  \__short_authors: :~
+  { \rmfamily \itshape CEUR~Workshop~Proceedings }
+  \group_end:
+}
+
+\cs_new:Npn \__first_head: {
+  \parbox[t]{\textwidth}
+  {
+    \color{black!20}
+    \rule{\textwidth}{0pt}
+  }
+}
+
+\cs_new:Npn \__first_foot: {
+  \parbox[t]{\textwidth} {
+    % \rule{\textwidth}{.2pt}\\
+    \sffamily\small
+    \__first_footerline:
+    \hfill Page~ \thepage {} ~of~ \lastpage
+  }
+}
+
+\cs_new:Npn \__ceur_head: {
+  \parbox{\textwidth} {
+    \sffamily\small\centering
+    \__short_title:
+  }
+}
+
+\cs_new:Npn \__ceur_foot: {
+  \parbox[t]{\textwidth} {
+    % \rule{\textwidth}{.2pt}\\
+    \sffamily\small
+    \__first_footerline:
+    \hfill Page~\thepage {}~of~ \lastpage
+  }
+}
+
+% \newcommand \ps@first {
+%   \cs_set_eq:NN \@oddhead \__first_head:
+%   \cs_set_eq:NN \@evenhead \__first_head:
+%   \cs_set_eq:NN \@evenfoot \__first_foot:
+%   \cs_set_eq:NN \@oddfoot \__first_foot:
+% }
+
+% \newcommand \ps@ceur {
+%   \cs_set_eq:NN \@oddhead \__ceur_head:
+%   \cs_set_eq:NN \@evenhead \__ceur_head:
+%   \cs_set_eq:NN \@evenfoot \__ceur_foot:
+%   \cs_set_eq:NN \@oddfoot \__ceur_foot:
+% }
+
+% \ps@ceur
+
+%
+% Floats
+%
+
+\def\topfraction{.9}
+\def\bottomfraction{.9}
+\setcounter{topnumber}{4}
+\setcounter{bottomnumber}{3}
+\setcounter{totalnumber}{5}
+\renewcommand\textfraction{.1}
+\renewcommand\floatpagefraction{.9}
+\setcounter{dbltopnumber}{2}
+\renewcommand\dbltopfraction{.9}
+\renewcommand\dblfloatpagefraction{.95}
+\newdimen \FullWidth
+\FullWidth=\textwidth
+
+\newcolumntype{L}{@{\extracolsep{\fill}}l}
+\newcolumntype{R}{@{\extracolsep{\fill}}r}
+\newcolumntype{C}{@{\extracolsep{\fill}}c}
+
+\cs_gset_eq:NN \thead  \toprule
+\cs_gset_eq:NN \endthead  \midrule
+\cs_gset_eq:NN \tabref  \ref
+
+\dim_new:N \l_tbl_width_dim
+\dim_set:Nn \l_tbl_width_dim { \linewidth }
+
+\cs_new:Npn \__make_tbl_caption:nn #1#2
+{
+  \l_tbl_align_tl
+  \skip_vertical:N \l_tbl_abovecap_skip
+  % \bool_if:NTF \g_tbl_full_bool
+  % {
+  %  \color{scolor!70}\rule{\FullWidth}{2pt}\normalcolor\\
+  % }
+  % { \color{scolor!70}\rule{\tblwidth}{2pt}\normalcolor\\ }
+  % \fboxsep=4pt
+  % \colorbox{white}
+  {\parbox{ \dimexpr(\l_tbl_width_dim)}
+    {\rightskip=0pt\sffamily\small\textbf{\color{scolor}#1}\par#2\par\vskip4pt }}
+  \skip_vertical:N \l_tbl_belowcap_skip
+}
+
+\keys_define:nn { ceur / tbl } {
+  width     .dim_set:N   =  \l_tbl_width_dim ,
+  pos       .tl_set:N    =  \l_tbl_pos_tl ,
+  cols      .tl_set:N    =  \l_tbl_cols_tl ,
+  align     .tl_set:N    =  \l_tbl_align_tl,
+  abovecap  .skip_set:N  =  \l_tbl_abovecap_skip ,
+  belowcap  .skip_set:N  =  \l_tbl_belowcap_skip ,
+  abovetbl  .skip_set:N  =  \l_tbl_abovetbl_skip ,
+  belowtbl  .skip_set:N  =  \l_tbl_belowtbl_skip ,
+  full      .bool_gset:N =  \g_tbl_full_bool ,
+  unknown   .code:n      =  \tl_set:Nx \l_tbl_pos_tl { \l_keys_key_str },
+}
+
+\cs_set:Npn \__reset_tbl: {
+  \tl_set:Nx \l_tbl_pos_tl { t }
+  \tl_set:Nx \l_tbl_cols_tl { 1 }
+  \tl_set:Nn \l_tbl_align_tl { \centering }
+  \skip_set:Nn \l_tbl_abovecap_skip { 6pt }
+  \skip_set:Nn \l_tbl_belowcap_skip { 0pt }
+  \skip_set:Nn \l_tbl_abovetbl_skip { 6pt }
+  \skip_set:Nn \l_tbl_belowtbl_skip { 6pt }
+}
+
+\RenewDocumentEnvironment { table } { O{} } {
+  \__reset_tbl:
+  \bool_gset_false:N \g_tbl_full_bool
+  \dim_set:Nn \l_tbl_width_dim { \linewidth }
+  \keys_set:nn { ceur / tbl } { #1 }
+  \csxdef{fps@table}{\l_tbl_pos_tl}
+  \csgdef{tblwidth}{\dim_use:N \l_tbl_width_dim}
+  \cs_set_eq:NN \@makecaption \__make_tbl_caption:nn
+  \@float{table}
+  \l_tbl_align_tl
+  \sffamily\small
+}
+{ \end@float }
+
+
+\RenewDocumentEnvironment { table* } { O{width=\FullWidth} } {
+  \__reset_tbl:
+  \bool_gset_true:N \g_tbl_full_bool
+  \dim_set:Nn \l_tbl_width_dim { \FullWidth }
+  \keys_set:nn { ceur / tbl } { #1 }
+  \csxdef{fps@table}{\l_tbl_pos_tl}
+  \csgdef{tblwidth}{\dim_use:N \l_tbl_width_dim}
+  \cs_set_eq:NN \@makecaption \__make_tbl_caption:nn
+  \@dblfloat{table}
+  \l_tbl_align_tl
+  \sffamily\small
+  % \leftskip=-\FullWidth
+}
+{ \end@dblfloat }
+
+\dim_new:N \l_fig_width_dim
+\dim_set:Nn \l_fig_width_dim { \linewidth }
+
+\cs_new:Npn \__make_fig_caption:nn #1#2 {
+  \l_fig_align_tl
+  \skip_vertical:N \l_fig_abovecap_skip
+  % \bool_if:NTF \g_fig_full_bool
+  % { \skip_horizontal:n { -\FullWidth } } { }
+  \parbox{ \l_fig_width_dim }
+  {\rightskip=0pt\sffamily\small\textbf{\color{scolor}#1:}~#2\par }
+  \skip_vertical:N \l_fig_belowcap_skip
+}
+
+\keys_define:nn { ceur / fig } {
+  width     .dim_set:N   =  \l_fig_width_dim ,
+  pos       .tl_set:N    =  \l_fig_pos_tl ,
+  cols      .tl_set:N    =  \l_fig_cols_tl ,
+  align     .tl_set:N    =  \l_fig_align_tl,
+  abovecap  .skip_set:N  =  \l_fig_abovecap_skip ,
+  belowcap  .skip_set:N  =  \l_fig_belowcap_skip ,
+  abovefig  .skip_set:N  =  \l_fig_abovefig_skip ,
+  belowfig  .skip_set:N  =  \l_fig_belowfig_skip ,
+  full      .bool_gset:N =  \g_fig_full_bool ,
+  unknown   .code:n      =  \tl_set:Nx \l_fig_pos_tl { \l_keys_key_str },
+}
+
+\cs_set:Npn \__reset_fig: {
+  \tl_set:Nx \l_fig_pos_tl { t }
+  \tl_set:Nx \l_fig_cols_tl { 1 }
+  \tl_set:Nn \l_fig_align_tl { \raggedleft }
+  \skip_set:Nn \l_fig_abovecap_skip { 6pt }
+  \skip_set:Nn \l_fig_belowcap_skip { 6pt }
+  \skip_set:Nn \l_fig_abovefig_skip { 6pt }
+  \skip_set:Nn \l_fig_belowfig_skip { 6pt }
+}
+
+\RenewDocumentEnvironment { figure } { O{} } {
+  \__reset_fig:
+  \bool_gset_false:N \g_fig_full_bool
+  \dim_set:Nn \l_fig_width_dim { \linewidth }
+  \keys_set:nn { ceur / fig } { #1 }
+  \csxdef{fps@figure}{\l_fig_pos_tl}
+  \csgdef{figwidth}{\dim_use:N \l_fig_width_dim}
+  \cs_set_eq:NN \@makecaption \__make_fig_caption:nn
+  \@float{figure}
+  \l_fig_align_tl
+  \sffamily\small
+}{ \end@float }
+
+\RenewDocumentEnvironment { figure* } { O{width=\textwidth} } {
+  \__reset_fig:
+  \bool_gset_true:N \g_fig_full_bool
+  \dim_set:Nn \l_fig_width_dim { \FullWidth }
+  \keys_set:nn { ceur / fig } { #1 }
+  \csxdef{fps@figure}{\l_fig_pos_tl}
+  \csgdef{figwidth}{\dim_use:N \l_fig_width_dim}
+  \cs_set_eq:NN \@makecaption \__make_fig_caption:nn
+  \@dblfloat{figure}
+  \l_fig_align_tl
+  \sffamily\small
+  % \leftskip=-\FullWidth
+}
+{ \end@dblfloat }
+
+%
+% wrapped figure
+%
+\RequirePackage{wrapfig}
+
+\dim_new:N \l_wrap_figwidth_dim
+\dim_new:N \l_wrap_fighspace_dim
+\dim_new:N \l_wrap_figvspace_dim
+\dim_new:N \l_wrap_fighcorr_dim
+\dim_new:N \l_wrap_figvcorr_dim
+\dim_new:N \l_above_bio_dim
+\int_new:N \l_wrap_figlcorr_int
+\int_new:N \l_wrap_figlines_int
+\tl_new:N  \l_wrap_figfile_tl
+
+\NewDocumentCommand \wfigwidth { m }
+  { \dim_set:Nn \l_wrap_figwidth_dim { #1 } }
+\NewDocumentCommand \wfighspace { m }
+  { \dim_set:Nn \l_wrap_fighspace_dim { #1 } }
+\NewDocumentCommand \wfigvspace { m }
+  { \dim_set:Nn \l_wrap_figvspace_dim { #1 } }
+\NewDocumentCommand \wfighcorr { m }
+  { \dim_set:Nn \l_wrap_fighcorr_dim { #1 } }
+\NewDocumentCommand \wfigvcorr { m }
+  { \dim_set:Nn \l_wrap_figvcorr_dim { #1 } }
+\NewDocumentCommand \addfiglines { m }
+  { \int_set:Nn \l_wrap_figlcorr_int { #1 } }
+\NewDocumentCommand \abovebioskip { m }
+  { \dim_set:Nn \l_above_bio_dim { #1 } }
+
+\cs_new:Nn \__fig_defaults: {
+  \wfigwidth  { 25.5mm }
+  \wfighspace { 0mm }
+  \wfigvspace { 0mm }
+  \wfighcorr  { 0pt }
+  \wfigvcorr  { -12pt }
+  \wfigvcorr  { 0pt }
+  \abovebioskip { 12pt }
+  \tl_set:Nn  \l_wrap_figpos_tl { l }
+  \int_set:Nn \l_wrap_figlines_int { 3 }
+  \int_set:Nn \l_wrap_figlcorr_int { 1 }
+  \tl_clear:N \l_wrap_figcap_tl
+}
+
+\__fig_defaults:
+
+\keys_define:nn { wrap / fig } {
+  width    .dim_set:N    =  \l_wrap_figwidth_dim ,
+  hspace   .dim_set:N    =  \l_wrap_fighspace_dim ,
+  vspace   .dim_set:N    =  \l_wrap_figvspace_dim ,
+  hcorr    .dim_set:N    =  \l_wrap_fighcorr_dim ,
+  vcorr    .dim_set:N    =  \l_wrap_figvcorr_dim ,
+  lcorr    .int_set:N    =  \l_wrap_figlcorr_int ,
+  pos      .tl_set:N     =  \l_wrap_figpos_tl ,
+  lines    .int_set:N    =  \l_wrap_figlines_int ,
+  cap      .tl_set:N     =  \l_wrap_figcap_tl ,
+}
+
+\cs_new:Npn \__find_fig_height:n #1 {
+  \box_clear:N  \g_tmpa_box
+  \hbox_gset:Nn \g_tmpa_box
+  { \includegraphics [ width = \l_wrap_figwidth_dim ] { #1 } }
+  \dim_zero:N \l_tmpa_dim
+  \dim_set:Nn \l_tmpa_dim { \box_ht:N \g_tmpa_box }
+  \dim_add:Nn \l_tmpa_dim { \box_dp:N \g_tmpa_box }
+  \fp_set:Nn  \l_tmpa_fp  { \dim_to_fp:n { \l_tmpa_dim } }
+  \fp_set:Nn  \l_tmpb_fp  { \dim_to_fp:n { \baselineskip } }
+  % 
+  \fp_set:Nn \l_wrap_figlines_fp
+  { \fp_eval:n { ( \l_tmpa_fp / \l_tmpb_fp )  + .5 } }
+  \int_set:Nn \l_wrap_figlines_int
+  { \fp_to_int:N \l_wrap_figlines_fp }
+  % 
+  \iow_term:x { ...~wr-fig:~[BL:~\the\baselineskip] ~ ...}
+  \iow_term:x { ...~wr-fig:~[LINE-FP:~ \fp_use:N \l_wrap_figlines_fp]~ ...}
+  \iow_term:x { ...~wr-fig:~[LINE-INT:~ \int_use:N \l_wrap_figlines_int]~ ...}
+}
+
+\newbox \l_bio_text_box
+
+\NewDocumentCommand \WrapFigure { o m } {
+  \__fig_defaults:
+  \IfNoValueTF { #1 } { } { \keys_set:nn { wrap / fig } { #1 } }
+  \stepcounter { ca_biography_ctr }
+  \__find_fig_height:n { #2 }
+  \dim_zero:N \l_tmpb_dim
+  \dim_set:Nn \l_tmpb_dim
+  { \l_wrap_figwidth_dim + \l_wrap_fighspace_dim }
+  \int_gadd:Nn \l_wrap_figlines_int { \int_use:N \l_wrap_figlcorr_int }
+  \setlength { \columnsep } { 5pt }
+  \setlength { \intextsep } { 0pt }
+  % \mbox{}
+  \ifbool { dc } {
+    \xdef\Columnwidth{238.25pt}
+  }{
+    \xdef\Columnwidth{\the\textwidth}
+  }
+  \ifcsundef { cabio\theca_biography_ctr lines }
+  {
+    \setbox \l_bio_text_box = \vbox \bgroup
+    \hsize = \dimexpr ( \Columnwidth - 72.28pt )
+  }
+  {
+    \ifbool { dc } {
+      \int_gset:Nn \l_wrap_figlines_int
+      { \csuse { cabio\theca_biography_ctr lines } }
+    } { }
+    \skip_vertical:N \l_above_bio_dim
+    \begin{wrapfigure}[\int_use:N \l_wrap_figlines_int]
+      { \l_wrap_figpos_tl }
+      [ \dim_use:N \l_wrap_fighcorr_dim ]
+      { \dim_use:N \l_tmpb_dim }
+      % \skip_vertical:N \l_wrap_figvcorr_dim
+      \includegraphics[width=\l_wrap_figwidth_dim]{#2}
+    \end{wrapfigure}
+    \setbox \l_bio_text_box = \vbox \bgroup
+    \hsize = \dimexpr ( \Columnwidth )
+  }
+}
+
+\cs_set:Nn \__fwidth: { 1in }
+\cs_set:Nn \__fpos: { l }
+
+%
+% short authors/title
+%
+
+\tl_new:N \__short_authors:
+\newcommand\shortauthors[1]{ \cs_gset:Nn \__short_authors: { #1 } }
+
+\tl_new:N \__short_title:
+\newcommand\shorttitle[1]{ \cs_gset:Nn \__short_title: { #1 } }
+
+\newcounter { ca_biography_ctr }
+\newbool { cas_no_pic_bio }
+\boolfalse { cas_no_pic_bio }
+
+\NewDocumentCommand \bio { O{} m }
+{
+  \global \boolfalse { cas_no_pic_bio }
+  \casbiographyfont
+  \par \medskip  \tl_set:Nn \l_tmpa_tl { #2 }
+  \tl_if_empty:NTF \l_tmpa_tl
+  { \global \booltrue { cas_no_pic_bio } }
+  { \WrapFigure [ #1 ]{ #2 } }
+  \noindent \ignorespaces
+}
+
+\int_new:N \l_ca_temp_inta
+
+\NewDocumentCommand \endbio { } {
+ \ifbool{ cas_no_pic_bio } { } {
+  \egroup
+%  \fp_set:Nn \l_wrap_figlines_fp
+%    { \fp_eval:n { ( ( \l_tmpa_fp +
+%      \numexpr\dimexpr\the\ht\l_bio_text_box )
+%      / \l_tmpb_fp )  + .5 } }
+  \int_gset:Nn \l_ca_temp_inta
+      { \numexpr\dimexpr(\the\ht\l_bio_text_box + 2\baselineskip )/
+        \dimexpr\the\baselineskip }
+  \iow_now:Nx \@auxout {
+     \string\csgdef{cabio\theca_biography_ctr lines}
+        { \int_use:N \l_ca_temp_inta } }
+\mbox{}\vspace*{-4.5pt}\noindent
+\unvbox \l_bio_text_box }
+}
+
+\let\casbiographyfont\relax
+
+\NewDocumentEnvironment { biography } { o m }
+{
+  \IfValueTF { #1 }
+  { \par\medskip \noindent \includegraphics[width=1in]{#1} }
+  { }
+  \par\smallskip
+  \noindent \textbf{#2:}\enspace
+}
+{ }
+
+\ExplSyntaxOff
+
+%
+% Customized Enumeration
+%
+\def\blstr#1{\gdef\@bslstr{#1}}
+\def\@blstr{1}
+\newdimen\leftMargin
+\leftMargin=2em
+\newtoks\@enLab  %\newtoks\@enfont
+\def\@enQmark{?}
+\def\@enLabel#1#2{%
+  \edef\@enThe{\noexpand#1{\@enumctr}}%
+  \@enLab\expandafter{\the\@enLab\csname the\@enumctr\endcsname}%
+  \@enloop}
+\def\@enSpace{\afterassignment\@enSp@ce\let\@tempa= }
+\def\@enSp@ce{\@enLab\expandafter{\the\@enLab\space}\@enloop}
+\def\@enGroup#1{\@enLab\expandafter{\the\@enLab{#1}}\@enloop}
+\def\@enOther#1{\@enLab\expandafter{\the\@enLab#1}\@enloop}
+\def\@enloop{\futurelet\@entemp\@enloop@}
+\def\@enloop@{%
+  \ifx A\@entemp         \def\@tempa{\@enLabel\Alph  }\else
+  \ifx a\@entemp         \def\@tempa{\@enLabel\alph  }\else
+  \ifx i\@entemp         \def\@tempa{\@enLabel\roman }\else
+  \ifx I\@entemp         \def\@tempa{\@enLabel\Roman }\else
+  \ifx 1\@entemp         \def\@tempa{\@enLabel\arabic}\else
+  \ifx \@sptoken\@entemp \let\@tempa\@enSpace         \else
+  \ifx \bgroup\@entemp   \let\@tempa\@enGroup         \else
+  \ifx \@enum@\@entemp   \let\@tempa\@gobble          \else
+                         \let\@tempa\@enOther
+             \fi\fi\fi\fi\fi\fi\fi\fi
+  \@tempa}
+\newlength{\@sep} \newlength{\@@sep}
+\setlength{\@sep}{.5\baselineskip plus.2\baselineskip
+            minus.2\baselineskip}
+\setlength{\@@sep}{.1\baselineskip plus.01\baselineskip
+            minus.05\baselineskip}
+\providecommand{\sfbc}{\rmfamily\upshape}
+\providecommand{\sfn}{\rmfamily\upshape}
+\def\@enfont{\ifnum \@enumdepth >1\let\@nxt\sfn \else\let\@nxt\sfbc \fi\@nxt}
+\def\enumerate{%
+   \ifnum \@enumdepth >3 \@toodeep\else
+      \advance\@enumdepth \@ne
+      \edef\@enumctr{enum\romannumeral\the\@enumdepth}\fi
+   \@ifnextchar[{\@@enum@}{\@enum@}}
+\def\@@enum@[#1]{%
+  \@enLab{}\let\@enThe\@enQmark
+  \@enloop#1\@enum@
+  \ifx\@enThe\@enQmark\@warning{The counter will not be printed.%
+   ^^J\space\@spaces\@spaces\@spaces The label is: \the\@enLab}\fi
+  \expandafter\edef\csname label\@enumctr\endcsname{\the\@enLab}%
+  \expandafter\let\csname the\@enumctr\endcsname\@enThe
+  \csname c@\@enumctr\endcsname7
+  \expandafter\settowidth
+            \csname leftmargin\romannumeral\@enumdepth\endcsname
+            {\the\@enLab\hskip\labelsep}%
+  \@enum@}
+\def\@enum@{\list{{\@enfont\csname label\@enumctr\endcsname}}%
+           {\usecounter{\@enumctr}\def\makelabel##1{\hss\llap{##1}}%
+     \ifnum \@enumdepth>1\setlength{\topsep}{\@@sep}\else
+           \setlength{\topsep}{\@sep}\fi
+     \ifnum \@enumdepth>1\setlength{\itemsep}{0pt plus1pt minus1pt}%
+      \else \setlength{\itemsep}{\@@sep}\fi
+     %\setlength\leftmargin{\leftMargin}%%%{1.8em}
+     \setlength{\parsep}{0pt plus1pt minus1pt}%
+     \setlength{\parskip}{0pt plus1pt minus1pt}
+                   }}
+
+\def\endenumerate{\par\ifnum \@enumdepth >1\addvspace{\@@sep}\else
+           \addvspace{\@sep}\fi \endlist}
+
+\def\sitem{\@noitemargtrue\@item[\@itemlabel *]}
+
+\def\itemize{\@ifnextchar[{\@Itemize}{\@Itemize[]}}
+
+\def\@Itemize[#1]{%
+  \def\next{#1}%
+  \ifnum \@itemdepth >\thr@@\@toodeep\else
+    \advance\@itemdepth\@ne
+    \ifx\next\@empty\else\expandafter\def\csname
+      labelitem\romannumeral\the\@itemdepth\endcsname{#1}\fi%
+    \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}%
+    \expandafter\list\csname\@itemitem\endcsname
+    {\def\makelabel##1{\hss\llap{##1}}}%
+  \fi
+  \setlength{\itemsep}{\@@sep}
+  \setlength{\parsep}{0pt plus1pt minus1pt}%
+  \setlength{\parskip}{0pt plus1pt minus1pt}
+}
+
+%
+% Customized theorem
+% (non-italic enunciations)
+%
+
+\def\newdefinition#1{%
+  \@ifnextchar[{\@odfn{#1}}{\@ndfn{#1}}}%]
+\def\@ndfn#1#2{%
+  \@ifnextchar[{\@xndfn{#1}{#2}}{\@yndfn{#1}{#2}}}
+\def\@xndfn#1#2[#3]{%
+  \expandafter\@ifdefinable\csname #1\endcsname
+    {\@definecounter{#1}\@newctr{#1}[#3]%
+     \expandafter\xdef\csname the#1\endcsname{%
+       \expandafter\noexpand\csname the#3\endcsname \@dfncountersep
+          \@dfncounter{#1}}%
+     \global\@namedef{#1}{\@dfn{#1}{#2}}%
+     \global\@namedef{end#1}{\@enddefinition}}}
+\def\@yndfn#1#2{%
+  \expandafter\@ifdefinable\csname #1\endcsname
+    {\@definecounter{#1}%
+     \expandafter\xdef\csname the#1\endcsname{\@dfncounter{#1}}%
+     \global\@namedef{#1}{\@dfn{#1}{#2}}%
+     \global\@namedef{end#1}{\@enddefinition}}}
+\def\@odfn#1[#2]#3{%
+  \@ifundefined{c@#2}{\@nocounterr{#2}}%
+    {\expandafter\@ifdefinable\csname #1\endcsname
+    {\global\@namedef{the#1}{\@nameuse{the#2}}
+  \global\@namedef{#1}{\@dfn{#2}{#3}}%
+  \global\@namedef{end#1}{\@enddefinition}}}}
+\def\@dfn#1#2{%
+  \refstepcounter{#1}%
+  \@ifnextchar[{\@ydfn{#1}{#2}}{\@xdfn{#1}{#2}}}
+\def\@xdfn#1#2{%
+  \@begindefinition{#2}{\csname the#1\endcsname}\ignorespaces}
+\def\@ydfn#1#2[#3]{%
+  \@opargbegindefinition{#2}{\csname the#1\endcsname}{#3}\ignorespaces}
+\def\@dfncounter#1{\noexpand\arabic{#1}}
+\def\@dfncountersep{.}
+\def\@begindefinition#1#2{\trivlist
+   \item[\hskip\labelsep{\bfseries #1\ #2.}]\upshape}
+\def\@opargbegindefinition#1#2#3{\trivlist
+      \item[\hskip\labelsep{\bfseries #1\ #2\ (#3).}]\upshape}
+\def\@enddefinition{\endtrivlist}
+
+\def\@begintheorem#1#2{\trivlist
+  \let\baselinestretch\@blstr
+   \item[\hskip \labelsep{\bfseries #1\ #2.}]\itshape}
+\def\@opargbegintheorem#1#2#3{\trivlist
+  \let\baselinestretch\@blstr
+      \item[\hskip \labelsep{\bfseries #1\ #2\ (#3).}]\itshape}
+%
+% Unnumbered roman proofs
+%
+\def\newproof#1{%
+  \@ifnextchar[{\@oprf{#1}}{\@nprf{#1}}}
+\def\@nprf#1#2{%
+  \@ifnextchar[{\@xnprf{#1}{#2}}{\@ynprf{#1}{#2}}}
+\def\@xnprf#1#2[#3]{%
+  \expandafter\@ifdefinable\csname #1\endcsname
+    {\@definecounter{#1}\@newctr{#1}[#3]%
+     \expandafter\xdef\csname the#1\endcsname{%
+       \expandafter\noexpand\csname the#3\endcsname \@prfcountersep
+          \@prfcounter{#1}}%
+     \global\@namedef{#1}{\@prf{#1}{#2}}%
+     \global\@namedef{end#1}{\@endproof}}}
+\def\@ynprf#1#2{%
+  \expandafter\@ifdefinable\csname #1\endcsname
+    {\@definecounter{#1}%
+     \expandafter\xdef\csname the#1\endcsname{\@prfcounter{#1}}%
+     \global\@namedef{#1}{\@prf{#1}{#2}}%
+     \global\@namedef{end#1}{\@endproof}}}
+\def\@oprf#1[#2]#3{%
+  \@ifundefined{c@#2}{\@nocounterr{#2}}%
+    {\expandafter\@ifdefinable\csname #1\endcsname
+    {\global\@namedef{the#1}{\@nameuse{the#2}}%
+  \global\@namedef{#1}{\@prf{#2}{#3}}%
+  \global\@namedef{end#1}{\@endproof}}}}
+\def\@prf#1#2{%
+  \refstepcounter{#1}%
+  \@ifnextchar[{\@yprf{#1}{#2}}{\@xprf{#1}{#2}}}
+\def\@xprf#1#2{%
+  \@beginproof{#2}{\csname the#1\endcsname}\ignorespaces}
+\def\@yprf#1#2[#3]{%
+  \@opargbeginproof{#2}{\csname the#1\endcsname}{#3}\ignorespaces}
+\def\@prfcounter#1{\noexpand\arabic{#1}}
+\def\@prfcountersep{.}
+\def\@beginproof#1#2{\trivlist\let\baselinestretch\@blstr
+   \item[\hskip \labelsep{\scshape #1.}]\rmfamily}
+\def\@opargbeginproof#1#2#3{\trivlist\let\baselinestretch\@blstr
+      \item[\hskip \labelsep{\scshape #1\ (#3).}]\rmfamily}
+\def\@endproof{\endtrivlist}
+\newcommand*{\qed}{\hbox{}\hfill$\Box$}
+
+\xspaceaddexceptions{]}
+
+\ExplSyntaxOn
+
+%%
+%% Bibliography
+%%
+
+% \RequirePackage[numbers,sort&compress]{natbib}
+\RequirePackage[numbers]{natbib}
+\AtBeginDocument{\bibsep=0pt}
+
+\bibliographystyle{elsarticle-num-names}
+% \bibliographystyle{elsarticle-num}
+
+%%
+%% Fonts
+%%
+
+\ifpdftex
+\RequirePackage[T1]{fontenc}
+\fi
+
+%% Main font
+\file_if_exist:nTF { libertinus.sty }
+{
+  \RequirePackage{libertinus}
+}{
+  \iow_term:x { Libertinus fonts are not available }
+}
+
+%% Math font for pdfLaTeX
+% \ifpdftex
+% \file_if_exist:nTF { libertinust1math.sty }
+% {
+%   \RequirePackage{libertinust1math}
+% }{
+%   \iow_term:x { Libertinus math fonts are not available }
+% }
+% \fi
+
+\ExplSyntaxOff
+
+%%
+%% Compatibility workaround
+%%
+
+%% Old font naming commands for Koma class
+
+\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm}
+\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf}
+\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt}
+\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf}
+\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit}
+\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl}
+\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc}
+
+\endinput
+
+%
+% End of class 'ceurart'
+%
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: t
+%%% coding: utf-8-unix
+%%% End: