12
$\begingroup$

Here's a nice function with a nice plot:

f[t_] := Exp[-Abs[t]] Sin[t];
Plot[f[t], {t, -10, 10}, PlotRange -> All]

nice function

What I would like to do is to make it noisy... to add something to f[t] so that it returns a noisy version. A roundabout way to accomplish this is to discretize/sample f[t], and then add noise to the samples:

range = Range[-10, 10, 0.1]; 
ListLinePlot[f[#] & /@ range + 
      RandomReal[{-0.03, 0.03},Length[range]], PlotRange -> All]

nice function with noise

Is there a more direct way? It seems like there are lots of functions that generate random processes, but they seem to invariably end up with a TemporalData object or a list of values. Is there any way to add noise directly to the function?


Update: I'm sorry I can't accept all the answers! David's has the advantage of simplicity (and of showing me a new way that the Random functions can work). A.G.'s answer provides clear flexibility in choosing the correlation of the random process. J.M.'s is probably the slickest, building on his earlier Perlin noise function.

$\endgroup$
  • $\begingroup$ Do you want the whole function or is a plot enough? $\endgroup$ – A.G. Nov 10 '17 at 1:12
  • $\begingroup$ I was hoping for a function that could be used elsewhere. $\endgroup$ – bill s Nov 10 '17 at 1:54
  • $\begingroup$ @bills I think that your question deserves more thinking. Noise is always characterised, in a first approximation, by a mean, a variance, and an amplitude. Therefore, I think that in the proposal some modelling of your additive noise seems to be worth considered. $\endgroup$ – José Antonio Díaz Navas Nov 11 '17 at 16:37
  • 1
    $\begingroup$ I wasn't too picky about the character of the noise, but the answers do provide a variety of possibilities -- for example, J.M.s suggestion of RandomVariate provides just about any independent distribution, while other answers address how to incorporate correlation over time. $\endgroup$ – bill s Nov 11 '17 at 21:49
11
$\begingroup$
Plot[
  f[t] + Sum[.01 RandomReal[n] Cos[n t/10], {n, 10}], 
  {t, -10, 10}, 
  PlotRange -> All]

enter image description here

$\endgroup$
  • 3
    $\begingroup$ Even simpler: Plot[f[t] + RandomReal[1], {t, -10, 10}]. I had no idea RandomReal could be used like this. Thanks! $\endgroup$ – bill s Nov 10 '17 at 0:08
  • $\begingroup$ @bill, you can use RandomVariate[] too if you want: Plot[f[t] + RandomVariate[NormalDistribution[0, 1/50]], {t, -10, 10}, PlotRange -> All] $\endgroup$ – J. M. will be back soon Nov 10 '17 at 4:51
  • 2
    $\begingroup$ An incredibly minor quibble: this new function will always have the same derivative as the original function at $t = 0$. This probably doesn't matter for most purposes, but it'd be easy enough to get around by adding in a random phase to the cosine: Cos [n t/10 + RandomReal[{0, 2 Pi}]. $\endgroup$ – Michael Seifert Nov 10 '17 at 15:31
12
$\begingroup$

If you need your function to look "ragged", but still be "continuous" and "reproducible", you can use one-dimensional Perlin noise (previously used here):

fBm = With[{permutations = Apply[Join, ConstantArray[RandomSample[Range[0, 255]], 2]]},
           Compile[{{x, _Real}},
                   Module[{xf = Floor[x], xi, xa, u, i, j},
                          xi = Mod[xf, 16] + 1;
                          xa = x - xf; u = xa*xa*xa*(10. + xa*(xa*6. - 15.));
                          i = permutations[[permutations[[xi]] + 1]]; 
                          j = permutations[[permutations[[xi + 1]] + 1]];
                          (2 Boole[OddQ[i]] - 1)*xa*(1. - u) +
                          (2 Boole[OddQ[j]] - 1)*(xa - 1.)*u],
                   RuntimeAttributes -> {Listable},
                   RuntimeOptions -> {"EvaluateSymbolically" -> False}]];

and then do something like

Plot[f[t] + Sum[fBm[5 2^k t]/2^k, {k, 0, 2}]/20, {t, -10, 10}, 
     PlotPoints -> 55, PlotRange -> All]

noisy pulse

$\endgroup$
8
$\begingroup$

If you want something like the example you present, you'll likely need to have the errors serially correlated as the number of evaluated data points gets large. Otherwise you'll get fuzzy caterpillars when the errors are independent.

Update: Hopefully a more justified presentation than before.

Suppose that we add noise to f[t] such that the distribution of the random noise is normally distributed with mean zero and variance $\sigma^2$. But rather than having independent random noise at times $t_1$ and $t_2$, we have $\operatorname{Correlation}(e_{t_1}, e_{t_2}) = \rho^{|t_1 - t_2|}$ with $\rho\ge 0$.

So that defines a random function with a continuous time index. Nothing has been said so far that makes this a discrete time model.

But when we want a particular realization of this function with random noise, we need to choose specific times to produce a display of the function. This doesn't make the function discrete in $t$. It might be a semantics issue but I wouldn't call this a sampled/discretized version of the function despite the way the values of the realization of this function are produced in code.

The following code uses values of $t$ that are equally spaced however the functions involved will take any unequally-spaced values of $t$. The parameter $\rho$ is the correlation of two errors one unit apart.

Manipulate[
 (* Values of t to consider *)
 t = Table[-10 + 20 i/n, {i, 0, n}];
 (* Differences in sucessive values of t *)
 d = Differences[t];
 (* Autoregressive errors of order 1 *)
 e = ConstantArray[0, n + 1];
 e[[1]] = RandomVariate[NormalDistribution[0, σ], 1][[1]];
 Do[e[[i]] = ρ^d[[i - 1]] e[[i - 1]] + 
    Sqrt[1 - ρ^(2 d[[i - 1]])] RandomVariate[NormalDistribution[0, σ], 1][[1]],
  {i, 2, n + 1}];
 (* Values of underlying function *)
 fTrue = f[#] & /@ t;
 (* Function plus errors *)
 y = fTrue + e;
 (* Plot true function and contaminated function *)
 ListPlot[{Transpose[{t, fTrue}], Transpose[{t, y}]}, 
  PlotRange -> All, Joined -> True, 
  PlotStyle -> {{Thickness[0.01]}, {Red}}],

 (* Sliders *)
 {{σ, 0.05}, 0.01, 0.2, Appearance -> "Labeled"},
 {{ρ, 0.5}, 0, 0.999, Appearance -> "Labeled"},
 {{n, 100}, 10, 2000, 1, Appearance -> "Labeled"},

 TrackedSymbols :> {σ, ρ, n},

 Initialization :> (
   f[t_] := Exp[-Abs[t]] Sin[t];
   )]

Correlated errors

When there is a large number of points close together and independent errors are used ($\rho=0$), then the result looks like a fuzzy caterpillar and probably unrealistic for any physical process. (Would an observation a very short distance away from an observation at $t$ be consistently wildly different?)

Fuzzy caterpillars with independent errors

$\endgroup$
  • 1
    $\begingroup$ Like in my example, this operates on a sampled version of the function. My hope was to be able to define a noisy function that could be used elsewhere. $\endgroup$ – bill s Nov 10 '17 at 1:56
6
$\begingroup$

In order to get a function it is possible to add a noise function. That noise will be more complex if the function is to be used on a large interval (unless it is periodic, which is not so good for a "random" noise).

Here is an example that produces a smooth function while avoiding periodical noise.

SeedRandom[1]; (* change for different noise *)
n = 200; (* increase for more randomness *)
a = 10; (* use function on interval [-a, a] *)
w = 1/500; (* weight of random noise *)
c = Table[RandomVariate[NormalDistribution[]], n]; (* coefficients *)
\[Epsilon][x_] := w Sum[ c[[i]] Cos[  \[Pi] i (x - a)/(2 a)], 
                         {i, 1, n}]; (* noise *)
Plot[\[Epsilon][t], {t, -10, 10}, PlotRange -> All]

f[t_] := Exp[-Abs[t]] Sin[t] + \[Epsilon][t];
Plot[f[t], {t, -a, a}, PlotRange -> All]

Noise:

Mathematica graphics

Function:

Mathematica graphics

$\endgroup$
  • 3
    $\begingroup$ Instead of Table[RandomVariate[NormalDistribution[]], n], you could do RandomVariate[NormalDistribution[], n]. Then, you can do ε[x_] = w c.Cos[π Range[n] (x - a)/(2 a)]. $\endgroup$ – J. M. will be back soon Nov 10 '17 at 4:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.