1 #include "cado.h" // IWYU pragma: keep
2 
3 #include <list>
4 #include <map>
5 #include <string>
6 // #include <iostream>
7 #include <sstream>
8 #include <cstring>      // strlcpy (openbsd) // IWYU pragma: keep
9 
10 #include "las-descent-trees.hpp"
11 #include "portability.h"
12 #include "macros.h"
13 
14 
15 using namespace std;
16 
display_tree(FILE * o,tree * t,string const & prefix)17 int descent_tree::display_tree(FILE* o, tree * t, string const& prefix) {
18     int res = 1;
19     char comment[10] = {'\0'};
20     if (!t->contender) {
21         if (t->try_again) {
22             snprintf(comment, sizeof(comment), " try%d", t->try_again);
23         } else {
24             size_t rc = strlcpy(comment, " ###", sizeof(comment));
25             ASSERT_ALWAYS(rc < sizeof(comment));
26         }
27     }
28     fprintf(o, "%s%s [%1.4f]%s\t\t%s\n",
29             prefix.c_str(), t->label().c_str(), t->spent,
30             comment,
31             t->label.fullname().c_str());
32     string new_prefix = prefix + "  ";
33     typedef list<tree *>::iterator it_t;
34     for(it_t i = t->children.begin() ; i != t->children.end() ; i++) {
35         if (!display_tree(o, *i, new_prefix))
36             res = 0;
37     }
38     if (!t->contender)
39         res = 0;
40     return res;
41 }
42 
display_last_tree(FILE * o)43 void descent_tree::display_last_tree(FILE * o) {
44     bool xs = is_successful(forest.back());
45     display_tree(o, forest.back(), xs ? "# ": "# FAILED ");
46 }
47 
48 struct collected_stats {
49     bool ok;
50     double t;
51     int d;
52     int w;
collected_statscollected_stats53     collected_stats(bool ok, double t, int d, int w) :
54         ok(ok), t(t), d(d), w(w) {}
55 };
56 
display_all_trees(FILE * o)57 void descent_tree::display_all_trees(FILE * o)
58 {
59     typedef list<tree *>::iterator it_t;
60     int total = 0, good = 0;
61     for(it_t i = forest.begin() ; i != forest.end() ; i++, total++) {
62         bool xs = is_successful(*i);
63         good += display_tree(o, *i, xs ? "# ": "# FAILED ");
64     }
65     fprintf(o, "# Success %d/%d (%1.2f%%)\n", good, total,
66             100.0 * (double) good / total);
67     list<collected_stats> foo;
68     typedef map<tree_label, list<collected_stats> > stats_t;
69     stats_t stats;
70     typedef stats_t::iterator sit_t;
71     for(it_t i = forest.begin() ; i != forest.end() ; i++, total++) {
72         collected_stats w(is_successful(*i),
73                 (*i)->spent,
74                 tree_depth(*i),
75                 tree_weight(*i)
76                 );
77         sit_t it = stats.find((*i)->label);
78         if (it == stats.end()) {
79             list<collected_stats> v;
80             v.push_back(w);
81             stats.insert(make_pair((*i)->label, v));
82         } else {
83             it->second.push_back(w);
84         }
85     }
86 #if 0
87     /* (since we've dropped the dependence on siever_config, we now
88      * longer do this)
89      */
90     /* We also use this to provide an updated stats file (whose
91      * results are based on actual descents, and thus less
92      * speculative) */
93 
94     list<string> new_hints;
95     for(sit_t it = stats.begin() ; it != stats.end() ; it++) {
96         /* Collect and print stats for this sq size */
97         fprintf(o, "# Stats for %s\n", it->first().c_str());
98         int n = it->second.size();
99         int nok = 0;
100         double t1 = 0;
101         double t2 = 0;
102         double tmin = 999999;
103         double tmax = 0;
104         int d1 = 0;
105         int dmin = 0;
106         int dmax = 0;
107         int w1 = 0;
108         int wmin = 0;
109         int wmax = 0;
110         typedef list<collected_stats>::iterator lit_t;
111         for(lit_t i = it->second.begin() ; i != it->second.end() ; i++) {
112             nok += i->ok;
113             t1 += i->t;
114             t2 += i->t * i->t;
115             d1 += i->d;
116             w1 += i->w;
117             tmin = min(tmin, i->t);
118             tmax = max(tmax, i->t);
119             dmin = min(dmin, i->d);
120             dmax = max(dmax, i->d);
121             wmin = min(wmin, i->w);
122             wmax = max(wmax, i->w);
123         }
124         fprintf(o, "#   success %.2f (%d/%d)\n", (double) nok / n, nok, n);
125         fprintf(o, "#   depth avg %.1f, min %d, max %d\n",
126                 (double) d1/n, dmin, dmax);
127         fprintf(o, "#   weight avg %.1f, min %d, max %d\n",
128                 (double) w1/n, wmin, wmax);
129         double tt1 = (double) t1/n;
130         double tt2 = (double) t2/n;
131         fprintf(o, "#   time avg %.3f, sdev %.3f, min %.3f, max %.3f\n",
132                 tt1, sqrt(tt2-tt1*tt1), tmin, tmax);
133 
134         ostringstream os;
135         os << it->first()
136             << " " << tt1
137             << " " << (double) nok / n
138             << " I=" << it->first.sc->logI;
139         for(int i = 0 ; i < 2 ; i++) {
140             os << " " << it->first.sc->sides[i]->lim
141                 << "," << it->first.sc->sides[i]->lpb
142                 << "," << it->first.sc->sides[i]->mfb
143                 << "," << it->first.sc->sides[i]->lambda;
144         }
145         new_hints.push_back(os.str());
146     }
147     fprintf(o, "# The following data is an _example_ which can be used to provide a hint file\n");
148     for(list<string>::iterator i = new_hints.begin() ; i != new_hints.end() ; i++) {
149         fprintf(o, "# %s\n", i->c_str());
150     }
151 #endif
152 }
153 
154