# Btrix deep attachments
People take heed, how Beatrix advances in battle to beat the legions beyond the ocean floor.
# Dual deep
So far Btrix
only attached her nestable arrays
A,[X]Z
to the separator comma.
Now she will express nesting depth, in a bold move to go beyond,
by attaching brackets to brackets.
Jonathan Bowers already reached this algorithmic stage, with the
Big Hoss
for sure.
Mathematical historians must decide the debate over Bowers'
poorly defined system, how it counts separator nesting depth
and where it fits in with Bird's and ours.
It won't be necessary to compare expressions of
Btrix
with the Extended Array Functions of Eaf
and Beaf like we did before.
If the rules across systems have comparable strength,
and structures have similar data capacity,
then the numbers expressed are approximately as Big.
The system Beaf
of Bowers & Bird separates numbers between bracketed arrays
(it helps their zero 0
is a sign).
Their comma is strictly just an abbreviation sign for the subarray
[1]
(and if [0]
existed here, they could separate units
1..
in entries).
In Btrix and Eaf
a comma precedes separator subarrays
(so number entries can be counted down until void
,,
in between commas).
In Btrix an opening bracket
[
always attaches an array structure
S
to a preceding sign on the left.
The separator comma
,[
had its inside space expanded with an index
s]
and then to linear and multiple dimensions
and further S]
through hyperspace, to the nested arrays of last chapter.
Arrays are delimited by a corresponding
]
closing bracket on the right.
Watch the usual systems dig their initial first deep
to an arbitrary Big nesting depth –
working examples of how these algorithms can be implemented.
Bird's isn't clear about the exact form of his rules in all cases,
his articles have more to do with classifying higher structures
than with the reduction of expressions to Big number.
Below we suppose his
Beaf reduces superseparator
[[1]]
to a nested array of depth b
,
but we let the following
[[2X]]
repeat preceding superseparators at ground level.
Better and Bigger is to bring all superseparators
down to depth b
too,
as shown in Eaf
and Btrix.
- Beaf(a,2[[1]]2) = Beaf(a,2[1,2]2) = Beaf(a,a[2]a,a) <≈ Eaf(a,3,[1[1]]2) = Eaf(a,a,[1,[1,2]2]2) = Eaf(3,3,[4,3,[2]3,3,[3]3,3,[2]3,3]2) {a=3} ≈ Btrix(a,3,[][1]1) ≡ a,a,[,[,1]1]1 = a,a,[,[a-]1]1 = a,a,[.,[a--]..a-]1 :a-
- Beaf(a,b[[2X]]2Z) ≈ Beaf(a,b.[[1X]]2..[[2X]]1Z) :b: < Eaf(a,b,[1[1X]]2Z) = Eaf(a,a.,[1..[X]]2.,[1[1X]]1Z) :b: < Btrix(a,b1,[][1X]1Z) ≡ a,a,.[,..1][X].1,[][1X]Z :b:
In a comparison between systems similar wildcards
[X]
for subarrays
are to be considered effectively equal.
Follows the rules for dual deep expressions
a,b,[V][W]Z
of Btrix.
We use the RegExp quantifier
?
for an optional
false/true
word.
Below when
[Sr,j]?
is true
(then quantifier
[Sr]{1}
matches at case j
)
this opens up the next deep nested array.
Instead of
([W])?
we dare to write [W]?
to quantify the preceding 2nd subarray.
There's no need to backslash
\[
in this context, and each particular ?
has the same truth value in the equation
(think of signs ?
as indexed ?i,j
by the free indices of the word it quantifies).
- let $k ≡ ,[Si,k][Ti,k]?.. :rk {initi=0 r≥0} ¥j ≡ $j,[Sr,j]?
- 5.7 a,b1.¥j[..$n,1..Yj]1.Z :n: (upload counter) = a,a.¥j[..$nb,..Yj]1.Z :n:
- 6.6 a,b.¥j[..$n,[1V][W]?1..Yj]1.Z :n: (upsize dimensions) = a,a.¥j[..$n.,[V][W]?..1,[1V][W]?..Yj]1.Z :n: :b
- 9.0 a,b.¥j[..$n,[][1W]1..Yj]1.Z :n: (dig up nests) = a,a.¥j[..$n.,[..][W]1.,[][1W]..Yj]1.Z :n: :b:
Miraculously rule 6.
handles all size increases here, also those in the second deep.
Rule 9.
is new,
it digs up
nestings of b
levels, subtracting 1
from the active iterator (Bowers' pilot) past the dual deep
(subtracting from the second deep itself
would be significantly slower in the long run).
With hindsight,
a nestable system with mixed separators (to allow alternative
,[M],[N]
constructs) would prove to be superfluous (from here on),
now that serial deeps also mix arrays
.
A related question is, if combining two or three attachment styles
would increase the power of the algorithm significantly,
compared to deploying a new /
type of separator
and/or {}
brackets,
given that each new point of attachment
expands the information space similarly.
There are different positions
and methods to attach a next batch of arrays.
In
Bird I
his superseparators are attached
[..X..]
:k:
to both sides at once.
That's before Bird contains them with a more advanced separator
[X\k]
sign (his backslash).
It's more profitable for an array system to attach deep arrays
left inside
[..Xi]
:n:
to the opening tag, or right inside
[Xi..]
:n:
to the closing tag as in Eaf,
because we get an array space for free.
In this extra space a deep entry over the superarray
will have the same strength as the number of brackets on
both sides in Bird's early system.
Note that in system Eaf
a right inside attached array contains the next deep.
But, if we let our rules match strictly from left to right,
a left inside attached array would be the superarray
iterated over by the right serial deep (clear of,
but denominated by the number of closing brackets on its left),
as if dwelling on top of Bird's both sides
subsystem.
A first choice in Btrix
is to have deep arrays in series attached left outside
,.[Xi]..
:n
to the closing tag.
Then we can hold the attachment left inside
(of serial arrays) in reserve for the next batch,
instead of introducing a new separator character
(a future /
big comma).
Again
,[V][k]
≡
[..V..] :k:
and dual deeps in Btrix
,[V][W]
≡
[V\W]
versus Bird are comparable in capacity.
Further serial deeps in Btrix
,.[Vi]..
≡
[.Vi\..1]
≡
[1\\2]
have the same data capacity as a row of backslashed
Beaf.
We won't follow in Bird's footsteps,
since we are keen to know exactly where the already employed characters
will be exhausted completely.
Going to squeeze the maximum Big out of our current
[]
bracket pair.
# Serial deeps
Writing rules as equations of general expressions has become
rather cumbersome. The part that changes can be hard to find,
but is all that matters in a rule.
We'll introduce a RepExp rewrite
style algorithm for serial deeps
that is hopefully more legible.
Our prescriptions should solely match the changing subsequence
– with RepExp right on target –
like Bowers'
airplane
analogy for array structures made rigorous.
Variables n≥0
are greedy for the unit signs 1..
they consist of.
Here we use the unit 1
but it can stand for any number sign
(like 2
,ω
, etc),
but not for zero 0
which is empty
(counted down fully), and generally not for any number
n<1
which cannot reach a limit when counted down.
In our RepExp
the sign !
negates the following characters
(up to the space), so
!1
means not to match one.
This exclamation !
sign can also function as a positioning dot.
Dots are used .
to mark positions,
so that we can insert ↓
something there.
To insert a minus sign after a number
n1↓-
means to count down to number n
(decrement 1- ≡ 0
to empty).
We can move up ↑
a previous string or value b
,
so it is lifted from place and inserted at the dot(s
where it would repeat :b
a selected word some b
times).
There are two search directions.
We start moving (the cursor) to the right
→Y
until we find the first word Y
,
or by X→YXZ
the first X
which is contained in YXZ
(other containments are covered by
earlier listed rules).
We can also move back X←Y
to get at word X
in Y
on the left.
Now we have four arrow moves.
Series of separator arrays (nested to any depth)
can be written with the signature
,[W]
where start and end bracket correspond to the same
parent separator.
Those brackets need not be a pair, as would be the case with
,.[Vi]..1
serial deeps.
This way the rule for serial deeps
in Btrix
looks simpler in RepExp notation.
- 9.1 a,b .→,[V][1W]1↓- where parent nests ↓,[V..][W]1 :↑b: are all ]1 active
A program that runs the algorithm with
RepExp
searches →
the next counter (Bowers' pilot)
directly right of a separator or its array,
which can be declared active (ready to iterate over).
As before, in Btrix
we have the provision that (for an array to be active)
all the (serial) arrays it is embedded in must also be active
(have a right iterator).
Therefore (to put b
to good use)
in Btrix
the whole parent context (an active array is nested in)
should be checked (up to ground level) to affirm the form
]1
at every (serial array) closing bracket (closer).
To do this the program moves right
to find brackets ]
that are unaccounted for →
passing serial sisters →
counting (down and up) the depth of nieces
→
until it rises to the grand mothers.
If a (grand) parent level closer is met
],
followed by an inactive entry (counted down to void),
we've established that the
[W],
parent (serial) array is inactive.
Then Btrix moves on
→
from there,
restarting the procedure (find a next candidate).
Only if all arrays in the pedigree have active
]1
closers, any old rule of
Btrix can be applied.
For rule 9.
the character directly left of the opening
[
must
(in Btrix!)
be the ]
closing bracket
of an empty array []
to insert a new nesting to depth b
with copies of the preceding mother in.
Is it useless and inefficient to expand possible
(other) occurences of active separators,
when they are nested inside an inactive parent?
Or is it actually a good strategy?
We can prove it doesn't do much harm, by resolving
some extreme examples.
Because expressions where this matters are extremely rare,
the growth rate will not be
significantly affected either way.
Let a<<b
the basket be Big, for expressions of Btrix
(by rule all grand parents must be active)
versus system Betrix
(only the direct parent must be active)
to work out differently.
The Xb
denotes an array
whose structure is dominated by the value of the superscript,
just like xW
is a variable
dominated by the strength of the superscripted word.
a,b,[,[1V]1],1 case Btrix < Betrix
5.≈ a,a,[,[1V]1]b,
6.= a,a,[.,[V]..1,[1V]]b, :a
= a,a,[Xa]b
6·2.= a,a,[.,[V]1..],1 :b
== a,a,[Xb]a {Xa<<Xb}
<≈ Btrix(a,b,[,[1V]1]1,1)
a,b,[,1],[,1,W]1 case Betrix < Btrix
=5.= a,a,[b],[a,,W]1
= a,a,[b],[Ya]1 {b<<xW<<Ya<<Yb}
5.≈ a,a,[,1],[b,,W]1
== a,a,[xW],[Yb]1
<≈ Betrix(a,b,[,1]1,[,1,W]1)
These cases show ambiguous results (spread the risk).
System Betrix
doesn't bother if her grandparents are active
(as long as the direct separator or parent array is).
She doesn't need to, because in a common reduction train
such cases are insignificantly few.
Forms ],
would only occur after some dominantly Big
]b,
iteration was exhausted (1st example).
And the upload over two forms [,
is a rare event too (2nd example).
This is confirmed by creating competing
<≈
successor expressions with no significant cost.
We do take care to remove trailing arrays
from Betrix though,
after rule 6.
by rule
2.
which is defined later,
as part of her core RepExp regime.
No defunct structure that gives no returns
can be allowed to suck up the accumulated value of
b
(where initial value a
comes in place).
No way!
The RepExp
program to resolve (rewrite) expressions in
Betrix runs as follows:
Move right →
until a number sign 1
is matched. If there's a comma ,
on its left, apply rule 3.
(to ↓
add a
)
or rule 5.
(to ↑
move b
up).
If it has an opening bracket [
directly on its left, mark it,
and proceed →
to find the corresponding closing bracket
]
on its right.
To identify bracket pairs
a machine program has to keep score of the nesting level
it is searching in.
If the current closer ]
is directly followed by the 1
of a counter, we are ready to act on this
[W]1
separator array.
Else if the closing ]
is followed by
an opening [
find →
the next corresponding ]
and loop →
until the character right of this closer is either: a counter
1
(for the active
[W]1
serial array),
or a separator character ,
(the counter is void).
For an active (serial) array, count down the entry
]1-
right after the closer.
Go back ←
to the marked opening
[
and match the character
directly to its left, to determine which rule to apply.
If it's the very separator ,
rule 6.
applies
(to copy the preceding parent array
b
times).
UNDER CONSTRUCTION
Else in Betrix (!)
if an opening bracket [
is matched rule 9.
applies
(to nest a copy of the preceding mother to depth
b
).
But for an inactive (serial) array in
Betrix,
we set the cursor back ←
to the opening mark and continue →
to query its child arrays, until the first rule match by
RepExp is found.
Note that in Btrix
we searched right on after an inactive closer,
and the resulting growth difference was provably insignificant,
so that's an option (though not strictly by
RepExp rules) for comparison.
Past the single deep nested array, we see room to attach two complementary types of inside arrays and one extra type on the outside (as in Btrix). But given the default matching direction of rules (left to right), it seems natural to first reduce superarrays attached left inside, then those right inside and only then (if other rules fail) those attached right outside.
Rules in Betrix
are written in RepExp notation,
and listed in order of execution.
Entries
a>0
and
b>0
form her double base.
The machine searches right
→1
for a number and establishes its position –
to be either some ,1
counter in between, or at the start [1
of an active separator array
(with the counter right after).
- 0.2 Betrix(a, ≡ a, (show: without left function signature)
- 3.3 a,b.,1↓- ↓a
(motor: with counter
c
overb
, appenda
tob
and count downc
) - 5.8 a,b, .→,1↓- ↑b
(upload: counter down over an empty entry, and move
b
up here) - 4.4 a,., ↓a
(free fill: if entry
b
is void puta
in place without countdown) - 2.4 ,] ≡ ] 2.5 [W]] ≡ ] so ,[W]] ≡ ]
(separator drop: trailing entry @
5.
and subarray @6.
) - UNDER CONSTRUCTION
6.7 a,b .→,[1W]1↓-
↓,[W]1.. :↑b
(upsize: counter down past separator, repeat pre-separator and
1
) - UNDER CONSTRUCTION 9.2 a,b .→,[[1V]W]1↓- 9.2 {1∉V} ↓,[V..][W]1 :↑b: (dig up: counter down over serial deeps, dig nestings)
- 7.2 []1 ≡ 1 7.3 ,[-]1 ≡ 1
(nest drop: trailing right array @
6·9.
& fit to drop,[-]
@5·6.
) - 1.5 a,b →!1 = b 1.5 else a,b,X = b
(choice: if there's no counter found, output
b
) - 4.5 a,!1, ↓,
(else fill: if
a
is a single base then insert extra entry) - 8.1 ,[S],[T] {S<T} ≡ ,[T] OBSOLETE
(weighted drop: Bird's option to remove
semi-trailing
separators)
How Betrix digs deep in rule
9.
is pretty maximal,
but different than in Btrix.
Rules of allowance are not necessary for the complete reduction
of an expression, and we mark this route
in a less pronounced manner.
We won't use rule 8.
anymore.
It has an insignificant effect on the resulting number,
which is too Big already
(to drop smaller left separators
makes the result slightly smaller).
Cleaning up useless separators may be a natural reflex,
but we find the comparison rules for array sizes
too difficult to implement properly for all types of arrays
(see how Bird struggles).
So in our system we reuse (which merely adds
to sizes)
these semi-trailing separators.
Example expressions in Betrix. The start is a little awkward but the superpower class of each linear entry is the same as in Btrix.
3,,1 4.= 3,3,1 3.= 3,33, 1:= 6
3,,,1 4.= 3,3,,1 5.= 3,,3, 4.= 3,3,3,
3.= 3,33,2, =3.= 3,3333,, 1:= 12
3,[1]1 =4.= 3,3,[1]1 6.= 3,,[]1,[]1,[]1,[1]
=7·2.= 3,,1,1,1 4·3:= 3,6,,1,1
=5·4·3:= 3,21,,,1 =5·2·4·3:= 3,12,,20
=5·4·3·1:= 47071589412 ≈ 5E10 ≈ 3^22.4
Under construction
At the moment our Betrix algorithm is like a Dutch cheese with series of deep nested holes.
# Opening attachment
To separate serial deeps
[1]..
we'd like to sort them in holes,
just like numbers 1..
were arranged in entries, rows, dimensions, nests and deeps.
Now to line up a row of hole entries
we need a new construct
to separate our arrays with, but which?
To have a bigger comma ,
you might extend it to a slash /
forward
comparable to Bird's slash \
backward
(which takes off a hole-dimension
sooner, as Bird reduces deeps to slash).
After the first hole-row
[Xi,j]../..
you can have dimensions, nests and deeps of holes,
by using a next type of bracket characters
/{}
filled with number entries m
, comma nests
,[W]
and serial deeps (using ground separator chars).
You'd hole-nest them /{}
to arbitrary depth,
and further iterate over serial hole-deeps
/.{1}..
to exhaust a similar batch of structures.
However, this will cost you a lot of characters
before long!
We will use Bird's original construction beyond nested arrays
to fill the 2nd batch of structures.
To have a bigger comma ,
we extend it to
,[[]1]
= ,[[b]]
= ,.[1].. :b
After the first hole-row
[Xi,j]../..
we have dimensions, nests and deeps of holes,
by using a next type of bracket characters
/{}
filled with number entries m
, comma nests
,[W]
and serial deeps (using ground separator chars).
We hole-nest them /{}
to arbitrary depth,
and further iterate over serial hole-deeps
/.{1}..
to exhaust the 1st batch of structures.
# Big comma
Under construction
# Betrix numerous characters
Instead of defining each batch of structures anew,
with perhaps a dedicated comma sign and two new brackets
(the theoretical minimum would be one new bracket sign),
we like to address each batch
¢(x)
with an index.
So we can have a new
,(2) ≡ \
separator sign, and
](1) ≡ }
as above, and we started
[() ≡ [
with a 0th batch of characters.
To differentiate between char-index brackets
and common round brackets (not used in resolving
expressions in Btrix),
we may prefix an empty sign 0(X)
to the latter (or just rely on context).
The algorithms that breathe life into this world of indexed characters
should be so similar for each, that a general definition
for arbitrary batches of structures is not too far fetched.
Just imagine what would happen if we upgrade
a character ¢(,1Y)
with value b
from the basket.
For example:
3,2,(,1)1 = 3,3,(2)1 = 3,3\1
= 3,3,/\1 ???
= 3,3,(1)1,(1)1,(1)1 = 3,3/{1}{1}{1}1 ???