【问题标题】:Matlab: program stops iterating at random times before "for" loop is completedMatlab:程序在“for”循环完成之前随机停止迭代
【发布时间】:2014-10-17 10:10:05
【问题描述】:

在 MATLAB 中编写一个程序来模拟队列中的等待时间。目前,它应该为所有 855 个作业分配一个队列进入和退出时间(以秒为单位)。但是,每次我运行它时,它都会选择一个随机时间点,并停止将队列进入时间分配给在此时间之后到达的作业。也许我的随机数生成器有问题?这是我的代码:

function waitTimes = mcQueue2(arrivals, services)
% inputs the array of absolute arrival times and service times for each
% voter, places them into queue and service, 
% RECORDS WAIT TIME

secsOpen = 46800; 
arrivalArray = arrivalTimes(arrivals); % uses xlsread to make an array from an excel 
% file of times, in seconds, from 1 to secsOpen when jobs arrive
serviceArray = generateServiceTimes(services); % generateServiceTimes reads an input 
% array from an excel sheet, counts its elements, creates an array of that number of 
% elements, and populates each element with a random number using logninv()

arrivalArray(1) = 1; % set the first arrival to arrive at the first second
serversBusy = [0 0 0 0]; % each time a job exits queue and begins service, the service 
% time associated with that job is added to the serversBusy time of whichever server is 
% handling 
numMachines = numel(serversBusy);
arrivalIndex = 1;
queue = []; 
numInQueue = zeros(1, secsOpen); % tracks how many people are in queue each second
waitTimes = cat(2, (1:numel(arrivalArray))', zeros(numel(arrivalArray), 2));

for sec = 1:secsOpen
    % every second, check if someone is arriving that second
    if arrivalArray(arrivalIndex) == sec
        % if they arrive, put them into the queue
        queue = cat(2, queue, arrivalIndex);
        % record the time they entered queue
        waitTimes(arrivalIndex, 2) = sec;
        % increment arrivalIndex to wait for the next arrival
        arrivalIndex = arrivalIndex + 1;
    end
    %check if any of the servers are becoming available
    for ii = 1:numMachines
        if serversBusy(ii) <= sec && numel(queue) > 0
        % if so, send the first voter in queue to the server
            % record the current time as the time they exited queue
            waitTimes(queue(1), 3) = sec; 
            % add this job's service time to the time the server is busy until
            serversBusy(ii) = sec + serviceArray(queue(1));
            % remove the job from the queue
            queue(1) = [];
        end
    end
    numInQueue(sec) = length(queue);
end
plot(1:sec, numInQueue, '*')
end

使用我输入到arrivalTimes 和generateServiceTime 的当前电子表格,应该有855 个作业到达服务器。例如,我最近一次运行代码时,它为前 27 个到达和退出时间分配了到达和退出时间,而其余 828 个元素则没有。这是一个waitTimes的例子:

       1           1           1
       2          51          51
       3         188         188
       4         190         190
       5         231         231
       6         329         399
       7         355         400
       8         505         505
       9         633         633
      10         734         734
      11         739         762
      12         804         905
      13         852        1137
      14         914        1185
      15         974        1205
      16         976        1225
      17        1066        1489
      18        1068        1537
      19        1074        1558
      20        1097        1778
      21        1132        1798
      22        1170        1892
      23        1208        1960
      24        1271        2096
      25        1299        2158
      26        1304        2176
      27        1354        2268
      28           0           0
      29           0           0
      30           0           0

(零继续从 30 到 855)1 到 27 的输出正是我想要的。为什么它不继续对列表中的其余元素执行此操作??

这是arrivalTimes和generateServiceTime的代码:

function arrivals = arrivalTimes(excelFile)
% inputs an excel file of the template 'SamplePrecincts.xlsx' outputs the
% array of arrival times
% the excelFile contains the interarrival times between jobs, so arrivalTimes sums them     
% to get the absolute time when the job arrives.
interarrivals = (xlsread(excelFile, 'Sheet2', 'D1:ALN5'))';
interarrivals(~any(interarrivals,2), : ) = []; % get rid of any zeros
arrivals = zeros(size(interarrivals, 1), size(interarrivals, 2));
arrivals(1) = 0;
for k = 2:numel(interarrivals)
    arrivals(k) = arrivals(k-1) + interarrivals(k);
end
end

excelFile Sheet2 D1:ALN5中每个单元格的公式如下:

 FLOOR.MATH(GAMMA.INV(RAND(), 1, $C$2))

其中 C2 当前为 53.9731

function serviceTimes = generateServiceTimes(excelFile)
% takes an input of the template 'SamplePrecincts.xlsx' and generates
% lognormal vote times based on the YKA paper. returns in seconds
interarrivals = (xlsread(excelFile, 'Sheet2', 'D1:ALN5'))';
interarrivals(~any(interarrivals,2), : ) = []; % get rid of any zeros
[r, c] = size(interarrivals);
voteTimes = zeros(r, c);
for k = 1:numel(voteTimes)
    voteTimes(k) = ceil(60*logninv(rand(), 1.7042, 0.4406));
end
end

【问题讨论】:

  • 我猜上面的输出来自waitTimes变量。第一列来自arrivalArray,它是使用arrivalTimes 函数从Excel 文件(?) 中读取的。您确定arrivalArray 的每个元素都是可以与arrivalArray(arrivalIndex) == sec 进行相同比较的整数吗? arrivalTimes 的代码是什么样的,arrivals 的示例输入也会是什么样的?
  • 感谢您的意见,原来我自己修好了!我摆脱了arrivalsservices 参数,并用excelFile 参数替换了它,该参数用作arrivalTimes()generateServiceTimes() 的参数
  • WAIT 结果没有帮助,我只是随机让它迭代 600 次而不是 855 次。
  • Sean - 你需要打印出arrivalArray 数据。它看起来像什么?

标签: matlab for-loop random queue simulation


【解决方案1】:

首先:'D1:ALN5' 范围对应于 5*999 = 4995 个条目(= 工作),所以我不确定它是否适合您的 855 个工作的价值。

我调查了你的问题,我想我知道你的问题是什么: 当您加载arrivaltimes 时,只有当整个列仅由零组成时,您才会删除零。

我的建议是使arrivaltimes 成为向量而不是矩阵,例如,在arrivalTimes 函数中的interarrivals = (xlsread(excelFile, 'Sheet2', 'D1:ALN5'))'; 行之后添加以下行interarrivals = interarrivals(:);

请注意,这不会阻止 waitTimes 变量最后出现大量零:第二列中的零表示该作业永远不会开始(在 secsOpen 限制之前)。第三列中的零表示工作永远无法完成(在secsOpen 限制之前)。

还要注意,如果最后一个作业在时间到达 @ 987654331@ 的限制,但是可以通过将waitTimes 函数中的if arrivalArray(arrivalIndex) == sec 行更改为if (arrivalIndex &lt;= numel(arrivalArray)) &amp;&amp; (arrivalArray(arrivalIndex) == sec) 来轻松挽救。

希望这能解决你的问题!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 2020-08-05
    • 2012-11-07
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多