Exemple simple de génération de données avec et sans bruit

Le code de cet article requiert un compilateur C++ 11, et il se trouve que certains compilateurs C++ 11 ne supporteront pas quelques-unes des caractéristiques récentes du langage telles que std::result_of. Dans ce cas, vous pouvez simplement écrire double plutôt que typename std::result_of<F()>::type du fait que ce programme manipule des double. Vous perdrez en généralité, bien sûr, mais si vous ne souhaitez que faire fonctionner le tout, cela devrait vous permettre de procéder.

Il arrive, dans certains de mes cours, que les étudiant(e)s soient appelé(e)s à opérer sur des données brutes, que ce soit dans un but d'optimisation ou de modification des pratiques (p. ex. : morceler un traitement de longue durée pour l'intégrer dans un thread assujetti à des contraintes de temps réel). Pour elles et pour eux, il est donc parfois utile d'avoir accès à des données brutes.

Le petit programme qui suit peut alors servir. Il génère deux séries de données lisibles par un logiciel tel qu'Excel, soit une sinusoïdale « lisse » et une sinusoïdale « bruitée ». Notez que je ne suis pas un expert de l'injection de bruit dans un signal, alors j'ai bricolé quelque chose de simple et rapide pour dépanner, sans plus. Sachant cela, si vous avez envie de l'utiliser ou de vous en inspirer pour faire quelque chose d'analogue, amusez-vous bien!

#include <cmath>
#include <fstream>
#include <locale>
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <type_traits>
#include <functional>
#include <algorithm>

template <class F>
   auto generer_donnees(F fct, int n) -> std::vector<typename std::result_of<F()>::type>
   {
      using namespace std;
      vector<typename result_of<F()>::type> v(n);
      generate(begin(v), end(v), fct);
      return v;
   }

class sinusoidale
{
   double increment;
   int n;
public:
   using result_type = double;
   sinusoidale(double increment)
      : increment{increment}, n{}
   {
   }
   result_type operator()()
   {
      using std::sin;
      return sin(increment * n++);
   }
};

template <class F, class T>
   class bruiter_impl
   {
      F f_;
      T seuil_;
   public:
      bruiter_impl(F f, const T &seuil)
         : f_{f}, seuil_{seuil}
      {
      }
      typename std::result_of<F()>::type operator()()
      {
         using namespace std;
         return f_() + static_cast<T>(rand() - RAND_MAX/2)/RAND_MAX * seuil_;
      }
   };

template <class F, class T>
   bruiter_impl<F,T> bruiter(F fct, T seuil)
   {
      return bruiter_impl<F,T>(fct,seuil);
   }

int main(int argc, char *argv[])
{
   using namespace std;
   static const string SORTIE_LISSE = "lisse.txt",
                       SORTIE_BRUITEE = "bruitee.txt";
   enum { REPETITIONS = 5, GRANULARITE = 100 }; // vous pouvez faire varier ces paramètres
   const double PI = 3.14159; // allez-y avec un PI plus précis si nécessaire
   const double BRUIT = 0.1; // jouez avec ce paramètre en fonction de vos besoins
   {
      ofstream sortie{SORTIE_LISSE};
      sortie.imbue(locale{""});
      cout << "Génération de " << SORTIE_LISSE
           << " avec " << REPETITIONS << " répétitions de granularité " << GRANULARITE << endl;
      for (int rep = 0; rep != REPETITIONS; ++rep)
      {
         auto v = generer_donnees(sinusoidale(2*PI/GRANULARITE), GRANULARITE);
         copy(begin(v), end(v), ostream_iterator<double>{sortie, "\n"});
      }
   }
   {
      ofstream sortie(SORTIE_BRUITEE);
      sortie.imbue(locale{""});
      cout << "Génération de " << SORTIE_BRUITEE
           << " avec " << REPETITIONS << " répétitions de granularité " << GRANULARITE << endl;
      for (int rep = 0; rep != REPETITIONS; ++rep)
      {
         auto v = generer_donnees(bruiter(sinusoidale(2*PI/GRANULARITE),0.1), GRANULARITE);
         copy(begin(v), end(v), ostream_iterator<double>{sortie, "\n"});
      }
   }
}

Valid XHTML 1.0 Transitional

CSS Valide !