Создать трехугольную матрицу

Мне нужно запрограммировать R с матрицей, которая имеет (1+x^2) вниз по ведущей диагонали (постоянное значение x дано ранее в программе) и x вниз по диагонали по обе стороны от ведущей диагонали, и 0 везде остальное. Надеюсь это имеет смысл! Может кто-нибудь сказать мне, как я запрограммирую это, я могу только найти, как вводить значения на первой диагонали, а не любые другие диагонали. Это матрица 71x71, поэтому я не могу ввести ее вручную!

3 ответа

скаляр

Если x это скаляр и n является общим измерением строки и столбца:

# test inputs
x <- 10
n <- 5

m <- diag(1+x^2, n)
m[abs(row(m) - col(m)) == 1] <- x

давая:

> m
     [,1] [,2] [,3] [,4] [,5]
[1,]  101   10    0    0    0
[2,]   10  101   10    0    0
[3,]    0   10  101   10    0
[4,]    0    0   10  101   10
[5,]    0    0    0   10  101

Вектор

Если x является вектором, так как субдиагональ и супердиагональ на один элемент короче диагонали, мы должны указать их отдельно - здесь последние два определены как y,

# test values for diagonal and sub/super diagonals
x <- 1:5
y <- 11:14

m <- diag(x)
m[row(m) - col(m) == 1] <- m[row(m) - col(m) == -1] <- y

давая:

> m
     [,1] [,2] [,3] [,4] [,5]
[1,]    1   11    0    0    0
[2,]   11    2   12    0    0
[3,]    0   12    3   13    0
[4,]    0    0   13    4   14
[5,]    0    0    0   14    5

Заметка

Обратите внимание, что такая матрица называется трехдиагональной матрицей, и поиск трехдиагональной R приведет к появлению некоторых соответствующих ссылок.

Я хотел бы создать матрицу разреженной полосы:

# test inputs
x <- 10
n <- 5

library(Matrix)
M <- bandSparse(n, n, #dimensions
                (-1):1, #band, diagonal is number 0
                list(rep(x, n-1), 
                     rep(1+x^2, n), 
                     rep(x, n-1)))
#5 x 5 sparse Matrix of class "dgCMatrix"
#
#[1,] 101  10   .   .   .
#[2,]  10 101  10   .   .
#[3,]   .  10 101  10   .
#[4,]   .   .  10 101  10
#[5,]   .   .   .  10 101

При необходимости его можно легко привести к плотной матрице:

as.matrix(M)
#     [,1] [,2] [,3] [,4] [,5]
#[1,]  101   10    0    0    0
#[2,]   10  101   10    0    0
#[3,]    0   10  101   10    0
#[4,]    0    0   10  101   10
#[5,]    0    0    0   10  101

diagonals пакет может приблизить вас (но не полностью) с fatdiag функция. Вот пример того, как создать матрицу 12x12 и заполнить область вокруг диагонали значением:

> library(diagonals)
> m <- matrix(0, nrow=12, ncol=12)
> fatdiag(m, steps=3) <- 999
> m
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]  999  999  999  999    0    0    0    0    0     0     0     0
 [2,]  999  999  999  999    0    0    0    0    0     0     0     0
 [3,]  999  999  999  999    0    0    0    0    0     0     0     0
 [4,]  999  999  999  999    0    0    0    0    0     0     0     0
 [5,]    0    0    0    0  999  999  999  999    0     0     0     0
 [6,]    0    0    0    0  999  999  999  999    0     0     0     0
 [7,]    0    0    0    0  999  999  999  999    0     0     0     0
 [8,]    0    0    0    0  999  999  999  999    0     0     0     0
 [9,]    0    0    0    0    0    0    0    0  999   999   999   999
[10,]    0    0    0    0    0    0    0    0  999   999   999   999
[11,]    0    0    0    0    0    0    0    0  999   999   999   999
[12,]    0    0    0    0    0    0    0    0  999   999   999   999

Вы также можете указать size, что может быть более полезным для вас... это заполнит столько ячеек по диагонали:

> m <- matrix(0, nrow=12, ncol=12)
> fatdiag(m, size=2) <- 999
> m
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]  999  999    0    0    0    0    0    0    0     0     0     0
 [2,]  999  999    0    0    0    0    0    0    0     0     0     0
 [3,]    0    0  999  999    0    0    0    0    0     0     0     0
 [4,]    0    0  999  999    0    0    0    0    0     0     0     0
 [5,]    0    0    0    0  999  999    0    0    0     0     0     0
 [6,]    0    0    0    0  999  999    0    0    0     0     0     0
 [7,]    0    0    0    0    0    0  999  999    0     0     0     0
 [8,]    0    0    0    0    0    0  999  999    0     0     0     0
 [9,]    0    0    0    0    0    0    0    0  999   999     0     0
[10,]    0    0    0    0    0    0    0    0  999   999     0     0
[11,]    0    0    0    0    0    0    0    0    0     0   999   999
[12,]    0    0    0    0    0    0    0    0    0     0   999   999

Когда это будет сделано, вы сможете использовать методы, которые вы используете, чтобы заполнить диагональ желаемым значением. (Так как 71 не делится на что-либо, вам, возможно, придется создать 72x72, а затем отрубить концы.) Не зная контекста вашей проблемы, трудно оценить, насколько приемлема глупость:)

Другие вопросы по тегам