Для цикла внутри цикла - PullRequest
2 голосов
/ 29 июня 2019

Позвольте мне описать задачу: у меня есть 3 матрицы (M1,M2,M3), каждая из которых имеет длину (Mi) строк и 2 столбца. Нам дана функция g(x,s), где s - это двумерный параметр, а x и eta. Я хочу проверить первую матрицу M1, если существует s, например g(x,M1(i,:)>eta. Я хочу ЗАКОНЧИТЬ алгоритм и установить s_new=M1(i,:). Если таких s внутри M1 не существует, я хочу перейти к матрице M2 и искать внутри нее. Следующая матрица М3. Если такой s_new не существует во всех матрицах, я хочу сломаться. Моя первая попытка:

function[s_new]= checking(M1,M2,M3,x)
bool1=0;
eta = 10^-8;
g = @(x,s) x-s(1)-s(2);
while bool1==0
            for i=1:length(M1)
                if g(x,M1(i,:))>eta
                    s_new=M1(i,:);
                    bool1=1;
                end
            end
            for i=1:length(M2)
                 if g(x,M2(i,:))>eta
                    s_new=M2(i,:);
                    bool1=1;
                 end
            end
            for i=1:length(M3)
                 if g(x,M3(i,:))>eta
                    s_new=M3(i,:);
                    bool1=1;
                 end
            end
            bool1=1;
        end

Моя вторая попытка включала какую-то опцию перерыва, но она тоже не работала. Проблема заключается в том, что alghoritm не останавливается, когда находит s в M1, например, когда выполняется наше условие, он переходит к M2 и, если находит такие s, изменяет s_new. Также, чтобы сэкономить некоторое время, я не хочу, чтобы алгоритм alghoritm проходил через матрицу M2, если такая s существует в M1.

Пример, почему это работает плохо:

M1=[0,-1;0,-1], M2=[0,-2;0,-2], M3=[0,0;0,0], x=0 

Он должен возвращать вектор [0,-1] и вместо него возвращает [0,-2]. Любая помощь приветствуется. РЕДАКТИРОВАТЬ: bool1 = 1 внутри циклов for подчеркнут красным, что говорит о том, что bool1 может быть не использован, как если бы он не распознал его из условия при запуске, в то время как bool1 = 0

Ответы [ 2 ]

2 голосов
/ 29 июня 2019

Добавив решение @ Rotem, вы можете полностью избавиться от циклов for для вашей проблемы.Вместо зацикливания всех индексов вы можете использовать функцию find и ее способность сообщать о первом индексе, который удовлетворяет вашему условию.Также вы можете полностью исключить переменную bool1.Я предлагаю следующий код:

%function [s_new]= checking(M1,M2,M3,x)
M1 = [0,-1; 0,-1]; 
M2 = [0,-2; 0,-2];
M3 = [0,0; 0,0];
x = 0;
eta = 10^-8;
% Here I have vectorized your function g so that it can work over all the rows of the s matrix. This is the step which actually removes the for-loop. sum(s, 2) always sums over the 2 columns in your matrix.
g = @(x, s) x - sum(s, 2);
% Now we assign an empty matrix to s_new. This step gets rid of the bool1 because now we can check whether s_new is still empty or not. It also returns empty matrix if no value of s_new is found in any of your matrices M1, M2 or M3
s_new = [];
% Now we find if an s_new exists in M1. We first calculate the g function over the entire M1 matrix. Then we check if your condition is satisfied. Then the find function returns the first row of M1 that satisfies your condition. If it doesnot find any row that satisifies this condition, find will return an empty matrix which we can check to assign the value to s_new
s_new_index = find(g(x, M1) > eta, 1, 'first');
if ~isempty(s_new_index) % the isempty function checks for empty matrices. ~ stands for NOT
    s_new = M1(s_new_index, :);
end
% Now we check if s_new was assigned earlier. If not then we repeat the same thing with M2 and then M3
if isempty(s_new)
    s_new_index = find(g(x, M2) > eta, 1, 'first');
    if ~isempty(s_new_index)
        s_new = M2(s_new_index, :);
    end
end
if isempty(s_new)
    s_new_index = find(g(x, M3) > eta, 1, 'first');
    if ~isempty(s_new_index)
        s_new = M3(s_new_index, :);
    end
end
2 голосов
/ 29 июня 2019

Я думаю, что нашел проблему

Вы хотели разорвать цикл while в случае bool1=1;

Вы можете добавить if bool1, break;end после каждого раздела:

%function[s_new]= checking(M1,M2,M3,x)
M1=[0,-1;0,-1]; 
M2=[0,-2;0,-2];
M3=[0,0;0,0];
x=0;

bool1=0;
eta = 10^-8;
g = @(x,s) x-s(1)-s(2);
while bool1==0
    for i=1:length(M1)
        if g(x,M1(i,:))>eta
            s_new=M1(i,:);
            bool1=1;
        end
    end
    if bool1, break;end

    for i=1:length(M2)
         if g(x,M2(i,:))>eta
            s_new=M2(i,:);
            bool1=1;
         end
    end
    if bool1, break;end

    for i=1:length(M3)
         if g(x,M3(i,:))>eta
            s_new=M3(i,:);
            bool1=1;
         end
    end
    bool1=1;
end

display(s_new)

Более элегантно без цикла while:

%function[s_new]= checking(M1,M2,M3,x)
M1=[0,-1;0,-1]; 
M2=[0,-2;0,-2];
M3=[0,0;0,0];
x=0;

bool1=0;
eta = 10^-8;
g = @(x,s) x-s(1)-s(2);

for i=1:length(M1)
    if g(x,M1(i,:))>eta
        s_new=M1(i,:);
        bool1=1;
    end
end

if ~bool1
    for i=1:length(M2)
         if g(x,M2(i,:))>eta
            s_new=M2(i,:);
            bool1=1;
         end
    end
end

if ~bool1
    for i=1:length(M3)
         if g(x,M3(i,:))>eta
            s_new=M3(i,:);
            bool1=1;
         end
    end
end

display(s_new)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...