Repository: keras-team/keras (python)

Issue:
SVD operation failed when compute_uv=False (TF backend)
### Problem raised

TensorFlow `tf.linalg.svd()` with compute_uv=False returns a single tensor containing the singular values, and not three tensors "s, u, v" when compute_uv=True.
However, code line 188 in `keras/src/backend/tensorflow/linalg.py` always expects three returned tensors, even if only one is expected when compute_uv=False. It raises a ValueError: not enough values to unpack.
https://github.com/keras-team/keras/blob/6abd865eaa1af31d8fc60a573992a9e75f570bb8/keras/src/backend/tensorflow/linalg.py#L188)

### Tested versions:

- Keras 3.4.1
- TensorFlow 2.17.0

### Code to reproduce:

```python
import keras
keras.ops.svd([[1.0, 0.0], [2.0, 0.0]], compute_uv=False)
```

Pull request:
Fix `svd` with `compute_uv=False`
Fix #20094 

Patch:
diff --git a/keras/src/backend/tensorflow/core.py b/keras/src/backend/tensorflow/core.py
index a551785fc..6d8c748e7 100644
--- a/keras/src/backend/tensorflow/core.py
+++ b/keras/src/backend/tensorflow/core.py
@@ -223,7 +223,11 @@ def compute_output_spec(fn, *args, **kwargs):
 
 
 def cond(pred, true_fn, false_fn):
-    return tf.cond(pred, true_fn=true_fn, false_fn=false_fn)
+    if isinstance(pred, tf.Variable):
+        return tf.cond(pred, true_fn=true_fn, false_fn=false_fn)
+    return tf.__internal__.smart_cond.smart_cond(
+        pred, true_fn=true_fn, false_fn=false_fn
+    )
 
 
 def vectorized_map(function, elements):
diff --git a/keras/src/backend/tensorflow/linalg.py b/keras/src/backend/tensorflow/linalg.py
index 636586d14..2813303a4 100644
--- a/keras/src/backend/tensorflow/linalg.py
+++ b/keras/src/backend/tensorflow/linalg.py
@@ -185,6 +185,8 @@ def solve_triangular(a, b, lower=False):
 
 
 def svd(x, full_matrices=True, compute_uv=True):
+    if compute_uv is False:
+        return tf.linalg.svd(x, full_matrices=full_matrices, compute_uv=False)
     s, u, v = tf.linalg.svd(
         x, full_matrices=full_matrices, compute_uv=compute_uv
     )
diff --git a/keras/src/backend/torch/linalg.py b/keras/src/backend/torch/linalg.py
index 17a710867..7bd2a5a05 100644
--- a/keras/src/backend/torch/linalg.py
+++ b/keras/src/backend/torch/linalg.py
@@ -68,9 +68,7 @@ def solve_triangular(a, b, lower=False):
 
 def svd(x, full_matrices=True, compute_uv=True):
     if not compute_uv:
-        raise NotImplementedError(
-            "`compute_uv=False` is not supported for torch backend."
-        )
+        return torch.linalg.svdvals(x)
     return torch.linalg.svd(x, full_matrices=full_matrices)
 
 


Test patch:
diff --git a/keras/src/ops/core_test.py b/keras/src/ops/core_test.py
index f0dc56150..9610ba06b 100644
--- a/keras/src/ops/core_test.py
+++ b/keras/src/ops/core_test.py
@@ -703,6 +703,19 @@ class CoreOpsCorrectnessTest(testing.TestCase, parameterized.TestCase):
                 lambda: ops.zeros((4,)),
             )
 
+    def test_cond_raw_bool_compile(self):
+        class ExampleLayer(layers.Layer):
+            def call(self, x, training=False):
+                return ops.cond(training, lambda: x, lambda: x * 2.0)
+
+        model = models.Sequential([ExampleLayer()])
+        model.compile(
+            optimizer=optimizers.SGD(), loss=losses.MeanSquaredError()
+        )
+        x = np.ones((2, 4), dtype=np.float32)
+        y = np.zeros((2, 4), dtype=np.float32)
+        model.evaluate(x, y, batch_size=2)
+
     def test_unstack(self):
         rng = np.random.default_rng(0)
         x = rng.uniform(size=(2, 3, 4))
diff --git a/keras/src/ops/linalg_test.py b/keras/src/ops/linalg_test.py
index bc04ab0b0..8e722dd41 100644
--- a/keras/src/ops/linalg_test.py
+++ b/keras/src/ops/linalg_test.py
@@ -534,6 +534,10 @@ class LinalgOpsCorrectnessTest(testing.TestCase, parameterized.TestCase):
         # High tolerance due to numerical instability
         self.assertAllClose(x_reconstructed, x, atol=1e-3)
 
+        # Test `compute_uv=False`
+        s_no_uv = linalg.svd(x, compute_uv=False)
+        self.assertAllClose(s_no_uv, s)
+
     @parameterized.named_parameters(
         ("b_rank_1", 1, None),
         ("b_rank_2", 2, None),