# How to hand-craft an edge into a Pluto's a computational graph?

**URL:** <https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619>\
**Category:** Specific Domains\
**Tags:** question, pluto\
**Created:** [January 10, 2024, 12:52pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619 "2024-01-10T12:52:26Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![vvbond](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vvbond/32/10105_2.png) [@vvbond](https://discourse.julialang.org/u/vvbond)\
**Post date:** [January 10, 2024, 12:52pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/1 "2024-01-10T12:52:26Z")

</div>

Consider the following contrived example of a Pluto notebook:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/d/a/da7d7e73e585448f67a279e945dc211395bcee62.png)

First of all, I have a hard time even to visualise the corresponding computational graph. Below is my attempt to indicate by the dashed arrow that the computation of `sum(x)` is triggered by changes of `x` defined upstream, but not by changes in `n`:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/7/7/77e0f3972ae3ca2259d3dfda3923ad9d0f223de0.png)

Put in words, the middle node (the 3d cell) doesn’t trigger downstream computations: `sum(x)` (the 4th cell) is not recomputed whenever `n` changes its value.

This ill-defined behaviour is just a symptom. It is easy, of course, to link `n` to `sum(x)` to obtain a well-defined state in this case. My objective, however, is to understand how could I introduce an explicit edge between nodes/cells 3 and 4, without referencing upstream `n`.

What triggering technique could be used to this end?

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [January 10, 2024, 2:01pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/2 "2024-01-10T14:01:52Z")

</div>

I know this is probably not what you are looking for, but my answer would be to combine expressions into cells using `begin ... end` (like 1 and 3) or to introduce a function that returns a modified copy of `x` instead of the in-place modification that you have now.

---

<div class="post-metadata">

**Author:** ![vvbond](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vvbond/32/10105_2.png) [@vvbond](https://discourse.julialang.org/u/vvbond)\
**Post date:** [January 10, 2024, 2:28pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/3 "2024-01-10T14:28:28Z")

</div>

Yeah, of course. But, you’re right, it’s not what I’m after.  
(Thanks for looking into it, anyway.)

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [January 10, 2024, 3:44pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/4 "2024-01-10T15:44:40Z")

</div>

I think Pluto’s graph follows assignments, not necessarily modifications.

```julia
### A Pluto.jl notebook ###
# v0.19.36

using Markdown
using InteractiveUtils

# ╔═╡ 371228e6-afce-11ee-0e08-ffcab94f43bb
x = collect(1:10)

# ╔═╡ a0c5e59e-102b-4d04-a568-b19456a6d79a
n = 5

# ╔═╡ f59fac3f-6c9c-4b4e-87f6-44a80f036af0
y = if isodd(n)
    x[1:2:n] .= 42
    x
end

# ╔═╡ e75712ff-f50d-4f00-be5b-77408a49ece3
sum(y)

# ╔═╡ Cell order:
# ╠═371228e6-afce-11ee-0e08-ffcab94f43bb
# ╠═a0c5e59e-102b-4d04-a568-b19456a6d79a
# ╠═f59fac3f-6c9c-4b4e-87f6-44a80f036af0
# ╠═e75712ff-f50d-4f00-be5b-77408a49ece3

```

I don’t see how to add an assignment that catches reducing `n` yet.

Edit. ugh:

```julia
y = if isodd(n)
	y = copy(x)
	y[1:2:n] .= 42
	y
end

```

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [January 10, 2024, 4:06pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/5 "2024-01-10T16:06:56Z")

</div>

The core issue here is that modification have no deeper order. E.g.  
Consider cells like:

```julia
# cell 1
x = Ref(2)

# cell 2
x[] = 5

# cell 3
@show x

```

Then it is clear that cell 1 must be executed first becuase it defines the variable `x` used in the other cells. But there is no unambigous order of cells 2 and 3.

You can introduce “auxiliary variables” to establish an order like:

```julia
# cell 1
x = Ref(2)

# cell 2
x[] = 5; aux=nothing;

# cell 3
aux; @show x

```

---

<div class="post-metadata">

**Author:** ![vvbond](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vvbond/32/10105_2.png) [@vvbond](https://discourse.julialang.org/u/vvbond)\
**Post date:** [January 10, 2024, 4:28pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/6 "2024-01-10T16:28:00Z")

</div>

> I think Pluto’s graph follows assignments, not necessarily modifications.

Yep, good point. Thanks!

The proposed solution would work for this case, but it still misses the point.

---

<div class="post-metadata">

**Author:** ![vvbond](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vvbond/32/10105_2.png) [@vvbond](https://discourse.julialang.org/u/vvbond)\
**Post date:** [January 10, 2024, 4:47pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/7 "2024-01-10T16:47:16Z")

</div>

Correct! The issue is clear and there is no way to remove the unambiguity automatically. Hence the need to introduce an order explicitly.

Auxiliary variables solution is close. Yet, the goal here is to trigger the follow-up computations _only_ if the input modification actually did take place. I.e., in the given example, I seek to recompute `sum(x)` only when `x[1:2:n] .= 42` was actually executed.

I see now, that it was not clear from the initial description. Sorry.

The `if` block was meant to illustrate the problem: an `aux` variable put within the scope of `if` would result in the `aux not defined` error for even values of `n`.

That’s where I kinda stuck.

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [January 10, 2024, 4:57pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/8 "2024-01-10T16:57:53Z")

</div>

Is ‘undoing’ the modification of `x` when n becomes even or smaller a desired outcome?

---

<div class="post-metadata">

**Author:** ![vvbond](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vvbond/32/10105_2.png) [@vvbond](https://discourse.julialang.org/u/vvbond)\
**Post date:** [January 10, 2024, 5:50pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/9 "2024-01-10T17:50:44Z")

</div>

Nope, previously modified entries of `x` remain intact.

---

<div class="post-metadata">

**Author:** ![vvbond](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vvbond/32/10105_2.png) [@vvbond](https://discourse.julialang.org/u/vvbond)\
**Post date:** [January 10, 2024, 6:17pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/10 "2024-01-10T18:17:13Z")

</div>

Below, the closest I’ve got to to the required functionality so far.

The last bit is somewhat weird but it does the job: `sum(x)` is recomputed when either the whole vector `x` is re-assigned or a subset of its entries gets modified.

Thanks everyone for discussion! Please do let me know if you find of a better way to achieve the desired goal.

```julia
# ╔═╡ b6de62ec-afa8-11ee-3cab-c1aacaec6cb3
x = collect(1:10)

# ╔═╡ 10e03418-8a12-4cd9-9283-bf5bcad49618
n = 3

# ╔═╡ aa375da5-dba0-4a0e-8e96-3b0d80d32458
isodd(n) && (aux=nothing; x[1:2:n] .= 42)

# ╔═╡ 669e5597-2506-409d-b13c-39c81539e60a
if @isdefined aux
	sum(x)
else
	sum(x)
end

```

---

<div class="post-metadata">

**Author:** ![disberd](https://avatars.discourse-cdn.com/v4/letter/d/8edcca/32.png) [@disberd](https://discourse.julialang.org/u/disberd)\
**Post date:** [February 13, 2024, 2:55pm UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/11 "2024-02-13T14:55:02Z")

</div>

The part of Pluto analyzing expression and determining their order and graph has been recently moved to separate packages that are standalone registered in General:

> [@\[ANN\] ExpressionExplorer.jl and PlutoDependencyExplorer.jl – the internal reactivity algorithm of Pluto!](https://discourse.julialang.org/t/ann-expressionexplorer-jl-and-plutodependencyexplorer-jl-the-internal-reactivity-algorithm-of-pluto/109068):
>
> We just released two new packages! tada[ExpressionExplorer.jl](https://github.com/JuliaPluto/ExpressionExplorer.jl) (EE) – find all variables assigned and referenced in a piece of code. [PlutoDependencyExplorer.jl](https://github.com/JuliaPluto/PlutoDependencyExplorer.jl) (PDE) – sort a list of codes by execution order Both packages are quite small and load fast, with minimal dependencies. The packages were part of [Pluto’s](https://plutojl.org) source code, but we decided to release them separately so that they can be used in other projects! ExpressionExplorer Find all variables referenced and defined in an expression. Thi…

You might have a look there for more details or directly use them for your use case if relevant!

---

<div class="post-metadata">

**Author:** ![fonsp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fonsp/32/222349_2.png) [@fonsp](https://discourse.julialang.org/u/fonsp)\
**Post date:** [February 21, 2024, 9:00am UTC](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/12 "2024-02-21T09:00:33Z")

</div>

Fun question! The “official” answer to the question in the title is: create variables! Pluto only tracks assignments and references, so that’s the mechanism you need to use to tell Pluto about extra edges.

The [example from abraemer](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/5) will work, also when `n` is even.

```julia
x = collect(1:10)

n = 3

begin
    modification_done = nothing
    if isodd(n)
        x[1:2:n] .= 37
    end
end

begin
    # reference this variable to create the reactive edge
    modification_done
    sum(x)
end

```

But I think that a solution that uses `copy` [like contradict suggested](https://discourse.julialang.org/t/how-to-hand-craft-an-edge-into-a-plutos-a-computational-graph/108619/4) is probably better, as this eliminates any surprises when working on one of the intermediate cells.
