Điều đầu tiên cần hiểu là P và NP phân loại ngôn ngữ , không phải vấn đề . Để hiểu điều này có nghĩa là gì, chúng ta cần một số định nghĩa khác trước.
Một bảng chữ cái là một tập hợp hữu hạn không trống rỗng của các biểu tượng.
{ 0
, 1
} là một bảng chữ cái như bộ ký tự ASCII. {} không phải là một bảng chữ cái vì nó trống. N (các số nguyên) không phải là một bảng chữ cái vì nó không hữu hạn.
Hãy Σ là một bảng chữ cái. Một nối ra lệnh của một số hữu hạn các ký tự từ Σ được gọi là một từ trên Σ .
Chuỗi 101
là một từ trên bảng chữ cái { 0
, 1
}. Các từ trống (thường được viết như ε ) là một từ trong bất kỳ bảng chữ cái. Chuỗi penguin
là một từ trên bảng chữ cái có chứa các ký tự ASCII. Các ký hiệu thập phân của π số không phải là một từ trên bảng chữ cái { .
, 0
, 1
, 2
, 3
, 4
, 5
, 6
, 7
, 8
, 9
} bởi vì nó không phải là hữu hạn.
Độ dài của một từ w , được viết là | w |, là số ký hiệu trong đó.
Ví dụ: | hello
| = 5 và | ε | = 0. Với mọi từ w , | w | ∈ N và do đó hữu hạn.
Hãy Σ là một bảng chữ cái. Tập Σ * chứa tất cả các từ trên Σ , bao gồm ε . Tập Σ + chứa tất cả các từ trên Σ , trừ ε . Đối với n ∈ N , Σ n là tập hợp các từ có độ dài n .
Đối với mỗi bảng chữ cái Σ , Σ * và Σ + là vô hạn tập hợp đếm được . Đối với các ký tự ASCII bộ Σ ASCII , các biểu thức thông thường .*
và .+
biểu thị Σ ASCII * và Σ ASCII + tương ứng.
{ 0
, 1
} 7 là tập hợp các mã ASCII 7-bit { 0000000
, 0000001
, ..., 1111111
}. { 0
, 1
} 32 là tập hợp các giá trị nguyên 32 bit.
Hãy Σ là một bảng chữ cái và L ⊆ Σ * . L được gọi là ngôn ngữ trên Σ .
Đối với một bảng chữ cái Σ , tập rỗng và Σ * là ngôn ngữ tầm thường trên Σ . Các cựu thường được gọi là ngôn ngữ trống rỗng . Ngôn ngữ trống {} và ngôn ngữ chỉ chứa từ trống { ε } là khác nhau.
Tập hợp con của { 0
, 1
} 32 tương ứng với các giá trị dấu phẩy động không phải NaN IEEE 754 là ngôn ngữ hữu hạn.
Ngôn ngữ có thể có vô số từ nhưng mọi ngôn ngữ đều có thể đếm được. Tập hợp các chuỗi { 1
, 2
, ...} biểu thị số nguyên trong ký hiệu thập phân là một ngôn ngữ vô hạn trong bảng chữ cái { 0
, 1
, 2
, 3
, 4
, 5
, 6
, 7
, 8
, 9
}. Tập hợp vô hạn các chuỗi { 2
, 3
, 5
, 7
, 11
, 13
, ...} biểu thị các số nguyên tố trong ký hiệu thập phân là một tập hợp con thích đó. Ngôn ngữ chứa tất cả các từ khớp với biểu thức chính quy [+-]?\d+\.\d*([eE][+-]?\d+)?
là ngôn ngữ trong bộ ký tự ASCII (biểu thị một tập hợp con của các biểu thức dấu phẩy động hợp lệ như được xác định bởi ngôn ngữ lập trình C).
Không có ngôn ngữ chứa tất cả các số thực (trong bất kỳ ký hiệu nào) vì tập hợp các số thực không thể đếm được.
Hãy Σ là một bảng chữ cái và L ⊆ Σ * . Một máy D quyết định L nếu cho mỗi đầu vào w ∈ Σ * nó tính toán hàm đặc trưng χ L ( w ) trong thời gian hữu hạn. Hàm đặc trưng được định nghĩa là
χ L : Σ * → {0, 1}
w ↦ 1, w ∈ L
0, nếu không.
Một máy như vậy được gọi là một người quyết định cho L . Chúng tôi viết “ D ( w ) = x ” cho “cho w , D kết quả đầu ra x ”.
Có nhiều mẫu máy. Một cái chung nhất được sử dụng thực tế hiện nay là mô hình của máy Turing . Một máy Turing có bộ lưu trữ tuyến tính không giới hạn được nhóm vào các ô. Mỗi ô có thể chứa chính xác một ký hiệu của bảng chữ cái tại bất kỳ thời điểm nào. Máy Turing thực hiện tính toán của nó như một chuỗi các bước tính toán. Trong mỗi bước, nó có thể đọc một ô, có thể ghi đè giá trị của nó và di chuyển đầu đọc / ghi theo một vị trí sang ô bên trái hoặc bên phải. Những hành động mà máy sẽ thực hiện được điều khiển bởi một máy tự động trạng thái hữu hạn.
Một máy truy cập ngẫu nhiên với một bộ hướng dẫn hữu hạn và bộ nhớ không giới hạn là một kiểu máy khác mạnh mẽ như mô hình máy Turing.
Vì lợi ích của cuộc thảo luận này, chúng tôi sẽ không làm phiền chúng tôi với mô hình máy chính xác mà chúng tôi sử dụng mà chỉ nói rằng máy có bộ điều khiển xác định hữu hạn, lưu trữ không giới hạn và thực hiện tính toán như một chuỗi các bước có thể đếm được.
Vì bạn đã sử dụng nó trong câu hỏi của mình, tôi cho rằng bạn đã quen thuộc với ký hiệu của big big-O nên đây chỉ là một cách làm mới nhanh chóng.
Đặt f : N → là một hàm. Tập O ( f ) chứa tất cả các chức năng g : N → N mà có tồn tại các hằng số n 0 ∈ N và c ∈ N sao cho với mỗi n ∈ N với n > n 0 đúng là g ( n ) ≤ c f ( n ).
Bây giờ chúng tôi đã chuẩn bị để tiếp cận câu hỏi thực sự.
Lớp P chứa tất cả các ngôn ngữ L mà tồn tại một máy Turing D rằng quyết định L và một hằng số k ∈ N sao cho với mỗi đầu vào w , D tạm dừng sau ít nhất T (| w |) bước cho một hàm T ∈ O ( n ↦ n k ).
Vì O ( n ↦ n k ), trong khi về mặt toán học, không thuận tiện để viết và đọc, hầu hết mọi người - thành thật mà nói, mọi người ngoại trừ bản thân tôi - thường viết đơn giản là O ( n k ).
Lưu ý rằng ràng buộc phụ thuộc vào độ dài của w . Do đó, đối số bạn đưa ra cho ngôn ngữ của các số nguyên tố chỉ đúng với các số trong bảng mã unaray , trong đó đối với mã hóa w của một số n , độ dài của mã hóa | w | tỷ lệ với n . Không ai sẽ sử dụng một mã hóa như vậy trong thực tế. Tuy nhiên, sử dụng một thuật toán tiên tiến hơn là chỉ đơn giản là thử tất cả các yếu tố có thể, ngôn ngữ của các số nguyên tố vẫn nằm trong P nếu các đầu vào được mã hóa ở dạng nhị phân (hoặc bất kỳ cơ sở nào khác). (Mặc dù có sự quan tâm lớn, nhưng điều này chỉ có thể được chứng minh bởi Manindra Agrawal, Neeraj Kayal và Nitin Saxena trong một bài báo giành giải thưởng năm 2004 để bạn có thể đoán rằng thuật toán này không đơn giản lắm.)
Các ngôn ngữ tầm thường {} và Σ * và ngôn ngữ không tầm thường { ε } rõ ràng trong P (đối với bất kỳ bảng chữ cái Σ ). Bạn có thể viết các hàm trong ngôn ngữ lập trình yêu thích của bạn, lấy một chuỗi làm đầu vào và trả về một boolean cho biết chuỗi đó có phải là một từ trong ngôn ngữ cho mỗi chuỗi này không và chứng minh rằng hàm của bạn có độ phức tạp thời gian chạy đa thức?
Mỗi thường xuyên ngôn ngữ (một ngôn ngữ mô tả bởi một regular expression) là P .
Hãy Σ là một bảng chữ cái và L ⊆ Σ * . Một máy V mà phải mất một tuple được mã hóa của hai chữ w , c ∈ Σ * và đầu ra là 0 hoặc 1 sau một số hữu hạn các bước là một người xác minh cho L nếu nó có các thuộc tính sau.
- Given ( w , c ), V đầu ra 1 chỉ nếu w ∈ L .
- Đối với mỗi w ∈ L , tồn tại một c ∈ Σ * mà V ( w , c ) = 1.
Chữ c trong định nghĩa trên được gọi là nhân chứng (hoặc chứng chỉ ).
Một xác minh được phép cung cấp cho âm tính giả vì sự làm chứng sai ngay cả khi w thực sự là trong L . Tuy nhiên, nó không được phép đưa ra dương tính giả. Nó cũng được yêu cầu rằng đối với mỗi từ trong ngôn ngữ, tồn tại ít nhất một nhân chứng.
Đối với ngôn ngữ COMPOSITE, có chứa mã hóa thập phân của tất cả các số nguyên không phải là số nguyên tố, một nhân chứng có thể là một yếu tố. Ví dụ, (659, 709)
là một nhân chứng cho 467231
∈ COMPOSITE. Bạn có thể dễ dàng xác minh rằng trên một tờ giấy trong khi không có nhân chứng đưa ra, việc chứng minh rằng 467231 không phải là số nguyên tố sẽ khó khăn nếu không sử dụng máy tính.
Chúng tôi đã không nói bất cứ điều gì về cách một nhân chứng thích hợp có thể được tìm thấy. Đây là phần không xác định.
Lớp NP chứa tất cả các ngôn ngữ L mà tồn tại một máy Turing V rằng thẩm tra L và một hằng số k ∈ N như vậy mà cho tất cả các đầu vào ( w , c ), V tạm dừng sau ít nhất T (| w bước cho một chức năng |) T ∈ O ( n ↦ n k ).
Lưu ý rằng định nghĩa trên ngụ ý rằng với mỗi w ∈ L tồn tại một nhân chứng c với | c | ≤ T (| w |). (Máy Turing không thể nhìn vào nhiều biểu tượng của nhân chứng hơn.)
NP là siêu khối của P (tại sao?). Người ta không biết liệu có tồn tại các ngôn ngữ mà là trong NP nhưng không phải trong P .
Yếu tố số nguyên không phải là một ngôn ngữ mỗi se. Tuy nhiên, chúng ta có thể xây dựng một ngôn ngữ đại diện cho vấn đề quyết định liên quan đến nó. Nghĩa là, một ngôn ngữ chứa tất cả các bộ dữ liệu ( n , m ) sao cho n có hệ số d với d ≤ m . Hãy để chúng tôi gọi ngôn ngữ này YẾU TỐ. Nếu bạn có một thuật toán để quyết định FACTOR, nó có thể được sử dụng để tính toán một hệ số đầy đủ chỉ với chi phí đa thức bằng cách thực hiện tìm kiếm nhị phân đệ quy cho từng thừa số nguyên tố.
Thật dễ dàng để chỉ ra rằng FACTOR nằm trong NP . Một nhân chứng thích hợp chỉ đơn giản là nhân tố d và tất cả các trình xác minh sẽ phải làm là xác minh rằng d ≤ m và n mod d = 0. Tất cả điều này có thể được thực hiện trong thời gian đa thức. (Hãy nhớ, một lần nữa, đó là độ dài của mã hóa được tính và đó là logarit trong n .)
Nếu bạn có thể chỉ ra rằng FACTOR cũng ở P , bạn có thể chắc chắn nhận được nhiều giải thưởng hấp dẫn. (Và bạn đã phá vỡ một phần đáng kể của mật mã ngày nay.)
Đối với mọi ngôn ngữ trong NP , có một thuật toán brute-force quyết định nó một cách xác định. Nó chỉ đơn giản là thực hiện một tìm kiếm toàn diện trên tất cả các nhân chứng. (Lưu ý rằng độ dài tối đa của một nhân chứng bị giới hạn bởi một đa thức.) Vì vậy, thuật toán của bạn để quyết định PRIMES thực sự là một thuật toán mạnh mẽ để quyết định COMPOSITE.
Để giải quyết câu hỏi cuối cùng của bạn, chúng tôi cần giới thiệu giảm . Giảm là một khái niệm rất mạnh mẽ của khoa học máy tính lý thuyết. Giảm một vấn đề này sang vấn đề khác về cơ bản có nghĩa là giải quyết một vấn đề bằng cách giải quyết vấn đề khác.
Hãy Σ là một bảng chữ cái và A và B được ngôn ngữ trên Σ . Một là thời gian đa thức nhiều-one khử đến B nếu có tồn tại một hàm f : Σ * → Σ * với các thuộc tính sau.
- w ∈ A ⇔ f ( w ) ∈ B cho tất cả các w ∈ Σ * .
- Hàm f có thể được tính bằng máy Turing cho mọi đầu vào w trong một số bước được giới hạn bởi một đa thức trong | w |.
Trong trường hợp này, chúng tôi viết Một ≤ p B .
Ví dụ: Đặt A là ngôn ngữ chứa tất cả các biểu đồ (được mã hóa dưới dạng ma trận kề) có chứa một hình tam giác. (Một tam giác là một chu kỳ có độ dài 3.) Gọi thêm B là ngôn ngữ chứa tất cả các ma trận có dấu vết khác không. (Các dấu vết của một ma trận là tổng hợp của các yếu tố đường chéo chính của nó.) Sau đó, A là đa thức thời gian nhiều một rút gọn về B . Để chứng minh điều này, chúng ta cần tìm một hàm biến đổi thích hợp f . Trong trường hợp này, chúng ta có thể đặt f để tính công suất thứ 3 của ma trận kề. Điều này đòi hỏi hai sản phẩm ma trận, mỗi sản phẩm có độ phức tạp đa thức.
Đó là trivially đúng là L ≤ p L . (Bạn có thể chứng minh chính thức không?)
Chúng tôi sẽ áp dụng điều này cho NP ngay bây giờ.
Một ngôn ngữ L là NP -hard khi và chỉ khi L '≤ p L cho mọi ngôn ngữ L ' ∈ NP .
Một ngôn ngữ NP -hard có thể có hoặc không có trong chính NP .
Một ngôn ngữ L là NP -complete khi và chỉ khi
Ngôn ngữ NP -complete nổi tiếng nhất là SAT. Nó chứa tất cả các công thức boolean có thể được thỏa mãn. Ví dụ: ( a ∨ b ) ∧ ( a ∨ ¬ b ) ∈ SAT. Một nhân chứng hợp lệ là { a = 1, b = 0}. Công thức ( a ∨ b ) ∧ ( a ∨ b ) ∧ ¬ b ∉ SAT. (Làm thế nào bạn sẽ chứng minh điều đó?)
Không khó để chỉ ra rằng SAT ∈ NP . Để cho thấy NP -hardness of SAT là một số công việc nhưng nó đã được thực hiện vào năm 1971 bởi Stephen Cook .
Khi một ngôn ngữ NP -complete đã được biết đến, việc hiển thị độ linh hoạt NP của các ngôn ngữ khác là tương đối đơn giản . Nếu ngôn ngữ Một được biết đến là NP -Hard, sau đó cho thấy rằng A ≤ p B cho thấy B là NP -Hard, quá (thông qua transitivity của “≤ p ”). Năm 1972 Richard Karp đã công bố một danh sách 21 ngôn ngữ mà ông có thể hiển thị là NP- Hoàn thành thông qua (transitive) giảm SAT. (Đây là bài viết duy nhất trong câu trả lời này mà tôi thực sự khuyên bạn nên đọc. Không giống như những bài khác, nó không khó hiểu và đưa ra một ý tưởng rất hay về cách chứng minh tính đồng bộ NP thông qua việc giảm hoạt động.)
Cuối cùng, một bản tóm tắt ngắn. Chúng ta sẽ sử dụng các ký hiệu NPH và NPC để biểu thị các lớp ngôn ngữ NP -hard và NP -complete tương ứng.
- P ⊆ NP
- NPC ⊂ NP và NPC ⊂ NPH , thực NPC = NP ∩ NPH theo định nghĩa
- ( Một ∈ NP ) ∧ ( B ∈ NPH ) ⇒ Một ≤ p B
Lưu ý rằng sự bao gồm NPC ⊂ NP là thích hợp ngay cả trong trường hợp đó P = NP . Để thấy điều này, hãy làm rõ rằng không có ngôn ngữ không tầm thường nào có thể được giảm xuống thành một ngôn ngữ tầm thường và có những ngôn ngữ tầm thường trong P cũng như các ngôn ngữ không tầm thường trong NP . Đây là một trường hợp góc (không thú vị), mặc dù.
Phụ lục
Nguồn chính của bạn nhầm lẫn dường như thể là bạn đang nghĩ đến việc các “ n ” trong “ O ( n ↦ f ( n ))” như giải thích của đầu vào của một thuật toán khi nó thực sự đề cập đến chiều dài của đầu vào. Đây là một sự khác biệt quan trọng bởi vì nó có nghĩa là độ phức tạp tiệm cận của thuật toán phụ thuộc vào mã hóa được sử dụng cho đầu vào.
Tuần này, một kỷ lục mới cho thủ tướng Mersenne lớn nhất được biết đến đã đạt được. Số nguyên tố lớn nhất hiện được biết đến là 2 74 207 281 - 1. Con số này quá lớn đến nỗi khiến tôi đau đầu nên tôi sẽ sử dụng số nhỏ hơn trong ví dụ sau: 2 31 - 1 = 2 147 483 647. Nó có thể được mã hóa theo những cách khác nhau.
- theo số mũ Mersenne của nó dưới dạng số thập phân:
31
(2 byte)
- dưới dạng số thập phân:
2147483647
(10 byte)
- dưới dạng số đơn nguyên:
11111…11
trong đó số …
được thay thế bằng 2 147 483 640 1
s (gần 2 GiB)
Tất cả các chuỗi này mã hóa cùng một số và được cung cấp bất kỳ chuỗi nào trong số này, chúng ta có thể dễ dàng xây dựng bất kỳ mã hóa nào khác có cùng số. (Bạn có thể thay thế mã hóa thập phân bằng nhị phân, bát phân hoặc thập lục phân nếu bạn muốn. Nó chỉ thay đổi độ dài theo một yếu tố không đổi.)
Thuật toán ngây thơ để kiểm tra tính nguyên thủy chỉ là đa thức cho các mã hóa đơn nguyên. Các thử nghiệm AKS tính nguyên là đa thức cho số thập phân (hoặc bất kỳ cơ sở khác b ≥ 2). Phép thử nguyên thủy Lucas-Lehmer là thuật toán được biết đến nhiều nhất cho các số nguyên tố Mersenne M p với p một số nguyên tố lẻ nhưng nó vẫn theo cấp số nhân về độ dài của mã hóa nhị phân của số mũ Mersenne p (đa thức tính theo p ).
Nếu chúng ta muốn nói về sự phức tạp của một thuật toán, điều rất quan trọng là chúng ta rất rõ ràng chúng ta sử dụng biểu diễn nào. Nói chung, người ta có thể giả định rằng mã hóa hiệu quả nhất được sử dụng. Đó là, nhị phân cho số nguyên. (Lưu ý rằng không phải mọi số nguyên tố đều là số nguyên tố Mersenne nên sử dụng số mũ Mersenne không phải là sơ đồ mã hóa chung.)
Trong mật mã lý thuyết, nhiều thuật toán được chính thức thông qua một chuỗi k 1
s hoàn toàn vô dụng làm tham số đầu tiên. Thuật toán không bao giờ nhìn vào tham số này nhưng nó cho phép nó chính thức là đa thức tính bằng k , là tham số bảo mật được sử dụng để điều chỉnh bảo mật của thủ tục.
Đối với một số vấn đề mà ngôn ngữ quyết định trong mã hóa nhị phân là NP -complete, ngôn ngữ quyết định không còn là NP -complete nếu mã hóa các số nhúng được chuyển thành đơn nguyên. Các ngôn ngữ quyết định cho các vấn đề khác vẫn còn NP -complete. Cái sau được gọi là NP -complete mạnh mẽ . Ví dụ nổi tiếng nhất là bin đóng gói .
Cũng rất thú vị khi xem mức độ phức tạp của thuật toán thay đổi nếu đầu vào được nén . Đối với ví dụ về các số nguyên tố Mersenne, chúng ta đã thấy ba bảng mã, mỗi mã được nén theo logarit hơn so với tiền thân của nó.
Năm 1983, Hana Galperin và Avi Wigderson đã viết một bài báo thú vị về sự phức tạp của các thuật toán đồ thị phổ biến khi mã hóa đầu vào của đồ thị được nén theo logarit. Đối với những đầu vào này, ngôn ngữ của đồ thị chứa một hình tam giác từ phía trên (nơi rõ ràng là P ) đột nhiên trở thành NP -complete.
Và đó là vì các lớp ngôn ngữ như P và NP được xác định cho các ngôn ngữ , không phải cho các vấn đề .