%mathpiper,def="RandomInterestingPolynomial"

//Retract("RandomInterestingPolynomial",*);
//Retract("NewRandomPoly",*);
//Retract("RandomIrreducibleQuadratic",*);
//Retract("RandomIrreducibleQuadraticWithComplexRoots",*);
//Retract("RandomIrreducibleQuadraticWithRealRoots",*);


10 # RandomInterestingPolynomial( deg_IsPositiveInteger, _var ) <--
[
    RandomSeed( SystemTimer() );   //  randomize random number generator
    NewRandomPoly(deg,var);   
];


10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,1)) <--
[
    Local(p,i1,i2);
    i1 := RandomInteger(1,10);
    i2 := RandomInteger(-10,10);
    p  := NormalForm(UniVariate(var,0,{i2,i1}));
];


10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,2)) <--
[
    Local(ii,i1,i2,p,quadPoly);
    p := FillList(0,2);
    For(ii:=1,ii<=2,ii++)
    [
        i1 := RandomInteger(10);
        i2 := RandomInteger(-10,10);
        If( i1 > 1, i2 := i1*i2 );
        p[ii] := NormalForm(UniVariate(var,0,{i2,i1}));
    ];
    quadPoly := ExpandBrackets(p[1]*p[2]);
    quadPoly := Simplify(Quotient(quadPoly,LeadingCoef(quadPoly)));
];


10 # RandomIrreducibleQuadratic( _var ) <--
[
    Local(ii,coeffs,discrim,u,p,f);
    // Use random integers for coefficients a2 and a1.  Then select a0 
    // in one of two ways:
    //  (1) so that discriminant is negative integer,  or
    //  (2) so that discriminant is positive integer but not square.
    If(RandomInteger(2)=1,
        RandomIrreducibleQuadraticWithComplexRoots(var),
        RandomIrreducibleQuadraticWithRealRoots(var)
    );
];


10 # RandomIrreducibleQuadraticWithRealRoots(_var) <--
[
    Local(coeffs,ijk);
    coeffs    := FillList(1,3);
    coeffs[2] := RandomInteger(-10,10);
    coeffs[3] := RandomInteger(1,10);
    ijk := Floor(coeffs[2]^2 / (4*coeffs[3]));
    coeffs[1] := RandomInteger(-10,ijk);
    discrim := coeffs[2]^2-4*coeffs[1]*coeffs[3];
    NormalForm(UniVariate(var,0,coeffs));
];


10 # RandomIrreducibleQuadraticWithComplexRoots(_var) <--
[
    Local(coeffs,ijk);
    coeffs := {1,RandomInteger(-10,10),RandomInteger(1,10)};
    coeffs[1] := Ceil(N(coeffs[2]^2/(4*coeffs[3]))) + RandomInteger(1,5);
    NormalForm(UniVariate(var,0,coeffs));
];


10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,3)) <--
[
    Local(ii,i1,i2,i3,p,CubicPoly);
    p := FillList(1,3);
    If( RandomInteger(3) = 1,
      [
        For(ii:=1,ii<=3,ii++)
        [
          i1 := RandomInteger(2);
          i2 := RandomInteger(-10,10);
          If( i1 > 1, i2 := i1*i2 );
          p[ii] := NormalForm(UniVariate(var,0,{i2,i1}));
        ];
      ],
      [
          i1 := RandomInteger(2);
          i2 := RandomInteger(-10,10);
          If( i1 > 1, i2 := i1*i2 );
          p[1] := NormalForm(UniVariate(var,0,{i2,i1}));
          p[2] := RandomIrreducibleQuadratic(var);
      ]
    );
    CubicPoly := ExpandBrackets(Product(p));
];


10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,4)) <--
[
    Local(ii,i1,i2,i3,i4,p,QuarticPoly);
    p := FillList(1,4);
    If( RandomInteger(2) = 1,
      [
          p[1] := NewRandomPoly(3,x);
          i1 := RandomInteger(2);
          i2 := RandomInteger(-10,10);
          If( i1 > 1, i2 := i1*i2 );
          p[2] := NormalForm(UniVariate(var,0,{i2,i1}));
      ],
      [
          p[1] := NewRandomPoly(2,x);
          p[2] := NewRandomPoly(2,x);
      ]
    );
    QuarticPoly := ExpandBrackets(Product(p));
];


10 # NewRandomPoly( _deg, _var )_(IsEqual(deg,5)) <--
[
    Local(ii,i1,i2,i3,i4,p,QuinticPoly);
    p := FillList(1,4);
    p[1] := NewRandomPoly(1,x);
    p[2] := RandomIrreducibleQuadraticWithRealRoots(x);
    p[3] := RandomIrreducibleQuadraticWithComplexRoots(x);
    QuinticPoly := ExpandBrackets(Product(p));
];


11 # NewRandomPoly( deg_IsPositiveInteger, _var )_(deg > 5) <--
[
    Local(p,n,m);
    p := {};
    m := deg;
    Until( m < 3 )
    [
        n := RandomInteger(2,Floor(N(deg/2)));
        Tell("     ",{m,n});
        Push(p,NewRandomPoly(n,var));
        m := m - n;
    ];
    Tell("      ",m);
    If( m > 0, Push(p,NewRandomPoly(m,x)));
    Expand(Product(p));
];

%/mathpiper




%mathpiper_docs,name="RandomInterestingPolynomial",categories="User Functions;Numbers (Random)"
*CMD RandomInterestingPolynomial --- construct a random "interesting" polynomial
*CMD RandomIrreducibleQuadraticWithComplexRoots --- constructs a random quadratic polynomial with complex roots
*CMD RandomIrreducibleQuadraticWithRealRoots --- constructs a random quadratic polynomial with real roots

*STD
*CALL
    RandomInterestingPolynomial(deg,var)
    RandomIrreducibleQuadraticWithComplexRoots(var)
    RandomIrreducibleQuadraticWithRealRoots(var)

*PARMS

{deg} -- degree of the resulting univariate polynomial

{var} -- free variable for the resulting univariate polynomial

*DESC

RandomInterestingPolynomial generates a random "interesting" polynomial in 
variable {var}, of degree {deg}, with integer coefficients.

Unlike the similar function {RandomPoly}, which merely generates
polynomials with random integer coefficients, the current function 
generates polynomials which are constructed by multiplying simpler 
random polynomials (with integer coefficients).  In this way, the
generated polynomials are guaranteed to be "interesting" in the sense
that they will always be factorable.  It is a known fact that a polynomial
whose coefficients are integers chosen at random will almost always
turn out to be irreducible.  This is not usually very "interesting",
especially in a learning context.

If you would like to construct higher degree polynomials having certain
specific kinds of roots, you can write a custom function to do this, 
using {RandomIrreducibleQuadraticWithRealRoots} or 
{RandomIrreducibleQuadraticWithComplexRoots} to create quadratics
with which to compose the higher polynomial.

*E.G.

In> RandomInterestingPolynomial(3,x)
Result: x^3+2*x^2-12*x-48
    
In> Factor(%)
Result: (x-4)*(x^2+6*x+12)
    
In> Solve(x^2+6*x+12,x)
Result: {x==Complex(-3,Sqrt(3)),x==Complex(-3,(-Sqrt(12))/2)}
    
Notice that although the polynomial is indeed factorable, it is 
not guaranteed to have only linear factors (over the integers), 
and (some of) the roots of the polynomial may be complex.
    
In> RandomIrreducibleQuadraticWithRealRoots(x)
Result: 6*x^2+2*x-7
    
In> Solve(%,x)
Result: {x==(Sqrt(172)-2)/12,x==(-(Sqrt(172)+2))/12}
    
In>  RandomIrreducibleQuadraticWithComplexRoots(x)
Result: 8*x^2-5*x+3
    
In> Solve(%,x)
Result: {x==Complex(5/16,Sqrt(71/256)),x==Complex(5/16,(-Sqrt(71))/16)}

*SEE Random, RandomPoly
%/mathpiper_docs



