# Merging two sets of relations by some rule

**URL:** <https://alloytools.discourse.group/t/merging-two-sets-of-relations-by-some-rule/407>\
**Category:** Uncategorized\
**Created:** [October 9, 2023, 2:18pm UTC](https://alloytools.discourse.group/t/merging-two-sets-of-relations-by-some-rule/407 "2023-10-09T14:18:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![brianhicks](https://yyz2.discourse-cdn.com/free1/user_avatar/alloytools.discourse.group/brianhicks/32/5_2.png) [@brianhicks](https://alloytools.discourse.group/u/brianhicks)\
**Post date:** [October 9, 2023, 2:18pm UTC](https://alloytools.discourse.group/t/merging-two-sets-of-relations-by-some-rule/407/1 "2023-10-09T14:18:32Z")

</div>

Say I have a `Document` with a `counts` field, like this:

```plaintext
open util/natural

sig ID {}

sig Document {
  counts: ID -> lone Natural
}

```

I’d like to merge any two documents by combining the `counts` and taking the max `Natural` for each `ID`. So if I have these documents, I want to merge them in this way:

| | **Document 0** | **Document 1** | **Merged** |
| --- | --- | --- | --- |
| **ID 0** | 1 | 2 | 2 |
| **ID 1** | 1 | 0 | 1 |

I’m having trouble with this! First I tried a set comprehension, which didn’t work (seems to be mostly about filtering rather than transforming?) Then I tried something like this:

```plaintext
fun merge[d1, d2: ID -> lone Natural]: (ID -> lone Natural) {
  let both = d1 + d2 | { kv: both }
}

```

That doesn’t work because `both` needs to be a unary set. Sure, ok, fair. But how _do_ you do this? I can think of plenty of ways to mess with the sets as a whole, but I’m having trouble finding a way to tell Alloy that I want to make a pairwise decision on all the relations in the set!

---

<div class="post-metadata">

**Author:** ![alcino](https://yyz2.discourse-cdn.com/free1/user_avatar/alloytools.discourse.group/alcino/32/25_2.png) [@alcino](https://alloytools.discourse.group/u/alcino)\
**Post date:** [October 10, 2023, 6:18am UTC](https://alloytools.discourse.group/t/merging-two-sets-of-relations-by-some-rule/407/2 "2023-10-10T06:18:13Z")

</div>

Hi,

You can define the resulting relation by comprehension. For example, you could use comprehension to summarize a relation that possibly contains many naturals per id, and then use it to merge the union of the two count relations:

```plaintext
fun summarize[ds : ID -> set Natural] : (ID -> lone Natural) {
	{i : ID, n : Natural | i->n in ds and n = max[i.ds] }
}

fun merge[d1, d2: ID -> lone Natural]: (ID -> lone Natural) {
  	summarize[d1+d2]
}

```

Best,  
Alcino

---

<div class="post-metadata">

**Author:** ![brianhicks](https://yyz2.discourse-cdn.com/free1/user_avatar/alloytools.discourse.group/brianhicks/32/5_2.png) [@brianhicks](https://alloytools.discourse.group/u/brianhicks)\
**Post date:** [October 10, 2023, 10:24am UTC](https://alloytools.discourse.group/t/merging-two-sets-of-relations-by-some-rule/407/3 "2023-10-10T10:24:23Z")

</div>

Ooh, ok, that makes sense. Thank you. The gap in my understanding here was that I got that `{ i : ID, n : Natural | … }` would be the cartesian product, but I didn’t think to limit that to the set of `ds` in the condition. Makes total sense now.
