hanoi

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

Towers of Hanoi

The Tower of Hanoi is a classic mathematical puzzle that consists of three rods and a number
of disks of different sizes which can slide onto any rod. The puzzle starts with the disks neatly
stacked in ascending order of size on one rod, the smallest at the top, thus making a conical
shape. The objective of the puzzle is to move the entire stack to another rod, obeying the
following simple rules:

1. Only one disk can be moved at a time: Each move consists of taking the upper disk
from one of the stacks and placing it on top of another stack or on an empty rod.
2. Only the topmost disk can be moved: You cannot move a disk that is below another
disk. Only the disk that is visible at the top of one of the stacks can be moved in a
turn.
3. No disk may be placed on top of a smaller disk: This is a crucial rule. You cannot place
a larger disk onto a smaller disk. Disks must always be stacked in order of decreasing
size from bottom to top.

1. State Function:
State(j,p,t,i) is represented as:
(j,p,t)∈Si.

This function indicates whether a disk j is at position p on tower t at step i. It's the
foundational representation of the game's state at any given move.
2. no_smaller_discs_belove Function:
no-smaller_discs_belove(j,p,t,i) is represented as:

∀k,q (k<j∧1≤k∧p>q∧1≤q)⇒(k,q,t)∉Si

This function ensures that no smaller disks (disk k) are below disk j on tower tt at step i,
adhering to the game's rule that a larger disk can't be placed on a smaller one.
3. no_discs_above Function:
no_discs_above(j,p,t,i) is represented as:

∀k,q (1≤k≤3∧p<q∧1≤q)⇒(k,q,t)∉Si

This function checks that there are no disks above disk j at its position p on tower t at step i.
Only the topmost disk can be moved in the Tower of Hanoi puzzle.
4. pre_move Function:
pre_move(j,p,t,i) is represented as:
(j,p,t)∈Si∧no_smaller_discs_belove(j,p,t,i)∧no_discs_above(j,p,t,i)

This function encapsulates the conditions that must be met before disk j can be moved from
its position p on tower t at step i. It combines the checks for no smaller disks below and no
disks above.
5. post_move Function:
post_move(j,p1,p2,t1,t2,i) is represented as:

(j,p1,t1)∉S(i+1)∧(j,p2,t2)∈S(i+1)∧no_smaller_discs_belove(j,p2,t2,i+1)∧no_discs_above(j,p2,t2,i+1)

This function checks the conditions after disk j has been moved from position p1 on tower t1
to position p2 on tower t2 from step i to step i+1. It ensures that the disk is no longer in its
original position, is in its new position, and maintains the game's rules at its new location.
6. do_move Function:
do_move(j,p1,p2,t1,t2,i) is represented as:

pre_move(j,p1,t1,i)∧post_move(j,p1,p2,t1,t2,i)

This function represents a valid move of a disk j from position p1 on tower t1 to position p2
on tower t2 from step i to step i+1. It combines both the preconditions and postconditions of
a move.
7. Initial State Assert:
S0={(1,3,1),(2,2,1),(3,1,1)}

This assert statement defines the initial state S0 of the puzzle, with all disks arranged on
tower 1 in size order.
8. No Disks on Towers 2 and 3 at Initial State Assert:

∀disk,pos (1≤disk≤3∧1≤pos≤3)⇒((disk,pos,2)∉S0∧(disk,pos,3)∉S0

This assert ensures that towers 2 and 3 are empty at the start of the game.
9. Final State Assert:
S7={(1,3,3),(2,2,3),(3,1,3)}

This assert statement defines the final state S7 of the puzzle, with all disks arranged on
tower 3 in size order, representing the puzzle's solved state.
10. No Disks on Towers 1 and 2 at Final State Assert:

∀disk,pos (1≤disk≤3∧1≤pos≤3)⇒((disk,pos,1)∉S7∧(disk,pos,2)∉S7)

This assert ensures that towers 1 and 2 are empty at the end of the game, indicating a
successful solution.
11. Possible Moves Assert:
∀i (0≤i<7)⇒∃j,p1,p2,t1,t2 (1≤j≤3∧1≤t1≠t2≤3∧1≤p1,p2≤3)∧do_move(j,p1,p2,t1,t2,i)

This assert states that for each step from 0 to 6, there exists a valid move of a disk j that
follows the rules of the game, leading towards the solution.

; Declare the state function


(declare-fun State (Int Int Int Int) Bool)

; Helper function to check if no smaller discs are not belove position p on tower t at step i
(define-fun no-smaller_discs_belove ((j Int) (p Int) (t Int) (i Int)) Bool
(not
(exists ((k Int) (q Int))
(implies
(and (> j k) (>= k 1))
(and (> p q) (>= q 1))
(State k q t i)
)
)
)
)

(define-fun no_discs_above ((j Int) (p Int) (t Int) (i Int)) Bool


(not
(forall ((k Int))
(implies
(and (>= k 1) (<= k 3))
(exists ((q Int))
(implies
(and (> q p) (<= q 3))
(State k q t i)
)
)
)
)
)
)
; Pre-move condition using the helper function
(define-fun pre_move ((j Int) (p Int) (t Int) (i Int)) Bool
(and
(State j p t i)
(no-smaller_discs_belove j p t i)
(no_discs_above j p t i)
)
)

; Post-move condition using the helper function


(define-fun post_move ((j Int) (p1 Int) (p2 Int) (t1 Int) (t2 Int) (i Int) ) Bool
(and
(and
(not (State j p1 t1 (+ i 1)))
(State j p2 t2 (+ i 1))
)
(no-smaller_discs_belove j p2 t2 (+ i 1))
(no_discs_above j p2 t2 (+ i 1))
)
)

; Define the move function


(define-fun do_move ((j Int) (p1 Int) (p2 Int) (t1 Int) (t2 Int) (i Int)) Bool
(and
(pre_move j p1 t1 i)
(post_move j p1 p2 t1 t2 i)
)
)
; Assert the initial state: all discs are on the first tower (tower 1) at move 0
(assert (and
(State 1 3 1 0) ; Disk 1 (smallest) is at position 1 on tower 1 at move 0
(State 2 2 1 0) ; Disk 2 (middle) is at position 2 on tower 1 at move 0
(State 3 1 1 0) ; Disk 3 (largest) is at position 3 on tower 1 at move 0
))

; Assert that no disks are on towers 2 and 3 at move 0, for any position
(assert (forall ((disk Int) (pos Int))
(implies
(and (>= disk 1) (<= disk 3) (>= pos 1) (<= pos 3))
(and
(not (State disk pos 2 0)) ; Disk is not on tower 2 at move 0
(not (State disk pos 3 0)) ; Disk is not on tower 3 at move 0
)
)
)
; Assert the final state: all discs are on the third tower (tower 3) at the final move (move 7)
(assert (and
(State 1 3 3 7) ; Disk 1 (smallest) is at position 3 on tower 3 at move 7
(State 2 2 3 7) ; Disk 2 (middle) is at position 2 on tower 3 at move 7
(State 3 1 3 7) ; Disk 3 (largest) is at position 1 on tower 3 at move 7
))
; Assert that no disks are on towers 1 and 2 at the final move (move 7), for any position
(assert (forall ((disk Int) (pos Int))
(implies
(and (>= disk 1) (<= disk 3) (>= pos 1) (<= pos 3))
(and
(not (State disk pos 1 7)) ; Disk is not on tower 1 at move 7
(not (State disk pos 2 7)) ; Disk is not on tower 2 at move 7
)
)
))
; Encode possible moves using quantifiers
(assert (forall ((i Int)) (implies (and (>= i 0) (< i 7))
(exists ((j Int) (p1 Int) (p2 Int) (t1 Int) (t2 Int))
(and
(>= j 1) (<= j 3)
(>= t1 1) (<= t1 3)
(>= t2 1) (<= t2 3)
(>= p1 1) (<= p1 3)
(>= p2 1) (<= p2 3)
(not (= t1 t2))
(do_move j p1 p2 i t1 t2)
)
)
)))
(check-sat)
; Ask the solver to find a solution
(echo "Step 0:")
(get-value ((State 1 1 1 0) (State 1 2 1 0) (State 1 3 1 0)))
(get-value ((State 2 1 1 0) (State 2 2 1 0) (State 2 3 1 0)))
(get-value ((State 3 1 1 0) (State 3 2 1 0) (State 3 3 1 0)))

(get-value ((State 1 1 2 0) (State 1 2 2 0) (State 1 3 2 0)))


(get-value ((State 2 1 2 0) (State 2 2 2 0) (State 2 3 2 0)))
(get-value ((State 3 1 2 0) (State 3 2 2 0) (State 3 3 2 0)))

(get-value ((State 1 1 3 0) (State 1 2 3 0) (State 1 3 3 0)))


(get-value ((State 2 1 3 0) (State 2 2 3 0) (State 2 3 3 0)))
(get-value ((State 3 1 3 0) (State 3 2 3 0) (State 3 3 3 0)))

(echo "Step 1:")


(get-value ((State 1 1 1 1) (State 1 2 1 1) (State 1 3 1 1)))
(get-value ((State 2 1 1 1) (State 2 2 1 1) (State 2 3 1 1)))
(get-value ((State 3 1 1 1) (State 3 2 1 1) (State 3 3 1 1)))

(get-value ((State 1 1 2 1) (State 1 2 2 1) (State 1 3 2 1)))


(get-value ((State 2 1 2 1) (State 2 2 2 1) (State 2 3 2 1)))
(get-value ((State 3 1 2 1) (State 3 2 2 1) (State 3 3 2 1)))

(get-value ((State 1 1 3 1) (State 1 2 3 1) (State 1 3 3 1)))


(get-value ((State 2 1 3 1) (State 2 2 3 1) (State 2 3 3 1)))
(get-value ((State 3 1 3 1) (State 3 2 3 1) (State 3 3 3 1)))
(echo "Step 2:")
(get-value ((State 1 1 1 2) (State 1 2 1 2) (State 1 3 1 2)))
(get-value ((State 2 1 1 2) (State 2 2 1 2) (State 2 3 1 2)))
(get-value ((State 3 1 1 2) (State 3 2 1 2) (State 3 3 1 2)))
(get-value ((State 1 1 2 2) (State 1 2 2 2) (State 1 3 2 2)))
(get-value ((State 2 1 2 2) (State 2 2 2 2) (State 2 3 2 2)))
(get-value ((State 3 1 2 2) (State 3 2 2 2) (State 3 3 2 2)))
(get-value ((State 1 1 3 2) (State 1 2 3 2) (State 1 3 3 2)))
(get-value ((State 2 1 3 2) (State 2 2 3 2) (State 2 3 3 2)))
(get-value ((State 3 1 3 2) (State 3 2 3 2) (State 3 3 3 2)))

You might also like