| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| |
| |
|
|
| int L = 577837, R = 979141; |
|
|
| int main() { |
| |
| int bits = 20; |
| assert(L >= (1 << 19) && R < (1 << 20)); |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
|
|
| |
|
|
| |
| |
| |
| |
| |
|
|
| cout << "Analyzing ADFA states for L=" << L << " R=" << R << " bits=" << bits << endl; |
|
|
| |
| |
|
|
| struct State { |
| int lo, hi; |
| int k; |
| }; |
|
|
| |
| map<tuple<int,int,int>, int> state_id; |
| int next_id = 0; |
|
|
| |
| vector<array<int,2>> trans; |
|
|
| |
| function<int(int, int, int)> get_state = [&](int k, int lo, int hi) -> int { |
| if (lo > hi) return -1; |
| auto key = make_tuple(k, lo, hi); |
| auto it = state_id.find(key); |
| if (it != state_id.end()) return it->second; |
|
|
| int id = next_id++; |
| state_id[key] = id; |
| trans.push_back({-1, -1}); |
|
|
| if (k == 0) { |
| |
| return id; |
| } |
|
|
| int mid = 1 << (k - 1); |
| |
| |
| int lo0 = lo, hi0 = min(hi, mid - 1); |
| trans[id][0] = get_state(k - 1, lo0, hi0); |
|
|
| |
| |
| int lo1 = max(lo, mid) - mid, hi1 = hi - mid; |
| trans[id][1] = get_state(k - 1, lo1, hi1); |
|
|
| return id; |
| }; |
|
|
| |
| |
| |
| |
| int base = 1 << 19; |
| int lo_start = max(0, L - base); |
| int hi_start = min((1 << 19) - 1, R - base); |
|
|
| cout << "Start suffix range: [" << lo_start << ", " << hi_start << "]" << endl; |
|
|
| int start_child = get_state(19, lo_start, hi_start); |
|
|
| |
| |
| |
|
|
| cout << "\nTotal distinct states (excluding START): " << next_id << endl; |
| cout << "Total nodes (including START): " << next_id + 1 << endl; |
|
|
| |
| map<int, vector<pair<int,int>>> by_k; |
| for (auto& [key, id] : state_id) { |
| auto [k, lo, hi] = key; |
| by_k[k].push_back({lo, hi}); |
| } |
|
|
| cout << "\nStates by depth (remaining bits k -> number of states):" << endl; |
| int total = 1; |
| for (int k = 19; k >= 0; k--) { |
| auto& states = by_k[k]; |
| sort(states.begin(), states.end()); |
| cout << "k=" << k << " (depth " << (20-k) << "): " << states.size() << " states" << endl; |
| for (auto& [lo, hi] : states) { |
| auto it = state_id.find({k, lo, hi}); |
| int id = it->second; |
| cout << " id=" << id << " [" << lo << "," << hi << "]"; |
| if (k > 0) { |
| cout << " -> 0:" << trans[id][0] << " 1:" << trans[id][1]; |
| } |
| cout << endl; |
| } |
| total += states.size(); |
| } |
| cout << "\nTotal: " << total << endl; |
|
|
| |
| |
| cout << "\n=== Cross-depth analysis ===" << endl; |
|
|
| |
| |
| |
| |
|
|
| |
| |
| map<int, long long> state_hash; |
|
|
| function<long long(int)> compute_hash = [&](int id) -> long long { |
| if (state_hash.count(id)) return state_hash[id]; |
| if (id == -1) return -1; |
| long long h0 = compute_hash(trans[id][0]); |
| long long h1 = compute_hash(trans[id][1]); |
| |
| long long h = h0 * 1000000007LL + h1 * 998244353LL + 12345; |
| return state_hash[id] = h; |
| }; |
|
|
| for (auto& [key, id] : state_id) { |
| compute_hash(id); |
| } |
|
|
| |
| map<long long, vector<int>> by_hash; |
| for (auto& [key, id] : state_id) { |
| by_hash[state_hash[id]].push_back(id); |
| } |
|
|
| cout << "\nStates grouped by sub-DAG hash:" << endl; |
| int mergeable = 0; |
| for (auto& [h, ids] : by_hash) { |
| if (ids.size() > 1) { |
| cout << "Hash " << h << ": states"; |
| for (int id : ids) { |
| |
| for (auto& [key, sid] : state_id) { |
| if (sid == id) { |
| auto [k, lo, hi] = key; |
| cout << " (k=" << k << ",[" << lo << "," << hi << "])"; |
| break; |
| } |
| } |
| } |
| cout << endl; |
| mergeable += ids.size() - 1; |
| } |
| } |
| cout << "Potentially mergeable: " << mergeable << " states" << endl; |
|
|
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
|
|
| |
| map<int, int> eq_class; |
| int n_classes = 0; |
|
|
| |
| |
|
|
| |
| for (int k = 0; k <= 19; k++) { |
| |
| map<pair<int,int>, int> sig_to_class; |
|
|
| for (auto& [key, id] : state_id) { |
| auto [kk, lo, hi] = key; |
| if (kk != k) continue; |
|
|
| if (k == 0) { |
| |
| if (!sig_to_class.count({-1, -1})) { |
| sig_to_class[{-1, -1}] = n_classes++; |
| } |
| eq_class[id] = sig_to_class[{-1, -1}]; |
| } else { |
| int c0 = (trans[id][0] == -1) ? -1 : eq_class[trans[id][0]]; |
| int c1 = (trans[id][1] == -1) ? -1 : eq_class[trans[id][1]]; |
| auto sig = make_pair(c0, c1); |
| if (!sig_to_class.count(sig)) { |
| sig_to_class[sig] = n_classes++; |
| } |
| eq_class[id] = sig_to_class[sig]; |
| } |
| } |
| } |
|
|
| cout << "\n=== After cross-depth minimization ===" << endl; |
| cout << "Number of equivalence classes: " << n_classes << endl; |
| cout << "Total nodes (with START): " << n_classes + 1 << endl; |
|
|
| |
| map<int, vector<int>> class_members; |
| for (auto& [id, cls] : eq_class) { |
| class_members[cls].push_back(id); |
| } |
|
|
| int merged_count = 0; |
| for (auto& [cls, members] : class_members) { |
| if (members.size() > 1) { |
| cout << "Class " << cls << " merges:"; |
| for (int id : members) { |
| for (auto& [key, sid] : state_id) { |
| if (sid == id) { |
| auto [k, lo, hi] = key; |
| cout << " (k=" << k << ",[" << lo << "," << hi << "])"; |
| break; |
| } |
| } |
| } |
| cout << endl; |
| merged_count += members.size() - 1; |
| } |
| } |
| cout << "Total nodes saved by cross-depth merging: " << merged_count << endl; |
|
|
| return 0; |
| } |
|
|