Объявление переменных в Python 2.7x, чтобы избежать проблем позже - PullRequest
0 голосов
/ 26 мая 2018

Я новичок в Python, пришедший из MATLAB, и давно из C. Я написал скрипт в MATLAB, который имитирует перенос наносов в реках как марковский процесс.Код случайным образом размещает круги произвольного диаметра в прямоугольной области заданного размера.Круги неоднородного размера, нарисованы случайным образом из заданного диапазона размеров.Я не знаю, сколько раз я буду проходить через операцию размещения круга, поэтому я использую цикл while для завершения процесса.В попытке быть более ориентированным на сообщество, я перевожу скрипт MATLAB на Python.Я использовал онлайн-инструмент OMPC, чтобы начать, и работал с ним вручную из автоматически переведенной версии (это было не очень полезно, что неудивительно).Для отладки кода на ходу я использую сгенерированные MATLAB результаты, чтобы обычно сравнивать и сравнивать с результатами в Python.Мне кажется очевидным, что я объявил переменные таким образом, что это приводит к проблемам при выполнении вычислений в сценарии.Вот два примера непротиворечивых проблем между различными случаями выполнения кода.Во-первых, код сгенерировал то, что я считаю массивами внутри массивов, потому что скрипт возвращает результаты, которые выглядят следующим образом:

  • array ([[True] [False]], dtype = bool)

Этот результат был сгенерирован для следующего фрагмента кода в операции overlap_logix:

CenterCoord_Array = np.asarray(CenterCoordinates)
Diameter_Array = np.asarray(Diameter)
dist_check = ((CenterCoord_Array[:,0] - x_Center) ** 2 + (CenterCoord_Array[:,1] - y_Center) ** 2) ** 0.5
radius_check = (Diameter_Array / 2) + radius
radius_check_update = np.reshape(radius_check,(len(radius_check),1))
radius_overlap = (radius_check_update >= dist_check)
    # Now actually check the overalp condition.
    if np.sum([radius_overlap]) == 0:
        # The new circle does not overlap so proceed.
        newCircle_Found = 1
        debug_value = 2
    elif np.sum([radius_overlap]) == 1:
        # The new circle overlaps with one other circle
        overlap = np.arange(0,len(radius_overlap), dtype=int)
        overlap_update = np.reshape(overlap,(len(overlap),1))
        overlap_logix = (radius_overlap == 1)
        idx_true = overlap_update[overlap_logix]
        radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)

Аналогичный результат для того же прогона был получен для переменных:

  • radius_check_update
  • radius_overlap
  • overlap_update

Вот тот же фрагмент кода для рабочей версии MATLAB (согласно запросу):

distcheck = ((Circles.CenterCoordinates(1,:)-x_Center).^2 +  (Circles.CenterCoordinates(2,:)-y_Center).^2).^0.5;
radius_check = (Circles.Diameter ./ 2) + radius;
radius_overlap = (radius_check >= distcheck);
    % Now actually check the overalp condition.
    if sum(radius_overlap) == 0
        % The new circle does not overlap so proceed.
        newCircle_Found = 1;
        debug_value = 2;
    elseif sum(radius_overlap) == 1
        % The new circle overlaps with one other circle
        temp = 1:size(radius_overlap,2);
        idx_true = temp(radius_overlap == 1);
        radius = distcheck(1,idx_true) - (Circles.Diameter(1,idx_true)/2);

ВВерсия Python Я создал массивы из списков, чтобы было проще работать с содержимым (первые две строки фрагмента кода).Массив в массиве result и создание массивов для доступа к данным подсказывает мне, что я неправильно объявил типы переменных, но я не уверен.Кроме того, некоторые переменные имеют размер, например, (2L,) (числовое измерение будет меняться при размещении кружков), где нет второго измерения.Это создает очевидные проблемы, когда я пытаюсь использовать массив в операции с другим массивом размером (2L, 1L).Из-за этих проблем я начал перекраивать массивы, а затем остановился, потому что решил, что это хаки, потому что я объявил одну или несколько переменных неправильно.Во-вторых, для этого же запуска я обнаружил следующую ошибку:

  • TypeError: объект 'numpy.ndarray' не может быть вызван

для операции:

radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)

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

https://github.com/smchartrand/MarkovProcess_Bedload

Я настроил код для запуска с некоторыми начальнымизначения параметров, поэтому не нужно принимать решения;эти значения параметров дают ожидаемые результаты в сценарии на основе MATLAB, которые выглядят примерно так при построении графика: enter image description here

Итак, у меня, похоже, возникают проблемы с операциями в строках 151-165, в зависимости от значения теста np.sum ([radius_overlap]) , и я думаю, что это потому, что я неправильно объявил типы переменных, но я действительно не уверен.Я могу с уверенностью сказать, что версия Python и версия MATLAB согласованы в выводе через первый шаг цикла while и строку кода 127, которая входит во второй этап цикла while.Ниже этого пункта в коде вышеописанные проблемы в конечном итоге приводят к сбою сценария.Иногда выполнение скрипта выполняется на 15%, а иногда - не до 5% - это связано со случайным характером размещения кругов.Я готовлю код в IDE Spyder (Python 2.7) и публично поделюсь рабочим кодом в рамках моего исследования.Я был бы очень признателен за любую помощь, которая может быть предложена для выявления моих ошибок и неправильных применений в практике программирования на python.

1 Ответ

0 голосов
/ 29 мая 2018

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

Stackoverflow Вопрос 176011

SciPy FAQ

SciPy NumPy для пользователей Matlab

Третья веб-страница была очень полезной для меня, пришедшей из MATLAB.Вот модифицированный и рабочий фрагмент кода Python, который относится к исходному фрагменту, представленному выше:

dist_check = ((CenterCoordinates[0,:] - x_Center) ** 2 + (CenterCoordinates[1,:] - y_Center) ** 2) ** 0.5
radius_check = (Diameter / 2) + radius
radius_overlap = (radius_check >= dist_check)
# Now actually check the overalp condition.
if np.sum([radius_overlap]) == 0:
    # The new circle does not overlap so proceed.
    newCircle_Found = 1
    debug_value = 2
elif np.sum([radius_overlap]) == 1:
    # The new circle overlaps with one other circle
    overlap = np.arange(0,len(radius_overlap[0]), dtype=int).reshape(1, len(radius_overlap[0]))
    overlap_logix = (radius_overlap == 1)
    idx_true = overlap[overlap_logix]
    radius = dist_check[idx_true] - (Diameter[0,idx_true] / 2)

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

  • CenterCoordinates и
  • Diameter

как пустые массивы, тогда как я инициализировал их как списки вопубликованный вопрос.Это сделало несколько математических операций более простыми.Я также неправильно индексировал переменные с помощью скобок (), в отличие от правильного метода с использованием скобок [].Вот пример исправления, которое я сделал, что помогло коду выполнить в соответствии с намеченным:

  • Неправильно: radius = dist_check (idx_true, 1) - (Diameter (idx_true, 1) / 2)
  • Исправить: radius = dist_check [idx_true] - (Diameter [0, idx_true] / 2)

Этот пример также показывает, что у меня были проблемы с размерами массива, которые я исправлял переменными по переменным.Я до сих пор не уверен, является ли мой рабочий код наиболее питонным или наиболее эффективным способом случайного заполнения прямоугольной области, но я успешно проверил его примерно 100 раз.Пересмотренный и рабочий код можно скачать здесь:

Рабочий скрипт Python для случайного заполнения прямоугольной области кружками

Вот изображение окончательных результатов для успешного запускарабочего кода:

enter image description here

Основными уроками для меня были: (1) числовые массивы более эффективны для повторяющихся численных расчетов и (2) размерностьМассивы, которые я создал, не всегда были такими, как я ожидал, и нужно соблюдать осторожность при создании массивов.Спасибо тем, кто посмотрел на мой вопрос и попросил разъяснений.

...