Skip to content
Snippets Groups Projects
Commit e2165feb authored by Samuel Grayson's avatar Samuel Grayson
Browse files

Final commit

parent b89bb190
No related branches found
No related tags found
No related merge requests found
...@@ -61,35 +61,58 @@ The quantities in [square brackets] in the last line can be precomputed for all ...@@ -61,35 +61,58 @@ The quantities in [square brackets] in the last line can be precomputed for all
<p><strong>Algorithm 1</strong> <code>best_order</code> should compute the best order to the tests, using the assumptions above. <p><strong>Algorithm 1</strong> <code>best_order</code> should compute the best order to the tests, using the assumptions above.
<div><pre><code class="language-python">import numpy.typing as npt <div><pre><code class="language-python">from typing import List
import numpy.typing as npt
import numpy as np import numpy as np
def reverse(array: npt.NDArray[np.float64]) -&gt; npt.NDArray[np.float64]: def reverse(array: npt.NDArray[np.float64]) -&gt; npt.NDArray[np.float64]:
"""Reverse a numpy array""" """Reverse a numpy array"""
return array[::-1] return array[::-1]
def cumprod_noninclusive(array: npt.NDArray[np.float64]) -&gt; npt.NDArray[np.float64]: def cumsum(
ret = np.ones_like(array) array: npt.NDArray[np.float64],
for i in range(1, len(array)): inclusive: bool = True,
ret[i] = ret[i-1] * array[i-1] one_larger_output: bool = False,
) -&gt; npt.NDArray[np.float64]:
if one_larger_output:
assert not inclusive
ret = np.zeros(len(array) + int(one_larger_output))
for i in range(int(not inclusive), len(ret)):
ret[i] = ret[i-1] + array[i - int(not inclusive)]
return ret
def cumprod(
array: npt.NDArray[np.float64],
inclusive: bool = True,
one_larger_output: bool = False,
) -&gt; npt.NDArray[np.float64]:
if one_larger_output:
assert not inclusive
ret = np.ones(len(array) + int(one_larger_output))
for i in range(int(not inclusive), len(ret)):
ret[i] = ret[i-1] * array[i - int(not inclusive)]
return ret return ret
def next_best(nt: int, d: npt.NDArray[np.float64], p: npt.NDArray[np.float64]): def next_best(d: npt.NDArray[np.float64], p: npt.NDArray[np.float64]) -&gt; List[int]:
""" """
Returns the index of the best test to run. Returns the index of the best test to run.
nt, d, and p should already include a fictitious initial and fictitious final test.
""" """
# Compute D and P for the unmodified order. if len(d) == 1:
# np.cumsum is inclusive, D[k] = d[0] + d[1] + ... + d[k] return 0
# cumprod_noninclusive is not, P[k] = p[0] * p[1] * ... * p[k-1] * (1 - p[k])
D = np.cumsum(d) assert len(d) == len(p)
P = cumprod_noninclusive(p) * (1 - p)
# D[ell] := d[0] + d[1] + ... + d[ell]
# Precompute intermediate values. D = cumsum(d)
A = np.cumsum(D * P) - d[0] * p[0] # P[ell] := p[0] * p[1] * ... * p[ell-1] * (1 - p[ell])
B = np.cumsum(P) - p[0] P = cumprod(p, inclusive=False) * (1 - p)
# A[ell] := D[1] * P[1] + D[2] * P[2] + ... + D[ell - 1] * P[ell - 1] for ell &gt; 0
A = cumsum(D * P, inclusive=False) - D[0] * P[0]
# B[ell] := P[1] + P[2] + ... + P[ell - 1] for ell &gt; 0
B = cumsum(P, inclusive=False) - P[0]
# C[ell] := D[ell+1] * P[ell+1] + D[ell+2] * P[ell+2] + ... + D[len(D) - 1] * P[len(D) - 1]
# TODO: this
C = np.cumsum(reverse(D * P)) C = np.cumsum(reverse(D * P))
# Compute E of the swapped order 0 &lt;-&gt; k for all k. # Compute E of the swapped order 0 &lt;-&gt; k for all k.
...@@ -102,42 +125,33 @@ def next_best(nt: int, d: npt.NDArray[np.float64], p: npt.NDArray[np.float64]): ...@@ -102,42 +125,33 @@ def next_best(nt: int, d: npt.NDArray[np.float64], p: npt.NDArray[np.float64]):
+ C + C
) )
# Find min, excluding the trailing fictitious test, which would otherwise be optimal. return np.argmin(E_of_swap)
return np.argmin(E_of_swap[:-1])
def best_order( def best_order(
nt: int,
d: npt.NDArray[np.float64], d: npt.NDArray[np.float64],
p: npt.NDArray[np.float64], p: npt.NDArray[np.float64],
) -&gt; npt.NDArray[np.float64]: ) -&gt; npt.NDArray[int]:
""" """
Returns a list of indices which consist the best order to run. Returns a list of indices which consist the best order to run.
nt, d, and p should not contain fictitious tests.
""" """
order = np.zeros(nt) assert len(d) == len(p)
# Add the fictitious test to these. tests = np.arange(len(d), dtype=int)
nt = nt + 2
d = np.concatenate([0], d, [0])
p = np.concatenate([1], p, [0])
# Loop through each test and find the best order. # Loop through each test and find the best order.
for k in range(nt - 1): for k in range(len(d)):
# The first k have already been assigned. # The first k have already been assigned.
best = next_best(nt - k, d[k:], p[k:]) best = next_best(d[k:], p[k:])
order[k] = best
# Swap best with k + 1, the first real test in the next round. # Swap best with k, so that arr[k+1:] are the remaining tests
np.swap(p, k + 1, best) if k != best:
np.swap(d, k + 1, best) p[[k, best]] = p[[best, k]]
d[[k, best]] = d[[best, k]]
tests[[k, best]] = tests[[best, k]]
# Set the first test in the next round to be fictitious. assert list(sorted(tests)) == list(range(len(d)))
# This deletes the test we select for this round.
d[k + 1] = 0
p[k + 1] = 1
return order return tests
</code></pre></div></p> </code></pre></div></p>
</body></html> </body></html>
\ No newline at end of file
◊begin[
(require
txexpr
"lib/txexpr.rkt")
(define-values (rest template-data) (splitf-txexpr* doc 'template-data))
(define title (get-child template-data 'title #:default '("Working Title")))
(define head (get-child template-data 'head #:default '()))
(define body (get-elements rest))
]
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> ◊(->html
<head> `(html ((lang "en"))
<meta charset="utf-8" /> (head
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script> (meta ((charset "utf-8")))
<script (title ,@title)
id="MathJax-script" ,@head)
async (body
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" (h1 ,@title)
></script> ,@body)))
</head>
<body>
◊(->html doc #:splice? #t)
</body>
</html>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment