# randomly generate a collection of points which are near either
#  line_pts()      -  a line with randomly chosen slope and intercept  
#  bad_line_pts()  -  a line with random slope and intercept, with outliers  
#  quadratic_pts() -  a quadratic with randomly chosen coefficients
#  cubic_pts()     -  a cubic with randomly chosen coefficients
#  circle_pts()    -  a circle with randomly chosen center and radius.
#  exp_pts()       -  y=a*e^{bx} with a, b random.
#  set_seed(s)     -  set randomization to seed s.
# example:
#    plot(line_pts(), style = point, axes = boxed);
#
#  the data points are chosen from an appropriate uniform distribution, 
#  and the "noise" added is from a normal(0,1/2)  distribution.
#   The randomization seed depends on the system clock.
##########
#  uses the globals  points_wanted and  myrand(a,b)
##########
#
Seed:=randomize():
with(stats):

set_seed := seed -> randomize(seed);
#
myrand := (a,b) -> evalf(a+(b-a)*(rand()/10^12)):
points_wanted := 21:
#
line_pts:= proc(numpts::posint:= 40)
 local fuzz, m, b, x,i;
 global myrand;
   m:= myrand(-5,5);
   b:= myrand(-20,20);
   fuzz := [ random[normald[0,0.5]](numpts)];
   x    := [ random[uniform[-10,10]](numpts)];
   RETURN( [ [x[i], m*x[i]+b+fuzz[i]] $i=1..nops(x)]);
end:

bad_line_pts:= proc(numpts::posint:=40)
 local fuzz, m, b, x,i,pts;
 global myrand;
   pts:=numpts-8;
   m:= myrand(0.3,3);
   if (myrand(-10,10) < 0) then m:= m*(-1) fi; 
   b:= myrand(-20,20);
   fuzz := [ random[normald[0 ,0.5]](pts), 
             random[uniform[  3, 10]](4),
             random[uniform[-10, -3]](4)];
   x    := [ random[uniform[-10,10]](pts),
             random[uniform[-10,-5]](4),
             random[uniform[  5,10]](4)];
   x[pts]:=9;
   fuzz[pts]:=200;
   RETURN( [ [x[i], m*x[i]+b+fuzz[i]] $i=1..nops(x)]);
end:

quadratic_pts := proc()
 local fuzz, a, b, c,s, x,i;
   a:= myrand(-5,5);
   b:= myrand(-5,5);
   c:= myrand(-10,10);
   if (myrand(-10,10) > 0) then s:=1 else s:=-1 fi;
   fuzz := [ random[normald[0,0.5]](points_wanted)];
   x    := [ random[uniform[-5,5]](points_wanted)];
   RETURN( [ [x[i], s*(x[i] - a)*(x[i]-b)+c+fuzz[i]] $i=1..points_wanted]);
end:

cubic_pts := proc()
 local fuzz, a, b, c, d,s,x,i;
   a:= myrand(-3,3);
   b:= myrand(-3,3);
   c:= myrand(-3,3);
   d:= myrand(-10,10);
   if (myrand(-10,10) > 0) then s:=1 else s:=-1 fi;
   fuzz := [ random[normald[0,0.5]](points_wanted)];
   x    := [ random[uniform[-3,3]](points_wanted)];
   RETURN( [ [x[i], s*(a-x[i])*(b-x[i])*(c-x[i])+d+fuzz[i]] $i=1..points_wanted]);
end:

exp_pts:= proc()
 local fuzz, a, b, x,i;
   a:= myrand(1,5);
   b:= myrand(-2,2);
   fuzz := [ random[normald[0,0.5]](points_wanted)];
   x    := [ random[uniform[0,5]](points_wanted)];
   RETURN( [ [x[i], a*exp(b*x[i])+fuzz[i]] $i=1..points_wanted]);
end:

circle_pts := proc()
     local dat, i, rad, rads, angles, a, b;
      rad :=  myrand(3,10);
      a := myrand(-10,10);
      b:=  myrand(-10,10);
      rads := [ random[normald[rad,rad/50]](points_wanted)];
      angles := [ random[uniform[0,2*Pi]](points_wanted) ];
      RETURN ( [ [a+rads[i]*cos(angles[i]), b+rads[i]*sin(angles[i])]  $ i=1..points_wanted  ]):
 end:

printf(`defined set_seed(s), line_pts(n), bad_line_pts(n)`):
#printf(`defined set_seed(s), line_pts(), bad_line_pts(), quadratic_pts(), exp_pts(), cubic_pts(), and circle_pts()`):