 }
 
 
-/*
-size_t handle_maxpool_layer(elina_manager_t* man, elina_abstract0_t* element, const size_t* pool_size, const size_t* input_size)
-{
-    assert(pool_size[0] == 2 && pool_size[1] == 2 && pool_size[2] == 1);
-
-    size_t* output_size = (size_t*) malloc(3*sizeof(size_t));
-
-    for(size_t i = 0; i < 3; i++)
-    {
-        output_size[i] = input_size[i]/pool_size[i];
-    }
-
-    //size_t num_input_neurons = input_size[0]*input_size[1]*input_size[2];
-    const size_t num_out_neurons = output_size[0]*output_size[1]*output_size[2];
-
-    const size_t o12 = output_size[1]*output_size[2];
-    const size_t i12 = input_size[1]*input_size[2];
-    const size_t p01 = pool_size[0]*pool_size[1];
-
-    fppoly_t* const fp = fppoly_of_abstract0(element);
-    fppoly_add_new_layer(fp, num_out_neurons, MAXPOOL, NONE);
-
-    size_t out_pos;
-    double* inf = (double*) calloc(p01, sizeof(double));
-    double* sup = (double*) calloc(p01, sizeof(double));
-    size_t* pool_map = (size_t*) calloc(p01, sizeof(size_t));
-    neuron_t** out_neurons = fp->layers[fp->numlayers - 1]->neurons;
-
-    for(out_pos = 0; out_pos < num_out_neurons; out_pos++)
-    {
-        const size_t out_x = out_pos/o12;
-        const size_t out_y = (out_pos - out_x*o12)/output_size[2];
-        const size_t out_z = out_pos - out_x*o12 - out_y*output_size[2];
-
-        const size_t inp_x = out_x*pool_size[0];
-        const size_t inp_y = out_y*pool_size[1];
-        const size_t inp_z = out_z;
-
-        const size_t inp_pos = inp_x*i12 + inp_y*input_size[2] + inp_z;
-
-        size_t x_shift, y_shift, l = 0;
-
-        double sum_u = 0.0;
-        double sum_l = 0.0;
-        double max_u = -INFINITY;
-        double max_l = -INFINITY;
-
-        size_t max_l_var = 0;
-        size_t max_u_var = 0;
-        size_t min_width_var = 0;
-        double min_width = INFINITY;
-
-        for(x_shift = 0; x_shift < pool_size[0]; x_shift++)
-        {
-            for(y_shift = 0; y_shift < pool_size[1]; y_shift++)
-            {
-                const size_t pool_cur_dim = inp_pos + x_shift*i12 + y_shift*input_size[2];
-                pool_map[l] = pool_cur_dim;
-                // use the ReLU bounds from the previous layer
-                const double lb = -fp->layers[fp->numlayers - 2]->neurons[pool_cur_dim]->lb;
-                const double ub = fp->layers[fp->numlayers - 2]->neurons[pool_cur_dim]->ub;
-
-                if(ub <= 0)
-                {
-                    inf[l] = 0.0;
-                    sup[l] = 0.0;
-                }
-                else if(lb > 0)
-                {
-                    inf[l] = lb;
-                    sup[l] = ub;
-                }
-                else
-                {
-                    inf[l] = 0;
-                    sup[l] = ub;
-                }
-
-                sum_u = sum_u + sup[l];
-                sum_l = sum_l + inf[l];
-
-                if(sup[l] > max_u)
-                {
-                    max_u = sup[l];
-                    max_u_var = pool_map[l];
-                }
-
-                if(inf[l] > max_l)
-                {
-                    max_l = inf[l];
-                    max_l_var = pool_map[l];
-                }
-
-                if((ub-lb) < min_width)
-                {
-                    min_width = ub - lb;
-                    min_width_var = pool_map[l];
-                }
-
-                l++;
-            }
-        }
-
-        bool flag = false;
-        size_t var = 0;
-
-        for(size_t j = 0; j < p01; j++)
-        {
-            bool is_greater = true;
-
-            for(size_t k = 0; k < p01; k++)
-            {
-                if(k == j)
-                {
-                    continue;
-                }
-
-                if((inf[k] == sup[k]) && (inf[j] >= sup[k]))
-                {
-                    continue;
-                }
-                else if((inf[j] == inf[k]) && (sup[j] == sup[k]) && (inf[j] == sup[j]))
-                {
-                    continue;
-                }
-                else if(inf[j] <= sup[k])
-                {
-                    is_greater = false;
-                    break;
-                }
-            }
-
-            if(is_greater)
-            {
-                flag = true;
-                var = pool_map[j];
-                break;
-            }
-        }
-
-        if(flag)
-        {
-            double coeff[1];
-            size_t dim[1];
-            coeff[0] = 1;
-            dim[0] = var;
-            out_neurons[out_pos]->maxpool_lexpr = create_sparse_expr(coeff, 0, dim, 1);
-            out_neurons[out_pos]->maxpool_uexpr = create_sparse_expr(coeff, 0, dim, 1);
-            //out_neurons[out_pos]->expr = create_sparse_expr(coeff, 0, dim, 1);
-        }
-        else
-        {
-            double lcoeff[1];
-            size_t ldim[1];
-            lcoeff[0] = 1;
-            ldim[0] = max_l_var;
-
-            out_neurons[out_pos]->maxpool_lexpr = create_sparse_expr(lcoeff, 0, ldim, 1);
-
-            double ucoeff[1];
-            size_t udim[1];
-            ucoeff[0] = 0;
-            udim[0] = 0;
-            out_neurons[out_pos]->maxpool_uexpr = create_sparse_expr(ucoeff, max_u, udim, 1);
-        }
-
-        out_neurons[out_pos]->lb = -max_l;
-        out_neurons[out_pos]->ub = max_u;
-    }
-
-    //update_state_using_previous_layers(man, fp, fp->numlayers - 1);
-
-    free(inf);
-    free(sup);
-    free(pool_map);
-    free(output_size);
-
-    return num_out_neurons;
-}
-*/
-
-
 void free_layer(layer_t* layer)
 {
     free_expr_array<<<layer->num_out_neurons, 1>>>(layer->expr_array, layer->num_out_neurons);

}


/*
__global__
void device_layer_create_sparse_exprs(expr_t** expr_array, const double* weights, const double* bias, const size_t* dims, const size_t num_out_neurons, const size_t num_in_neurons)
{
    size_t i = blockIdx.x;

    if(i < num_out_neurons)
    {
        const double* weight_i = weights + i*num_in_neurons;
        const size_t* dims_i = dims + i*num_in_neurons;
        const double bias_i = bias[i];
        expr_array[i] = create_sparse_expr(weight_i, bias_i, dims_i, num_in_neurons);
        sort_sparse_expr(expr_array[i]);
    }
}


void layer_create_sparse_exprs(expr_t** expr_array, const double* weights, const double* bias, const size_t* dims, const size_t num_out_neurons, const size_t num_in_neurons)
{
    double* tmp_weights;
    cudaMalloc((void**) &tmp_weights, num_out_neurons*num_in_neurons*sizeof(double));
    size_t* tmp_dims;
    cudaMalloc((void**) &tmp_dims   , num_out_neurons*num_in_neurons*sizeof(size_t));

    cudaMemcpy(tmp_weights, weights, num_out_neurons*num_in_neurons*sizeof(double), cudaMemcpyHostToDevice);
    cudaMemcpy(tmp_dims   , dims   , num_out_neurons*num_in_neurons*sizeof(size_t), cudaMemcpyHostToDevice);

    double* tmp_bias;
    cudaMalloc((void**) &tmp_bias, num_out_neurons*sizeof(double));
    cudaMemcpy(tmp_bias, bias, num_out_neurons*sizeof(double), cudaMemcpyHostToDevice);

    device_layer_create_sparse_exprs<<<num_out_neurons, 1>>>(expr_array, tmp_weights, tmp_bias, tmp_dims, num_out_neurons, num_in_neurons);

    cudaFree(tmp_weights);
    cudaFree(tmp_dims);
    cudaFree(tmp_bias);
}


elina_abstract0_t* fppoly_from_network_input_poly(elina_manager_t* man, const size_t intdim, const size_t realdim, const double* inf_array,
                                                  const double* sup_array, const double* lexpr_weights, const double* lexpr_cst, const size_t* lexpr_dim,
                                                  const double* uexpr_weights, const double* uexpr_cst, const size_t* uexpr_dim, const size_t expr_size)
{
    fppoly_t* res = (fppoly_t*) malloc(sizeof(fppoly_t));
    fppoly_from_network_input_box(res, intdim, realdim, inf_array, sup_array);

    size_t num_pixels = intdim + realdim;

    cudaMalloc((void**) &res->input_lexpr, num_pixels*sizeof(expr_t*));
    cudaMalloc((void**) &res->input_uexpr, num_pixels*sizeof(expr_t*));

    layer_create_sparse_exprs(res->input_lexpr, lexpr_weights, lexpr_cst, lexpr_dim, num_pixels, expr_size);
    layer_create_sparse_exprs(res->input_uexpr, uexpr_weights, uexpr_cst, uexpr_dim, num_pixels, expr_size);

    return abstract0_of_fppoly(man, res);
}
*/


void fppoly_add_new_layer(fppoly_t* const fp, const size_t num_out_neurons, const size_t num_in_neurons, const layertype_t type, const activation_type_t activation)
{
    const size_t numlayers = fp->numlayers;


        exprA->inf_coeff[j] = exprA->inf_coeff[j] + exprB->inf_coeff[j] + (maxA + maxB)*ulp;
        exprA->sup_coeff[j] = exprA->sup_coeff[j] + exprB->sup_coeff[j] + (maxA + maxB)*ulp;
    }
}

