Repository: ivy-llc/ivy

Issue:
triplet_margin_loss



Discussion:

Resolving patch:
diff --git a/ivy/functional/frontends/paddle/nn/functional/distance.py b/ivy/functional/frontends/paddle/nn/functional/distance.py
--- a/ivy/functional/frontends/paddle/nn/functional/distance.py
+++ b/ivy/functional/frontends/paddle/nn/functional/distance.py
@@ -1 +0,0 @@
-# local
diff --git a/ivy/functional/frontends/paddle/nn/functional/loss.py b/ivy/functional/frontends/paddle/nn/functional/loss.py
--- a/ivy/functional/frontends/paddle/nn/functional/loss.py
+++ b/ivy/functional/frontends/paddle/nn/functional/loss.py
@@ -24,6 +24,18 @@ def _get_reduction_func(reduction):
     return ret
 
 
+def _pairwise_distance(x1, x2, *, p=2.0, eps=1e-06, keepdim=False):
+    x1, x2 = paddle.promote_types_of_paddle_inputs(x1, x2)
+    x1_dim = len(x1.shape)
+    x2_dim = len(x2.shape)
+    if x1_dim > x2_dim:
+        output_dim = x1_dim
+    else:
+        output_dim = x2_dim
+
+    return ivy.vector_norm(x1 - x2 + eps, ord=p, axis=output_dim - 1, keepdims=keepdim)
+
+
 @with_supported_dtypes(
     {"2.5.1 and below": ("float32",)},
     "paddle",
@@ -230,3 +242,43 @@ def margin_ranking_loss(input, other, label, margin=0.0, reduction="mean", name=
     out = ivy.atleast_1d(out)
 
     return out
+
+
+@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle")
+@to_ivy_arrays_and_back
+def triplet_margin_loss(
+    input,
+    positive,
+    negative,
+    margin=1.0,
+    p=2.0,
+    eps=1e-06,
+    swap=False,
+    reduction="mean",
+):
+    reduction = _get_reduction_func(reduction)
+
+    a_dim = input.ndim
+    p_dim = positive.ndim
+    n_dim = negative.ndim
+
+    ivy.assertions.check_true(
+        a_dim == p_dim and p_dim == n_dim,
+        lambda: (
+            "The input, positive, and negative tensors are expected to have "
+            f"the same number of dimensions, but got: input {a_dim}D, "
+            f"positive {p_dim}D, and negative {n_dim}D inputs"
+        ),
+    )
+
+    dist_positive = _pairwise_distance(input, positive, p=p, eps=eps)
+    dist_negative = _pairwise_distance(input, negative, p=p, eps=eps)
+    if swap:
+        dist_swap = _pairwise_distance(positive, negative, p=p, eps=eps)
+        dist_negative = ivy.minimum(dist_negative, dist_swap)
+    loss = ivy.maximum(
+        dist_positive - dist_negative + ivy.array(margin), ivy.array(0.0)
+    )
+
+    loss = reduction(loss).astype(input.dtype)
+    return loss


Test patch:
diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_loss.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_loss.py
--- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_loss.py
+++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_loss.py
@@ -391,3 +391,52 @@ def test_paddle_margin_ranking_loss(
         margin=margin,
         reduction=reduction,
     )
+
+
+@handle_frontend_test(
+    fn_tree="paddle.nn.functional.triplet_margin_loss",
+    dtype_and_inputs=helpers.dtype_and_values(
+        available_dtypes=helpers.get_dtypes("float"),
+        num_arrays=3,
+        allow_inf=False,
+        shared_dtype=True,
+        min_value=0.0,
+        max_value=1.0,
+        min_num_dims=1,
+        max_num_dims=2,
+        min_dim_size=1,
+    ),
+    margin=st.floats(min_value=1e-6, max_value=1e6),
+    p=st.integers(min_value=0, max_value=2),
+    swap=st.booleans(),
+    reduction=st.sampled_from(["none", "mean", "sum"]),
+    test_with_out=st.just(False),
+)
+def test_paddle_triplet_margin_loss(
+    dtype_and_inputs,
+    margin,
+    p,
+    swap,
+    reduction,
+    test_flags,
+    fn_tree,
+    backend_fw,
+    frontend,
+    on_device,
+):
+    input_dtype, x = dtype_and_inputs
+    helpers.test_frontend_function(
+        input_dtypes=[input_dtype[0], input_dtype[1], input_dtype[2]],
+        backend_to_test=backend_fw,
+        frontend=frontend,
+        test_flags=test_flags,
+        fn_tree=fn_tree,
+        on_device=on_device,
+        input=x[0],
+        positive=x[1],
+        negative=x[2],
+        margin=margin,
+        p=p,
+        swap=swap,
+        reduction=reduction,
+    )