def algo_bagging():
    """
    Returns an exam-style explanation of the Bagging algorithm,
    including how bootstrap samples are created, how the bagged
    predictor is formed, and how Train MSE and Test MSE are computed.
    """
    text = """
ALGORITHM: BAGGING WITH DECISION TREES

Consider a training dataset D = {(x_i, y_i) : i = 1, ..., n} and let B denote
the number of bootstrap samples to be drawn.

For each b = 1, ..., B a bootstrap dataset of size n is generated by sampling
with replacement from the original data. Each of these B datasets serves as the
basis for fitting a separate decision tree. Denote the fitted response from the
b-th tree at observation i by ŷ_ib.

Once the B trees are constructed, the bagged estimate for the i-th observation is
that obtained by averaging the B individual predictions:
        ŷ_i^bag = (1 / B) * Σ_{b=1}^B ŷ_ib
for regression.  
For classification, the final prediction is obtained by majority vote across the
B trees.

To estimate the training MSE using bagging, the bagged fitted values ŷ_i^bag are
substituted into the usual expression for mean squared error:
        Train MSE = (1 / (n - p)) * Σ_{i=1}^n (y_i - ŷ_i^bag)^2
where p represents the number of estimated parameters (for trees, p is often
treated implicitly, and the expression reduces to an average squared deviation).

To compute the test MSE, the test observations x_i^test are passed through each
of the B fitted trees to obtain B predicted values for each test point, and the
bagged prediction is again their average. Substituting the bagged predictions into
        Test MSE = (1 / (n - p)) * Σ_{i=1}^n (y_i - ŷ_i^bag)^2
gives the estimated prediction error on the test set. The key idea is that every
test point receives B predictions, and the average of these forms the bagged
estimator used in the MSE calculation.
"""
    return text
