<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def update(self, points, pointvol=0., vol_dec=0.5, vol_check=2., rstate=None, bootstrap=0, pool=None, mc_integrate=False):
 """ Update the set of ellipsoids to bound the collection of points. Parameters points : `~numpy.ndarray` with shape (npoints, ndim) The set of points to bound. pointvol : float, optional The minimum volume associated with each point. Default is `0.`. vol_dec : float, optional The required fractional reduction in volume after splitting an ellipsoid in order to to accept the split. Default is `0.5`. vol_check : float, optional The factor used when checking if the volume of the original bounding ellipsoid is large enough to warrant `> 2` splits via `ell.vol > vol_check * nlive * pointvol`. Default is `2.0`. rstate : `~numpy.random.RandomState`, optional `~numpy.random.RandomState` instance. bootstrap : int, optional The number of bootstrapped realizations of the ellipsoids. The maximum distance to the set of points "left out" during each iteration is used to enlarge the resulting volumes. Default is `0`. pool : user-provided pool, optional Use this pool of workers to execute operations in parallel. mc_integrate : bool, optional Whether to use Monte Carlo methods to compute the effective volume and fractional overlap of the final union of ellipsoids with the unit cube. Default is `False`. """


        if rstate is None:
            rstate = np.random

        if not HAVE_KMEANS:
            raise ValueError("scipy.cluster.vq.kmeans2 is required "
                             "to compute ellipsoid decompositions.")

        npoints, ndim = points.shape

        # Calculate the bounding ellipsoid for the points, possibly
        # enlarged to a minimum volume.
        firstell = bounding_ellipsoid(points, pointvol=pointvol)

        # Recursively split the bounding ellipsoid using `vol_check`
        # until the volume of each split no longer decreases by a
        # factor of `vol_dec`.
        ells = _bounding_ellipsoids(points, firstell, pointvol=pointvol,
                                    vol_dec=vol_dec, vol_check=vol_check)

        # Update the set of ellipsoids.
        self.nells = len(ells)
        self.ells = ells
        self.ctrs = np.array([ell.ctr for ell in self.ells])
        self.covs = np.array([ell.cov for ell in self.ells])
        self.ams = np.array([ell.am for ell in self.ells])
        self.vols = np.array([ell.vol for ell in self.ells])
        self.vol_tot = sum(self.vols)

        # Compute expansion factor.
        expands = np.array([ell.expand for ell in self.ells])
        vols_orig = self.vols / expands
        vol_tot_orig = sum(vols_orig)
        self.expand_tot = self.vol_tot / vol_tot_orig

        # Use bootstrapping to determine the volume expansion factor.
        if bootstrap > 0:

            # If provided, compute bootstraps in parallel using a pool.
            if pool is None:
                M = map
            else:
                M = pool.map
            ps = [points for it in range(bootstrap)]
            pvs = [pointvol for it in range(bootstrap)]
            vds = [vol_dec for it in range(bootstrap)]
            vcs = [vol_check for it in range(bootstrap)]
            args = zip(ps, pvs, vds, vcs)
            expands = list(M(_ellipsoids_bootstrap_expand, args))

            # Conservatively set the expansion factor to be the maximum
            # factor derived from our set of bootstraps.
            expand = max(expands)

            # If our ellipsoids are overly constrained, expand them.
            if expand > 1.:
                vs = self.vols * expand**ndim
                self.scale_to_vols(vs)

        # Estimate the volume and fractional overlap with the unit cube
        # using Monte Carlo integration.
        if mc_integrate:
            self.vol, self.funit = self.monte_carlo_vol(return_overlap=True)