Skip to content

Commit acc0471

Browse files
Add transversal example (#790)
* Add files via upload * Add some comments * Add author credits --------- Co-authored-by: ThomSerg <[email protected]>
1 parent a0428ef commit acc0471

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

examples/transversals.ipynb

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"## Minimal transversals\n",
8+
"\n",
9+
"Let $\\mathcal{S}$ be a family of sets. A set $T$ is a *transversal* (or *hitting set*) of $\\mathcal{S}$ if $T$ intersects every $S\\in\\mathcal{S}$. The family of minimal transversals of $\\mathcal{S}$ is denoted by $\\text{Tr}(\\mathcal{S})$.\n",
10+
"\n",
11+
"The minimality of $T$ can be characterized by the following condition:\n",
12+
"If $x\\in T$, then $S\\cap T= \\{x\\}$ for some $S\\in\\mathcal{S}$. "
13+
]
14+
},
15+
{
16+
"cell_type": "code",
17+
"execution_count": null,
18+
"metadata": {},
19+
"outputs": [],
20+
"source": [
21+
"\"\"\"\n",
22+
"Author: Nandor Sieben (https://github.com/nandorsieben)\n",
23+
"\"\"\"\n",
24+
"\n",
25+
"import cpmpy as cp\n",
26+
"from typing import List"
27+
]
28+
},
29+
{
30+
"cell_type": "code",
31+
"execution_count": 7,
32+
"metadata": {},
33+
"outputs": [],
34+
"source": [
35+
"def Tr(sets:List):\n",
36+
" \"\"\"\n",
37+
" Given a family of sets, returns all minimal transversals.\n",
38+
" \"\"\"\n",
39+
" X = {s for S in sets for s in S} # all elements across all sets, deduplicated\n",
40+
" \n",
41+
" # Decision Variables\n",
42+
" t = {x:cp.boolvar() for x in X} # whether to inlude an element into the transversal\n",
43+
"\n",
44+
" # Model\n",
45+
" model = cp.Model()\n",
46+
"\n",
47+
" # Constraints\n",
48+
" # 1) transversal\n",
49+
" for S in sets:\n",
50+
" model += cp.any([t[s] for s in S]) # must hit each set by intersecting with at least one element\n",
51+
" # 2) minimal transversal\n",
52+
" # for each element x, if it is included in our transversal T, \n",
53+
" # there must exist a set S which intersects with T in only that single element x\n",
54+
" for x in X: \n",
55+
" model += t[x].implies(\n",
56+
" cp.any(\n",
57+
" [cp.all([~t[s] for s in S if s!=x]) \n",
58+
" for S in sets if x in S]\n",
59+
" )\n",
60+
" )\n",
61+
" \n",
62+
" # Solve and collect results\n",
63+
" result = []\n",
64+
" model.solveAll(display=lambda: result.append({a for a in t if t[a].value()}))\n",
65+
" return result "
66+
]
67+
},
68+
{
69+
"cell_type": "code",
70+
"execution_count": 8,
71+
"metadata": {},
72+
"outputs": [
73+
{
74+
"data": {
75+
"text/plain": [
76+
"[{2}, {1, 3}]"
77+
]
78+
},
79+
"execution_count": 8,
80+
"metadata": {},
81+
"output_type": "execute_result"
82+
}
83+
],
84+
"source": [
85+
"Tr([{1,2},{2,3}])"
86+
]
87+
},
88+
{
89+
"cell_type": "code",
90+
"execution_count": 9,
91+
"metadata": {},
92+
"outputs": [
93+
{
94+
"data": {
95+
"text/plain": [
96+
"[{2, 3}, {1, 2}]"
97+
]
98+
},
99+
"execution_count": 9,
100+
"metadata": {},
101+
"output_type": "execute_result"
102+
}
103+
],
104+
"source": [
105+
"Tr([{2},{1,3}])"
106+
]
107+
},
108+
{
109+
"cell_type": "code",
110+
"execution_count": 10,
111+
"metadata": {},
112+
"outputs": [
113+
{
114+
"data": {
115+
"text/plain": [
116+
"[{1, 4, 5}, {1, 3, 4}, {1, 5, 8}, {1, 5, 7}, {2, 7}, {2, 8}, {2, 4}]"
117+
]
118+
},
119+
"execution_count": 10,
120+
"metadata": {},
121+
"output_type": "execute_result"
122+
}
123+
],
124+
"source": [
125+
"Tr([{1,2},{2,4,5},{2,3,5},{4,7,8}])"
126+
]
127+
}
128+
],
129+
"metadata": {
130+
"kernelspec": {
131+
"display_name": ".venv",
132+
"language": "python",
133+
"name": "python3"
134+
},
135+
"language_info": {
136+
"codemirror_mode": {
137+
"name": "ipython",
138+
"version": 3
139+
},
140+
"file_extension": ".py",
141+
"mimetype": "text/x-python",
142+
"name": "python",
143+
"nbconvert_exporter": "python",
144+
"pygments_lexer": "ipython3",
145+
"version": "3.12.8"
146+
}
147+
},
148+
"nbformat": 4,
149+
"nbformat_minor": 4
150+
}

0 commit comments

Comments
 (0)