Remove trivial sequential alias chains Example: dsk = {'x': 1, 'y': Alias('x'), 'z': Alias('y')} resolve_aliases(dsk, {'z'}, {'x': {'y'}, 'y': {'z'}}) == {'z': 1}
(dsk: dict, keys: set, dependents: dict)
| 274 | |
| 275 | |
| 276 | def resolve_aliases(dsk: dict, keys: set, dependents: dict) -> dict: |
| 277 | """Remove trivial sequential alias chains |
| 278 | |
| 279 | Example: |
| 280 | |
| 281 | dsk = {'x': 1, 'y': Alias('x'), 'z': Alias('y')} |
| 282 | |
| 283 | resolve_aliases(dsk, {'z'}, {'x': {'y'}, 'y': {'z'}}) == {'z': 1} |
| 284 | |
| 285 | """ |
| 286 | if not keys: |
| 287 | raise ValueError("No keys provided") |
| 288 | dsk = dict(dsk) |
| 289 | work = list(keys) |
| 290 | seen = set() |
| 291 | while work: |
| 292 | k = work.pop() |
| 293 | if k in seen or k not in dsk: |
| 294 | continue |
| 295 | seen.add(k) |
| 296 | t = dsk[k] |
| 297 | if isinstance(t, Alias): |
| 298 | target_key = t.target |
| 299 | # Rules for when we allow to collapse an alias |
| 300 | # 1. The target key is not in the keys set. The keys set is what the |
| 301 | # user is requesting and by collapsing we'd no longer be able to |
| 302 | # return that result. |
| 303 | # 2. The target key is in fact part of dsk. If it isn't this could |
| 304 | # point to a persisted dependency and we cannot collapse it. |
| 305 | # 3. The target key has only one dependent which is the key we're |
| 306 | # currently looking at. This means that there is a one to one |
| 307 | # relation between this and the target key in which case we can |
| 308 | # collapse them. |
| 309 | # Note: If target was an alias as well, we could continue with |
| 310 | # more advanced optimizations but this isn't implemented, yet |
| 311 | if ( |
| 312 | target_key not in keys |
| 313 | and target_key in dsk |
| 314 | # Note: whenever we're performing a collapse, we're not updating |
| 315 | # the dependents. The length == 1 should still be sufficient for |
| 316 | # chains of these aliases |
| 317 | and len(dependents[target_key]) == 1 |
| 318 | ): |
| 319 | tnew = dsk.pop(target_key).copy() |
| 320 | |
| 321 | dsk[k] = tnew |
| 322 | tnew.key = k |
| 323 | if isinstance(tnew, Alias): |
| 324 | work.append(k) |
| 325 | seen.discard(k) |
| 326 | else: |
| 327 | work.extend(tnew.dependencies) |
| 328 | |
| 329 | work.extend(t.dependencies) |
| 330 | return dsk |
| 331 | |
| 332 | |
| 333 | class TaskRef: |