MATLAB: быстрое создание случайной симметричной матрицы с фиксированной степенью (сумма строк)

я ищу метод для создания, быстрым способом случайной матрицы A со свойствами follwing:

  • A = transpose(A)
  • A(i,i) = 0 для всех I
  • A(i,j) >= 0 для всех i, j
  • sum(A) =~ degree; сумма строк случайным распределением хочу указать (здесь =~ означает примерное равенство).

распределение degree из Матрицы orig, а конкретно degree=sum(orig), таким образом, я знаю, что существуют матрицы с этим распределением.

например: orig=[0 12 7 5; 12 0 1 9; 7 1 0 3; 5 9 3 0]

orig =
 0    12     7     5
12     0     1     9
 7     1     0     3
 5     9     3     0

 sum(orig)=[24 22 11 17];

теперь одна возможная матрица A=[0 11 5 8, 11 0 4 7, 5 4 0 2, 8 7 2 0] is

A = 
 0    11     5     8
11     0     4     7
 5     4     0     2
 8     7     2     0

С sum(A)=[24 22 11 17].

я пробую это довольно долго, но, к сожалению, мои две идеи не сработали:


Вариант 1:

переключатель Nswitch умножить на два случайных элемента:A(k1,k3)--; A(k1,k4)++; A(k2,k3)++; A(k2,k4)--; (транспонированные элементы а).

к сожалению, Nswitch = log(E)*EE=sum(sum(nn))) для того, чтобы матрицы были очень некоррелированными. Как мой E > 5.000.000, это невозможно (в частности, поскольку мне нужно не менее 10 таких матриц).


вариант 2:

я создаю матрицу в соответствии с распределением с нуля. Идея в том, чтобы заполнить каждую строку i С degree(i) числа, основанные на распределении degree:

nn=orig;
nnR=zeros(size(nn));
for i=1:length(nn)
    degree=sum(nn);
    howmany=degree(i);
    degree(i)=0;
    full=rld_cumsum(degree,1:length(degree));
    rr=randi(length(full),[1,howmany]);
    ff=full(rr);
    xx=i*ones([1,length(ff)]);
    nnR = nnR + accumarray([xx(:),ff(:)],1,size(nnR));
end
A=nnR;

однако, в то время как sum(A')=degree, sum(A) систематически отклоняется от degree и я не могу найти причину для этого.

небольшие отклонения от degree, конечно, хорошо, но, похоже, системные отклонения в частности матриц содержат в некоторых местах большие числа.


я был бы очень рад, если бы кто-нибудь мог показать мне быстрый метод для version1, или причину систематического отклонения дистрибутива в версии 2, или метод для создавайте такие матрицы по-другому. Спасибо!


Edit:

это проблема в matsmathпредложенное решение: Представьте, что у вас есть матрица:

orig = 
 0    12     3     1
12     0     1     9
 3     1     0     3
 1     9     3     0

С r(i)=[16 22 7 13].

  • Шаг 1: r(1)=16, мой случайный целочисленный раздел равен p (i)=[0 7 3 6].
  • Шаг 2: Проверьте, что все p(i)
  • Шаг 3:

мой случайный матрица начинается выглядит как

A = 
 0    7     3     6
 7    0     .     .
 3    .     0     .
 6    .     .     0

С новым вектором суммы строк rnew=[r(2)-p (2),..., r (n) - p(n)]=[15 4 7]

вторая итерация (здесь возникает проблема):

  • Шаг 1: rnew(1)=15, мой случайный целочисленный раздел p(i)=[0 A B]: rnew (1)=15=A+B.
  • Шаг 2: Проверьте, что все p(i)противоречие :-/

Edit2:

это код, представляющий (насколько мне известно) решение, опубликованное Давида Айзенштата:

orig=[0 12 3 1; 12 0 1 9; 3 1 0 3; 1 9 3 0];
w=[2.2406 4.6334 0.8174 1.6902];
xfull=zeros(4);

for ii=1:1000
    rndmat=[poissrnd(w(1),1,4); poissrnd(w(2),1,4); poissrnd(w(3),1,4); poissrnd(w(4),1,4)];
    kkk=rndmat.*(ones(4)-eye(4)); % remove diagonal
    hhh=sum(sum(orig))/sum(sum(kkk))*kkk; % normalisation
    xfull=xfull+hhh;
end

xf=xfull/ii;
disp(sum(orig)); % gives [16    22     7    13]
disp(sum(xf));   % gives [14.8337    9.6171   18.0627   15.4865] (obvious systematic problem)
disp(sum(xf'))   % gives [13.5230   28.8452    4.9635   10.6683] (which is also systematically different from [16, 22, 7, 13]

2 ответов


поскольку этого достаточно, чтобы приблизительно сохранить последовательность степеней, позвольте мне предложить случайное распределение, где каждая запись выше диагонали выбирается в соответствии с распределение Пуассона. Моя интуиция подсказывает, что мы хотим найти веса w_i такое, что i,j запись i != j и означает w_i*w_j (все элементы диагонали равны нулю). Это дает нам нелинейную систему уравнений:

for all i, (sum_{j != i} w_i*w_j) = d_i,

здесь d_i степень i. Эквивалентно,

for all i, w_i * (sum_j w_j) - w_i^2 = d_i.

последнее можно решить, применив метод Ньютона как описано ниже из начального решения w_i = d_i / sqrt(sum_j d_j).

как только мы получим w_iС, мы можем попробовать повторно используя poissrnd для генерации выборок сразу нескольких распределений Пуассона.


(если у меня есть время, я попробую реализовать это в numpy.)

Якобиева матрица системы уравнений для 4 на 4 проблема is

(w_2 + w_3 + w_4) w_1               w_1               w_1
w_2               (w_1 + w_3 + w_4) w_2               w_2
w_3               w_3               (w_1 + w_2 + w_4) w_3
w_4               w_4               w_4               (w_1 + w_2 + w_3).

в общем, давайте A быть диагональной матрицей, где A_{i,i} = sum_j w_j - 2*w_i. Пусть u = [w_1, ..., w_n]' и v = [1, ..., 1]'. Якобиан может быть написано J = A + u*v'. Обратное задается --Шерман Моррисон формула

                              A^-1*u*v'*A^-1
J^-1 = (A + u*v')^-1 = A^-1 - -------------- .
                              1 + v'*A^-1*u

для шага Ньютона нам нужно вычислить J^-1*y для некоторых y. Это можно сделать прямолинейно во времени O(n) используя приведенное выше уравнение. Я добавлю больше деталей, когда будет возможность.


первый подход (основанный на version2)

пусть ваш вектор суммы строк задан матрицей orig [r (1), r(2),..., r (n)].

Step 1. Take a random integer partition of the integer r(1) into exactly n-1 parts, say p(2), p(3), ..., p(n)
Step 2. Check if p(i)<=r(i) for all i=2...n. If not, go to Step 1.
Step 3. Fill out your random matrix first row and colum by the entries 0, p(2), ... , p(n), and consider the new row sum vector [r(2)-p(2),...,r(n)-p(n)].

повторите эти шаги с матрицей Порядка n-1.

дело в том, что вы рандомизируете одну строку за раз и уменьшаете проблему до поиска матрицы размера на один меньше.


как указал OP в комментарии, этот наивный алгоритм терпит неудачу. Причина в том, что рассматриваемые матрицы имеют дальше необходимое условие на их записи следующим образом:

факт:

если A является ориг-матрицей с суммами строк [r(1), r(2), ..., r(n)] затем обязательно для каждого i=1..n он считает, что r(i)<=-r(i)+sum(r(j),j=1..n).

то есть, любая сумма строк, скажем ith,r(i), обязательно не больше, чем сумма других сумм строк (не включая r(i)).

в свете этого возможен пересмотренный алгоритм. Обратите внимание, что в шаге 2b. мы проверяем, имеет ли новый вектор суммы строк свойство, описанное выше.

Step 1. Take a random integer partition of the integer r(1) into exactly n-1 parts, say p(2), p(3), ..., p(n)
Step 2a. Check if p(i)<=r(i) for all i=2...n. If not, go to Step 1.
Step 2b. Check if r(i)-p(i)<=-r(i)+p(i)+sum(r(j)-p(j),j=2..n) for all i=2..n. If not, go to Step 1.
Step 3. Fill out your random matrix first row and colum by the entries 0, p(2), ... , p(n), and consider the new row sum vector [r(2)-p(2),...,r(n)-p(n)].

второй подход (основанный на version1)

я не уверен, что такой подход дает вам случайные матрицы, но это, безусловно, дает вам разные матриц.

идея здесь в том, чтобы изменить некоторые части вашего orig матрица локально, таким образом, который поддерживает все его свойства.

вы должны посмотреть для случайной подматрицы 2x2 ниже главной диагонали, которая содержит строго положительные записи, такие как [[a,b],[c,d]] и perturbe его содержимое на случайное значение r to [[a+r,b-r],[c-r,d+r]]. Вы также делаете то же самое изменение над главной диагональю, чтобы сохранить вашу новую матрицу симметричной. Здесь дело в том, что изменения внутри записей "отменяют" друг друга.

конечно, r следует выбирать таким образом, чтобы b-r>=0 и c-r>=0.

вы можете следовать этой идее для того чтобы доработать большие подматрицы тоже. Например, вы можете выбрать 3 координаты случайных строк r1, r2, r2 и 3 случайных координат столбца c1, c2 и c3 а затем внести изменения в свой orig матрица на 9 позиции (ri,cj) следующим образом: вы измените свой 3x3 подматрицу [[a b c],[d e f], [g h i]] to [[a-r b+r c] [d+r e f-r], [g h-r i+r]]. Вы делаете то же самое в транспонированных местах. Опять же, случайное значение r должен быть выбран таким образом, чтобы a-r>=0 и f-r>=0 и h-r>=0. Более того,c1 и r1 и c3 и r3 должен быть отличным, так как вы не можете изменить 0 записей в главной диагонали матрицы orig.

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