Как генерировать случайный вектор Matlab с этими ограничениями
У меня проблемы с созданием случайного вектора V
в Matlab действуют следующие ограничения: (заданные параметры N
,D
, L
, а также theta
)
- Вектор
V
должно бытьN
единицы длиной - Элементы должны иметь в среднем
theta
- Нет 2 последовательных элементов могут отличаться более чем на +/-10
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 выполнял функции инициализации.