Функция для поиска записей с одинаковым максимальным значением в векторе

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

Функция является подфункцией в функциональном блоке MATLAB в Simulink. И вся модель Simulink скомпилирована.

Моя основная идея заключалась в следующем:

function ind = findOpt(vector)
index_max = find(vector == max(vector));
random = randi([1,length(index_max)],1);
ind = index_max(random);
end

Но у меня возникли проблемы со сравнением в find и в randi. Я узнал о безопасном сравнении здесь: Проблема с использованием функции поиска в MATLAB. Также я нашел способ заменить randi([1,imax],1): Реализовать 'randi' с помощью 'rand' в MATLAB< /а>.

Мой код теперь выглядит так:

function ind = findOpt(vector)
tolerance = 0.00001;
index_max = find(abs(vector - max(vector)) < tolerance);
random = ceil(length(index_max)*rand(1));
ind = index_max(random);
end

Все еще не работает. Я понимаю, что длина index_max неясна и вызывает проблемы. Но я не могу придумать никакого способа узнать это раньше. Есть идеи, как это решить?

Кроме того, я шокирован тем, что ceil не работает, когда код выполняется?? В режиме отладки видимых изменений на входе нет.

Я думал о создании массива вроде: index_max = abs(vector - max(vector)) < tolerance; Но не знаю, как это может помочь. Кроме того, это не решает мою проблему со случайным выбором. Надеюсь, у кого-то есть больше идей или, по крайней мере, может дать мне несколько советов!

Я использую MATLAB R2012b (32 бита) на ПК с Windows 7-64 бит с компилятором Lcc-win32 C 2.4.1.

Редактировать: Вектор обычно имеет размер 5x1 и содержит значения от -2000 до нуля, которые имеют тип double, например. vector = [-1000 -1200 -1000 -1100 -1550]'. Но я думаю, что такая простая функция должна работать с любым входным вектором.

Вызов length(index_max) вызывает системную ошибку в MATLAB и заставляет меня закрыть его. Думаю, это из-за странного ответа, который я получаю от find. Для вектора со всеми одинаковыми значениями возврат из find похож на [1.000 2.000 1.000 2.000 0.000]', что для меня вообще не имеет никакого смысла.


person FxH    schedule 15.01.2014    source источник
comment
что не работает? Попробовали ваш код в Matlab, и все в порядке?   -  person stijn    schedule 15.01.2014
comment
В MATLAB у меня тоже все работает. Но запуск модели Simulink вызывает ошибку времени выполнения, говорящую: Ожидается целочисленное значение, найдена нецелочисленная переменная random со значением 4,07362. Для строки с: ind=index_max(random);   -  person FxH    schedule 15.01.2014
comment
Хм. Это интересно..   -  person stijn    schedule 15.01.2014
comment
реализовать потолок самостоятельно.   -  person Autonomous    schedule 15.01.2014
comment
не могли бы вы выложить свой вектор? Я думаю, что есть много простых решений с использованием find и randi, но я думаю, вы не хотите их использовать   -  person Autonomous    schedule 15.01.2014
comment
Ставьте random = length(index_max)*rand(1) и random = ceil(random) в последовательных строках без точки с запятой. Каков результат этих двух строк? Также поместите which ceil в функцию после строки, вызывающей ceil, и также дайте нам вывод этой строки.   -  person user664303    schedule 15.01.2014
comment
Ввод which ceil дает мне ошибку кодера, утверждающую: Функция «которая» не поддерживается для совместной генерации. [...]. И ceil(x) по-прежнему возвращает x.   -  person FxH    schedule 15.01.2014
comment
Если вы откроете новый MATLAB и вызовете findOpt(rand(100, 1)), это сработает? Если это так, я предполагаю, что код, из которого вы обычно вызываете findOpt(), перегружает ceil(); надо найти где.   -  person user664303    schedule 16.01.2014
comment
Я сохранил findOpt() в М-файле и сделал, как вы сказали. Работает отлично, даже для моей первоначальной реализации. Но все же в функциональном блоке MATLAB в Simulink это не сработает. Не думайте, что я перегружаю ceil. Может проблема в компиляторе? Завтра попробую на другом компе. Посмотрим, что там происходит...   -  person FxH    schedule 16.01.2014


Ответы (2)


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

function varargout = table(mode, varargin)
persistent table;

if isempty(table) && ~strcmp(mode,'writeTable')
     error(...)
end

switch mode
     case 'getValue'
        ...
     case 'writeTable'
        table = ...
     ...
end
end

Хотел избежать передачи размеров для таблицы при каждом вызове и подумал, что будет достаточно, если первый вызов инициализирует таблицу с помощью mode='writeTable'. Похоже, это вызвало мою проблему. Нет проблем после замены на:

if isempty(table)
     table = zeros(dim1,dim2,...)
end
person FxH    schedule 18.01.2014

person    schedule
comment
Пробовал, но по-прежнему получаю ошибку времени выполнения для ceil(rand(1)*end) Почему-то ceil не делает того, что должен делать, и просто проходит через rand(1)*end. - person FxH; 15.01.2014
comment
Каков результат which ceil? Мой built-in (C:\Program Files\MATLAB\R2013b\toolbox\matlab\elfun\@double\ceil) % double method. - person user664303; 15.01.2014