Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • david/sda
  • naima/sda
  • tomeh/sda
3 results
Show changes
Commits on Source (43)
*/*~
Python/__pycache__/*
Sujets/*
CPP/src/*
CPP/include/*
Corrections/*
Java/*.class
Java/.idea
plots/plot_files/*
plots/png/*
\ No newline at end of file
image: alpine
stages:
- test
sda:test:
script:
- echo "Exercice 1"
- ls -lF AUTHORS.md
- echo "Exercice 2"
- ls -lF plots/*_alpha_2.pdf
- echo "Exercice 3"
- ls -lF plots/my_plot_result
- grep my_plot_result launch_analysis.sh
- ALPHA=$(head -n 1 AUTHORS.md)
- echo "ALPHA ${ALPHA}"
- ls -lF plots/*_alpha_${ALPHA}.pdf
- echo "Exercice 4"
- ls -lF RAPPORT.md
......@@ -7,7 +7,7 @@ analyzer_t * analyzer_create(){
analyzer_t * res = (analyzer_t *) malloc( sizeof(analyzer_t) );
res->capacity = 4;
res->cost = (double *) malloc( sizeof(double) * res->capacity );
res->cumulative_cost = (double *) malloc( sizeof(double) * res->capacity );
res->cumulative_cost = (long double *) malloc( sizeof(long double) * res->capacity );
res->cumulative_square = 0.;
res->size = 0;
return res;
......@@ -26,7 +26,7 @@ void analyzer_append(analyzer_t * a, double x){
if( a->size >= (a->capacity * 3)/4 ){
a->capacity *= 2;
a->cost = (double *) realloc(a->cost, sizeof(double) * a->capacity*2);
a->cumulative_cost = (double *) realloc(a->cumulative_cost, sizeof(double) * a->capacity*2);
a->cumulative_cost = (long double *) realloc(a->cumulative_cost, sizeof(long double) * a->capacity*2);
}
a->cost[a->size] = x;
a->cumulative_cost[a->size] = (a->size) ? a->cumulative_cost[a->size-1]+x : x;
......@@ -35,25 +35,25 @@ void analyzer_append(analyzer_t * a, double x){
}
}
double get_total_cost(analyzer_t * a){
long double get_total_cost(analyzer_t * a){
return (a->size) ? a->cumulative_cost[a->size-1] : -1;
}
double get_amortized_cost(analyzer_t * a, size_t pos){
long double get_amortized_cost(analyzer_t * a, size_t pos){
if(pos >= 0 && pos < a->size)
return (pos)? a->cumulative_cost[pos]/pos : a->cumulative_cost[pos];
return -1;
}
double get_average_cost(analyzer_t * a){
long double get_average_cost(analyzer_t * a){
if(a->size)
return a->cumulative_cost[a->size - 1]/a->size;
return -1;
}
double get_variance(analyzer_t * a){
double mean, mean_square;
long double get_variance(analyzer_t * a){
long double mean, mean_square;
if(a->size){
mean = get_average_cost(a);
mean_square = mean * mean;
......@@ -62,7 +62,7 @@ double get_variance(analyzer_t * a){
return -1;
}
double get_standard_deviation(analyzer_t * a){
long double get_standard_deviation(analyzer_t * a){
if(a->size)
return sqrt(get_variance(a));
return -1;
......@@ -73,7 +73,7 @@ void save_values(analyzer_t * a, char * path){
int i;
if( (f = fopen(path, "w")) != NULL ){
for (i = 0; i < a->size; ++i){
fprintf(f,"%d %lf %lf\n", i, a->cost[i], get_amortized_cost(a, i));
fprintf(f,"%d %lf %Lf\n", i, a->cost[i], get_amortized_cost(a, i));
}
}else{
fprintf(stderr, "Could not save values in file %s", path);
......@@ -83,6 +83,6 @@ void save_values(analyzer_t * a, char * path){
void plot_values(analyzer_t * a){
int i;
for (i = 0; i < a->size; ++i){
printf("%d %lf %lf\n", i, a->cost[i], get_amortized_cost(a, i));
printf("%d %lf %Lf\n", i, a->cost[i], get_amortized_cost(a, i));
}
}
......@@ -12,9 +12,9 @@ typedef struct analyzer_s{
double * cost;
// Coût cumulatif. La case i contient la somme des coûts des i premières opérations.
// Permet de calculer le coût amorti d'une opération.
double * cumulative_cost;
long double * cumulative_cost;
// Carré du coût cumulatif. Sert à calculer la variance. On ne garde que la dernière valeur.
double cumulative_square;
long double cumulative_square;
// Capacité de stockage des tableaux
size_t capacity;
// Nombre d'éléments dans chaque tableaux.
......@@ -51,7 +51,7 @@ void analyzer_append(analyzer_t * a, double cost);
@param a est une analyse.
@returns la somme des coûts enregistrés dans cette analyse.
*/
double get_total_cost(analyzer_t * a);
long double get_total_cost(analyzer_t * a);
/**
Renvoie le coût amorti d'une opération.
......@@ -60,7 +60,7 @@ double get_total_cost(analyzer_t * a);
@param pos est l'indice de l'opération pour laquelle on veut connaître le coût amorti.
@returns le coût amorti d'une opération.
*/
double get_amortized_cost(analyzer_t * a, size_t pos);
long double get_amortized_cost(analyzer_t * a, size_t pos);
/**
Renvoie la moyenne des coûts de toutes les opérations enregistrées dans l'analyse.
......@@ -68,7 +68,7 @@ double get_amortized_cost(analyzer_t * a, size_t pos);
@param a est une analyse.
@returns la moyenne des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_average_cost(analyzer_t * a);
long double get_average_cost(analyzer_t * a);
/**
Renvoie la variance des coûts de toutes les opérations enregistrées dans l'analyse.
......@@ -76,7 +76,7 @@ double get_average_cost(analyzer_t * a);
@param a est une analyse.
@returns la variance des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_variance(analyzer_t * a);
long double get_variance(analyzer_t * a);
/**
Renvoie l'écart-type des coûts de toutes les opérations enregistrées dans l'analyse.
......@@ -84,7 +84,7 @@ double get_variance(analyzer_t * a);
@param a est une analyse.
@returns l'écart-type des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_standard_deviation(analyzer_t * a);
long double get_standard_deviation(analyzer_t * a);
/**
Sauvegarde la liste des coûts et des coûts amortis dans un fichier.
......
......@@ -60,7 +60,7 @@ size_t arraylist_capacity(arraylist_t * a){
}
char arraylist_do_we_need_to_enlarge_capacity(arraylist_t * a){
return ( a->size >= (a->capacity * 3)/4 )? TRUE: FALSE;
return a->size == a->capacity ? TRUE: FALSE;
}
void arraylist_enlarge_capacity(arraylist_t * a){
......
......@@ -15,15 +15,18 @@ int main(int argc, char ** argv){
analyzer_t * copy_analysis = analyzer_create();
// Analyse de l'espace mémoire inutilisé.
analyzer_t * memory_analysis = analyzer_create();
// Mesure de la durée d'une opération.
struct timespec before, after;
clockid_t clk_id = CLOCK_REALTIME;
// utilisé comme booléen pour savoir si une allocation a été effectuée.
char memory_allocation;
for(i = 0; i < 1000000 ; i++){
// Ajout d'un élément et mesure du temps pris par l'opération.
timespec_get(&before, TIME_UTC);
clock_gettime(clk_id, &before);
memory_allocation = arraylist_append(a, i);
timespec_get(&after, TIME_UTC);
clock_gettime(clk_id, &after);
// Enregistrement du temps pris par l'opération
analyzer_append(time_analysis, after.tv_nsec - before.tv_nsec);
......@@ -35,15 +38,15 @@ int main(int argc, char ** argv){
}
// Affichage de quelques statistiques sur l'expérience.
fprintf(stderr, "Total cost: %lf\n", get_total_cost(time_analysis));
fprintf(stderr, "Average cost: %lf\n", get_average_cost(time_analysis));
fprintf(stderr, "Variance: %lf\n", get_variance(time_analysis));
fprintf(stderr, "Standard deviation: %lf\n", get_standard_deviation(time_analysis));
fprintf(stderr, "Total cost: %Lf\n", get_total_cost(time_analysis));
fprintf(stderr, "Average cost: %Lf\n", get_average_cost(time_analysis));
fprintf(stderr, "Variance: %Lf\n", get_variance(time_analysis));
fprintf(stderr, "Standard deviation: %Lf\n", get_standard_deviation(time_analysis));
// Sauvegarde les données de l'expérience.
save_values(time_analysis, "../dynamic_array_time_c.plot");
save_values(copy_analysis, "../dynamic_array_copy_c.plot");
save_values(memory_analysis, "../dynamic_array_memory_c.plot");
save_values(time_analysis, "../plots/dynamic_array_time_c_alpha_2.plot");
save_values(copy_analysis, "../plots/dynamic_array_copy_c_alpha_2.plot");
save_values(memory_analysis, "../plots/dynamic_array_memory_c_alpha_2.plot");
// Nettoyage de la mémoire avant la sortie du programme
arraylist_destroy(a);
......
......@@ -10,3 +10,7 @@ clean:
rm -rf *.o
rm -rf *~
rm -rf arraylist_analysis
%.o: %.cpp
$(CC) $(CPPFLAGS) -c $< -o $@
......@@ -8,14 +8,14 @@ void Analyzer::append(const double & x){
cumulative_square += x*x;
}
double Analyzer::get_average_cost(){
long double Analyzer::get_average_cost(){
if(cumulative_cost.empty())
throw std::runtime_error("List is empty");
return cumulative_cost.back()/cumulative_cost.size();
}
double Analyzer::get_variance(){
double mean, mean_square;
long double Analyzer::get_variance(){
long double mean, mean_square;
mean = get_average_cost();
mean_square = mean * mean;
return cumulative_square - mean_square;
......
......@@ -31,7 +31,7 @@ public:
Complexité en temps/espace, meilleur cas : O(1)
@returns la somme des coûts enregistrés dans cette analyse.
*/
double get_total_cost(){
long double get_total_cost(){
return cumulative_cost.back();
}
......@@ -41,7 +41,7 @@ public:
@param pos est l'indice de l'opération pour laquelle on veut connaître le coût amorti.
@returns le coût amorti d'une opération.
*/
double get_amortized_cost(size_t pos){
long double get_amortized_cost(size_t pos){
return (pos)? cumulative_cost.at(pos)/pos : cumulative_cost.at(pos);
}
......@@ -50,21 +50,21 @@ public:
Complexité en temps/espace, meilleur cas : O(1)
@returns la moyenne des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_average_cost();
long double get_average_cost();
/**
Renvoie la variance des coûts de toutes les opérations enregistrées dans l'analyse.
Complexité en temps/espace, meilleur cas : O(1)
@returns la variance des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_variance();
long double get_variance();
/**
Renvoie l'écart-type des coûts de toutes les opérations enregistrées dans l'analyse.
Complexité en temps/espace, meilleur cas : O(1)
@returns l'écart-type des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_standard_deviation(){
long double get_standard_deviation(){
return std::sqrt(get_variance());
}
......@@ -85,9 +85,9 @@ private:
std::vector<double> cost;
// Coût cumulatif. La case i contient la somme des coûts des i premières opérations.
// Permet de calculer le coût amorti d'une opération.
std::vector<double> cumulative_cost;
std::vector<long double> cumulative_cost;
// Carré du coût cumulatif. Sert à calculer la variance. On ne garde que la dernière valeur.
double cumulative_square;
long double cumulative_square;
};
......
......@@ -48,8 +48,8 @@ public:
bool memory_reduction = false;
if(!data.empty()){
if( do_we_need_to_reduce_capacity() ){
memory_reduction = true;
reduce_capacity();
memory_reduction = true;
reduce_capacity();
}
data.pop_back();
}
......@@ -62,7 +62,7 @@ public:
@param pos est la l'indice de la case on l'utilisateur veut connaître la valeur.
@returns la valeur située à la position donnée par l'utilisateur.
*/
P get(const int & pos){
P get(const int pos){
return data[pos];
}
......@@ -89,7 +89,7 @@ private:
@returns true si le tableau doit être agrandi, false sinon.
*/
bool do_we_need_to_enlarge_capacity(){
return data.size() >= (data.capacity() * 3)/4;
return data.size() == data.capacity();
}
/**
......
#include<iostream>
#include<time.h>
#include <chrono>
#include<cstdlib>
#include "arraylist.hpp"
#include "analyzer.hpp"
using namespace std::chrono;
int main(int argc, char ** argv){
int i;
// Tableau dynamique.
......@@ -15,18 +18,19 @@ int main(int argc, char ** argv){
Analyzer copy_analysis;
// Analyse de l'espace mémoire inutilisé.
Analyzer memory_analysis;
struct timespec before, after;
high_resolution_clock::time_point before, after;
// Booléen permettant de savoir si une allocation a été effectuée.
bool memory_allocation;
for(i = 0; i < 1000000 ; i++){
// Ajout d'un élément et mesure du temps pris par l'opération.
timespec_get(&before, TIME_UTC);
before = high_resolution_clock::now();
memory_allocation = a.append(i);
timespec_get(&after, TIME_UTC);
after = high_resolution_clock::now();
// Enregistrement du temps pris par l'opération
time_analysis.append(after.tv_nsec - before.tv_nsec);
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(after - before);
time_analysis.append(static_cast<double>(duration.count()));
// Enregistrement du nombre de copies efféctuées par l'opération.
// S'il y a eu réallocation de mémoire, il a fallu recopier tout le tableau.
copy_analysis.append( (memory_allocation)? i:1 );
......@@ -41,9 +45,10 @@ int main(int argc, char ** argv){
std::cerr<<"Standard deviation :"<<time_analysis.get_standard_deviation()<<std::endl;
// Sauvegarde les données de l'expérience.
time_analysis.save_values("../dynamic_array_time_cpp.plot");
copy_analysis.save_values("../dynamic_array_copy_cpp.plot");
memory_analysis.save_values("../dynamic_array_memory_cpp.plot");
time_analysis.save_values("../plots/dynamic_array_time_cpp_alpha_2.plot");
copy_analysis.save_values("../plots/dynamic_array_copy_cpp_alpha_2.plot");
memory_analysis.save_values("../plots/dynamic_array_memory_cpp_alpha_2.plot");
return 0;
}
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
/**
......@@ -13,8 +15,8 @@ public class Analyzer {
*/
public Analyzer() {
cost = new ArrayList<Double>();
cumulative_cost = new ArrayList<Double>();
cumulative_square = 0.;
cumulative_cost = new ArrayList<BigDecimal>();
cumulative_square = new BigDecimal(0.);
}
/**
......@@ -25,9 +27,11 @@ public class Analyzer {
@param x est la valeur que l'on souhaite ajouter à l'analyse.
*/
void append(double x){
BigDecimal x_big = new BigDecimal(x);
cost.add(x);
cumulative_cost.add( (!cumulative_cost.isEmpty()) ? cumulative_cost.get(cumulative_cost.size()-1)+x : x);
cumulative_square += x*x;
cumulative_cost.add( (!cumulative_cost.isEmpty()) ? cumulative_cost.get(cumulative_cost.size()-1).add(x_big) : x_big);
BigDecimal x_square = x_big.multiply(x_big);
cumulative_square = cumulative_square.add(x_square);
}
/**
......@@ -35,7 +39,7 @@ public class Analyzer {
Complexité en temps/espace, meilleur cas : O(1)
@returns la somme des coûts enregistrés dans cette analyse.
*/
double get_total_cost(){
BigDecimal get_total_cost(){
return cumulative_cost.get(cumulative_cost.size()-1);
}
......@@ -45,8 +49,8 @@ public class Analyzer {
@param pos est l'indice de l'opération pour laquelle on veut connaître le coût amorti.
@returns le coût amorti d'une opération.
*/
double get_amortized_cost(int pos){
return (pos > 0)? cumulative_cost.get(pos)/pos : cumulative_cost.get(pos);
BigDecimal get_amortized_cost(int pos){
return (pos > 0)? cumulative_cost.get(pos).divide(new BigDecimal(pos), RoundingMode.HALF_UP) : cumulative_cost.get(pos);
}
/**
......@@ -54,10 +58,10 @@ public class Analyzer {
Complexité en temps/espace, meilleur cas : O(1)
@returns la moyenne des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_average_cost(){
BigDecimal get_average_cost(){
if(cumulative_cost.isEmpty())
throw new RuntimeException("List is empty");
return cumulative_cost.get(cumulative_cost.size()-1)/cumulative_cost.size();
return cumulative_cost.get(cumulative_cost.size()-1).divide(new BigDecimal(cumulative_cost.size()));
}
/**
......@@ -65,11 +69,13 @@ public class Analyzer {
Complexité en temps/espace, meilleur cas : O(1)
@returns la variance des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_variance(){
double mean, mean_square;
BigDecimal get_variance(){
BigDecimal mean, mean_square;
mean = get_average_cost();
mean_square = mean * mean;
return cumulative_square - mean_square;
mean_square = mean.multiply(mean);
if(cumulative_square.compareTo(mean_square) < 0)
throw new RuntimeException("Error: mean of squares is less than square of mean: "+mean+" "+cumulative_square);
return cumulative_square.subtract(mean_square);
}
/**
......@@ -77,8 +83,8 @@ public class Analyzer {
Complexité en temps/espace, meilleur cas : O(1)
@returns l'écart-type des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_standard_deviation(){
return Math.sqrt(get_variance());
BigDecimal get_standard_deviation(){
return new BigDecimal(Math.sqrt(get_variance().doubleValue()));
}
/**
......@@ -124,9 +130,9 @@ public class Analyzer {
private ArrayList<Double> cost;
// Coût cumulatif. La case i contient la somme des coûts des i premières opérations.
// Permet de calculer le coût amorti d'une opération.
private ArrayList<Double> cumulative_cost;
private ArrayList<BigDecimal> cumulative_cost;
// Carré du coût cumulatif. Sert à calculer la variance. On ne garde que la dernière valeur.
private double cumulative_square;
private BigDecimal cumulative_square;
}
import java.util.ArrayList;
import java.util.Arrays;
/**
Cette classe est un proxy pour les ArrayList, c'est à dire les tableaux dynamiques en Java.
On utilise cette classe afin d'avoir le contrôle sur la gestion de la mémoire.
*/
public class ArrayListProxy<T> {
public class ArrayList<T> {
/**
Constructeur de la classe des tableaux dynamiques.
Complexité en temps/espace, pire et meilleur cas : O(1)
*/
public ArrayListProxy() {
public ArrayList() {
this.capacity = 4;
this.data = new ArrayList<T>(this.capacity);
this.data = new Object[this.capacity];
}
/**
......@@ -24,12 +24,11 @@ public class ArrayListProxy<T> {
@returns true si le tableau a été agrandit, false sinon
*/
boolean append(T x){
boolean memory_allocation = false;
if( do_we_need_to_enlarge_capacity() ){
memory_allocation = true;
enlarge_capacity();
boolean memory_allocation = do_we_need_to_enlarge_capacity();
if( memory_allocation ){
enlarge_capacity();
}
data.add(x);
data[size++] = x;
return memory_allocation;
}
......@@ -41,13 +40,11 @@ public class ArrayListProxy<T> {
@returns true si le tableau a été réduit, false sinon
*/
boolean pop_back(){
boolean memory_reduction = false;
if(!data.isEmpty()){
if( do_we_need_to_reduce_capacity() ){
memory_reduction = true;
reduce_capacity();
}
data.remove(data.size()-1);
boolean memory_reduction = do_we_need_to_reduce_capacity();
if(size != 0){
if( memory_reduction )
reduce_capacity();
size--;
}
return memory_reduction;
}
......@@ -58,8 +55,9 @@ public class ArrayListProxy<T> {
@param pos est la l'indice de la case on l'utilisateur veut connaître la valeur.
@returns la valeur située à la position donnée par l'utilisateur.
*/
@SuppressWarnings("unchecked")
T get(int pos){
return data.get(pos);
return (T)data[pos];
}
/**
......@@ -68,7 +66,7 @@ public class ArrayListProxy<T> {
@returns le nombre d'éléments stockés dans le tableau.
*/
int size(){
return data.size();
return size;
}
/**
......@@ -85,15 +83,15 @@ public class ArrayListProxy<T> {
@returns true si le tableau doit être agrandi, false sinon.
*/
private boolean do_we_need_to_enlarge_capacity() {
return data.size() >= (capacity * 3)/4;
return size == capacity;
}
/**
Cette fonction augmente la capacité du tableau.
*/
private void enlarge_capacity(){
capacity *= 2;
data.ensureCapacity( capacity );
capacity *= 2;
data = java.util.Arrays.copyOf(data, capacity);
}
/**
......@@ -101,19 +99,21 @@ public class ArrayListProxy<T> {
@returns true si le tableau doit être réduit, false sinon.
*/
private boolean do_we_need_to_reduce_capacity(){
return data.size() <= capacity/4 && data.size() >4;
return size <= capacity/4 && size >4;
}
/**
Cette fonction reduit la capacité du tableau.
*/
void reduce_capacity(){
capacity /= 2;
data.ensureCapacity( capacity );
}
// Tableau dynamique en Java. Sa capacité réelle est masquée, mais on peut avoir un contrôle dessus.
private ArrayList<T> data;
// Capacité réelle du tableau data.
private int capacity;
/**
Cette fonction reduit la capacité du tableau.
*/
void reduce_capacity(){
data = java.util.Arrays.copyOf(data, capacity/2);
capacity /= 2;
}
// Tableau dynamique en Java. Sa capacité réelle est masquée, mais on peut avoir un contrôle dessus.
private Object[] data;
// Capacité réelle du tableau data.
private int capacity;
// Nombre réel d'éléments dans le tableau.
private int size;
}
......@@ -5,13 +5,13 @@ public class Main {
public static void main(String[] args) {
int i, time_ind = 0, pop_ind = 0;
// Tableau dynamique.
ArrayListProxy<Integer> a = new ArrayListProxy<Integer>();
ArrayList<Integer> a = new ArrayList<Integer>();
// Analyse du temps pris par les opérations.
Analyzer time_analysis = new Analyzer();
// Analyse du nombre de copies faites par les opérations.
Analyzer copy_analysis = new Analyzer();
// Analyse de l'espace mémoire inutilisé.
Analyzer memory_analysis = new Analyzer();
// Analyse de l'espace mémoire inutilisé.
Analyzer memory_analysis = new Analyzer();
long before, after;
// Booléen permettant de savoir si une allocation a été effectuée.
boolean memory_allocation;
......@@ -28,8 +28,8 @@ public class Main {
// Enregistrement du nombre de copies efféctuées par l'opération.
// S'il y a eu réallocation de mémoire, il a fallu recopier tout le tableau.
copy_analysis.append( (memory_allocation == true)? i: 1);
// Enregistrement de l'espace mémoire non-utilisé.
memory_analysis.append( a.capacity() - a.size() );
// Enregistrement de l'espace mémoire non-utilisé.
memory_analysis.append( a.capacity() - a.size() );
}
// Affichage de quelques statistiques sur l'expérience.
......@@ -39,8 +39,8 @@ public class Main {
System.err.println("Standard deviation :"+time_analysis.get_standard_deviation());
// Sauvegarde les données de l'expérience: temps et nombre de copies effectuées par opération.
time_analysis.save_values("../dynamic_array_time_java.plot");
copy_analysis.save_values("../dynamic_array_copy_java.plot");
memory_analysis.save_values("../dynamic_array_memory_java.plot");
time_analysis.save_values("../plots/dynamic_array_time_java_alpha_2.plot");
copy_analysis.save_values("../plots/dynamic_array_copy_java_alpha_2.plot");
memory_analysis.save_values("../plots/dynamic_array_memory_java_alpha_2.plot");
}
}
# -- coding: utf-8 --
import math
# Classe utilisee pour faire des statistiques elementaires
......
# Cette classe est un simple proxy vers le type "list" de python
# Le langage ne permettant pas de manipuler l'espace memoire d'une "list",
# on se contente ici d'observer son comportement.
class ArrayListProxy:
# Constructeur de la classe ArraylistProxy
def __init__(self):
self.data = []
# Ajoute l'element x au tableau
# Complexite en temps/espace, pire cas : O(data.size)
# Complexite en temps/espace, meilleur cas : O(1)
# Complexite amortie : O(1)
def append(self, x):
self.data.append(x)
# Supprime le dernier element du tableau
def pop_back(self):
self.data.pop()
# Renvoie l'element situe a la position 'pos' dans le tableau
def get(self, pos):
return self.data[pos]
# Renvoie le nombre d'elements dans le tableau
def get_size(self):
return len(data)
# -- coding: utf-8 --
import time
import sys
from arraylist import ArrayListProxy
from analyzer import Analyzer
# Tableau dynamique.
a = ArrayListProxy()
a = []
# Analyse du temps pris par les operations.
time_analysis = Analyzer();
# Analyse de la mémoire gaspillée à un instant t.
memory_analysis = Analyzer();
# Analyse du nombre de copies effectuées à un instant t.
copy_analysis = Analyzer();
# Taille supposée de l'en-tête d'une list en Python
__list_header_size__ = 56
# Taille supposée d'une entrée dans une list en Python
__list_entry_size__ = 8
wasted_memory = sys.getsizeof(a)-__list_header_size__
for i in range(1000000):
previous_size = sys.getsizeof(a)
before = time.time()
a.append(i)
after = time.time()
# Enregistrement du temps pris par l'operation
time_analysis.append((after - before)*10**9)
# Enregistrement du nombre de copie effectuées par l'opération
# S'il n'y avait pas d'espace gaspillé à l'étape précédente,
# alors une réallocation a eu lieu à cette étape.
if sys.getsizeof(a) > previous_size:
copy_analysis.append(i+1)
else:
copy_analysis.append(1)
# Enregistrement de l'espace mémoire gaspillé à un instant donné
wasted_memory = sys.getsizeof(a)-__list_header_size__ - __list_entry_size__*(i+1)
memory_analysis.append(wasted_memory)
# Affichage de quelques statistiques sur l'experience.
sys.stderr.write("Total cost : " + str(time_analysis.get_total_cost())+"\n")
......@@ -23,4 +47,6 @@ sys.stderr.write("Variance :" + str(time_analysis.get_variance())+"\n")
sys.stderr.write("Standard deviation :" + str(time_analysis.get_standard_deviation())+"\n")
# Sauvegarde les donnees de l'experience.
time_analysis.save_values("../dynamic_array_time_python.plot")
time_analysis.save_values("../plots/dynamic_array_time_python_alpha_2.plot")
memory_analysis.save_values("../plots/dynamic_array_memory_python_alpha_2.plot")
copy_analysis.save_values("../plots/dynamic_array_copy_python_alpha_2.plot")
# Compilation et exécution en C:
# Sujet de TP 1: Gitlab, Benchmarks et tableaux dynamiques
cd C/
## Règles pour ce semestre
make
Vous travaillerez en binôme durant les TPs. Il ne sera pas possible de changer
de binôme en cours de semestre.
./arraylist_analysis
Il est interdit de partager du code avec d'autres binômes ou de "s'en inspirer".
make clean
Toute ressemblance suspecte sera AUTOMATIQUEMENT considérée comme de la fraude
et sévèrement sanctionnée.
cd ..
Chaque semaine, un rendu vous sera demandé (vous aurez jusqu'au dimanche soir pour
rendre le TP si vous ne finissez pas à temps) via gitlab.
# Compilation et exécution en C++:
Vos travaux seront évalués une fois à mi-semestre et une fois à la fin du semestre.
cd CPP/
## Exercice 1: git
### Clonez le projet sda sur votre compte étudiant
make
Dans votre terminal, commencez par la configuration de votre utilisateur git:
git config --global user.name "NOM_PRENOM"
(le reste du TP peut se faire à partir de n'importe quelle session)
./arraylist_analysis
Placez vous dans le répertoire où vous souhaitez créer le dossier
make clean
`git clone https://depot.lipn.univ-paris13.fr/david/sda.git`
cd ..
`cd sda`
# Compilation et exécution en Java:
### Vérifiez que vous êtes dans la branche tp1
cd Java
`git branch`
javac *
Si n'êtes pas dans la branche tp1, tapez
java Main
`git checkout tp1`
cd ..
### Créez votre propre branche
# Exécution en Python
Le nom de votre branche est constitué de vos numéros d'étudiants séparés par un `_`
cd Python
`git checkout -b tp1_NUMERO1_NUMERO2`
python main.py
### Ajoutez un fichier `AUTHORS.md` à votre branche
cd ..
A la racine du projet, créez un fichier `AUTHORS.md` contenant 2 lignes avec vos noms, prénoms et numéros d'étudiants.
# Observation des résultats
### Dans le répertoire courant, lisez le contenu du fichier plot_result
Ajoutez ensuite ce fichier au projet
more plot_result
`git add AUTHORS.md`
### puis lancez gnuplot
`git commit -am "Ajout du fichier AUTHORS.md"`
gnuplot
### Poussez votre branche sur gitlab
`git push -u origin tp1_NUMERO1_NUMERO2`
### puis copiez le contenu du fichier plot_result dans gnuplot (3 lignes, une par une)
\ No newline at end of file
Login : `tp_sda`
Mot de passe : `structure`
### Vérifiez sur gitlab
Sur la page de gitlab:
- vérifiez que la branche a été poussée dans `Repository -> Branches`
- vérifiez que le pipeline a échoué (car vous n'avez pas encore fini le TP), dans `CI/CD -> Pipelines`
- cliquez sur `failed` pour voir le détail des tests effectués
## Exercice 2: Lancer les benchmarks
Vérifiez que le répertoire `plots` ne contient que le fichier `plot_result`.
Nous allons à présent tester différentes implémentations des tableaux dynamiques dans différents langages.
Lisez les fichiers `main` de chaque langage et vérifiez que la même expérience est bien effectuée à chaque fois.
Exécutez le script `SHELL` (le lire ne vous fera pas de mal non plus):
`sh launch_analysis.sh`
Une fois les calculs effectués, regardez les fichiers `pdf` obtenus dans le répertoire `plots`
Ajoutez tous les fichiers pdf obtenus à votre branche en utilisant les commandes
`git add plots/*.pdf`
`git commit -am "Première expérience"`
`git push`
## Exercice 3: A vous de jouer!
Dans le langage de votre choix (C, C++, JAVA, pas possible en Python), modifiez la fonction `enlarge_capacity`
afin de multiplier la capacité du tableaux par une autre constante `alpha` que 2 (Demandez à votre chargé de TP
de choisir une constante alpha pour votre binôme).
Ajouter une ligne au début du fichier AUTHORS.md contenant la valeur de alpha (et uniquement cette valeur).
Dans la fonction `main`, changez le nom de fichiers de sortie en ramplaçant `alpha_2` par `alpha_votre_valeur`
Dans le répertoire `plots`, faites une copie du fichier `plot_result`
`cp plot_result my_plot_result`
Modifiez le fichier `my_plot_result` pour ne fournir que des courbes dans le langage que vous avez choisi.
Modifiez également le nom des fichiers pdf en sortie afin qu'ils contiennent la bonne valeur de alpha.
Modifiez le fichier `launch_analysis.sh` afin qu'il exécute gnuplot à partir de `my_plot_result`
Relancez le script `launch_analysis.sh`
Ajoutez les résultats (fichiers pdf) à votre branche.
## Exercice 4: Au rapport!
Créez un fichier RAPPORT.md à la racine projet.
1) Tentez d'expliquer pourquoi certains langages sont plus rapides que d'autres dans cette expérience.
2) Observez l'espace mémoire inutilisé au fur et à mesure du programme. Qu'en pensez vous?
Imaginez un scénario dans lequel cela pourrait poser problème.
3) Décrivez les différences obtenues en faisant varier alpha dans les deux expériences.
A FINIR AVANT DIMANCHE !
Votre travail n'est validé que si le pipeline réussi.
\ No newline at end of file
RED='\033[0;31m'
NC='\033[0m' # No Color
# Compilation et exécution en C:
echo "${RED} Compilation du code source en C ${NC}"
cd C/
make
echo "${RED} Exécution des benchmarks en C ${NC}"
./arraylist_analysis
echo "${RED} Nettoyage ${NC}"
make clean
cd ..
# Compilation et exécution en C++:
echo "${RED} Compilation du code source en C++ ${NC}"
cd CPP/
make
echo "${RED} Exécution des benchmarks en C++ ${NC}"
./arraylist_analysis
echo "${RED} Nettoyage ${NC}"
make clean
cd ..
# Compilation et exécution en Java:
echo "${RED} Compilation du code source en Java ${NC}"
cd Java
javac *
echo "${RED} Exécution des benchmarks en Java ${NC}"
java Main
echo "${RED} Nettoyage ${NC}"
rm *.class
cd ..
# Exécution en Python
echo "${RED} Compilation du code source en Python ${NC}"
cd Python
echo "${RED} Exécution des benchmarks en Python ${NC}"
python main.py
cd ..
# Observation des résultats
### Dans le répertoire plots, lisez le contenu du fichier plot_result
cd plots
more plot_result
### puis lancez ce script avec gnuplot
gnuplot plot_result
plot [0:1000000][0:600] 'dynamic_array_time_c.plot' using 1:3 w lines title "Amortized C", 'dynamic_array_time_cpp.plot' using 1:3 w lines title "Amortized C++", 'dynamic_array_time_java.plot' using 1:3 w lines title "Amortized JAVA", 'dynamic_array_time_python.plot' using 1:3 w lines title "Amortized Python", 'dynamic_array_copy_c.plot' using 1:2 w boxes title "Memory Allocation"
plot 'dynamic_array_memory_c.plot' using 1:2 w lines title "Espace memoire inutilise"
plot 'dynamic_array_copy_c.plot' using 1:2 w boxes title "Nombre de copies de valeurs effectuees"
\ No newline at end of file