## Sunday, August 27, 2023

### Matrix Operations in kdb+/q

In q, a matrix (an array of m x n numbers) is represented as a list of lists. For example, here is a matrix with 2 rows and 3 columns:

```q)A:(1 2 3;4 5 6)
q)A
1 2 3
4 5 6
```

If A and B are matrices of the same size, then they can be added and subtracted. To find the entries of A + B, you simply add the corresponding entries of A and B. To find A - B, subtract corresponding entries. If A and B have different sizes, you will get a `'length` error.

```q)A:(1 2;3 4)
q)B:(5 6;7 8)
q)A+B
6  8
10 12
q)B-A
4 4
4 4
q)C:(1 1 1;2 2 2)
q)A+C
'length
  A+C
^
```

Scalar Multiplication
If A is a matrix and k is a scalar, then the matrix kA is obtained by multiplying each entry of A by k.

```q)A:(1 2;3 4)
q)k:2
q)k*A
2 4
6 8
```

Matrix Multiplication
First, in order to multiply two matrices A and B, the number of columns of A must match the number of rows of B. If A is m x n and B is n x p, then the size of the product matrix AB will be m x p. In order to calculate AB, you have to take the dot product (multiply corresponding numbers and then add them up) of each row vector in A and the corresponding column vector in B. This can be done in q using the `mmu` (or `\$`) operator.

```q)A:(1 2f;3 4f)
q)B:(5 6f;7 8f)
q)A
1 2
3 4
q)B
5 6
7 8
q)A mmu B
19 22
43 50
```

Identity Matrix
This is a square matrix with 1s on the diagonal and 0s everywhere else.

```q)I:{`float\${x=/:x}til x}
q)I 3
1 0 0
0 1 0
0 0 1
```

Matrix Inverse
The inverse of A is A-1 if AA-1=A-1A=I, where I is the identity matrix. Use the `inv` function to find the inverse of a matrix.

```q)A:(1 2f;3 4f)
q)inv A
-2  1
1.5 -0.5
q)A mmu inv A
1 1.110223e-016
0 1
```

Matrix Tranpose
The tranpose AT of a matrix A is a flipped version of the original matrix which is obtained by changing its rows into columns (or equivalently, its columns into rows). This can be done by using the `flip` operation in q.

```q)A:(1 2 3;4 5 6)
q)flip A
1 4
2 5
3 6
```

## Saturday, August 26, 2023

### Using "flock" to Prevent Multiple Instances of a Script from Running

In a previous post, I wrote about how you can use the `lockfile` command to ensure that only one instance of a script is running at a time. An alternative to `lockfile` is the `flock` command, which is used as follows:

```flock /path/to/mylockfile cmd
```

By default, if the lock cannot be immediately acquired, `flock` will wait indefinitely until it becomes available. However, you can use the `--nonblock` (or `-n`) flag if you want `flock` to fail (with an exit code of 1) rather than wait if the lock cannot be immediately acquired. You can also specify how long `flock` should wait by passing in a `--timeout` in seconds.

A convenient form of `flock` often used within shell scripts is to use a file descriptor, as follows:

```(
flock -n 9 || exit 1
# ... commands executed under lock ...
) 9>/path/to/mylockfile
```

If you want to prevent multiple instances of a shell script from running simultaneously, add the following boilerplate at the top of your script, which will cause the script to lock itself automatically on first run:

```[ "\${FLOCKER}" != "\$0" ] && exec env FLOCKER="\$0" flock -en "\$0" "\$0" "\$@" || :
```