<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://wiki.kram.nz/index.php?action=history&amp;feed=atom&amp;title=211L1SolutionBruteForce</id>
	<title>211L1SolutionBruteForce - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.kram.nz/index.php?action=history&amp;feed=atom&amp;title=211L1SolutionBruteForce"/>
	<link rel="alternate" type="text/html" href="https://wiki.kram.nz/index.php?title=211L1SolutionBruteForce&amp;action=history"/>
	<updated>2026-04-08T20:14:32Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://wiki.kram.nz/index.php?title=211L1SolutionBruteForce&amp;diff=264&amp;oldid=prev</id>
		<title>Mark: 1 revision(s)</title>
		<link rel="alternate" type="text/html" href="https://wiki.kram.nz/index.php?title=211L1SolutionBruteForce&amp;diff=264&amp;oldid=prev"/>
		<updated>2008-03-08T22:35:28Z</updated>

		<summary type="html">&lt;p&gt;1 revision(s)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en-GB&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 22:35, 8 March 2008&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en-GB&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key mediawiki-mw_:diff:1.41:old-263:rev-264 --&gt;
&lt;/table&gt;</summary>
		<author><name>Mark</name></author>
	</entry>
	<entry>
		<id>https://wiki.kram.nz/index.php?title=211L1SolutionBruteForce&amp;diff=263&amp;oldid=prev</id>
		<title>Mark at 05:37, 23 July 2006</title>
		<link rel="alternate" type="text/html" href="https://wiki.kram.nz/index.php?title=211L1SolutionBruteForce&amp;diff=263&amp;oldid=prev"/>
		<updated>2006-07-23T05:37:11Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;In computer science, &amp;#039;&amp;#039;&amp;#039;brute-force search&amp;#039;&amp;#039;&amp;#039; is a trivial but very general problem-solving technique, that consists of systematically enumerating all possible candidates for the solution and checking whether each candidate satisfies the problem&amp;#039;s statement.&lt;br /&gt;
&lt;br /&gt;
For example, a brute-force algorithm to find the divisors of a natural number &amp;#039;&amp;#039;n&amp;#039;&amp;#039; is to enumerate all integers from 1 to &amp;#039;&amp;#039;n&amp;#039;&amp;#039;, and check whether each of them divides &amp;#039;&amp;#039;n&amp;#039;&amp;#039; without remainder. For another example, consider the popular eight queens problem, that asks to place eight queen&amp;#039;s on a standard chessboard so that no queen attacks any other.  A brute-force algorithm for this problem is to generate all possible arrangements of eight queens on the board, and, for each arrangement, check whether there are any two queens on the same row, column, or diagonal.&lt;br /&gt;
&lt;br /&gt;
Brute-force search is simple to implement, and will always find a solution if it exists.  However, its cost is proportional to the number of candidate solutions, which, in many practical problems, tends to grow very quickly as the size of the  problem increases.  Therefore, brute-force search is typically used when the problem size is limited (as in the eight queens above), or when there are problem-specific heuristic&amp;#039;s that can be used to reduce the set of candidate solutions to a manageable size.&lt;br /&gt;
&lt;br /&gt;
The method is also used when the simplicity of implementation is more important than speed. This is the case, for example, in critical applications where any errors in the algorithm would have very serious consequences; or when using a computer to prove a mathematical theorem. Brute-force search is also useful as &amp;quot;baseline&amp;quot; method when benchmarking other algorithms or metaheuristics.  Indeed, brute-force search can be viewed as the simplest metaheuristic. &lt;br /&gt;
&lt;br /&gt;
==Implementing the brute-force search==&lt;br /&gt;
&lt;br /&gt;
===Basic algorithm===&lt;br /&gt;
In order to apply brute-force search to a specific class of problems, one must implement four [[procedures]], &amp;#039;&amp;#039;first&amp;#039;&amp;#039;, &amp;#039;&amp;#039;next&amp;#039;&amp;#039;, &amp;#039;&amp;#039;valid&amp;#039;&amp;#039;, and &amp;#039;&amp;#039;output&amp;#039;&amp;#039;. These procedures should take as a parameter the data &amp;#039;&amp;#039;P&amp;#039;&amp;#039; for the particular instance of the problem that is to be solved, and should do the following:&lt;br /&gt;
# &amp;#039;&amp;#039;first&amp;#039;&amp;#039; (&amp;#039;&amp;#039;P&amp;#039;&amp;#039;): generate a first candidate solution for &amp;#039;&amp;#039;P&amp;#039;&amp;#039;.&lt;br /&gt;
# &amp;#039;&amp;#039;next&amp;#039;&amp;#039; (&amp;#039;&amp;#039;P&amp;#039;&amp;#039;, &amp;#039;&amp;#039;c&amp;#039;&amp;#039;): generate the next candidate for &amp;#039;&amp;#039;P&amp;#039;&amp;#039; after the current one &amp;#039;&amp;#039;c&amp;#039;&amp;#039;.&lt;br /&gt;
# &amp;#039;&amp;#039;valid&amp;#039;&amp;#039; (&amp;#039;&amp;#039;P&amp;#039;&amp;#039;, &amp;#039;&amp;#039;c&amp;#039;&amp;#039;): check whether candidate &amp;#039;&amp;#039;c&amp;#039;&amp;#039; is a solution for &amp;#039;&amp;#039;P&amp;#039;&amp;#039;.&lt;br /&gt;
# &amp;#039;&amp;#039;output&amp;#039;&amp;#039; (&amp;#039;&amp;#039;P&amp;#039;&amp;#039;, &amp;#039;&amp;#039;c&amp;#039;&amp;#039;):  use the solution &amp;#039;&amp;#039;c&amp;#039;&amp;#039; of &amp;#039;&amp;#039;P&amp;#039;&amp;#039; as appropriate to the application&lt;br /&gt;
&lt;br /&gt;
The &amp;#039;&amp;#039;next&amp;#039;&amp;#039; procedure must also tell when there are no more candidates for the instance &amp;#039;&amp;#039;P&amp;#039;&amp;#039;, after the current one &amp;#039;&amp;#039;c&amp;#039;&amp;#039;. A convenient way to do that is to return a &amp;quot;null candidate&amp;quot;, some conventional data value Λ that is distinct from any real candidate. Likewise the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; procedure should return Λ if there are no candidates at all for the instance &amp;#039;&amp;#039;P&amp;#039;&amp;#039;. The brute-force method is then expressed by the algorithm&lt;br /&gt;
&lt;br /&gt;
 c \gets first(P)&lt;br /&gt;
 while c \neq Λ do&lt;br /&gt;
   if valid(P,c) then output(P, c)&lt;br /&gt;
   c \gets next(P,c)&lt;br /&gt;
&lt;br /&gt;
For example, when looking for the divisors of an integer &amp;#039;&amp;#039;n&amp;#039;&amp;#039;,  the instance data &amp;#039;&amp;#039;P&amp;#039;&amp;#039; is the number &amp;#039;&amp;#039;n&amp;#039;&amp;#039;. The call &amp;#039;&amp;#039;first&amp;#039;&amp;#039; (&amp;#039;&amp;#039;n&amp;#039;&amp;#039;) should returns the integer 1 if &amp;#039;&amp;#039;n&amp;#039;&amp;#039; &amp;lt;math&amp;gt;\geq&amp;lt;/math&amp;gt; 1, or Λ otherwise; the call &amp;#039;&amp;#039;next&amp;#039;&amp;#039; (&amp;#039;&amp;#039;n&amp;#039;&amp;#039;,&amp;#039;&amp;#039;c&amp;#039;&amp;#039;) should return &amp;#039;&amp;#039;c&amp;#039;&amp;#039; + 1 if &amp;#039;&amp;#039;c&amp;#039;&amp;#039; &amp;lt;math&amp;gt;&amp;lt;&amp;lt;/math&amp;gt; &amp;#039;&amp;#039;n&amp;#039;&amp;#039;, and Λ otherwise; and &amp;#039;&amp;#039;valid&amp;#039;&amp;#039; (&amp;#039;&amp;#039;n&amp;#039;&amp;#039;,&amp;#039;&amp;#039;c&amp;#039;&amp;#039;) should return &amp;#039;&amp;#039;&amp;#039;true&amp;#039;&amp;#039;&amp;#039; if and only if &amp;#039;&amp;#039;c&amp;#039;&amp;#039; is a divisor of &amp;#039;&amp;#039;n&amp;#039;&amp;#039;.  (In fact, if we choose Λ to be &amp;#039;&amp;#039;n&amp;#039;&amp;#039; + 1, the tests are unnecessary, and the algorithm simplifies considerably.)&lt;br /&gt;
&lt;br /&gt;
===Common variations===&lt;br /&gt;
The brute-force search algorithm above will call &amp;#039;&amp;#039;output&amp;#039;&amp;#039; for every candidate that is a solution to the given instance &amp;#039;&amp;#039;P&amp;#039;&amp;#039;. The algorithm is easily modified to stop after finding the first solution, or a specified number of solutions; or after testing a specified number of candidates, or after spending a given amount of [[central processing unit|CPU]] time.&lt;br /&gt;
&lt;br /&gt;
==Combinatorial explosion==&lt;br /&gt;
The main disadvantage of the brute-force method is that, for many real-world problems, the number of natural candidates is prohibitively large.&lt;br /&gt;
&lt;br /&gt;
For instance, if we look for the divisors of a number as described above, the number of candidates tested will be the given number &amp;#039;&amp;#039;n&amp;#039;&amp;#039;. So if &amp;#039;&amp;#039;n&amp;#039;&amp;#039; has sixteen decimal digits, say, the search will require executing at least 10&amp;lt;sup&amp;gt;15&amp;lt;/sup&amp;gt; computer instructions, which will take several days on a typical [[personal computer|PC]].  If &amp;#039;&amp;#039;n&amp;#039;&amp;#039; is a random 64-[[binary digit|bit]] natural number, which has about 19 decimal digits on the average, the search will take about 10 years.&lt;br /&gt;
&lt;br /&gt;
This steep growth in the number of candidates, as the size of the data increases, occur in all sorts of problems. For instance, if we are seeking a particular rearrangement of 10 letters, then we have [[factorial|10!]] = 3,628,800 candidates to consider; which a typical PC can generate and test in less than one second. However, adding one more letter — which is only a 10% increase in the data size — will multiply the number of candidates by 11 — a 1000% increase.  For 20 letters, the number of candidates is 20!, which is about 2.4×10&amp;lt;sup&amp;gt;18&amp;lt;/sup&amp;gt; or 2.4 [[quadrillion]]; and the search will take about 10,000 years.  This unwelcome phenomenon is commonly called the [[combinatorial explosion]].&lt;br /&gt;
&lt;br /&gt;
== Speeding up brute-force searches ==&lt;br /&gt;
One way to speed up a brute-force algorithm is to reduce the search space, that is, the set of candidate solutions, by using [[heuristic]]s specific to the problem class.&lt;br /&gt;
&lt;br /&gt;
For example, consider the popular [[eight queens problem]], which asks to place eight [[queen (chess)|queen]]s on a standard [[chessboard]] so that no queen attacks any other.  If we consider only that the queens are all alike, and that no two queens can be placed on the same square, we conclude that the candidates are [[combinations|all possible ways of choosing]] of a set of 8 squares from the set all 64 squares; which means 64!/56!/8! = 4,426,165,368 candidate solutions.&lt;br /&gt;
&lt;br /&gt;
However, a little more thought tells us that no arrangement with two queens on the same row or the same column can be a solution. Therefore, we can further restrict the set of candidates to those arrangements where queen 1 is on row 1, queen 2 is in row 2, and so on; all in different columns. We can describe such an arrangement by an array of eight numbers &amp;#039;&amp;#039;c&amp;#039;&amp;#039;[1] through &amp;#039;&amp;#039;c&amp;#039;&amp;#039;[8], each of them between 1 and 8, where &amp;#039;&amp;#039;c&amp;#039;&amp;#039;[1] is the column of queen 1, &amp;#039;&amp;#039;c&amp;#039;&amp;#039;[2] is the column of queen 2, and so on.  Since these numbers must be all different, the number of candidates to search is the number of [[permutation]]s of the integers 1 through 8, namely 8! = 40,320 — about 1/100,000 of the original number.&lt;br /&gt;
&lt;br /&gt;
As this example shows, a little bit of analysis will often lead to dramatic reductions in the number of candidate solutions, and may turn an intractable problem into a trivial one.  This example also shows that the candidate enumeration procedures (&amp;#039;&amp;#039;first&amp;#039;&amp;#039; and &amp;#039;&amp;#039;next&amp;#039;&amp;#039;) for the restricted set may be just as simple as those of the original set, or even simpler.&lt;br /&gt;
&lt;br /&gt;
In some cases, the analysis may reduce the candidates to the set of all valid solutions; that is, it may result in an algorithm that directly enumerates all the solutions (or finds one solution, as appropriate), without wasting time with tests and the generation of invalid candidates.  For example, consider the problem of checking whether two words are [[anagram]]s of each other. A naive implementation of the brute-force method would generate all possible [[permutation|rearrangement]]s of the letters of the first word, and compare each one to the second word. However, that problem can be solved much more efficiently by sorting or counting the letters of each word separately, and comparing the results.&lt;br /&gt;
&lt;br /&gt;
==Reordering the search space==&lt;br /&gt;
In applications that require only one solution, rather than all solutions, the expected running time of a brute force search will often depend on the order in which the candidates are tested. As a general rule, one should test the most promising candidates first.  For example, when searching for a proper divisor of a random number &amp;#039;&amp;#039;n&amp;#039;&amp;#039;, it is better to enumerate the candidate divisors in increasing order, from 2 to &amp;#039;&amp;#039;n&amp;#039;&amp;#039; - 1, than the other way around — because the probability that &amp;#039;&amp;#039;n&amp;#039;&amp;#039; is divisible by &amp;#039;&amp;#039;c&amp;#039;&amp;#039; is 1/&amp;#039;&amp;#039;c&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
Moreover, the probability of a candidate being valid is often affected by the previous failed trials. For example, consider the problem of finding a &amp;#039;&amp;#039;&amp;#039;1&amp;#039;&amp;#039;&amp;#039; bit in a given 1000-bit string &amp;#039;&amp;#039;P&amp;#039;&amp;#039;. In this case, the candidate solutions are the indices 1 to 1000, and a candidate &amp;#039;&amp;#039;c&amp;#039;&amp;#039; is valid if &amp;#039;&amp;#039;P&amp;#039;&amp;#039;[&amp;#039;&amp;#039;c&amp;#039;&amp;#039;] = &amp;#039;&amp;#039;&amp;#039;1&amp;#039;&amp;#039;&amp;#039;.  Now, suppose that the first bit of &amp;#039;&amp;#039;P&amp;#039;&amp;#039; is equally likely to be &amp;#039;&amp;#039;&amp;#039;0&amp;#039;&amp;#039;&amp;#039; or &amp;#039;&amp;#039;&amp;#039;1&amp;#039;&amp;#039;&amp;#039;, but each bit thereafter is equal to the previous one with 90% probability. If the candidates are enumerated in increasing order, 1 to 1000, the  number &amp;#039;&amp;#039;t&amp;#039;&amp;#039; of candidates examined before success will be about 6, on the average.  On the other hand, if the candidates are enumerated in the order 1,11,21,31...991,2,12,22,32 etc., the expected value of &amp;#039;&amp;#039;t&amp;#039;&amp;#039; will be only a little more than 2. &lt;br /&gt;
&lt;br /&gt;
More generally, the search space should be enumerated in such a way that the next candidate is most likely to be valid, &amp;#039;&amp;#039;given that the previous trials were not&amp;#039;&amp;#039;.  So if the valid solutions are likely to be &amp;quot;clustered&amp;quot; in some sense, then each new candidate should be as far as possible from the previous ones, in that same sense. The converse holds, of course, if the solutions are likely to be spread out more uniformly than expected by chance.&lt;br /&gt;
&lt;br /&gt;
==Alternatives to brute force search==&lt;br /&gt;
There are many other search methods, or metaheuristics, which are designed to take advantage of various kinds of partial knowledge one may have about the solution. &lt;br /&gt;
&lt;br /&gt;
[[Heuristic]]s can also be used to make an early cutoff of parts of the search. One example of this is the [[minimax]] principle for searching game trees. This eliminates many subtrees at an early stage in the search.&lt;br /&gt;
&lt;br /&gt;
In certain fields such as language parsing techniques such as [[chart parsing]] can exploit constraints in the problem to reduce an exponential complexity problem into a polynomial complexity problem.&lt;br /&gt;
&lt;br /&gt;
The search space for problems can also be reduced by replacing the full problem with a simplified version. For example, in [[computer chess]], rather than computing the full [[minimax]] tree of all possible moves for the remainder of the game, a more limited tree of minimax possibilities is computed, with the tree being pruned at a certain number of moves, and the remainder of the tree being approximated by a [[evaluation function|static evaluation function]].&lt;/div&gt;</summary>
		<author><name>Mark</name></author>
	</entry>
</feed>