2017-02-13 20 views
1

Я расчета раствора ограниченной линейной задачи наименьших квадратов следующим образом:lsqlin оптимизирован расчет (MATLAB)

lb = zeros(7,1); 
ub = ones(7,1); 
for i = 1:size(b,2) 
    x(:,i) = lsqlin(C,b(:,i),[],[],[],[],lb,ub); 
end 

, где находится Cm x 7 и b является m x n. n довольно большой, что приводит к медленному времени вычисления. Есть ли способ ускорить эту процедуру и избавиться от медленного цикла for. Я использую lsqlin вместо pinv или \, потому что мне нужно ограничить мое решение границами 0-1 (lb и ub).

+0

Вы всегда можете попробовать переключиться по умолчанию. Попробуйте '' '' inner-point'''. Не уверен, для чего этот цикл, и как вы ожидаете от нас работы. – sascha

+0

Я пробовал разные решатели, но проблема такая же. Я использую цикл for, потому что если я попытаюсь дать 'x = lsqlin (C, b, [], [], [], [], lb, ub);' Я получаю 'Внутренние размеры матрицы должны совпадать .' ошибка. С другой стороны, если я использую 'pinv (C) * b' или' C \ b', он работает как шарм, но для 'lsqlin' мне нужно сделать это через цикл' for', и поскольку мне нужны ограничения Мне нужно использовать 'lsqlin'. Поэтому я просто спрашиваю, есть ли возможность оптимизировать или отменить цикл 'for'. – ThT

ответ

2

Цикл for не обязательно является причиной какой-либо медлительности - вы не предварительно выделяете и lsqlin, вероятно, распечатывает много вещей на каждой итерации. Тем не менее, вы можете ускорить это, повернув свою матрицу C в разреженную диагональную матрицу блока, C2, с n идентичными блоками (see here). Это решает все проблемы n за один раз. Если новый C2 не разрежен, вы можете использовать намного больше памяти, и вычисление может занять гораздо больше времени, чем при использовании цикла for.

n = size(b,2); 
C2 = kron(speye(n),C); 
b2 = b(:); 
lb2 = repmat(lb,n,1); % or zeros(7*n,1); 
ub2 = repmat(ub,n,1); % or ones(7*n,1); 
opts = optimoptions(@lsqlin,'Algorithm','interior-point','Display','off'); 
x = lsqlin(C2,b2,[],[],[],[],lb2,ub2,[],opts); 

Использование optimoptions, Я specified the algorithm и установить 'Display' к 'off', чтобы убедиться, что любые выходы и предупреждения не замедляют расчеты.

На моей машине это в 6-10 раз быстрее, чем при использовании петли for (с правильными параметрами предварительной настройки и настройки). Этот подход предполагает, что малая C2 матрица с элементами m*n*7 может поместиться в память. Если нет, то будет использоваться только подход на основе петли for (кроме написания вашей собственной специализированной версии lsqlin или использования любых других проблем, связанных с проблемой).

+0

большое спасибо за ваш ответ. Ваше решение, похоже, делает трюк ;-). У меня также были сообщения, но не предварительное выделение (следующее, что я планировал попробовать) при использовании разреженной диагональной матрицы блоков - это трюк, о котором я не знаю, и, похоже, это помогает. Спасибо за вашу помощь еще раз. – ThT

+0

только другой вопрос. Насколько оптимальным является использование разреженной диагональной матрицы блока, память разумна. Потому что, например, в моем случае мне приходится иметь дело с матрицами размера 'C' (193200x7)' b' (193200x16450) или больше, что плохо, что я не упоминал об этом раньше. Поскольку вы можете понять, как пытаться ваше решение на практике, теперь у меня проблема с памятью (250Gb недостаточно для предварительного выделения C2). Любой намек на это? – ThT

+0

Я предполагал, что 'm' меньше, чем' n', потому что вы указали, что 'n' было большим в вашем вопросе. Ваш разреженный 'C2' потребуется примерно в той же памяти, что и массив 193200x7x16450 (в отличие от полного массива, который был бы в 16450 раз больше!). Ваш 'b' уже больше, чем максимальный размер массива по умолчанию в моей версии Matlab (вам, вероятно, пришлось перейти к изменению предела). Цикл 'for' - это путь, если вы связаны с памятью, если другие части системы не являются разреженными. – horchler

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

  • Нет связанных вопросов^_^