This paper describes a conditional term rewriting system for Joy based on the two constructors concatenation and quotation.
A rewriting system consists of a set of
syntactic rules for performing replacements on certain suitable entities.
The best known such system is the one we learnt at school
for evaluating arithmetic expressions.
Any programming language can be given a rewriting system,
but for Joy it is particularly simple.
The basic binary rewriting relation will be written in infix notation
as =>
, pronounced "can be rewritten as".
The following are some sample rules for the + operator,
the < predicate
and the dip combinator.
2 3 + => 5 2 3 < => true a [P] dip => P aIn the last example,
P
is any program and a
is any literal
(such as a number) or a program
whose net effect is to push exactly one item onto the stack.
The rewriting relation is extended to allow rewriting in appropriate contexts,
further extended to accomodate several rewriting steps,
and finally extended to become a congruence relation,
an equivalence relation compatible with program concatenation.
This congruence relation between programs
is essentially the same as the identity relation in the algebra
of of functions which the programs denote.
Although Joy functions take a stack as argument and value,
in the rewrite rules the stack is never mentioned.
The following are rewriting rules for arithmetic expressions in four different notations: infix, functional, prefix and postfix:
2 + 3 => 5 +(2,3) => 5 + 2 3 => 5 2 3 + => 5In each case on the left the operands are
2
and 3
,
and the operator or constructor is +
,
so they all refer to the same arithmetic term.
Since Joy uses what looks like postfix notation,
it might be thought that one should attempt a term rewriting system
with rules just like the second one in the last line.
That would treat the short program 2 3 +
as being composed of two operands and one operator or constructor.
It would also treat the gap between 2
and 3
as quite different from the gap between 3
and +
.
The difference would be explained away as a syntactic
coincidence due to the choice of notation.
Apart from +
there would be very many term constructors.
However, Joy has operators for manipulating the top few elements of the stack, such as swap, dup and pop. These are also found in the language Forth, see for example \AX{Salman {\it et al}}{1984}{Salman-etal:84} and \AX{Kelly {\it et al}}{1986}{Kelly-etal:86}. These operators take a stack as argument and yield a stack as value, and their presence forces all other operators to be of the same type. For example, the following is a rewrite rule for swap:
a b swap => b aUnlike Forth, Joy also has quotations and combinators. These features also force the conclusion that the appropriate rewriting system is a string rewriting system. Consider the following four programs:
[2] [3 +] b [2] [3 +] concat i [2 3] [+] b [2 3] [+] concat iThey all eventually have to reduce to
5
,
just like the earlier Joy program 2 3 +
.
It suggests that in the latter the gaps have to be treated
in the same way,
the program is a concatenation of three atomic symbols,
and it denotes the composition of three functions.
So, at least for Joy programs without quotations
and combinators,
the appropriate system is a string rewriting system.
Such a system is equivalent to a term rewriting system
with a concatenation constructor for programs as the only constructor.
To handle combinators,
a quotation constructor has to be introduced
as a second constructor.
The remainder of this paper is organised as follows: The next section introduces rewriting systems in general. Then follows a section on the principal concepts of a rewriting system for Joy. The next two sections give details of rewriting rules for operators and for combinators. Two other sections re-examine the stack and the quotation constructor. It is argued that the stack is not just an optimisation useful in an inmplementation, but that it is almost essential for understanding the semantics of Joy. The possibility of an extensional version of the quotation constructor is discussed but dismissed as unnecessarily restrictive. A final section is an outline of a rewriting system for Joy types; the system resembles a categorial grammar.
Rewriting systems can be classified according to the entities that are being rewritten. In a string rewriting system those entities are linear sequences of symbols or strings of symbols. In a term rewriting system these entities are expressions or terms build from operands and operators. In a graph rewriting system they are graphs of various kinds.
A string rewriting system is based on an alphabet which is just a set of symbols. Strings over a given alphabet are arbitrary sequences of symbols, each taken from the alphabet. The empty sequence or null string is included. A rewriting rule is of the form
x => ywhere both x and y are strings. A string rewriting system consists of an alphabet and a relation =>, a set of such pairs or rules. A wider relation ==> is defined as follows: For strings
w
, x
, y
and z
,
w x z ==> w y zif and only if
x => z
. This relation allows
replacement of x
by y
in arbitrary contexts w..z
.
A term rewriting system also requires an alphabet of symbols. Each symbol has an associated arity which is a natural number (0, 1, 2, ...). Symbols of arity 0 are nullary symbols or operands, symbols of positive arity are unary, binary, ternary and so on symbols or operators. A term over such an alphabet is either an operand or it is an operator of arity $n$ together with $n$ further terms. Terms are really abstract syntax trees, and various notations can be used for their concrete linear representation. A rewriting rule is again a pair of the form
x => ywhere
x
and y
now have to be terms.
A term rewriting system consists of an alphabet of symbols,
each with their own arity,
and a set of such rules.
A wider relation ==> is defined as follows:
y ==> zif and only if
y
and z
are alike terms except that
y
contains a subterm u
where z
contains
a subterm w
such that u => w
.
In any rewriting system it is useful to define ==>> as
the reflexive transitive closure of ==>
.
x ==>> zif and only if
x = z
or for some y
,
x ==> y
and y ==>> z
.
Here is an example for a fragment of a rewriting system for arithmetical expressions in Joy:
2 3 + => 5 7 2 3 + * ==> 7 5 * 7 2 3 + * ==>> 35In the second line the subexpression
2 3 +
on the left
is called a reducible expression or redex
since it can be reduced using the rule in the first line.
There are two distinct ways in which a string rewriting system
can be interpreted as a term rewriting system.
On the first interpretation,
the term system has exactly one operand.
It has as unary constructors all the symbols of the string system.
It has no other constructors.
The single operand is just the null string,
and any symbol, say s
from the string alphabet
is interpreted as a unary operator append s
.
The appending is either uniformly on the left or uniformly on the right.
On the second interpretation, the term system has as operands all the symbols from the string system. It has only one binary constructor, concatenation. This interpretation is most useful for a rewriting system for Joy because it is now possible to add the unary quotation constructor which is needed for the combinators.
Rewriting systems can be based just on unconditional rules of the
form x => y
,
but they can also have conditional rules.
Such rules state that certain rewritings are permitted
provided certain other rewritings are permitted.
The next sections give a conditional rewriting system for Joy.
A short general introduction to rewriting systems is in \AX{Salomaa}{1985}{Salomaa:85}. String rewriting systems in particular are discussed in \AX{Book}{1985}{Book:85}. A general survey of rewriting systems is in \AX{Schmitt}{1987}{Schmitt:87}. %
This section describes the basis of a conditional rewriting system for Joy using a notation similar to Prolog.
A rewriting system for Joy will be a collection of syntactic rules for rewriting Joy programs. Such a system must be based on the two principal program constructors, program concatenation and program quotation. The system to be presented here uses (unconditional) axioms of the form
P => Qwhere
P
and Q
are programs.
There are also conditional rules of the following forms,
where R
, S
, T
and U
are further programs.
P => Q :- R => S. P => Q :- R => S, T => U.The rules are written in a Prolog-like syntax. The turnstyle :- is pronounced "if". On its left is the conclusion or consequent. On the right is a premise or antecedent. The antecedent can be a conjunction, as in the second form above, and the comma , is pronounced "and". So the second of the above rules can be read as: "
P
can be replaced by Q
if
R
can be replaced by S
and
T
can be replaced by U
".
Details of these rules are given in the next two sections.
Using the same notation, the relation ==> is defined by the three rules
P ==> Q :- P => Q. P Q ==> P R :- Q ==> R. P R ==> Q R :- P ==> Q.The last two clauses allow rewriting in a context ---
P
on the left
or R
on the right.
The next rules for ==>
concern combinators.
In the following, C
$i$ is any combinator expecting
at least $i$ quotation parameters.
[P] C1 ==> [Q] C1 :- P ==> Q. [P] [R] C2 ==> [Q] [R] C2 :- P ==> Q. [P] [S] [R] C3 ==> [Q] [S] [R] C3 :- P ==> Q. [P] [T] [S] [R] C4 ==> [Q] [T] [S] [R] C4 :- P ==> Q.
Note that there is no rewrite rule
[P] ==> [Q] :- P ==> Q.The reason for this is further explained in section 7.
The final relation to be introduced is ==>>,
the reflexive transitive closure of ==>
.
It is defined by
P ==>> P. P ==>> R :- P ==> Q, Q ==>> R.
The simplest examples of rewriting axioms are those generated
by definitions.
If an atom name
has been defined using == as program P
,
in the form
name == Pthen
name
may be rewritten as P
:
name => P
The stack is normally a sequence of values of various types.
This sequence is just a special list
which is modified by programs.
The first general operator is newstack,
which clears the stack.
Clearing twice is the same as clearing just once.
If literals were pushed before the clearing,
this has the same effect as just clearing.
So newstack
is in fact the right zero element for
program concatenation.
newstack newstack => newstack. P newstack => newstack.Since the stack is a list, it should be possible to put this list on top of the stack --- that is to say, on top of itself. Also, it should be possible to make the list on top of the stack become the stack. There are two operators that do just that: The stack operator pushes onto the stack a list containing all the elements of the stack. The unstack operator expects a list on top of the stack and makes that the stack. The
unstack
operator undoes what the stack
operator
does,
but the reverse is true only in special cases.
newstack stack => newstack []. [] unstack => newstack. newstack L => [L] reverse unstack.In the last rule,
L
has to be a list of literals.
Also, it should be noted that the stack is not always
a sequence of values, it can also contain operators
and combinators.
So, strictly speaking the stack is always a quotation,
and the stack
operator pushes a quotation
onto the stack,
and the unstack
operator expects a quotation
on the stack and makes that the new stack.
Although the stack was mentioned in these informal explanations, it should be noted that it is not referred to at all in the rewrite rules. The same will be true in the sections to follow.  Joy symbols denote functions from stacks to stacks. But syntax does not concern semantic concepts such as denotation. rem
The unary operators pop and dup
are defined on all stacks containing at least one element.
In the rewrite rules to follow, let a
be any literal
or a program whose net effect is to push exactly one value onto the stack.
a pop => id. a dup => a a.The generalisation that
a
may be not just a literal but can be
a program whose effect is to push a single value
is needed for rare cases like the following:
[*] first dup => [*] first [*] first.The two programs on the left and right of the arrow have the net effect of pushing two occurrences of the multiplication operator
*
onto the stack.
The binary operators swap, popd, and dupd
are defined on all stacks containing at least two elements.
 Let
a
, b
and c
be any literals
or equivalent programs.
a b c swapd => b a c. a b c rollup => c a b. a b c rolldown => b c a. a b c rotate => c b a.
The ternary operator choice also expects three elements,
but the third element has to be a truth value.

The simple types of Joy are the truth value type, the character type and the integer type. The next rules are for the operators on these types.
Rewrite rules for the unary operators
succ, pred, abs and sign
for integer operands is given by the following rules.
Since characters are just small positive integers,
the operators can also be applied to characters.
The last two operators can also be applied to truth values.
In what follows, let i
, j
and k
be any integers.
i succ => j. ( j = i+1 ) i pred => j. ( j = i-1 ) i abs => j. ( j = abs(i) ) i sign => j. ( j = sign(i) )
Rewrite rules for the binary operators +, -, *, /, rem, max and min for integers operands are as follows.
i j + => k. ( k = i+j ) i j - => k. ( k = i-j ) i j * => k. ( k = i*j ) i j / => k. ( k = i/j ) i j rem => k. ( k = i mod j ) i j max => k. ( k = max(i,j) ) i j min => k. ( k = min(i,j) )Again these binary operators can be applied to characters as well as integers. In the mixed case the type of the result
k
is the same as the type of the second parameter i
.
Most implementations of Joy will also provide many other arithmetical operations. Since these will be defined in a library, no reduction rules should be given here.
The type of truth values is one of the Boolean types.
The binary operators are and, or and xor
(exclusive or).
The unary operator is not.
Let p
and q
be truth values
true
or false
.
p q and => r. ( r = p and q ) p q or. => r ( r = p or q ) p q xor. => r ( r = p xor q ) p not => r. ( r = not p )
A predicate is a function which leaves a truth value on the stack. The unary predicates null, small, odd, even, positive and negative are defined for all numeric types:
i null => p. ( p = (i=0) ) i small => p. ( p = (i<2) ) i odd => p. ( p = odd(i) ) i even => p. ( p = even(i) ) i positive => p. ( p = positive(i) ) i negative => p. ( p = negative(i) )
The binary predicates =, !=, <, <=, > and >= have the obvious rewrite rules:
i j = => p. ( p = (i = j) ) i j != => p. ( p = not(i = j) ) i j < => p. ( p = (i < j) ) i j <= => p. ( p = (i <= j) ) i j > => p. ( p = (i > j) ) i j >= => p. ( p = (i >= j) )
The remainder of this section deals with aggregate types: sets, strings and quotations, with lists as a special case. The unary operators first, second, third and rest expect a non-empty aggregate on top of the stack. The following are the rules for list aggregates:
[a L] first => a. [a b L] second => b. [a b c L] third => c. [a L] rest => [L].
Here [a L]
is a non-empty list or quotation
whose first member is a
and whose rest is [L]
.
For strings an analogous notation can be used
to obtain analogous rules. For example
"cS" first => 'c. "cS" rest => "S".Here "cS" denotes a non-empty string whose first character is
'c
and whose remaining characters are the string "S"
.
For sets the rules are entirely analogous, except that the numeric ordering of the members is used. One possible notation is the following:
{a S} first => a. {a S} rest => {S}.Here
{a S}
denotes a non-empty set whose smallest
member is a
and whose other members are those of {S}
.
The binary operators cons and swons expect an aggregate and a potential member on top of the stack. These are the rules for list aggregates:
a [L] cons => [a L]. [L] a swons => [a L].The rules for strings and sets are analogous.
The unary operators uncons and unswons also expect a non-empty aggregate. The rules for list aggregates are:
[a L] uncons => a [L]. [a L] unswons => [L] a.So for strings and sets some of the rules are
'c "S" cons => "cS". {S} a swons => {a S}. {a S} uncons => a {S}.
The two binary operators at and of are for indexing into aggregates. For list the rules might be written:
[l1 l2 ... li ... ln] i at => li. i [l1 l2 ... li ... ln] of => li.So the two operators are converses of each other. For both operators in the case of sequences the sequence ordering is used, and for sets the underlying ordering is used. But the notation with the dots
...
is not
satisfactory.
Here is a better version for at
applied to lists:
[a L] 1 at => a. [a L] n at => b :- [L] (n-1) at => b.And here is a version for
of
applied to sets:
1 {a S} of => a. n {a S} of => b :- (n-1) {S} of => b.
The unary operator size takes an aggregate and determines the number of elements:
[] size => 0. [a L] size => (n+1) :- L size => n.
The unary operator reverse can be applied to any aggregate but it is useful only for sequences:
[] reverse => []. [a L] reverse => [M a] :- L reverse => M.These rules for
reverse
are correct but inefficient
since appending to the right to produce [M a]
requires copying --- at least for the obvious implementation of lists.
Most implementations would use an accumulating parameter
to optimise the reverse
operator.
It is of some interest that this optimisation can
be expressed in rewrite rules:
reverse => [] swap shunt. [L] [] shunt => [L]. [L] [a M] shunt => [a L] [M] shunt.
The binary operator concat can be applied to two sequences which are either both lists or both strings.
[] [L] concat => [L]. [a L] [M] concat => [a N] :- [L] [M] concat => [N].
The operators and, or, xor and not can be applied not only to truth values but also to values of the set type. The reduction rules look exactly as for the truth values, except that the operations have to be performed bitwise. So they compute the intersection, union, symmetric difference and complement with respect to the largest set.
The two unary predicates null and small can also be applied to aggregates. These are the rules for lists, those for strings and sets are analogous.
[] null => true. [a L] null => false. [] small => true. [a] small => true. [a b L] small => false.
The two binary predicates in and has test aggregates for members.
a [] in => false. a [a L] in => true. a [b L] in => a [L] inThe has predicate is just the converse:
[] a has => false. [a L] a has => true. [b L] a has => [L] a has.
Most implementations of Joy will provide an operator for sorting a sequence and a binary operator merge for combining two already sorted sequences. Since these will be implemented in a library, no reduction rules are given here. The same applies to many other operators for aggregates. %
Sometimes it is necessary to test a parameter for its type. The unary predicates logical, char, integer, set, string and list are true if the parameter is a truth value, character, integer, set, string or list, respectively. The predicate leaf is true if the parameter is not a list.
false logical => true. 123 logical => false. 123 integer => true. ['A 'B 'C] leaf => false.
There is another operator for multi-choices.
It expects a non-empty list of non-empty lists on top of the stack
and below that one further item.
The opcase operator
matches the type of the item
with the first
members of the lists.
When a match is found,
the rest
of that list is pushed onto the stack.
If no match is found,
then the last list is used as the default.
123 [ [0 P] ['a Q] ["" R] ... ] opcase => 123 [P]. 'c [ [0 P] ['a Q] ["" R] ... ] opcase => 'c [Q]. "Hello" [ [0 P] ['a Q] ["" R] ... ] opcase => "Hello" [R].
The simplest unary combinators are i and x,
they require the top of the stack to be one quotation.
Let P
be any program.
[P] i => P. [P] x => [P] P.
The next unary combinators, dip, dip2 and dip3,
allow manipulation
of the stack below the top few elements.

Another unary combinator is nullary.
Its rewrite rule has to be expressed conditionally.
Let L
, M
and P
be any programs.
L [P] nullary => L a :- L P => M a.Three similar unary combinators are unary, binary and ternary:
L b [P] unary => L a :- L b P => M a. L b c [P] binary => L a :- L b c P => M a. L b c d [P] ternary => L a :- L b c d P => M a.
Three further unary combinators are
app1, app2 and app3.
Let a
, a'
, b
, b'
, c
and c'
be any literals or equivalent.
Note that the primed versions are used as the result
of applying P
to the unprimed versions.
L a [P] app1 => L a' :- L a P => M a'. L a b [P] app2 => L a' b' :- L a P => M a', L b P => N b' L a b c [P] app3 => L a' b' c' :- L a P => M a', L b P => N b', L c P => O c'.There is even an app4 combinator which applies
[P]
to four parameters a
, b
, c
and d
.
The binary combinators expect two quotations
on top of the stack.
The b combinator expects two quotations [P]
and [Q]
,
with [Q]
on top.
[P] [Q] b => P Q.The cleave combinator also expects two quotations, and below that an item
a
.
L a [P] [Q] cleave => L b c :- L a P => M b, L a Q => N c.
The ternary combinators expect three quotations on top of the stack. One of the most important is ifte which performs branching. Its third parameter is the if-part, its second parameter is the then-part, its first parameter, on top, is the else-part.
L [I] [T] [E] ifte => T :- L I => M true. L [I] [T] [E] ifte => E :- L I => M false.
The binary whiledo combinator is similar to the ifte
combinator
in that it has a test, the while-part, which is second on the stack.
The combinator repeatedly executes the while-part
and while that yields true
it executes the other part,
the do-part.
L [W] [D] whiledo => L :- L W => M false. L [W] [D] whiledo => L D [W] [D] whiledo :- L W => M true.The ternary tailrec combinator for tail recursion also has a test, the third parameter. If that yields true, the second parameter is executed and the combinator exits, otherwise the top parameter is executed and after that the process is repeated.
L [I] [T] [R] tailrec => L T :- L I => M true. L [I] [T] [R] tailrec => L R [I] [T] [R] tailrec :- L I => M false.
The quaternary combinators expect four quotations
on top of the stack.
The linrec combinator for linear recursion
expects an if-part [I]
, a then-part [T]
,
and two recursion parts [R1]
and [R2]
.
L [I] [T] [R1] [R2] linrec => L T :- L I => M true. L [I] [T] [R1] [R2] linrec => L R1 [I] [T] [R1] [R2] linrec R2 :- L I => M false.
The binrec combinator for binary recursion is similar, except that the first recursion part has to produce two values. The recursion with all four parts is applied to the two values separately. The second recursion part then has available the two results from these two applications.
L [I] [T] [R1] [R2] binrec => L T :- L I => M true. L [I] [T] [R1] [R2] binrec => L a b R2 :- L T => M false, L R1 [I] [T] [R1] [R2] binrec => N a b.
The genrec combinator for general recursion is also has an if-part, a then-part and two recursion parts. It differs from the other two combinators in that after the execution of the first recursion part nothing in particular is executed, but a program consisting of the four parts and the combinator is pushed onto the stack. The second recursion part thus has it available as a parameter.
L [I] [T] [R1] [R2] genrec => L T :- L I => M true. L [I] [T] [R1] [R2] genrec => L R1 [[I] [T] [R1] [R2] genrec] R2 :- L I => M false.
There are several combinators which do not have a fixed number
of quotation parameters.
Instead they use a list of quotations.
The cond combinator is like the one in Lisp,
it is a generalisation of the ifte
combinator.
It expects a non-empty list of programs,
each consisting of a quoted if-part followed by a then-part.
The various if-parts are executed until one is found
that returns true
, and then its corresponding then-part
is executed.
The last program in the list is the default
which is executed if none of the if-parts yield true
.
L [ [[I1] T1] REST ] cond => L T1 :- L I1 => M true. L [ [[I1] T1] REST ] cond => L [ REST ] cond :- L I1 => M false.
The condlinrec combinator is similar,
it expects a list of pairs or triples of quoted programs.
Pairs consist of an if-part and a then1-part,
and triples consist of an if-part, a rec1-part and a rec2-part.
Again the first if-part that yields true
selects its corresponding then-part or rec1-part for execution.
If there is a rec2-part,
the combinator first recurses and then executes the rec2-part.
The last program is the default,
it does not have an if-part.
The cleave
combinator also has a generalisation,
The construct combinator
expects two parameters,
a quotation and above that a list of quotations.
Each quotation in the list
will produce a value that will eventually be pushed
onto the stack,
and the first quotation determines the stack
onto which these values will be pushed.
L [P] [..[Qi]..] construct => L P ..qi.. :- L Qi => M qi.
Some combinators expect values of specific types below their quotation parameters. The next few combinators expect values of simple types.
The binary combinator branch
expects a truth value below its two quotation parameters:
The branch combinator resembles the
choice
operator and the ifte
combinator.
The truth value below the two quotations
determines which of the two quotations will be executed.
If the truth value is true
,
then the if-part, the second parameter, is executed,
otherwise the then-part, the top parameter, is executed.
true [P] [Q] branch => P. false [P] [Q] branch => Q.
The unary combinator times expects a numeric value
below its quotation parameter:
The times
combinator executes its quotation parameter
as many times as indicated by the numeric value;
if the value is zero or less,
then the quotation is not executed at all.
0 [P] times => id. n [P] times => P (n-1) [P] times.%
The stack is normally a list,
so any list could serve as the stack,
including a list which happens to be on top of the stack.
But the stack can also contain operators and combinators,
although this does not happen often.
So the stack is always a quotation,
and any other quotation could serve as the stack,
including one on top of the stack.
The infra combinator
expects a quotation [P]
which will be executed
and below that another quotation which normally will be just a list [M]
.
The infra
combinator
temporarily discards the remainder of the stack
and takes the quotation or list [M]
to be the stack.
It then executes the top quotation [P]
which yields a result stack.
This resulting stack is then pushed as a list [N]
onto the original
stack replacing the original quotation or list.
Hence any quotation can serve as a complex unary operation
on other quotations or lists.
L [M] [P] infra => L [N] :- [M] unstack P => N.
For linear recursion over numeric types
the if-part often is [null]
and the first recursion part is [dup pred]
.
The primrec combinator has this built in.
For integers the rewrite rules are:
0 [T] [R2] primrec => pop T. i [T] [R2] primrec => i dup pred [T] [R2] primrec R2.The
primrec
combinator can also be used for
aggregates.
The implicit if-part is again [null]
,
and the implicit first recursion part is [rest]
.
Below is the version for lists, the versions for sets and strings
are analogous.
[] [T] [R2] primrec => pop T. [a L] [T] [R2] primrec => a [L] [T] [R2] primrec R2.
The unary combinators step, map, filter and split all expect an aggregate below their quotation parameter.
For step operating on lists the rewrite rule is:
[] [P] step => id. K [a L] [P] step => M [L] [P] step :- K a P => M.For strings and sets the rules are analogous. The same is true of the rules to follow. For map operating on lists the rewrite rule is:
[] [P] map => []. K [a L] [P] map => K [b M] :- K a P => K b, K [L] [P] map => K M.The filter combinator expects a predicate as its quotation parameter.
[] [P] filter => []. K [a L] [P] filter => K [a M] :- K a P => J true, K [L] [P] filter => K [M].
The first list is just like the one from filter
,
the second list is the list of those elements which did
not pass the predicate test [P]
and hence are not members of the first list.
[] [P] split => []. K [a L] [P] split => K [a M] [N] :- K a P => J true, K [L] [P] split => K [M] [N]. K [a L] [P] split => K [M] [a N] :- K a P => J false, K [L] [P] split => K [M] [N].
The unary combinator fold expects a quotation which computes a binary operation. Below that has to be a literal and below that an aggregate. The literal is used as a start value to fold or reduce the aggregate. Applied to lists the combinator has these rules:
[] a [P] fold => a. [b L] a [P] fold => d :- a b P => c, [L] a [P] fold c P => d.
The two unary combinators some and all
expect an aggregate below their
quotation parameter.
The quotation must be a predicate,
yielding a truth value.
The some combinator returns true
if some members
of the aggregate pass the test of the quotation,
otherwise it returns false
.
The all combinator returns true
if all members
of the aggregate pass the test of the quotation,
otherwise it returns false
.
For empty aggregates some
returns false
and all
returns true
.
The rules for some
are:
[] [P] some => false. L [a A] [P] some => L true :- L a P => M true. L [a A] [P] some => L [A] [P] some :- L a P => M false.The rules for
all
are:
[] [P] all => true. L [a A] [P] all => L false :- L a P => M false. L [a A] [P] all => L [A] [P] all :- L a P => M true.
The unary combinator zipwith expects two aggregates and above that a program suitable for combining their respective elements. For lists the rules are
[] [A] [P] zipwith => []. [A] [] [P] zipwith => []. L [a A] [b B] [P] zipwith => L [c C] :- L a b P => M c, L [A] [B] [P] zipwith => L [C].%
This section deals with the role of the Joy stack from a syntactic and semantic point of view.
First, let us consider a quite small arithmetic expression in postfix notation:
2 3 + 8 5 - *A reduction might begin by doing the addition first, or the subtraction first, followed in a second step by the other operation. In fact, the addition and the subtraction could be done in parallel in the same step. Only when both reductions have been done will it be possible to do the final multiplication. The final result is the value
20
,
and it is independent of the order in which
the reductions have been applied.
In detail,
the first mentioned reduction sequence will look like this:
2 3 + 8 5 - * 5 8 5 - * 5 3 * 15One possible strategy for reductions is the following:
Scan the expression from left to right until a redex is found, an expression that can be replaced in accordance with a rewrite rule. Apply the rule. Repeat until no more rules can be applied.
This strategy is most efficient for reducing expressions in which redexes are found early. The following is an example. Again all operators are binary, but note that except at the beginning operators and literals alternate. In each step the first three symbols constitute a redex.
10 5 / 3 * 4 - 1 +The strategy is least efficient when a redex is found late. In the example below, note that all operators occur towards the end.
3 2 6 8 6 - / + *The strategy requires skipping the
3
, 2
and 6
and only then replacing 8 6 -
by 2
.
The next step requires skipping 3
and 2
and only then replacing 6 2 /
by 3
.
The next step requires skipping 3
and only then replacing 2 3 +
by 5
.
The final step requires no skipping,
3 5 *
is replaced by 15
.
All this skipping is of course inefficient.
A better strategy would apply the next operator at the point of the most recent change, if that is possible. An obvious way to do this is to use a stack of values for intermediate results. As the expression is being processed, operands such as literal numbers are pushed, and operators pop their arguments off the stack and push their result. This is of course the method commonly used for evaluating postfix expressions. So we have the following situation: The rewriting rules for programs are purely syntactic, they do not mention the stack. But the stack can be used as an optimisation of the rewrite rules. On the other hand, the stack is apparently an essential semantic entity, it is the argument and value of the functions denoted by programs.
But this now raises the question whether the stack is just an optimisation for the rewriting system or whether it is really needed as a semantic object. In other words, is it possible to give a semantic characterisation of Joy which does not involve a stack at all? In such a semantics the programs will have to denote something, and presumably they will have to denote functions. But what might be the arguments and values of these functions?
It will help to review the stack based semantics of Joy: The literals such as numerals, characters, strings and quotations denote functions taking any stack as argument and producing another stack as value which is like the argument stack except that a single item has been pushed on top. The operators also denote unary functions from stacks to stacks, and the result stack is like the argument stack except that the top few items have been replaced by the result of applying some operation. Likewise, the combinators denote unary functions from stacks to stacks, and the result stack depends on the combinator and the top few quotations.
To obtain a Joy semantics without a stack we take our hint from the rewriting rules. The operators and combinators no longer denote functions from stacks to stacks. The rewrite rule for addition transforms a program ending with two numerals into a program ending with a numeral for their sum. This is the key for a semantics without a stack: Joy programs denote unary functions taking one program as arguments and giving one program as value. The literals denote append operations; the program returned as value is like the program given as argument, except that it has the literal appended to it. The operators denote replacement operations, the last few items in the argument program have to be replaced by the result of applying the operator. Similarly the combinators also denote (higher order) functions from programs to programs, the result program depends on the combinator and the last few quotations of the argument program.
It is clear that such a semantics without a stack is possible and that it is merely a rephrasing of the semantics with a stack. Purists would probably prefer a system with such a lean ontology in which there are essentially just programs operating on other programs. But most programmers are so familiar with stacks that it seems more helpful to give a semantics with a stack. Its is of course irrelevant for the semantics that for efficiency reasons any implementation of Joy will in fact use a stack.
There is one other argument for a stack semantics. By a program one would normally mean one that can be run, at least when supplied with appropriate parameters. The stack, however, can sometimes contain sequences of items that make the stack a non-executable program because it violates type rules. Such situations arise for example by executing one of the following:
[ 3 * ] second [ pop cons map ] [] stepThe first results in the one operator
*
being pushed.
The second results in two operators and one combinator to be pushed.
Such situations are required only rarely.
But the possibility is needed,
for example for a Joy interpreter joy written in Joy itself.
Such an interpreter is described in another paper.
It was mention in section 3 that for quotations there is no rewrite rule of the form
[P] ==> [Q] :- P ==> Q.If there were such a rule, then the rewriting
42 dup ==> 42 42.would license
[ 42 dup ] ==> [ 42 42 ].and hence
[ 42 dup ] second ==>> [ 42 42 ] second. dup ==>> 42.which is absurd. On the other hand,
[ 42 dup ] i + ==> [ 42 42 ] i +is acceptable. So, quotations must not allow substitutions in all contexts, but only in those where the quotation is guaranteed to be undone by a dequoting operation, by a combinator. In other words, quotation is an intensional constructor.
There is a simple way out of this,
and it is to treat quotations of programs to be very different
from lists.
Notice that the absurdity comes from taking the second
element of the quotations [42 dup]
and [42 42]
.
If it were forbidden to treat quoted programs as data structures,
then the fatal inference would be blocked.
In detail,
such a treatment would look like this:
If P
is a program, then (P)
is its quotation,
now written inside round parentheses.
Also, [P]
is its list, as before written inside
square brackets.
Both (P)
and [P]
can be pushed onto the stack,
can be swap
ped, dup
licated and pop
ped,
can be inserted into lists and later extracted.
But only (P)
can be used as a parameter for combinators,
and it cannot treated as a list.
On the other hand, [P]
cannot be used
as a parameter for combinators,
but it can be treated as a list.
Importantly, there could then be a reduction rule
(P) ==> (Q) :- P ==> Q.and hence quotation would be an extensional constructor.
This is a draconian solution, it allows programs such as
[2] cons reversebut forbids
(+) cons mapThe latter uses
map
to add a single number on top of the stack
to each member of a list that is second on the stack.
If the single number on top of the stack is, say 7
,
then the cons
operation produces (7 +)
to be used by map
.
The prohibition would rule out parameterisation.
In general,
the prohibition would rule out using constructed programs
as parameters to combinators.
It is possible to make a less drastic compromise:
As before, quotations (P)
serve as parameters to combinators,
but they can also be built up by list operations
such as concat
enation or cons
ing
further items into their front.
This would allow parameterisation as in the map
example above.
Quotations could be constructed and built up further and further
and eventually called by a combinator,
but quotations could not be destructed.
On this proposal constructive operations on quotations
would be allowed, but destructive operations would not.
All list operations would need to be classified as constructive
or destructive.
Even the size
operator would turn out to be destructive.
This compromise solution has much in its favour. Quotation is extensional, combinators can use constructed programs, but the absurdity does not arise. On the other hand, the compromise requires a syntactic distinction between quotations and lists, and it requires a semantic distinction between operations that can be applied to lists and to quotations, and those that can be applied only to lists.
On the whole, then, it does seem preferable to have quotation as an intensional constructor.
The rewriting system described up to here concerned values.
It is also possible to give a rewriting system for Joy type expressions.
We shall need constant and variable symbols for these types.
The following will be used as type constants:
Log
for the truth values,
Chr
for the characters,
Int
for the integers,
Set
for the sets,
Str
for the strings and
Lst
for possibly heterogeneous lists.
For lists whose member are all of the same type, say Int
,
the notation [Int]
will be used.
As variables we use
T
, T1
, T2
and so on.
So [T]
is the type of lists whose members are all of
the type T
.
The following is a sample of one style of rules for operators:
T1 T2 swap => T2 T1. Int Int + => Int. Str size => Int.The notation used above has been made as close as possible to the notation for the rewriting rules for values. In the following a different notation will be introduced which is more useful.
Literals have atomic types,
operators and combinators have compound types.
There are three constructors for compound types:
type concatenation, type quotation and type cancellation.
The first two are derived from the corresponding program constructors.
The third is new and has no counterpart program constructor.
It uses the infix symbol -> to combine two types into a new one.
If T
is a type, then so is its quotation [T]
.
If T1
and T2
are types,
then so are their concatenation
(T1 T2)
and their cancellation T1->T2
.
If P1
and P2
are programs of types
T1
and T2
,
then the type of their concatenation (P1 P2)
is the concatenation (T1 T2)
of their types.
Cancellation satisfies the law
T1 T1->T2 => T2For types with concatenated parameter types:
(T1 T2)->T3 => T1->(T2->T3)The expression on the right of the arrow can be written without parentheses on the convention that the cancellation operator
\
is taken to be right associative.
The three rules given above should now be rewritten in this style:
swap => (T1 T2) -> (T2 T1). + => (Int Int) -> Int. size => Str -> Int.
The following are a sample of further rules in the two styles: Those in the left column are in the earlier style, those in the right are in the new style.
Chr succ => Chr. succ => Chr->Chr. Int Int > => Log. > => (Int Int)->Log. Log Log and => Log. and => (Log Log)->Log. [T Lst] first => T. first => [T Lst]->T. [T Lst] rest => Lst. rest => [T Lst]->Lst. T Lst cons => [T Lst]. cons => (T Lst)->[T Lst]. [T Lst] uncons => T Lst. uncons => [T Lst]->(T Lst). Chr Str cons => Str. cons => (Chr Str)->Str. Set null => Log. null => Set->Log.Consider now the program
P
below.
Its type is given by the concatenation of the types of its parts,
in the line just below.
All the types here are built from the atomic type Int
of integers.
By four applications of cancellation the type in line 1 is simplified
to the type Int
in line 4.
P: 2 3 + dup * 1. Int Int (Int Int)->Int Int->(Int Int) (Int Int)->Int 2. Int Int->(Int Int) (Int Int)->Int 3. (Int Int) (Int Int)->Int 4. Int
For combinators only only a few examples will be given here, for i and map.
i => [T] -> T. map => ([T1 -> T2]) -> ([T1] -> [T2]).
The formalism used in this section is that of categorial grammars. These have their origin in the (simple) theory of types and as generating devices are as powerful as context free grammars. Expositions and applications are to be found in the volume edited by \AX{Oehrle {\it et al}}{1988}{Oehrle-etal:88}, see in particular the contributions by \X{Casadio} and \X{Lambek}. Another reference is the volume edited by \AX{Buskzkowski {\it et al}}{1988}{Buszkowski-etal:88}.
Rewriting systems are purely syntactic. If the object language has a semantics, then the rewriting rules have to be shown to be correct with reepsect to this semantics. This is true of the rewriting rules of the previous sections which dealt with values. It is also true for the rewriting rules for types. The basic semantic notion here is that of assigning types to programs. These take the form
P : Twhich is not a rewriting rule but a statement which says that program
P
is of type T
.
The basic type statements are to atomic programs,
literals, operators and combinators.
Here are some examples:
42 : Int 'A : Chr succ : Chr -> Chr > : Int Int -> Log first : [T Lst] -> T i : [T] -> TThis is the style adopted in the Joy manual. To obtain rewrite rules using => a single conditional rule is needed which converts the semantic predicate : into the syntactic
=>
,
as follows.
X => T :- X : T.
The material in this section has very tentative, most of the details need to be worked out fully.


Freelancer Web Matching Service
Freelancer - Client Web Matching Service
Using nodejs (backend) + reactjs (frontend)
Full responsive application
Demo
https://github.com/jgtonys/freelancer-web-matching.git
How to run
- git clone
- root directory -
npm install
- client directory -
npm install
- root directory -
npm start
To build client files
npm run build
Functions
Token authentication (JWT) + Session-Storage
File upload with Multer
Encryption with Bcrypt
Development Environment
es6(babel), axios, node-sass, SPA, webpack
Backend
"dependencies": {
"async": "^2.6.0",
"bcrypt": "^3.0.2",
"body-parser": "^1.18.2",
"express": "^4.16.3",
"jsonwebtoken": "^8.2.0",
"lodash": "^4.17.5",
"multer": "^1.4.1",
"mysql2": "^1.6.1"
}
Frontend
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/polyfill": "^7.0.0",
"@material-ui/core": "^3.4.0",
"@material-ui/icons": "^3.0.1",
"axios": "^0.18.0",
"babel-runtime": "^6.26.0",
"bootstrap": "^4.1.3",
"cross-env": "^5.2.0",
"css-loader": "^1.0.1",
"node-sass": "^4.9.4",
"react": "^16.6.0",
"react-dom": "^16.6.0",
"react-pdf": "^4.0.0",
"react-redux": "^5.1.0",
"react-router": "^4.3.1",
"react-router-dom": "^4.3.1",
"react-swipeable-views": "^0.13.0",
"react-text-mask": "^5.4.3",
"reactstrap": "^6.5.0",
"redux": "^4.0.1",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"webpack": "^4.23.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
},
"devDependencies": {
"@babel/core": "^7.1.2",
"@babel/preset-env": "^7.1.0",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.4",
"html-webpack-plugin": "^3.2.0"
}
Structure
- app (backend)
- controller (server app controller)
- models (database models)
- routes (routing)
- client (frontend)
- config
- config.js (port, session setting)
- db.js (database setting)
- express.js
- jwt.js (optional, token authentication)
- server.js
- package.json (npm install modules, description)
Comments


22
1 Yahweh spoke to Moses, saying,
2 "Speak to Aaron and to his sons, tell them to keep away from the holy things of the people of Israel, which they dedicate to me. They must not profane my holy name. I am Yahweh.
3 Say to them, 'Anyone among all your descendants throughout your people's generations who is unclean when he approaches the holy things that the people of Israel dedicate to Yahweh, that person must be cut off from before me. I am Yahweh.
4 None of the descendants of Aaron who has an infectious skin disease, or an infection flowing from his body, may eat any of the sacrifices made to Yahweh until he is clean. Whoever touches anything unclean through contact with the dead, or by contact with a man who has a flow of semen,
5 or whoever touches any creeping animal that makes him unclean, or any person who makes him unclean, whatever kind of uncleanness it may be—
6 then the priest who touches anything unclean will be unclean until evening. He must not eat any of the holy things, unless he has bathed his body in water.
7 When the sun has set, he will then be clean. After sunset he may eat from the holy things, because they are his food.
8 He must not eat anything found dead or killed by wild animals, by which he would defile himself. I am Yahweh.
9 The priests must follow my instructions, or they will be guilty of sin and could die for profaning me. I am Yahweh, who dedicates them to myself.
10 No one outside the priest's family, including guests of a priest or his hired servants, may eat anything that is holy.
11 But if a priest buys any slave with his own money, that slave may eat from the things set apart for Yahweh. And the priest's family members and slaves born in his house, they also may eat with him from those things.
12 If a priest's daughter married someone who is not a priest, she may not eat any of the holy contribution offerings.
13 But if a priest's daughter is a widow, or divorced, and if she has no child, and if she returns to live in her father's house as in her youth, she may eat from her father's food. But no one who is not in the priestly family may eat from the priest's food.
14 If a man eats a holy food without knowing it, then he must repay the priest for it; he must add one fifth to it and give it back to the priest.
15 The people of Israel must not dishonor the holy things that they have raised high and presented to Yahweh,
16 and cause themselves to carry the sin that would make them guilty of eating the holy food, for I am Yahweh, who dedicates them to myself.'"
17 Yahweh spoke to Moses, saying,
18 "Speak to Aaron and his sons, and to all the people of Israel. Say to them, 'Any Israelite, or an alien living in Israel, when they present a sacrifice—whether it is to fulfill a vow, or whether it is a freewill offering, or they present to Yahweh a burnt offering,
19 if it is to be accepted, they must offer a male animal without blemish from the cattle, sheep, or goats.
20 But you must not offer whatever has a blemish. I will not accept it on your behalf.
21 Whoever offers a sacrifice of fellowship offerings from the herd or the flock to Yahweh to fulfill a vow, or as a freewill offering, it must be unblemished to be accepted. There must be no defect in the animal.
22 You must not offer animals that are blind, disabled, or maimed, or that have warts, sores, or scabs. You must not offer these to Yahweh as a sacrifice by fire on the altar.
23 You may present as a freewill offering an ox or a lamb that is deformed or small, but an offering like that will not be accepted for a vow.
24 Do not offer animals to Yahweh that have bruised, crushed, torn, or cut reproductive organs. Do not offer these in your land,
25 and do not accept them from a foreigner's hand as food presented to God, because there are defects or blemishes in them. I will not accept them on your behalf.' "
26 Yahweh spoke to Moses and said,
27 "When a calf or a sheep or a goat is born, it must remain seven days with its mother. Then from the eighth day on, it may be accepted as a sacrifice for an offering made by fire to Yahweh.
28 Do not kill a cow or ewe along with its young, both on the same day.
29 When you sacrifice a thank offering to Yahweh, you must sacrifice it in an acceptable way.
30 It must be eaten on the same day that it is sacrificed. You must leave none of it until the next morning. I am Yahweh.
31 So you must keep my commandments and carry them out. I am Yahweh.
32 You must not dishonor my holy name. I must be acknowledged as holy by the people of Israel.  I am Yahweh."


SWEET CHARITY
Director & Choreographer - Ricardo Robinson
Musical Director - Juna Broome
Accompanist - Charles Bridges
Stage Manager - Susan Mangum
Producer - Linda Montgomery
THE CAST
Charity Hope Valentine - Nikki Johnson
Nickie - Juna Broome
Helene - Pam Johnson
Carmen - Amanda Hall
Frenchy - Lacy Hinton
Rosie - Holly McCann
Elaine - Misty Stokley
Suzanne - Nora Walters
Ursula - Rikki McNeely
Betsy - Jessica Wade
Herman - Sam Buchanan
Vittorio - Gerald Wansley
Oscar - Kyle Chesney
Daddy Brubeck - A.J. Reynolds
Asst. to Brubeck - Dallen Boutwell
Asst. to Brubeck - Wesley Slade
Charlie - Kenny Jordan
Tammy Daniel, Martha Kay Holifield, Brent Holifield, Kate Jones,
Tod Lightsey, Gabby Mooney, Jeremy Nix, Brandon Nixon,
Taylor Pounds, Megan Ruffin, Swayze Swindle


Let \({\bf x}\,\) be the position vector in three dimensions, with \(r=|{\bf x}\,|\), and let \(\bf a\) be a constant vector. Using index notation, show that
\(\quad {\rm div}\,{\bf x}\,\,=\,3\),
\[{\rm div}\,{\bf x}\,=\frac{\partial x_i}{\partial x_i}=\delta_{ii}=3\,.\]
\(\quad {\rm curl}\,{\bf x}\,\,=0\),
\[({\rm curl}\,{\bf x}\,)_i =\varepsilon_{ijk}\frac{\partial x_k}{\partial x_j} =\varepsilon_{ijk}\delta_{jk}=0\,,\] using the fact that \(\varepsilon_{ijk}\) is antisymmetric under swaps of \(j\) and \(k\) while \(\delta_{jk}\) is symmetric.
\(\quad {\rm grad}\,r\,=\,{\bf x}\,/r\),
\[\begin{aligned} ({\rm grad}\,r)_i= \frac{\partial}{\partial x_i}r &= \frac{\partial}{\partial x_i}(x_jx_j)^{1/2} \\ &= \frac{1}{2}(x_jx_j)^{-1/2}\,\frac{\partial}{\partial x_i} x_k x_k \\ &= \frac{1}{2}(x_jx_j)^{-1/2}\,(2\delta_{ik}x_k) \\ &= (x_jx_j)^{-1/2}\,x_i \\ &= x_i/r\,. \end{aligned}\]
\(\quad {\rm div}\,(r^n {\bf x}\,)\,=\,(n+3)\, r^n\),
\[\begin{aligned} {\rm div}\,(r^n{\underline{x}}) &=\frac{\partial}{\partial x_i}(r^nx_i) =(\frac{\partial}{\partial x_i}r^n)x_i +r^n(\frac{\partial}{\partial x_i}x_i) =nr^{n-1} (\frac{\partial}{\partial x_i}r)x_i +r^n\delta_{ii}\\ &=nr^{n-1}(x_i/r)\,x_i+3r^n =nr^n+3r^n=(n+3)r^n. \end{aligned}\]
\(\quad {\rm grad}\,({\bf a}\cdot {\bf x}\,)\,=\,{\bf a}\),
\[({\rm grad}\,({\underline{a}}\cdot{\underline{x}}))_i= \frac{\partial}{\partial x_i}(a_jx_j)=a_j \frac{\partial}{\partial x_i}x_j =a_j\delta_{ij}=a_i\,.\]
\(\quad {\rm div}\,( {\bf a}\times{\bf x}\,)\,=0\),
\[{\rm div}\,({\underline{a}}\times{\underline{x}}) =\frac{\partial}{\partial x_i}(\varepsilon_{ijk}a_jx_k) =\varepsilon_{ijk}a_j\delta_{ik}=0\,,\] using the fact that \(\varepsilon_{ijk}\) is antisymmetric under swaps of \(i\) and \(k\) while \(\delta_{ik}\) is symmetric.
\(\quad {\rm curl}\,({\bf a}\times{\bf x}\,)\,=\,2\,{\bf a}\),
\[\begin{aligned} ({\rm curl}\,({\underline{a}}\times{\underline{x}}))_i & = \varepsilon_{ijk}\frac{\partial}{\partial x_j}(\varepsilon_{klm}a_lx_m) = \varepsilon_{ijk} \varepsilon_{klm} a_l \frac{\partial}{\partial x_j} x_m \\ & = (\delta_{il}\delta_{jm}- \delta_{im}\delta_{jl}) a_l \frac{\partial}{\partial x_j} x_m = (\delta_{il}\delta_{jm}- \delta_{im}\delta_{jl}) a_l \delta_{jm}\\ &=a_i\delta_{jj}-\delta_{ij}a_j=3a_i-a_i=2a_i\,. \end{aligned}\]
\(\quad {\rm curl}\,( r^2 {\bf a})\,=\,2\, ({\bf x}\,\times{\bf a})\),
\[\begin{aligned} ({\rm curl}\,( r^2 {\bf a}))_i &=\varepsilon_{ijk}\frac{\partial}{\partial x_j}(r^2{\bf a}_k) =\varepsilon_{ijk}\Bigl(\frac{\partial}{\partial x_j}r^2\Bigr){\bf a}_k\\[2pt] &=\varepsilon_{ijk}2r\frac{\partial r}{\partial x_j}\,{\bf a}_k =\varepsilon_{ijk}2r\frac{x_j}{r}\,{\bf a}_k =(2\, ({\bf x}\,\times{\bf a}))_i\,. \end{aligned}\]
\(\quad \nabla^2 (1/r)\,=\,0\) if \(r\ne 0\) : using \(\frac{\partial}{\partial x_i}r=x_i/r\) from part (c),
\[\begin{aligned} \nabla^2 (1/r)&= \frac{\partial}{\partial x_i} \frac{\partial}{\partial x_i}(r^{-1}) = \frac{\partial}{\partial x_i} \bigl(-r^{-2}\frac{\partial}{\partial x_i}r \bigr) = \frac{\partial}{\partial x_i} \bigl(-r^{-3}x_i \bigr) \\[2pt] &= -\bigl(\frac{\partial}{\partial x_i} r^{-3} \bigr) x_i -r^{-3} \bigl(\frac{\partial}{\partial x_i}x_i\bigr) = 3r^{-4}\bigl(\frac{\partial}{\partial x_i}r\bigr)x_i -r^{-3} \delta_{ii} \\[3pt] &= 3r^{-5} x_ix_i -3r^{-3} =(3-3)r^{-3}=0\,. \end{aligned}\] Notice that this is only valid for \(r\neq 0\) since the calculation involves division by \(r\).
\(\quad \nabla^2 (\log r)\,=\,1/r^2\) if \(r\ne 0\) :
as in part (i), and using \(\frac{\partial}{\partial x_i}r=x_i/r\) again, \[\begin{aligned} \nabla^2 (\log r)&= \frac{\partial}{\partial x_i} \frac{\partial}{\partial x_i}(\log r) = \frac{\partial}{\partial x_i} \bigl(r^{-1}\frac{\partial}{\partial x_i}r \bigr) = \frac{\partial}{\partial x_i} \bigl(r^{-2}x_i \bigr) \\[2pt] &= \bigl(\frac{\partial}{\partial x_i} r^{-2} \bigr) x_i +r^{-2} \bigl(\frac{\partial}{\partial x_i}x_i\bigr) = -2r^{-3}\bigl(\frac{\partial}{\partial x_i}r\bigr)x_i +r^{-2} \delta_{ii} \\[3pt] &= -2r^{-4} x_ix_i +3r^{-2} =(-2+3)r^{-2}=1/r^2. \end{aligned}\] Again, this is only valid for \(r\neq 0\) since the calculation involves division by \(r\).
\(\quad {\rm div}\,[ ({\bf a}\cdot {\bf x}\,) {\bf x}\,]\,=\,4\, {\bf a}\cdot {\bf x}\,\),
\[\begin{aligned} {\rm div}\,[ ({\bf a}\cdot {\bf x}\,) {\bf x}\,] &= \frac{\partial}{\partial x_i} \bigl( a_jx_jx_i\bigr)= a_j\frac{\partial}{\partial x_i} \bigl( x_jx_i\bigr)= a_j\Bigl( \bigl(\frac{\partial}{\partial x_i}x_j\bigr)x_i +x_j\bigl(\frac{\partial}{\partial x_i}x_i\bigr)\Bigr)\\[4pt] &= a_j\bigl(\delta_{ij}x_i+x_j\delta_{ii}\bigr) = a_j\bigl(x_j+3x_j\bigr) =4a_jx_j=4{\underline{a}}\cdot{\underline{x}}\,. \end{aligned}\] Using \({\rm div}\,f {\bf V}=(\nabla f)\cdot {\bf V}+f{\rm div}\,{\bf V}\), with \(f={\bf a} \cdot {\bf x}\,\) so \(\nabla f={\bf a}\) from part (e) and \({\bf V}={\bf x}\,\) so \({\rm div}\,{\bf x}\,=3\) from part (a) hence \({\rm div}\,[ ({\bf a}\cdot {\bf x}\,) {\bf x}\,]\,={\bf a}\cdot{\bf x}\,+{\bf a}\cdot{\bf x}\,3=4{\bf a}\cdot{\bf x}\,\).
\(\quad {\rm div}\,[ {\bf x}\,\times( {\bf x}\,\times{\bf a})]\,=\,2\, {\bf a}\cdot {\bf x}\,\),
\[\begin{aligned} {\rm div}\,[ {\bf x}\,\times( {\bf x}\,\times{\bf a})] &= \frac{\partial}{\partial x_i}\left( \varepsilon_{ijk}x_j\varepsilon_{klm}x_la_m\right) = \varepsilon_{ijk} \varepsilon_{klm} \frac{\partial}{\partial x_i}\left( x_jx_l\right)a_m\\[3pt] &= \left(\delta_{il}\delta_{jm}-\delta_{im}\delta_{jl}\right) \frac{\partial}{\partial x_i}\left( x_jx_l\right)a_m\\[3pt] &= \frac{\partial}{\partial x_i}\left( x_jx_i\right)a_j - \frac{\partial}{\partial x_i}\left( x_jx_j\right)a_i \\[3pt] &= \delta_{ij}x_ia_j+x_j\delta_{ii}a_j- \delta_{ij}x_ja_i-x_j\delta_{ij}a_i\\[3pt] &=x_ja_j+3x_ja_j-x_ja_j-x_ja_j=2x_ja_j=2{\underline{a}}\cdot{\underline{x}}\,. \end{aligned}\]
\(\quad {\rm curl}\,\left( {{{\bf a}\times{\bf x}\,}/ {r^3}} \right)\,= \, 3\, {{({\bf a}\cdot {\bf x}\,) {\bf x}\,}/{r^5}}\,-\,{{{\bf a}}/{r^3}}\),
\[\begin{aligned} \left({\rm curl}\,\left( {{{\bf a}\times{\bf x}\,}/ {r^3}} \right)\right)_i &= \varepsilon_{ijk}\frac{\partial}{\partial x_j}\left( \varepsilon_{klm}a_lx_m/r^3 \right) = \varepsilon_{ijk} \varepsilon_{klm}a_l \frac{\partial}{\partial x_j}\left( x_m/r^3 \right) \\[3pt] &= \varepsilon_{ijk} \varepsilon_{klm}a_l \Bigl( \delta_{jm}r^{-3} +x_m\frac{\partial}{\partial x_j}r^{-3} \Bigr) \\[3pt] &= \varepsilon_{ijk} \varepsilon_{klm}a_l \Bigl( \delta_{jm}r^{-3} -3x_mr^{-4}\frac{\partial}{\partial x_j}r \Bigr) \\[3pt] &= \varepsilon_{ijk} \varepsilon_{klm}a_l \Bigl( \delta_{jm}r^{-3} -3x_mr^{-5}x_j \Bigr) \\[3pt] &= \left(\delta_{il}\delta_{jm}-\delta_{im}\delta_{jl} \right)a_l \Bigl( \delta_{jm}r^{-3} -3x_mr^{-5}x_j \Bigr) \\[3pt] &= a_i\delta_{jj}r^{-3}-a_j\delta_{ij}r^{-3} -3a_ix_jr^{-5}x_j+3a_jx_ir^{-5}x_j \\[3pt] &= 3a_ir^{-3}-a_ir^{-3}-3a_ir^{-3}+3x_ia_jx_jr^{-5} \\[3pt] &=-a_ir^{-3}+3x_ia_jx_jr^{-5} =\left(-{\underline{a}}/r^3+3{\underline{x}}({\underline{a}}\cdot{\underline{x}})/r^5\right)_i\,. \end{aligned}\] Remark: in this question, and also in some of the earlier ones, there is some freedom in the order in which you, for example, use the product rule on derivatives, use the very useful formula, and simplify \(\delta\)s involving summed indices. In such cases any order is fine – the final answer will be the same.
Exam question June 2002 (Section A): calculate the curl of \(({\bf a}\cdot {\bf x}\,)~ {\bf x}\,\).
\[\begin{aligned} \bigl({\rm curl}\,(({\bf a}\cdot {\bf x}\,)\, {\bf x}\,)\bigr)_i &= \varepsilon_{ijk}\frac{\partial}{\partial x_j}\bigl( a_lx_lx_k\bigr) \\[3pt] &= \varepsilon_{ijk}a_l\bigl(\delta_{jl}x_k+x_l\delta_{jk}\bigr) \\[3pt] &= \varepsilon_{ijk}a_jx_k+\varepsilon_{ijj}a_lx_l =\varepsilon_{ijk}a_jx_k=\bigl({\underline{a}}\times{\underline{x}}\bigr)_i\,, \end{aligned}\] using the fact that \(\varepsilon_{ijj}=0\), by the antisymmetry of the Levi-Civita symbol. Note: in the first line \({\underline{a}}\cdot{\underline{x}}\) was written using \(l\) as the repeated index rather than \(j\) or \(k\), since \(j\) and \(k\) were already being used to write the curl.
General remark: Even though some of these index notation calculations look a little long, they are (almost) all self-contained, while in the version of this question on the Topic 3 sheet, there was much more quoting of results from other parts.
The vector \({\underline{a}}\) has components \((a_r)=(1,1,1)\) and the vector \({\underline{b}}\) has components \((b_r)=(2,3,4)\). In the following expressions state which indices are free and which are dummy, and give the numerical values of the expressions for each value that the free variable takes (e.g. for \(a_r-b_r\) the free variable is \(r\) and it takes the values \(1,\, 2,\, 3\) so \(a_1-b_1=-1\), \(a_2-b_2=-2\), \(a_3-b_3=-3\) )
\(a_r+b_r\),
\(r\) is a free index so we need to specify 3 pieces of information. \(a_r+b_r\) is the r-th component of the vector \({\underline{a}}+{\underline{b}}\) so we can give the information in the form \((a_r+b_r)=(3,4,5)\) or as \(a_1+b_1=3\), \(a_2+b_2=4\), \(a_3+b_3=5\).
\(a_r\, b_r\),
\(r\) is a dummy index and \(a_r\,b_r=a_1\,b_1+a_2\,b_2+a_3\,b_3=9\), which is the scalar product of \({\underline{a}}\) and \({\underline{b}}\).
\(a_r\,b_s\,a_r\),
\(r\) is a dummy index, and \(s\) is free so to specify \(a_r\,b_s\,a_r\) we need to specify 3 pieces of information, these are the components of the vector \({\underline{b}} \,{\underline{a}}\cdot{\underline{a}}\). Now \(a_r\,a_r=a_1^2+a_2^2+a_3^2=3\) so \((a_r\,b_s\,a_r)=(3b_s)=(6,9,12)\)
\(a_r\,b_s\,a_r\,b_s-a_r\,b_r\,a_s\,b_s\).
\(r\) and \(s\) are both dummy indices. \(a_r\,b_s\,a_r\,b_s-a_r\,b_r\,a_s\,b_s= (a_r\,a_r)(b_s\,b_s)-(a_r\,b_r) (a_s\,b_s)\) now \(a_r\,a_r=3\) and \(b_s\,b_s=4+9+16=29\) so \(a_r\,b_s\,a_r\,b_s-a_r\,b_r\,a_s\,b_s=3\times 29-9^2=6\).
If \(\delta_{rs}\) is the three-dimensional Kronecker delta, evaluate
\(\delta_{rs}\,\delta_{sr}\,\delta_{pq}\,\delta_{pq}\),
\(\delta_{rs}\,\delta_{sr}\,\delta_{pq}\,\delta_{pq}= \delta_{rr}\,\delta_{pq}\,\delta_{pq}=3\,\delta_{pp}=3\times 3=9\).
\(\delta_{rs}\,\delta_{sk}\,\delta_{kl}\,\delta_{lr}\),
\(\delta_{rs}\,\delta_{sk}\,\delta_{kl}\,\delta_{lr}= \delta_{rk}\,\delta_{kl}\,\delta_{lr}=\delta_{rl}\,\delta_{lr}= \delta_{rr}=3\).
\(\delta_{rs}\,\delta_{qr}\,\delta_{pq}\,\delta_{sp}\).
\(\delta_{rs}\,\delta_{qr}\,\delta_{pq}\,\delta_{sp}= \delta_{qs}\,\delta_{pq}\,\delta_{sp}=\delta_{ps}\,\delta_{sp}= \delta_{ss}=3\).
If \(\delta_{rs}\) is the three-dimensional Kronecker delta, simplify
\((\delta_{rp}\,\delta_{sq}-\delta_{rq}\, \delta_{sp})\,a_p\,b_q\),
\((\delta_{rp}\,\delta_{sq}-\delta_{rq}\, \delta_{sp})\,a_p\,b_q=\delta_{rp}\,\delta_{sq}\,a_p\,b_q -\delta_{rq}\,\delta_{sp}\,a_p\,b_q=\,a_r\,b_s-\,a_s\,b_r\,,\)
\((\delta_{rp}\,\delta_{sq}-\delta_{rq}\, \delta_{sp})\,\delta_{pq}\).
\((\delta_{rp}\,\delta_{sq}-\delta_{rq}\, \delta_{sp})\,\delta_{pq}=\delta_{rp}\,\delta_{sq}\,\delta_{pq}- \delta_{rq}\,\delta_{sp}\,\delta_{pq}=\delta_{rs}-\delta_{rs}=0\) .
If \(\delta_{rs}\) is the Kronecker delta in \(n\) dimensions, calculate
\(\delta_{rr}\),
\(\delta_{rr}=1+1+..+1\) (n terms), so \(\delta_{rr}=n\),
\(\delta_{rs}\,\delta_{rs}\),
\(\delta_{rs}\,\delta_{rs}=\delta_{rr}=n\),
\(\delta_{rs}\,\delta_{st}\,\delta_{tr}\).
\(\delta_{rs}\,\delta_{st}\,\delta_{tr}= \delta_{rs}\,\delta_{sr}=\delta_{rr}=n\).
Starting from \(\varepsilon_{ijk}\,\varepsilon_{klm}
=\delta_{il}\,\delta_{jm}-\delta_{im}\,\delta_{jl}\) simplify as much as possible:
\(\varepsilon_{ijk}\varepsilon_{ijp}\) ,
First use the cyclic symmetry of \(\varepsilon_{ijk}\) to rewrite the expression with the repeated indices next to each other: \(\varepsilon_{ijk}\varepsilon_{ijp}= \varepsilon_{jki}\varepsilon_{ijp}\) . Then, relabelling in the starting formula, \[\varepsilon_{jki}\varepsilon_{ijp} =\delta_{jj}\,\delta_{kp}-\delta_{jp}\,\delta_{kj} =3\,\delta_{kp}-\delta_{kp}=2\,\delta_{kp}\]
\(\varepsilon_{ijk}\varepsilon_{ijk}\).
Substituting \(p=k\) into part (a), \[\varepsilon_{ijk}\varepsilon_{ijk}=2\,\delta_{kk}=6\]
Calculate \(\varepsilon_{ijj}\) .
\(\varepsilon_{ijk}\) vanishes whenever two indices take the same value, so \(\varepsilon_{ijj}\) also vanishes, being a sum of terms in each of which the last two indices take the same value.
Show, using index notation, that
\(~ {\bf a}\times({\bf b}\times{\bf c})\,+\, {\bf b}\times({\bf c}\times{\bf a})\,+\,{\bf c}\times ({\bf a}\times{\bf b})\, =\,0\) ,
The \(i\)-th component of \(\quad {\bf a}\times({\bf b}\times{\bf c})\) is \[\begin{aligned} \varepsilon_{ijk}\,a_j\,(\varepsilon_{krs}\,b_r\,c_s)&= (\varepsilon_{ijk}\,\varepsilon_{rsk})\,a_j\,b_r\,c_s= (\delta_{ir}\,\delta_{js}-\delta_{is}\,\delta_{jr})\,a_j\,b_r\,c_s\\ &= \delta_{ir}\,\delta_{js}\,a_j\,b_r\,c_s-\delta_{is}\,\delta_{jr}\,a_j\,b_r\,c_s =\,a_s\,b_i\,c_s-\,a_r\,b_r\,c_i \end{aligned}\] so the \(i\)-th component of \({\bf a}\times({\bf b}\times{\bf c})\,+\, {\bf b}\times({\bf c}\times{\bf a})\,+\,{\bf c}\times ({\bf a}\times{\bf b})\) is \[\begin{aligned} &\hspace{-30pt} (a_s\,b_i\,c_s-\,a_r\,b_r\,c_i)+(b_s\,c_i\,a_s-\,b_r\,c_r\,a_i)+(c_s\,a_i\,b_s-\,c_r\,a_r\,b_i)\\ &= a_i\, (c_s\,\,b_s-\,b_r\,c_r)+b_i\,(a_s\,c_s-\,c_r\,a_r)+c_i\,(b_s\,a_s -\,a_r\,b_r)=0 \end{aligned}\] since the names of dummy indices can be changed.
\(~ ({\bf a}\times{\bf b}) \times({\bf c}\times{\bf d})\,=\, \left[{\bf d}\cdot ({\bf a}\times{\bf b})\right] {\bf c}\,-\, \left[{\bf c}\cdot ({\bf a}\times{\bf b})\right] {\bf d}\\[2pt] ~~\quad\qquad\qquad\qquad \ \ \ =\,\left[{\bf a}\cdot ({\bf c}\times{\bf d})\right] {\bf b}\,-\, \left[ {\bf b}\cdot ({\bf c}\times{\bf d})\right] {\bf a},\)
The \(i\)-th component of \(({\bf a}\times{\bf b}) \times({\bf c}\times{\bf d})\) is
\[\begin{aligned}
\varepsilon_{ijk}\,\left(\varepsilon_{jrs}\,a_r\,b_s\right)\,\left(\varepsilon_{kpq}\,c_p\,d_q\right)&=
\varepsilon_{ijk}\,\varepsilon_{jrs}\,\varepsilon_{kpq}\,a_r\,b_s\,c_p\,d_q\\
&=(\varepsilon_{jki}\,\varepsilon_{jrs})\,\varepsilon_{kpq}\,a_r\,b_s\,c_p\,d_q \\
&=\delta_{kr}\,\delta_{is}\,\varepsilon_{kpq}\,a_r\,b_s\,c_p\,d_q-\delta_{ks}\,\delta_{ir}\,\varepsilon_{kpq}\,a_r\,b_s\,c_p\,d_q\\
&=\varepsilon_{rpq}\,a_r\,b_i\,c_p\,d_q-
\varepsilon_{spq}\,a_i\,b_s\,c_p\,d_q
\end{aligned}\] which is the same as the \(i\)-th component of \(\left[{\bf a}\cdot ({\bf c}\times{\bf d})\right] {\bf b}\,-\,
\left[ {\bf b}\cdot ({\bf c}\times{\bf d})\right] {\bf a}\) , because this is \[\left[ \, a_r\,( \varepsilon_{rpq} \,c_p\,d_q) \right]\,b_i\,
\,-\,
\left[ \,b_s\, (\varepsilon_{spq}\,c_p\,d_q ) \right]\,a_i\] We can also expand the \(i\)-th component of \(({\bf a}\times{\bf b}) \times
({\bf c}\times{\bf d})\) as \[\varepsilon_{ijk}\,\left(\varepsilon_{jrs}\,a_r\,b_s\right)\,\left(\varepsilon_{kpq}\,c_p\,d_q\right)=
\varepsilon_{ijk}\,\varepsilon_{jrs}\,\varepsilon_{kpq}\,a_r\,b_s\,c_p\,d_q\] \[(\varepsilon_{ijk}\,\varepsilon_{pqk})\,\varepsilon_{jrs}\,a_r\,b_s\,c_p\,d_q
=
\delta_{ip}\,\delta_{jq}\,\varepsilon_{jrs}\,a_r\,b_s\,c_p\,d_q-\delta_{iq}\,\delta_{jp}\,\varepsilon_{jrs}\,a_r\,b_s\,c_p\,d_q\] \[=
\varepsilon_{qrs}\,a_r\,b_s\,c_i\,d_q \varepsilon_{prs}\,a_r\,b_s\,c_p\,d_i\] which is the same as the \(i\)-th component of \(\left[{\bf d}\cdot ({\bf a}\times{\bf b})\right] {\bf c}\,-\,
\left[{\bf c}\cdot ({\bf a}\times{\bf b})\right] {\bf d}\) , because this is \[\left[ \,d_q\,( \varepsilon_{qrs}\,a_r\,b_s )\right]\,c_i\,
-\,
\left[ \,c_p \,( \varepsilon_{prs}\,a_r\,b_s\, )\right]\, d_i \,.\]
\(~ ({\bf a}\times{\bf b}) \cdot ({\bf c}\times{\bf d})\,=\, ({\bf a}\cdot {\bf c}) ({\bf b}\cdot {\bf d})\,-\, ({\bf a}\cdot {\bf d}) ({\bf b}\cdot {\bf c})\) ,
\[\begin{aligned} ({\bf a}\times{\bf b}) \cdot ({\bf c}\times{\bf d}) &= ({\bf a}\times{\bf b})_i({\bf c}\times{\bf d})_i \\ &= \epsilon_{ijk}a_jb_k \epsilon_{ilm}c_l d_m \\ &= \epsilon_{ijk}\epsilon_{ilm} a_jb_k c_l d_m \\ &= (\delta_{jl}\delta_{km} - \delta_{jm}\delta_{kl}) a_jb_k c_l d_m \\ &= a_j c_j b_k d_k - a_j d_j b_k c_k \\ &= ({\bf a}\cdot {\bf c})({\bf d}\cdot {\bf b}) - ({\bf a}\cdot {\bf d})({\bf b}\cdot {\bf c}). \end{aligned}\]
\(\quad {\bf a}\times[ {\bf a}\times( {\bf a} \times{\bf b})]\,=\, a^2\, ( {\bf b}\times{\bf a})\) ,
Note that the left-hand side of this expression is a vector, so we will write down the \(i\)th component of this vector, and check that this gives the \(i\)th component of the right-hand side of the expression. If this holds for all \(i\), the expression is then true as a statement about vectors. \[\begin{aligned} \left( {\bf a}\times [{\bf a}\times ({\bf a}\times {\bf b})] \right)_i &= \epsilon_{ijk}a_j\epsilon_{klm}a_l\epsilon_{mno}a_nm_o \\ &= \epsilon_{ijk}(\delta_{kn}\delta_{lo} - \delta_{ko}\delta_{ln})a_j a_l a_n b_o \\ &= \epsilon_{ijk}a_ja_k a_l b_l - \epsilon_{ijk}a_jb_ka_la_l \\ &= ({\bf a}\cdot {\bf b})({\bf a}\times {\bf a})_i - ({\bf a}\cdot {\bf a})({\bf a}\times {\bf b})_i. \end{aligned}\] Now note that \({\bf a}\times {\bf a}= 0\) for all vectors \({\bf a}\), and recall that \({\bf a}\times {\bf b}= - {\bf b}\times {\bf a}\), so we have \[\left( {\bf a}\times [{\bf a}\times ({\bf a}\times {\bf b})] \right) = ({\bf a}\cdot {\bf a})({\bf b}\times {\bf a}),\] and letting \(a = |{\bf a}|\), we have the required result.
\(~ ({\bf a}\times{\bf b}) \cdot ({\bf c}\times{\bf d})+ ({\bf b}\times{\bf c}) \cdot ({\bf a}\times{\bf d})+ ({\bf c}\times{\bf a}) \cdot ({\bf b}\times{\bf d}) =0\) .
Using part (a), we have \[\begin{aligned} ({\bf a}\times{\bf b}) &\cdot ({\bf c}\times{\bf d})+ ({\bf b}\times{\bf c}) \cdot ({\bf a}\times{\bf d})+ ({\bf c}\times{\bf a}) \cdot ({\bf b}\times{\bf d}) \\ =&\ ({\bf a}\cdot {\bf c})({\bf d}\cdot {\bf b}) - ({\bf a}\cdot {\bf d})({\bf b}\cdot {\bf c}) + ({\bf b}\cdot {\bf a})({\bf c}\cdot {\bf d}) \\ &- ({\bf b}\cdot {\bf d})({\bf c}\cdot {\bf a}) + ({\bf c}\cdot {\bf b})({\bf a}\cdot {\bf d}) - ({\bf c}\cdot {\bf d})({\bf a}\cdot {\bf b}) \\ =&\ 0. \end{aligned}\]
Exam question June 2002 (Section A): Evaluate \(\varepsilon_{ijk} \varepsilon_{ijl}x_k x_l\).
\[\begin{aligned} \varepsilon_{ijk} \varepsilon_{ijl}x_k x_l& =(\delta_{jj}\delta_{kl}-\delta_{jl}\delta_{kj})x_k x_l\\[2pt] &=(3\delta_{kl}-\delta_{kl})x_k x_l=2\delta_{kl}x_k x_l=2x_lx_l =2|{\bf x}|^2.\end{aligned}\]
Exam question June 2001 (Section A): Evaluate \(\varepsilon_{ijk} \partial_i \partial_j (x_l x_l)^{1/2}\) away from the origin.
The answer is zero, because the mixed second partial derivatives are symmetric in \(i\) and \(j\) while the \(\varepsilon_{ijk}\) is antisymmetic. For full marks you should say that the mixed partial derivatives are symmetric in \(i\) and \(j\) because they are continuous functions at all points away from the origin (which are the only points which need to be considered).
Exam question June 2003 (Section A): Calculate \(\partial_i\,(\varepsilon_{ijk}~ \varepsilon_{jkl}~x_l\,)\). (Hint: use the connection between \(\partial_ix_j=\frac{\partial x_j}{\partial x_i}\) and the Kronecker delta.)
Use \(\partial_i x_j=\delta_{ij}\) in \(\partial_i\,(\varepsilon_{ijk}~ \varepsilon_{jkl}~x_l\,)\) \(=\varepsilon_{ijk}~ \varepsilon_{jkl}~\partial_i\,x_l\) \(=\varepsilon_{ijk}~ \varepsilon_{jkl}\,\delta_{il}\)\(=\varepsilon_{ijk}~ \varepsilon_{jki}\)\(=\varepsilon_{ijk}~ \varepsilon_{ijk}\)\(=\delta_{ii}\delta_{jj}-\delta_{ij}\delta_{ji}\)\(=3\times 3-\delta_{ii}=9-3\)\(=6\).
The functions \(f\), \(g\) are scalars, while \({\bf A}\) and \({\bf B}\) are vector functions with components \(A_i\) and \(B_i\) respectively. Verify the following identities using index notation:
\(\quad {\rm grad}\,\, (fg)\,=\, f\, {\rm grad}\,g\,+\, g\, {\rm grad}\,f\),
The \(i\)-th component of the LHS is \(\partial_i (fg)=f\partial_i g+g\partial_i f\) by the product-rule. This is the \(i\)-th component of the RHS, which proves the identity.
\(\quad {\rm grad}\, ({\bf A} \cdot {\bf B})\,=\, {\bf A} \times{\rm curl}\, {\bf B} + {\bf B} \times{\rm curl}\, {\bf A} \,+\,({\bf B}\cdot \nabla) {\bf A} \,+\, ({\bf A}\cdot \nabla) {\bf B}\),
This time it’s best to start on the RHS (general message: it’s always a good idea to start with the most complicated side and then simplify). We have \[\begin{aligned} \left({\bf A} \times{\rm curl}\, {\bf B} + {\bf B} \times{\rm curl}\, {\bf A}\right)_i &\,=\, \varepsilon_{ijk}A_j \varepsilon_{klm}\partial_lB_m + \varepsilon_{ijk}B_j \varepsilon_{klm}\partial_lA_m\\ &\,=\, \varepsilon_{ijk}\varepsilon_{klm} \left(A_j\partial_lB_m+B_j\partial_lA_m\right)\\ &\,=\, \left(\delta_{il}\delta_{jm}- \delta_{im}\delta_{jl}\right) \left(A_j\partial_lB_m+B_j\partial_lA_m\right)\\ &\,=\, A_j\partial_iB_j +B_j\partial_iA_j -A_j\partial_jB_i -B_j\partial_jA_i\end{aligned}\] The last two terms in the final line are exactly cancelled by the \(i\)-th component of \(({\bf B}\cdot \nabla) {\bf A} \,+\, ({\bf A}\cdot \nabla) {\bf B}\), while the first two are reasonably-easily seen to be the \(i\)-th component of \({\rm grad}\, ({\bf A} \cdot {\bf B})\), proving the identity.
\(\quad {\rm div}\, (f {\bf A})\,=\,f\,{\rm div}\,{\bf A}\,+\, ({\rm grad} f) \cdot {\bf A}\),
The LHS is a scalar equal to \(\partial_i(fA_i)=f\partial_iA_i+(\partial_if)A_i\) by the product rule for derivatives. This equals the RHS, which proves the identity.
\(\quad {\rm curl}\, (f {\bf A})\,= \, f\, {\rm curl}\,{\bf A}\,+\, ({\rm grad}\,f) \times{\bf A}\),
The LHS is a vector whose \(i\)-th component is \[\varepsilon_{ijk}\partial_j(fA_k)=\varepsilon_{ijk}\left(f\partial_jA_k + (\partial_j f)A_k\right)\] \[=f\varepsilon_{ijk}\partial_jA_k+\varepsilon_{ijk}(\partial_j f)A_k\] This is the \(i\)-th component of the RHS, which proves the identity.
\(\quad {\rm div}\,({\bf A}\times{\bf B})\,=\,{\bf B}\cdot {\rm curl}\,{\bf A}\,-\, {\bf A}\cdot {\rm curl}\,{\bf B}\),
The LHS is a scalar equal to \(\partial_i(\varepsilon_{ijk}A_jB_k)=\varepsilon_{ijk}\partial_i(A_jB_k)\) since \(\varepsilon_{ijk}\) is just a number, independent of \({\bf x}\). Using the product-rule this becomes \[\varepsilon_{ijk}(\partial_iA_j)B_k+\varepsilon_{ijk}A_j(\partial_iB_k) =B_k\left(\varepsilon_{kij}(\partial_iA_j)\right)-A_j(\varepsilon_{jik}\partial_iB_k)\] This equals the RHS, which proves the identity.
\(\quad {\rm curl}\,({\bf A}\times{\bf B})\,=\,({\rm div}\,{\bf B}) {\bf A}\,-\,({\rm div}\,{\bf A}) {\bf B}\,+\, ({\bf B}\cdot \nabla) {\bf A} \,-\, ({\bf A}\cdot \nabla) {\bf B}\),
The LHS is a vector whose \(i\)-th component is \(\varepsilon_{ijk}\partial_j(\varepsilon_{krs}A_rB_s)= \varepsilon_{ijk}\varepsilon_{rsk}\partial_j(A_rB_s)\) since \(\varepsilon_{krs}=\varepsilon_{rsk}\) is just a number, independent of \({\bf x}\). Using the product-rule, and the very useful formula, this becomes \[(\delta_{ir}\delta_{js}-\delta_{is}\delta_{jr})\left((\partial_jA_r)B_s+A_r(\partial_jB_s)\right)\] \[=\delta_{ir}\delta_{js}(\partial_jA_r)B_s + \delta_{ir}\delta_{js}A_r(\partial_jB_s) -\delta_{is}\delta_{jr} (\partial_jA_r)B_s-\delta_{is}\delta_{jr}A_r(\partial_jB_s)\] \[=(\partial_sA_i)B_s+A_i(\partial_sB_s) - (\partial_rA_r)B_i-A_r(\partial_rB_i)=A_i(\partial_sB_s)- (\partial_rA_r)B_i +(B_s\partial_s)A_i-(A_r\partial_r)B_i\] This is the \(i\)-th component of the RHS, which proves the identity.
\(\quad {\rm div}\,{\rm curl}\,{\bf A}\;=\;0\),
The LHS is a scalar equal to \(\partial_i(\varepsilon_{ijk}\partial_jA_k)= \varepsilon_{ijk}\partial_i\partial_jA_k\). On the assumption that \(\partial_i\partial_jA_k\) is continuous then \(\partial_i\partial_jA_k=\partial_j\partial_iA_k\) so \(\varepsilon_{ijk}\partial_i\partial_jA_k=\varepsilon_{ijk}\partial_j\partial_iA_k =\varepsilon_{jik}\partial_i\partial_jA_k\) by re-naming dummy variables, but this is \(-\varepsilon_{ijk}\partial_i\partial_jA_k\) by skew symmetry of \(\varepsilon_{ijk}\), i.e. \(\varepsilon_{ijk}\partial_i\partial_jA_k=-\varepsilon_{ijk}\partial_i\partial_jA_k\) which implies \(\varepsilon_{ijk}\partial_i\partial_jA_k=0\).
\(\quad {\rm curl}\,\,{\rm curl}\,{\bf A}\,=\, {\rm grad}\,{\rm div}\,{\bf A}- \nabla^2 {\bf A}\).
The LHS is a vector whose \(i\)-th component is \[\varepsilon_{ijk}\partial_j(\varepsilon_{krs}\partial_rA_s)= \varepsilon_{ijk}\varepsilon_{rsk}\partial_j(\partial_rA_s )\] since \(\varepsilon_{krs}=\varepsilon_{rsk}\) is just a number, independent of \({\bf x}\). Using the very useful formula, this becomes \[(\delta_{ir}\delta_{js}-\delta_{is}\delta_{jr})\partial_j\partial_rA_s =\delta_{ir}\delta_{js}\partial_j\partial_rA_s-\delta_{is}\delta_{jr}\partial_j\partial_rA_s =\partial_s\partial_iA_s-\partial_r\partial_rA_i\] On the assumption that \(\partial_j\partial_rA_s\) is continuous we can write this as \(\partial_i\partial_sA_s-\partial_r\partial_rA_i\). This is the \(i\)-th component of the RHS, which proves the identity.
What is the divergence of the vector function \({\bf{A}}({{\bf x}\,})= r\,{{\bf x}\,} + {\bf \nabla}\,r\) where \({{\bf x}\,}\) is the position vector in 3 dimensions and \(r=|{\bf x}\,|\)? What is the corresponding result in \(n\) dimensions?
Using components, \(\nabla\cdot {\bf{A}} = \partial_i\left(rx_i+\partial_i(r)\right) = \partial_i(r)x_i+r\partial_ix_i+ \partial_i(\partial_i(r))\) . Using \(\partial_i(r)=\partial_i(x_jx_j)^{1/2}={\textstyle\frac{1}{2}}(x_jx_j)^{-1/2}2x_i=x_i/r\) (as in [vecresultsindex](c)) this is \[\begin{aligned} x_ix_i/r+r\delta_{ii}+\partial_i(x_i/r)&= r+3r+(\partial_ix_i)/r-x_ir^{-2}\partial_i(r) \\ &= 4r+\delta_{ii}/r-x_ir^{-2}x_i/r \\ &= 4r+3/r-1/r=4r+2/r\,.\end{aligned}\] In \(n\) dimensions \(\delta_{ii}=n\) which changes the result to \((n+1)r+(n-1)/r\).


|
Little Heroes
|
Simple progress bar that fills itself based on the specified value. More...
Public Types | |
| enum | FillDirection { FillDirection.LeftToRight, FillDirection.RightToLeft, FillDirection.BottomToTop, FillDirection.TopToBottom } |
Public Member Functions | |
| delegate void | OnDragFinished () |
| virtual void | ForceUpdate () |
| Update the value of the scroll bar. More... | |
Public Attributes | |
| OnDragFinished | onDragFinished |
| Delegate triggered when the scroll bar stops being dragged. More... | |
| Transform | thumb |
| Object that acts as a thumb. More... | |
| int | numberOfSteps = 0 |
| Number of steps the slider should be divided into. More... | |
| List< EventDelegate > | onChange = new List<EventDelegate>() |
| Callbacks triggered when the scroll bar's value changes. More... | |
Static Public Attributes | |
| static UIProgressBar | current |
| Current slider. More... | |
Protected Member Functions | |
| void | Start () |
| Register the event listeners. More... | |
| virtual void | Upgrade () |
| Used to upgrade from legacy functionality. More... | |
| virtual void | OnStart () |
| Functionality for derived classes. More... | |
| void | Update () |
| Update the value of the scroll bar if necessary. More... | |
| void | OnValidate () |
| Invalidate the scroll bar. More... | |
| float | ScreenToValue (Vector2 screenPos) |
| Drag the scroll bar by the specified on-screen amount. More... | |
| virtual float | LocalToValue (Vector2 localPos) |
| Calculate the value of the progress bar given the specified local position. More... | |
| void | SetThumbPosition (Vector3 worldPos) |
| Set the position of the thumb to the specified world coordinates. More... | |
Protected Attributes | |
| UIWidget | mBG |
| UIWidget | mFG |
| float | mValue = 1f |
| FillDirection | mFill = FillDirection.LeftToRight |
| Transform | mTrans |
| bool | mIsDirty = false |
| Camera | mCam |
| float | mOffset = 0f |
Properties | |
| Transform | cachedTransform [get] |
| Cached for speed. More... | |
| Camera | cachedCamera [get] |
| Camera used to draw the scroll bar. More... | |
| UIWidget | foregroundWidget [get, set] |
| Widget used for the foreground. More... | |
| UIWidget | backgroundWidget [get, set] |
| Widget used for the background. More... | |
| FillDirection | fillDirection [get, set] |
| The scroll bar's direction. More... | |
| float | value [get, set] |
| Modifiable value for the scroll bar, 0-1 range. More... | |
| float | alpha [get, set] |
| Allows to easily change the scroll bar's alpha, affecting both the foreground and the background sprite at once. More... | |
| bool | isHorizontal [get] |
| Whether the progress bar is horizontal in nature. More... | |
| bool | isInverted [get] |
| Whether the progress bar is inverted in its behaviour. More... | |
Simple progress bar that fills itself based on the specified value.
|
virtual |
Update the value of the scroll bar.
Reimplemented in UIScrollBar.
|
protectedvirtual |
Calculate the value of the progress bar given the specified local position.
Reimplemented in UIScrollBar.
| delegate void UIProgressBar.OnDragFinished | ( | ) |
|
protectedvirtual |
Functionality for derived classes.
Reimplemented in UIScrollBar, and UISlider.
|
protected |
Invalidate the scroll bar.
|
protected |
Drag the scroll bar by the specified on-screen amount.
|
protected |
Set the position of the thumb to the specified world coordinates.
|
protected |
Register the event listeners.
|
protected |
Update the value of the scroll bar if necessary.
|
protectedvirtual |
Used to upgrade from legacy functionality.
Reimplemented in UIScrollBar, and UISlider.
|
static |
Current slider.
This value is set prior to the callback function being triggered.
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
| int UIProgressBar.numberOfSteps = 0 |
Number of steps the slider should be divided into.
For example 5 means possible values of 0, 0.25, 0.5, 0.75, and 1.0.
| List<EventDelegate> UIProgressBar.onChange = new List<EventDelegate>() |
Callbacks triggered when the scroll bar's value changes.
| OnDragFinished UIProgressBar.onDragFinished |
Delegate triggered when the scroll bar stops being dragged.
Useful for things like centering on the closest valid object, for example.
| Transform UIProgressBar.thumb |
Object that acts as a thumb.
|
getset |
Allows to easily change the scroll bar's alpha, affecting both the foreground and the background sprite at once.
|
getset |
Widget used for the background.
|
get |
Camera used to draw the scroll bar.
|
get |
Cached for speed.
|
getset |
The scroll bar's direction.
|
getset |
Widget used for the foreground.
|
getprotected |
Whether the progress bar is horizontal in nature.
Convenience function.
|
getprotected |
Whether the progress bar is inverted in its behaviour.
Convenience function.
|
getset |
Modifiable value for the scroll bar, 0-1 range.


Flip Tanedo
Are you looking for my
personal page
?
[.]
Hugo Theme
Seminyak
. Photo by
Carrie Rosema
.


Debugging the whole ecosystem
I was recently exporting a large number of records via CSV, some 130k rows. Luckily, the rows only consisted of three columns.
When testing the output, I noticed that there were only 65355 rows written. A nice round number, being the highest positive integer that can be stored in a 16bit value.
I checked the docs for Ruby's IO#write, and noted that from IO#write_nonblock, it may be buffered. So stepping through the loop from the working case to the failing:
File.open(path, 'wb') do |f|
records.each.with_index do |record, index|
binding.pry if index >= 65354
f.write(record.csv_row)
end
end
I could see that it failed to alter the size of the file at path
. Manually calling f.flush && f.write(row_data)
seemed to make a difference to the file size.
Now I inserted a IO#flush in the output loop every 100 rows or so.
File.open(path, 'wb') do |f|
records.each.with_index do |record, index|
f.write(record.csv_row)
f.flush if index % 100 == 0
end
end
Still no difference in the output though, loading it into Apple Pages. Still limited to 65355 rows. On a hunch, I opened the file in vim. Lo and behold! 130k lines ready and waiting for me. Going back, I removed the IO#flush
call, regenerated the file, and still Pages reports 65355 rows, vim reports 130k lines.
So, moral of the story... don't rely on pretty software for large data sets? Trust but verify? Commandline wins?
Stay in touch
Hi, I'm James Cowlishaw. Mickey is a minimal one-column theme for Spelt, based on Mickey for Jekyll, by @VincentChan.


ros-emacs - launch Emacs with Slime # Synopsis
ros emacs [ARGS…]
Launches Emacs with a Slime(https://common-lisp.net/project/slime/) buffer opened, which is connected to the back-end lisp implementation of roswell. Additional arguments are passed to emacs.
ros(1), emacs(1) _


{% extends "layout.html" %} {% block body %}
Simulation
Simulate the experiment 100 times under the assumption that the null hypothesis is true, i.e. assuming there is no gender bias. Use a deck of 48 cards, each representing one resume in the study. 35 of these cards are red, representing promoted candidates, and 13 are blue, representing NOT promoted candidates.
Step 1. Shuffle the deck.
Step 2. Split into 2 piles of 24 as to represent the completely random, non-biased promotion decisions for the 24 males and 24 females.
Step 3. Compute the difference in promotion rates between males and females. To do this: count the number of red cards in each pile of 24, calculate the proportion of such files in each pile, and compute the difference.
Step 4. Record this value on the dot plot.
Step 5. Repeat Steps (1)-(4) 100 times.
Results
The dot plot shows the distribution of simulated differences. We want to compare the data from the original experiment to this distribution of simulated differences in order to gauge the likelihood of obtaining such a result if in fact the null hypothesis is true. Does the original observation appear to be a likely outcome? How likely is it to obtain differences at least as extreme as the original difference if in fact the null hypothesis is true?


Student at the full stack program at CNM Ingenuity's Deep Dive Coding Bootcamp. Trained in the LAMP stack (Linux, Apache, MySQL, and PHP). This is the most common stack of the internet, where PHP is the primary language of upto eighty-percent of websites. Training also included JavaScript, HTML, CSS, Bootstrap, React, Insomnia, JSX, Docker, Putty, Github, GitBash, and PHP Storm.
I earned a BBA in Entrepreneurship (2017) from Anderson's School of Management at the University of New Mexico, where I and along side my classmates created multiple business plans including one that was for the New Mexico Jazz Workshop on behalf of the Small Business Institute of New Mexico. I have worked in the TeleCom Industry (Verizon wireless), the Automotive industry (Audi, VW, Subaru) and the Aviation Industry (Eclipse Aviation)
I have been accepted to Anderson Masters of Science in Information Systems and Assurance MS-ISA located at the University of New Mexico. My concentration will be in Cyber-Security and with some Data Analytics. Estimated completion May of 2021.


bilby
bilby
bilby
The figures below show the plots for bilby
chirp_mass
The figures below show the summary plots for the run
mass_ratio
The figures below show the summary plots for the run
a_1
The figures below show the summary plots for the run
a_2
The figures below show the summary plots for the run
tilt_1
The figures below show the summary plots for the run
tilt_2
The figures below show the summary plots for the run
phi_12
The figures below show the summary plots for the run
phi_jl
The figures below show the summary plots for the run
dec
The figures below show the summary plots for the run
ra
The figures below show the summary plots for the run
theta_jn
The figures below show the summary plots for the run
psi
The figures below show the summary plots for the run
geocent_time
The figures below show the summary plots for the run
recalib_H1_amplitude_0
The figures below show the summary plots for the run
recalib_H1_amplitude_1
The figures below show the summary plots for the run
recalib_H1_amplitude_2
The figures below show the summary plots for the run
recalib_H1_amplitude_3
The figures below show the summary plots for the run
recalib_H1_amplitude_4
The figures below show the summary plots for the run
recalib_H1_amplitude_5
The figures below show the summary plots for the run
recalib_H1_amplitude_6
The figures below show the summary plots for the run
recalib_H1_amplitude_7
The figures below show the summary plots for the run
recalib_H1_amplitude_8
The figures below show the summary plots for the run
recalib_H1_amplitude_9
The figures below show the summary plots for the run
recalib_H1_phase_0
The figures below show the summary plots for the run
recalib_H1_phase_1
The figures below show the summary plots for the run
recalib_H1_phase_2
The figures below show the summary plots for the run
recalib_H1_phase_3
The figures below show the summary plots for the run
recalib_H1_phase_4
The figures below show the summary plots for the run
recalib_H1_phase_5
The figures below show the summary plots for the run
recalib_H1_phase_6
The figures below show the summary plots for the run
recalib_H1_phase_7
The figures below show the summary plots for the run
recalib_H1_phase_8
The figures below show the summary plots for the run
recalib_H1_phase_9
The figures below show the summary plots for the run
recalib_L1_amplitude_0
The figures below show the summary plots for the run
recalib_L1_amplitude_1
The figures below show the summary plots for the run
recalib_L1_amplitude_2
The figures below show the summary plots for the run
recalib_L1_amplitude_3
The figures below show the summary plots for the run
recalib_L1_amplitude_4
The figures below show the summary plots for the run
recalib_L1_amplitude_5
The figures below show the summary plots for the run
recalib_L1_amplitude_6
The figures below show the summary plots for the run
recalib_L1_amplitude_7
The figures below show the summary plots for the run
recalib_L1_amplitude_8
The figures below show the summary plots for the run
recalib_L1_amplitude_9
The figures below show the summary plots for the run
recalib_L1_phase_0
The figures below show the summary plots for the run
recalib_L1_phase_1
The figures below show the summary plots for the run
recalib_L1_phase_2
The figures below show the summary plots for the run
recalib_L1_phase_3
The figures below show the summary plots for the run
recalib_L1_phase_4
The figures below show the summary plots for the run
recalib_L1_phase_5
The figures below show the summary plots for the run
recalib_L1_phase_6
The figures below show the summary plots for the run
recalib_L1_phase_7
The figures below show the summary plots for the run
recalib_L1_phase_8
The figures below show the summary plots for the run
recalib_L1_phase_9
The figures below show the summary plots for the run
luminosity_distance
The figures below show the summary plots for the run
phase
The figures below show the summary plots for the run
recalib_H1_frequency_0
The figures below show the summary plots for the run
recalib_H1_frequency_1
The figures below show the summary plots for the run
recalib_H1_frequency_2
The figures below show the summary plots for the run
recalib_H1_frequency_3
The figures below show the summary plots for the run
recalib_H1_frequency_4
The figures below show the summary plots for the run
recalib_H1_frequency_5
The figures below show the summary plots for the run
recalib_H1_frequency_6
The figures below show the summary plots for the run
recalib_H1_frequency_7
The figures below show the summary plots for the run
recalib_H1_frequency_8
The figures below show the summary plots for the run
recalib_H1_frequency_9
The figures below show the summary plots for the run
recalib_L1_frequency_0
The figures below show the summary plots for the run
recalib_L1_frequency_1
The figures below show the summary plots for the run
recalib_L1_frequency_2
The figures below show the summary plots for the run
recalib_L1_frequency_3
The figures below show the summary plots for the run
recalib_L1_frequency_4
The figures below show the summary plots for the run
recalib_L1_frequency_5
The figures below show the summary plots for the run
recalib_L1_frequency_6
The figures below show the summary plots for the run
recalib_L1_frequency_7
The figures below show the summary plots for the run
recalib_L1_frequency_8
The figures below show the summary plots for the run
recalib_L1_frequency_9
The figures below show the summary plots for the run
log_likelihood
The figures below show the summary plots for the run
log_prior
The figures below show the summary plots for the run
total_mass
The figures below show the summary plots for the run
mass_1
The figures below show the summary plots for the run
mass_2
The figures below show the summary plots for the run
symmetric_mass_ratio
The figures below show the summary plots for the run
iota
The figures below show the summary plots for the run
spin_1x
The figures below show the summary plots for the run
spin_1y
The figures below show the summary plots for the run
spin_1z
The figures below show the summary plots for the run
spin_2x
The figures below show the summary plots for the run
spin_2y
The figures below show the summary plots for the run
spin_2z
The figures below show the summary plots for the run
phi_1
The figures below show the summary plots for the run
phi_2
The figures below show the summary plots for the run
chi_eff
The figures below show the summary plots for the run
chi_1_in_plane
The figures below show the summary plots for the run
chi_2_in_plane
The figures below show the summary plots for the run
chi_p
The figures below show the summary plots for the run
cos_tilt_1
The figures below show the summary plots for the run
cos_tilt_2
The figures below show the summary plots for the run
redshift
The figures below show the summary plots for the run
comoving_distance
The figures below show the summary plots for the run
mass_1_source
The figures below show the summary plots for the run
mass_2_source
The figures below show the summary plots for the run
chirp_mass_source
The figures below show the summary plots for the run
total_mass_source
The figures below show the summary plots for the run
H1_optimal_snr
The figures below show the summary plots for the run
L1_optimal_snr
The figures below show the summary plots for the run
H1_matched_filter_snr_abs
The figures below show the summary plots for the run
H1_matched_filter_snr_angle
The figures below show the summary plots for the run
L1_matched_filter_snr_abs
The figures below show the summary plots for the run
L1_matched_filter_snr_angle
The figures below show the summary plots for the run
inverted_mass_ratio
The figures below show the summary plots for the run
final_spin_non_evolved
The figures below show the summary plots for the run
peak_luminosity_non_evolved
The figures below show the summary plots for the run
final_mass_non_evolved
The figures below show the summary plots for the run
final_mass_source_non_evolved
The figures below show the summary plots for the run
radiated_energy_non_evolved
The figures below show the summary plots for the run
H1_time
The figures below show the summary plots for the run
L1_time
The figures below show the summary plots for the run
network_optimal_snr
The figures below show the summary plots for the run
network_matched_filter_snr
The figures below show the summary plots for the run
cos_theta_jn
The figures below show the summary plots for the run
cos_iota
The figures below show the summary plots for the run
final_spin
The figures below show the summary plots for the run
peak_luminosity
The figures below show the summary plots for the run
final_mass
The figures below show the summary plots for the run
final_mass_source
The figures below show the summary plots for the run
radiated_energy
The figures below show the summary plots for the run


Enter your GitHub username in the box above and click the button!
If you get rate limited, you can enter a token as found here.
The script will look up whether your public repos have licenses.
This page uses Google Analytics to track which usernames have been searched, so that pretty graphs can be made later.
License checker by edunham , distributed under the MIT License. The source is on GitHub, pull requests welcome.
GitHub has a neat blog related to this topic here.