Каков наилучший способ передать множество констант и переменных рабочей области в целевую функцию fsolve?

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

Рассмотрим цикл с 1000 итераций, выполняющий некоторые вычисления с этими переменными: 0,6 с без глобальных переменных (~1000 переменных), 2,2 с с одной определенной глобальной переменной (и другими переменными), 6 с ~1000 глобальных переменных (и с другими переменными). ). Итак, вы видите, что ОПРЕДЕЛЕНИЕ уже одного глобального — это шаг, который значительно замедляет итерации в функции, которая использует глобальные значения, в отличие от того, что они не используются изначально.

Моей текущей проблемой является функция fsolve, которая вызывает другую функцию и, по-видимому, требует глобальных переменных. И это большая проблема для меня. Я читал, что вы можете передавать переменные в функцию по-разному, например, используя структуру, но эту структуру нужно будет «распаковывать» внутри моих итераций, что снова замедляет итерации.

Теперь мой вопрос: я не хочу использовать глобальные переменные. Как я могу обойти их в fsolve? Моя идея состоит в том, чтобы загрузить их перед входом в цикл. Пожалуйста, скажи мне, что я могу здесь что-то сделать.

Спасибо за чтение, пожалуйста, помогите!

ОБНОВЛЕНИЕ I:

   % load workspacevars.mat % I'm loading some variables that are going to be used.

one_of_the_variables_that_is_imported = 1;

for loop=1:1000
x(loop,:)=linspace(rand(),1,13); % x is going to change all the time, so I simulate this here
x1=x(loop,1); % 
x2=x(loop,2); % 
x13=x(loop,13); % shortened so you get the general idea.

result_1 = x1 * one_of_the_variables_that_is_imported
result_2 = x2 * one_of_the_variables_that_is_imported
result_13 = x13 * one_of_the_variables_that_is_imported

end

Итак, еще раз, я не хочу использовать ни глобальные переменные, ни загружать рабочее пространство для передачи переменных, как это сработает?

ОБНОВЛЕНИЕ II:

По запросу, вот очень, очень близкий пример к моей реальной проблеме (пожалуйста, не пугайтесь длины или отображения, код работает, но не слишком эффективен). Опять же, пожалуйста, сосредоточьтесь на основной проблеме, заключающейся в том, что у меня есть ~ 1000 констант, которые я должен вызывать из файла рабочей области .m или с глобальными переменными, и я не хочу этого делать.

**Небольшая модификация: для этой цели больше подходит pastebin: http://pastebin.com/6e1K90fR

ОБНОВЛЕНИЕ III:

большое спасибо @SCFrench!

Я думаю, что только что понял, как ужасно долго глобальные операции занимают по сравнению со структурами! Позвольте мне поделиться с вами этой забавной историей:

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

Так что теперь мой план состоит в том, чтобы нажать ctrl+H на каждую переменную, которая у меня есть, и заменить ее на c.Var. Это около 1000 Вар, поэтому я лучше спрошу в последний раз, прежде чем приступить к этой утомительной задаче. Надеюсь потом заработает. Ваш пример был очень хорош, и чем чаще я его читаю, тем больше у меня получается. Не могли бы вы в последний раз объяснить, как константы переменных передаются в лямбду и передаются в myfun? Боюсь, я не знаю термина лямбда в этом контексте и хотел бы лучше понять вас. Я не могу прокомментировать ваш комментарий, поэтому извините за это длинное обновление и большое спасибо заранее!

ОБНОВЛЕНИЕ IV:

Код без глобалов работает Чёртовски ХОРОШО !!!!!! большое спасибо всем, это фантастика. Я сократил общее время с нелепых 20 секунд на итерацию до менее чем одной секунды. что 95% увеличение эффективности!!!

Несмотря на то, что я прыгаю от радости, есть одна вещь, которую нужно скорректировать: один из моих результатов в fsolve успешно повторяется, это нормально. но я включил дальнейшее вычисление в f2 (функция, которую нужно решить), которую не нужно решать, но я все еще хочу, чтобы ее вывод был в моем f1, который вызывает fsolve. Теперь мой код читается

[x,fval,exitflag,output,jacobian] = fsolve(@(x) f2(x, c), x0, options);

хотя я предпочел бы иметь

[x,y,fval,exitflag,output,jacobian] = fsolve(@(x) f2(x, c), x0, options);

но я получаю слишком много выходных параметров как ошибку, когда пытаюсь это сделать. Поэтому мне пришлось прибегнуть к отчаянным мерам и снова вызвать global y, чтобы обе функции знали y. Как еще вы могли бы это сделать, ведь теперь я знаю, насколько ужасны глобальные объекты?


person Easyquestionsonly    schedule 30.11.2014    source источник
comment
Можете ли вы дать небольшой код о том, что вы пытаетесь сделать? Похоже, вы выполняете процедуру оптимизации много раз в цикле, и функция оптимизации требует большого количества входных данных, которые вы должны передать функции или определить как global? Это правильно?   -  person David    schedule 01.12.2014
comment
fsolve пытается найти параметры в итерационной процедуре, пока решение не сойдется. Эта функция требует много входных данных, и теперь наступает часть, которую я надеялся улучшить: статус-кво исходного скрипта заключался в том, что все переменные были определены в функции, вызываемой fsolve, здесь фиктивная версия: f1 fsolve( f2) end f2 все переменные end и да, они были глобальными как в f1, так и в f2. я пытаюсь загрузить их, прежде чем переходить к итерациям здесь. Как бы я сделал это по-умному?   -  person Easyquestionsonly    schedule 01.12.2014
comment
1000 переменных? 1000 глобалов? Что это за код? Похоже, ваша главная проблема может заключаться в использовании правильной структуры данных. И да, глобалы медленнее — даже всего один. Есть очень мало веских причин для их использования. Вообще не понятно, что ты делаешь. Пожалуйста, отредактируйте свой вопрос с фактическим кодом, который демонстрирует проблему. Вам просто нужно передать параметры вашей целевой функции? Прочтите документацию по fsolve и эту статью.   -  person horchler    schedule 01.12.2014
comment
Спасибо вам большое за ваш ответ. Мне нужно получить доступ к таблице Excel, чтобы импортировать их за один раз. Эти переменные затем находятся в моей рабочей области. И их нужно передать той функции, о которой я говорил. Я добавлю небольшой фрагмент фактического кода, чтобы вы могли представить, о чем я говорю.   -  person Easyquestionsonly    schedule 01.12.2014
comment
Попытка описать здесь анонимные функции MATLAB, вероятно, запутала бы мой ответ. На SO есть много других обсуждений анонимных функций. Это выглядит как хорошее простое место для начала: stackoverflow.com/questions/22215571/   -  person SCFrench    schedule 01.12.2014
comment
Еще одна вещь - вы можете изменить заголовок этого вопроса на что-то более описательное, что-то вроде Как лучше всего передать множество констант в целевую функцию fsolve?   -  person SCFrench    schedule 01.12.2014


Ответы (1)


Вот упрощенный пример того, как я буду решать эту проблему:

function y = example

% a1 = -2; a2 = -1; save('example_constants.mat')

constants = load('example_constants.mat');

y = fsolve(@(x) myfun(x, constants), [-5;-5]);

end

function F = myfun(x, c)
F = [ 2 * x(1) - x(2) - exp(c.a1 * x(1))
      -x(1) + 2 * x(2) - exp(c.a2 * x(2))];
end

При этом используются две функции MATLAB. Во-первых, если вы запрашиваете вывод из load, он сохраняет все загруженные переменные как поля структуры и возвращает структуру в качестве вывода. После вызова load вы ссылаетесь на каждую константу в MAT-файле, используя такие выражения, как constants.a1 (constants, потому что это имя переменной, назначенной выходу load, и a1, потому что это имя переменной, которая была хранится в example_constants.mat). Другая используемая функция — это анонимные функции, которые фиксируют значение структуры констант в лямбда-выражение и передают его в myfun в качестве второго ввода (c) на каждой итерации.

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

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

person SCFrench    schedule 01.12.2014
comment
Большое спасибо за этот хороший ответ. У меня есть две проблемы: насколько эффективнее вызывать структуры вместо рабочей области или глобальных переменных в числах? 100 раз или 1000 раз? то, что вы предлагаете, заставит меня переписать мои формулы внутри структуры, чтобы каждая переменная имела этот префикс структуры, это правильно? r_1 = c.Var1 * c.Var2 и т. д. - person Easyquestionsonly; 01.12.2014
comment
Я разместил обновление, которое касается вашего комментария. Спасибо, что поделились своим кодом, вы думаете, что преобразование всех переменных в структуры поможет много по сравнению с использованием глобальных переменных или загрузкой рабочей области, да? - person Easyquestionsonly; 01.12.2014