Skip to main content
guest
Join
|
Help
|
Sign In
Liberty BASIC Programmer's Encyc
Home
guest
|
Join
|
Help
|
Sign In
Wiki Home
Recent Changes
Pages and Files
Members
Home
General Tutorials
Advanced Tutorials
GUI Programming
Graphics and Games
Strings and Text
Numbers and Math
Using Files
Windows API
Communications
Programmer's Tools
Articles by Date
FAQs
Rosetta Code
General Articles
Newsletters Contents
Table of Contents
Demos
Submit Articles
TOS and License
RandomOptimalSelection
Edit
5
…
1
Tags
tutorials
edit
Save
Cancel
Notify
RSS
Backlinks
Source
Print
Export (PDF)
Operations in a loop. <br /> <h1>Single-pass random optimal selection.</h1> <em><a class="wiki_link" href="/tsh73">tsh73</a></em>, may 2013<br /> <img id="wikitext@@toc@@normal" class="WikiMedia WikiMediaToc" title="Table of Contents" src="/site/embedthumbnail/toc/normal?w=225&h=100"/><hr /> <h1>(How come?)</h1> I encountered this problem in one of my programs.<br /> I thought solution to be kind of cool, in a nerdy kind of way; but I had a doubt if it’s too obvious to warrant an article of its own. So I checked it on my colleague, a teacher; and she said “I think it’s interesting, go ahead and post it”. So here I am.<br /> <br /> <h1>The problem:</h1> Imagine you have a choosing program, likely involving big (lengthy) search. You are interested in picking just one of “best” solutions; being “best” amounts to having maximum of some criteria – a single number.<br /> However, beforehand you have no idea what number would it be; more, you have no idea if it would be single solution with maximum criteria or hundreds of them.<br /> But in case you have several of them, you think it would be nice to pick one of them at random – I mean, with equal probability. (In case you program some game, say Tic-tac-toe, it would make computer opponent play more interesting – instead of picking same response along each path, it would show some variation). (Note: You can easily have first of them or last of them, depending of putting > or >= in your maximum search code; but with equal probability? ) <br /> <br /> <h1>Easy (read no-thinking) way</h1> So. Easy (read no-thinking) way if doing this would require several passes of search loop.<br /> <ul class="quotelist"><li>1. On the first pass, you determine maximum criteria value (“best”).</li><li>2. On the second pass, you count number of occurrences (Nbest) of that “best” value.</li></ul><ul><li>Then you can dimension array for that value (dim A(Nbest))<br /> 3. Third pass fill that array with solutions yielding “best” criteria.</li><li>And at last, we can finally generate random number R between 1 and Nbest and return A(R).</li></ul><br /> <pre class="lb">'problem:<br/>'You have a choosing program, likely involving big (lengthy) search.<br/>'You are interested in picking just one of "best" solutions;<br/>'being "best" amounts to having maximum of some criteria - a single number.<br/>'v.1. Easy (read no-thinking) way<br/><br/>'for now, i 1..N would be search space, b(i) is criteria<br/>'i, so that b(i)= max, is solution (one of).<br/>N=100<br/>dim b(N)<br/>NN=int(rnd(0)*20)+20<br/>for i = 1 to N<br/> b(i)=int(rnd(0)*NN)<br/>next<br/>print "We have ";N; " integer random numbers."<br/><br/>'On the first pass, you determine maximum criteria value ("best").<br/>best = -1e40 'so that it would be guaranteed less then maximum<br/>for i = 1 to N<br/> if b(i)>best then best=b(i)<br/>next<br/>print "Maximum of them: "; best<br/>'On the second pass, you count number of occurrences (Nbest) of that "best" value.<br/>Nbest=0 <br/>print "solution","value"<br/>for i = 1 to N<br/> if b(i)=best then<br/> Nbest=Nbest+1<br/> print i, b(i)<br/> end if<br/>next<br/>print "----------------------"<br/>print "Num of solutions(maxumums) ";Nbest<br/>'Then you can dimension array for that value (dim A(Nbest))<br/>dim a(Nbest)<br/>'Third pass fill that array with solutions yielding "best" criteria.<br/>j=0<br/>print "number","solution","value"<br/>for i = 1 to N<br/> if b(i)=best then<br/> j=j+1<br/> a(j)=i<br/> print j, a(j), b(a(j))<br/> end if<br/>next<br/>print "----------------------"<br/>'And at last, we can finally generate random number R between 1 and Nbest<br/>R=int(rnd(0)*Nbest)+1<br/>'and return A(R).<br/>print "We choose solution ";a(R);" with value ";b(a(R))</pre> This approach has one definite value – clarity. Remember? <br /> <em>Make it work – make it work right – make it work fast</em>, and only in that order! <br /> But supposed you already at “work right” phase, some speeding up might as well be welcome. We started with “big (lengthy) search”, remember?<br /> <br /> <h1>Cutting it 2x</h1> Currently, our algorithm passes over that lengthy search trice.<br /> We can rather easily cut it 2x:<br /> First, we can combine first two phases in one, in a single pass<br /> <pre class="lb">'On the first pass, you determine maximum criteria value ("best").<br/>'On the second pass, you count number of occurrences (Nbest) of that "best" value.<br/>' combine first two phases in one, in a single pass<br/>best = -1e40 'so that it would be guaranteed less then maximum<br/>Nbest=0<br/>for i = 1 to N<br/> if b(i)=best then<br/> Nbest=Nbest+1<br/> end if<br/> if b(i)>best then 'order is important: it's too late to check if(b(i)=best)<br/> best=b(i) 'after assignment on this line!<br/> Nbest=1<br/> end if<br/>next<br/>print "Maximum of them: "; best<br/>print "Num of solutions(maxumums) ";Nbest</pre> So that leaves us with two passes (of three)<br /> Second, we can skip that array business altogether.<br /> We just generate R then run last pass, stopping after hitting R-th best value.<br /> <pre class="lb">'We just generate R then run last pass, stopping after hitting R-th best value.<br/>R=int(rnd(0)*Nbest)+1<br/>print "We choose ";R;"-th solution"<br/>j=0<br/>print "number","solution","value"<br/>for i = 1 to N<br/> if b(i)=best then<br/> j=j+1<br/> print j, i, b(i)<br/> if j=R then exit for 'stopping after hitting R-th best value<br/> end if<br/>next<br/>print "----------------------"<br/>print "We choose solution ";i;" with value ";b(i)</pre> That will cost us from around 1 (best case, R=1) to around full search pass (worst case, R=Nbest), in average – a half. So we end up with 1½ of a full search. As I promised, 2x cut from three passes :).<br /> <br /> <h1>And now, in a single pass</h1> Could it be made better? <br /> Well, yes. <br /> We will do all that in a single pass.<br /> Here’s how.<br /> <br /> Then we hit best value, we could have a counter – how much times we already had that best value?<br /> <ul><li>If answer is 0, (this is best value and it happened just now), then we just keep it, no question asked.</li><li>If answer is 1, we have N=2 equal values. So we take new value with probability 1/N<br /> (ha! It just means ½ in our case!), that is, with condition<ul class="quotelist"><li><tt>If rnd(0)<1/N then</tt></li></ul>If condition fails, we will keep old value.</li><li>Likewise, if answer is 2, we have N=3 equal values. We take new value with probability 1/N (1/3 now), else we well keep old value (that happened to be 1st or second best value with equal probability).</li></ul>You get the picture. ;)<br /> Now, the code.<br /> <pre class="lb">'problem:<br/>'You have a choosing program, likely involving big (lengthy) search.<br/>'You are interested in picking just one of "best" solutions;<br/>'being "best" amounts to having maximum of some criteria - a single number.<br/>'v.3. Single pass solution.<br/><br/>'for now, i 1..N would be search space, b(i) is criteria<br/>'i, so that b(i)= max, is solution (one of).<br/>N=100<br/>dim b(N)<br/>NN=int(rnd(0)*20)+20<br/>for i = 1 to N<br/> b(i)=int(rnd(0)*NN)<br/>next<br/>print "We have ";N; " integer random numbers."<br/><br/>'Single pass<br/>'Gets maximum, <br/>'counts number of maximums<br/>'and randomly keeps one of them.<br/>best = -1e40 'so that it would be guaranteed less then maximum<br/>Nbest=0<br/>solution=0<br/>for i = 1 to N<br/> if b(i)=best then<br/> Nbest=Nbest+1 'now we have Nbest equal values<br/> 'So we take new value with probability 1/Nbest<br/> If rnd(1)<1/Nbest then<br/> solution=i<br/> end if<br/> 'else we well keep old value (do nothing)<br/> end if<br/> if b(i)>best then 'this is best value and it happened just now<br/> best=b(i) 'we just keep it, no question asked<br/> solution=i<br/> Nbest=1 'start counting anew<br/> end if<br/>next<br/>print "Maximum of them: "; best<br/>print "Num of solutions(maxumums) ";Nbest<br/>print "We choose solution ";solution;" with value ";b(solution)</pre> As I promised, it all happened along single pass of an algorithm! <br /> <hr /> <img id="wikitext@@toc@@flat" class="WikiMedia WikiMediaTocFlat" title="Table of Contents" src="/site/embedthumbnail/toc/flat?w=100&h=16"/>
Javascript Required
You need to enable Javascript in your browser to edit pages.
help on how to format text
Turn off "Getting Started"
Home
...
Loading...