Skip to content
Snippets Groups Projects
net_test_pde_1.cpp 13.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • Michal Kravcenko's avatar
    Michal Kravcenko committed
    /**
    
     * Example solving the time dependent water flow 1D diffusion PDE:
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
     *
    
     * y_xx - y_t = 0, for (x, t) in [0, 1] x [0, 1]
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
     * y(0, t) = sin(t)
    
     * y(x, 0) = e^(-sqrt(0.5)x) * sin(-sqrt(0.5)x)
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
     *
     * -------------------------------------------
     * Analytical solution:
     * NN representation: sum over [a_i * (1 + e^(bi - x * w_ix - t * w_it))^(-1)]
     * -------------------------------------------
    
     * Optimal NN setting with biases (4 inner neurons)
    
     * Path   1. wx =      0.51954589, wt =     -0.48780445, b =      0.35656955, a =      1.69279158
     * Path   2. wx =     -1.24173503, wt =      1.13351300, b =      0.32528567, a =      1.69148458
     * Path   3. wx =      0.64754127, wt =      0.95758760, b =     -0.95852707, a =      2.77877453
     * Path   4. wx =      1.65439557, wt =     -0.31784248, b =     -1.81237586, a =     -3.96157108
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
     * @author Michal Kravčenko
     * @date 9.8.18
     */
    
    #include <random>
    #include <iostream>
    
    kra568's avatar
    kra568 committed
    #include <4neuro_public.h>
    
    Martin Beseda's avatar
    Martin Beseda committed
    void optimize_via_particle_swarm(l4n::DESolver& solver,
                                     l4n::MultiIndex& alpha,
                                     size_t max_iters,
                                     size_t n_particles) {
    
        printf("Solution via the particle swarm optimization!\n");
    
    Martin Beseda's avatar
    Martin Beseda committed
        std::vector<double> domain_bounds(
    
            2 * (solver.get_solution(alpha)->get_n_biases() + solver.get_solution(alpha)->get_n_weights()));
    
    Martin Beseda's avatar
    Martin Beseda committed
        for (size_t i = 0; i < domain_bounds.size() / 2; ++i) {
    
            domain_bounds[2 * i]     = -10;
    
        double w  = 0.700;
    
    
        /* if the maximal velocity from the previous step is less than 'gamma' times the current maximal velocity, then one
         * terminating criterion is met */
        double gamma = 0.5;
    
        /* if 'delta' times 'n' particles are in the centroid neighborhood given by the radius 'epsilon', then the second
         * terminating criterion is met ('n' is the total number of particles) */
        double epsilon = 0.02;
    
        double delta   = 0.7;
    
            &domain_bounds,
            c1,
            c2,
            w,
            gamma,
            epsilon,
            delta,
            n_particles,
            max_iters
    
    Martin Beseda's avatar
    Martin Beseda committed
        solver.solve(swarm);
    
    Martin Beseda's avatar
    Martin Beseda committed
    void optimize_via_gradient_descent(l4n::DESolver& solver,
                                       double accuracy) {
    
        printf("Solution via a gradient descent method!\n");
    
    Martin Beseda's avatar
    Martin Beseda committed
        l4n::GradientDescent gd(accuracy,
                                1000);
    
    Martin Beseda's avatar
    Martin Beseda committed
        solver.randomize_parameters();
        solver.solve(gd);
    
    Martin Beseda's avatar
    Martin Beseda committed
    void export_solution(size_t n_test_points,
                         double te,
                         double ts,
                         l4n::DESolver& solver,
                         l4n::MultiIndex& alpha_00,
                         l4n::MultiIndex& alpha_01,
                         l4n::MultiIndex& alpha_20,
                         const std::string prefix) {
    
        l4n::NeuralNetwork* solution    = solver.get_solution(alpha_00);
        l4n::NeuralNetwork* solution_t  = solver.get_solution(alpha_01);
    
    Martin Beseda's avatar
    Martin Beseda committed
        l4n::NeuralNetwork* solution_xx = solver.get_solution(alpha_20);
    
        size_t i, j;
        double x, t;
        /* ISOTROPIC TEST SET FOR BOUNDARY CONDITIONS */
        /* first boundary condition & its error */
    
    Martin Beseda's avatar
    Martin Beseda committed
        sprintf(buff,
                "%sdata_2d_pde1_y.txt",
                prefix.c_str());
        std::string final_fn(buff);
    
        printf("Exporting file '%s' : %7.3f%%\r",
               final_fn.c_str(),
               0.0);
    
        std::vector<double> input(2), output(1), output_t(1), output_xx(1);
    
        std::ofstream       ofs(final_fn,
                                std::ofstream::out);
        double              frac        = (te - ts) / (n_test_points - 1);
    
    Martin Beseda's avatar
    Martin Beseda committed
        for (i = 0; i < n_test_points; ++i) {
    
            x      = i * frac + ts;
    
    Martin Beseda's avatar
    Martin Beseda committed
            for (j = 0; j < n_test_points; ++j) {
    
                t     = j * frac + ts;
    
    Martin Beseda's avatar
    Martin Beseda committed
                solution->eval_single(input,
                                      output);
    
                ofs << x << " " << t << " " << output[0] << std::endl;
    
    Martin Beseda's avatar
    Martin Beseda committed
                printf("Exporting file '%s' : %7.3f%%\r",
                       final_fn.c_str(),
                       (100.0 * (j + i * n_test_points)) / (n_test_points * n_test_points - 1));
    
    Martin Beseda's avatar
    Martin Beseda committed
        printf("Exporting file '%s' : %7.3f%%\n",
               final_fn.c_str(),
               100.0);
    
    Martin Beseda's avatar
    Martin Beseda committed
        sprintf(buff,
                "%sdata_2d_pde1_first_equation_error.txt",
                prefix.c_str());
        final_fn = std::string(buff);
    
        ofs = std::ofstream(final_fn,
                            std::ofstream::out);
        printf("Exporting file '%s' : %7.3f%%\r",
               final_fn.c_str(),
               0.0);
        for (i = 0; i < n_test_points; ++i) {
    
            x      = i * frac + ts;
    
    Martin Beseda's avatar
    Martin Beseda committed
            for (j = 0; j < n_test_points; ++j) {
    
                t     = j * frac + ts;
    
    Martin Beseda's avatar
    Martin Beseda committed
                solution_t->eval_single(input,
                                        output_t);
                solution_xx->eval_single(input,
                                         output_xx);
    
                ofs << x << " " << t << " " << std::fabs(output_xx[0] - output_t[0]) << std::endl;
    
    Martin Beseda's avatar
    Martin Beseda committed
                printf("Exporting file 'data_2d_pde1_first_equation_error.txt' : %7.3f%%\r",
                       (100.0 * (j + i * n_test_points)) / (n_test_points * n_test_points - 1));
    
    Martin Beseda's avatar
    Martin Beseda committed
        printf("Exporting file '%s' : %7.3f%%\n",
               final_fn.c_str(),
               100.0);
    
        /* ISOTROPIC TEST SET FOR BOUNDARY CONDITIONS */
        /* first boundary condition & its error */
    
    Martin Beseda's avatar
    Martin Beseda committed
        sprintf(buff,
                "%sdata_1d_pde1_yt.txt",
                prefix.c_str());
    
    Martin Beseda's avatar
    Martin Beseda committed
        sprintf(buff,
                "%sdata_1d_pde1_yx.txt",
                prefix.c_str());
    
    Martin Beseda's avatar
    Martin Beseda committed
        ofs = std::ofstream(final_fn_t,
                            std::ofstream::out);
        std::ofstream ofs2(final_fn_x,
                           std::ofstream::out);
        printf("Exporting files '%s' and '%s' : %7.3f%%\r",
               final_fn_t.c_str(),
               final_fn_x.c_str(),
               0.0);
        for (i = 0; i < n_test_points; ++i) {
    
    Martin Beseda's avatar
    Martin Beseda committed
            double yx = std::pow(l4n::E,
                                 -0.707106781 * x) * std::sin(-0.707106781 * x);
    
    Martin Beseda's avatar
    Martin Beseda committed
            solution->eval_single(input,
                                  output);
    
    Martin Beseda's avatar
    Martin Beseda committed
            solution->eval_single(input,
                                  output);
    
            ofs << i + 1 << " " << t << " " << yt << " " << evalt << " " << std::fabs(evalt - yt) << std::endl;
            ofs2 << i + 1 << " " << x << " " << yx << " " << evalx << " " << std::fabs(evalx - yx) << std::endl;
    
    Martin Beseda's avatar
    Martin Beseda committed
            printf("Exporting files '%s' and '%s' : %7.3f%%\r",
                   final_fn_t.c_str(),
                   final_fn_x.c_str(),
                   (100.0 * i) / (n_test_points - 1));
    
    Martin Beseda's avatar
    Martin Beseda committed
        printf("Exporting files '%s' and '%s' : %7.3f%%\n",
               final_fn_t.c_str(),
               final_fn_x.c_str(),
               100.0);
    
    Martin Beseda's avatar
    Martin Beseda committed
        std::cout
    
            << "********************************************************************************************************************************************"
            << std::endl;
    
    Martin Beseda's avatar
    Martin Beseda committed
    
    void test_pde(double accuracy,
                  size_t n_inner_neurons,
                  size_t train_size,
                  double ds,
                  double de,
                  size_t n_test_points,
                  double ts,
                  double te,
                  size_t max_iters,
                  size_t n_particles) {
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        /* do not change below */
    
        size_t        n_inputs    = 2;
        size_t        n_equations = 3;
    
    Martin Beseda's avatar
    Martin Beseda committed
        l4n::DESolver solver_01(n_equations,
                                n_inputs,
                                n_inner_neurons);
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        /* SETUP OF THE EQUATIONS */
    
    Martin Beseda's avatar
    Martin Beseda committed
        l4n::MultiIndex alpha_00(n_inputs);
        l4n::MultiIndex alpha_01(n_inputs);
        l4n::MultiIndex alpha_20(n_inputs);
    
    Martin Beseda's avatar
    Martin Beseda committed
        alpha_00.set_partial_derivative(0,
                                        0);
        alpha_01.set_partial_derivative(1,
                                        1);
        alpha_20.set_partial_derivative(0,
                                        2);
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        /* the governing differential equation */
    
    Martin Beseda's avatar
    Martin Beseda committed
        solver_01.add_to_differential_equation(0,
                                               alpha_20,
                                               "1.0");
        solver_01.add_to_differential_equation(0,
                                               alpha_01,
                                               "-1.0");
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        /* dirichlet boundary condition */
    
    Martin Beseda's avatar
    Martin Beseda committed
        solver_01.add_to_differential_equation(1,
                                               alpha_00,
                                               "1.0");
        solver_01.add_to_differential_equation(2,
                                               alpha_00,
                                               "1.0");
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        /* SETUP OF THE TRAINING DATA */
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        std::vector<double> inp, out;
    
        double frac, x, t;
    
        /* TRAIN DATA FOR THE GOVERNING DE */
    
        std::vector<std::pair<std::vector<double>, std::vector<double>>> data_vec_zero;
    
        frac = (de - ds) / (train_size - 1);
        for (unsigned int i = 0; i < train_size; ++i) {
            for (unsigned int j = 0; j < train_size; ++j) {
                inp = {frac * j, frac * i};
                out = {0.0};
                data_vec_zero.emplace_back(std::make_pair(inp,
    
        l4n::DataSet      ds_00(&data_vec_zero);
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        std::vector<std::pair<std::vector<double>, std::vector<double>>> data_vec_t;
        std::vector<std::pair<std::vector<double>, std::vector<double>>> data_vec_x;
    
        /* ISOTROPIC TRAIN SET */
        frac = (de - ds) / (train_size - 1);
    
    Martin Beseda's avatar
    Martin Beseda committed
        for (unsigned int i = 0; i < train_size; ++i) {
    
            inp = {0.0, frac * i};
            out = {std::sin(inp[1])};
    
    Martin Beseda's avatar
    Martin Beseda committed
            data_vec_t.emplace_back(std::make_pair(inp,
                                                   out));
    
    Martin Beseda's avatar
    Martin Beseda committed
            out = {std::pow(l4n::E,
                            -0.707106781 * inp[0]) * std::sin(-0.707106781 * inp[0])};
            data_vec_x.emplace_back(std::make_pair(inp,
                                                   out));
    
        l4n::DataSet ds_t(&data_vec_t);
        l4n::DataSet ds_x(&data_vec_x);
    
        std::cout << "Train data setup finished" << std::endl;
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
        /* Placing the conditions into the solver */
    
    Martin Beseda's avatar
    Martin Beseda committed
        solver_01.set_error_function(0,
                                     l4n::ErrorFunctionType::ErrorFuncMSE,
    
    Martin Beseda's avatar
    Martin Beseda committed
        solver_01.set_error_function(1,
                                     l4n::ErrorFunctionType::ErrorFuncMSE,
    
    Martin Beseda's avatar
    Martin Beseda committed
        solver_01.set_error_function(2,
                                     l4n::ErrorFunctionType::ErrorFuncMSE,
    
        std::cout << "Error function defined" << std::endl;
    
        /* Solving the equation */
    
    Martin Beseda's avatar
    Martin Beseda committed
        optimize_via_particle_swarm(solver_01,
                                    alpha_00,
                                    max_iters,
                                    n_particles);
        export_solution(n_test_points,
                        te,
                        ts,
                        solver_01,
                        alpha_00,
                        alpha_01,
                        alpha_20,
                        "particle_");
    
        optimize_via_gradient_descent(solver_01,
                                      accuracy);
        export_solution(n_test_points,
                        te,
                        ts,
                        solver_01,
                        alpha_00,
                        alpha_01,
                        alpha_20,
                        "gradient_");
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    }
    
    int main() {
    
        std::cout << "Running lib4neuro Partial Differential Equation example   1" << std::endl;
    
    Martin Beseda's avatar
    Martin Beseda committed
        std::cout
    
            << "********************************************************************************************************************************************"
            << std::endl;
    
    Martin Beseda's avatar
    Martin Beseda committed
        std::cout
    
            << "          Governing equation: y_xx - y_t = 0,                                   for (x, t) in [0, 1] x [0, 1]"
            << std::endl;
    
    Martin Beseda's avatar
    Martin Beseda committed
        std::cout << "Dirichlet boundary condition:    y(0, t) = sin(t),                              for t in [0, 1]"
                  << std::endl;
        std::cout << "Dirichlet boundary condition:    y(x, 0) = exp(-sqrt(0.5)x) * sin(-sqrt(0.5)x), for x in [0, 1]"
                  << std::endl;
        std::cout
    
            << "********************************************************************************************************************************************"
            << std::endl;
    
    Martin Beseda's avatar
    Martin Beseda committed
        std::cout
    
            << "Expressing solution as y(x, t) = sum over [a_i / (1 + exp(bi - wxi*x - wti*t))], i in [1, n], where n is the number of hidden neurons"
            << std::endl;
    
    Martin Beseda's avatar
    Martin Beseda committed
        std::cout
    
            << "********************************************************************************************************************************************"
            << std::endl;
    
        unsigned int n_inner_neurons = 2;
    
        unsigned int train_size      = 5;
        double       accuracy        = 1e-1;
        double       ds              = 0.0;
        double       de              = 1.0;
    
        unsigned int test_size = 10;
    
        double       ts        = ds;
        double       te        = de + 0;
    
        size_t particle_swarm_max_iters = 10;
    
        size_t n_particles              = 5;
    
    Martin Beseda's avatar
    Martin Beseda committed
        test_pde(accuracy,
                 n_inner_neurons,
                 train_size,
                 ds,
                 de,
                 test_size,
                 ts,
                 te,
                 particle_swarm_max_iters,
                 n_particles);
    
    Michal Kravcenko's avatar
    Michal Kravcenko committed
    
        return 0;