Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Andrew Childs
reversal-sort
Commits
dcf8876e
Commit
dcf8876e
authored
Feb 23, 2021
by
Hrishee Shastri
Browse files
TBS and GDC(TBS) implementation
parent
f7095365
Changes
1
Hide whitespace changes
Inline
Side-by-side
TripartiteBinarySort.py
0 → 100644
View file @
dcf8876e
import
SBR
import
math
import
itertools
import
random
from
itertools
import
permutations
"""
TripartiteBinarySort.py -- Implementation of the TBS algorithm for sorting bitstrings and permutations,
along with a couple testing/analysis functions
"""
def
tbs_v1
(
perm
):
"""
Returns the cost to sort perm using TBS
"""
revlist
=
permutationsort_divideconquer_tbs
(
perm
,
0
,
len
(
perm
)
-
1
)
cost
=
SBR
.
compress_reversals
(
revlist
,
len
(
perm
))
/
3
return
cost
def
tripartite_binary_sort
(
T
,
i
,
j
):
"""
Performs TBS (binary version) on T[i,j] inclusive, returns list of reversals
"""
if
all
(
T
[
ind
]
<=
T
[
ind
+
1
]
for
ind
in
range
(
i
,
j
)):
return
[]
part1
,
part2
=
(
2
*
i
+
j
)
//
3
,
(
i
+
2
*
j
)
//
3
revlist
=
[]
revlist
+=
tripartite_binary_sort
(
T
,
i
,
part1
)
flipbits
(
T
,
part1
+
1
,
part2
)
revlist
+=
tripartite_binary_sort
(
T
,
part1
+
1
,
part2
)
flipbits
(
T
,
part1
+
1
,
part2
)
revlist
+=
tripartite_binary_sort
(
T
,
part2
+
1
,
j
)
oneind
,
zerind
=
zero_one_indices
(
T
,
i
,
j
)
if
oneind
<
zerind
:
rev
=
SBR
.
Reversal
(
oneind
,
zerind
)
SBR
.
reverse
(
T
,
rev
)
revlist
.
append
(
rev
)
return
revlist
def
flipbits
(
T
,
i
,
j
):
for
index
in
range
(
i
,
j
+
1
):
T
[
index
]
=
int
(
not
T
[
index
])
def
zero_one_indices
(
T
,
i
,
j
):
"""
returns indices of leftmost 1 and rightmost 0 to reverse the segment across
the median
"""
oneind
=
-
1
zerind
=
-
1
# Find leftmost 1
for
ind
in
range
(
i
,
j
+
1
):
if
T
[
ind
]
==
1
:
oneind
=
ind
break
# Find rightmost 0
for
ind
in
range
(
j
,
i
-
1
,
-
1
):
if
T
[
ind
]
==
0
:
zerind
=
ind
break
return
oneind
,
zerind
def
perm_to_01
(
L
,
i
,
j
):
"""
TUrns a permutation L[i:j] into a permutation of 0s and 1s, where L[i] is 0 if it is
less than the median and L[i] is 1 if it is greater than the median
"""
subseq
=
L
[
i
:
j
+
1
]
sorted_subseq
=
sorted
(
subseq
)
median
=
(
j
-
i
)
//
2
return
L
[:
i
]
+
[
int
(
sorted_subseq
.
index
(
k
)
>
median
)
for
k
in
subseq
]
+
L
[
j
+
1
:]
def
permutationsort_divideconquer_tbs
(
L
,
i
,
j
):
"""
Sorts the given permutations L from index i to j (inclusive) using a divide and conquer approach. Returns a list of
reversals used to perform the sort.
"""
if
i
==
j
:
return
[]
T
=
perm_to_01
(
L
,
i
,
j
)
revs
=
tripartite_binary_sort
(
T
,
i
,
j
)
m
=
(
i
+
j
)
//
2
SBR
.
apply_revs
(
revs
,
L
)
return
revs
+
permutationsort_divideconquer_tbs
(
L
,
i
,
m
)
+
permutationsort_divideconquer_tbs
(
L
,
m
+
1
,
j
)
def
all_binary_lists_equal
(
n
):
"""
generates list of lists, where each list is a binary sequence of length n,
with equal number of 0s and 1s
"""
def
blep
(
n
,
b
,
ct0s
,
ct1s
,
lis
):
if
len
(
b
)
==
n
:
if
ct1s
==
n
//
2
:
lis
.
append
(
b
)
return
if
ct0s
==
math
.
ceil
(
n
/
2
):
lis
.
append
(
b
+
[
1
]
*
(
n
-
len
(
b
)))
return
if
ct1s
==
n
//
2
:
lis
.
append
(
b
+
[
0
]
*
(
n
-
len
(
b
)))
return
blep
(
n
,
b
+
[
0
],
ct0s
+
1
,
ct1s
,
lis
)
blep
(
n
,
b
+
[
1
],
ct0s
,
ct1s
+
1
,
lis
)
return
lis
=
[]
blep
(
n
,
[],
0
,
0
,
lis
)
return
lis
def
test_binary_sort
():
"""
Testing correctness of sorting bitstrings with TBS.
"""
wrong
=
0
for
i
in
range
(
1000
):
l
=
[
0
]
*
random
.
randint
(
100
,
200
)
+
[
1
]
*
random
.
randint
(
100
,
200
)
random
.
shuffle
(
l
)
before
=
l
.
copy
()
#print(before)
tripartite_binary_sort
(
l
,
0
,
len
(
l
)
-
1
)
#print(l, '\n')
if
l
!=
sorted
(
before
):
print
(
"failed"
)
print
(
"passed"
)
def
test_perm_sort
():
"""
Testing correctness of sorting permutations with TBS as
bitstring sorting subroutine.
Returns number
"""
wrong
=
0
n
=
1000
for
ct
in
range
(
n
):
L
=
list
(
range
(
1
,
random
.
randint
(
5
,
200
)))
random
.
shuffle
(
L
)
before
=
L
.
copy
()
permutationsort_divideconquer_tbs
(
L
,
0
,
len
(
L
)
-
1
)
#print(before, '\n', L, '\n')
if
L
!=
sorted
(
before
):
print
(
"failed"
)
return
print
(
"passed"
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment