#include <iostream>
#include <vector>
#include <random>
#include <iomanip>
#include "bitset"
using namespace std;

class MarkovChain {
public:
    MarkovChain(size_t order, bool partial_links = false)
            : order_(order), partial_links_(partial_links) {
        size_t num_states = (1 << order); // 2^order
        transition_matrix_.resize(num_states, std::vector<double>(2, 0.0));
        generate_transition_matrix();
    }

    void generate_transition_matrix() {
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_real_distribution<> dis(0.0, 1.0);
        for (size_t state = 0; state < transition_matrix_.size(); ++state) {
            double p = dis(gen);
            transition_matrix_[state][0] = p;
            transition_matrix_[state][1] = 1.0 - p;
        }
    }

    void print_transition_matrix() {
        std::cout << std::fixed << std::setprecision(2);
        for (size_t state = 0; state < transition_matrix_.size(); ++state) {
            std::cout << "State " << bitset<3>(state) << ": "
                      << "0 -> " << transition_matrix_[state][0] << ", "
                      << "1 -> " << transition_matrix_[state][1] << std::endl;
        }
    }

    std::vector<int> generate_data(size_t length) {
        std::vector<int> data;
        data.reserve(length);
        size_t current_state = 0;
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_real_distribution<> dis(0.0, 1.0);
        for (size_t i = 0; i < length; ++i) {
            double random_value = dis(gen);
            int next_bit = random_value < transition_matrix_[current_state][0] ? 0 : 1;
            data.push_back(next_bit);
            if (partial_links_) {
                current_state = (current_state << 1) & ((1 << order_) - 1);
            } else {
                current_state = (current_state << 1 | next_bit) & ((1 << order_) - 1);
            }
        }
        return data;
    }
    void estimate_transition_matrix(const std::vector<int>& data) {
        size_t num_states = (1 << order_);
        std::vector<size_t> state_counts(num_states, 0);
        std::vector<std::vector<size_t>> transition_counts(num_states, std::vector<size_t>(2, 0));

        size_t current_state = 0;
        for (int bit : data) {
            ++state_counts[current_state];
            ++transition_counts[current_state][bit];
            if (partial_links_) {
                current_state = (current_state << 1) & ((1 << order_) - 1);
            } else {
                current_state = (current_state << 1 | bit) & ((1 << order_) - 1);
            }
        }
        ++state_counts[current_state];

        for (size_t state = 0; state < num_states; ++state) {
            double sum = static_cast<double>(state_counts[state]);
            transition_matrix_[state][0] = transition_counts[state][0] / sum;
            transition_matrix_[state][1] = transition_counts[state][1] / sum;
        }
    }

    double euclidean_norm() {
        double sum_of_squares = 0.0;
        for (size_t i = 0; i < transition_matrix_.size(); ++i) {
            for (size_t j = 0; j < transition_matrix_[i].size(); ++j) {
                sum_of_squares += transition_matrix_[i][j] * transition_matrix_[i][j];
            }
        }
        return std::sqrt(sum_of_squares);
    }


private:
    size_t order_;
    bool partial_links_;
    std::vector<std::vector<double>> transition_matrix_;
};

int main() {
    size_t order = 3;
    bool partial_links = false;
    MarkovChain chain(order, partial_links);
std::cout << "Transition matrix:" << std::endl;
    chain.print_transition_matrix();
    std::cout << "Euclidean norm of transition matrix: " << chain.euclidean_norm() << std::endl;
    double norm1 = chain.euclidean_norm();
    size_t data_length = 1000;
    std::vector<int> generated_data = chain.generate_data(data_length);
    std::cout << "Generated data: ";
    for(int bit = 0;bit<10;bit++) {
        std::cout << generated_data[bit];
    }
    std::cout << std::endl;
    size_t estimated_data_length = 1000;
    std::vector<int> estimated_data = chain.generate_data(data_length);
    chain.estimate_transition_matrix(generated_data);


    std::cout << "\nEstimated transition matrix:\n";
    chain.print_transition_matrix();


    std::cout << "Euclidean norm of transition matrix: " << chain.euclidean_norm() << std::endl;
    double norm2 = chain.euclidean_norm();
    cout<<"Delta = "<<abs(norm1-norm2);

    return 0;
}
опиши подробно код для курсовой