---
title: "Reproducing the illustrative example"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Reproducing the illustrative example}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 6,
                      fig.height = 4)
library(simOutrank)
```

This vignette reproduces the illustrative example of Delias et al. (2023),
"Improving the non-compensatory trace-clustering decision process". The log
ships with the
package as `illustrative_log`.

## The scenario

A service desk handles two customer tiers, `"GOLD"` and `"NORMAL"` (the paper
calls the latter "Blue"), each with its own process flow, and records each
customer's satisfaction. There are 25 fictitious customers (Table 1 of the
paper), numbered in Table 1's order; the last two (cases `24` and `25`) are
deliberate outliers whose flow does not fit either tier.

```{r log}
traces <- as_traces(illustrative_log, "case_id", "activity", "timestamp")
table(illustrative_log$status[!duplicated(illustrative_log$case_id)],
      illustrative_log$satisfaction[!duplicated(illustrative_log$case_id)])
```

## The criteria (Table 2)

The paper defines four criteria with the following parameters. "Status" and
"Satisfaction" are binary criteria; a veto of -1 in the paper means "no veto",
which we express as `veto = NULL`.

| Criterion | Direction | Similarity | Indifference | Veto | Weight |
|-----------|-----------|-----------:|-------------:|-----:|-------:|
| Activities | similarity | 0.8 | 0.7 | 0.4 | 0.2 |
| Transitions (edit distance) | dissimilarity | 2 | 3 | 6 | 0.2 |
| Status | similarity | 1 | 0 | -- | 0.3 |
| Satisfaction | similarity | 1 | 0 | -- | 0.3 |

```{r criteria}
criteria <- list(
  crit_activity_profile(weight = 0.2, indifference = 0.7, similarity = 0.8,
                        veto = 0.4),
  crit_edit_distance(weight = 0.2, similarity = 2, indifference = 3, veto = 6),
  crit_nominal("status", weight = 0.3),
  crit_nominal("satisfaction", weight = 0.3)
)
sim <- outrank_similarity(traces, criteria)
sim
```

Cases that share the same trace, tier and satisfaction are fully similar under
every criterion, so their credibility is exactly 1:

```{r identical}
sim$S[c("1", "2", "3"), c("1", "2", "3")]
```

## Run 1: clustering without domain knowledge

The paper targets four clusters (tier x satisfaction). This is the baseline
"Run 1", with no constraints or trimming.

```{r run1}
clust <- cluster_traces(sim, k = 4, seed = 42)
split(names(clust$memberships), clust$memberships)
```

The clusters recover the main structure of the process: cases with an identical
profile always land together, the two satisfaction levels are largely
separated, and the short-path Gold customers form their own group.

## A note on exact reproduction

The paper reports its memberships as a shaded figure (Table 3) rather than as a
table, so they are not machine-readable here. `simOutrank` also standardises on
the corrected Ng-Jordan-Weiss row normalisation (see `?cluster_traces`), which
can differ from the normalisation used to produce the original figure. We
therefore reproduce the *pipeline and its structural conclusions* rather than a
bit-for-bit membership vector; the credibility matrix `S` itself is pinned as a
regression fixture in the package's tests.

Runs 2 and 3 of the paper -- separating the tiers with a cannot-link constraint
and trimming the outliers -- are covered in the
[robustness vignette](robustness.html).

## Reference

Delias, P., Doumpos, M., Grigoroudis, E. and Matsatsinis, N. (2023). Improving
the non-compensatory trace-clustering decision process. *International
Transactions in Operational Research*, 30(3), 1387–1406.
doi:10.1111/itor.13062
```
