Как генерировать случайный вектор Matlab с этими ограничениями

У меня проблемы с созданием случайного вектора V в Matlab действуют следующие ограничения: (заданные параметры N,D, L, а также theta)

  1. Вектор V должно быть N единицы длиной
  2. Элементы должны иметь в среднем theta
  3. Нет 2 последовательных элементов могут отличаться более чем на +/-10
  4. D == sum(L*cosd(V-theta))

У меня больше всего проблем с последним. Есть идеи?

редактировать
Решения на других языках или формы уравнений одинаково приемлемы. Matlab - просто удобный инструмент для создания прототипов, но окончательный алгоритм будет в java.

редактировать
Из комментариев и первоначальных ответов я хочу добавить некоторые разъяснения и первоначальные мысли.

Я не ищу "действительно случайное" решение из любого стандартного дистрибутива. Я хочу, чтобы псевдослучайно сгенерированная последовательность значений удовлетворяла ограничениям, заданным для набора параметров.

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

Мое первоначальное понимание заключается в том, что тета может быть удалена из рассмотрения до конца, поскольку (2) по существу добавляет тэту к каждому элементу вектора среднего значения 0 (сдвигая среднее значение в тета), а (4) просто снова удаляет это среднее значение. Итак, если вы можете найти решение для тета =0, проблема решена для всех тета.

Как и требовалось, здесь представлен разумный диапазон параметров (не жесткие ограничения, а типичные значения):
5<N<200
3<D<150
L==1
0 < theta < 360

4 ответа

Я бы начал с создания "действительного" вектора. Это должно быть возможно - скажем, рассчитать его для каждой записи, чтобы иметь одинаковое значение.

Как только вы получили этот вектор, я бы применил некоторые преобразования, чтобы "перемешать" его. " Отклонение выборки" является ключевым словом - если случайная последовательность нарушит одно из ваших правил, вы просто не сделаете этого.

В качестве преобразований я придумываю:

  • переключить две записи
  • измените значение одной записи и измените вторую, чтобы сохранить 4-е условие (теоретически вы можете просто перетасовать два до тех пор, пока условие не будет выполнено - но вероятность того, что это произойдет, довольно мала)

Но, может быть, вы можете найти еще немного.

Делайте это разумно часто, и вы получите "правильный" случайный вектор. Теоретически вы должны быть в состоянии получить все допустимые векторы - практически вы можете попытаться создать несколько "начальных" векторов, чтобы это не заняло так много времени.

Вы не даете нам много деталей для работы, поэтому я предполагаю следующее:

  • случайные числа должны быть взяты из [-127+theta +127-theta]
  • все случайные числа будут взяты из равномерного распределения
  • все случайные числа будут иметь тип int8

Затем для первых 3 требований вы можете использовать это:

N = 1e4;
theta = 40;
diffVal = 10;

g = @() randi([intmin('int8')+theta  intmax('int8')-theta], 'int8') + theta;
V = [g(); zeros(N-1,1, 'int8')];
for ii = 2:N
    V(ii) = g();
    while abs(V(ii)-V(ii-1)) >= diffVal
        V(ii) = g();
    end
end

встроить анонимную функцию для большей скорости.

Теперь последнее требование,

D == sum(L*cos(V-theta))

немного странно...cos(V-theta) это особый способ масштабирования данных в [-1 +1] интервал, который умножение с L затем будет масштабироваться до [-L +L], На первый взгляд, вы ожидаете sum усреднить до 0,

Тем не менее, ожидаемое значение cos(x) когда x случайная величина из равномерного распределения в [0 2*pi] является 2/pi (см. здесь, например). На данный момент игнорируем тот факт, что наши пределы отличаются от [0 2*pi], ожидаемое значение sum(L*cos(V-theta)) будет просто уменьшить до постоянного значения 2*N*L/pi,

Как вы можете заставить это равняться некоторой другой константе D вне меня... не могли бы вы остановиться подробнее на этом?

Таким образом, исходя из ваших новых требований, кажется, что вы на самом деле ищете упорядоченный список случайных углов с максимальным изменением угла в 10 градусов (который я сначала преобразую в радианы), так что расстояние и направление от начало до конца и длина ссылки и количество ссылок указаны?

Имитация первоначальной догадки. Он не будет выполняться с ограничениями D и Theta (т.е. с указанным D и указанным Theta)

angles = zeros(N, 1)

for link = 2:N
    angles (link) = theta(link - 1) + (rand() - 0.5)*(10*pi/180)
end

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

dx = sum(L*cos(angle));
dy = sum(L*sin(angle));

D = sqrt(dx^2 + dy^2);
theta = atan2(dy/dx);

стоимость теперь просто разница между вектором, данным моим D а также theta выше и вектор, заданный указанным D а также theta (т.е. входы).

Вам по-прежнему придется применять правило максимального изменения 10 градусов, возможно, это должно просто сделать функцию затрат огромной, если она будет нарушена? Возможно, есть более чистый способ указать ограничения последовательности в алгоритмах оптимизации (я не знаю как).

Я чувствую, что если вы можете найти правильную оптимизацию с правильными параметрами, это должно быть в состоянии симулировать вашу проблему.

Вот способ сделать это. Ясно, что не все комбинации тета, N, L и D являются действительными. Также ясно, что вы пытаетесь моделировать случайные объекты, которые являются довольно сложными. Возможно, вам будет трудно показать что-нибудь полезное в отношении этих векторов.

Сериал, который вы пытаетесь смоделировать, похож на процесс Винера. Итак, я начал с того, что вы можете начать с чего-то случайного, но разумного. Затем я использую это в качестве отправной точки для оптимизации, которая пытается удовлетворить 2,3 и 4. Чем ближе ваше начальное значение к действительному вектору (удовлетворяющему всем вашим условиям), тем лучше сходимость.

function series = generate_series(D, L, N,theta)
s(1) = theta;
for i=2:N,
    s(i) = s(i-1) + randn(1,1);
end
f = @(x)objective(x,D,L,N,theta)
q = optimset('Display','iter','TolFun',1e-10,'MaxFunEvals',Inf,'MaxIter',Inf)
[sf,val] = fminunc(f,s,q);
val
series = sf;



function value= objective(s,D,L,N,theta)
a = abs(mean(s)-theta);
b = abs(D-sum(L*cos(s-theta)));
c = 0;
for i=2:N,
    u =abs(s(i)-s(i-1)) ;
    if u>10,
        c = c + u;
    end
end
value = a^2 + b^2+ c^2;

Кажется, вы пытаетесь смоделировать что-то очень сложное / странное (путь заданной кривизны?), Смотрите вопросы других комментаторов. Тем не менее, вам придется использовать свои знания предметной области, чтобы связать D и L с разумными мю и сигмой, чтобы Wiener выполнял функции инициализации.

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