File: bracket.tex

package info (click to toggle)
form 4.2.1%2Bgit20200217-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 5,500 kB
  • sloc: ansic: 101,613; cpp: 9,375; sh: 1,582; makefile: 505
file content (253 lines) | stat: -rw-r--r-- 10,988 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
\chapter{Brackets}
\label{brackets}

At times one would like to order the output in a specific way. In an 
expression which is for instance a polynomial in terms of the symbol $x$, 
one might want to make this behaviour in terms of $x$ more apparent by 
printing the output in such a way, that all powers of $x$ are outside 
parentheses\index{parentheses}, and the whole rest is inside parentheses. 
This is done with the bracket\index{bracket} statement:
\begin{verbatim}
    Bracket x;
\end{verbatim}
or in short notation
\begin{verbatim}
    B x;
\end{verbatim}
One can specify more than one object in the bracket statement, but only a 
single bracket statement (the last one) is considered. Bracket statements 
belong to the module in which they occur. Hence they are forgotten after 
the next end-of-module.

If a vector is mentioned in a bracket statement, 
all occurrences of this vector as a loose vector, a vector with any index, 
inside a dotproduct, or inside a tensor are taken outside brackets. If the 
vector occurs inside a non-commuting tensor, all other non commuting 
objects that are to the left of this tensor will also be taken outside the 
parentheses.

When a function or tensor is mentioned in a bracket statement, it is not 
allowed to have any arguments in the bracket statement. All occurrences of 
this function will be pulled outside brackets. If the function is 
non-commuting, all other functions and/or tensors that are non-commuting 
and are to the left of the specific function(s) or tensor(s) will also be 
outside parentheses.

The opposite of the bracket statement is the antibracket\index{antibracket} 
statement:
\begin{verbatim}
    AntiBracket x;
\end{verbatim}
or
\begin{verbatim}
    ABracket x;
\end{verbatim}
or
\begin{verbatim}
    AB x;
\end{verbatim}
This statement causes also brackets in the output, but now everything is 
put outside brackets, except for powers of x and coefficients. This way one 
can make the $x$-dependence apparent differently.

Because the bracket statement causes a different ordering of the terms when 
storing the expression, one can use this ordering in the next module. There 
are various ways to do this.

One can use the contents of a given bracket in a r.h.s. expression as in
% THIS EXAMPLE IS PART OF THE TESTSUITE. CHANGES HERE SHOULD BE APPLIED THERE AS
% WELL!
\begin{verbatim}
    Symbols a,b,c,x;
    L  F = a*x^2+b*x+c;
    B x;
    .sort
    L  Discriminant = F[x]^2-4*F[x^2]*F[1];
    Print;
    .end
\end{verbatim}
The outside of the bracket is placed between braces\index{braces} after the 
name of the expression. The bracket that has nothing outside is referred to 
with the number 1. If a bracket is empty, its contents will be represented 
by the value zero.

The regular algorithm by which \FORM{} finds brackets in an expression, is 
to start from the beginning and inspect each term until it finds the 
appropriate bracket. This is fully in the spirit of the sequential 
treatment of expressions in \FORM{}. This can however be rather 
slow\index{slow} in big 
expressions that reside on a disk. Hence there is the bracket\index{bracket 
index} 
index\index{index!bracket} 
feature. It is invoked by putting a $+$-sign after the bracket (or B) 
statement as in 
\begin{verbatim}
    Bracket+ x;
\end{verbatim}
or
\begin{verbatim}
    B+ x;
\end{verbatim}
This option causes \FORM{} to build a tree of (disk) positions for the 
different brackets, with the condition that the whole storage of this tree 
of brackets does not exceed a given maximum space, named 
`bracketindexsize'\index{bracketindexsize} 
(see chapter~\ref{setup} on the setup parameters). 
If the index would need more space \FORM{} will start 
skipping brackets in the index. This means that it will have to look for 
the bracket in a sequential fashion, but starting from the position 
indicated by the previous bracket in the index. This will still be very 
fast, provided the index is not very small.

When the bracket index option is used, \FORM\ will not compress the 
expressions that use such an index with the zlib compression, even if the 
user asked for this in an earlier statement. The use of the index indicates 
that the brackets are going to be used intensively, and hence the 
continuous decompression that would result would destroy most of the profit 
that comes from the index. If the brackets are only for cosmetics in the 
output, it is better not to use the index option. It does use resources to 
construct the index\index{index tree} tree\index{tree!index}. Also when 
brackets are only used sequentially as in the features discussed below, the 
presence of the index is not beneficial. It should only be applied when 
contents of brackets are used in the above way (like with the 
discriminant).

There are several statements that make use of the bracket ordering:
\begin{itemize}
\item Keep\index{keep brackets} Brackets;
	This statement takes from the input one term at a time as usual, but 
then it takes the part outside the brackets, executes the statements of the 
module only on that part of the term, and then, when all statements of the 
module have had their effect, the resulting term(s) is/are multiplied by 
the full content of the bracket. The next term taken from the input will be 
the first term of the next bracket. This way one can hide part of the terms 
for the pattern matcher. Also one can avoid that the same matching will 
occur many times, as in an expression of the type
\begin{verbatim}
      + f(y)*(x+x^2+x^3+x^4+1)
\end{verbatim}
If we would want to make a replacement of the type
\begin{verbatim}
    Keep Brackets;
    id f?{f1,f2,f3}(u?) = f(u+1)/u;
\end{verbatim}
the pattern matching and the substitution would have to be done only once, 
rather than 5 times, as would be the case if the Keep bracket statement 
would not be used.
\item Collect\index{collect} FunctionName;
	The contents of the various brackets will be placed inside a function 
with the given name. Hence
\begin{verbatim}
      + f(y)*(x+x^2+x^3+x^4+1)
      + f(y^2)*(x+2*x^2+3*x^3+4*x^4+1)
\end{verbatim}
with
\begin{verbatim}
    Collect h;
\end{verbatim}
would result in:
\begin{verbatim}
      + f(y)*h(x+x^2+x^3+x^4+1)
      + f(y^2)*h(x+2*x^2+3*x^3+4*x^4+1)
\end{verbatim}
This can be very useful to locate $x$-dependence even further, because 
bracketing the new expression in terms of $h$ could make very clear 
whether a given polynomial in $x$ would factor the whole expression, or 
which factors are occurring. To bring \verb:h(x+1): and \verb:h(2*x+2): to 
multiples of the same objects one should consult the pages on the 
normalize\index{normalize} 
(\ref{substanormalize}) 
and makeinteger\index{makeinteger} (\ref{substamakeinteger}) statements.

The Collect statement, together with the PolyFun\index{polyfun} statement, 
can also be very useful, if the variable $x$ (or other variables) is 
temporarily not playing much of a role in the pattern matching. It can make 
the program much faster.

For more information on the collect statement one should consult 
section~\ref{substacollect}.
\end{itemize}

\noindent
Restrictions: The bracket index can only be used with active expressions. 
Hence the access of specific brackets in stored expressions will always be 
of the slow variety. To make it faster, one can copy the expression into a 
local expression with indexed brackets, use it, and drop the expression 
when it is not needed any longer.

The brackets can also be used to save space on the disk in problems in 
which the expressions become rather large. Let us assume the following 
simple problem:
\begin{verbatim}
    Symbols x1,...,x12;
    Local F = (x1+...+x12)^10;
    .sort
    id  x1 = x4+x7;
    .end
\end{verbatim}
If the program is run like this the expression F contains 352716 terms 
after the sort and after the id the sorting in the .end results in a final 
stage sort\index{sort!final stage} of which the statistics are:
\begin{verbatim}
Time =      46.87 sec
                F        Terms active    =     504240
                         Bytes used      =   13462248

Time =      52.09 sec    Generated terms =     646646
                F        Terms in output =     184756
                         Bytes used      =    4883306
\end{verbatim}
We see, that the intermediate sort file still contains more than 500000 
terms and more than 13 Mbytes, while the final result contains less than 5 
Mbytes. Why is this? When the terms in \FORM\ are sorted first come the 
powers of \verb:x1:, because this is the variable that was declared first. 
Hence the terms that do not have powers of \verb:x1: come much later in the 
input and will not be compared with the terms generated by the substitution 
of for instance a single power of \verb:x1: until very late in the sorting. 
What can we do about this? We can try to group the terms in the first sort 
such that after the substitution like terms will be `very close' to each 
other and hence will add quickly. This is done in the program
\begin{verbatim}
    Symbols x1,...,x12;
    Local F = (x1+...+x12)^10;
    AntiBracket x1,x4,x7;
    .sort
    id  x1 = x4+x7;
    .end
\end{verbatim}
Now all powers of the mentioned variables will be inside the brackets and 
all other variables will be outside. Because the terms inside the brackets 
are all following each other in the input of the second module, terms that 
will add will be generated closely together.
The result is visible in the final statistics:
\begin{verbatim}
Time =      47.23 sec
                F        Terms active    =     184761
                         Bytes used      =    4928008

Time =      48.40 sec    Generated terms =     646646
                F        Terms in output =     184756
                         Bytes used      =    4883306
\end{verbatim}
Now the final step of the sorting has already almost the proper number of 
terms. The difference is due to brackets that are half in one `patch' on 
the disk and half in the next `patch' (for the meaning of the patches, one 
should read the part about sorting\index{sorting} in chapter~\ref{setup} on 
the setup file. It should be rather clear now that this saves disk space 
and the corresponding amount of time. These early cancellations can also be 
seen in the first statistics message of the second module. In the first 
case it is
\begin{verbatim}
Time =      19.76 sec    Generated terms =      10431
                F   5216 Terms left      =       8065
                         Bytes used      =     239406
\end{verbatim}
and in the second case it is
\begin{verbatim}
Time =      22.82 sec    Generated terms =      10124
                F   5835 Terms left      =       3186
                         Bytes used      =      96678
\end{verbatim}
This also causes a more efficient use of the large buffer and again a 
better use of the disk. There have been cases in which this `trick' was 
essential to keep the sort file inside the available disk space.