We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Introduction to Programming for Business Analytics - Exercise 5: Advanced Data Types

00:00

Formal Metadata

Title
Introduction to Programming for Business Analytics - Exercise 5: Advanced Data Types
Title of Series
Number of Parts
22
Author
License
CC Attribution 4.0 International:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Identifiers
Publisher
Release Date
Language
Producer
Computer animationLecture/Conference
Computer animationLecture/Conference
Computer animationLecture/Conference
Computer animationLecture/Conference
Computer animation
Computer animationLecture/Conference
Computer animationLecture/Conference
Computer animation
Computer animationLecture/Conference
Computer animation
Lecture/Conference
Computer animation
Computer animationLecture/Conference
Computer animation
Computer animationLecture/Conference
Computer animation
Computer animation
Computer animationLecture/Conference
Lecture/Conference
Computer animation
Computer animationLecture/Conference
Computer animation
Lecture/ConferenceComputer animation
Computer animationLecture/Conference
Computer animationLecture/Conference
Computer animation
Lecture/ConferenceComputer animation
Lecture/ConferenceComputer animation
Computer animation
Computer animation
Computer animation
Transcript: English(auto-generated)
Hi, welcome to the fifth exercise sheet. Before we get started, I'd like to remind you as every time that you should
please try to solve the tasks yourself before you watch this video, because the video will not help you understand the content of the lecture. If you don't try to solve the task yourselves. With that said, let's get started with the first exercise, which is called multi dimensional arrays. So we're asked to write these two matrices, which are
given here in mathematical notation as Julia matrices. And we can do that using the using the brackets. And we just
put one line of our matrix, where we separate the numbers by spaces. And then for each new line, we put a semicolon. And now we get the matrix. Let's see if we're correct 575
863 1034. Yeah, that looks correct. Now we have to assign it to a variable called a whoops. Okay. And
exactly the same for matrix B. Again, let's check if we're
correct. 940 looks good. 478 looks good. A 133 also looks good. Okay. And now we're done with task one. For task two, we have to calculate the results of these four Julia expressions on paper. Okay, let's examine our expressions
first before we begin with the calculation. So A and B, these are matrices that we just defined in task one. And two, in this case is a scalar, which is just a number. And
when we do matrix and vector math, we often refer to, we often refer to numbers as scalars, as opposed to matrices and vectors which are not scalars. And in this case, the scalar is given as the right hand side of the multiplication operator, which just multiplies every element of
the matrix A with two. And then the second row, we have the matrix addition operator, which adds two matrices element by element. And in the in the third row, we have the transposition operator, the transposition operator flips a
matrix on its diagonal. And in the last row, we have the matrix multiplication, which, yeah, it's the most complicated operator, which we will look at in this exercise. And we'll see what it does later. But let's get
started with element wise matrix multiplication. So we have given the matrix a here 575 and so on. And this element wise multiplication just multiplies every element of the matrix with two. So five becomes 10, seven becomes 14,
five again becomes 10, 816, and so on. Right. And to check if this is correct, we can just type the expression down here. Yeah, and we get the result 10 1410, and so on. For the matrix addition, we add all of the elements of our two
matrices. And we all we only add those elements which are at the same position in both matrices. So this five here is in the upper left corner of the matrix a, we can also say it's at index one one. And this is why we added to the
element which is at index one one in the other matrix B. In this case, that's the nine. So nine plus five is 14. And we continue in the same fashion. So seven plus four is 13. And so on. Sorry, seven plus four is not 13. It's 11. Yeah,
let's let's look at the result here to see if we are correct before I make more calculation errors in my head. Okay, 1411 five, yeah, that looks that looks correct. Okay, now for the transposition operator. As I
said, we flipped the matrix on its diagonal. So that means the diagonal in this case, it's 564 remains unchanged, and all the other elements are swapped. Like, like the day, like it's used like a mirror, essentially. So we swap five with 10, seven with eight, and three with three.
Let's look at the result. Yeah, as I said, the diagonal remains unchanged, five is swapped with 10, and so on. And now for the matrix multiplication. It really helps to write down the matrices, as I did here in this, in this form, right up here, we have matrix A, which
is the right hand side of our matrix multiplication. And here we have matrix B, which is the left hand side of our matrix multiplication. And to calculate all of the elements in our result matrix x one until x nine. For every one of
these elements, we look at the column of a, which is in the same column as our result. So first results in the first column, that means we look at the first column of a result is in the third column, which means we look at the third column of a. And the same goes for the rows. So
here, this result x two is in the second row of the result, which means we look at the second row of B. And this result here, x six is in the third row of the result matrix, which means we look at the third row of the
input matrix. Okay. And now what do we do? Let's take one example x one. So first row of B first column of a. And for each of the elements, we multiply the elements that are at the same position. So nine times five, four times eight,
zero times 10. And then we add the multiple the products, we add the products. Let's spell this out. So as I said, nine times five, plus eight times four, plus zero times
10. Okay. And let's look at another example x six. So x six means we look at the third row of B, and the second column of a. So one times seven, plus three times
six, plus three times three. Okay. And yeah, if we if we use the matrix multiplication operator and Julia, this is
what happens, right? Julia does does exactly this calculation for every element. Let's look at the result. And there we have it. Okay. So yeah, if if you don't believe me, you can you can check but it's it's
just the calculation that we just looked at. Now, if you think matrix multiplication, that's weird. When will I ever need this? Task three is here to give you an example for how we can use matrix multiplication in the business context. Okay, so your company uses five
resources, R one, R two, up to R five, to produce three intermediate products, I one, I two and I three. These are in turn used to produce two final products P one and P two. And the following tables show how many units of each resource are required for the production of one unit of
each intermediate product. And how many units of each intermediate product are required for the production of one unit of each final product respectively. Okay, if this is a little abstract, you can think of an example. For example, our company might be a bakery, R one to R five might be resources such as flour, sugar, salt, butter and
chocolate. And I want to I three might be intermediate products like dough, another kind of dough and a third kind of dough, whatever. And then we might have final products
such as croissants and bread rolls, right? Just any products will do but this is really not about the bakery. This is really about the math behind production planning. Okay, and for example, the tables tell you that you need eight units of R one and 12 units of R two, nine units of
R three, etc, to produce one unit of I one, right, this is just this column of this table. All right, and we can represent these tables in Julia using multi dimensional arrays. So yeah, multi dimensional arrays, otherwise known as matrices. So our matrix m one is just this
table up here 8, 7, 10, 12, 6, 4, and so on. And the second matrix m two is just the other table 957348. All right, suppose your company wants to produce 400 units of
P one and 300 units of P two. This can be expressed using the following vector. So a vector 400 300. Again, we can represent this in Julia like this. All right. And now we asked to write a Julia expression that evaluates to a three element vector that indicates how many units of each
intermediate product are required to produce the quantities Q. Okay, so the first quantity in Q is 400 units of P one. Let's see how many units of in the intermediate products we need. So for one unit of P one, we need nine units of I one seven of I two and four of I
three. And to make 400 units of P one, we will need 400 units of I sorry, 400 times nine units of I one 400 times seven units of I two and 400 times four units of I three, right. And the same goes for P two, just with 300 as the
factor. Okay, and you may have noticed already that this is basically just like a matrix multiplication. So if you imagine this, this way of writing down the matrices from task two, if you apply this to this table here, and instead of
the second matrix, use the vector Q, which you just put here, right, imagine the vector Q sitting right here, then you have 400 times nine plus 300 times five, which is then the first element of your result vector. And you can do
the same for the second row. So 400 times seven, and 300 plus 300 times three is the second result of your result vector, and so on. Okay, and we can, we can represent this in Julia by just typing m two, right and two times Q. All
right, and this is our result vector. And we can do the same for the second part of the task, which says, Furthermore, write a Julia expression that evaluates to a
five element vector that indicates how many units of each resource are required to produce the quantities Q. Okay, we already know how many units of the intermediate products we require. And now we have to put this into the resource table. So we know that we need 5100 units of I
one. And so that means we need 5100 times eight units of our one 5100 times 12 units of our two, and so on, just for I one, right. And again, if we if if you imagine that
this vector, this three element vector is sitting right here for the multiplication. And then again, this task is just a matrix multiplication 5100 times eight plus the second
element 3700 3700 times seven plus 10 times the third element 4000 10 times 4000 is the first element of our result vector. Okay, so we just take this vector and we
multiply it again with m one. And then we have the the result vector. So this is how many units of each resource we need to make the quantities Q. And this is how many units of each intermediate product we need to make the quantities
cube. So again, with our example, it would be 400 croissants and 300 bread rolls. In task four, we are given two Julia functions f one and f two, both have one parameter m. And it says that suppose that MSA is always a
square matrix. So that means that it's a matrix that either has dimensions three times three, four times four, five times five. So a matrix where both axes have the same number of elements. And as opposed to non square matrices, for instance, a five times three matrix would not be a
square matrix. And without executing either function, we have to decide which one returns the transpose of m and which one returns the diagonal of m. Okay, let's just look at these functions line by line. So first function first line, we have a, we call a function size of m, and size of m returns a
tuple of the dimensions of m. And we know that m is a square matrix. So n and m, these two variables are equal. And if m is a three times three matrix, n would be three, and m would
also be three. If we have a four by four matrix, both would be four, and so on. Now, second line, we call the function zeros with one parameter, and zeros just creates a vector, which is initialized with zero. So if we
put three here, if n is three, and we just get a vector with three zeros, and we assign this vector to the variable result. And in the end, and the last line, we return this vector, we return the vector result. And we can see that before we return it, it the vector is manipulated using
these loops here. So the first loop goes from one to n, and the x variable is called I, the second group goes from one to m, and the index variable is called J. And inside of the second loop, we have an if branch. And this if
branch tells us that we do nothing if i is not equal to j. So if i is not equal to j, we we do nothing. But if i is equal to j, then we change the vector result. And we change the element i of the vector result. And to this
element, we assign the element that is at the position i j. In m, we take the first we take element one one, right, which if i is is equal to one and j is equal to one, we execute
this assignment. If i is equal to two and j is equal to two, we execute the assignment. If i is equal to three and j is equal to three, we execute the assignment and so on, all the way up until the last elements of the loop ranges. So
up until n and m. Yeah, and that means we just go down the diagonal of m, right? So element one, one of m, element two, two of m, element three, three of m, and so on, depending on the size of m, of course. Yeah, so we assign
all the elements of the diagonal to result and then in the end, we return results. So we can conclude that f1 returns the diagonal of m. Okay, now we already based we basically already know that f2 returns the transpose. But let's have a look at f2 nonetheless, and see how it returns the transpose. So the function starts in a very
similar way. So the first four lines of the second function are exactly the same. Again, we read out the size of our matrix m. Oh, sorry, it's not exactly the same, because instead of handing just one argument to the function zeros,
we give two arguments to the function zeros n and m, which makes zeros not return a vector, but instead zeros returns a matrix. And we assign the matrix to the variable result. Now our two loops iterate again over one to n
and one to m. And now there's no if branch instead, we just assign to our result matrix in every iteration. But we assign to i, j in the result matrix, the element that is at j, i in the matrix m, the input matrix. So if i and j are
equal, that basically is just just means we copy from the input matrix to the output matrix called result. But if i and j are not equal, it's obviously not just a copy, but we also swap the position of the element. Right? So yeah,
that means we have implemented a transpose. Because in the transpose function, we keep the diagonal the same, but we swap all of the other elements using the diagonal as the symmetry line. Yeah, and with that, we can conclude that
f2 is the transpose function, which returns the transpose of m called result. For task five, we have to do some implementation. So we have given we are given three Julia
functions. The functions are called element wise, multiply, add and multiply. All of the functions take two arguments. In the first function, the arguments are called matrix and scalar. And in the other two functions, the argument sorry, the parameters are called matrix one and matrix two
respectively. And we can see the first function just does an element wise multiplication, where it multiplies every element of matrix with a scalar using the dot multiply operator. And the second function adds the two matrices and the third function multiplies the two matrices.
Alright, now the task is to implement semantically equivalent functions. But we're not allowed to use Julia's matrix operators. So we have to use loops and indices and operators that just operate on scalars. Alright, let's get
started. We just put a function definition, let's call it my element wise multiply. Okay. So this is our function
definition. So far, so boring. We know that we want to create a matrix, right, we want to return a matrix because we want to have we want to return a matrix where every element is
multiplied with scalar. So let's start by just creating an matrix that we can return. Yeah, one simple way to create a new matrix is just use the function zeros. But to call zeros, we have to know the dimensions of our result
matrix. And obviously, the result matrix should have the same dimensions as the input matrix, because we just want to multiply every element of the input matrix with the scalar. Okay, and we can find the dimensions of the input matrix using the function size. And size gives
us a tuple. Let's have a look at the tuple maybe before we continue. Let's just test the function. Okay, we put in
a two by two matrix 1234. And we get, we get the size now of the matrix, the size is 22. Okay, so a tuple. And we can get the elements of the tuple by assigning it like this. And then we can make a new matrix with all zeros
with hat which has the same dimensions by calling zeros and M. And then we can just return the result and now look at it again. And there we have it our result matrix with all zero elements. Okay, now we have to fill the matrix
right, because we want to. Yeah, we want to implement this element wise multiplication. And to fill the matrix, we can use loops. Right, we saw that we saw it basically in this task. And let's just be quick and copy
the loops on here. Okay. Let's just so now if we if we want
to manipulate our matrix result, we can just assign to
the elements of result using the loop variables i and j. And we can copy our input matrix. Well, yeah, let's do something more boring. Let's do something more boring. First, we just put the scalar, which is given as an argument, we just put that into every element of result. Let's look
at that. So now we have to as our result as every element of our result matrix here. And if we put a five here, then it's five, right? Okay. And but we don't really want just a scalar. Obviously, we want to multiply the elements of our
matrix with the scalar. And we can access an element of our matrix using the bracket operator, to which we give to to which we give two indices. And if we do this, then we just copy the matrix, right, we copy the input
matrix, every element of our input matrix, we copy into the matrix result, then we return result. So it's no surprise that we just get the matrix that we put in, we just get that back. So if we change it around, then yeah, it changes in the result. Okay. And to to have the desired
output, we have to multiply with scalar here. So that means we read one element out of our input matrix, we read the element i at the indices ij. So for instance, if i is one and j
is one, we read the element 1.0 of our input matrix, we multiply it with two, and then we write it into our result matrix at the position ij. In our example, it was one
one. So it would be this position in the output matrix. And this would become two now this would become four, six and eight. Let's see. Yes, that works. All right. And with that, we are done with the element wise multiplication
function. Let's continue with the addition function. And we can actually copy the the beginning of the function, we
can just copy that to our other function, because we will basically start in the same way. The only thing we have to change is what we do in inside of the loops, right? Because otherwise, it's actually very similar, because
my add returns a matrix, right? And to return the right matrix, we have to manipulate every single element of our result matrix. So it makes total sense to just create a new matrix with the right size, and then to use
two loops to iterate over every element of the matrix. And then to in the end, we return the matrix, which we created, and then manipulated. Okay. And we know that we
want to put some value into every element of our matrix result. And which will you do we want to put? Well, we want to add matrix one and matrix two, right? So we just take the element, the right element out of matrix one. And
we add it to the element of matrix two, which is at the same position. Okay, let's see how this looks how the result looks. Okay, so I put in two matrices. And the
first one is 1234, the matrix we just saw in the other task. The second one is a matrix that has all ones. So in
the output, we should see a matrix that is like this, but every element is to every element that we add a one, right? So one plus one is two, two plus one is three, three plus one is four, four plus one is five. Yeah, and that's
exactly the matrix we get. We can maybe try something different. Yeah, we can also add a different matrix that seems to work fine. So yeah, this is the code for the matrix addition functions. And now for the last task, we have a
look at the matrix multiplication. Okay, again, it
is kind of obvious that we want to create a new matrix, which contains the result of our matrix multiplication, right? And now the the dimensions of the new matrix, they are a
little bit more complicated, because they depend in an interesting way on the dimensions of matrix one and matrix two. Let's look at an example. In fact, we saw already plenty of examples in this exercise. So we know that if we multiply two square matrices, then the result is
again, a square matrix that has the same dimensions. But if we multiply non square matrices, then it is a little different. For example, in this task, we multiplied m two, which is a three times two matrix with a vector q. The vector is
essentially the same as a as a two times one matrix. Right. And what we get is a three times one vector. So three
times two matrix times two times one vector, and we get a three times one vector as our result. Yeah, so three times two, two times one, and the result is three times one. So it's the outermost indices of our matrix multiplication. And the
same is true for for this multiplication. Here, we multiply this vector, which is three times one vector, we multiply this with m one, and m one is a matrix that has the dimensions five times three. So five times three matrix times
three times one matrix, three times one matrix, the same as a vector, and we get a five times one matrix out, which is the same as a five element vector. So again, we have the
outermost indices as the sizes of our result matrix. Okay, so let's implement this in our code. We want a result matrix that has the outermost indices as its dimensions. So we
call size twice we call size of matrix one, we call size of matrix two. And, and the outermost indices are now n
and q. And in fact, we know that m and p are always equal. Because if m and p are not equal, then it's impossible to multiply these matrices. Okay, and in the examples we saw m and p would have been three, our five respectively. All
right. Let's just see if this makes sense so far. Let's just
put an m one as our first matrix and then m two times q as the second matrix. And what we want to see now is a dimensions five times one, right? Like this. Let's see if
I made a mistake. Or if I did it correctly. Yeah, there's a mistake. Where's the mistake? Okay, we have in 55. This is this box, and the box calls in 4054, which is this cell.
And then in line four, p comma q equals size of matrix two. All right, we put in a vector. And then it doesn't work. Okay, yeah, we have to. Yeah, that's it, we can do a
little trick. And we call can call the matrix constructor here. And then it should work. No, also doesn't work. Well, maybe we
yeah, okay. This works. But it's a little ugly, because we have to use reshape, which we didn't really talk about yet in the in the class. Yeah, but, okay, I will just introduce it now. reshape essentially takes this argument. And if we put
these parameters, then it just takes a vector and transforms it into a matrix where the other dimension is one, right? I just already told you a couple of times that a vector three three element vector is essentially the same as a three times one
matrix. And the five element vector is essentially the same as a five times one matrix, right? And to Julia, it's not because in Julia vector and matrix are different data types. And if we use this function reshape, we can transform the vector to a matrix. Without without changing its content,
we just change the data type. Okay, and what we know now is that our result matrix looks right. We have a five times three matrix here, and a three times one vector here. And we get a five times one matrix out. So yeah, that
that looks correct. And let's actually use a simpler example. To test the rest of our code, we can just use B and A, which we used in the first task. B and A are three times
three matrices. Okay, so there's our three times three output matrix. Alright, now we have to actually fill the elements of our output matrix with the right content. And to do this, we can again, we can already put two loops right
because we know that we have to do some work for every element of our output matrix. So that that already means we need two loops, one loop which iterates over the first
dimension and the other loop which iterates over the second dimension of the output matrix. So the first dimension of the output matrix one to n, second dimension is one to q now. And we know that we have to do something here,
right? So we want to assign some stuff to this, to this element. So if we just execute it like this, then we will assign minus one. Why is it only Oh, yeah, I put the
wrong indices, I have to put i and j here, obviously. Yeah, now it's minus one in every in every element of our output matrix. Okay, now let's think about what we actually have to do to implement the matrix multiplication. And I think
it's helpful to look again at this diagram here. So here, what did we do? We multiply this with this, we add the result to our sorry, we multiply a nine times five, we
multiply four times eight, we multiply zero times 10. We have three products, and then we add the products. And this is our result. Okay. All right. So why don't we just use a loop that looks at the first elements, multiplies them, looks
at the second elements, multiplies them, then looks at the third elements and multiplies them. And all of the results we add together, and this is x one. And yeah, we so we want a loop that goes from one, to two, to three, and
accesses the first element of this row, the first element of this column, first, second element of this row, second element of this column, third element of this row, third element of this column. Alright, so and in every iteration of our loop, we do one multiplication, and we add all
of the results into x one. Okay, let's look at our code. So in our code, x one is called result ij, right? Yeah, it's called result ij. But maybe it will be easier to
understand if I call it x one first. So x one equals to zero. And in the end, we also this is the wrong, this is the wrong function, I shouldn't add this, it's the addition function, we want to add the multiplication function. Alright, so x one is
equal to zero, right? Because zero is a good way to initialize x one, because we want to add stuff. And every time we add something, we add some results, then we can start with zero because zero is a neutral element of addition,
right? If you add zero to something, you change nothing, it's basically like you'd have done nothing at all. Okay, so x one equals to zero in the beginning. And now we use the loop to mount to iterate over the two vectors of
our input matrices, right, right, we iterate over the, over the column in the top matrix, and we iterate over the row in the left matrix. In every iteration of our loop, we multiply them, we go to the next element, we multiply them, we go to the next element, we multiply them. And every
time we have multiplied something we add it to the result. Okay, so let's use a loop with a new index variable. And the index variable should now go from one right to the number of elements which are in the row in the row and in the
column. And these two numbers, they have to be the same every time we do matrix multiplication. So these are m and p and m and p are exactly the same here. So we can just use either one. Okay, now this loop goes over our
column and row and computes x one, which is located down here. So we multiply the elements in the column and the row multiplication, right, column and the row, these are in matrix one and matrix two respectively. And for matrix
one, we need to fix the, we need to use the row, which is
in the row of our output back of our output element. So if our output element is in the first row, we want the first row of matrix one. And I believe we can get this row by putting i here. And we want to fix the first column of matrix
two if our output is in the first column. And I believe we can get this column if we put if we put j here. And then
once we have selected a row and we have selected a column, we want to look at every element of these two row and column. And for this, we use the variable k here. Okay. And now
we do the multiplication. And then we have to add the result to x one, right? Because x one is our is our output element. And in the end, we write x one back to result.
Okay, let's see if it works. I'm curious because it's very easy to make a mistake if you have so many variables. Let's see. 778757 is our first row. Let's look at that we don't
scroll up, we can just put another cell and we can test against Julia's matrix multiplication. Yeah, that looks fine. Yeah, okay. So we have already implemented a correct function. And we can actually make it a little bit more
simple. Because we know that result in the beginning contains only zeros, right? So that's why we don't actually need this variable x one. And we can make the function a little shorter if we just put result here. And we can get rid of x one entirely. And then then we Yeah, we just have
to make the function a little shorter. And that's it, we're done with matrix multiplication function, which doesn't use any matrix multiplication operators in Julia. For exercise task
six, we switch the topic, we leave matrices behind. And now we go to dictionaries, which is our second topic, our second advanced data type, which we will look at. So first advanced data type was matrices. Now the second advanced data type is dictionaries. Okay, and we're
asked to create some dictionaries. And the first cell, we have to create a dictionary which is empty. Okay, that's, that's very simple. We just call the dictionary constructor function with no arguments, and
we get an empty dictionary. Alright. Second task, we have to create a dictionary in which the key a is associated with the value b. Alright, again, we can call the dictionary constructor function. And we can just put in such an
ordered pair, which we can create with this arrow operator in Julia. And we on the left side, we put the key, which is in this case, the string a, and on the right side, we put the we put the string b, which is in this case, the sorry, we put the value, which is in this case, the
string b. Yeah, there we have it a dictionary where the key a is associated with the value b. And now, another dictionary where the key b is associated with the value a and the key c is associated with the value d. Alright, so again, left
side is the key. So b is the key, which we associate with the value a. And now we associate the key c with the value d. Okay. Yeah, and there we have it a dictionary with two entries. And for the fourth task, we asked to
create a dictionary in which the key names is associated with the vector, Alice Bob Carroll, and the key age is associated with the vector of 21 2025. Okay, so again, we call the dictionary constructor function. First, our first key
is names. Our second key is age. And then as values, we have two vectors. And the second vector contains 21 2025. And the first vector contains Alice Bob Carroll. Oh,
okay. Yeah, there we have it our dictionary with two entries where the strings string keys are associated with vector values. And with that we are done with task six. For task
seven, we want to use a dictionary to keep track of the values of our startup. And we're given this list of different
teams of our startup. So we have the management team, the HR team, the production team and the administration team. And for each of the teams we have given a we are given this list of employee names. And the first task is to summarize our staff in a dictionary which associates the team names
as the keys, which vectors of names as the values. All right. And again, we just call the dictionary constructor function. Our first key is management. And our first
value is the vector of names Zoe and Yannick. Okay, and I think it will get a little confusing if we continue like this, because the dictionary you want to create is quite
large. So let's actually use a different use a different method for creating the dictionary. We assign the dictionary to a to a variable D. And then we just use the dictionary bracket operator to to change the values of our
dictionary. If we do it like this, then we receive a dictionary which contains one entry. And then we can create
the other entries in the dictionary for the other teams. So severing wolf and full cow. Next team is called production. Okay, I will just I will just use copy and
paste. Because if I if I type all of this, I will make so many mistakes. All right. And now the next team is
administration. Okay. Yeah, looks good. We have created the
dictionary with four entries at the keys are HR administration, management and production. As you can see, as always with dictionaries, the order in which we put the stuff into the dictionary is not preserved. This is, as you know, from the lecture, in general, the case with dictionaries, they don't preserve order, which is
different from vectors, vectors preserve the order as we know, and then we have our values, which are just the vector of the vectors of names. And these are vectors. And obviously, the vectors inside of the dictionary preserve the
order inside of the vector. But the vectors themselves are shuffled in a different order, when they when they are put into the dictionary as as values of keys. But inside of
the vectors, the order is still the same. So the vector is the same vector, if we put it into the dictionary, or if we have it in a variable, right, it doesn't, it doesn't change. It's still a vector with all of the vector properties that we know from Julia. It's just a key value pairs inside of the dictionary, which are
shuffled. Alright, so second task, the production team would like to organize a team event, write a Julia expression that evaluates to a list of members of this team. All right, we can use the bracket operator to access a key in our dictionary, the dictionary is called D, it's assigned to the variable D. And we can access the value at
the key production by putting the key production into the bracket operator for our dictionary. And as a result, we get just the value which has been associated with this
key production in the dictionary. But third task, Liner was going to leave the administration team but new hire lotter will take over their position, right line of Julia code that changes the content of the respective vector accordingly. Okay, administration team, let's have
a look. Administration, right, that's the team. So Liners in the first position. So we can just change the first position of the vector, right. And if we, we, we read
out the value, which is associated with the key administration. And this value is the result of this expression, right? This is this expression is evaluated by Julia. And it evaluates to a vector, which is the vector which has been assigned as the value of the key administration and is stored inside of the dictionary. This
is the vector in the first part. And as soon as this expression is evaluated, we can then use all of the stuff all of the functions and all of the operators we can normally use on vectors we can just use on this expression. So we
can use the vector indexing operator, the bracket operator that we have known for many exercises. Now, we can just use this to access an element of our vector. In this case, the element is you know, and now we can also
assign to this element, a new value, a lotter. And now we have changed the the value in the dictionary. Right, if we look at the dictionary, which is what we do in the last line, we just get the entire dictionary. And we can see
that in the administration team, the vector is now changed. It doesn't it doesn't say lino anymore, it says lotto now in the first in the first element. Okay, task four. As your startup keeps growing, you decide to form a dedicated sales team and a marketing team. HR tells
you that they have hired Xaverine and Volker for sales, and Thalke and Simon for marketing. Write Julia code that adjusts your dictionary accordingly. Okay, it's interesting to note that HR which are called Xaverine and Volker themselves, if I had more people called Xaverine and Volker, maybe they're a
little biased about and that's not what this task is about. We just want to put new teams into our dictionary, right. So as our keys, we obviously use sales and marketing because that's the that's the new
teams that are formed. And yeah, let's just let's just make this less, more and more illustrative. If we just put an empty vector here, then we just have an empty team sales in our dictionary. And now we can
actually, as I said, we can use all of the functions that we can normally use on vectors, we can just use them on on this dictionary value. So yeah, this expression evaluates to a vector, right as you know, bracket operator on the dictionary, you put in the
key, you get the value. The value in this case is a vector. And we can use this vector as the argument of the function push, which we normally used push stuff into a vector. And so we are pushing into the sales team, severing. And there, there they are, severing
this as part of the sales team now. And we can also push another person to the sales team. Sorry, the
person is not called sales, the person is called Volker. And there we have the we have the sales team with Severin and Volker now. Okay. And now we can do something similar for the marketing team. Okay, and there's our new marketing team
with Volker and Simon. Yeah, again, there is no magic. There's no magic going on here. It's just very, very profane actually.
We use the bracket we assign to the bracket operator to put a new value into our dictionary And the the element of the The value we put as an argument to the bracket operator this is the key and the right hand side of the assignment is the value and
As soon as we have created new As we have put new key value pairs into our dictionary and we can then We can then read them out right we can we can access the key value pass using
again the bracket operator, so if we Use the bracket operator on our dictionary. We supply the key in this case. The key is the string marketing as the Argument to the bracket operator and This expression then evaluates to the value which has been
Associated with the key marketing in our dictionary Okay in this case the value is a mutable data type a Vector right we know vectors are mutable data types
That means we can Mutate the vector inside of the dictionary Because the dictionary is also also mutable data type we can just just Change We can just change the dictionary we can put new keys and new values
But if we change the vector which is inside of the dictionary we don't actually change the dictionary the dictionary Always In these two lines, right? We do not change the dictionary Not really the dictionary always just contains the same vector that we have assigned to the dictionary
We have we've put into the dictionary here, but the vector is a mutable data type so we can have the same Identical vector which can have different elements right and here we put a new element and here we put a new element But it's still the same vector inside of the dictionary So we don't actually change
So from the perspective of the dictionary it remains unchanged, but obviously If you look at the dictionary in its entirely in its entirety including all of the keys and all of the values then Obviously they do they do change because we have changed the values
But we haven't changed the values in a way that That influences the identity right it's still the ident it's still The vector is still the same vector, but we have changed its content Okay, I hope that has become clear now With that we're done with task 7
For task 8 we Now begin to use to actually use the dictionaries instead of just creating and changing their content so Air traffic controllers use the native phonetic alphabet for spelling actually don't quote me on that
They might use a different phonetic alphabet doesn't matter. We can represent this alphabet as a Julia dictionary. Okay, so this is the This is the Julia dictionary. It's quite long as you can see that it has a key value pair for every letter of the alphabet and the values are strings which are
The words which the air traffic controllers use when they spell so for instance if they want to spell ABC They would say alpha Rava Charlie, right? Okay Now our task is to write a Julia function that receives a word as input and returns its spelling in the native phonetic alphabet For example given the argument. Hello, your function should return hotel echo lima limo Oscar
Test your function by calling it with various arguments. Okay, let's stop function plain and simple We start with function definition Let's call our function NATO spelling maybe and we receive a word it's input so let's call our parameter what and
We should return a String, right? So why don't we just create a new? empty string and String is immutable data type, but we can replace the string which you have assigned to the variable result
After replacing it with the correct String in the end we can return result Okay. Now we want to build result part element by element for every letter in word, right so we can
use a loop to iterate all of over all of the letters in our argument called word and Let's see what happens if we just
If we just concatenate The current string result with letter and Assign again assigned us to the variable result and then at the end we return result. So let's just try
What happens now? Okay, we just get the result back Now before we can look our input characters up and this dictionary we have to convert them to uppercase because the dictionary only contains uppercase keys and
our input word contains lowercase letters some lowercase letters and Yeah, let's use the example from the task and capital hello We can use the function uppercase to transform a string to uppercase letters. Okay So let's just call uppercase here and
Yeah there we get the We get the letters in uppercase now, right? Okay. So now what we have to do is we have to look up every letter in the In the dictionary the dictionary is called NPA
I have to execute the cell to actually assign it to this variable and We can just Use the bracket operator of our dictionary To the bracket operator. We supply this argument the key so H E L L O
one one of the letters in every iteration of our loop here and It will look it up in the dictionary for H to load a return hotel and so on and it will Concatenate all of this into result. Let's see what we get Okay, we get hotel echo lima lima Oscar that already looks quite good
But we want to put these commas and spaces to make it a little bit more readable so we can Do this by By concatenating comma space to our
Result to our string result and Now we only have the problem that at the end of the string we still have this comma space here Okay, so there are two ways to deal with this problem the first way is you could do some if a branch here and that checks if you are at the end of your
String and if in the case you are then you don't put the comma space But another way which I will use now is to just Not return the entire string, but should return a slice of the string. I hope this works
yeah, okay, and with that we've just sliced off that last comma space here and We're done with this task in task 9. We will have a look at the second use case of dictionaries
and the first use case was to use dictionaries like a Like a phone book basically where we look up single elements To to translate as something right that was the net order phonetic dictionary now, we will have a different way of
Using dictionaries. It's not just about translation, but this time it's about caching intermediate results So we don't have to calculate the same stuff over and over and over again All right So consider the following Julia function which returns the Fibonacci sequence
We know this function from the previous exercises, right? So in the case where n is less than or equal to 1 we just return n and in the other case We have two recursive calls we call The function again with n minus 1 and we call the function with n minus 2 we add the two results and
that's what we return and Yeah, that's a simple very simple recursive function to calculate the nth element of the Fibonacci sequence and Yeah, the task explains that it's a disadvantage of this function that it computes the same results over and over again
And You can you can we can make this clear with an example, let's say we call the function with a 4 and 4 is obviously not less than or equal to 1 so we go to the recursive calls and then we
Call the function once with 3 and once with 2 Both of these are also not less than or equal to 1 so again We have more recursive calls for the 3 for the call that had the 3 as the argument we call
The function again with 2 as the argument and with 1 as the argument. So we already have Called the function in our entire computation Tree, we have called the function already two times with the same argument That's wasteful, right? We don't We want to
find a way to avoid this and One very simple way is to use a dictionary in which we store the result of every call to FIB More specifically we associate the key n with the value FIB of n for each n This is called caching and we say the dictionary acts as a cache
Okay, and now we have to write a Julia function that runs the nth number of the Fibonacci sequence So a function that is almost semantically equivalent to this function But which uses a dictionary as a cache the function should have two parameters n and the cache Okay with this we can get started
Two parameters n and the cache. All right That's that's our function definition done When your function is called the cache should be initialized with the two first numbers in the sequence All right, we'd know that the two first numbers in the Fibonacci sequence
Which are the stopping criterion for our recursion are? The numbers at index 1 and the number index 2, right because if We have the number at index 1 we return 1 and for the number index
No, sorry at the number at index 0 and the number at index 1 and the number at index 0 is 0 and the number at index 1 is 1
And So if we call our function The cache should be initialized with the first two numbers in the sequence. Okay. So the cache is a dictionary as we said and
Yeah, we just with this with this dictionary we have basically just expressed this if branch
Right if n is equal to 1 we return n which is 1 so n 1 leads to the result 1 which is this key value pair in the dictionary and If n is 0 we return 0
Which is this key value pair in the dictionary, okay Now in our in your function check if the cache already contains your desired result and Only calculate it if it is not in the cache yet
Okay How do we check if our cache returns it contains our desired result, let's see what we can do We have a dictionary
We can use the function keys No, it doesn't work. I Am sorry. I Just made a mistake. Yeah, we can use the function keys to get all the keys in our dictionary
And then we can We can use the in Operator to check if something is in the keys so 0 in keys would be true and
10 in keys would be false. All right, so this is this is what we will use to see if something is in our dictionary And check if the cache already contains your desired result the desired result
Would be the value that is associated with the key n right so we can check if n in keys cache and Only calculate it if it is not in the cache yet. All right, so
We want to do something if it is not in the cache. So we We negate the We negate the condition and then we do something here we we calculate some some result and
After that Return the value which is associated with n in the cache, right? So to return the value which is associated with n in the cache is very simple. We just return cache of n and now we have to to complete the function we have to
Calculate it if it is not in the cache yet. So if it's not in the cache yet, that's this if branch And to calculate this to calculate it is just to call to make this recursive call, right? but obviously now we have We have a second parameter called cache and also our function has a different name. It's called fit cached and
This is our desired result And we want to put this result into cache now because we want to cache
All of the results we calculate Alright Yeah, I think this should work fine actually, let's see Yeah, we get we get three as our result, let's see what happens if we
Call it multiple times Obviously Yeah, okay one one two three Okay
so now we have the Fibonacci sequence and The property of the Fibonacci sequence is that every number is the sum of the two previous numbers So two is the sum of one and one three is the sum of one and two five the sum of one Two and three or and so on. Yeah, that looks that looks correct. So yeah, we have Implemented a function that returns the nth element of the Fibonacci sequence and
With that we are We are done with this task For task 10. We again leave dictionaries behind as a topic and we look at structs now
Structs are the second the third advanced data type that we consider in the Advanced data type in the advanced data types lecture and The first task is to answer some simple question about
Questions about structs. So the first question is what is the header of the struct facility? And that simple the headers trust the line struct facility. That's All there is to it. What is the body? The body is this part name and balance? And you could also say that the end keyword also belongs to the header but yeah, that's a matter of that's a matter of definition
I don't consider it to be part of the header, but it doesn't really matter Third question how many fields also known as attributes does the struct facility contain yeah, it contains two fields name and balance and which is their names and
Fourth question is how many instances of the struct are created The answer is three. We create three instances The first instance is created with this call to the constructor function of the struct facility the second instance is created with this call to the constructor function and the third instance is created with this call and
What do the following expressions evaluate to AIX dot name? So let's let's have a look. We create a instance of the struct facility here and
for the first field of the struct we put this string and for the second field of the struct balance we put this integer and If we
Access using this syntax if we access the field name of our Instance, which we have assigned to this variable then it evaluates to the value of the field Which is this string? So this is the string which this expression evaluates to
and The same logic can be used to determine which Value this expression evaluates to So we have created an instance of our struct here and for the second field called balance we have as put this
value here minus 20 and if we use this syntax to access sorry if we use this syntax to access the field balance of our Instance we have which we have assigned to the variable LGE We get minus 20 as our result of the expression
All right, and sixth question Why can the following line of Julia code not be executed without an error? and the line is AIX dot balance plus equals 5 and the answer is it cannot be executed without an error because structs in Julia are immutable and
Yeah, that's why you can't change their content that's literally what the word immutable means You could define the struct as mutable using the keyword mutable Then it would the header would say mutable struct facility and then you could change the content But here we haven't defined it as mutable in task 11
It's our task to write an inventory management software for the warehouses of our company using Julia Your boss tells you to start by modeling customers products and orders as Julia structs
All right, so we have four different structs that we have to create and the struct address has to store a postal address Which consists of the street name the zip code the town the state and the country. All right Let's get started. Let's just define a struct called address and it should create a contain
the street name the zip code
the town and the state and the country Okay. Oh, yeah that with that we're done
Defining the struct and we're also asked to create an instance of each of our structs to test our code Yeah, we can we can do that again by calling the constructor of address Maybe I can just put my office address
So this would be the street the zip code Something like this, but don't quote me on that Yeah, maybe I just Google it
Okay, it's it's actually 5207 true All right The town is obviously Aachen the state is North Australia and the country Germany
Okay, and this creates an instance of our struct which we have just defined and Julia prints the instance in this way All right Second struct customer Our software needs to store the name of the company
Okay, apparently all of the customers are companies the postal address and the email address Okay Let's Get started struct customer whoops
so the name of the company right name of the company postal address and the email address Okay, and now again, let's create an instance Of the of the struct
Let's say that DPO the chair is actually a customer So that's that's the the chair where I'm working at DPO and That's the name. The address would now be this address Let's assign it to a variable so that we can use the instance in the second cell
If I spell the word address, right? Yeah, I have and then the email address, okay, so maybe
That Is some email address Yeah, and we have created an instance of the struct customer All right third struct product you we need to store the products manufacturer Along with the product name the ID number a description and the price per unit. All right
struct product manufacturer
Manufacturer Product name the ID number a description and the price per unit
Okay Yeah, let's create an instance of the struct What could the manufacturer beam? I don't know maybe Software Inc right some software company which will sell us
Some Software to solve optimization problems I'm just making stuff up really idea of the product could be one and the description could be best solver ever and the price let's say for the best solver ever and I
Would I would pay quite a high price So, yeah that that could be the price maybe Alright That's an instance of the struct product The last struct is called order should can to contain a reference to the order product
It's quantity the customer ordered it and the date on which the order was placed Okay Struct order should contain A reference to the audit product Okay, so we could either just refer to the product by its ID
But we can also just put the product into our struct. It doesn't really matter It's yeah, it's the choice of the programmer It's quantity. Okay quantity The customer ordered it so that would be customer
And the date on which the order was placed Product quantity customer date. Yeah, that looks complete. Okay, let's create an instance of order
So the product first Let's assign this to a variable so we can use it So the product the quantity I just need one one license for the optimization solver Then the customer which would be DPO now, let's assign this to a variable as well so we can use it
DPO and Now the date yeah, I've ordered this on July 1st
2021 all right now, that's our instance of the of our order, okay The task goes on By saying we should write a Julia function called print order that takes as input an order
Which is an instance of the struct and prints it according to the following template. Okay, let's get started by putting the function Header print order which takes an instance of the order. Let's call this order
Prints it according to the following template customer a ordered B units of product C at D. Mm-hmm Let's just copy the template Should we print or return it? We should print it. Okay. Yeah, it's also called print order. I could have guessed
Yeah, where a is replaced with the name of the customer, okay
So we have to figure out the customer name and we have to put this here The customer ordered B units so that is replaced with the quantity the quantity is a function of the order
Quantity Okay C Should be replaced with a product name, okay So we have to figure out the product name at D and D is the date right? Yeah the date of the order, okay
So we also have to figure out the date cool Yeah, how do we get the customer name of our order? Well, we have our order instance here. It looks like this and
We Get the customer of the order by just typing order dot customer Because in our struct order we have a field which is called customer so we can use this syntax to just access the content of the field How do we access the quantity the quantity is also a function of the order so that would be order dot quantity
the product name That would be order dot product right which gives us an this expression evaluates to an instance of product and
Product in turn has a field called name which we can access again like this Right you can when you when you try to understand what this expression does and you can imagine these parentheses here because this part is evaluated first and Then on the result in this this is evaluated right, okay
and For the date is again just a field of order so that is order dot date. Let's see what this gives us if we If we call it so print
order Yeah, we have to assign this to a variable so we can use it Okay, not very not very nice Yeah, we the customer name. We now it prints the entire instance of
The customer struct, but we want just a name Yeah, the name is just a field of the struct customer so we can put dot name here again Okay much better customer DPO ordered one units of product opt solver at first July
2022 all right and with that we're done with the entire exercise As always I hope that all of the questions you had about this exercise are answered But if they are not answered yet Please do reach out to us You can either use Moodle and ask a question the Moodle forum or you can also write us an email
We're more than happy to answer If you don't ask us any questions, we never know What's wrong with these videos or how we can help you So please do that if you have any remaining questions, and in any case have a nice day and see you next week