Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
Steiner Triples and Sat Solvers
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Lucy Anne Patton
Steiner Triples and Sat Solvers
Commits
8901a5e6
Commit
8901a5e6
authored
4 years ago
by
Lucy Anne Patton
Browse files
Options
Downloads
Patches
Plain Diff
Upload ChessBoard
parent
2ebc0afc
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
ChessBoard.py
+181
-0
181 additions, 0 deletions
ChessBoard.py
with
181 additions
and
0 deletions
ChessBoard.py
0 → 100644
+
181
−
0
View file @
8901a5e6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Feb 2 09:36:24 2021
@author: lukepatton
"""
import
math
from
pysat.solvers
import
Glucose3
class
ChessBoardRepresentation
:
# The initialization sets up the chess board and solves it using Glucose3
# input: n, the order of the NS1D0 sequence (int)
# result: the chess board is setup, NS1D0 contains the ns1d0 sequence
def
__init__
(
self
,
n
):
self
.
size
=
n
self
.
vars
=
[
i
for
i
in
range
(
1
,
(
n
*
n
)
+
1
)]
self
.
clauses
=
[]
self
.
ruleOne
()
self
.
ruleTwo
()
self
.
ruleThreeA
()
self
.
ruleThreeB
()
self
.
ruleFour
()
self
.
solve
()
self
.
ns1d0
=
self
.
getNS1D0FromSolution
()
# Gets a row from the chessboard
# input: row, the row number desired (int)
# output: all the variables in that row (list of ints)
def
getRow
(
self
,
row
):
row
=
row
%
self
.
size
firstVar
=
(
self
.
size
*
row
)
+
1
lastVar
=
(
self
.
size
*
(
row
+
1
))
return
[
i
for
i
in
range
(
firstVar
,
lastVar
+
1
)]
# Gets a column from the chessboard
# input: column, the column number desired (int)
# output: all the variables in that column (list of ints)
def
getColumn
(
self
,
col
):
col
=
col
%
self
.
size
return
[(
i
*
self
.
size
)
+
(
col
+
1
)
for
i
in
range
(
self
.
size
)]
# Gets a diagonal from the chessboard
# input: diag, the diagonal number desired (int)
# output: all the variables in that diagonal (list of ints)
def
getDiagonal
(
self
,
diag
):
diag
=
diag
%
self
.
size
answer
=
[]
for
i
in
range
(
self
.
size
):
j
=
(
diag
+
i
)
%
self
.
size
answer
.
append
((
i
*
self
.
size
)
+
j
+
1
)
return
answer
# Cancels all variables in a list
# input: varList, a list of variables to be set to False (list of ints)
# result: adds a clause of -i for every i in the list
def
cancelList
(
self
,
varList
):
for
i
in
varList
:
self
.
clauses
.
append
([
-
i
])
# Guarantees only one of the items from a list is True
# input: varList, a list of variables, from which one should be True (list
# of ints)
# result: adds a clause to guarantee at least one of the variables is True
# as well as clauses guaranteeing no more than one of the variables are
# True
def
exactlyOneFromList
(
self
,
varList
):
atLeastOneClause
=
varList
self
.
clauses
.
append
(
atLeastOneClause
)
for
i
in
range
(
len
(
varList
)):
for
j
in
range
(
i
+
1
,
len
(
varList
)):
noDoublesClause
=
[
-
varList
[
i
],
-
varList
[
j
]]
self
.
clauses
.
append
(
noDoublesClause
)
# Gets the board position from the variable number
# input: i, the variable number (int)
# output: board position of the variable (2-tuple of ints)
def
positionFromNumber
(
self
,
i
):
row
=
((
i
-
1
)
//
self
.
size
)
col
=
((
i
-
1
)
%
self
.
size
)
return
(
row
,
col
)
# Adds clauses for Rule One (column 0 and row 1 are free, column 1 and row
# 0 have exactly one position filled)
# input: none
# result: clauses have been added
def
ruleOne
(
self
):
self
.
cancelList
(
self
.
getColumn
(
0
))
self
.
cancelList
(
self
.
getRow
(
1
))
self
.
exactlyOneFromList
(
self
.
getColumn
(
1
))
self
.
exactlyOneFromList
(
self
.
getRow
(
0
))
# Adds clauses for Rule Two (column and row 1/2 are free)
# input: none
# result: clauses have been added
def
ruleTwo
(
self
):
half
=
math
.
ceil
(
self
.
size
/
2
)
self
.
cancelList
(
self
.
getColumn
(
half
))
self
.
cancelList
(
self
.
getRow
(
half
))
# Adds clauses for Rule Three A (for every j from 2 to n, either row j or
# row 1 - j is occupied. Same with columns)
# input: none
# result: clauses have been added
def
ruleThreeA
(
self
):
for
j
in
range
(
2
,
self
.
size
):
if
j
!=
math
.
ceil
(
self
.
size
/
2
):
combinedRowList
=
self
.
getRow
(
j
)
combinedRowList
.
extend
(
self
.
getRow
(
1
-
j
))
combinedColList
=
self
.
getColumn
(
j
)
combinedColList
.
extend
(
self
.
getColumn
(
1
-
j
))
self
.
exactlyOneFromList
(
combinedRowList
)
self
.
exactlyOneFromList
(
combinedColList
)
# Adds clauses for Rule Three B (row j occupied iff col j is ocucpied)
# input: none
# result: clauses have been added
def
ruleThreeB
(
self
):
for
j
in
range
(
2
,
self
.
size
):
crossSection
=
((
j
-
1
)
*
self
.
size
)
+
j
row
=
self
.
getRow
(
j
)
for
space
in
row
:
if
space
!=
crossSection
:
impliesClause
=
[
-
space
]
implication
=
[
i
for
i
in
self
.
getColumn
(
j
)
if
i
!=
crossSection
]
impliesClause
.
extend
(
implication
)
self
.
clauses
.
append
(
impliesClause
)
col
=
self
.
getColumn
(
j
)
for
space
in
col
:
if
space
!=
crossSection
:
impliesClause
=
[
-
space
]
implication
=
[
i
for
i
in
self
.
getRow
(
j
)
if
i
!=
crossSection
]
impliesClause
.
extend
(
implication
)
self
.
clauses
.
append
(
impliesClause
)
# Adds clauses for Rule Four (either diagonal j or -j is occupied, but not
# both)
# input: none
# result: clauses have been added
def
ruleFour
(
self
):
for
j
in
range
(
1
,
self
.
size
):
combinedList
=
self
.
getDiagonal
(
j
)
combinedList
.
extend
(
self
.
getDiagonal
(
-
j
))
self
.
exactlyOneFromList
(
combinedList
)
# Solves the SAT problem and stores the solution to self.solution
# input: none
# result: self.solution contains solution
def
solve
(
self
):
g3
=
Glucose3
()
for
clause
in
self
.
clauses
:
g3
.
add_clause
(
clause
)
if
g3
.
solve
():
self
.
solution
=
g3
.
get_model
()
return
# Gets the NS1D0 from the stored solution. If the NS1D0 received is too
# short, that means that there is a sub-sequence. Eliminate the current
# solution and try again
# input: None
# output: an NS1D0 sequence from this order n
def
getNS1D0FromSolution
(
self
):
sequence
=
[
0
]
while
sequence
[
-
1
]
!=
1
:
for
num
in
self
.
solution
:
pair
=
self
.
positionFromNumber
(
num
)
if
pair
[
0
]
==
sequence
[
-
1
]:
sequence
.
append
(
pair
[
1
])
if
len
(
sequence
)
<
(
self
.
size
+
1
)
/
2
:
notASolution
=
[
-
i
for
i
in
self
.
solution
]
self
.
clauses
.
append
(
notASolution
)
self
.
solve
()
return
self
.
getNS1D0FromSolution
()
return
sequence
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment