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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
/////////////////////////
#include <iostream>
using namespace std;
void usage() {
cout << R"EoF(Program to fit to perform Singular Value Decomposition (SVD).
Typical usage:
./svd -m -1 -ifile whatever.csv -svd eigen.csv
Options include:
-h # print this message (and immediately exit)
-ifile $fn # input data file
-svd $fn # write the results to $fn
-meta NN # use NNth line of input header as metadata
# NN=-1 means use *last* line of input header
To write to stdout, use "-" for the $fn.
)EoF";
}
#include <iomanip> /* for setw */
#include <vector>
#include "arg_parser.h"
#include <string>
#include <sstream>
#include <map>
#include "parse_csv.h"
#include "poissonier.h"
#include <armadillo>
// Format all the elements of a C++ vector,
// creating a string suitable for printing.
template<class T>
string dump(vector<T> const arg) {
stringstream rslt;
string sep = "";
for (T val : arg) {
rslt << sep << val;
sep = ", ";
}
return rslt.str();
}
// Format all the elements of a counted array,
// creating a string suitable for printing.
template<class T>
string dump(int const nn, T const arg[]) {
stringstream rslt;
string sep = "";
for (int ii = 0; ii < nn; ii++) {
rslt << sep << arg[ii];
sep = ",";
}
return rslt.str();
}
// numerically accurate sinh(arg)/arg
template<class T>
inline T sinhc(T arg) {
if (abs(arg) < 1e-4) return 1 + arg*arg/6;
return sinh(arg)/arg;
}
struct evendor {
double t; // time
double n; // number of events
};
// Intensity, usually denoted lambda,
// i.e. integral of rate(t) dt over the given interval.
double inty_multi_exp(vector<double> const& prm,
double const t1, double const t2, vector<double> const norm) {
double rslt(0);
int nn = prm.size();
for (int ii = 0; ii < nn; ii+=2){
double amp(prm[ii] * norm[ii]);
double rate(1+ii < nn ? prm[1+ii] * norm[1+ii] : 0.);
double mid((t2 + t1) / 2.);
double tau(t2 - t1);
rslt += amp * exp(-rate*mid) * tau * sinhc(rate*tau/2.);
}
return rslt;
}
// Add something to a particular component of a vector.
template<class T>
vector<T> goose(vector<T> const& vvv, int const ii, T const delta) {
vector<T> rslt(vvv);
rslt[ii] += delta;
return rslt;
}
typedef vector<vector<string> > VVS;
void dump_matrix(ostream& ouch, arma::mat const &mmm,
int const pr = 3, int const texmode=0){
int wd(pr+6);
int dim(mmm.n_rows);
for (int ii = 0; ii < dim; ii++) {
for (int jj = 0; jj < dim; jj++) {
if (texmode) {
if ( mmm(ii, jj) > 3 )
ouch << "\\y{"; /* } */
else ouch << "\\x{"; /* } */
ouch << setprecision(pr) << setw(wd) << mmm(ii, jj)
/* { */ << "} ";
} else {
ouch << setprecision(pr) << setw(wd) << mmm(ii, jj) << ", ";
}
}
if (texmode) {
ouch << " \\z" << endl;
} else {
ouch << endl;
}
}
}
string dump(arma::mat const mmm, string const prefix="") {
int NR = mmm.n_rows;
int NC = mmm.n_cols;
stringstream rslt;
for (int ii = 0; ii < NR; ii++) {
string sep = prefix;
for (int jj = 0; jj < NC; jj++) {
rslt << sep << fixed << setw(11) << mmm(ii, jj);
sep = ", ";
}
rslt << endl;
}
return rslt.str();
}
string dump(arma::vec vvv, arma::mat const mmm) {
int NR = mmm.n_rows;
int NC = mmm.n_cols;
stringstream rslt;
for (int ii = 0; ii < NR; ii++) {
rslt << fixed << setw(11) << vvv(ii)
<< ","; // skip a column
for (int jj = 0; jj < NC; jj++) {
rslt << "," << fixed << setw(11) << mmm(ii, jj);
}
rslt << endl;
}
return rslt.str();
}
string dumpx(arma::vec vvv, arma::mat const mmm) {
int NR = mmm.n_rows;
int NC = mmm.n_cols;
stringstream rslt;
for (int ii = 0; ii < NR; ii++) {
double tmp = vvv(ii);
rslt << fixed << setw(11) << tmp;
rslt << ","; // skip a column
for (int jj = 0; jj < NC; jj++) {
rslt << "," << fixed << setw(11) << mmm(ii, jj);
}
rslt << endl;
}
return rslt.str();
}
void do_svd(string const ifile, string const ofile,
int const gotmeta, int whichmeta){
if (ifile == "") {
if (ofile != "") throw invalid_argument("do_fit needs an input file");
return;
}
ifstream inx;
if (ifile != "-") {
inx.open(ifile);
if (! inx.good()) {
cerr << "Cannot open input '" << ifile << "'" << endl;
exit(1);
}
}
istream& in(ifile == "-" ? cin : inx);
VVS alldata;
alldata = readCSV<string>(in);
cout << alldata.size() << endl;
int hh = count_header(alldata);
cout << hh << endl;
VVS aoa(alldata.begin()+hh, alldata.end());
int NR = aoa.size();
if (NR == 0) throw invalid_argument("no data???");
int NC = aoa[0].size();
cout << "NR: " << NR
<< " NC: " << NC << endl;
arma::mat maha(NR, NC, arma::fill::zeros);
for (int ii = 0; ii < NR; ii++) {
for (int jj = 0; jj < NC; jj++) {
maha(ii, jj) = stod(aoa[ii][jj]);
}
}
if (ofile != "") {
ofstream xxout;
if (ofile != "-") {
xxout.open(ofile);
}
ostream& xout(ofile != "-" ? xxout : cout);
string meta;
if (gotmeta) {
if (whichmeta < 0) whichmeta += hh;
meta = dump(alldata[whichmeta]);
}
xout << ",," << meta << endl;
xout << dump(maha, ",,"); // already includes newlines
arma::mat U, V;
arma::vec eival;
arma::svd(U, eival, V, maha);
xout << endl;
xout << "cost²,," << meta << endl;
xout << dumpx(eival, V) << endl;
}
}
int main(int argc, char * const * argv) {
poissonier poi;
string seed;
string ifile;
arg_parser arg(argc, argv);
arg.fold_case = 1;
string progname = arg.nextRaw();
string svdfile;
int gotmeta(0);
int whichmeta(0);
for (;;){
string raw_arg = arg.nextRaw(); // get next keyword
if (arg.fail()) break;
int where = arg.cur.length();
if (where){
if (arg.cur[where-1] == ':') arg.cur = arg.cur.substr(0,where-1);
}
if (0) {}
else if (arg.prefix("help") || arg.prefix("-h")) {
usage();
exit(0);
}
else if (arg.prefix("-meta")) {
gotmeta++;
arg >> whichmeta;
}
else if (arg.prefix("-ifile")) arg >> ifile;
else if (arg.prefix("-seed")) arg >> seed;
else if (arg.prefix("-svd")) arg >> svdfile;
else {
cerr << "Unrecognized command '" << raw_arg << "'" << endl;
exit(1);
}
}
if (seed == "--") seed = poi.randomize();
else if (seed != "") poi.seed(seed);
if (!(svdfile.length()
))
svdfile = "-";
do_svd(ifile, svdfile, gotmeta, whichmeta);
}
|