forked from inakleinbottle/exponentiating_formulae
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbidirectional_transformer.cpp
155 lines (125 loc) · 6.55 KB
/
bidirectional_transformer.cpp
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
#include "SHOW.h"
#include "environment.h"
// the receiving environment: a number of channels generated by linear functionals of the past and future
// run backwards (signatures)
// the number of shuffles (linear functionals)
constexpr DEG WIDTHOUTLEFT = 1;
constexpr DEG WIDTHOUTRIGHT = 1;
constexpr DEG WIDTHOUT = WIDTHOUTLEFT + WIDTHOUTRIGHT;
// the degree of the signature desired in the output
constexpr DEG DEPTHOUT = 2;
// the depth of the shuffles producing the channels
constexpr DEG INOUTDEPTH = 2;
// the incoming stream with enough accuracy to determine the
// required integrals of the projections
constexpr DEG WIDTHIN = 2;
constexpr DEG DEPTHWORKING = (DEPTHOUT * INOUTDEPTH);
// the input, working and output environments
using IN = Environment<WIDTHIN, DEPTHOUT>;
using WORKING = Environment<WIDTHIN, DEPTHWORKING>;
using OUT = Environment<WIDTHOUT, DEPTHOUT>;
int bidirectional_transformer()
{
IN in;
WORKING working;
OUT out;
//adjoint_to_multiply(antipode(sig),sh)
std::cout << "Creating three generic input log signatures \"before\", \"during\", \" and \"after\" truncated to level " << DEPTHOUT << "\n\n";
IN::LIE logsig_before = in.generic_vector<IN::LIE>(1000);
IN::TENSOR sig_before = exp(in.maps_.l2t(logsig_before));
// pad the lie element with zeros and then exponentiate it
WORKING::LIE logsig_before_working;
add_equals_short(logsig_before_working, logsig_before);
WORKING::TENSOR sig_before_working = exp(working.maps_.l2t(logsig_before_working));
IN::LIE logsig_during = in.generic_vector<IN::LIE>(2000);
IN::TENSOR sig_during = exp(in.maps_.l2t(logsig_during));
// pad the lie element with zeros and then exponentiate it
WORKING::LIE logsig_during_working;
add_equals_short(logsig_during_working, logsig_during);
WORKING::TENSOR sig_during_working = exp(working.maps_.l2t(logsig_during_working));
IN::LIE logsig_after = in.generic_vector<IN::LIE>(3000);
IN::TENSOR sig_after = exp(in.maps_.l2t(logsig_after));
// pad the lie element with zeros and then exponentiate it
WORKING::LIE logsig_after_working;
add_equals_short(logsig_after_working, logsig_after);
WORKING::TENSOR sig_after_working = exp(working.maps_.l2t(logsig_after_working));
IN::TENSOR sig = sig_before * sig_during * sig_after;
// Create the left and right shuffles; the left shuffles act on the signature of the path up to the current time;
// the right shuffles act on the signature of the remainder of the path run backwards
// all shuffles generate channels in path.
typename WORKING::SHUFFLE_TENSOR generic_basic_shuffles[OUT::WIDTH];
const DEG in_shuffle_tensor_width = IN::SHUFFLE_TENSOR::BASIS::start_of_degree(INOUTDEPTH + 1) - IN::SHUFFLE_TENSOR::BASIS::start_of_degree(0);
// now populate a vector of shuffles that gives the OUT path
std::cout << "Creating the weights: " << OUT::WIDTH << " generic truncated input shuffles truncated to level " << INOUTDEPTH << "\n\n";
{
IN::SHUFFLE_TENSOR generic_basic_shuffles_short[OUT::WIDTH];
int count = 0;
for (auto& sh : generic_basic_shuffles_short) {
sh= in.generic_vector<IN::SHUFFLE_TENSOR>(count);
count += in_shuffle_tensor_width;
}
// now twist the shuffles so that they all act on the
// signature of the initial segment of the path
//
// modify the right width shuffles
// adjoint_to_multiply(antipode(sig),sh)
for (DEG it = WIDTHOUTLEFT; it != WIDTHOUT; ++it)
generic_basic_shuffles_short[it] = IN::adjoint_to_multiply(antipode(sig), generic_basic_shuffles_short[it]);
// copy the full set of truncated degree shuffles into the deeper workspace where the half-shuffles will all be defined
for (DEG it = 0; it != WIDTHOUT; ++it)
generic_basic_shuffles[it] = add_equals_short(generic_basic_shuffles[it], generic_basic_shuffles_short[it]);
std::cout << "Created " << WIDTHOUTLEFT << " generic channel defining shuffle polynomials with " << WIDTHOUTRIGHT << " twisted to access the future\n";
}
// now populate the tensor over the vector of shuffle coordinates
// to get the signature of the OUT path (a grouplike element).
std::map<OUT::TENSOR::BASIS::KEY, WORKING::SHUFFLE_TENSOR> result;
const OUT::TENSOR::BASIS obasis;
auto& obegin = obasis.begin();
auto& oend = obasis.end();
const WORKING::SHUFFLE_TENSOR::BASIS ibasis;
auto& ibegin = ibasis.begin();
auto& iend = ibasis.end();
auto tkey = obegin;
// the first entry in the tensor is the polynomial that is the constant 1
if (tkey != oend) {
result[tkey] = WORKING::SHUFFLE_TENSOR(WORKING::poly_t(1));
tkey = obasis.nextkey(tkey);
}
// the increment of the path (so constant terms get set to zero!!!)
if (tkey != oend) {
for (auto basic_shuffle : generic_basic_shuffles) {
basic_shuffle[ibegin] -= basic_shuffle[ibegin];
result[tkey] = basic_shuffle;
tkey = obasis.nextkey(tkey);
}
}
for (; tkey != oend; tkey = obasis.nextkey(tkey)) {
auto letter = tkey.lparent();// first letter of key as a key
auto rest = tkey.rparent(); // remainder of key as a key
result[tkey] = half_shuffle_multiply(result[letter], result[rest]);
}
OUT::TENSOR ans_before = apply1<OUT, WORKING>(result, sig_before_working);
SHOW(antipode(ans_before) * ans_before);
// note that result must be applied to the WORKING signature of the path
// provided by the extended log signatures along the chosen partition, and depends
// on the partition;
//
// but is defined for any interval where we have determined the working signature
// so we really have defined a rough path!!!!
//
// DEPTHIN rough path -> (fix a partition) piecewise lie approximation to degee DEPTHIN
// -> extend this to rough path defined on every interval of degree DEPTHWORKING
// -> use the formulae to produce a DEPTHOUT rough path on any interval
//
// So can change the partition from layer to layer!!!!!!!!!!
//
// the magic is that the twisting of the shuffles does not depend on
// the partition but only on the IN::sig
//
OUT::TENSOR ans_before_during = apply1<OUT, WORKING>(result, sig_before_working * sig_during_working);
SHOW(antipode(ans_before_during) * ans_before_during);
OUT::TENSOR ans_during = antipode(ans_before) * ans_before_during;
SHOW(antipode(ans_during) * ans_during);
std::cout <<out.maps_.t2l(log(ans_during)) << "\n\n";
return 0;
}