@DaylightIsBurning

Однородный итеративный семплинг в многомерном пространстве?

Есть функция от Nd параметров f(x[1], x[2], x[3],…, x[Nd]). Даны граничные значения для каждого из параметров. Я хочу итеративно вычислять значения этой функции так, что бы чем дальше, тем больше была плотность точек перебора, при чем плотность росла равномерно для всех аргументов, во всём пространстве.

В одном измерении сразу на ум приходит следующий алгоритм: берём отрезок, делим на 2, каждый полученный участок на 2 и т.д сокращаем интервал семплирования. Подскажите, как можно эффективно реализовать подобный подход в многомерном пространстве, при чем вычисления эти будут идти параллельно, что не должно быть сложно.

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

Можно использовать генератор случайных чисел, но, тогда чем больше итераций, тем больше вероятность возникновения локальных уплотнений/пустот, а у меня задача — обеспечить максимум минимальной плотности, что бы не было в одном месте густо, в другом — пусто.
  • Вопрос задан
  • 2816 просмотров
Пригласить эксперта
Ответы на вопрос 3
@DaylightIsBurning Автор вопроса
Вроде придумал, для одномерного случая:
{0/1, 1/1}; {1/2}; {1/4, 3/4}; {1/8, 3/8, 5/8, 7/8}; {1/16,3/16,5/16,7/16,9/16,11/16,13/16,15/16};…
То есть в числителе последовательно перебираем все нечетные, в знаменателе чем глубже, тем больше степень двойки. Не надо никаких if и хранения «пройденных» значений.
Ответ написан
Комментировать
@Sayonji
Да точно так же можно, как и при делении на два.
Предположим, аргументы нормированны, то есть от 0 до 1.
Тогда по шагам:
1) точка 0.5; 0.5; 0.5,…
2) точки (0.25a), (0.25b), (0.25c),… | a,b,c = 1...3
3) точки (0.125a), (0.125b), (0.125c),… | a,b,c = 1...7

Ну, само собой, каждый раз берем те, которые еще не брали.

Как получать точки для итерации?
iters = new int[Nd] ;
for (i = 1; ; i++) { // номер итерации
    step = 1 / 2^i; // полдлины интервала семплирования
    for ( /* iters пробегает все возможные наборы из чисел от 1 до (2^i - 1) */ ) {
        if ( /* все числа в iters четные */ )
            continue; // уже брали раньше
        sample F(iters[0] * step, iters[1] * step, iters[2] * step, ...)
    }
}

Ну и в строчке с sample надо повозиться с аргументами, чтобы сдвинуть их обратно в те диапазоны, где они были.

Как добиться однородной плотности по всем аргументам. Если у них разные, но не слишком, диапазоны, нормировать их нужно самым большим из них. Т.е. сдвинуть все в [0; x], где x будет равно 1 только для самого длинного диапазона. А потом во втором форе (который будет работать как куча вложенных друг в друга) отсекать лишние хвосты. Т. е. если, например, 0.125 * iters[2] уже больше, чем величина х для третьего аргумента, то по этой переменной дальше не итерируем. Перед входом во второй for эти границы можно просчитать, это совсем несложно.
И последнее. Если диапазоны отличаются значительно, то может иметь смысл как-то посчитать, с какой итерации следует начинать цикл, т.к. часть из них будет пропущена. Тем больше, чем больше различаются диапазоны.
Как-то так, я думаю.
Ответ написан
@DaylightIsBurning Автор вопроса
-
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы