# How to give an one-time assignment to a large parametric matrix?

**URL:** <https://discourse.julialang.org/t/how-to-give-an-one-time-assignment-to-a-large-parametric-matrix/75664>\
**Category:** General Usage\
**Tags:** zygote, matrices, autodiff\
**Created:** [February 2, 2022, 2:50pm UTC](https://discourse.julialang.org/t/how-to-give-an-one-time-assignment-to-a-large-parametric-matrix/75664 "2022-02-02T14:50:55Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![GtJeight](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gtjeight/32/33422_2.png) [@GtJeight](https://discourse.julialang.org/u/GtJeight)\
**Post date:** [February 2, 2022, 2:50pm UTC](https://discourse.julialang.org/t/how-to-give-an-one-time-assignment-to-a-large-parametric-matrix/75664/1 "2022-02-02T14:50:56Z")

</div>

One-time assignment means something essentially equal to this:

```julia
function Mf(t)
    M=[t t^2;t^3 t^4] #assignment, just list all its entries in the bracket
end

```

but not this:

```julia
function Mf(t)
    M=zeros(2,2) #assignment
    M[1,1]=t #mutation
    M[1,2]=t^2
    M[2,1]=t^3
    M[2,2]=t^4
    M
end

```

When a large parametric matrix(e.g. M(t) is 1000x1000) is needed, I can’t assign it by the first way(list all 1000x1000 entries), but to use the second way

```julia
function Mf(t)
    M=zeros(1000,1000) #assignment
    for i=1:1000
        for j=1:1000
            M[i,j]=m_ij(t) #mutation, m_ij(t) is an explicit expression depends on i,j,t
        end
    end
    M
end

```

However, if I need to compute gradient of a loss function of M(t) by Zygote, e.g. L(t)=det(M(t))

```julia
gradient(t->det(Mf(t)), t0)[1]

```

an error will occur since **mutating array in differetiated function is not allowed** , means that I shouldn’t adopt the second way

```julia
ERROR: LoadError: Mutating arrays is not supported -- called setindex!(::Matrix{Float64}, _...)

```

So I wonder if there is a method of assigning a large parametric matrix at one-time without mutating it (the explicit expression of m\_ij(t) is known)  
I failed to find the answer by searching and watching tutorials. I would be grateful if someone tells the solution.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [February 2, 2022, 3:11pm UTC](https://discourse.julialang.org/t/how-to-give-an-one-time-assignment-to-a-large-parametric-matrix/75664/2 "2022-02-02T15:11:57Z")

</div>

You can do this, though I don’t know if that solves the specific error you are facing:

```julia
julia> M = [exp(i*j) for i in 1:10, j in 1:10]
10×10 Matrix{Float64}:
     2.71828 7.38906 20.0855 54.5982 … 1096.63 2980.96 8103.08 22026.5
     7.38906 54.5982 403.429 2980.96 1.2026e6 8.88611e6 6.566e7 4.85165e8
    20.0855 403.429 8103.08 1.62755e5 1.31882e9 2.64891e10 5.32048e11 1.06865e13
    54.5982 2980.96 1.62755e5 8.88611e6 1.44626e12 7.8963e13 4.31123e15 2.35385e17
   148.413 22026.5 3.26902e6 4.85165e8 1.58601e15 2.35385e17 3.49343e19 5.18471e21
   403.429 1.62755e5 6.566e7 2.64891e10 … 1.73927e18 7.01674e20 2.83075e23 1.14201e26
  1096.63 1.2026e6 1.31882e9 1.44626e12 1.90735e21 2.09166e24 2.29378e27 2.51544e30
  2980.96 8.88611e6 2.64891e10 7.8963e13 2.09166e24 6.23515e27 1.85867e31 5.54062e34
  8103.08 6.566e7 5.32048e11 4.31123e15 2.29378e27 1.85867e31 1.5061e35 1.2204e39
 22026.5 4.85165e8 1.06865e13 2.35385e17 2.51544e30 5.54062e34 1.2204e39 2.68812e43

```

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [February 2, 2022, 3:29pm UTC](https://discourse.julialang.org/t/how-to-give-an-one-time-assignment-to-a-large-parametric-matrix/75664/3 "2022-02-02T15:29:32Z")

</div>

I ignore the actual matrix types involved. Would the following work for you?  
The overhead of one-time allocation should be amortized over the full run.

- generate a first matrix with your mutating method
- create a second, non-mutating matrix as (deep) copy
- empty your first matrix
- use the second one in Zygote

---

<div class="post-metadata">

**Author:** ![GtJeight](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gtjeight/32/33422_2.png) [@GtJeight](https://discourse.julialang.org/u/GtJeight)\
**Post date:** [February 2, 2022, 3:43pm UTC](https://discourse.julialang.org/t/how-to-give-an-one-time-assignment-to-a-large-parametric-matrix/75664/4 "2022-02-02T15:43:06Z")

</div>

This actually working, thanks sir!

```julia
using Zygote

function Mf(t)
    M=[t^(2i+j-2) for i in 1:2, j in 1:2]
end

gradient(t->sum(Mf(t)),2)[1]

```

---

<div class="post-metadata">

**Author:** ![GtJeight](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gtjeight/32/33422_2.png) [@GtJeight](https://discourse.julialang.org/u/GtJeight)\
**Post date:** [February 2, 2022, 3:45pm UTC](https://discourse.julialang.org/t/how-to-give-an-one-time-assignment-to-a-large-parametric-matrix/75664/5 "2022-02-02T15:45:37Z")

</div>

I am not sure if you mean to do this

```julia
using Zygote

function Nf(t)
    N=zeros(2,2)
    N[1,1]=t
    N[1,2]=t^2
    N[2,1]=t^3
    N[2,2]=t^4
    N2=deepcopy(N)
end

gradient(t->sum(Nf(t)),2)[1]

```

this code reports the same error

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [February 2, 2022, 4:24pm UTC](https://discourse.julialang.org/t/how-to-give-an-one-time-assignment-to-a-large-parametric-matrix/75664/6 "2022-02-02T16:24:03Z")

</div>

My answer tried to provide a parametrically built, immutable matrix.  
You actually want to pass a function generating a parameterized matrix, as did @lmiq .
