 
 void layer_compute_bounds_from_exprs(neuron_t** neurons, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr, const size_t size)
 {
+    // allocate
+    expr_t** lexpr_array = (expr_t**) malloc(size*sizeof(expr_t*));
+    expr_t** uexpr_array = (expr_t**) malloc(size*sizeof(expr_t*));
+
     for(size_t i = 0; i < size; i++)
     {
-        neuron_t* neuron = neurons[i];
-
-        if((input_lexpr != nullptr) && (input_uexpr != nullptr))
-        {
-            replace_input_poly_cons_in_lexpr(&(neuron->expr), input_inf, input_sup, input_lexpr, input_uexpr);
-            replace_input_poly_cons_in_uexpr(&(neuron->expr), input_inf, input_sup, input_lexpr, input_uexpr);
-        }
-
-        compute_lb_from_expr(&(neuron->lb), &(neuron->expr), input_inf, input_sup, input_lexpr, input_uexpr);
-        compute_ub_from_expr(&(neuron->ub), &(neuron->expr), input_inf, input_sup, input_lexpr, input_uexpr);
-    }
+        lexpr_array[i] = copy_expr(neurons[i]->expr);
+        uexpr_array[i] = copy_expr(neurons[i]->expr);
+    }
+
+    double* lb_array = (double*) malloc(size*sizeof(double));
+    double* ub_array = (double*) malloc(size*sizeof(double));
+
+    // compute
+    if((input_lexpr != nullptr) && (input_uexpr != nullptr))
+    {
+        replace_input_poly_cons_in_lexpr(lexpr_array, input_inf, input_sup, input_lexpr, input_uexpr, size);
+        replace_input_poly_cons_in_uexpr(uexpr_array, input_inf, input_sup, input_lexpr, input_uexpr, size);
+    }
+
+    compute_lb_from_expr(lb_array, lexpr_array, input_inf, input_sup, input_lexpr, input_uexpr, size);
+    compute_ub_from_expr(ub_array, uexpr_array, input_inf, input_sup, input_lexpr, input_uexpr, size);
+
+    for(size_t i = 0; i < size; i++)
+    {
+        neurons[i]->lb = lb_array[i];
+        neurons[i]->ub = ub_array[i];
+    }
+
+    // free
+    for(size_t i = 0; i < size; i++)
+    {
+        free_expr(lexpr_array[i]);
+        free_expr(uexpr_array[i]);
+    }
+
+    free(lexpr_array);
+    free(uexpr_array);
+
+    free(lb_array);
+    free(ub_array);
 }
 
 

}



void update_state_using_previous_layers(elina_manager_t* man, fppoly_t* fp, const size_t layerno)
{
    fppoly_internal_t* pr = fppoly_init_from_manager(man, ELINA_FUNID_ASSIGN_LINEXPR_ARRAY);

        {
            if(fp->layers[k]->activation == RELU)
            {
                lexpr_replace_relu_bounds(lexpr_array, aux_neurons, num_out_neurons);
                uexpr_replace_relu_bounds(uexpr_array, aux_neurons, num_out_neurons);
            }

            expr_from_previous_layer(lexpr_array, aux_neurons, num_out_neurons);
            expr_from_previous_layer(uexpr_array, aux_neurons, num_out_neurons);
        }
        else
        {
            lexpr_replace_maxpool_bounds(lexpr_array, aux_neurons, num_out_neurons);
            uexpr_replace_maxpool_bounds(uexpr_array, aux_neurons, num_out_neurons);
        }
    }

    if((fp->input_lexpr != nullptr) && (fp->input_uexpr != nullptr))
    {
        replace_input_poly_cons_in_lexpr(lexpr_array, fp->input_inf, fp->input_sup, fp->input_lexpr, fp->input_uexpr, num_out_neurons);
        replace_input_poly_cons_in_uexpr(uexpr_array, fp->input_inf, fp->input_sup, fp->input_lexpr, fp->input_uexpr, num_out_neurons);
    }

    double* lb_array = (double*) malloc(num_out_neurons*sizeof(double));
    double* ub_array = (double*) malloc(num_out_neurons*sizeof(double));

    compute_lb_from_expr(lb_array, lexpr_array, fp->input_inf, fp->input_sup, fp->input_lexpr, fp->input_uexpr, num_out_neurons);
    compute_ub_from_expr(ub_array, uexpr_array, fp->input_inf, fp->input_sup, fp->input_lexpr, fp->input_uexpr, num_out_neurons);

    for(size_t i = 0; i < num_out_neurons; i++)
    {
        out_neurons[i]->lb = lb_array[i];
        out_neurons[i]->ub = ub_array[i];
    }

    free(lb_array);
    free(ub_array);

    if(fp->out != nullptr)
    {
        //TODO: The (l/u)expr_array assigned here is not correct. The contents were changed in the replace_input_poly_cons_in_lexpr, but they should not have been changed there. Need to create another temporary array for the results of replace_input_poly_cons_in_lexpr. Maybe this is a feature, not a bug? Seems like this is exactly what the method get_expr_for_output_neuron is doing!
        fp->out->lexpr = lexpr_array;
        fp->out->uexpr = uexpr_array;
    }
    else
    {
        for(size_t i = 0; i < num_out_neurons; i++)
        {
            free_expr(lexpr_array[i]);
            free_expr(uexpr_array[i]);
        }

        free(lexpr_array);
        free(uexpr_array);
    }
}

