This is WhitneyStratifications.info, produced by Macaulay2, version 1.25.11

WhitneyStratifications -- Computes Whitney Statifications of real and complex varieties and of algebraic maps between them.
***************************************************************************************************************************

Description
===========

This package computes Whitney stratifications of real and complex algebraic
varieties using the algorithms described in [1, 2, 4]. For varieties considered
over the complex numbers the output is indexed by the strata dimension. When
wishing to treat the variety over the reals, the same output may be used, but
the dimensions of the strata may differ (and some strata may be empty), see [2]
for more details. This post processing in the real case is currently left to
the user.

A method is also provided to stratify polynomial maps $f:X\to Y$ between
algebraic varieties, the output is a Whitney stratification of both $X$ and
$Y$, such that for each (open, connected) strata $M$ of $X$ there is an (open,
connected) strata $N$ of $Y$ such that $f(M) \subset N$ and such that the
restriction of $f$ to $M$ is a submersion. This in particular is sufficient to
guarantee that Thom's (first) isotopy lemma holds; namely that the stratified
homeomorpism type of $f^{-1}(q)$ is fixed for all $q$ in a given strata of the
codomain.

Using the methods of [1] or [4] computing the Conormal variety of a variety is
an important step in these algorithms, so a method for this is also provided.
An alternative method based on [2] is also provided, this requires the
computation of polar varieties, hence a method for this is provided as well.

Finally, based on work in [3], we use Whitney stratification to compute the
characteristic cycle of a constructable function and of the associated
annhilator ideal of a D-module.

References:

[1] Martin Helmer and Vidit Nanda. "Conormal Spaces and Whitney
Stratifications", Foundations of Computational Mathematics, DOI:
10.1007/s10208-022-09574-8.

[2] Martin Helmer, Anton Leykin, and Vidit Nanda. "Effective Whitney
Stratification of Real Algebraic Varieties". Arxiv: 2307.05427.

[3] Martin Helmer, Felix Tellander. "Spectral Decomposition of Euler-Mellin
Integrals". Arxiv: 2505.12458.

[4] Martin Helmer and Rafael Mohr. A New Algorithm for Whitney Stratification
of Varieties . Arxiv: 2406.1712.

Author
======

  * Martin Helmer (see http://martin-helmer.com/ )
    <martin.helmer@swansea.ac.uk>

Version
=======

This documentation describes version 2.23 of WhitneyStratifications, released
June 21, 2025.

Citation
========

If you have used this package in your research, please cite it as follows:

+-----------------------------------------------------------------------------+
|@misc{WhitneyStratificationsSource,                                          |
|  title = {{WhitneyStratifications: Compute Whitney Stratifications. Version~|
|  author = {Martin Helmer},                                                  |
|  howpublished = {A \emph{Macaulay2} package available at                    |
|    \url{https://github.com/Macaulay2/M2/tree/stable/M2/Macaulay2/packages}} |
|}                                                                            |
|-----------------------------------------------------------------------------|
|2.23}},                                                                      |
+-----------------------------------------------------------------------------+

Exports
=======

  * Functions and commands
      * conormal -- Computes the conormal variety
      * conormalRing (missing documentation)
      * eulerObsMatrix -- Computes a matrix containing
        the strata-wise values of the local Euler obstruction function.
      * mapStratify -- Computes a Whitney stratification of
        a polynomial map $f:X\to Y$ between real or complex varieties.
      * mapStratifyPol -- Computes a Whitney
        stratification of a polynomial map $f:X\to Y$ between real or complex
        varieties.
      * minCoarsenWS -- Coarsens a given Whitney
        stratification to the unique minimal one.
      * multCC -- Computes a list containing the coefficient
        associated to each term in the characteristic cycle of the
        constructable function corresponding to the input.
      * nonProperSet (missing documentation)
      * polarSequence -- Computes the list of
        multiplcities of a subvareity in the polar varieties of another
        vareity.
      * polarVars -- Computes the list of all polar varieties
        of a variety
      * whitneyStratify -- Computes a Whitney
        stratification of the real and complex varieties using conormal
        methods.
      * whitneyStratifyPol -- Computes a Whitney
        stratification of the real and complex varieties.
  * Methods
      * "conormal(Ideal)" -- see conormal, -- Computes the
        conormal variety
      * conormal(Ideal,Ring) (missing documentation)
      * conormalRing(Ideal) (missing documentation)
      * conormalRing(Ideal,List,List) (missing documentation)
      * conormalRing(Ring) (missing documentation)
      * "eulerObsMatrix(MutableHashTable)" -- see eulerObsMatrix,
        -- Computes a matrix containing the strata-wise values
        of the local Euler obstruction function.
      * "mapStratify(List,Ideal,Ideal)" -- see mapStratify,
        -- Computes a Whitney stratification of a polynomial map $f:X\to Y$
        between real or complex varieties.
      * "mapStratifyPol(List,Ideal,Ideal)" -- see mapStratifyPol,
        -- Computes a Whitney stratification of a polynomial
        map $f:X\to Y$ between real or complex varieties.
      * "minCoarsenWS(MutableHashTable)" -- see minCoarsenWS,
        -- Coarsens a given Whitney stratification to the unique
        minimal one.
      * "multCC(MutableHashTable)" -- see multCC, -- Computes a
        list containing the coefficient associated to each term in the
        characteristic cycle of the constructable function corresponding to the
        input.
      * nonProperSet(List,Ideal,Ideal) (missing documentation)
      * "polarSequence(Ideal,Ideal)" -- see polarSequence,
        -- Computes the list of multiplcities of a subvareity in the polar
        varieties of another vareity.
      * "polarSequence(Ideal,Ideal,List)" -- see polarSequence,
        -- Computes the list of multiplcities of a subvareity in
        the polar varieties of another vareity.
      * "polarVars(Ideal)" -- see polarVars, -- Computes the
        list of all polar varieties of a variety
      * "whitneyStratify(Ideal)" -- see whitneyStratify,
        -- Computes a Whitney stratification of the real and complex varieties
        using conormal methods.
      * whitneyStratify(Ideal,ZZ) (missing documentation)
      * whitneyStratify(Ideal,ZZ,ZZ) (missing documentation)
      * "whitneyStratifyPol(Ideal)" -- see whitneyStratifyPol,
        -- Computes a Whitney stratification of the real
        and complex varieties.
  * Symbols
      * AssocPrimes (missing documentation)
      * coordProj (missing documentation)
      * isProper (missing documentation)
      * StratsToFind (missing documentation)

For the programmer
==================

The object WhitneyStratifications, is a package (Macaulay2Doc),
defined in WhitneyStratifications.m2.

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

AssocPrimes
***********

Functions with optional argument named AssocPrimes:
===================================================

  * mapStratify(...,AssocPrimes=>...) (missing documentation)
  * mapStratifyPol(...,AssocPrimes=>...) (missing documentation)
  * whitneyStratify(...,AssocPrimes=>...) (missing documentation)

For the programmer
==================

The object AssocPrimes (missing documentation) is a symbol (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in currentString:1:400.

conormal -- Computes the conormal variety
*****************************************

  * Usage:
        conormal(I)
  * Inputs:
      * I, an ideal (Macaulay2Doc), in a polynomial ring
        $k[x_1,\dots, x_n]$ for a field $k$, defining a closed variety in $k^n$
        (or in $\PP^n$ if the ideal is homogeneous).
  * Outputs:
      * C, an ideal defining the conormal variety in $k^n \times \PP^{n-1}$.

Description
===========

For a complex projective variety $X=V(I)\subset \PP^n$ this command computes
the ideal of the conormal variety $Con(X)$ in $k^n \times \PP^{n-1}$.

+-----------------------------------------------------------------------------+
|i1 : S=QQ[x..z]                                                              |
|                                                                             |
|o1 = S                                                                       |
|                                                                             |
|o1 : PolynomialRing                                                          |
+-----------------------------------------------------------------------------+
|i2 : I=ideal(y^2*z-x^2)                                                      |
|                                                                             |
|            2     2                                                          |
|o2 = ideal(y z - x )                                                         |
|                                                                             |
|o2 : Ideal of S                                                              |
+-----------------------------------------------------------------------------+
|i3 : conormal I                                                              |
|                                                                             |
|                                           2    2     2                      |
|o3 = ideal (y*v  - 2z*v , x*v  + 2z*v , z*v  - v , y*v  - 2v v , y*z*v  +    |
|               1       2     0       2     0    1     0     1 2       0      |
|     ------------------------------------------------------------------------|
|            2             2     2                                            |
|     x*v , y v  + 2x*v , y z - x )                                           |
|        1     0       2                                                      |
|                                                                             |
|o3 : Ideal of QQ[x..z, v ..v ]                                               |
|                        0   2                                                |
+-----------------------------------------------------------------------------+

Ways to use conormal:
=====================

  * "conormal(Ideal)"
  * conormal(Ideal,Ring) (missing documentation)

For the programmer
==================

The object conormal, is a method function (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

conormalRing
************

Ways to use conormalRing:
=========================

  * conormalRing(Ideal) (missing documentation)
  * conormalRing(Ideal,List,List) (missing documentation)
  * conormalRing(Ring) (missing documentation)

For the programmer
==================

The object conormalRing (missing documentation) is a method function (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in currentString:1:400.

coordProj
*********

For the programmer
==================

The object coordProj (missing documentation) is a symbol (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in currentString:1:400.

eulerObsMatrix -- Computes a matrix containing the strata-wise values of the local Euler obstruction function.
**************************************************************************************************************

  * Usage:
        eulerObsMatrix(V)
  * Inputs:
      * V, a mutable hash table (Macaulay2Doc), in the
        format output by whitneyStratify and whitneyStratifyPol: the keys are
        the dimensions of strata, each gives a list of ideals defining all
        (closures of) strata of the corresponding dimension. Note that the
        input needs to represent a Whitney stratification to ensure correct
        results (though it need not be minimal).
  * Optional inputs (Macaulay2Doc),:
      * Algorithm (missing documentation) => ..., default value "saturate",
      * Print (missing documentation) => ..., default value false,
  * Outputs:
      * {Eu, StratList}, a list consisting of two elements: the first is a
        matrix Eu which gives the value of the local Euler obstruction function
        and the second is an ordered list of lists with each element consisting
        of the dimension and the equations of the closure of a Whitney strata.

Description
===========

Below we find the value of the Euler obstruction function (also called the
local Euler obstruction function) for all strata pairs. We begin by computing a
Whitney stratification to input into the eulerObsMatrix function. We will use
the Whitney cusp as our example variety, which we denote $X$.

+---------------------------------------------------+
|i1 : S=QQ[x..z]                                    |
|                                                   |
|o1 = S                                             |
|                                                   |
|o1 : PolynomialRing                                |
+---------------------------------------------------+
|i2 : Y=ideal(y^2+x^3-x^2*z^2)                      |
|                                                   |
|              2 2    3    2                        |
|o2 = ideal(- x z  + x  + y )                       |
|                                                   |
|o2 : Ideal of S                                    |
+---------------------------------------------------+
|i3 : V=whitneyStratify Y                           |
|                                                   |
|o3 = MutableHashTable{...3...}                     |
|                                                   |
|o3 : MutableHashTable                              |
+---------------------------------------------------+
|i4 : peek V                                        |
|                                                   |
|o4 = MutableHashTable{0 => {ideal (z, y, x)}      }|
|                      1 => {ideal (y, x)}          |
|                                   2 2    3    2   |
|                      2 => {ideal(x z  - x  - y )} |
+---------------------------------------------------+

Now we are ready to compute the Euler obstructions of strata.

+-----------------------------------------------------------------------------+
|i5 : EuL=eulerObsMatrix V                                                    |
|                                                                             |
|                                                                      2 2    |
|o5 = {| 1 1 1 |, {{0, ideal (z, y, x)}, {1, ideal (y, x)}, {2, ideal(x z  -  |
|      | 0 1 2 |                                                              |
|      | 0 0 1 |                                                              |
|     ------------------------------------------------------------------------|
|      3    2                                                                 |
|     x  - y )}}}                                                             |
|                                                                             |
|o5 : List                                                                    |
+-----------------------------------------------------------------------------+
|i6 : Eu=first EuL                                                            |
|                                                                             |
|o6 = | 1 1 1 |                                                               |
|     | 0 1 2 |                                                               |
|     | 0 0 1 |                                                               |
|                                                                             |
|              3       3                                                      |
|o6 : Matrix ZZ  <-- ZZ                                                       |
+-----------------------------------------------------------------------------+
|i7 : stratList=last EuL                                                      |
|                                                                             |
|                                                          2 2    3    2      |
|o7 = {{0, ideal (z, y, x)}, {1, ideal (y, x)}, {2, ideal(x z  - x  - y )}}   |
|                                                                             |
|o7 : List                                                                    |
+-----------------------------------------------------------------------------+

The strata (closures) are represented as two element lists, the first element
being the dimension and the second the defining equations. The order of this
list is used in the matrix of Euler obstruction values.

First fix some notation. Suppose $V_i\subset V_j$ are two strata closures
appearing in the list at positions $i$ and $j$, $i\leq j$. Let  $Z$ be the open
strata corresponding to $V_i$; $Z$ consists of all points in $V_i$ which are
not in any strata closure of dimension strictly less than that of $V_i$.

With this notation in hand, the entry in row i and column j of the matrix Eu is
$Eu_{V_j}(Z)$, which is the value of the local Euler obstruction function
associated to $V_j$, $Eu_{V_j}: V_j\to \mathbb{Z}$, at any point in $Z$.

For more discussion see Remark 4.2 of reference [3] (Martin Helmer, Felix
Tellander. "Spectral Decomposition of Euler-Mellin Integrals". Arxiv:
2505.12458.) Note that $Eu_{V_j}$ is defined to have value 0 outside $V_j$,
meaning if some strata closure $V_l$ is not contained in $V_j$ the
corresponding matrix row and column will be zero.

Note, this algorithm implementation contains steps which are probabilistic. To
be confident of the answer it is advised to confirm by running twice.

Lets look at our specific example. Consider the last column of the matrix Eu.
Since the last entry in our ordered list is the defining equation of the
Whitney cusp $Y$, this column gives the the values of $Eu_Y$, the Euler
obstruction function of $Y$.

+----------+
|i8 : Eu_2 |
|          |
|o8 = | 1 ||
|     | 2 ||
|     | 1 ||
|          |
|       3  |
|o8 : ZZ   |
+----------+

The first entry of the column

+-------------+
|i9 : Eu_(0,2)|
|             |
|o9 = 1       |
+-------------+

is the value of $Eu_Y$ at any point in $Z=Y-V(x,y)=\{(x,y,z)|y^2+x^3-x^2*z^2=0,
\; x\neq 0,\;y\neq 0\} $.

The second entry in of the column

+--------------+
|i10 : Eu_(1,2)|
|              |
|o10 = 2       |
+--------------+

is the value of $Eu_Y$ at any point in $Z=V(x,y)-V(x,y,z)=\{(x,y,z)|x=y=0, \;
z\neq 0\} $. And the final entry of the column is the value of $Eu_Y$ at the
point $(0,0,0)$.

There are also several different options to perform the underlying polar
variety calculations. The default algorithm uses the M2 saturate command to
compute the polar varieties, this option is Algorithm=>. The other options are:
Algorithm=>"msolve" and  Algorithm=>"M2F4". The Algorithm=>"msolve" only works
in versions 1.25.06 and above of Macaulay2. The  Algorithm=>"M2F4" is mostly
beneficial when working over a finite field. Note that over a finite field we
can still sometimes obtain useful information about the stratification, but the
coefficients appearing in the resulting polynomials may (or likely will) be
incorrect.

Ways to use eulerObsMatrix:
===========================

  * "eulerObsMatrix(MutableHashTable)"

For the programmer
==================

The object eulerObsMatrix, is a method function with options (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

isProper
********

Functions with optional argument named isProper:
================================================

  * mapStratify(...,isProper=>...) (missing documentation)
  * mapStratifyPol(...,isProper=>...) (missing documentation)

For the programmer
==================

The object isProper (missing documentation) is a symbol (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in currentString:1:400.

mapStratify -- Computes a Whitney stratification of a polynomial map $f:X\to Y$ between real or complex varieties.
******************************************************************************************************************

  * Usage:
        mapStratify(f,X,Y)
  * Inputs:
      * f, a list (Macaulay2Doc), a list of polynomials in the same
        ring as the ideal X
      * X, an ideal (Macaulay2Doc), defining an affine or
        projective variety.
      * Y, an ideal (Macaulay2Doc), defining an affine or
        projective variety.
  * Optional inputs (Macaulay2Doc),:
      * AssocPrimes (missing documentation) => ..., default value true,
      * isProper (missing documentation) => ..., default value true,
      * Print (missing documentation) => ..., default value false,
      * StratsToFind (missing documentation) => ..., default value "all",
  * Outputs:
      * MS, a list (Macaulay2Doc), a List containing two elements:
        a Whitney stratification of $X$ and of $Y$. Each stratification is
        stored in a hash table indexed by (complex) dimension, with the entry
        of (complex) dimension $i$ consisting of a list of prime ideals. The
        strata of $V(I)$ are the connected components of the successive
        difference between the varieties in the hash tables.

Description
===========

For a polynomial map $f:X\to Y$ this command computes a Whitney stratification
of $f$, that is a Whitney stratification of $X$ and of $Y$ (in the same output
format as the whitneyStatify command), such that for each (open, connected)
strata $M$ of $X$ there is an (open, connected) strata $N$ of $Y$ such that
$f(M) \subset N$ and such that the restriction of $f$ to $M$ is a submersion.
When $f$ is a proper map this stratification turns $f$ into a locally trivial
fiber bundle by Thom's isotopy lemma. More generally when $f$ is a dominant map
between varieties of the same dimension a stratification which further
stratifies by non-properness locus is also implemented (as described in Section
3.3 of [2], M. Helmer, V. Nanda, Effective Whitney Stratification of Real
Algebraic Varieties . Arxiv: 2307.05427). This can be used to, for example,
solve the real root classification problem (see Section 5 of [2]), that is to
stratify the parameter space of a parametric system of polynomials with
generically finitely many complex solutions into regions where the number of
real solutions is fixed.

We illustrate this on the quadratic equation $ax^2+bx+c$ by stratifying the
parameter space, $(a,b,c)\in \RR^3$, into regions where the number of real
roots is constant.

Here we stratify the projection map $X\to \RR^3$ where $X=V(ax^2+bx+c)$.

+-----------------------------------------------------------+
|i1 : R=QQ[a,b,c,x]                                         |
|                                                           |
|o1 = R                                                     |
|                                                           |
|o1 : PolynomialRing                                        |
+-----------------------------------------------------------+
|i2 : I=ideal(a*x^2+b*x+c)                                  |
|                                                           |
|              2                                            |
|o2 = ideal(a*x  + b*x + c)                                 |
|                                                           |
|o2 : Ideal of R                                            |
+-----------------------------------------------------------+
|i3 : S=QQ[(gens(R))_(toList(0..2))]                        |
|                                                           |
|o3 = S                                                     |
|                                                           |
|o3 : PolynomialRing                                        |
+-----------------------------------------------------------+
|i4 : gens S                                                |
|                                                           |
|o4 = {a, b, c}                                             |
|                                                           |
|o4 : List                                                  |
+-----------------------------------------------------------+
|i5 : F={R_0,R_1,R_2}                                       |
|                                                           |
|o5 = {a, b, c}                                             |
|                                                           |
|o5 : List                                                  |
+-----------------------------------------------------------+
|i6 : ms=mapStratify(F,I,ideal(0_S),isProper=>false)        |
|for j2....                                                 |
|loop over components of JY=ideal 1                         |
|for j2....                                                 |
|loop over components of JY=ideal 1                         |
|loop over components of JY=ideal (c, b, a)                 |
|at K= ideal (c, b, a)                                      |
|for j2....                                                 |
|loop over components of JY=ideal 1                         |
|                                                           |
|o6 = {MutableHashTable{...4...}, MutableHashTable{...4...}}|
|                                                           |
|o6 : List                                                  |
+-----------------------------------------------------------+
|i7 : peek last ms                                          |
|                                                           |
|o7 = MutableHashTable{0 => {ideal (c, b, a)}          }    |
|                      1 => {ideal (b, a)}                  |
|                      3 => {ideal 0}                       |
|                                            2              |
|                      2 => {ideal a, ideal(b  - 4a*c)}     |
+-----------------------------------------------------------+

For this and other root classification examples the option isProper=>false
should be used, as the corresponding projection maps are in general not proper.
Note that the top dimensional strata in this case are the four connected
components of $\RR^3-V(a(b^2-4ac))$, and so on for the lower dimensional
strata.

Another root classification example, this time we find the regions of the
parameter space $\{(a,b)\in \RR^2\}$ where the number of real roots to the
system $x^2-y^2+b = -ax+x^2+by=0$ is constant; this is Example 1.2 in Reference
[2].

+-----------------------------------------------------------------------------+
|i8 : R=QQ[a,b,x,y];                                                          |
+-----------------------------------------------------------------------------+
|i9 : I=ideal(x^2-y^2+b, -a*x+x^2+b*y);                                       |
|                                                                             |
|o9 : Ideal of R                                                              |
+-----------------------------------------------------------------------------+
|i10 : S=QQ[(gens(R))_(toList(0..1))];                                        |
+-----------------------------------------------------------------------------+
|i11 : F={R_0,R_1};                                                           |
+-----------------------------------------------------------------------------+
|i12 : ms=mapStratify(F,I,ideal(0_S),isProper=>false)                         |
|for j2....                                                                   |
|loop over components of JY=ideal 1                                           |
|for j2....                                                                   |
|loop over components of JY=ideal 1                                           |
|                                      2 3      5    4      2 2       4       |
|loop over components of JY=ideal (108a b  + 54b  - a  + 60a b  + 232b  +     |
|at K= ideal (b, a)                                                           |
|at K= ideal (b + 4, a)                                                       |
|                          2                                                  |
|at K= ideal (27b - 4, 729a  + 128)                                           |
|                                                                             |
|o12 = {MutableHashTable{...3...}, MutableHashTable{...3...}}                 |
|                                                                             |
|o12 : List                                                                   |
|-----------------------------------------------------------------------------|
|   3    4       2 3     5    4      2 2      4      3    5     3 2       4   |
|64b , 6a b - 12a b  + 6b  - a  + 60a b  + 40b  + 64b , 3a  - 6a b  + 3a*b  + |
|-----------------------------------------------------------------------------|
|  3         3                                                                |
|2a b - 20a*b )                                                               |
+-----------------------------------------------------------------------------+
|i13 : peek last ms                                                           |
|                                                                             |
|o13 = MutableHashTable{2 => {ideal 0}                                        |
|                                                                             |
|                       0 => {ideal (b, a), ideal (b + 4, a), ideal (27b -    |
|                                             6     4 2     2 4    6    4     |
|                       1 => {ideal b, ideal(a  - 3a b  + 3a b  - b  + a b    |
|-----------------------------------------------------------------------------|
|                       }                                                     |
|       2                                                                     |
|4, 729a  + 128)}                                                             |
|     2 3     5      4                                                        |
|- 20a b  - 8b  - 16b )}                                                      |
+-----------------------------------------------------------------------------+

Another broad class of interesting examples is parameterized projective
varieties, as the projection map to the parameter space is induced by the
projection $\PP^n\times \CC^m\to \CC^m$ and is hence always proper. Again we
seek to understand how the topology of the variety changes with parameters. The
following example is a special case of an example from the study of Feynman
integrals in mathematical physics (in particular is arises from the "one loop
bubble" for the case of equal masses). Note that for any fixed value of
parameters M1, P, the resulting polynomial Gh is homogeneous.

+----------------------------------------------------------------+
|i14 : R=QQ[M1,P,X_0..X_2];                                      |
+----------------------------------------------------------------+
|i15 : U = (X_1+X_2);                                            |
+----------------------------------------------------------------+
|i16 : F =U*(M1*X_1+M1*X_2)-P*X_1*X_2;                           |
+----------------------------------------------------------------+
|i17 : Gh = U*X_0+F;                                             |
+----------------------------------------------------------------+
|i18 : Xh=ideal (X_0*X_1*X_2*Gh);                                |
|                                                                |
|o18 : Ideal of R                                                |
+----------------------------------------------------------------+
|i19 : F={M1,P};                                                 |
+----------------------------------------------------------------+
|i20 : S=QQ[(gens(R))_(toList(0..1))];                           |
+----------------------------------------------------------------+
|i21 : ms=mapStratify(F,Xh,ideal(0_S));                          |
|for j2....                                                      |
|loop over components of JY=ideal 1                              |
|for j2....                                                      |
|loop over components of JY=ideal 1                              |
|for j2....                                                      |
|loop over components of JY=ideal 1                              |
|loop over components of JY=ideal 1                              |
+----------------------------------------------------------------+
|i22 : peek last ms                                              |
|                                                                |
|o22 = MutableHashTable{0 => {ideal (P, M1)}                    }|
|                       1 => {ideal P, ideal M1, ideal(4M1 - P)} |
|                       2 => {ideal 0}                           |
+----------------------------------------------------------------+

Finally we remark that the option: StratsToFind, may be used with this
function, but should only be used with care. The default setting is
StratsToFind=>"all", and this is the only value of the option which is
guaranteed to compute the complete stratification, the other options may fail
to find all strata but are provided to allow the user to obtain partial
information on larger examples which may take too long to run on the default
"all" setting. The other possible values are StratsToFind=>"singularOnly", and
StratsToFind=>"most". The option  StratsToFind=>"singularOnly" is the fastest,
but also the most likely to return incomplete answers, and hence the output of
this command should be treated as a partial answer only. The option
StratsToFind=>"most" will most often get the full answer, but can miss strata,
so again the output should be treated as a partial answer. In the example below
all options return the complete answer, but only the output with
StratsToFind=>"all" should be considered complete; StratsToFind=>"all" is run
when no option is given.

+-----------------------------------------------------------------------+
|i23 : time ms=mapStratify(F,Xh,ideal(0_S),StratsToFind=>"singularOnly")|
|for j2....                                                             |
|loop over components of JY=ideal 1                                     |
|for j2....                                                             |
|loop over components of JY=ideal 1                                     |
|for j2....                                                             |
|loop over components of JY=ideal 1                                     |
|loop over components of JY=ideal 1                                     |
| -- used 1.86134s (cpu); 1.39054s (thread); 0s (gc)                    |
|                                                                       |
|o23 = {MutableHashTable{...5...}, MutableHashTable{...3...}}           |
|                                                                       |
|o23 : List                                                             |
+-----------------------------------------------------------------------+
|i24 : peek last ms                                                     |
|                                                                       |
|o24 = MutableHashTable{0 => {ideal (P, M1)}                    }       |
|                       1 => {ideal P, ideal M1, ideal(4M1 - P)}        |
|                       2 => {ideal 0}                                  |
+-----------------------------------------------------------------------+
|i25 : time ms=mapStratify(F,Xh,ideal(0_S),StratsToFind=>"most")        |
|for j2....                                                             |
|loop over components of JY=ideal 1                                     |
|for j2....                                                             |
|loop over components of JY=ideal 1                                     |
|for j2....                                                             |
|loop over components of JY=ideal 1                                     |
|loop over components of JY=ideal 1                                     |
| -- used 4.36684s (cpu); 3.30925s (thread); 0s (gc)                    |
|                                                                       |
|o25 = {MutableHashTable{...5...}, MutableHashTable{...3...}}           |
|                                                                       |
|o25 : List                                                             |
+-----------------------------------------------------------------------+
|i26 : peek last ms                                                     |
|                                                                       |
|o26 = MutableHashTable{0 => {ideal (P, M1)}                    }       |
|                       1 => {ideal P, ideal M1, ideal(4M1 - P)}        |
|                       2 => {ideal 0}                                  |
+-----------------------------------------------------------------------+
|i27 : time ms=mapStratify(F,Xh,ideal(0_S),StratsToFind=>"all")         |
|for j2....                                                             |
|loop over components of JY=ideal 1                                     |
|for j2....                                                             |
|loop over components of JY=ideal 1                                     |
|for j2....                                                             |
|loop over components of JY=ideal 1                                     |
|loop over components of JY=ideal 1                                     |
| -- used 5.03276s (cpu); 3.70395s (thread); 0s (gc)                    |
|                                                                       |
|o27 = {MutableHashTable{...5...}, MutableHashTable{...3...}}           |
|                                                                       |
|o27 : List                                                             |
+-----------------------------------------------------------------------+
|i28 : peek last ms                                                     |
|                                                                       |
|o28 = MutableHashTable{0 => {ideal (P, M1)}                    }       |
|                       1 => {ideal P, ideal M1, ideal(4M1 - P)}        |
|                       2 => {ideal 0}                                  |
+-----------------------------------------------------------------------+

Ways to use mapStratify:
========================

  * "mapStratify(List,Ideal,Ideal)"

For the programmer
==================

The object mapStratify, is a method function with options (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

mapStratifyPol -- Computes a Whitney stratification of a polynomial map $f:X\to Y$ between real or complex varieties.
*********************************************************************************************************************

  * Usage:
        mapStratifyPol(f,X,Y)
  * Inputs:
      * f, a list (Macaulay2Doc), a list of polynomials in the same
        ring as the ideal X
      * X, an ideal (Macaulay2Doc), defining an affine or
        projective variety.
      * Y, an ideal (Macaulay2Doc), defining an affine or
        projective variety.
  * Optional inputs (Macaulay2Doc),:
      * Algorithm (missing documentation) => ..., default value "saturate",
      * AssocPrimes (missing documentation) => ..., default value true,
      * isProper (missing documentation) => ..., default value true,
      * Print (missing documentation) => ..., default value false,
      * StratsToFind (missing documentation) => ..., default value "all",
  * Outputs:
      * MS, a list (Macaulay2Doc), a List containing two elements:
        a Whitney stratification of $X$ and of $Y$. Each stratification is
        stored in a hash table indexed by (complex) dimension, with the entry
        of (complex) dimension $i$ consisting of a list of prime ideals. The
        strata of $V(I)$ are the connected components of the successive
        difference between the varieties in the hash tables.

Description
===========

For a polynomial map $f:X\to Y$ this command computes a Whitney stratification
of $f$, that is a Whitney stratification of $X$ and of $Y$ (in the same output
format as the whitneyStatify command), such that for each (open, connected)
strata $M$ of $X$ there is an (open, connected) strata $N$ of $Y$ such that
$f(M) \subset N$ and such that the restriction of $f$ to $M$ is a submersion.
When $f$ is a proper map this stratification turns $f$ into a locally trivial
fiber bundle by Thom's isotopy lemma. More generally when $f$ is a dominant map
between varieties of the same dimension a stratification which further
stratifies by non-properness locus is also implemented (as described in Section
3.3 of [2], M. Helmer, V. Nanda, Effective Whitney Stratification of Real
Algebraic Varieties . Arxiv: 2307.05427). This can be used to, for example,
solve the real root classification problem (see Section 5 of [2]), that is to
stratify the parameter space of a parametric system of polynomials with
generically finitely many complex solutions into regions where the number of
real solutions is fixed.

This method is used in an exactly identical way to mapStratify. The main
difference is that it uses the underlying Whitney stratification step based on
polar variety computation, and is hence probabilistic (while mapStratify uses
conormal method for the Whitney stratification step and is hence
deterministic).

The mapStratifyPol method is often faster than mapStratify. Similar to the
whitneyStratifyPol method it also produces unnecessary components (which are
random).

We carry out the example of the quadratic equation $ax^2+bx+c$ by stratifying
the parameter space, $(a,b,c)\in \RR^3$, into regions where the number of real
roots is constant. To remove unnecessary strata we do the calculation once and
take the common elements as the result.

Here we stratify the projection map $X\to \RR^3$ where $X=V(ax^2+bx+c)$.

+-----------------------------------------------------------------------------+
|i1 : R=QQ[a,b,c,x]                                                           |
|                                                                             |
|o1 = R                                                                       |
|                                                                             |
|o1 : PolynomialRing                                                          |
+-----------------------------------------------------------------------------+
|i2 : I=ideal(a*x^2+b*x+c)                                                    |
|                                                                             |
|              2                                                              |
|o2 = ideal(a*x  + b*x + c)                                                   |
|                                                                             |
|o2 : Ideal of R                                                              |
+-----------------------------------------------------------------------------+
|i3 : S=QQ[(gens(R))_(toList(0..2))]                                          |
|                                                                             |
|o3 = S                                                                       |
|                                                                             |
|o3 : PolynomialRing                                                          |
+-----------------------------------------------------------------------------+
|i4 : gens S                                                                  |
|                                                                             |
|o4 = {a, b, c}                                                               |
|                                                                             |
|o4 : List                                                                    |
+-----------------------------------------------------------------------------+
|i5 : F={R_0,R_1,R_2}                                                         |
|                                                                             |
|o5 = {a, b, c}                                                               |
|                                                                             |
|o5 : List                                                                    |
+-----------------------------------------------------------------------------+
|i6 : ms1=mapStratifyPol(F,I,ideal(0_S),isProper=>false)                      |
|                                                                             |
|o6 = {MutableHashTable{...4...}, MutableHashTable{...4...}}                  |
|                                                                             |
|o6 : List                                                                    |
+-----------------------------------------------------------------------------+
|i7 : ms2=mapStratifyPol(F,I,ideal(0_S),isProper=>false)                      |
|                                                                             |
|o7 = {MutableHashTable{...4...}, MutableHashTable{...4...}}                  |
|                                                                             |
|o7 : List                                                                    |
+-----------------------------------------------------------------------------+
|i8 : ms={new MutableHashTable from for k in keys first ms1 list              |
|                                                                             |
|o8 = {MutableHashTable{...4...}, MutableHashTable{...4...}}                  |
|                                                                             |
|o8 : List                                                                    |
|-----------------------------------------------------------------------------|
|k=>toList((set(first ms1)#k)*(set(first ms2)#k)),new MutableHashTable from   |
|-----------------------------------------------------------------------------|
|for k in keys last ms1 list k=>toList((set(last ms1)#k)*(set(last ms2)#k))}  |
+-----------------------------------------------------------------------------+
|i9 : peek last ms                                                            |
|                                                                             |
|o9 = MutableHashTable{0 => {ideal (c, b, a)}          }                      |
|                      1 => {ideal (b, a)}                                    |
|                      3 => {ideal 0}                                         |
|                                            2                                |
|                      2 => {ideal a, ideal(b  - 4a*c)}                       |
+-----------------------------------------------------------------------------+

Ways to use mapStratifyPol:
===========================

  * "mapStratifyPol(List,Ideal,Ideal)"

For the programmer
==================

The object mapStratifyPol, is a method function with options (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

minCoarsenWS -- Coarsens a given Whitney stratification to the unique minimal one.
**********************************************************************************

  * Usage:
        minCoarsenWS(WS)
  * Inputs:
      * WS, a mutable hash table (Macaulay2Doc), a
        MutableHashTable storing a Whitney stratification (produced by either
        whitneyStatify or whitneyStatifyPol).
  * Optional inputs (Macaulay2Doc),:
      * Algorithm (missing documentation) => ..., default value "saturate",
      * Print (missing documentation) => ..., default value false,
  * Outputs:
      * minWS, a MutableHashTable storing the unique minimal Whitney
        stratification obtained by coarsening the given one.

Description
===========

For a given Whitney stratification, represented in the form output by the
whitneyStratify and whitneyStratifyPol commands, this command identifies any
strata which are unnecessary and removes them to compute a coarsening.

In the example below we use whitneyStratifyPol to compute a non-minimal Whitney
stratification and then use minCoarsenWS to obtain the unique minimal Whitney
stratification from this output.

+-----------------------------------------------------------------------------+
|i1 : R=QQ[x..z]                                                              |
|                                                                             |
|o1 = R                                                                       |
|                                                                             |
|o1 : PolynomialRing                                                          |
+-----------------------------------------------------------------------------+
|i2 : I=ideal(y^2*z-x^2)                                                      |
|                                                                             |
|            2     2                                                          |
|o2 = ideal(y z - x )                                                         |
|                                                                             |
|o2 : Ideal of R                                                              |
+-----------------------------------------------------------------------------+
|i3 : WS= whitneyStratifyPol I                                                |
|                                                                             |
|o3 = MutableHashTable{...3...}                                               |
|                                                                             |
|o3 : MutableHashTable                                                        |
+-----------------------------------------------------------------------------+
|i4 : peek WS                                                                 |
|                                                                             |
|o4 = MutableHashTable{0 => {ideal (z, y, x), ideal (1747430111571076z -      |
|                      1 => {ideal (y, x)}                                    |
|                                   2     2                                   |
|                      2 => {ideal(y z - x )}                                 |
|-----------------------------------------------------------------------------|
|258644393880625, y, x)}}                                                     |
+-----------------------------------------------------------------------------+
|i5 : mWS=minCoarsenWS WS                                                     |
|                                                                             |
|o5 = MutableHashTable{...3...}                                               |
|                                                                             |
|o5 : MutableHashTable                                                        |
+-----------------------------------------------------------------------------+
|i6 : peek mWS                                                                |
|                                                                             |
|o6 = MutableHashTable{0 => {ideal (z, y, x)}}                                |
|                      1 => {ideal (y, x)}                                    |
|                                   2     2                                   |
|                      2 => {ideal(y z - x )}                                 |
+-----------------------------------------------------------------------------+

Ways to use minCoarsenWS:
=========================

  * "minCoarsenWS(MutableHashTable)"

For the programmer
==================

The object minCoarsenWS, is a method function with options (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

multCC -- Computes a list containing the coefficient associated to each term in the characteristic cycle of the constructable function corresponding to the input.
******************************************************************************************************************************************************************

  * Usage:
        multCC(V)
  * Inputs:
      * V, a mutable hash table (Macaulay2Doc), in the
        format output by whitneyStratify and whitneyStratifyPol: the keys are
        the dimensions of strata, each gives a list of ideal defining all
        (closures of) strata of the corresponding dimension. Note that the
        input needs to represent a Whitney stratification to ensure correct
        results (though it need not be minimal).
  * Optional inputs (Macaulay2Doc),:
      * Algorithm (missing documentation) => ..., default value "saturate",
      * Print (missing documentation) => ..., default value false,
  * Outputs:
      * {Eu, CClist}, a list consisting of two elements: the first is a matrix
        Eu which gives the value of the local Euler obstruction function (see
        also the \(eulerObsMatrix\) function documentation) and the second is
        an ordered list of lists, CClist. The list CClist consists of lists,
        the first entry in each list is the multiplicity of the (conormal
        variety of) the strata closure in the characteristic cycle, and the
        second entry is a list with the dimension and the equations of the
        closure of the strata.

Description
===========

Below we find the multiplicities of the elements of the formal sum making up
the characteristic cycle of the constructable function associated to the input.
When $V$ corresponds to a hypersurface this also gives the characteristic cycle
arising from the D-module annihilating the associated rational function. For
further background see Remark 4.2 and Example 4.5 of reference [3] (Martin
Helmer, Felix Tellander. "Spectral Decomposition of Euler-Mellin Integrals".
Arxiv: 2505.12458.) Note that $Eu_{V_j}$ is defined to have value 0 outside
$V_j$, meaning if some strata closure $V_l$ is not contained in $V_j$ the
corresponding matrix row and column will be zero.

This multiplicity also directly gives the value of the the Euler characteristic
of the complex link of any stratum to the variety corresponding to our Whitney
stratification, as we will see on our example below.

Note, this algorithm implementation contains steps which are probabilistic. To
be confident of the answer it is advised to confirm by running twice.

We begin by computing a Whitney stratification to input into the multCC
function. We will use the Whitney cusp as our example variety, which we denote
$X$.

+---------------------------------------------------+
|i1 : R=QQ[x..z]                                    |
|                                                   |
|o1 = R                                             |
|                                                   |
|o1 : PolynomialRing                                |
+---------------------------------------------------+
|i2 : Y=ideal(y^2+x^3-x^2*z^2)                      |
|                                                   |
|              2 2    3    2                        |
|o2 = ideal(- x z  + x  + y )                       |
|                                                   |
|o2 : Ideal of R                                    |
+---------------------------------------------------+
|i3 : V=whitneyStratify Y                           |
|                                                   |
|o3 = MutableHashTable{...3...}                     |
|                                                   |
|o3 : MutableHashTable                              |
+---------------------------------------------------+
|i4 : peek V                                        |
|                                                   |
|o4 = MutableHashTable{0 => {ideal (z, y, x)}      }|
|                      1 => {ideal (y, x)}          |
|                                   2 2    3    2   |
|                      2 => {ideal(x z  - x  - y )} |
+---------------------------------------------------+

Now we are ready to compute the Euler obstructions of strata.

+-----------------------------------------------------------------------------+
|i5 : CCmults=multCC V                                                        |
|                                                                             |
|                                                                             |
|o5 = {| 1 -1 1 |, {{1, {0, ideal (z, y, x)}}, {1, {1, ideal (y, x)}}, {1, {2,|
|      | 0 -1 2 |                                                             |
|      | 0 0  1 |                                                             |
|     ------------------------------------------------------------------------|
|            2 2    3    2                                                    |
|     ideal(x z  - x  - y )}}}}                                               |
|                                                                             |
|o5 : List                                                                    |
+-----------------------------------------------------------------------------+
|i6 : Eu=first CCmults                                                        |
|                                                                             |
|o6 = | 1 -1 1 |                                                              |
|     | 0 -1 2 |                                                              |
|     | 0 0  1 |                                                              |
|                                                                             |
|              3       3                                                      |
|o6 : Matrix ZZ  <-- ZZ                                                       |
+-----------------------------------------------------------------------------+
|i7 : CCmultiplcityList=last CCmults                                          |
|                                                                             |
|                                                                        2 2  |
|o7 = {{1, {0, ideal (z, y, x)}}, {1, {1, ideal (y, x)}}, {1, {2, ideal(x z  -|
|     ------------------------------------------------------------------------|
|      3    2                                                                 |
|     x  - y )}}}                                                             |
|                                                                             |
|o7 : List                                                                    |
+-----------------------------------------------------------------------------+

Now we can extract the multiplicity with which the conormal variety of each
strata will appear in the characteristic cycle.

+----------------------------------------------+
|i8 : m=for s in CCmultiplcityList list first s|
|                                              |
|o8 = {1, 1, 1}                                |
|                                              |
|o8 : List                                     |
+----------------------------------------------+

Using this we can immediately obtain the the value of the the Euler
characteristic, $\chi(CL_{Y}(S))$ of the complex link, $CL_{Y}(S)$ of any
stratum $S$ of $Y$ to the variety Y (for any variety $Y$). See (7) and Remark
4.2 of reference  [3] (Martin Helmer, Felix Tellander. "Spectral Decomposition
of Euler-Mellin Integrals". Arxiv: 2505.12458.) for a definition.

Note that the block of code below can be used identically on any other example
as well.

+-----------------------------------------------------------------------------+
|i9 : d=dim Y                                                                 |
|                                                                             |
|o9 = 2                                                                       |
+-----------------------------------------------------------------------------+
|i10 : dStrats=for s in CCmultiplcityList list first last s                   |
|                                                                             |
|o10 = {0, 1, 2}                                                              |
|                                                                             |
|o10 : List                                                                   |
+-----------------------------------------------------------------------------+
|i11 : EulerCharComplexLink=for i from 0 to #CCmultiplcityList-1 list         |
|                                                                             |
|o11 = {0, 2, 0}                                                              |
|                                                                             |
|o11 : List                                                                   |
|-----------------------------------------------------------------------------|
|(1-(-1)^(d-dStrats_i)*m_i)                                                   |
+-----------------------------------------------------------------------------+

There are also several different options to perform the underlying polar
variety calculations. The default algorithm uses the M2 saturate command to
compute the polar varieties, this option is Algorithm=>. The other options are:
Algorithm=>"msolve" and  Algorithm=>"M2F4". The Algorithm=>"msolve" only works
in versions 1.25.06 and above of Macaulay2. The  Algorithm=>"M2F4" is mostly
beneficial when working over a finite field. Note that over a finite field we
can still sometimes obtain useful information about the stratification, but the
coefficients appearing in the resulting polynomials may (or likely will) be
incorrect.

Ways to use multCC:
===================

  * "multCC(MutableHashTable)"

For the programmer
==================

The object multCC, is a method function with options (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

nonProperSet
************

Ways to use nonProperSet:
=========================

  * nonProperSet(List,Ideal,Ideal) (missing documentation)

For the programmer
==================

The object nonProperSet (missing documentation) is a method function (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in currentString:1:400.

polarSequence -- Computes the list of multiplcities of a subvareity in the polar varieties of another vareity.
**************************************************************************************************************

  * Usage:
        polarSequence(I)
  * Inputs:
      * IX, an ideal (Macaulay2Doc), in a polynomial ring
        $k[x_1,\dots, x_n]$ for a field $k$.
      * IZ, an ideal (Macaulay2Doc), in a polynomial ring
        $k[x_1,\dots, x_n]$ for a field $k$ such that $V(IX)\subset V(IZ)$.
      * polsZ, a list (Macaulay2Doc), a list of ideals defining the
        polar varieties of $Z=V(IZ)$; this is an optional argument to avoid
        recomputing polar varieties for multiple polar sequence calculations.
        This is meant to be the output of polarVars(IZ).
  * Optional inputs (Macaulay2Doc),:
      * Algorithm (missing documentation) => ..., default value "saturate",
      * Print (missing documentation) => ..., default value false,
  * Outputs:
      * polarMultiplcities, a list of integers giving the (Hilbert-Samuel)
        multiplicity sequence of $X=V(IX)$ in each of the polar varieties of
        $Z=V(IZ)$ which contain it.

Description
===========

Below we compute the polar multiplicity sequence for the origin and the z-axis
in the Whitney umbrella.

+----------------------------------+
|i1 : R=QQ[x..z]                   |
|                                  |
|o1 = R                            |
|                                  |
|o1 : PolynomialRing               |
+----------------------------------+
|i2 : IZ=ideal(y^2*z-x^2)          |
|                                  |
|            2     2               |
|o2 = ideal(y z - x )              |
|                                  |
|o2 : Ideal of R                   |
+----------------------------------+
|i3 : IX=ideal(x,y,z)              |
|                                  |
|o3 = ideal (x, y, z)              |
|                                  |
|o3 : Ideal of R                   |
+----------------------------------+
|i4 : polarSequence(IX, IZ)        |
|                                  |
|o4 = {0, 1, 2}                    |
|                                  |
|o4 : List                         |
+----------------------------------+
|i5 : polarSequence(ideal(x,y), IZ)|
|                                  |
|o5 = {0, 0, 2}                    |
|                                  |
|o5 : List                         |
+----------------------------------+

Note that for any polar varieties of $Z$ which do not contain $X$ we obtain
multiplicity 0.

Ways to use polarSequence:
==========================

  * "polarSequence(Ideal,Ideal)"
  * "polarSequence(Ideal,Ideal,List)"

For the programmer
==================

The object polarSequence, is a method function with options (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

polarVars -- Computes the list of all polar varieties of a variety
******************************************************************

  * Usage:
        polarVars(I)
  * Inputs:
      * I, an ideal (Macaulay2Doc), in a polynomial ring
        $k[x_1,\dots, x_n]$ for a field $k$, defining a closed variety in $k^n$
        (or in $\PP^n$ if the ideal is homogeneous).
  * Optional inputs (Macaulay2Doc),:
      * Algorithm (missing documentation) => ..., default value "saturate",
      * Print (missing documentation) => ..., default value false,
  * Outputs:
      * pols, a list of ideals defining polar varieties to $X=V(I)$ relative to
        a random flag of linear subspaces. The list starts with a dimension 0
        polar variety and ends with the $dim(X)$ polar variety, which is $X$,
        hence the last ideal in the list is I.

Description
===========

For a complex variety $X=V(I)$ this command computes a list of ideals defining
polar varieties to $X=V(I)$ relative to a random flag of linear subspaces. For
the relevant definitions see, e.g., [2]: Martin Helmer, Anton Leykin, and Vidit
Nanda. "Effective Whitney Stratification of Real Algebraic Varieties". Arxiv:
2307.05427.

+-----------------------------------------------------------------------------+
|i1 : S=QQ[x..z]                                                              |
|                                                                             |
|o1 = S                                                                       |
|                                                                             |
|o1 : PolynomialRing                                                          |
+-----------------------------------------------------------------------------+
|i2 : I=ideal(y^2*z-x^2)                                                      |
|                                                                             |
|            2     2                                                          |
|o2 = ideal(y z - x )                                                         |
|                                                                             |
|o2 : Ideal of S                                                              |
+-----------------------------------------------------------------------------+
|i3 : polarVars I                                                             |
|                                                                             |
|                                                                             |
|o3 = {ideal (10163344z - 73462041, 5081672y - 72382095, 16200370336x -       |
|     ------------------------------------------------------------------------|
|                                                                 2           |
|     620386936245), ideal (200154345987154y*z + 1747430111571076z  +         |
|     ------------------------------------------------------------------------|
|                                                        2                    |
|     77004596873425x - 258644393880625z, 22926102710641y  -                  |
|     ------------------------------------------------------------------------|
|                      2                                                      |
|     1747430111571076z  - 154009193746850x + 258644393880625z,               |
|     ------------------------------------------------------------------------|
|                                                                             |
|     958363227262357797634x*y + 8366906813245811988196x*z +                  |
|     ------------------------------------------------------------------------|
|                             2                                               |
|     28102913712083461939300z  + 1238420653872092055625x -                   |
|     ------------------------------------------------------------------------|
|                                      2     2                                |
|     4159629066255610515625z), ideal(y z - x )}                              |
|                                                                             |
|o3 : List                                                                    |
+-----------------------------------------------------------------------------+

There are also several different options to perform the polar variety
calculations. The default algorithm uses the M2 saturate command to compute the
polar varieties, this option is Algorithm=>. The other options are:
Algorithm=>"msolve" and  Algorithm=>"M2F4". The Algorithm=>"msolve" only works
in versions 1.25.06 and above of Macaulay2. The  Algorithm=>"M2F4" is mostly
beneficial when working over a finite field. Note that over a finite field we
can still sometimes obtain useful information, but the coefficients appearing
in the resulting polynomials may (or likely will) be incorrect.

Ways to use polarVars:
======================

  * "polarVars(Ideal)"

For the programmer
==================

The object polarVars, is a method function with options (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

StratsToFind
************

Functions with optional argument named StratsToFind:
====================================================

  * mapStratify(...,StratsToFind=>...) (missing documentation)
  * mapStratifyPol(...,StratsToFind=>...) (missing documentation)

For the programmer
==================

The object StratsToFind (missing documentation) is a symbol (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in currentString:1:400.

whitneyStratify -- Computes a Whitney stratification of the real and complex varieties using conormal methods.
**************************************************************************************************************

  * Usage:
        whitneyStratify(I)
  * Inputs:
      * I, an ideal (Macaulay2Doc), an ideal defining a closed
        subvariety of affine or projective space over a field.
  * Optional inputs (Macaulay2Doc),:
      * AssocPrimes (missing documentation) => ..., default value true,
      * Projective (missing documentation) => ..., default value false,
  * Outputs:
      * WS, a mutable hash table (Macaulay2Doc), a hash
        table indexed by (complex) dimension, with the entry of (complex)
        dimension $i$ consisting of a list of prime ideals. The strata of
        $V(I)$ are the connected components of the difference between the
        variety defined by WS#i and that defined by WS#(i-1).

Description
===========

For a variety $X$ this command computes a Whitney stratification WS where WS#i
is a list of strata closures in (complex) dimension $i$; for a prime ideal $P$
in WS#i the associated open (connected) strata is given by the connected
components of $V(P)-Z$ where $Z$ is the union of the varieties defined by the
entries of WS#(i-1). We demonstrate the method for the Whitney umbrella below.

+---------------------------------------------+
|i1 : R=QQ[x..z]                              |
|                                             |
|o1 = R                                       |
|                                             |
|o1 : PolynomialRing                          |
+---------------------------------------------+
|i2 : I=ideal(y^2*z-x^2)                      |
|                                             |
|            2     2                          |
|o2 = ideal(y z - x )                         |
|                                             |
|o2 : Ideal of R                              |
+---------------------------------------------+
|i3 : WS=whitneyStratify I                    |
|                                             |
|o3 = MutableHashTable{...3...}               |
|                                             |
|o3 : MutableHashTable                        |
+---------------------------------------------+
|i4 : peek WS                                 |
|                                             |
|o4 = MutableHashTable{0 => {ideal (z, y, x)}}|
|                      1 => {ideal (y, x)}    |
|                                   2     2   |
|                      2 => {ideal(y z - x )} |
+---------------------------------------------+

Now the projective version; using the option Projective=>true will treat the
input as a projective variety. If this option is omitted the input is treated
as an affine cone over the projective variety.

+--------------------------------------------------------------+
|i5 : S=QQ[x..z,w]                                             |
|                                                              |
|o5 = S                                                        |
|                                                              |
|o5 : PolynomialRing                                           |
+--------------------------------------------------------------+
|i6 : I=ideal(y^2*z-x^2*w)                                     |
|                                                              |
|            2     2                                           |
|o6 = ideal(y z - x w)                                         |
|                                                              |
|o6 : Ideal of S                                               |
+--------------------------------------------------------------+
|i7 : WS=whitneyStratify(I,Projective=>true)                   |
|                                                              |
|o7 = MutableHashTable{...3...}                                |
|                                                              |
|o7 : MutableHashTable                                         |
+--------------------------------------------------------------+
|i8 : peek WS                                                  |
|                                                              |
|o8 = MutableHashTable{0 => {ideal (z, y, x), ideal (w, y, x)}}|
|                      1 => {ideal (y, x)}                     |
|                                   2     2                    |
|                      2 => {ideal(y z - x w)}                 |
+--------------------------------------------------------------+

Another projective example.

+-----------------------------------------------------------------------------+
|i9 : R=QQ[a_0..a_4]                                                          |
|                                                                             |
|o9 = R                                                                       |
|                                                                             |
|o9 : PolynomialRing                                                          |
+-----------------------------------------------------------------------------+
|i10 : I=ideal(a_0^2*a_4-a_1*a_2^2+a_3^3-a_3*a_0^2-a_4^2*a_3)                 |
|                                                                             |
|                 2    2      3    2        2                                 |
|o10 = ideal(- a a  - a a  + a  + a a  - a a )                                |
|               1 2    0 3    3    0 4    3 4                                 |
|                                                                             |
|o10 : Ideal of R                                                             |
+-----------------------------------------------------------------------------+
|i11 : V=whitneyStratify(I,Projective=>true)                                  |
|                                                                             |
|o11 = MutableHashTable{...4...}                                              |
|                                                                             |
|o11 : MutableHashTable                                                       |
+-----------------------------------------------------------------------------+
|i12 : peek V                                                                 |
|                                                                             |
|o12 = MutableHashTable{2 => {}                                               |
|                                                      2     2                |
|                       0 => {ideal (a  - a , a , a , a  - 2a ), ideal (a ,   |
|                                     3    4   2   1   0     4           4    |
|                                                  2     2                    |
|                       1 => {ideal (a  - a , a , a  - 2a )}                  |
|                                     3    4   2   0     4                    |
|                                      2    2      3    2        2            |
|                       3 => {ideal(a a  + a a  - a  - a a  + a a )}          |
|                                    1 2    0 3    3    0 4    3 4            |
|-----------------------------------------------------------------------------|
|            }                                                                |
|                                                                             |
|a , a , a )}                                                                 |
| 3   2   0                                                                   |
+-----------------------------------------------------------------------------+

Note that as with the Whitney umbrella simply taking successive singular loci
will not yield the correct stratification, in particular one would miss the two
points defined by the second entry of V#0.

+------------------------------------------------+
|i13 : J=radical (I+minors(codim I, jacobian I)) |
|                                                |
|                           2     2              |
|o13 = ideal (a  - a , a , a  - 2a )             |
|              3    4   2   0     4              |
|                                                |
|o13 : Ideal of R                                |
+------------------------------------------------+
|i14 : J2=radical (J+minors(codim J, jacobian J))|
|                                                |
|o14 = ideal (a , a , a , a )                    |
|              4   3   2   0                     |
|                                                |
|o14 : Ideal of R                                |
+------------------------------------------------+

By default whitneyStratify will use the algorithm of [1] (Martin Helmer and
Vidit Nanda. "Conormal Spaces and Whitney Stratifications", Foundations of
Computational Mathematics, DOI: 10.1007/s10208-022-09574-8), which as a step
requires the computation of the associated primes of a certain ideal arising
from a conormal variety. This can in practice be very costly. The algorithm of
[4] (Martin Helmer and Rafael Mohr. A New Algorithm for Whitney Stratification
of Varieties . Arxiv: 2406.1712) also uses conormal varieties but avoids the
need to compute associated primes. This algorithm is often much faster (though
it is slightly more likely to produce non-minimal Whitney stratifications, it
is accessed with the option AssocPrimes=>false. Both algorithms are
deterministic and are guaranteed to produce a correct Whitney stratification
(though not necessarily the unique minimal one).

+----------------------------------------------------+
|i15 : R=QQ[x..z]                                    |
|                                                    |
|o15 = R                                             |
|                                                    |
|o15 : PolynomialRing                                |
+----------------------------------------------------+
|i16 : I=ideal(y^2+x^3-x^2*z^2)                      |
|                                                    |
|               2 2    3    2                        |
|o16 = ideal(- x z  + x  + y )                       |
|                                                    |
|o16 : Ideal of R                                    |
+----------------------------------------------------+
|i17 : WS=whitneyStratify(I,AssocPrimes=>false)      |
|                                                    |
|o17 = MutableHashTable{...3...}                     |
|                                                    |
|o17 : MutableHashTable                              |
+----------------------------------------------------+
|i18 : peek WS                                       |
|                                                    |
|o18 = MutableHashTable{0 => {ideal (z, y, x)}      }|
|                       1 => {ideal (y, x)}          |
|                                    2 2    3    2   |
|                       2 => {ideal(x z  - x  - y )} |
+----------------------------------------------------+

Ways to use whitneyStratify:
============================

  * "whitneyStratify(Ideal)"
  * whitneyStratify(Ideal,ZZ) (missing documentation)
  * whitneyStratify(Ideal,ZZ,ZZ) (missing documentation)

For the programmer
==================

The object whitneyStratify, is a method function with options (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.

whitneyStratifyPol -- Computes a Whitney stratification of the real and complex varieties.
******************************************************************************************

  * Usage:
        whitneyStratifyPol(I)
  * Inputs:
      * I, an ideal (Macaulay2Doc), an ideal defining a closed
        subvariety of affine or projective space over a field.
  * Optional inputs (Macaulay2Doc),:
      * Algorithm (missing documentation) => ..., default value "saturate",
      * Print (missing documentation) => ..., default value false,
  * Outputs:
      * WS, a mutable hash table (Macaulay2Doc), a hash
        table indexed by (complex) dimension, with the entry of (complex)
        dimension $i$ consisting of a list of prime ideals. The strata of
        $V(I)$ are the connected components of the difference between the
        variety defined by WS#i and that defined by WS#(i-1).

Description
===========

For a variety $X$ this command computes a Whitney stratification WS where WS#i
is a list of strata closures in (complex) dimension $i$; for a prime ideal $P$
in WS#i the associated open (connected) strata is given by the connected
components of $V(P)-Z$ where $Z$ is the union of the varieties defined by the
entries of WS#(i-1).

This function uses an algorithm based on the computation of polar varieties and
is probabilistic (unlike the conormal based whitneyStratify which is
deterministic).

There are several options which can be used to change how the polar varieties
are computed and which may be faster on some examples.

We demonstrate the method for the Whitney umbrella below. Note that the polar
variety method always generates unnecessary strata (which are random) and need
not be present in a minimal Whitney stratification.

+-----------------------------------------------------------------------------+
|i1 : R=QQ[x..z]                                                              |
|                                                                             |
|o1 = R                                                                       |
|                                                                             |
|o1 : PolynomialRing                                                          |
+-----------------------------------------------------------------------------+
|i2 : I=ideal(y^2+x^3-x^2*z^2)                                                |
|                                                                             |
|              2 2    3    2                                                  |
|o2 = ideal(- x z  + x  + y )                                                 |
|                                                                             |
|o2 : Ideal of R                                                              |
+-----------------------------------------------------------------------------+
|i3 : WS1=whitneyStratifyPol I                                                |
|                                                                             |
|o3 = MutableHashTable{...3...}                                               |
|                                                                             |
|o3 : MutableHashTable                                                        |
+-----------------------------------------------------------------------------+
|i4 : peek WS1                                                                |
|                                                                             |
|o4 = MutableHashTable{0 => {ideal (z, y, x), ideal (16082425z - 41802274, y, |
|                      1 => {ideal (y, x)}                                    |
|                                   2 2    3    2                             |
|                      2 => {ideal(x z  - x  - y )}                           |
|-----------------------------------------------------------------------------|
|x), ideal (16082425z + 41802274, y, x)}}                                     |
+-----------------------------------------------------------------------------+

Note that since the "extra" strata are random we can generate the minimal
stratification by taking the common strata closures which appear in two
different calculations (with high probability). We do this as follows:

+-----------------------------------------------------------------------------+
|i5 : WS2=whitneyStratifyPol I                                                |
|                                                                             |
|o5 = MutableHashTable{...3...}                                               |
|                                                                             |
|o5 : MutableHashTable                                                        |
+-----------------------------------------------------------------------------+
|i6 : peek WS2                                                                |
|                                                                             |
|o6 = MutableHashTable{0 => {ideal (z, y, x), ideal (69602258z - 116427849, y,|
|                      1 => {ideal (y, x)}                                    |
|                                   2 2    3    2                             |
|                      2 => {ideal(x z  - x  - y )}                           |
|-----------------------------------------------------------------------------|
|x), ideal (69602258z + 116427849, y, x)}}                                    |
+-----------------------------------------------------------------------------+
|i7 : WS=new MutableHashTable from for k in keys WS1 list                     |
|                                                                             |
|o7 = MutableHashTable{...3...}                                               |
|                                                                             |
|o7 : MutableHashTable                                                        |
|-----------------------------------------------------------------------------|
|k=>toList((set(WS1)#k)*(set(WS2)#k))                                         |
+-----------------------------------------------------------------------------+
|i8 : peek WS                                                                 |
|                                                                             |
|o8 = MutableHashTable{0 => {ideal (z, y, x)}      }                          |
|                      1 => {ideal (y, x)}                                    |
|                                   2 2    3    2                             |
|                      2 => {ideal(x z  - x  - y )}                           |
+-----------------------------------------------------------------------------+

There are also several different options to perform the underlying polar
variety calculations. The default algorithm uses the M2 saturate command to
compute the polar variteies, this option is Algorithm=>. The other options are:
Algorithm=>"msolve" and  Algorithm=>"M2F4". The Algorithm=>"msolve" only works
in versions 1.25.06 and above of Macaulay2. The  Algorithm=>"M2F4" is mostly
beneficial when working over a finite field. Note that over a finite field we
can still sometimes obtain useful information about the stratification, but the
coefficients appearing in the resulting polynomials may (or likely will) be
incorrect.

+-----------------------------------------------------------------------------+
|i9 : WS3=whitneyStratifyPol(I,Algorithm=>"msolve")                           |
|                                                                             |
|o9 = MutableHashTable{...3...}                                               |
|                                                                             |
|o9 : MutableHashTable                                                        |
+-----------------------------------------------------------------------------+
|i10 : peek WS3                                                               |
|                                                                             |
|o10 = MutableHashTable{0 => {ideal (z, y, x), ideal (8715011z - 19247903, y, |
|                       1 => {ideal (y, x)}                                   |
|                                    2 2    3    2                            |
|                       2 => {ideal(x z  - x  - y )}                          |
|-----------------------------------------------------------------------------|
|x), ideal (8715011z + 19247903, y, x)}}                                      |
+-----------------------------------------------------------------------------+
|i11 : R=ZZ/32749[x..z]                                                       |
|                                                                             |
|o11 = R                                                                      |
|                                                                             |
|o11 : PolynomialRing                                                         |
+-----------------------------------------------------------------------------+
|i12 : I=ideal(y^2+x^3-x^2*z^2)                                               |
|                                                                             |
|               2 2    3    2                                                 |
|o12 = ideal(- x z  + x  + y )                                                |
|                                                                             |
|o12 : Ideal of R                                                             |
+-----------------------------------------------------------------------------+
|i13 : WS3=whitneyStratifyPol(I,Algorithm=>"M2F4")                            |
|                                                                             |
|o13 = MutableHashTable{...3...}                                              |
|                                                                             |
|o13 : MutableHashTable                                                       |
+-----------------------------------------------------------------------------+

On harder examples the whitneyStratifyPol can be much faster than other methods
and often the option Algorithm=>"msolve" will be the fastest (the msolve option
is not currently set as default since the msolve package is a new addition to
M2).

Ways to use whitneyStratifyPol:
===============================

  * "whitneyStratifyPol(Ideal)"

For the programmer
==================

The object whitneyStratifyPol, is a method function with options (Macaulay2Doc).

-------------------------------------------------------------------------------

The source of this document is in WhitneyStratifications.m2:1665:0.