CS 51500 Homework 1 Solutions
CS 51500 Homework 1 Solutions
Problem 0
I would like to thank my wife Preeti Agarwal whose understanding of matrices
helped me with deriving the solutions for a number of problems in the homework
I would also like to thank Professor Gleich, Nadim and Sai for providing help with
the classes and homeworks. I also took references and directionfrom wikipedia,
particularly for Problem 8. Lastly I took a lot of reference from Julia online
documentation
1
Problem 1.1
2 3 5 1 2 −3 25 −51 21
7 11 13 −4 −5 −6 = 54 −145 30
17 19 23 7 −8 9 102 −245 42
Julia code:
A=[
2 3 5
7 11 13
17 19 23
]
B = [
1 2 -3
-4 -5 -6
7 -8 9
]
A*B
2
Problem 1.2
xT y = 500500.0
Julia code:
x=ones(1000, 1)
y=1:1000
x'y
3
Problem 1.3
1.5 2.0 3.0
T
1.5 2.0 3.0
ex = 1.5
2.0 3.0
1.5 2.0 3.0
1.5 1.5 1.5 1.5
xeT = 2.0 2.0 2.0 2.0
3.0 3.0 3.0 3.0
Julia code:
x=[1.5 2 3]'
e = ones(4, 1)
display(e*x')
display(x*e')
Output:
julia>
4×3 Matrix{Float64}:
1.5 2.0 3.0
1.5 2.0 3.0
1.5 2.0 3.0
1.5 2.0 3.0
3×4 Matrix{Float64}:
1.5 1.5 1.5 1.5
2.0 2.0 2.0 2.0
3.0 3.0 3.0 3.0
4
Problem1.4
−5 4 2
e2 xT =
−5 4 2
−5
xeT1 = 4
2
Julia code:
x=[-5 4 2]'
e1 = ones(1,1)
e2 = ones(2,1)
display(e2*x')
display(x*e1')
Output:
julia>
2×3 Matrix{Float64}:
-5.0 4.0 2.0
-5.0 4.0 2.0
3×1 Matrix{Float64}:
-5.0
4.0
2.0
5
Problem 1.5
2 3 5 10
7 11 13 e3 = 31
17 19 23 59
2 3 5
eT3 7 11 13 = 26 33 41
17 19 23
Julia code:
x=[
2 3 5
7 11 13
17 19 23
]
e1 = ones(1,1)
e3 = ones(3,1)
display(x*e3)
display(e3'*x)
Output:
julia>
3×1 Matrix{Float64}:
10.0
31.0
59.0
1×3 Matrix{Float64}:
26.0 33.0 41.0 2.0
6
Problem 1.6
2 0 0 1 2 3 2 4 6
0 1/2 0 10 8 6 = 5 4 3
0 0 −1 −2 −2 −2 2 2 2
Julia code:
x=[
2 0 0
0 1/2 0
0 0 -1
]
y=[
1 2 3
10 8 6
-2 -2 -2
]
display(x*y)
Output:
julia>
3×3 Matrix{Float64}:
2.0 4.0 6.0
5.0 4.0 3.0
2.0 2.0 2.0
7
Problem 2.1
Consider
the 2-D array as mentioned in the problem:
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1
1 2 3 4 5 6 7 8 9 1 3 1 4 1 5 1
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
. . . . . . . . . . . . . . . .
9 8 7 6 5 4 3 2 1 0 1 1 1 2 1 3
8
Problem 2.2
Given 4096 X 10000 matrix, where each column represents a grayscale
image of 64X64 pixels.
9
Problem 2.3
Given that A is the matrix from part 1.
Considering the new matrix B = AT A [16x16 matrix]
10
Problem 2.4
Given that A is the matrix from part 2.
Considering the new matrix B = AT A [10000X10000 matrix]
11
Problem 3.1
Two diagonal matrices can only be multiplied if they have same dimensions,
n
X
C i,k = Ai,j B j,k (1)
j=1
Ai,j = 0, ∀i 6= j
Ai,j 6= 0, ∀i = j
C i,j = 0, ∀i 6= j
C i,j = Ai,i B i,i , ∀i = j
12
Problem 3.2
Two upper triangular matrices can only be multiplied if they have same dimensions,
n
X
C i,k = Ai,j B j,k (2)
j=1
Ai,j = 0, ∀i > j
Ai,j 6= 0, ∀i ≤ j
Ai,j 6= 0 if i ≤ j
and
B j,k 6= 0 if j ≤ k
For C i,j 6= 0, both Ai,j and B j,k must be non-zero for some j
⇒ C i,j 6= 0 only when i ≤ j and j ≤ k
C i,k = 0, ∀i > k
C i,k 6= 0, ∀i ≤ k
13
Problem 3.3
Let A be a diagonal matrix and B be a general matrix,
C = AB means,
n
X
C i,k = Ai,j B j,k (3)
j=1
Ai,j = 0, ∀i 6= j
Ai,j 6= 0, ∀i = j
14
Problem 3.4
Let A be a diagonal matrix and B be a general matrix,
C = BA means,
n
X
C i,k = B i,j Aj,k ∀0 ≤ i, k ≤ n (4)
j=1
Ai,j = 0, ∀i 6= j
Ai,j 6= 0, ∀i = j
15
Problem 4.1
1 a 1 −a
Given matrices A = and B =
0 1 0 1
1 + 0 −a + a
AB =
0+0 0+1
1 0
⇒ AB = = I2
0 1
Also
1+0 a−a
BA =
0+0 0+1
1 0
⇒ BA = = I2
0 1
16
Problem 4.2
I A I −A
Given matrices P = and Q =
0 I 0 I
Applying blockwise matrix multiplication rules
I + 0 −A + A
PQ =
0+0 0+I
I 0
⇒ PQ = =I
0 I
Similarly
I +0 A−A
QP =
0+0 0+I
I 0
⇒ PQ = =I
0 I
17
Problem 4.3
A B
Given matrices P = where A and C are invertible
0 C
P can be decomposed into a matrix-product as:
A 0 I A−1 B
P =
0 C 0 I
−1 −1
A−1 B
I A 0
⇒ P −1 = (using(AB)−1 = A−1 B −1 )
0 I 0 C
I −A−1 B A−1
−1 0
⇒P =
0 I 0 C −1
−1
−A−1 BC −1
−1 A
⇒P = (Soln )
0 C −1
18
Problem 5.1
Given F and G are square diagonal matrices. Lets say they are of size n × n
Their product H = F G can be written as:
n
X
H i,k = F i,j Gj,k
j=1
F i,j = 0, ∀i 6= j
F i,j 6= 0, ∀i = j
H i,j = 0, ∀i 6= j
H i,j = F i,j Gi,j , ∀i = j
H i,j = 0, ∀i 6= j
19
Problem 5.2
Given,
q(x) = Diag((I − H)x)(I + H)x (5)
1 − h1,1 −h1,2 ... −h1,n x1 1 + h1,1 h1,2 ... h1,n x1
−h2,1 1 − h2,2 ... −h2,n x2 h2,1 1 + h2,2 ... h2,n x2
q(x) = Diag
.. .. .. .. .. .. .. .. .. ..
. . . . . . . . . .
−hn,1 −hn,2 ... 1 − hn,n xn hn,1 hn,2 ... 1 + hn,n xn
x1 − h1,1 x1 − h1,2 x2 . . . − h1,n xn x1 + h1,1 x1 + h1,2 x2 + . . . + h1,n xn
x2 − h2,1 x1 − h2,2 x2 . . . − h2,n xn x2 + h2,1 x1 + h2,2 x2 + . . . + h2,n xn
= Diag
.. ..
. .
xn − hn,1 x1 − hn,2 x2 . . . − hn,n xn xn + hn,1 x1 + hn,2 x2 + . . . + hn,n xn
Pn Pn
x1 − j h1,j xj
...
x1 + j h1,j xj
0 0
Pn Pn
0 x2 − j h2,j xj ... 0 x2 + j h2,j xj
=
.. ..
. Pn
P.n
0 0 . . . xn − j hn,j xj xn + j hn,j xj
Pn Pn
x21 − ( j h1,j xj )2 x21 ( j h1,j xj )2
x22 − ( nj h2,j xj )2 x22 ( nj h2,j xj )2
P P
= = .. −
.. ..
. .
Pn .
n
x2n − ( j hn,j xj )2 x2n ( j hn,j xj )2
P
20
Problem 5.3
Given,
yT q(x) = xT Cx (6)
Rearranging the vectors x, Hx and y (both are of same length), we can write,
xT (Diag(y) − H T Diag(y)H)x = xT Cx
21
Problem 6.1
Sparse Matrix showing adjacencies A:
10×10 SparseMatrixCSC{Int64, Int64} with 48 stored entries:
. . 1 . . . . . . 1
. . 1 . . . . . . 1
1 1 . . 1 1 . . . 1
. . . . 1 1 1 1 1 1
. . 1 1 . . 1 1 1 1
. . 1 1 . . 1 1 . 1
. . . 1 1 1 . 1 . 1
. . . 1 1 1 1 . . 1
. . . 1 1 . . . . 1
1 1 1 1 1 1 1 1 1 .
22
Problem 6.2
Plot of neighbor connections for 10 persons:
23
Problem 6.3
We need to fill in the missing code in the evolves teps function so that for the
given initial vector of infected as x0, probability of infecting a neighbor as p and
an adjacency matrix A Given the conditions:
p = 0.2
x0 = zeros(size(A,1))
x0[1] = 1
evolve_steps(x0, p, A, 10)
24
Problem 6.4.i
Plot of Expected number of infections at 20 iterations:
ExpectedInfected = sum(X[:,2:end],dims=1)
display(ExpectedInfected)
plot(ExpectedInfected', legend = false, markershape = :ltriangle, w = 3)
xlabel!("Iteration")
ylabel!("Expected number of infected")
savefig("/Users/akshyag/Documents/Purdue/CS515_Homeworks/JuliaCodes/ExpectedInfected10_20steps")
25
Problem [Link]
Looking at the plots in the previous problem answer (6.4.i),
I feel that the plot indeed show the expected number of infections resulting from
an initial set of infections.
Running the simulation sufficient number of times, we can observe that the plots
ultimately converges.
In a real world scenario, ultimately all the persons would get infected (unless
isolated clusters are formed - because of vaccinations, lockdowns etc).
In case of this intuitive expected number of infections at any iteration, this is
covered. Because correctly modeled, all of the xi will converge to 1. And the
sum of expected columns would then converge to the number of people in the
simulation.
Thus this model of expected number of infected at an iteration is a sound one.
26
Problem 6.5.i
Code for the new approximated evolution steps. The rationale for taking a max
is because the probability of getting infected does not reduce as the iterations
proceed and can only increase as the infections grow.
"""
Run k steps of the approximate evolution and return the results as a matrix.
Each column of the matrix has the probabilities that the node
is infected under the `wrong` evolve function.
The first column of X is the initial vector x0.
At each iteration, we make sure the probabilities are at least x0 and these
are fixed.
"""
function approx_evolve_steps(x0::Vector, p::Real, A::AbstractMatrix, k::Int)
Y = zeros(length(x0),k+1)
Y[:, 1] = x0
for i=1:k
Y[:,i+1] = max.(p.*(A*Y[:,i]),x0)
end
return Y
end
27
Problem [Link]
Plots of different values of ρ, comparing the exact and approximate models.
28
Problem [Link]
From the plots in Problem [Link] solution, we can see that the plots start diverging
after ρ = 0.5
29
Problem 6.6
Code for 1000 node network with infections starting at node 1000
[Link]!(10) # ensure repeatable results...
A,xy = spatial_network(1000, 2)
p = 0.2
x0 = zeros(size(A,1))
x0[1000] = 1
X=evolve_steps(x0, p, A, 10)
Y=approx_evolve_steps(x0, p, A, 10)
display(sum(X[:,2:end],dims=1)[end])
display(sum(Y[:,2:end],dims=1)[end])
We notice the following results:
ρ Exact Approximate
0.05 1.47931 1.48714
0.1 3.88078 4.44701
0.15 19.69975 43.91785
0.2 62.03265 492.21783
30
Problem 6.7
Code used to generate the expected values:
"""
Function to calculate expected number of infections
for exact and approximate models given a vector of p,
initial infections vector x0, number of steps to run
and the adjacency matrix
"""
function simulate_expected_infections_10iter(A::AbstractMatrix, x0::Vector, pVector::Vector{Float64})
exact = Float64[]
approx = Float64[]
for i=1:size(pVector,1)
X=evolve_steps(x0, pVector[i], A, 10)
Y=approx_evolve_steps(x0, pVector[i], A, 10)
push!(exact, sum(X[:,2:end],dims=1)[end])
push!(approx, sum(Y[:,2:end],dims=1)[end])
end
return exact, approx
end
Evaluations:
Social Distancing 0%
ρ Exact Approximate
0.05 1.47931 1.48714
0.1 3.88078 4.44701
0.15 19.69975 43.91785
0.2 62.03265 492.21783
Social Distancing 10%
ρ Exact Approximate
0.05 1.47268 1.48032
0.1 3.72681 4.24232
0.15 18.1778 39.1121
0.2 57.3423 428.62
Social Distancing 20%
ρ Exact Approximate
0.05 1.44329 1.44925
0.1 3.19047 3.51014
0.15 12.9564 23.9737
0.2 41.6802 232.104
Social Distancing 30%
ρ Exact Approximate
0.05 1.41041 1.41545
0.1 2.66461 2.85352
0.15 7.88834 12.3597
0.2 24.7874 92.109
Social Distancing 40%
ρ Exact Approximate
0.05 1.31856 1.32110
0.1 2.19239 2.27393
0.15 5.43858 7.083111
0.2 16.3768 39.5507
31
Problem 6.7(continued)
Social Distancing 50%
ρ Exact Approximate
0.05 1.19099 1.19186
0.1 1.52555 1.54015
0.15 2.27787 2.41471
0.2 4.573 5.76687
Social Distancing 60%
ρ Exact Approximate
0.05 1.18397 1.1848
0.1 1.47751 1.49016
0.15 2.02066 2.12222
0.2 3.21915 3.92562
Thus we can clearly see that with the increase in the amount of social distancing,
we can drastically bring down the number of infected and the rate of spread of
infection.
32
Problem 6.8
Wearing of masks will directly effect the probability of getting infected in case we
come in close proximity of the infected neighbor.
We need to cover the case when either the person or neighbor or both or neither
wear masks.
Consider probability of infecting others while wearing a mask as αmask_save_others
Consider probability of getting infected while wearing a mask as αmask_self _saf ety
Consider probability of a person wearing a mask as ρwear_mask
So now instead of probability of getting infected, we have some extra qualification:
33
Problem 7.1
Given the transition matrix T as a sparse-matrix in I, J , V (co-ordinates) format.
Here,
T i,j = Probability of transition from state j to state i
x100 = 0
34
Problem 7.1 (continued)
Now, since the bases of ladders and tops of chutes are positions on which we do
not stop (for ladders, we go to their tops and for chutes we go to their bases),
We can assume any number for xi for such positions. For simplicity sake, lets
set this to 1. This is ok because we have all 0’s in the rows of matrix T 0 for such
positions.
Thus we can write the previous set of equations as (combining with all the data
about xi we have so far):
x101 = 1 + T 0101 x
x100 = 0
x99 = 1 + T 099 x
x98 = 1 + T 098 x
x97 = 1 + T 097 x
..
.
x2 = 1 + T 02 x
x1 = 1 + T 01 x
Or, to generalize
x100 = 0
xi = 1 + T 0i x where i = 101, 1, 2, . . . , 98, 99
Ix − T 0 x = [1 1 1 . . . 1 1 0]0
⇒ (I − T 0 )x = [1 1 1 . . . 1 1 0]0
⇒ x = (I − T 0 )−1 [1 1 1 . . . 1 1 0]0
35
Problem 7.1 (continued)
We can solve this equation in Julia through following code:
using CSV, DataFrames, SparseArrays, Plots
Ivec = CLMatrixDF[!,1]
Jvec = CLMatrixDF[!,2]
Vvec = CLMatrixDF[!,3]
xc = CLMatrixCoords[!,1]
yc = CLMatrixCoords[!,2]
# the sparse matrix representation of chutes and ladders game transition matrix
T = sparse(Ivec, Jvec, Vvec, 101, 101)
# Starting state = 101
# Ending state = 100
Id101 = zeros(101,101)
Id101[diagind(Id101)] .= 1
b=ones(101)
b[end-1] = 0
x = (Id101 - T')\b
y = hcat(1:length(x), x)
sorted_x = y[sortperm(y[:,2]), :]
display(sorted_x[end-10:end, :]) # To list starting points where the expected no. of steps is max
Output:
julia>
11×2 Matrix{Float64}:
13.0 37.8362
12.0 38.2165
11.0 38.643
8.0 38.9844
10.0 39.1129
7.0 39.2315
6.0 39.464
3.0 39.5749
101.0 39.5984
5.0 39.6719
2.0 40.0714
We can see that starting points 2, 5, 101, 3, 6, 7 and 10 all have the expected
number of steps as 40 (considering we need a whole number of steps, because we
cannot play a fractional turn)
36
Problem 7.2
One way to decide how many iterations to run is to stop when the new value to
be added to the final answer is too small to matter. In the code we supplied an
upper bound to number of iterations because we do not want to get caught with
a non-converging series.
From the output, we got that 999 iterations were needed to get upto this point
The code to iteratively arrive at the expected length of the game:
function expected_length_of_game(k, T)
p_k = zeros(101,1)
p_k[101] = 1 # initial state.
expected_len = 0
for i=1:k-1
p_k=T*p_k
# we can stop early if i*p_k is too small ~ eps(Float64)
if (p_k[100] != 0 && i*p_k[100] < eps(Float64))
println("Further iterations will not make a difference.\nIteration=", i)
break;
end
expected_len += i*p_k[100]
end
return expected_len
end
@show expected_length_of_game(2000, T)
Output is:
Further iterations will not make a difference.
Iteration=999
expected_length_of_game(2000, T) = 39.598369794090615
37
Problem 8.1
To write the linear system of equations for n = 3
Given boundary conditions for this case can be written as:
u(x0 , yj ) = u(x3 , yj ) = u(xi , y0 ) = u(xi , y3 ) = 0.
38
Problem 8.1(continued)
Now since the above matrix does not show a lot of structure, We can notice that
there are following structures:
1. There are -4s along main diagonal
2. There are 1s in sub-diagonal and super-diagonal
3. There are 1s in the diagonal three diagonal below and three diagonals above
the main diagonal
Since the other u(xi , yj ) are 0, any linear combination of those will not effect the
respective f (xi , yj ) values.
Thus we can complete the diagonals that were mentioned above and have a more
structured matrix linear equation as:
−4 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0
1 −4 1 0 0 1 0 0 0 0 0 0 0 0 0 0
0
1 −4 1 0 0 1 0 0 0 0 0 0 0 0 0
0
0 1 −4 1 0 0 1 0 0 0 0 0 0 0 0
1
0 0 1 −4 1 0 0 1 0 0 0 0 0 0 0
0
1 0 0 1 −4 1 0 0 1 0 0 0 0 0 0
0
0 1 0 0 1 −4 1 0 0 1 0 0 0 0 0
0
0 0 1 0 0 1 −4 1 0 0 1 0 0 0 0 u = n2 ×f
0
0 0 0 1 0 0 1 −4 1 0 0 1 0 0 0
0
0 0 0 0 1 0 0 1 −4 1 0 0 1 0 0
0
0 0 0 0 0 1 0 0 1 −4 1 0 0 1 0
0
0 0 0 0 0 0 1 0 0 1 −4 1 0 0 1
0
0 0 0 0 0 0 0 1 0 0 1 −4 1 0 0
0
0 0 0 0 0 0 0 0 1 0 0 1 −4 1 0
0 0 0 0 0 0 0 0 0 0 1 0 0 1 −4 1
0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 −4
We can add further structure by removing some 1s from the sub and super
diagonals so that the sub matrices can be written as I 4×4
Hence finally we can write the equation as:
−4 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0
1 −4 1 0 0 1 0 0 0 0 0 0 0 0 0 0
0
1 −4 1 0 0 1 0 0 0 0 0 0 0 0 0
0
0 1 −4 0 0 0 1 0 0 0 0 0 0 0 0
1
0 0 0 −4 1 0 0 1 0 0 0 0 0 0 0
0
1 0 0 1 −4 1 0 0 1 0 0 0 0 0 0
0
0 1 0 0 1 −4 1 0 0 1 0 0 0 0 0
0
0 0 1 0 0 1 −4 0 0 0 1 0 0 0 0 u = n2 ×f
0
0 0 0 1 0 0 0 −4 1 0 0 1 0 0 0
0
0 0 0 0 1 0 0 1 −4 1 0 0 1 0 0
0
0 0 0 0 0 1 0 0 1 −4 1 0 0 1 0
0
0 0 0 0 0 0 1 0 0 1 −4 0 0 0 1
0
0 0 0 0 0 0 0 1 0 0 0 −4 1 0 0
0
0 0 0 0 0 0 0 0 1 0 0 1 −4 1 0
0 0 0 0 0 0 0 0 0 0 1 0 0 1 −4 1
0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 −4
39
Problem 8.2
From above we can see that, the matrix has a structure as:
A I 0 0 −4 1 0 0 1 0 0 0
I A I 0 1 −4 1 0 0 1 0 0
0 I A I Where A = 0
and I = (4×4 identity matrix)
1 −4 1 0 0 1 0
0 0 I A 0 0 1 −4 0 0 0 1
We can see that:
1. Diagonal is all -4
2. Sub-diagonal is repeated ones vector with every nth element set to 0
3. Super-diagonal has similar structure as sub-diagonal
4. There are diagonals of ones which are n+1 away from main diagonal
Code:
using SparseArrays, Random, Plots
40
Problem 8.2
The sparse matrix and function vector for n = 10 and f (x, y) = 1 was generated
by:
n = 10
f(::Float64, ::Float64) = 1
A1, f1 = laplacian(n, f)
41
Problem 8.3
For solving and plotting for u(x, y), we ran the code:
n = 10
f(::Float64, ::Float64) = 1
A1, f1 = laplacian(n, f)
u1 = A1\f1
u_mat = reshape(u1, n+1, n+1)
surface([0:10], [0:10], u_mat)
savefig("SurfacePlot_n10")
42
Problem 8.4
As in the solution of Problem 8.1, we have the matrix equation as
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0
0 0 0 0 −4 1 0 0 1 0 0 0 0 0 0
f (1, 1)
0
0 0 0 0 1 −4 0 0 0 1 0 0 0 0 0
f (1, 2)
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 u = n 2 × 0
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0
0 0 0 0 1 0 0 0 −4 1 0 0 0 0 0
f (2, 1)
0
0 0 0 0 0 1 0 0 1 −4 0 0 0 0 0
f (2, 2)
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Removing the 0 rows from both sides, we can re-write the equations as
−4 1 1 0 u1,1 f (1, 1)
1
−4 0 1 × u1,2 = n2 × f (1, 2)
1 0 −4 1 u2,1 f (2, 1)
0 1 1 −4 u2,2 f (2, 2)
43
Problem 9.1
Code:
""" Returns y = A'*x where A is given by the CSC arrays
colptr, rowval, nzval, m, n and x is the vector. """
function csc_transpose_matvec(colptr, rowval, nzval, m, n, x)
y = zeros(n) # allocate output
for j=1:length(colptr)-1 # for each column ...
for nzi=colptr[j]:colptr[j+1]-1 # for each entry in the column
i = rowval[nzi]
v = nzval[nzi]
# For transpose, row and cols are interchanged
# So we go over all elements of the columns from original
# matrix (ie rows for all range of nzi in the give iteration)
# and multiply them with the value and store it in the
# columns location j
y[j] += v*x[i]
end
end
return y
end
println("B'*x1 = ",B'*x1)
println("csc_transpose_matvec([Link], [Link], [Link], 7, 6, x1) = ",
csc_transpose_matvec([Link], [Link], [Link], 7, 6, x1))
Output:
julia>
B'*x1 = [0; 56; 138; 118; 98; 200]
csc_transpose_matvec([Link], [Link], [Link], 7, 6, x1) = [0.0, 56.0, 138.0, 118.0, 98.0, 200.0]
44
Problem 9.2
Code:
""" Returns = A[:,i]'*x where A is given by the CSC arrays
colptr, rowval, nzval, m, n and x is the vector. """
function csc_column_projection(colptr, rowval, nzval, m, n, i, x)
y = 0
for nzi = colptr[i]:colptr[i+1]-1
i = rowval[nzi]
v = nzval[nzi]
# We go over all elements of the column from original
# matrix (ie rows for all range of nzi for given colptr)
# and multiply them with the nz-value and store it
y += v*x[i]
end
return y
end
@show B[:,3]'*x1
@show csc_column_projection([Link], [Link], [Link], 7, 6, 3, x1)
Output:
(B[:, 3])' * x1 = [138]
csc_column_projection([Link], [Link], [Link], 7, 6, 3, x1) = 138
45
Problem 9.3
Code:
""" Returns rho = A[:,i]'*A[:,j] where A is given by the CSC arrays
colptr, rowval, nzval, m, n and i, and j are the column indices. """
function csc_col_col_prod(colptr, rowval, nzval, m, n, i, j)
y = 0
nzi = colptr[i]
nzj = colptr[j]
while nzi <= colptr[i+1]-1 && nzj <= colptr[j+1]-1
rowi = rowval[nzi]
rowj = rowval[nzj]
if rowi == rowj
y += nzval[nzi]*nzval[nzj]
nzi += 1
nzj += 1
@show B[:,2]'*B[:,3]
@show csc_col_col_prod([Link], [Link], [Link], 7, 6, 2, 3 )
@show B[:,3]'*B[:,6]
@show csc_col_col_prod([Link], [Link], [Link], 7, 6, 3, 6 )
Output:
(B[:, 2])' * B[:, 3] = 208
csc_col_col_prod([Link], [Link], [Link], 7, 6, 2, 3) = 208
(B[:, 3])' * B[:, 6] = 180
csc_col_col_prod([Link], [Link], [Link], 7, 6, 3, 6) = 180
46
Problem 9.4
Code:
""" Returns rho = A[i,j] where A is given by the CSC arrays
colptr, rowval, nzval, m, n and i, and j are the column indices. """
function csc_lookup(colptr, rowval, nzval, m, n, i, j)
for nzi = colptr[j]:colptr[j+1]-1
if i == rowval[nzi]
return nzval[nzi]
end
end
return 0
end
@show B[1,2]
@show csc_lookup([Link], [Link], [Link], 7, 6, 1, 2)
@show B[4,3]
@show csc_lookup([Link], [Link], [Link], 7, 6, 4, 3)
@show B[6,5]
@show csc_lookup([Link], [Link], [Link], 7, 6, 6, 5)
Output:
julia>
B[1, 2] = 16
csc_lookup([Link], [Link], [Link], 7, 6, 1, 2) = 16
B[4, 3] = 9
csc_lookup([Link], [Link], [Link], 7, 6, 4, 3) = 9
B[6, 5] = 0
csc_lookup([Link], [Link], [Link], 7, 6, 6, 5) = 0
47
Problem 9.5
Code:
""" Returns x = A[i,:] where A is given by the CSC arrays
colptr, rowval, nzval, m, n and i is the row index . """
function csc_lookup_row(colptr, rowval, nzval, m, n, i)
y = zeros(n) # since row will have n elements
for j=1:length(colptr)-1 # for each column ...
for nzi=colptr[j]:colptr[j+1]-1 # for each entry in the column
if i == rowval[nzi]
y[j] = nzval[nzi]
end
end
end
return y
end
display(A[2,:])
display(csc_lookup_row([Link], [Link], [Link], 7, 6, 2))
Output:
julia>
6-element Vector{Int64}:
0
0
10
12
0
0
6-element Vector{Float64}:
0.0
0.0
10.0
12.0
0.0
0.0
48