2013-11-19 4 views
0

Я пытаюсь написать функцию (см. Код ниже), которая создаст список аэропортов, в которых вылетело или прибыло более 1000 рейсов, затем укажите вектор, содержащий индексы каждого из этих аэропортов в формате (x, y). Как аэропорт, так и данные по полету размещаются в отдельных структурах размером 1x6267 и 1x136010 соответственно, и каждый аэропорт и рейс имеют уникальный идентификационный номер, соответствующий его столбцу в структуре. Несмотря на то, что код, который я написал, успешно идентифицирует все аэропорты с более 1000 комбинированных прилетов/вылетов, функция выполняет почти 20 минут для выполнения и предоставляет только идентификационные номера аэропортов, а не их показатели в структуре аэропортов. Какие изменения мне необходимо внести в код, чтобы получить его время работы менее 5 минут и как я могу создать вектор индексов (x, y) для аэропортов? Любая помощь будет принята с благодарностью! Благодаря!Функция MATLAB: улучшение скорости/производительности кода

P.S. Я довольно новичок в MATLAB, поэтому заранее извиняюсь, если эти вопросы кажутся глупыми или очевидными.

function list = Problem10(flights, aircraft, airlines, airports) 
a=zeros(1,(length(airports))); 
for id=1:length(airports) 
    a(id)= FlightsToFrom(flights, id); 
end 
a(a==0) = []; 
[list]=[sort(a)] 
end 

function tofrom = FlightsToFrom(flights, ID) 
sum=0; 
for ii=1:length(flights) 
    if (isequal (flights(1,ii).from_id, ID))||(isequal (flights(1,ii).to_id, ID)) 
     sum=sum+1; 
     if sum > 1000 
      break; 
     end 
    end 
end 
if sum <=1000 
    tofrom=0; 
else 
    tofrom=ID; 
end 
end 

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

(In Workspace) 
airports <1x6267 struct> 
aircraft <1x384 struct> 
airlines <1x1559 struct> 
flights <1x136010 struct> 

(Inside of struct) 
flights(1,6) <1x1 struct> 
**Field**  **Value** 
airline_id 60 
from_id  967 
to_id   6252 
aircraft_id 18 
distance  32 
airtime  19 
passengers 0 
month   1 

flights(1,6).from_id <1x1 double> 
967 


airport(1,176) <1x1 struct> 
**Field**  **Value** 
code   'AEX' 
name   'Alexandria, LA: Alexandria International' 

airport(1,176).name <1x40 char> 
'Alexandria, LA: Alexandria International' 

(In Command Window) 

>> airports (2866) 

ans = 

    code: 'LAX' 
    name: 'Los Angeles, CA: Los Angeles International' 

>> airports (1, 2866) 

ans = 

    code: 'LAX' 
    name: 'Los Angeles, CA: Los Angeles International' 

>> airports (4703) 

ans = 

    code: 'SEA' 
    name: 'Seattle, WA: Seattle/Tacoma International' 

>> airports (1, 4703) 

ans = 

    code: 'SEA' 
    name: 'Seattle, WA: Seattle/Tacoma International' 

>> flights (4736) 

ans = 

    airline_id: 31 
     from_id: 1635 
      to_id: 1062 
    aircraft_id: 194 
     distance: 118 
     airtime: 1792 
    passengers: 1657 
      month: 1 

>> flights (1, 4736) 

ans = 

    airline_id: 31 
     from_id: 1635 
      to_id: 1062 
    aircraft_id: 194 
     distance: 118 
     airtime: 1792 
    passengers: 1657 
      month: 1 

>> flights(1,7369).to_id 

ans = 

    830 

>> flights(1,7369).from_id 

ans = 

     1047 
+0

Ваши «полеты» кажутся красиво цифровыми и квадратными. Если вы хотите более эффективно/легко обрабатывать его, это должно помочь хранить эту информацию в матрице, а не в структуре. Это может иметь место и для некоторых других структур. –

+0

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

ответ

2

Вся ваша FlightsToFrom() функции может быть полностью векторизация, что приводит к следующему (с несколькими дополнительными небольшими улучшениями):

function a = Problem10(flights, aircraft, airlines, airports) 
    numAirports = length(airports); 
    a(numAirports) = 0; % preallocate: faster than zeros() 
    from_ids = [flights.from_id]; 
    to_ids = [flights.to_id]; 
    for id = 1 : numAirports 
     a(id) = id * (sum(from_ids==id | to_ids==id) > 1000); 
    end 
    a(~a) = []; 
    %a = sort(a); % unnecessary - a is already sorted at this stage, by ascending ID! 
end 

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

+0

Это отлично работало и сокращало время экспоненциально ... спасибо тонну! Я полагаю, что я так зациклился на циклах (это то, над чем мы работали в классе в последнее время, поэтому я просто предположил, что это будет работать лучше всего), что я не смог этого более простого и разумного решения. Ваш ответ был очень полезен! – user3008753

0

Чтобы ускорить, я хотел бы предложить

function tofrom = FlightsToFrom(flights, ID) 
assert(~exist('sum','var')) 
nflights=sum([flights.fromId]==ID)+sum([flights.toId]==ID); 
if nflights <=1000 
    tofrom=0; 
else 
    tofrom=ID; 
end 
end 

Для вашего второго вопроса, то как аэропорты выглядят как? В настоящее время вы используете свой индекс цикла, это идентично идентификатору аэропорта?

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

numOfAirports=100 
numOfFlights=10000 
for idx=1:numOfFlights 
    flights(idx).fromId=randi(numOfAirports);flights(idx).toId=randi(numOfAirports); 
end 
+0

Daniel - большое спасибо за вашу помощь! Я попробовал ваше первое предложение и, к сожалению, не смог добиться правильного результата. Вместо вектора номеров аэропортов, которые я получил с исходной функцией, на этот раз и была создана пустая матрица (я думаю, потому что индивид from_id и to_ids размещен в отдельных матрицах структуры полета). Индекс петли, действительно идентичен идентификатору аэропорта. Я верну отредактировать свой вопрос, чтобы не включать некоторые примеры данных, поэтому, пожалуйста, дайте мне знать, если у вас есть предложения после этого. Опять же, я очень ценю помощь! – user3008753

+0

Я обновил свой ответ, предположив, что возникла некоторая проблема с суммой функции против суммы имени переменной. Если утверждение терпит неудачу, существует какая-то глобальная переменная, вызывающая проблему. – Daniel

+0

Я только что опробовал ваше предложение, и оно работает очень хорошо! Благодаря! – user3008753

0

Что занимает много времени в вашем коде зацикливается всем список полета 6267 раз, как вы вызываете функцию FlightsToFrom для каждого аэропорт ... Если вы сможете решить это всего за один проход через рейсы, программа будет работать в 6267 раз быстрее, что составляет долю секунды. Я не совсем уверен, что вы подразумеваете под «вектором индексов x, y для аэропортов» - что должен содержать этот вектор? В любом случае, вы могли бы сделать зацикливание по крайней мере, таким образом:

a=zeros(length(airports),length(airports)); 
for id = 1:length(flights) 
    a[flights(1,id).from_id, flights(1,id).to_id] = a[flights(1,id).from_id, flights(1,id).to_id] + 1; 
end 

В конце этого a представляет собой матрицу, которая содержит несколько раз полем происходившие из разных аэропортов. Например. [5,6] будет число раз, когда был рейс из аэропорта 5 в аэропорт 6. Затем вы можете делать материал в этой матрице с помощью встроенных функций MATLAB, например.

[row, col] = find(a>1000); 

даст вам координаты от/до рейсов, которые произошли более 1000 раз.

highdepartures = find(sum(a,1)>1000)); 
highdarrivals = find(sum(a,2)>1000)); 

даст вам список координатов аэропортов с наибольшим количеством вылетов/заездов, соответственно.

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