2013-02-08 2 views
4

есть. Я собираюсь создать 10^6 случайных точек в matlab с этими конкретными символами. точки должны быть внутри сферы с радиальными 25, 3-D, поэтому мы имеем x, y, z или r, theta, phi. минимальное расстояние между точками. во-первых, я решил создать точки, а затем проверить расстояния, а затем опустить точки с не имеют этих условий. но он может опустить многие моменты. Другим способом является использование RSA (Random Sequential Addition), это означает создание точек один за другим с этим минимальным расстоянием между ними. например, генерировать первую точку, а затем генерировать вторую случайным образом из минимального расстояния от точки 1. и продолжать до достижения 10^6 пунктов. , но это занимает много времени, и я не могу достичь 10^6 баллов, так как скорость поиска подходящей позиции для новых точек займет много времени.генерировать 3-х случайные точки с минимальным расстоянием между каждым из них?

Сейчас я использую эту программу:

Nmax=10000; 
R=25; 
P=rand(1,3); 
k=1; 
while k<Nmax 
theta=2*pi*rand(1); 
phi=pi*rand(1); 
r = R*sqrt(rand(1)); 
% convert to cartesian 
x=r.*sin(theta).*cos(phi); 
y=r.*sin(theta).*sin(phi); 
z=r.*cos(theta); 
P1=[x y z]; 
r=sqrt((x-0)^2+(y-0)^2+(z-0)^2); 
D = pdist2(P1,P,'euclidean'); 
% euclidean distance 

    if D>0.146*r^(2/3) 
     P=[P;P1]; 
     k=k+1; 
    end 
    i=i+1; 
end 
x=P(:,1);y=P(:,2);z=P(:,3); plot3(x,y,z,'.'); 

Как эффективно генерировать очки, эти условия? спасибо.

+0

Я использую эту программу: –

+0

Nmax = 10000; R = 25; P = rand (1,3); k = 1; , в то время как k 0,146 * r^(2/3) P = [P; P1]; k = k + 1; конец i = i + 1; конец x = P (:, 1); y = P (:, 2); z = P (:, 3); plot3 (x, y, z, '.'); –

ответ

4

Я более подробно рассмотрел ваш алгоритм и пришел к выводу, что НИКАКОЙ ПУТЬ он никогда не будет работать - по крайней мере, если вы действительно хотите получить миллион очков в этой сфере. Существует простая картина, которая объясняет, почему нет - это график количества очков, которые вам нужно проверить (используя вашу технику RSA), чтобы получить еще одну «хорошую» точку. Как вы можете видеть, это идет асимптотическим в несколько тысяч точек (я провел несколько более быстрый алгоритм против 200k точек, чтобы произвести это):

graph of points tested

Я не знаю, если вы когда-нибудь пытались вычислить теоретическое количество очков, которые вы могли бы поместить в свою сферу, когда у вас их прекрасно устроено, но я начинаю подозревать, что число намного меньше 1E6.

Полный код, который я использовал для исследования, плюс вывод, который он сгенерировал, можно найти here. Я никогда не дошел до того, как я описал в своем предыдущем ответе ... в настройке, которую вы описали, было слишком много.

EDIT: Я начал думать, что это может быть невозможно, даже при «идеальном» расположении, чтобы добраться до 1M точек. Я сделал простую модель для себя следующим образом:

Представьте, что вы начинаете с «внешней оболочки» (r = 25) и пытаетесь установить точки на равных расстояниях. Если разделить площадь «оболочка» в области одного «запретного диска» (радиус r_sub_crit), вы получите (высокую) оценку числа точек на таком расстоянии:

numpoints = 4*pi*r^2/(pi*(0.146 * r^(2/3))^2) ~ 188 * r^(2/3) 

Следующие «оболочка» должна быть в радиусе, равном 0,146 * r^(2/3) меньше, но если вы думаете о точках, которые очень тщательно организованы, вы можете приблизиться чуть ближе. Опять же, давайте будем щедрыми и скажем, что оболочки могут быть всего на 1/sqrt (3) ближе, чем критерии. Затем вы можете начать на внешней оболочке и работать ваш путь в, используя простой питон скрипт:

import scipy as sc 
r = 25 
npts = 0 
def rc(r): 
    return 0.146*sc.power(r, 2./3.) 
while (r > rc(r)): 
    morePts = sc.floor(4/(0.146*0.146)*sc.power(r, 2./3.)) 
    npts = npts + morePts 
    print morePts, ' more points at r = ', r 
    r = r - rc(r)/sc.sqrt(3) 

print 'total number of points fitted in sphere: ', npts 

Выход этого:

1604.0 more points at r = 25 
1573.0 more points at r = 24.2793037966 
1542.0 more points at r = 23.5725257555 
1512.0 more points at r = 22.8795314897 
1482.0 more points at r = 22.2001865995 
1452.0 more points at r = 21.5343566722 
1422.0 more points at r = 20.8819072818 
1393.0 more points at r = 20.2427039885 
1364.0 more points at r = 19.6166123391 
1336.0 more points at r = 19.0034978659 
1308.0 more points at r = 18.4032260869 
1280.0 more points at r = 17.8156625053 
1252.0 more points at r = 17.2406726094 
1224.0 more points at r = 16.6781218719 
1197.0 more points at r = 16.1278757499 
1171.0 more points at r = 15.5897996844 
1144.0 more points at r = 15.0637590998 
1118.0 more points at r = 14.549619404 
1092.0 more points at r = 14.0472459873 
1066.0 more points at r = 13.5565042228 
1041.0 more points at r = 13.0772594652 
1016.0 more points at r = 12.6093770509 
991.0 more points at r = 12.1527222975 
967.0 more points at r = 11.707160503 
943.0 more points at r = 11.2725569457 
919.0 more points at r = 10.8487768835 
896.0 more points at r = 10.4356855535 
872.0 more points at r = 10.0331481711 
850.0 more points at r = 9.64102993012 
827.0 more points at r = 9.25919600154 
805.0 more points at r = 8.88751153329 
783.0 more points at r = 8.52584164948 
761.0 more points at r = 8.17405144976 
740.0 more points at r = 7.83200600865 
718.0 more points at r = 7.49957037478 
698.0 more points at r = 7.17660957023 
677.0 more points at r = 6.86298858965 
657.0 more points at r = 6.55857239952 
637.0 more points at r = 6.26322593726 
618.0 more points at r = 5.97681411037 
598.0 more points at r = 5.69920179546 
579.0 more points at r = 5.43025383729 
561.0 more points at r = 5.16983504778 
542.0 more points at r = 4.91781020487 
524.0 more points at r = 4.67404405146 
506.0 more points at r = 4.43840129415 
489.0 more points at r = 4.21074660206 
472.0 more points at r = 3.9909446055 
455.0 more points at r = 3.77885989456 
438.0 more points at r = 3.57435701766 
422.0 more points at r = 3.37730048004 
406.0 more points at r = 3.1875547421 
390.0 more points at r = 3.00498421767 
375.0 more points at r = 2.82945327223 
360.0 more points at r = 2.66082622092 
345.0 more points at r = 2.49896732654 
331.0 more points at r = 2.34374079733 
316.0 more points at r = 2.19501078464 
303.0 more points at r = 2.05264138052 
289.0 more points at r = 1.91649661498 
276.0 more points at r = 1.78644045325 
263.0 more points at r = 1.66233679273 
250.0 more points at r = 1.54404945973 
238.0 more points at r = 1.43144220603 
226.0 more points at r = 1.32437870508 
214.0 more points at r = 1.22272254805 
203.0 more points at r = 1.1263372394 
192.0 more points at r = 1.03508619218 
181.0 more points at r = 0.94883272297 
170.0 more points at r = 0.867440046252 
160.0 more points at r = 0.790771268402 
150.0 more points at r = 0.718689381062 
140.0 more points at r = 0.65105725389 
131.0 more points at r = 0.587737626612 
122.0 more points at r = 0.528593100237 
113.0 more points at r = 0.473486127367 
105.0 more points at r = 0.422279001431 
97.0 more points at r = 0.374833844693 
89.0 more points at r = 0.331012594847 
82.0 more points at r = 0.290676989951 
75.0 more points at r = 0.253688551418 
68.0 more points at r = 0.219908564725 
61.0 more points at r = 0.189198057381 
55.0 more points at r = 0.161417773651 
49.0 more points at r = 0.136428145311 
44.0 more points at r = 0.114089257597 
38.0 more points at r = 0.0942608092113 
33.0 more points at r = 0.0768020649149 
29.0 more points at r = 0.0615717987589 
24.0 more points at r = 0.0484282253244 
20.0 more points at r = 0.0372289153633 
17.0 more points at r = 0.0278306908104 
13.0 more points at r = 0.0200894920319 
10.0 more points at r = 0.013860207063 
8.0 more points at r = 0.00899644813842 
5.0 more points at r = 0.00535025545232 

total number of points fitted in sphere: 55600.0 

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

+1

Еще одна вещь, которая пришла мне в голову - плотность точек - это функция от r - вы произвольно выбираете выборку в r при создании случайных точек, и вы, вероятно, не должны этого делать. Это сделало бы поколение немного более эффективным - но вы все еще против вышеуказанного предела ... Когда вы смотрите на распределение в 3D, оно ОЧЕНЬ неоднородно (вы посмотрели полный код, который я разместил?) – Floris

3

Есть много вещей, которые вы могли бы сделать, чтобы улучшить свою программу - как алгоритм, так и код.

На стороне кода, одна из вещей, которые действительно замедлят является тот факт, что не только вы используете for цикл (который медленно), но в линии

P = [P;P1]; 

вы добавляете элементы к массиву. Каждый раз, когда это происходит, Matlab нужно найти новое место для размещения данных, копируя все точки в процессе. Это быстро становится очень медленным. Предварительное выделение массива с

P = zeros(1000000, 3); 

отслеживающих число N точек вы нашли до сих пор, и изменение расчета расстояния до

D = pdist2(P1, P(1:N, :), 'euclidean'); 

бы по крайней мере, адрес ...

Другая проблема заключается в том, что вы проверяете новые очки против всех найденных ранее очков - поэтому, когда у вас есть 100 очков, вы проверяете около 100x100, за 1000 - 1000x1000. Вы можете видеть, что этот алгоритм O (N^3), по крайней мере ... не считая того, что вы получите больше «промахов» по ​​мере роста плотности. Алгоритм O (N^3) с N = 10E6 занимает не менее 10E18 циклов; если бы у вас была машина 4 ГГц с одним тактовым циклом для сравнения, вам понадобилось бы 2.5E9 секунд = примерно 80 лет. Вы можете попробовать параллельную обработку, но это просто грубая сила - кто этого хочет?

Я рекомендую вам подумать о том, чтобы разбить проблему на более мелкие кусочки (довольно буквально): например, если вы разделите сферу на маленькие квадратики размером примерно с вашего максимального расстояния, и для каждой коробки вы отслеживаете какие точки в нем, тогда вам нужно только проверить очки в «этом» поле и его ближайших соседях - всего 27 ящиков. Если ваши коробки имеют ширину 2,5 мм, у вас будет 100x100x100 = 1M боксов. Это похоже на много, но теперь ваше время вычисления будет резко сокращено, так как у вас будет (по окончанию алгоритма) только 1 балл в среднем за поле ... Конечно, с критерием расстояния, который вы используете, вы будете есть больше точек рядом с центром, но это детали.

Структура данных, которая вам нужна, будет массивом ячеек 100x100x100, и каждая ячейка содержит индекс хороших точек, найденных до сих пор «в этой ячейке».Проблема с массивом ячеек заключается в том, что он не поддается векторизации. Если вместо этого у вас есть память, вы можете назначить ее как 4D-массив размером 10x100x100x100, если у вас будет не более 10 очков на ячейку (если вы это сделаете, вам придется обрабатывать это отдельно, работайте со мной здесь ...) , Используйте индекс -1 точек пока не найдено

Тогда ваш чек будет что-то вроде этого:

% initializing: 
bigList = zeros(10,102,102,102)-1; % avoid hitting the edge... 
NPlist = zeros(102, 102, 102); % track # valid points in each box 
bottomcorner = [-25.5, -25.5, -25.5]; % boxes span from -25.5 to +25.5 
cellSize = 0.5; 

.

% in your loop: 
P1= [x, y, z]; 
cellCoords = ceil(P1/cellSize); 
goodFlag = true; 
pointsSoFar = bigList(:, cellCoords(1)+(-1:1), cellCoords(2)+(-1:1), cellCoords(3)+(-1:1)); 
pointsToCheck = find(pointsSoFar>0); % this is where the big gains come... 
r=sum(P1.^2); 
D = pdist2(P1,P(pointsToCheck, :),'euclidean'); % euclidean distance 

if D>0.146*r^(2/3) 
    P(k,:) = P1; 
    % check the syntax of this line... 
    cci = ind2sub([102 102 102], cellCoords(1), cellCoords(2), cellCoords(3)); 
    NP(cci)=NP(cci)+1; % increasing number of points in this box 
    % you want to handle the case where this > 10!!! 
    bigList(NP(cci), cci) = k; 
    k=k+1; 
end 
.... 

Я не знаю, можете ли вы взять его отсюда; если вы не можете сказать это в заметках, и у меня может быть какое-то время в эти выходные, чтобы более подробно описать это. Есть способы ускорить его с помощью некоторой векторизации, но с этим быстро становится сложно справиться.

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

2

Я нашел the reference - «Динамическая динамика роста опухоли мозга с использованием трехмерного сотового автомата», Ансал и др. (2000).

Я согласен, что это озадачивает - пока вы не осознаете одну важную вещь. Они сообщают о своих результатах в mm, но ваш код был написан в cm. Хотя это может показаться незначительным, формула для «критического радиуса», rc = 0.146r^(2/3) включает в себя константу, 0.146, размерность которой составляет mm^(1/3), а не cm^(1/3).

Когда я делаю это изменение в своем коде на языке python, чтобы оценить количество возможных узлов решетки, он скачет на коэффициент 10. Теперь они заявили, что использовали «предел помех» 0,38 - номер, на котором вы действительно не можете найти больше сайтов. Если вы включите этот предел, я предсказываю, что не может быть найдено более 200 тысяч точек - все еще не хватает их 1.5M, но не настолько сумасшедшим.

Возможно, вы обратитесь к авторам, чтобы обсудить это с ними? Если вы хотите включить меня в разговор, вы можете написать мне по электронной почте: SO (всего две буквы) по адресу my handle name dot united states. В той же области, где я размещал ссылки выше ...

+0

хорошо, спасибо за вашу полезную помощь. Я обязательно свяжусь с авторами и, конечно, сообщит вам их ответ по электронной почте. –

+0

Еще одна вещь - я только заметил, что код, который я использовал для создания кривой выше, использовал r = 1; поскольку мы намереваемся использовать r = 250 (работаем в мм), ситуация изменится совсем немного. Собираюсь выполнить некоторые вычисления, когда у меня есть минута. – Floris

+0

Я также понимаю одно, что мой код тоже в мм. Как вы могли сказать, что это в см? это r = 25 мм. как размер опухоли в мозге составляет 25 см? –