# How to find combination of linear transformations to recover original Matrix with wrap?

**URL:** https://discourse.julialang.org/t/how-to-find-combination-of-linear-transformations-to-recover-original-matrix-with-wrap/48186
**Category:** Specific Domains
**Tags:** question
**Created:** [October 11, 2020, 11:33pm UTC](https://discourse.julialang.org/t/how-to-find-combination-of-linear-transformations-to-recover-original-matrix-with-wrap/48186 "2020-10-11T23:33:19Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)
#### Post date: [October 11, 2020, 11:33pm UTC](https://discourse.julialang.org/t/how-to-find-combination-of-linear-transformations-to-recover-original-matrix-with-wrap/48186/1 "2020-10-11T23:33:19Z")

</div>

Given

```julia
obj::CircularArray{Bool,2,BitMatrix}

```

that has undergone a combination of linear transformations

- `circshift(A::AbstractMatrix, shifts::NTuple{2,<:Integer})`
- `rotl90(A::AbstractMatrix, k::Integer)`
- `reverse(A::AbstractMatrix; dims::Integer)`
- `permutedims(m::AbstractMatrix)`

how can I recover the inverse of linear transformations?

For example,

```julia
a = [3, 4, 21, 22, 25, 26, 28, 29, 30, 45, 46, 47, 49, 53, 54, 71, 72, 75, 78, 97, 101, 102, 123, 124, 125, 126, 149, 150, 175, 550, 551, 574, 575, 576, 577, 598, 599, 600, 603, 622]
b = [11, 17, 37, 38, 39, 40, 41, 63, 64, 65, 89, 464, 488, 489, 490, 512, 513, 514, 515, 516, 536, 542, 560, 561, 564, 567, 568, 584, 585, 586, 588, 590, 592, 593, 594, 610, 611, 614, 617, 618]
A = reshape((1:25^2) .∈ Ref(a), 25, 25)
B = reshape((1:25^2) .∈ Ref(b), 25, 25)

```

Here is `A`  
 ![Screen Shot 2020-10-11 at 6.59.45 PM](https://global.discourse-cdn.com/julialang/original/3X/0/d/0d4717a95ce32048c691f2f1b6fa36e9e159e1fb.png)  
and `B`  
 ![Screen Shot 2020-10-11 at 7.00.07 PM](https://global.discourse-cdn.com/julialang/original/3X/b/f/bf010cc4e81f1352d8106ff74bf0654999550e2d.png)

Through inspecting the images I was able to find that `A` can be obtained from `B` through

```julia
findall(A) == findall(circshift(B, (11, 3)))

```

However, I am still missing the mathematical foundation to implement the following:

```julia
function magic(A::AbstractMatrix{<:Boo},
               B::AbstractMatrix{<:Boo})
    # Finds R ∋ B * R == A
end

```

```julia
trans = qd_rigid(A, B, (25, 25), 3π/2)[1]

```

Gives the `AffineMap` I can use to recover the image! 🙂

---

<div class="post-metadata">

### Author: ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)
#### Post date: [October 12, 2020, 12:31am UTC](https://discourse.julialang.org/t/how-to-find-combination-of-linear-transformations-to-recover-original-matrix-with-wrap/48186/2 "2020-10-12T00:31:12Z")

</div>

RegisterQD.jl was the right solution!

---

<div class="post-metadata">

### Author: ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)
#### Post date: [October 12, 2020, 4:48am UTC](https://discourse.julialang.org/t/how-to-find-combination-of-linear-transformations-to-recover-original-matrix-with-wrap/48186/3 "2020-10-12T04:48:01Z")

</div>

Ended up filling an issue since it seems there are some issues with using `qd_rigid` directly.

---

<div class="post-metadata">

### Author: ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)
#### Post date: [October 12, 2020, 8:33am UTC](https://discourse.julialang.org/t/how-to-find-combination-of-linear-transformations-to-recover-original-matrix-with-wrap/48186/4 "2020-10-12T08:33:22Z")

</div>

Keep in mind that RegisterQD is not set up to test reflections (unless you provide an initial guess that has a reflection in it) or periodic boundary conditions. You might be able to pass in a custom array type that implements whatever boundary conditions you want, though; the key requirement is on the behavior of `warp` from ImageTransformations.

---

<div class="post-metadata">

### Author: ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)
#### Post date: [October 12, 2020, 5:27pm UTC](https://discourse.julialang.org/t/how-to-find-combination-of-linear-transformations-to-recover-original-matrix-with-wrap/48186/5 "2020-10-12T17:27:39Z")

</div>

Based on that feedback,

```julia
"""
    find_affine(A::CircularArray, B::CircularArray)
"""
function find_affine(A::CircularArray, B::CircularArray)
    size(A) == size(B) || throw(ArgumentError("A and B have different dimensions"))
    for (rev, rot, pd, r, c) in product(0:2, 0:1:3, false:true, 0:size(A, 1), 0:size(A, 2))
        x = rev == 0 ? B : reverse(B, dims = rev)
        x = rotl90(x, rot)
        x = pd ? permutedims(x) : x
        circshift(x, (r, c)) == A && return (rev, rot, pd, r, c)
    end
    throw(ErrorException("No match!"))
end

```

Maybe brute forcing it isn’t too bad. The search space is 16,224. Going to test that and then from that I can construct the affine map (`Transformation`) for it.
