SlideShare ist ein Scribd-Unternehmen logo
1 von 24
Downloaden Sie, um offline zu lesen
Dancing Links
an educational pearl
Massimo Nocentini, PhD.
massimo.nocentini@gmail.com
ESUG2019 – August 28, 2019.
outline
^ LinkedList new
add: 'me and the core idea';
add: 'DoubleLink objs';
add: 'exact cover problem';
add: 'AlgorithmX';
add: 'covering and uncovering columns';
add: 'N-Queens and Sudoku problems';
yourself
Hi!
$ whoami
Massimo Nocentini, PhD
Mathematician (algebraic combinatorics, formal methods for algs)
Programmer (automated reasoning, logics and symbolic comp)
https://github.com/massimo-nocentini/dancinglinksst
In Donald’s words1
: Suppose x points to an element of a doubly linked
list; let L[x] and R[x] point to the predecessor and successor of that
element. Then:
L[R[x]] ← L[x], R[L[x]] ← R[x] (1)
remove x from the list; every programmer knows this. But comparatively
few programmers have realized that
L[R[x]] ← x, R[L[x]] ← x (2)
will put x back again, with no refs to the whole list at all.
1https://arxiv.org/abs/cs/0011047
Space for sketching
Main ideas
Operation (2) arises in backtrack programs, which enumerate all
solutions to a given set of constraints and it was introduced in 1979
by Hitotumatu and Noshita.
The beauty of (2) is that operation (1) can be undone by knowing
only the value of x.
We can apply (1) and (2) repeatedly in complex data structures that
involve large numbers of interacting doubly linked lists.
Knuth: “This process causes the pointer variables inside the global
data structure to execute an exquisitely choreographed dance; hence
I like to call (1) and (2) the technique of dancing links.”
Minato et al. 2
constructs a Zero-suppressed BDD (ZDD) that
represents the set of sols and it enables the efficient use of memo
cache to speed up the search.
2https://aaai.org/ocs/index.php/AAAI/AAAI17/paper/view/14907
DoubleLinks and DoubleLinkedLists
DoubleLink objects respond to messages
remove
nextLink ifNotNil: [ :next | next previousLink: previousLink ].
previousLink ifNotNil: [ :previous | previous nextLink: nextLink ]
and
restore
nextLink ifNotNil: [ :next | next previousLink: self ].
previousLink ifNotNil: [ :previous | previous nextLink: self ]
that implement operations (1) and (2), respectively; moreover, we extend
DoubleLinkedList objects with the message
makeCircular
head
ifNotNil: [
head previousLink: tail.
tail nextLink: head ]
to introduce circular, doubly connected, lists.
Exact Cover ∈ NP
Given a matrix of 0s and 1s, does it have a set of rows containing
exactly one symbol 1 in each column?
The problem with matrix






r1
r2
r3
r4
r5






T 





1 1 1 0 1 0
1 1 0 0 0 0
0 0 0 1 0 1
0 0 1 1 0 1
0 0 1 0 1 0






=








1
1
1
1
1
1








T
is solved by two sets of rows, namely
{r1 = 1, r3 = 1} and {r2 = 1, r5 = 1, r3 = 1}.
We can think of the columns as elements of a universe, and the rows as
subsets of the universe; then the problem is to cover the universe with
disjoint subsets, NP-complete even when each row contains exactly
three 1s.
Space for sketching
AlgorithmX instance side
searchDepth: k forDLRootObject: h partialSelection: cont
^ (h isFixPointOf: [ :ro | ro right ])
ifTrue: [ self yieldNode: top onBlock: cont ]
ifFalse: [
memo
at: h columns
ifPresent: [ :tree | self yieldNode: tree onBlock: cont ]
ifAbsentPut: [
self
searchDepth: k
forDLColumnObject: h chooseColumn
partialSelection: cont ] ]
AlgorithmX instance side
searchDepth: k forDLColumnObject: c partialSelection: sel
^ self
onEnter: [ c cover ]
do: [
c
untilFixPointOf: [ :co | co up ]
foldr: [ :r :x |
| y |
y := self searchDepth: k
forDLDataObject: r
partialSelection: sel.
y isZDDBottom
ifTrue: [ x ]
ifFalse: [
self
uniqueNodeWithDLDataObject: r
withLowerNode: x
withHigherNode: y ] ]
init: bottom ]
onExit: [ c uncover ]
AlgorithmX instance side
searchDepth: k forDLDataObject: r partialSelection: cont
^ self
onEnter: [ r untilFixPointOf: [ :ro | ro right ]
do: [ :j | j column cover ] ]
do: [ self
searchDepth: k + 1
forDLRootObject: r column root
partialSelection: [ :sel |
cont
value:
(ValueLink new
value: r model;
nextLink: sel;
yourself) ] ]
onExit: [ r untilFixPointOf: [ :ro | ro left ]
do: [ :j | j column uncover ] ]
AlgorithmX instance side
The entry point is the message
searchDLRootObject: h onSolutionDo: aBlock
^ self
searchDepth: 0
forDLRootObject: h
partialSelection: [ :selLink |
aBlock value: (LinkedList new add: selLink; asSet) ]
Knuth advices to use the heuristic (provided by DLRootObject objs)
chooseColumn
^ self chooseColumnWithWeight: #size withOpt: #<
chooseColumnWithWeight: weightBlock withOpt: optBlock
^ self
untilFixPointOf: [ :ro | ro left ]
foldr: [ :j :r |
(optBlock value: (weightBlock value: j) value: (weightBlock value: r))
ifTrue: [ j ]
ifFalse: [ r ] ]
init: self right
that minimizes the search tree’s branching factor.
DLColumnObject instance side
The operation of covering column c removes c from the header list and
removes all rows in c’s own list from the other column lists they are in.
cover
we remove.
self
untilFixPointOf: [ :co | co down ]
do: [ :i |
i
untilFixPointOf: [ :do | do right ]
do: [ :j |
j nsLink remove.
j column updateSize: [ :s | s - 1 ] ] ]
Operation (1) is used here to remove objects in both the horizontal and
vertical directions.
DLColumnObject instance side
Finally, we get to the operation of uncovering a given column c. Here is
where the links do their dance:
uncover
self
untilFixPointOf: [ :co | co up ]
do: [ :i |
i
untilFixPointOf: [ :do | do left ]
do: [ :j |
j nsLink restore.
j column updateSize: [ :s | s + 1 ] ] ].
we restore
Notice that uncovering takes place in precisely the reverse order of the
covering operation, using the fact that (2) undoes (1).
Sudoku to Exact Cover reduction
emptySudokuIndicators
| ones start end |
start := 0. end := 8. ones := LinkedList new.
start to: end do: [ :row |
start to: end do: [ :column |
start to: end do: [ :value |
| rowIndex cellConstraint rowConstraint
columnConstraint boxConstraint model |
model := {(#x -> row). (#y -> column). (#v -> value)} asDictionary.
rowIndex := 81 * row + (9 * column) + value.
cellConstraint := rowIndex @ ((end + 1) * row + column).
rowConstraint := rowIndex @ (9 * row + value + 81).
columnConstraint := rowIndex @ (9 * column + value + (81 * 2)).
boxConstraint := rowIndex
@ (27 * (row // 3) + (9 * (column // 3)) + value + (81 * 3)).
ones
add: ((cellConstraint + 1) asDLPoint primary: true) -> model;
add: ((rowConstraint + 1) asDLPoint primary: true) -> model;
add: ((columnConstraint + 1) asDLPoint primary: true) -> model;
add: ((boxConstraint + 1) asDLPoint primary: true) -> model ] ] ].
^ ones
Soduku solutions
testDLXonSudoku
| grid sols chain matrices |
grid := DLDataObject gridOn: DLDataObjectTest new emptySudokuIndicators.
chain := Generator
on: [ :g | AlgorithmX new
searchDLRootObject: (grid at: #root)
onSolutionDo: [ :sel | g yield: sel ] ].
sols := (chain next: 2) contents.
matrices := sols collect: [ :sol | "build the corresponding matrix" ].
self
assert: matrices first printString
equals:
'(9 8 7 6 5 4 3 2 1
6 5 4 3 2 1 9 8 7
3 2 1 9 8 7 6 5 4
8 9 6 7 4 5 2 1 3
7 4 5 2 1 3 8 9 6
2 1 3 8 9 6 7 4 5
5 7 9 4 6 8 1 3 2
4 6 8 1 3 2 5 7 9
1 3 2 5 7 9 4 6 8 )'.
N-Queens to Exact Cover reduction
NQueensIndicators: n
| ones |
ones := LinkedList new.
0 to: n - 1 do: [ :row |
0 to: n - 1 do: [ :column |
| rowIndex rowConstraint columnConstraint
diagonalConstraint antiDiagonalConstraint model |
model := Dictionary new at: #x put: row; at: #y put: column; yourself.
rowIndex := n * row + column.
rowConstraint := rowIndex @ row.
columnConstraint := rowIndex @ (n + column).
diagonalConstraint := rowIndex @ (2 * n + (row + column)).
antiDiagonalConstraint := rowIndex
@ (2 * n + (2 * n) - 1 + (n - 1 - row + column)).
ones
add: ((rowConstraint + 1) asDLPoint primary: true) -> model;
add: ((columnConstraint + 1) asDLPoint primary: true) -> model;
add: ((diagonalConstraint + 1) asDLPoint primary: false) -> model;
add: ((antiDiagonalConstraint + 1) asDLPoint primary: false) -> model
^ ones
N-Queens solutions
testDLXon_NQueens_sequence
| seq elapsedTime |
elapsedTime := [ seq := (1 to: 10)
collect: [ :i | (self runDLXonNQueens: i next: nil) size ] ] timeToRun.
self assert: elapsedTime < 2 asSeconds.
self assert: seq "also known as https://oeis.org/A000170"
equals: {1 . 0 . 0 . 2 . 10 . 4 . 40 . 92 . 352 . 724}
testDLXon_8Queens
| matrices |
matrices := self runDLXonNQueens: 8 next: 1.
self
assert: matrices first printString
equals:
'(0 0 0 0 0 0 0 1
0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0 )'.
Final remarks
We presented a vanilla implementation of DLX with the ZDD
extension in pure Smalltalk, with an educational savor.
It is designed to be easy to understand and to play with still
remaining efficient and robust.
Dancing links are considered the state-of-the-art heuristic for EC
:) Knuth is still actively working on this (a new fascicle is in prep 3
)
:( Constraints are verbose and rigid to express (currently we use
Point objs), looking for a DSL that makes coding constraints easier
TODO
Group column objects using different colours to gain expressivity
Write reductions to Exact Cover (from 3SAT, Knapsack, TSP, ...)
3https://cs.stanford.edu/~knuth/fasc5c.ps.gz
Thanks!
yieldNode: tree onBlock: cont
tree sets
collect: [ :each | (each collect: #model) as: LinkedList ]
thenDo: [ :sel |
| link |
link := sel isEmpty ifTrue: [ nil ] ifFalse: [ sel firstLink ].
cont value: link ].
^ tree
uniqueNodeWithDLDataObject: r withLowerNode: x withHigherNode: y
| key |
key := Array with: r with: x with: y.
^ zDDTree
at: key
ifAbsentPut: [ | z |
z := ZDDNode new model: r; lower: x; higher: y; yourself.
x parent: z.
y parent: z.
z ]
DLDataObject class side
gridOn: aCollection
| rootObj columns rows headers allObjs |
aCollection
sort: [ :vAssoc :wAssoc |
| v w |
v := vAssoc key.
w := wAssoc key.
v y <= w y and: [ v x <= w x ] ].
allObjs := Dictionary new.
headers := DoubleLinkedList new.
columns := Dictionary new.
rows := Dictionary new.
rootObj := DLRootObject new
addInDoubleLinkedList: headers direction: #we;
yourself.
allObjs at: #root put: rootObj.
"to be contd..."
DLDataObject class side
gridOn: aCollection
"...contd..."
aCollection
do: [ :anAssociation |
| aPoint columnObj dataObj column row |
aPoint := anAssociation key.
column := columns
at: aPoint y
ifAbsentPut: [ | headerObj newColumn |
headerObj := DLColumnObject new size: 0; root: rootObj; yourself.
aPoint primary
ifTrue: [ headerObj addInDoubleLinkedList: headers
direction: #we ]
ifFalse: [ DoubleLinkedList
circular: [ :dll | headerObj addInDoubleLinkedList: dll
direction: #we ] ].
newColumn := DoubleLinkedList new.
headerObj addInDoubleLinkedList: newColumn direction: #ns.
allObjs at: aPoint y put: headerObj.
newColumn ].
"..to be contd further..."
DLDataObject class side
gridOn: aCollection
"...contd"
columnObj := column first.
dataObj := DLDataObject new
column: columnObj;
point: aPoint;
model: anAssociation value;
yourself.
row := rows at: aPoint x ifAbsentPut: [ DoubleLinkedList new ].
dataObj
addInDoubleLinkedList: column direction: #ns;
addInDoubleLinkedList: row direction: #we.
columnObj updateSize: [ :s | s + 1 ].
allObjs at: aPoint put: dataObj ].
headers makeCircular.
columns valuesDo: #makeCircular.
rows valuesDo: #makeCircular.
^ allObjs

Weitere ähnliche Inhalte

Was ist angesagt?

Introduction to haskell
Introduction to haskellIntroduction to haskell
Introduction to haskellLuca Molteni
 
Real World Haskell: Lecture 4
Real World Haskell: Lecture 4Real World Haskell: Lecture 4
Real World Haskell: Lecture 4Bryan O'Sullivan
 
Abstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsAbstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsPhilip Schwarz
 
Introducing: A Complete Algebra of Data
Introducing: A Complete Algebra of DataIntroducing: A Complete Algebra of Data
Introducing: A Complete Algebra of DataInside Analysis
 
Review session2
Review session2Review session2
Review session2NEEDY12345
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...Philip Schwarz
 
Computer Graphics in Java and Scala - Part 1
Computer Graphics in Java and Scala - Part 1Computer Graphics in Java and Scala - Part 1
Computer Graphics in Java and Scala - Part 1Philip Schwarz
 
Lec 9 05_sept [compatibility mode]
Lec 9 05_sept [compatibility mode]Lec 9 05_sept [compatibility mode]
Lec 9 05_sept [compatibility mode]Palak Sanghani
 
Proof of O(log *n) time complexity of Union find (Presentation by Wei Li, Zeh...
Proof of O(log *n) time complexity of Union find (Presentation by Wei Li, Zeh...Proof of O(log *n) time complexity of Union find (Presentation by Wei Li, Zeh...
Proof of O(log *n) time complexity of Union find (Presentation by Wei Li, Zeh...Amrinder Arora
 
The Functional Programming Triad of fold, scan and iterate
The Functional Programming Triad of fold, scan and iterateThe Functional Programming Triad of fold, scan and iterate
The Functional Programming Triad of fold, scan and iteratePhilip Schwarz
 
An Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using HaskellAn Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using HaskellMichel Rijnders
 
Scilab - Piecewise Functions
Scilab - Piecewise FunctionsScilab - Piecewise Functions
Scilab - Piecewise FunctionsJorge Jasso
 
Chapter 7.3
Chapter 7.3Chapter 7.3
Chapter 7.3sotlsoc
 

Was ist angesagt? (20)

Introduction to haskell
Introduction to haskellIntroduction to haskell
Introduction to haskell
 
Real World Haskell: Lecture 4
Real World Haskell: Lecture 4Real World Haskell: Lecture 4
Real World Haskell: Lecture 4
 
Abstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generatorsAbstracting over the Monad yielded by a for comprehension and its generators
Abstracting over the Monad yielded by a for comprehension and its generators
 
Introducing: A Complete Algebra of Data
Introducing: A Complete Algebra of DataIntroducing: A Complete Algebra of Data
Introducing: A Complete Algebra of Data
 
Dijkstra c
Dijkstra cDijkstra c
Dijkstra c
 
Review session2
Review session2Review session2
Review session2
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
 
Computer Graphics in Java and Scala - Part 1
Computer Graphics in Java and Scala - Part 1Computer Graphics in Java and Scala - Part 1
Computer Graphics in Java and Scala - Part 1
 
Lec 9 05_sept [compatibility mode]
Lec 9 05_sept [compatibility mode]Lec 9 05_sept [compatibility mode]
Lec 9 05_sept [compatibility mode]
 
Proof of O(log *n) time complexity of Union find (Presentation by Wei Li, Zeh...
Proof of O(log *n) time complexity of Union find (Presentation by Wei Li, Zeh...Proof of O(log *n) time complexity of Union find (Presentation by Wei Li, Zeh...
Proof of O(log *n) time complexity of Union find (Presentation by Wei Li, Zeh...
 
Matlab algebra
Matlab algebraMatlab algebra
Matlab algebra
 
Data Structures- Hashing
Data Structures- Hashing Data Structures- Hashing
Data Structures- Hashing
 
The Functional Programming Triad of fold, scan and iterate
The Functional Programming Triad of fold, scan and iterateThe Functional Programming Triad of fold, scan and iterate
The Functional Programming Triad of fold, scan and iterate
 
Machnical Engineering Assignment Help
Machnical Engineering Assignment HelpMachnical Engineering Assignment Help
Machnical Engineering Assignment Help
 
Algorithm Homework Help
Algorithm Homework HelpAlgorithm Homework Help
Algorithm Homework Help
 
Soft Heaps
Soft HeapsSoft Heaps
Soft Heaps
 
An Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using HaskellAn Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using Haskell
 
Lec23
Lec23Lec23
Lec23
 
Scilab - Piecewise Functions
Scilab - Piecewise FunctionsScilab - Piecewise Functions
Scilab - Piecewise Functions
 
Chapter 7.3
Chapter 7.3Chapter 7.3
Chapter 7.3
 

Ähnlich wie Dancing Links: an educational pearl

Deep Learning, Keras, and TensorFlow
Deep Learning, Keras, and TensorFlowDeep Learning, Keras, and TensorFlow
Deep Learning, Keras, and TensorFlowOswald Campesato
 
Deep Learning: R with Keras and TensorFlow
Deep Learning: R with Keras and TensorFlowDeep Learning: R with Keras and TensorFlow
Deep Learning: R with Keras and TensorFlowOswald Campesato
 
High-Performance Haskell
High-Performance HaskellHigh-Performance Haskell
High-Performance HaskellJohan Tibell
 
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docxSAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docxagnesdcarey33086
 
CE344L-200365-Lab2.pdf
CE344L-200365-Lab2.pdfCE344L-200365-Lab2.pdf
CE344L-200365-Lab2.pdfUmarMustafa13
 
Vectorise all the things - long version.pptx
Vectorise all the things - long version.pptxVectorise all the things - long version.pptx
Vectorise all the things - long version.pptxJodieBurchell1
 
Fundamentals of data structures
Fundamentals of data structuresFundamentals of data structures
Fundamentals of data structuresNiraj Agarwal
 
Reasoning about laziness
Reasoning about lazinessReasoning about laziness
Reasoning about lazinessJohan Tibell
 
Introduction to Matlab - Basic Functions
Introduction to Matlab - Basic FunctionsIntroduction to Matlab - Basic Functions
Introduction to Matlab - Basic Functionsjoellivz
 
MATLAB/SIMULINK for Engineering Applications day 2:Introduction to simulink
MATLAB/SIMULINK for Engineering Applications day 2:Introduction to simulinkMATLAB/SIMULINK for Engineering Applications day 2:Introduction to simulink
MATLAB/SIMULINK for Engineering Applications day 2:Introduction to simulinkreddyprasad reddyvari
 
Real World Haskell: Lecture 2
Real World Haskell: Lecture 2Real World Haskell: Lecture 2
Real World Haskell: Lecture 2Bryan O'Sullivan
 
CS 354 More Graphics Pipeline
CS 354 More Graphics PipelineCS 354 More Graphics Pipeline
CS 354 More Graphics PipelineMark Kilgard
 
C++ STL (quickest way to learn, even for absolute beginners).pptx
C++ STL (quickest way to learn, even for absolute beginners).pptxC++ STL (quickest way to learn, even for absolute beginners).pptx
C++ STL (quickest way to learn, even for absolute beginners).pptxAbhishek Tirkey
 

Ähnlich wie Dancing Links: an educational pearl (20)

Statistics lab 1
Statistics lab 1Statistics lab 1
Statistics lab 1
 
Q
QQ
Q
 
Introduction to R
Introduction to RIntroduction to R
Introduction to R
 
Deep Learning, Keras, and TensorFlow
Deep Learning, Keras, and TensorFlowDeep Learning, Keras, and TensorFlow
Deep Learning, Keras, and TensorFlow
 
Deep Learning: R with Keras and TensorFlow
Deep Learning: R with Keras and TensorFlowDeep Learning: R with Keras and TensorFlow
Deep Learning: R with Keras and TensorFlow
 
High-Performance Haskell
High-Performance HaskellHigh-Performance Haskell
High-Performance Haskell
 
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docxSAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
SAMPLE QUESTIONExercise 1 Consider the functionf (x,C).docx
 
CE344L-200365-Lab2.pdf
CE344L-200365-Lab2.pdfCE344L-200365-Lab2.pdf
CE344L-200365-Lab2.pdf
 
Matlab1
Matlab1Matlab1
Matlab1
 
MATLABgraphPlotting.pptx
MATLABgraphPlotting.pptxMATLABgraphPlotting.pptx
MATLABgraphPlotting.pptx
 
Vectorise all the things - long version.pptx
Vectorise all the things - long version.pptxVectorise all the things - long version.pptx
Vectorise all the things - long version.pptx
 
Fundamentals of data structures
Fundamentals of data structuresFundamentals of data structures
Fundamentals of data structures
 
Reasoning about laziness
Reasoning about lazinessReasoning about laziness
Reasoning about laziness
 
Introduction to Matlab - Basic Functions
Introduction to Matlab - Basic FunctionsIntroduction to Matlab - Basic Functions
Introduction to Matlab - Basic Functions
 
MATLAB/SIMULINK for Engineering Applications day 2:Introduction to simulink
MATLAB/SIMULINK for Engineering Applications day 2:Introduction to simulinkMATLAB/SIMULINK for Engineering Applications day 2:Introduction to simulink
MATLAB/SIMULINK for Engineering Applications day 2:Introduction to simulink
 
Tutorial 2
Tutorial     2Tutorial     2
Tutorial 2
 
Real World Haskell: Lecture 2
Real World Haskell: Lecture 2Real World Haskell: Lecture 2
Real World Haskell: Lecture 2
 
CS 354 More Graphics Pipeline
CS 354 More Graphics PipelineCS 354 More Graphics Pipeline
CS 354 More Graphics Pipeline
 
Linked list
Linked listLinked list
Linked list
 
C++ STL (quickest way to learn, even for absolute beginners).pptx
C++ STL (quickest way to learn, even for absolute beginners).pptxC++ STL (quickest way to learn, even for absolute beginners).pptx
C++ STL (quickest way to learn, even for absolute beginners).pptx
 

Mehr von ESUG

Workshop: Identifying concept inventories in agile programming
Workshop: Identifying concept inventories in agile programmingWorkshop: Identifying concept inventories in agile programming
Workshop: Identifying concept inventories in agile programmingESUG
 
Technical documentation support in Pharo
Technical documentation support in PharoTechnical documentation support in Pharo
Technical documentation support in PharoESUG
 
The Pharo Debugger and Debugging tools: Advances and Roadmap
The Pharo Debugger and Debugging tools: Advances and RoadmapThe Pharo Debugger and Debugging tools: Advances and Roadmap
The Pharo Debugger and Debugging tools: Advances and RoadmapESUG
 
Sequence: Pipeline modelling in Pharo
Sequence: Pipeline modelling in PharoSequence: Pipeline modelling in Pharo
Sequence: Pipeline modelling in PharoESUG
 
Migration process from monolithic to micro frontend architecture in mobile ap...
Migration process from monolithic to micro frontend architecture in mobile ap...Migration process from monolithic to micro frontend architecture in mobile ap...
Migration process from monolithic to micro frontend architecture in mobile ap...ESUG
 
Analyzing Dart Language with Pharo: Report and early results
Analyzing Dart Language with Pharo: Report and early resultsAnalyzing Dart Language with Pharo: Report and early results
Analyzing Dart Language with Pharo: Report and early resultsESUG
 
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6ESUG
 
A Unit Test Metamodel for Test Generation
A Unit Test Metamodel for Test GenerationA Unit Test Metamodel for Test Generation
A Unit Test Metamodel for Test GenerationESUG
 
Creating Unit Tests Using Genetic Programming
Creating Unit Tests Using Genetic ProgrammingCreating Unit Tests Using Genetic Programming
Creating Unit Tests Using Genetic ProgrammingESUG
 
Threaded-Execution and CPS Provide Smooth Switching Between Execution Modes
Threaded-Execution and CPS Provide Smooth Switching Between Execution ModesThreaded-Execution and CPS Provide Smooth Switching Between Execution Modes
Threaded-Execution and CPS Provide Smooth Switching Between Execution ModesESUG
 
Exploring GitHub Actions through EGAD: An Experience Report
Exploring GitHub Actions through EGAD: An Experience ReportExploring GitHub Actions through EGAD: An Experience Report
Exploring GitHub Actions through EGAD: An Experience ReportESUG
 
Pharo: a reflective language A first systematic analysis of reflective APIs
Pharo: a reflective language A first systematic analysis of reflective APIsPharo: a reflective language A first systematic analysis of reflective APIs
Pharo: a reflective language A first systematic analysis of reflective APIsESUG
 
Garbage Collector Tuning
Garbage Collector TuningGarbage Collector Tuning
Garbage Collector TuningESUG
 
Improving Performance Through Object Lifetime Profiling: the DataFrame Case
Improving Performance Through Object Lifetime Profiling: the DataFrame CaseImproving Performance Through Object Lifetime Profiling: the DataFrame Case
Improving Performance Through Object Lifetime Profiling: the DataFrame CaseESUG
 
Pharo DataFrame: Past, Present, and Future
Pharo DataFrame: Past, Present, and FuturePharo DataFrame: Past, Present, and Future
Pharo DataFrame: Past, Present, and FutureESUG
 
thisContext in the Debugger
thisContext in the DebuggerthisContext in the Debugger
thisContext in the DebuggerESUG
 
Websockets for Fencing Score
Websockets for Fencing ScoreWebsockets for Fencing Score
Websockets for Fencing ScoreESUG
 
ShowUs: PharoJS.org Develop in Pharo, Run on JavaScript
ShowUs: PharoJS.org Develop in Pharo, Run on JavaScriptShowUs: PharoJS.org Develop in Pharo, Run on JavaScript
ShowUs: PharoJS.org Develop in Pharo, Run on JavaScriptESUG
 
Advanced Object- Oriented Design Mooc
Advanced Object- Oriented Design MoocAdvanced Object- Oriented Design Mooc
Advanced Object- Oriented Design MoocESUG
 
A New Architecture Reconciling Refactorings and Transformations
A New Architecture Reconciling Refactorings and TransformationsA New Architecture Reconciling Refactorings and Transformations
A New Architecture Reconciling Refactorings and TransformationsESUG
 

Mehr von ESUG (20)

Workshop: Identifying concept inventories in agile programming
Workshop: Identifying concept inventories in agile programmingWorkshop: Identifying concept inventories in agile programming
Workshop: Identifying concept inventories in agile programming
 
Technical documentation support in Pharo
Technical documentation support in PharoTechnical documentation support in Pharo
Technical documentation support in Pharo
 
The Pharo Debugger and Debugging tools: Advances and Roadmap
The Pharo Debugger and Debugging tools: Advances and RoadmapThe Pharo Debugger and Debugging tools: Advances and Roadmap
The Pharo Debugger and Debugging tools: Advances and Roadmap
 
Sequence: Pipeline modelling in Pharo
Sequence: Pipeline modelling in PharoSequence: Pipeline modelling in Pharo
Sequence: Pipeline modelling in Pharo
 
Migration process from monolithic to micro frontend architecture in mobile ap...
Migration process from monolithic to micro frontend architecture in mobile ap...Migration process from monolithic to micro frontend architecture in mobile ap...
Migration process from monolithic to micro frontend architecture in mobile ap...
 
Analyzing Dart Language with Pharo: Report and early results
Analyzing Dart Language with Pharo: Report and early resultsAnalyzing Dart Language with Pharo: Report and early results
Analyzing Dart Language with Pharo: Report and early results
 
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
Transpiling Pharo Classes to JS ECMAScript 5 versus ECMAScript 6
 
A Unit Test Metamodel for Test Generation
A Unit Test Metamodel for Test GenerationA Unit Test Metamodel for Test Generation
A Unit Test Metamodel for Test Generation
 
Creating Unit Tests Using Genetic Programming
Creating Unit Tests Using Genetic ProgrammingCreating Unit Tests Using Genetic Programming
Creating Unit Tests Using Genetic Programming
 
Threaded-Execution and CPS Provide Smooth Switching Between Execution Modes
Threaded-Execution and CPS Provide Smooth Switching Between Execution ModesThreaded-Execution and CPS Provide Smooth Switching Between Execution Modes
Threaded-Execution and CPS Provide Smooth Switching Between Execution Modes
 
Exploring GitHub Actions through EGAD: An Experience Report
Exploring GitHub Actions through EGAD: An Experience ReportExploring GitHub Actions through EGAD: An Experience Report
Exploring GitHub Actions through EGAD: An Experience Report
 
Pharo: a reflective language A first systematic analysis of reflective APIs
Pharo: a reflective language A first systematic analysis of reflective APIsPharo: a reflective language A first systematic analysis of reflective APIs
Pharo: a reflective language A first systematic analysis of reflective APIs
 
Garbage Collector Tuning
Garbage Collector TuningGarbage Collector Tuning
Garbage Collector Tuning
 
Improving Performance Through Object Lifetime Profiling: the DataFrame Case
Improving Performance Through Object Lifetime Profiling: the DataFrame CaseImproving Performance Through Object Lifetime Profiling: the DataFrame Case
Improving Performance Through Object Lifetime Profiling: the DataFrame Case
 
Pharo DataFrame: Past, Present, and Future
Pharo DataFrame: Past, Present, and FuturePharo DataFrame: Past, Present, and Future
Pharo DataFrame: Past, Present, and Future
 
thisContext in the Debugger
thisContext in the DebuggerthisContext in the Debugger
thisContext in the Debugger
 
Websockets for Fencing Score
Websockets for Fencing ScoreWebsockets for Fencing Score
Websockets for Fencing Score
 
ShowUs: PharoJS.org Develop in Pharo, Run on JavaScript
ShowUs: PharoJS.org Develop in Pharo, Run on JavaScriptShowUs: PharoJS.org Develop in Pharo, Run on JavaScript
ShowUs: PharoJS.org Develop in Pharo, Run on JavaScript
 
Advanced Object- Oriented Design Mooc
Advanced Object- Oriented Design MoocAdvanced Object- Oriented Design Mooc
Advanced Object- Oriented Design Mooc
 
A New Architecture Reconciling Refactorings and Transformations
A New Architecture Reconciling Refactorings and TransformationsA New Architecture Reconciling Refactorings and Transformations
A New Architecture Reconciling Refactorings and Transformations
 

Kürzlich hochgeladen

Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 

Kürzlich hochgeladen (20)

Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 

Dancing Links: an educational pearl

  • 1. Dancing Links an educational pearl Massimo Nocentini, PhD. massimo.nocentini@gmail.com ESUG2019 – August 28, 2019.
  • 2. outline ^ LinkedList new add: 'me and the core idea'; add: 'DoubleLink objs'; add: 'exact cover problem'; add: 'AlgorithmX'; add: 'covering and uncovering columns'; add: 'N-Queens and Sudoku problems'; yourself
  • 3. Hi! $ whoami Massimo Nocentini, PhD Mathematician (algebraic combinatorics, formal methods for algs) Programmer (automated reasoning, logics and symbolic comp) https://github.com/massimo-nocentini/dancinglinksst In Donald’s words1 : Suppose x points to an element of a doubly linked list; let L[x] and R[x] point to the predecessor and successor of that element. Then: L[R[x]] ← L[x], R[L[x]] ← R[x] (1) remove x from the list; every programmer knows this. But comparatively few programmers have realized that L[R[x]] ← x, R[L[x]] ← x (2) will put x back again, with no refs to the whole list at all. 1https://arxiv.org/abs/cs/0011047
  • 5. Main ideas Operation (2) arises in backtrack programs, which enumerate all solutions to a given set of constraints and it was introduced in 1979 by Hitotumatu and Noshita. The beauty of (2) is that operation (1) can be undone by knowing only the value of x. We can apply (1) and (2) repeatedly in complex data structures that involve large numbers of interacting doubly linked lists. Knuth: “This process causes the pointer variables inside the global data structure to execute an exquisitely choreographed dance; hence I like to call (1) and (2) the technique of dancing links.” Minato et al. 2 constructs a Zero-suppressed BDD (ZDD) that represents the set of sols and it enables the efficient use of memo cache to speed up the search. 2https://aaai.org/ocs/index.php/AAAI/AAAI17/paper/view/14907
  • 6. DoubleLinks and DoubleLinkedLists DoubleLink objects respond to messages remove nextLink ifNotNil: [ :next | next previousLink: previousLink ]. previousLink ifNotNil: [ :previous | previous nextLink: nextLink ] and restore nextLink ifNotNil: [ :next | next previousLink: self ]. previousLink ifNotNil: [ :previous | previous nextLink: self ] that implement operations (1) and (2), respectively; moreover, we extend DoubleLinkedList objects with the message makeCircular head ifNotNil: [ head previousLink: tail. tail nextLink: head ] to introduce circular, doubly connected, lists.
  • 7. Exact Cover ∈ NP Given a matrix of 0s and 1s, does it have a set of rows containing exactly one symbol 1 in each column? The problem with matrix       r1 r2 r3 r4 r5       T       1 1 1 0 1 0 1 1 0 0 0 0 0 0 0 1 0 1 0 0 1 1 0 1 0 0 1 0 1 0       =         1 1 1 1 1 1         T is solved by two sets of rows, namely {r1 = 1, r3 = 1} and {r2 = 1, r5 = 1, r3 = 1}. We can think of the columns as elements of a universe, and the rows as subsets of the universe; then the problem is to cover the universe with disjoint subsets, NP-complete even when each row contains exactly three 1s.
  • 9. AlgorithmX instance side searchDepth: k forDLRootObject: h partialSelection: cont ^ (h isFixPointOf: [ :ro | ro right ]) ifTrue: [ self yieldNode: top onBlock: cont ] ifFalse: [ memo at: h columns ifPresent: [ :tree | self yieldNode: tree onBlock: cont ] ifAbsentPut: [ self searchDepth: k forDLColumnObject: h chooseColumn partialSelection: cont ] ]
  • 10. AlgorithmX instance side searchDepth: k forDLColumnObject: c partialSelection: sel ^ self onEnter: [ c cover ] do: [ c untilFixPointOf: [ :co | co up ] foldr: [ :r :x | | y | y := self searchDepth: k forDLDataObject: r partialSelection: sel. y isZDDBottom ifTrue: [ x ] ifFalse: [ self uniqueNodeWithDLDataObject: r withLowerNode: x withHigherNode: y ] ] init: bottom ] onExit: [ c uncover ]
  • 11. AlgorithmX instance side searchDepth: k forDLDataObject: r partialSelection: cont ^ self onEnter: [ r untilFixPointOf: [ :ro | ro right ] do: [ :j | j column cover ] ] do: [ self searchDepth: k + 1 forDLRootObject: r column root partialSelection: [ :sel | cont value: (ValueLink new value: r model; nextLink: sel; yourself) ] ] onExit: [ r untilFixPointOf: [ :ro | ro left ] do: [ :j | j column uncover ] ]
  • 12. AlgorithmX instance side The entry point is the message searchDLRootObject: h onSolutionDo: aBlock ^ self searchDepth: 0 forDLRootObject: h partialSelection: [ :selLink | aBlock value: (LinkedList new add: selLink; asSet) ] Knuth advices to use the heuristic (provided by DLRootObject objs) chooseColumn ^ self chooseColumnWithWeight: #size withOpt: #< chooseColumnWithWeight: weightBlock withOpt: optBlock ^ self untilFixPointOf: [ :ro | ro left ] foldr: [ :j :r | (optBlock value: (weightBlock value: j) value: (weightBlock value: r)) ifTrue: [ j ] ifFalse: [ r ] ] init: self right that minimizes the search tree’s branching factor.
  • 13. DLColumnObject instance side The operation of covering column c removes c from the header list and removes all rows in c’s own list from the other column lists they are in. cover we remove. self untilFixPointOf: [ :co | co down ] do: [ :i | i untilFixPointOf: [ :do | do right ] do: [ :j | j nsLink remove. j column updateSize: [ :s | s - 1 ] ] ] Operation (1) is used here to remove objects in both the horizontal and vertical directions.
  • 14. DLColumnObject instance side Finally, we get to the operation of uncovering a given column c. Here is where the links do their dance: uncover self untilFixPointOf: [ :co | co up ] do: [ :i | i untilFixPointOf: [ :do | do left ] do: [ :j | j nsLink restore. j column updateSize: [ :s | s + 1 ] ] ]. we restore Notice that uncovering takes place in precisely the reverse order of the covering operation, using the fact that (2) undoes (1).
  • 15. Sudoku to Exact Cover reduction emptySudokuIndicators | ones start end | start := 0. end := 8. ones := LinkedList new. start to: end do: [ :row | start to: end do: [ :column | start to: end do: [ :value | | rowIndex cellConstraint rowConstraint columnConstraint boxConstraint model | model := {(#x -> row). (#y -> column). (#v -> value)} asDictionary. rowIndex := 81 * row + (9 * column) + value. cellConstraint := rowIndex @ ((end + 1) * row + column). rowConstraint := rowIndex @ (9 * row + value + 81). columnConstraint := rowIndex @ (9 * column + value + (81 * 2)). boxConstraint := rowIndex @ (27 * (row // 3) + (9 * (column // 3)) + value + (81 * 3)). ones add: ((cellConstraint + 1) asDLPoint primary: true) -> model; add: ((rowConstraint + 1) asDLPoint primary: true) -> model; add: ((columnConstraint + 1) asDLPoint primary: true) -> model; add: ((boxConstraint + 1) asDLPoint primary: true) -> model ] ] ]. ^ ones
  • 16. Soduku solutions testDLXonSudoku | grid sols chain matrices | grid := DLDataObject gridOn: DLDataObjectTest new emptySudokuIndicators. chain := Generator on: [ :g | AlgorithmX new searchDLRootObject: (grid at: #root) onSolutionDo: [ :sel | g yield: sel ] ]. sols := (chain next: 2) contents. matrices := sols collect: [ :sol | "build the corresponding matrix" ]. self assert: matrices first printString equals: '(9 8 7 6 5 4 3 2 1 6 5 4 3 2 1 9 8 7 3 2 1 9 8 7 6 5 4 8 9 6 7 4 5 2 1 3 7 4 5 2 1 3 8 9 6 2 1 3 8 9 6 7 4 5 5 7 9 4 6 8 1 3 2 4 6 8 1 3 2 5 7 9 1 3 2 5 7 9 4 6 8 )'.
  • 17. N-Queens to Exact Cover reduction NQueensIndicators: n | ones | ones := LinkedList new. 0 to: n - 1 do: [ :row | 0 to: n - 1 do: [ :column | | rowIndex rowConstraint columnConstraint diagonalConstraint antiDiagonalConstraint model | model := Dictionary new at: #x put: row; at: #y put: column; yourself. rowIndex := n * row + column. rowConstraint := rowIndex @ row. columnConstraint := rowIndex @ (n + column). diagonalConstraint := rowIndex @ (2 * n + (row + column)). antiDiagonalConstraint := rowIndex @ (2 * n + (2 * n) - 1 + (n - 1 - row + column)). ones add: ((rowConstraint + 1) asDLPoint primary: true) -> model; add: ((columnConstraint + 1) asDLPoint primary: true) -> model; add: ((diagonalConstraint + 1) asDLPoint primary: false) -> model; add: ((antiDiagonalConstraint + 1) asDLPoint primary: false) -> model ^ ones
  • 18. N-Queens solutions testDLXon_NQueens_sequence | seq elapsedTime | elapsedTime := [ seq := (1 to: 10) collect: [ :i | (self runDLXonNQueens: i next: nil) size ] ] timeToRun. self assert: elapsedTime < 2 asSeconds. self assert: seq "also known as https://oeis.org/A000170" equals: {1 . 0 . 0 . 2 . 10 . 4 . 40 . 92 . 352 . 724} testDLXon_8Queens | matrices | matrices := self runDLXonNQueens: 8 next: 1. self assert: matrices first printString equals: '(0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 )'.
  • 19. Final remarks We presented a vanilla implementation of DLX with the ZDD extension in pure Smalltalk, with an educational savor. It is designed to be easy to understand and to play with still remaining efficient and robust. Dancing links are considered the state-of-the-art heuristic for EC :) Knuth is still actively working on this (a new fascicle is in prep 3 ) :( Constraints are verbose and rigid to express (currently we use Point objs), looking for a DSL that makes coding constraints easier TODO Group column objects using different colours to gain expressivity Write reductions to Exact Cover (from 3SAT, Knapsack, TSP, ...) 3https://cs.stanford.edu/~knuth/fasc5c.ps.gz
  • 21. yieldNode: tree onBlock: cont tree sets collect: [ :each | (each collect: #model) as: LinkedList ] thenDo: [ :sel | | link | link := sel isEmpty ifTrue: [ nil ] ifFalse: [ sel firstLink ]. cont value: link ]. ^ tree uniqueNodeWithDLDataObject: r withLowerNode: x withHigherNode: y | key | key := Array with: r with: x with: y. ^ zDDTree at: key ifAbsentPut: [ | z | z := ZDDNode new model: r; lower: x; higher: y; yourself. x parent: z. y parent: z. z ]
  • 22. DLDataObject class side gridOn: aCollection | rootObj columns rows headers allObjs | aCollection sort: [ :vAssoc :wAssoc | | v w | v := vAssoc key. w := wAssoc key. v y <= w y and: [ v x <= w x ] ]. allObjs := Dictionary new. headers := DoubleLinkedList new. columns := Dictionary new. rows := Dictionary new. rootObj := DLRootObject new addInDoubleLinkedList: headers direction: #we; yourself. allObjs at: #root put: rootObj. "to be contd..."
  • 23. DLDataObject class side gridOn: aCollection "...contd..." aCollection do: [ :anAssociation | | aPoint columnObj dataObj column row | aPoint := anAssociation key. column := columns at: aPoint y ifAbsentPut: [ | headerObj newColumn | headerObj := DLColumnObject new size: 0; root: rootObj; yourself. aPoint primary ifTrue: [ headerObj addInDoubleLinkedList: headers direction: #we ] ifFalse: [ DoubleLinkedList circular: [ :dll | headerObj addInDoubleLinkedList: dll direction: #we ] ]. newColumn := DoubleLinkedList new. headerObj addInDoubleLinkedList: newColumn direction: #ns. allObjs at: aPoint y put: headerObj. newColumn ]. "..to be contd further..."
  • 24. DLDataObject class side gridOn: aCollection "...contd" columnObj := column first. dataObj := DLDataObject new column: columnObj; point: aPoint; model: anAssociation value; yourself. row := rows at: aPoint x ifAbsentPut: [ DoubleLinkedList new ]. dataObj addInDoubleLinkedList: column direction: #ns; addInDoubleLinkedList: row direction: #we. columnObj updateSize: [ :s | s + 1 ]. allObjs at: aPoint put: dataObj ]. headers makeCircular. columns valuesDo: #makeCircular. rows valuesDo: #makeCircular. ^ allObjs