2011-01-08 2 views
3

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

[a b; c d] 

Я хочу найти структуру данных, которая позволит для a, b, c, d к либо действительных чисел или случайных величин. В качестве примера, допустим, что a = 1, b = -1, c = 2 но пусть d будет нормально распределенной случайной величиной со средним значением 0 и стандартным отклонением 1.

Структура данных, которые я имею в виду не даст никакого значения для d. Тем не менее, я также хочу иметь возможность проектировать функцию, которая может принимать в структуре, моделировать uniform(0,1), получить значение для d с использованием обратного CDF и затем выплюнуть фактическую матрицу.

У меня есть несколько идей для этого (все связано с функцией MATLAB icdf), но хотелось бы знать, как это сделали бы более опытные программисты. В этом приложении важно, чтобы структура была «худой», так как я буду работать с очень большими матрицами, и память будет проблемой.

EDIT # 1:

Спасибо всем за отзывы. Я решил использовать структуру ячеек и хранить случайные переменные в качестве функций. Чтобы сэкономить время обработки приложений большого масштаба, я решил указать местоположение случайных величин, чтобы сэкономить время во время «оценки».

+1

ли все случайные элементы, поддерживаемые всегда нормально распределены и независимы? Или вам нужно поддерживать другие дистрибутивы и/или ковариацию? – aschepler

+0

Более подробная информация о том, как будут выглядеть эти большие матрицы, поможет нам дать вам более конкретные решения. В частности, будут ли случайные значения сгруппированы в подматрицы в большей матрице или они будут разбросаны по всей большей матрице? – gnovice

+0

@aschepler: Мне нужно, чтобы он поддерживал пользовательские случайные переменные, а также другие общие типы случайных величин (например, нормальный, бета, единообразный и т. Д.) –

ответ

3

Одним из решений является создание вашей матрицы изначально как cell array, содержащей как числовые значения, так и function handles, для функций, предназначенных для генерации значения для этой записи. Для примера, вы можете сделать следующее:

generatorMatrix = {1 -1; 2 @randn}; 

Тогда вы могли бы создать функцию, которая принимает матрицу выше формы, evaluates the cells containing function handles, затем объединяют результаты с помощью цифровых входов клеток в create a numeric matrix использовать для дальнейших расчетов :

function numMatrix = create_matrix(generatorMatrix) 
    index = cellfun(@(c) isa(c,'function_handle'),... %# Find function handles 
        generatorMatrix); 
    generatorMatrix(index) = cellfun(@feval,...  %# Evaluate functions 
            generatorMatrix(index),... 
            'UniformOutput',false); 
    numMatrix = cell2mat(generatorMatrix); %# Change from cell to numeric matrix 
end 

Некоторые дополнительные вещи, которые вы можете сделать, будет использовать anonymous functions делать более сложные вещи с встроенными функциями или создавать записи ячеек разного размера.Это иллюстрируется следующей матрицей образцов, которая может быть использована для создания матрицы с первой строкой, содержащей 5, а затем 9, а остальные 9 строк содержат 1, а затем 9 чисел, полученных из равномерного распределения между 5 и 10:

generatorMatrix = {5 ones(1,9); ones(9,1) @() 5*rand(9)+5}; 

И каждый раз, когда эта матрица передается create_matrix она будет создавать новую матрицу 10 на 10, где подматрица 9-по-9 будет содержать различный набор случайных значений.


Альтернативное решение ...

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

Однако, если случайные значения являются единичными элементами, рассеянно рассеянными по всей матрице, то вариация, аналогичная той, что user57368 suggested может работать лучше. Вы можете хранить ваши матричные данные в трех частях: цифровая матрица с заполнителями (например, NaN), где будут отображаться произвольно генерируемые значения, индексный вектор, содержащий linear indices позиций произвольно сгенерированных значений, и массив ячеек такой же длины, как индексный вектор, содержащий function handles для функций, которые будут использоваться для генерации случайных значений. Чтобы упростить задачу, вы можете хранить эти три части данных в structure.

В качестве примера, следующее определяет матрицу 3 на 3 с 3 случайными значениями, хранящуюся в индексах 2, 4, и 9 и составленное соответственно от normal distribution, а uniform distribution от 5 до 10, и exponential distribution:

matData = struct('numMatrix',[1 nan 3; nan 2 4; 0 5 nan],... 
       'randIndex',[2 4 9],... 
       'randFcns',{{@randn , @() 5*rand+5 , @() -log(rand)/2}}); 

и вы можете определить новую функцию create_matrix легко создать матрицу из этих данных:

function numMatrix = create_matrix(matData) 
    numMatrix = matData.numMatrix; 
    numMatrix(matData.randIndex) = cellfun(@feval,matData.randFcns); 
end 
+0

Если матрица очень велика и имеет относительно небольшое количество случайных величин, то первый вызов «cellfun» будет тратить много времени и сильно разбивать память, поскольку массив ячеек представляет собой массив указателей, и каждый указатель должен быть разыменован для вызова 'isa'. Метод, который я предложил (используя два массива, второй разреженный), почти наверняка будет работать лучше (поскольку 'find' на разреженном массиве почти не работает, но делает код более непрозрачным. – user57368

+0

@ user57368: Вот почему я добавил второй пример. Это иллюстрирует, как вы можете разбить матрицу среди ячеек так, чтобы каждая ячейка содержала массив вместо скалярного значения, поэтому в итоге вы получаете меньше всего ячеек для работы. – gnovice

+0

Хорошо. Теперь, когда вы добавили @(), я вижу, как это будет работать. Определенно, самый чистый способ обработать его для матрицы, которая может быть определена всего несколькими строками. – user57368

1

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

Попробуйте использовать регулярную или разреженную матрицу для хранения реальных значений и оставьте ее равной нулю, где бы вы ни выбрали случайную переменную. Затем наряду с этим хранится разреженная матрица той же формы, ненулевые записи которой соответствуют случайным величинам в вашей матрице. Если вы хотите, значение записи во второй матрице можно использовать для указания того, какое распределение (т. Е. 1 для униформы, 2 для нормального и т. Д.).

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

+0

@ user57368: Зачем вам нужна разреженная матрица для # 2? Вы можете просто поместить данные в вектор, сохраняя как пространство, так и время. – Jonas

+0

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

+0

@ user57368: Вы можете определить местоположение в первой матрице, поставив «NaN», где бы вы не захотели иметь случайную переменную позже. – Jonas

Смежные вопросы