Repository: simpeg/simpeg

Issue:
Unassigned parent attributes in Regularizations
### Describe the issue:

I believe the structure of simpeg inheritance is causing issues. I have been trying to reproduce old codes from Simpeg 0.18.0 and do not believe the argument for 'gradient_type' is the Sparse regularization is working. It looks like this is due to inheritance and setters in the current simpeg, especially with the 'parent' attribute.

It seems that a lot of these classes that rely on complex and deep inheritance have had issues and could potentially be simplified. If this is not the case, it would be nice to put in some tests to make sure that these classes have the intended behavior.


### Reproducable code example:

```python
reg = regularization.VectorAmplitude(
    mesh,
    mapping=idenMap,
    active_cells=actv,
    reference_model_in_smooth=True,
    norms=[0.0, 2.0, 2.0, 2.0],
    gradient_type="total",
)
```


### Error message:

_No response_

### Runtime information:

Not applicable

### Context for the issue:

_No response_

Discussion:

Patch:
diff --git a/SimPEG/objective_function.py b/SimPEG/objective_function.py
index 3e2b347f3..28464bd66 100644
--- a/SimPEG/objective_function.py
+++ b/SimPEG/objective_function.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import numbers
 import numpy as np
 import scipy.sparse as sp
@@ -361,7 +363,12 @@ class ComboObjectiveFunction(BaseObjectiveFunction):
 
     """
 
-    def __init__(self, objfcts=None, multipliers=None, unpack_on_add=True):
+    def __init__(
+        self,
+        objfcts: list[BaseObjectiveFunction] | None = None,
+        multipliers=None,
+        unpack_on_add=True,
+    ):
         # Define default lists if None
         if objfcts is None:
             objfcts = []
@@ -382,6 +389,7 @@ class ComboObjectiveFunction(BaseObjectiveFunction):
             nP = None
 
         super().__init__(nP=nP)
+
         self.objfcts = objfcts
         self._multipliers = multipliers
         self._unpack_on_add = unpack_on_add
diff --git a/SimPEG/regularization/base.py b/SimPEG/regularization/base.py
index 656c1a257..4db6c4a1c 100644
--- a/SimPEG/regularization/base.py
+++ b/SimPEG/regularization/base.py
@@ -1665,8 +1665,13 @@ class WeightedLeastSquares(ComboObjectiveFunction):
             objfcts = kwargs.pop("objfcts")
 
         super().__init__(objfcts=objfcts, unpack_on_add=False, **kwargs)
+
+        for fun in objfcts:
+            fun.parent = self
+
         if active_cells is not None:
             self.active_cells = active_cells
+
         self.mapping = mapping
         self.reference_model = reference_model
         self.reference_model_in_smooth = reference_model_in_smooth


Test patch:
diff --git a/tests/base/test_regularization.py b/tests/base/test_regularization.py
index 82abaca79..6e7347978 100644
--- a/tests/base/test_regularization.py
+++ b/tests/base/test_regularization.py
@@ -680,6 +680,12 @@ class TestParent:
         with pytest.raises(TypeError, match=msg):
             regularization.parent = invalid_parent
 
+    def test_default_parent(self, regularization):
+        """Test setting default parent class to a BaseRegularization."""
+        mesh = discretize.TensorMesh([3, 4, 5])
+        parent = WeightedLeastSquares(mesh, objfcts=[regularization])
+        assert regularization.parent is parent
+
 
 class TestWeightsKeys:
     """