diff --git a/Makefile b/Makefile
index 437c3ab76d99ee6efba5bbd858e18e50bb3485a9..496a372fc7c7d4f3297631fcf40efe7255eb55d3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CC=gcc -Wall -Wextra
+CC=gcc -Wall -Wextra -lm
 opti: opti.o
 	$(CC) $^ -o $@
 opti.o: opti.c
diff --git a/opti.c b/opti.c
index 3aa38ad1aa821eb70ace882cee00723eae0173e1..56400ecf91b1db2c7660bacea7d7d5e01b37db68 100644
--- a/opti.c
+++ b/opti.c
@@ -9,7 +9,7 @@ double RANDOMNESS = 0.01;
 Point* line(double a, double b){
     Point * points = (Point*)malloc(sizeof(Point)*LINE_POINTS);
     double x = 0.0;
-    for(int i=0;i<LINE_POINTS-1;i++){
+    for(int i=0;i<LINE_POINTS;i++){
         Point d;
         d.x = x;
         d.y = (a*x)+b;
@@ -20,6 +20,14 @@ Point* line(double a, double b){
     return points;
 }
 
+double popow(double v, double w){
+    double u=v;
+    for(int i=1;i<w;i++){
+        v*=u;
+    }
+    return v;
+}
+
 double double_random(double min, double max) 
 {
     double my_random;
@@ -29,9 +37,10 @@ double double_random(double min, double max)
     return my_random;
 }
 
-Point* cloud(Point* a_line){
+// version 1 du nuage, se doit d'appeler line indirectement
+Point* cloud1(Point* a_line){
     Point * my_cloud = (Point*)malloc(sizeof(Point)*CLOUD_POINTS);
-    for(int i=0;i<CLOUD_POINTS-1;i++){
+    for(int i=0;i<CLOUD_POINTS;i++){
         Point chosen_point = a_line[rand()%LINE_POINTS-1];
         double new_y = double_random(chosen_point.y-RANDOMNESS, chosen_point.y+RANDOMNESS);
         my_cloud[i].x=chosen_point.x;
@@ -41,10 +50,84 @@ Point* cloud(Point* a_line){
     return my_cloud;
 }
 
+// version 2 du nuage, peut être généré grâce aux a et b d'une droite
+// génère aléatoirement des points sur l'axe des x (qui ne sont donc pas espacés uniformément)
+Point* cloud2(double a, double b){
+    Point * my_cloud = (Point*)malloc(sizeof(Point)*CLOUD_POINTS);
+    for(int i=0;i<CLOUD_POINTS;i++){
+        Point chosen_point;
+        chosen_point.x = double_random(0,1);
+        for(int j=0;j<CLOUD_POINTS-1;j++){
+            while(chosen_point.x==my_cloud[j].x){
+                chosen_point.x = double_random(0,1);
+            }
+        }
+        double rj = double_random(-RANDOMNESS, RANDOMNESS);
+        chosen_point.y = (a*chosen_point.x)+b+rj;
+        my_cloud[i].x=chosen_point.x;
+        my_cloud[i].y=chosen_point.y;
+        printf("\nx = %f | y = %f\n", my_cloud[i].x,my_cloud[i].y);
+    }
+    return my_cloud;
+}
+
+// version 3 du nuage, plus simple, x espacés uniformément
+Point* cloud3(double a, double b){
+    Point * my_cloud = (Point*)malloc(sizeof(Point)*CLOUD_POINTS);
+    for(int i=0;i<CLOUD_POINTS;i++){
+        Point chosen_point;
+        chosen_point.x = double_random(0,1);
+        for(int j=0;j<CLOUD_POINTS-1;j++){
+            while(chosen_point.x==my_cloud[j].x){
+                chosen_point.x = double_random(0,1);
+            }
+        }
+        double rj = double_random(-RANDOMNESS, RANDOMNESS);
+        chosen_point.y = (a*chosen_point.x)+b+rj;
+        my_cloud[i].x=chosen_point.x;
+        my_cloud[i].y=chosen_point.y;
+        printf("\nx = %f | y = %f\n", my_cloud[i].x,my_cloud[i].y);
+    }
+    return my_cloud;
+}
+
+double* average(Point* my_cloud, int cloud_size){
+    double* avg = (double*)malloc(sizeof(double)*4);
+    double x_avg, y_avg, x2_avg, xy_avg;
+    for(int i=0; i<cloud_size-1;i++){
+        x_avg+=my_cloud[i].x;
+        y_avg+=my_cloud[i].y;
+        x2_avg+=popow((my_cloud[i].x),2);
+        xy_avg+=((my_cloud[i].x)*(my_cloud[i].y));
+    }
+    x_avg/=cloud_size; y_avg/=cloud_size; x2_avg/=cloud_size; xy_avg/=cloud_size;
+    avg[0]=x_avg; avg[1]=y_avg; avg[2]=x2_avg; avg[3]=xy_avg;
+    printf("x=%f - y=%f - x2=%f - xy=%f", avg[0],avg[1],avg[2],avg[3]);
+    return avg;
+}
+
+double* a_and_b(double* my_average){
+    double* a_n_b = (double*)malloc(sizeof(double)*2);
+    double x_avg = my_average[0];
+    double y_avg = my_average[1];
+    double x2_avg = my_average[2];
+    double xy_avg = my_average[3];
+    double a = (xy_avg-(x_avg*y_avg))/(x2_avg-popow(x_avg,2));
+    double b = y_avg-(a*x_avg);
+    a_n_b[0]=a;
+    a_n_b[1]=b;
+    return a_n_b;
+}
+
+double cost(){
+    return 0.0;
+}
+
 int main (void){
     srand ( time ( NULL));
-    Point* first_line = line(7.0, 5.5);
-    cloud(first_line);
+    //Point* first_line = line(7.0, 5.5);
+    Point* fluffy = cloud2(7.0, 5.5);
+    average(fluffy, CLOUD_POINTS);
     printf("\ndone\n");
     return 0;
 }
\ No newline at end of file
diff --git a/opti.h b/opti.h
index 63113bc2be8a3f5469f6e6fc544b01c810f802a7..4b3591b1e69d7ee202b3400b0060ae25ee49e020 100644
--- a/opti.h
+++ b/opti.h
@@ -1,9 +1,10 @@
 #ifndef _OPTI_H_
 #define _OPTI_H_
+#include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <time.h>
+#include <math.h>
 
 
 
@@ -17,5 +18,8 @@ struct Point
 Point* line(double a, double b);
 double double_random(double min, double max);
 Point* cloud(Point* a_line);
+Point* cloud2(double a, double b);
+double* average(Point* my_cloud, int cloud_size);
+double* a_and_b(double* my_average);
 
 #endif
\ No newline at end of file
diff --git a/plot-c-arrays-with-matplotlib-master.zip b/plot-c-arrays-with-matplotlib-master.zip
new file mode 100644
index 0000000000000000000000000000000000000000..41607ac48a1b108fed5f2673b8729d04ad2f21d1
Binary files /dev/null and b/plot-c-arrays-with-matplotlib-master.zip differ
diff --git a/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/.gitignore b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c3a8bb1202f6a611e54937fa23cb13e5384dfd7b
--- /dev/null
+++ b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/.gitignore
@@ -0,0 +1,5 @@
+*.vec
+.vscode
+__pycache__
+example
+*.o
\ No newline at end of file
diff --git a/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/main.c b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..e1a7fcfc15cfc8577fb5902837783f2c0fcc55ee
--- /dev/null
+++ b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/main.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <math.h>
+
+#include "vector.h"
+
+/** @brief 
+ *  An exemple of mathematical function 
+ *  in 1 dimension.
+ * 
+ *  @param x A double variable.
+ *  @return f(x) = 2.0*sin(x) - 3.0*cos(x)
+ */
+double my_function(double x)
+{
+    return 2.0 * sin(x) - 3.0 * cos(x);
+}
+
+int main()
+{
+    // Create a vector X = [0,1,2...99]
+    double_vector_t *X = iota(100);
+    // Create a vector Y = my_function(x)
+    double_vector_t *Y = apply_function(X, my_function);
+
+    // Export our vectors into files
+    export_vector("../X.vec", X);
+    export_vector("../Y.vec", Y);
+
+    // Free our vectors
+    destroy_vector(&Y);
+    destroy_vector(&X);
+}
\ No newline at end of file
diff --git a/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/makefile b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..8dda09a90410c6b8b2345f33904420af11b0b79f
--- /dev/null
+++ b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/makefile
@@ -0,0 +1,12 @@
+
+CC=gcc -std=gnu11 -Wall -Wextra -g -fsanitize=leak -fsanitize=undefined
+LIBS=-lm
+
+example: vector.o vector.h main.c
+	$(CC) $^ $(LIBS) -o $@ 
+
+vector.o: vector.c vector.h 
+	$(CC) -c $< -o $@
+
+clean:
+	rm -f *.vec *.o example
\ No newline at end of file
diff --git a/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/vector.c b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/vector.c
new file mode 100644
index 0000000000000000000000000000000000000000..ff4428b90ba4387cf2dac65dd4e0e8a48db664ac
--- /dev/null
+++ b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/vector.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "vector.h"
+
+/** @brief 
+ *  Compute the endianness used by
+ *  the architecture.
+ *
+ *  @return 1 if little-endian, 0 if big-endian
+ */
+uint8_t get_endianness()
+{
+    uint32_t endianness = 0x01020304;
+    // Return the endianness by accessing the first byte in memory
+    // which should be 1 if big-endian and 4 if little-endian
+    return *((uint8_t *)(&endianness)) == 4;
+}
+
+/** @brief 
+ *  Create a vector of a given dimension.
+ * 
+ *  @param N The number of dimensions.
+ *  @return A dynamically allocated vector
+ */
+double_vector_t *init_vector(uint32_t N)
+{
+    double_vector_t *vec = malloc(sizeof(double_vector_t));
+    vec->components = malloc(N * sizeof(double));
+    vec->N = N;
+    if (vec == NULL)
+    {
+        perror("Can't allocate memory");
+        exit(EXIT_FAILURE);
+    }
+    return vec;
+}
+/** @brief 
+ *  Create a vector of a given dimension,
+ *  with values from 0 to N excluded.
+ * 
+ *  @param N The number of dimensions.
+ *  @return A dynamically allocated vector : [0,1..N-1]
+ */
+double_vector_t *iota(uint32_t N)
+{
+    double_vector_t *vec = init_vector(N);
+    for (uint32_t i = 0; i < N; i++)
+    {
+        vec->components[i] = i;
+    }
+    return vec;
+}
+/** @brief 
+ *  Apply a 1d function element-wise
+ *  to a given vector, and return the
+ *  result in a new vector.
+ * 
+ *  @param vec The argument vector
+ *  @param f   The 1d function to apply
+ *  @return A dynamically allocated vector : f(X)
+ */
+double_vector_t *apply_function(double_vector_t *vec, double_function_t f)
+{
+    double_vector_t *res = init_vector(vec->N);
+    for (uint32_t i = 0; i < vec->N; i++)
+    {
+        res->components[i] = f(vec->components[i]);
+    }
+    return res;
+}
+/** @brief 
+ *  Export a vector into a file.
+ * 
+ *  @param filename The name of the output file
+ *  @param vec      The vector to export
+ */
+void export_vector(const char *filename, double_vector_t *vec)
+{
+    FILE *output = fopen(filename, "w");
+
+    vector_metadata_t metadata;
+    metadata.endianness = get_endianness();
+    metadata.size_of_a_component = sizeof(double);
+    metadata.number_of_component = vec->N;
+
+    fwrite(&metadata, sizeof(vector_metadata_t), 1, output);
+    fwrite(vec->components,
+           metadata.size_of_a_component,
+           metadata.number_of_component,
+           output);
+
+    fclose(output);
+}
+/** @brief 
+ *  Free a vector.
+ * 
+ *  @param vec A double pointer on a vector
+ */
+void destroy_vector(double_vector_t **vec)
+{
+    free((*vec)->components);
+    free(*vec);
+    *vec = NULL;
+}
\ No newline at end of file
diff --git a/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/vector.h b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/vector.h
new file mode 100644
index 0000000000000000000000000000000000000000..ceb461c4dcc10ce7d46b4a951f5a7c39454d8e0c
--- /dev/null
+++ b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/C/vector.h
@@ -0,0 +1,62 @@
+#include <stdint.h>
+
+typedef struct double_vector
+{
+    uint32_t N; // The dimmension of the vector
+    double *components;
+} double_vector_t;
+// Function pointer, example : double f(double x);
+typedef double (*double_function_t)(double);
+
+/*
+* The attribute "packed" tells the compiler,
+* that the struct should be stored in memory 
+* without padding. It's highly recommended,
+* if we want to serialize the structure.
+* (for example to store it in a file)
+*/
+typedef struct vector_metadata
+{
+    uint8_t endianness;          // 1 = little, 0 = big
+    uint8_t size_of_a_component; // in bytes
+    uint32_t number_of_component;
+} __attribute__((packed)) vector_metadata_t;
+
+/** @brief 
+ *  Create a vector of a given dimension.
+ * 
+ *  @param N The number of dimensions.
+ *  @return A dynamically allocated vector
+ */
+double_vector_t *init_vector(uint32_t N);
+/** @brief 
+ *  Create a vector of a given dimension,
+ *  with values from 0 to N excluded.
+ * 
+ *  @param N The number of dimensions.
+ *  @return A dynamically allocated vector : [0,1..N-1]
+ */
+double_vector_t *iota(uint32_t N);
+/** @brief 
+ *  Apply a 1d function element-wise
+ *  to a given vector, and return the
+ *  result in a new vector.
+ * 
+ *  @param vec The argument vector
+ *  @param f   The 1d function to apply
+ *  @return A dynamically allocated vector : f(X)
+ */
+double_vector_t *apply_function(double_vector_t *vec, double_function_t f);
+/** @brief 
+ *  Export a vector into a file.
+ * 
+ *  @param filename The name of the output file
+ *  @param vec      The vector to export
+ */
+void export_vector(const char *filename, double_vector_t *vec);
+/** @brief 
+ *  Free a vector.
+ * 
+ *  @param vec A double pointer on a vector
+ */
+void destroy_vector(double_vector_t **vec);
\ No newline at end of file
diff --git a/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/Python/example.py b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/Python/example.py
new file mode 100644
index 0000000000000000000000000000000000000000..e40a55698493ef70de538cc86c46d2f79af95e43
--- /dev/null
+++ b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/Python/example.py
@@ -0,0 +1,19 @@
+from matplotlib import pyplot as plt
+from load_vec import load_vector
+
+X = load_vector("../X.vec")
+Y = load_vector("../Y.vec")
+
+type_of_data = 'curve'
+
+if type_of_data == 'curve':
+    plt.plot(X, Y, label="my curve")
+else:
+    plt.scatter(X, Y, marker='x', label="my points")
+
+plt.title("My data")
+plt.xlabel("X")
+plt.ylabel("Y")
+plt.legend(loc="upper right")
+
+plt.show()
diff --git a/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/Python/load_vec.py b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/Python/load_vec.py
new file mode 100644
index 0000000000000000000000000000000000000000..17880a18b4fccf86b61cad3cd8e90b1aead07926
--- /dev/null
+++ b/plot-c-arrays-with-matplotlib-master/plot-c-arrays-with-matplotlib-master/Python/load_vec.py
@@ -0,0 +1,50 @@
+import numpy as np
+from typing import Tuple
+METADATA_SIZE = 6
+
+
+def _parse_metadata(metadata: bytes) -> Tuple[type, int]:
+    """
+    Parse the metadata for a vec file.
+
+    Parameters:
+    metadata (bytes): The metadata bytes
+
+    Returns:
+    (type, int): The type and the number of component of the vector
+    """
+
+    little_endian = bool(metadata[0])
+    endianness = 'little' if little_endian else 'big'
+
+    size_of_components = int(metadata[1])
+    # For now we only consider two types
+    datatype = np.float64 if size_of_components == 8 else np.float
+
+    # Recover our 32 bit integer specifying the endianness
+    nb_components = int.from_bytes(metadata[2:], endianness)
+
+    return datatype, nb_components
+
+
+def load_vector(filename: str) -> np.ndarray:
+    """
+    Load a vector from a file.
+
+    Parameters:
+    filename (str): The name of the file containing the vector
+
+    Returns:
+    np.ndarray: The vector
+
+    """
+    file = open(filename, 'rb')
+    # Read our metadata struct
+    metadata = file.read(METADATA_SIZE)
+
+    datatype, nb_components = _parse_metadata(metadata)
+
+    array = np.fromfile(file, dtype=datatype, count=nb_components)
+
+    file.close()
+    return array