Lock Picking 101 Forum
A community dedicated to the fun and ethical hobby of lock picking.
       

Lock Picking 101 Home
Login
Profile
Members
Forum Rules
Frequent Forum Questions
SEARCH
View New Posts
View Active Topics


Live Chat on Discord
LP101 Forum Chat
Keypicking Forum Chat
Reddit r/lockpicking Chat



Learn How to Pick Locks
FAQs & General Questions
Got Beginner Questions?
Pick-Fu [Intermediate Level]


Ask a Locksmith
This Old Lock
This Old Safe
What Lock Should I Buy?



Hardware
Locks
Lock Patents
Lock Picks
Lock Bumping
Lock Impressioning
Lock Pick Guns, Snappers
European Locks & Picks
The Machine Shop
The Open Source Lock
Handcuffs


Member Spotlight
Member Introductions
Member Lock Collections
Member Social Media


Off Topic
General Chatter
Other Puzzles


Locksmith Business Info
Training & Licensing
Running a Business
Keyways & Key Blanks
Key Machines
Master Keyed Systems
Closers and Crash Bars
Life Safety Compliance
Electronic Locks & Access
Locksmith Supplies
Locksmith Lounge


Buy Sell Trade
Buy - Sell - Trade
It came from Ebay!


Advanced Topics
Membership Information
Special Access Required:
High Security Locks
Vending Locks
Advanced Lock Pick Tools
Bypass Techniques
Safes & Safe Locks
Automotive Entry & Tools
Advanced Buy/Sell/Trade


Locksport Groups
Locksport Local
Chapter President's Office
Locksport Board Room
 

Computing Total Differs (with lots of math)

Information about locks themselves. Questions, tips and lock diagram information should be posted here.

Computing Total Differs (with lots of math)

Postby xylac » 27 Mar 2014 21:10

First of all, be aware that this post is going to be very long and math heavy, but it will be useful to those looking for a mathematical approach to the following problem. I was inspired by this <http://www.lockpicking101.com/viewtopic.php?f=9&t=56649> thread to find a way to compute the total number of differs given a certain MACS.

Let's begin with some terminology. Let n be the number of pins, d be the possible depths, and h be the MACS. For the sake of example, consider a 5 pin system with 10 depths and a MACS of 7. It's easy to bound the solution with [h^n, d^n], but we want an exact answer. We also want something that can be computed as quickly as possible, so even if we have 10,000 pins with 3,000 depths, we can still solve the problem (not practical, but this is math). While I don't know if there's a solution in terms of n, d, and h, we can reduce the amount of time to count the solution pretty far.

Our first case is the code written by user geekmug here. The code is copied below.

Code: Select all
DEPTHS = 10
MAC = 7
PINS = 6

def is_valid_mac(key):
    for i in range(PINS - 1):
        if abs(key[i] - key[i + 1]) > MAC:
            return False
    return True

def main():
    valid = 0
    key = [0] * PINS
    is_not_done = True
    while is_not_done:
        if is_valid_mac(key):
            valid += 1

        for i in range(PINS):
            key[i] += 1
            if key[i] >= DEPTHS:
                key[i] = 0
                if i == PINS - 1 :
                  is_not_done = False
                continue
            else:
                break

    print("Valid: %d" % (valid,))

if __name__ == '__main__':
    main()


Essentially, the code is creating every possible bitting, and only counting those which do not violate the MACS. That means we are creating d^n keys, and checking up to n-1 chambers for a violation of the MACS. In terms of computational complexity, this solution is O(nd^n), or exponential with respect to n. In other words, this solution is fine for small n (which was the use for this script anyway), but as you increase the number of pins, solving the problem begins to take exponentially longer.

Luckily, we can speed up the solution even more. Let's start by counting all the 5 pin bittings of the form 0----. Then we can count all the 5 pin bittings of the form 1----, 2----, etc. and add them all up at the end. When we're counting the bittings of the form 0----, we can just add up the 4 pin bittings that don't violate the MACS. That is, add up the number of bittings of the form 0---,1---,2---,...,7--- (since we can't have a biting that's 08--- or 09---). Now when we count the bittings of the form 1----, we can just add up the number of bittings of the form 0--- through 8---. However, since we already counted most of these in the previous step, we can save time by remembering the answers we've already computed. In computer science, these concepts are known as recursion and memoization. Here's the code:

Code: Select all
DEPTHS = 10
MAC = 7
PINS = 6

def main():
   combos = [1] * DEPTHS
   for i in range(1,PINS):
      combos2 = [0] * DEPTHS
      for j in range(DEPTHS):
         for k in filter(lambda x: 0<=x<DEPTHS, range(j-MAC,j+MAC+1)):
            combos2[j] += combos[k]
      combos = combos2
   print("Valid: %d" % sum(combos))

if __name__ == '__main__':
   main()


Already you can see it runs slightly faster than the first script. What's the complexity? O(n*d*h). That means it can handle large n, d, and h, without much problem.

We can actually do a little bit better still. If you look at the second piece of code, you'll see that the outermost for loop is doing the equivalent of a matrix multiplication on a vector. If we have
Code: Select all
      [1,1,1,1,1,1,1,1,0,0]               [1]
      [1,1,1,1,1,1,1,1,1,0]               [1]
      [1,1,1,1,1,1,1,1,1,1]               [1]
      [1,1,1,1,1,1,1,1,1,1]               [1]
M =   [1,1,1,1,1,1,1,1,1,1]         and v=[1]
      [1,1,1,1,1,1,1,1,1,1]               [1]
      [1,1,1,1,1,1,1,1,1,1]               [1]
      [1,1,1,1,1,1,1,1,1,1]               [1]
      [0,1,1,1,1,1,1,1,1,1]               [1]
      [0,0,1,1,1,1,1,1,1,1]               [1]


where M is a dxd matrix constructed based on h, the total number of valid combinations for a system of n pins is given by v^T * M^(n-1) * v. In Mathematica,

Code: Select all
DEPTHS = 10
MAC = 7
PINS = 6

mat = Table[If[Abs[i - j] <= MAC, 1, 0],{i,DEPTHS},{j,DEPTHS}]
vec = Table[1, {DEPTHS}]
vec.MatrixPower[mat, PINS-1].vec


Finally, what is the complexity of this solution? Taking the matrix to a power turns out to be the computationally most expensive, and is at most O(d^3*log n). For a fixed d, this is significantly faster than our previous algorithm, and we may even be able to acheive faster results by taking advantage of the Jordan Normal form of our matrix. In this case we could even get an equation in terms of n.

Computing the total number of differs is a highly interesting mathematical problem. Even though keying systems with this many pins is impractical, this exercise should demonstrate an efficient, algorithmic way to compute the total number of differs. I skipped over most of the important details to avoid this from being too long, but if any of you have an interest in computer science or linear algebra, I hope this post has given you something to think about.

-xylac
xylac
 
Posts: 40
Joined: 25 Feb 2013 22:27

Re: Computing Total Differs (with lots of math)

Postby jtucek » 30 Mar 2014 22:51

xylac wrote:First of all, be aware that this post is going to be very long and math heavy, but it will be useful to those looking for a mathematical approach to the following problem. I was inspired by this <http://www.lockpicking101.com/viewtopic.php?f=9&t=56649> thread to find a way to compute the total number of differs given a certain MACS.


Apparently too mathy for most. I found it interesting, though.
xylac wrote:In computer science, these concepts are known as recursion and memoization.


I would have preferred to use dynamic programming (memoization's big brother). Compute the array for number of possible last-positions pins, then work backwards with the number of allowed pins with last and second to last. Technically the same time complexity as memoization, though.

I have 2 questions though: 1) do you think that the "2-step" rule, as well as the "not-all-the same" rule (e.g. no 5-5-5-5-5 keys) can be accounted for by the memoization/dynamic programming algorithms, and 2) could those selfsame rules be accounted for in the matrix-multiplication algorithm?

xylac wrote:Computing the total number of differs is a highly interesting mathematical problem. Even though keying systems with this many pins is impractical, this exercise should demonstrate an efficient, algorithmic way to compute the total number of differs. I skipped over most of the important details to avoid this from being too long, but if any of you have an interest in computer science or linear algebra, I hope this post has given you something to think about.


It was if nothing else interesting to me.

-j
jtucek
 
Posts: 24
Joined: 17 Mar 2014 12:06

Re: Computing Total Differs (with lots of math)

Postby Drifty Flintlock » 3 Apr 2014 17:56

Interesting stuff. I'm a sysdmin, not a programmer or a math guy, so some of the gory details are lost on me. I can envision how to write a fairly inefficient, brute force version of this myself, but yours is much nicer than anything I could do. Still, yeah, I think this is a useful thing to have, and I imagine it wouldn't require THAT much horsepower to sort through any practical key system.
Drifty Flintlock
 
Posts: 45
Joined: 8 Nov 2013 19:34
Location: Midwest USA


Return to Locks

Who is online

Users browsing this forum: Google [Bot] and 5 guests