האלכסון – אסון

בפוסט הקודם דיברתי על שיטת האלכסון של קנטור, שבאמצעותה מוכיחים כי המספרים הממשיים אינם בני מניה, וכעת אגש בלי שהיות להוכחה עצמה. כדי לפשט את העניינים לא אוכיח את הטענה על המספרים הממשיים, אלא על תת קבוצה שלהם; בוודאי שאם תת קבוצה של קבוצת הממשיים אינה בת מניה, גם היא עצמה אינה בת מניה (קל להראות התאמה חח"ע מתת הקבוצה לקבוצה שמכילה אותה; נסו למלא את הפרטים). הקבוצה שאבחר היא קבוצת כל המספרים הממשיים שהפיתוח העשרוני שלהם הוא מהצורה \(0.a_1a_2a_3\dots\), כאשר \(a_k\), לכל \(k\) טבעי, הוא או הספרה 0 או הספרה 1.

למה להגביל את עצמי לספרות 0 ו-1? כדי להימנע לחלוטין מכל סכנה של גלישה לשאלות של ייצוג. לפיתוח עשרוני (וגם בשאר בסיסי הספירה) התכונה ה"מוזרה" שקיימים מספרים שניתן לכתוב בשתי דרכים שונות – המקרה המפורסם ביותר הוא זה של \(1\) ו-\(0.999\dots\), שראוי לפוסט משל עצמו. הימנעות משימוש בספרה 9 מונעת כל בלבול שכזה.

כדי לעשות חיים עוד יותר קלים, אפסיק לדבר על פיתוח עשרוני ואדבר על סדרות; כל איבר בקבוצה שאני עוסק בה הוא בעצם סדרה אינסופית של ספרות שהן 0 או 1 – הסדרה \(a_1,a_2,a_3,\dots\). מספיק להראות כי מספר הסדרות הללו אינו בן מניה.

ההוכחה היא כדלהלן. נניח בשלילה שמספר הסדרות הוא דווקא כן בן מניה, אז קיימת התאמה חח"ע ועל בין הסדרות למספרים הטבעיים – כלומר, לכל סדרה אפשר להתאים באופן חח"ע מספר טבעי. אם כן, אפשר לסדר את הסדרות במעין טבלה, שבכל שורה יש סדרה: בשורה מספר 3 תהיה סדרה מספר שלוש, וכן הלאה. כל עמודה בטבלה תייצג איבר בסדרה: בעמודה 2 יהיה האיבר השני בסדרה, וכן הלאה.

כעת מגיע הטוויסט. אנו מסתכלים באלכסון של הטבלה הזו – כלומר, באיבר הראשון בסדרה הראשונה, באיבר השני בסדרה השניה, וכן הלאה. האלכסון הזה הוא בעצמו סדרה אינסופית. כעת ניקח את הסדרה ה"הפוכה" לאלכסון – כלומר, אם האיבר הראשון באלכסון היה 1, האיבר הראשון בסדרה ההפוכה יהיה 0, וכן הלאה.

מה קיבלנו? עוד סדרה אינסופית של אפסים ואחדים. כלומר, היא איבר בקבוצה שלנו, ולכן הותאם לה מספר טבעי כלשהו, ולכן היא מופיעה בטבלה במקום כלשהו. אבל היכן?

לא ייתכן שהיא תופיע במקום הראשון; הרי הספרה הראשונה בה בבירור שונה מהספרה הראשונה של הסדרה שבמקום הראשון (כי הספרה הזו הופיעה באלכסון, ולקחנו את "ההפך" שלה). ומה באשר למקום השני? הפעם אין בעיה עם הספרה הראשונה בסדרה שלנו, אבל יש בעיה עם הספרה השניה – הרי הספרה השניה בסדרה השניה נמצאת באלכסון, ולכן היא שונה מזו שסדרה שלנו. וכן הלאה וכן הלאה. לא משנה באיזו שורה נבחר – תהיה בה עמודה שנכנסה לאלכסון, ולכן הסדרה שלנו שונה מהסדרה שבאותה שורה בעמודה הזו. האלכסון מוודא שהסדרה שלנו תהיה שונה מכל סדרה שמופיעה בטבלה. המסקנה? הסדרה שלנו לא מופיעה בטבלה. סתירה.

(בכיוון האחר, ברור שלכל מספר טבעי אפשר להתאים סדרה כלשהי של 0 ו-1: המספר כשהוא מוצג בבסיס בינארי).

כאמור בפוסט הקודם, קנטור עצמו השתמש בהוכחה הזו כדי לתת דוגמה לשימוש במשפט אחר שלו – משפט שעוסק במספרים טרנסצנדנטיים (מושג שהזכרתי באחד הפוסטים הישנים שלי, על בניית המספרים). כדי להסביר מהו מספר טרנסצנדנטי קל יותר להסביר מהו מספר אלגברי: מספר אלגברי הוא מספר שהוא פתרון של משוואה פולינומית שמקדמיה רציונליים. למשל, שורש 2 הוא הפתרון של המשוואה \(x^2-2=0\). מספר טרנסצנדנטי הוא מספר ממשי שאינו אלגברי. שני המספרים הטרנסצנדנטיים הידועים ביותר הם הקבועים \(e\) ו-\(\pi\), אבל ההוכחה לטרנסצנדנטיות שלהם אינה פשוטה (של \(e\) קלה יותר מאשר של \(\pi\), אך בשני המקרים ההוכחה מסובכת יחסית). יש מספרים אחרים, שקל יותר להוכיח את הטרנסצנדנטיות שלהם, והמתמטיקאי ז'וזף ליוביל הציג כאלו (שנבנו במיוחד בשביל להראות את קיומם של מספרים טרנסצנדטיים) -"מספרי ליוביל". בכל המקרים הללו נדרשת כמות לא מועטה של עבודה.

והנה, ההוכחה של קנטור מראה כמעט מייד שרוב המספרים הממשיים הם טרנסצנדנטיים! זוהי ה"דוגמה" המובטחת, והיא נובעת מכך שקנטור הוכיח באותו מאמר שבו הופיעה שיטת האלכסון גם שישנו רק מספר בן מניה של מספרים אלגבריים. הסיבה לכך, בנפנוף ידיים מהיר, היא שכל מספר אלגברי מוגדר באמצעות משוואה אחת לפחות, וכל משוואה מוגדרת באופן מוחלט באמצעות מקדמיה – כך שיש התאמה חח"ע ועל בין סדרות סופיות של רציונליים ובין המשוואות שמגדירות מספרים אלגבריים. עוד צריך להראות שיש מספר בן מניה של סדרות סופיות שאבריהן בני מניה, ויש עוד נקודות עדינות להתייחס אליהן, אבל נראה לי שהרעיון ברור.

אם כן, יש רק מספר בן מניה של מספרים אלגבריים, ויש מספר לא בן מניה של מספרים ממשיים – ולכן יש מספר לא בן מניה של מספרים טרנסצנדנטיים. עד כדי כך פשוט.

אבל כעת חוזרת אלינו הטענה המקורית שלי, לפיה את רוב המספרים הממשיים אי אפשר לחשב, וכעת ההוכחה היא טריוויאלית: יש מספר לא בן מניה של ממשיים, אבל רק מספר בן מניה של תוכניות מחשב בשפה ++C. גמרנו.

נשאר רק להבין למה יש רק מספר בן מניה של תוכניות מחשב שכאלו. ובכן, כל תוכנית היא רצף של תווי ASCII. יש מספר סופי של תווים כאלו (מצדי שיהיה אפילו בן מניה). על כל תוכנית מחשב אפשר לחשוב בתור סדרה של תווים. לפני שניה טענתי (בנפנוף ידיים, אני מודה – אבל ההוכחה הטכנית אינה מסובכת) שיש רק מספר בן מניה של סדרות סופיות שאבריהן שייכים לקבוצה בת מניה. זהו. דרך אחרת לחשוב על זה שמתבססת על סופיות קבוצת תווי ה-ASCII היא לחשוב על תוכנית מחשב כעל מספר בייצוג בבסיס שגודלו כגודל קבוצת תווי ה-ASCII הקיימים; התו הראשון בתוכנית הוא ספרת ה"אחדות", התו השני הוא ספרת ה"עשרות", וכן הלאה. כך מתאימים באופן חח"ע ועל מספר לכל תוכנית.

כך, בצורה אגבית למדי, ראינו שקיימים דברים שלעולם לא נוכל לחשב. הטענה הזו נשמעת נחרצת למדי – בסך הכל דיברתי על תוכניות בשפת ++C, אולי בשפה חזקה יותר (Ruby!) כן אפשר לחשב? אבל כפי שכבר אמרתי קודם, ++C היא מה שמכונה Turing Complete; לא משנה באיזה מחשב (אפילו קוואנטי) ובאיזה שפת תכנות נבחר – ניתן יהיה לכתוב תוכנית ++C שעושה את אותו הדבר בדיוק.

לטעמי ההוכחה הזו היא עלובה ולא מספקת. היא אמנם אומרת שיש המון מספרים קשים לחישוב, אבל לא אומרת כלום על מה הם. זו הוכחה לא קונסטרוקטיבית "מעצבנת", כי היא מוכיחה אי היתכנות; מצד אחד היא חורצת לשון ואומרת "אי אפשר ואי אפשר!" ומצד שני לא אומרת מה אי אפשר. אני מעדיף הוכחות שאומרות "אפשר" ולא מראות איך.

זו כנראה הסיבה שבגללה מעדיפים להציג בכל דיון במגבלות יכולתו של המחשב את "בעיית העצירה" המפורסמת, שמצביעה על חוסר יכולת מאוד קונקרטי ומרכזי של המחשב, ומהווה בסיס להוכחת אי היכולת לפתור המוני בעיות קונקרטיות אחרות. אני מקווה להרחיב בנושא באחד מהפוסטים הבאים.

הגודל כן קובע

בפוסט הקודם הפרדנו את כל הקבוצות בעולם לשני סוגים: אלו שאפשר לתת לגודל שלהן משמעות בתור מספר טבעי ("קבוצות סופיות"), ואלו ששמות ללעג את ההגדרה שלנו ("קבוצות אינסופיות"). כאן נכנס לתמונה קנטור ומציע דרך טובה יותר למדוד עוצמה של קבוצה.

חשוב להדגיש שקנטור לא קם יום אחד בבוקר ואמר "אה, איזה כיף! בואו נתעסק בגודל של קבוצות אינסופיות!". הוא עסק במתמטיקה ה"קלאסית" שבה התעניין העולם המתמטי בתקופתו (וגם הגיע בה להישגים נאים), והצורך להגדיר את מושג הגודל הזה יותר במדוייק הגיע מתוך העיסוק הזה. איני חושב שקנטור ראה את עצמו כמחולל מהפכות, לפחות לא בזמן שבו פיתח את תורתו. מיותר לציין שמה שאני הולך לכתוב הוא לא בדיוק מה שקנטור אמר, ובפרט לא ייצוג כרונולוגי של התפתחות רעיונותיו.

הרעיון של קנטור הוא למעשה פשוט למדי, ואמחיש אותו באמצעות דוגמה מקובלת. נניח שישנו אצטדיון כדורגל בן 30,000 מושבים, והוא מלא באנשים. אני רוצה לדעת האם תפוסת האצטדיון מלאה – כלומר, האם הוא מכיל 30,000 אנשים. דרך אחת לעשות זאת היא להשתמש בשיטת הספירה שתיארתי בפוסט הקודם – לעבור אדם אדם, להוריד אותו מקבוצת "האנשים שטרם נספרו" ולהגדיל את המונה ב-1. זו שיטה איטית ומסורבלת להחריד.

השיטה השניה היא לצוות ברמקול על כל האנשים לשבת. בהנחה (הלא סבירה, אבל מילא) שהם יצייתו ושאין בקהל אנשים שתופסים שני מושבים ויותר, אני אוכל לגלות בשניות האם יש באצטדיון 30,000 אנשים, וגם אם יש יותר או פחות: אם אני רואה מושבים ריקים, יש פחות מ-30,000 איש; אם אני רואה שכמה אנשים ממשיכים לעמוד, יש יותר מ-30,000 איש; ואם לא קורה לא זה ולא זה, אז יש בדיוק 30,000 איש באצטדיון.

מה עשיתי כאן? לקחתי קבוצה שאת גודלה אני כבר יודע, וביצעתי התאמה בינה ובין הקבוצה שאת גודלה אני רוצה למדוד. בלשון מתמטית פורמלית, התאמה בין שתי קבוצות A ו-B היא פונקציה מ-A ל-B (או מ-B ל-A) שהיא חד חד ערכית (חח"ע) ועל. אפרש את כל המושגים הללו:

כשאני אומר "פונקציה מ-A ל-B" הכוונה היא למעין "מכונה" שלכל איבר מ-A מתאימה איבר אחד ויחיד מ-B. כלומר, אם a הוא איבר כלשהו של A ואני אזין אותו למכונה הזו, אני אקבל פלט של "b" כלשהו, כאשר b הוא איבר של B. מה שחשוב כאן הוא שלכל a יוחזר לי איזה שהוא b, ושה-b הזה יהיה יחיד (כלומר, לא יוחזרו שני איברים של B או יותר). במילים אחרות – שכל אדם באצטדיון (איבר ב-A) יבחר לעצמו כיסא אחד ויחיד באצטדיון (איבר ב-B) לשבת עליו.
כשאני אומר "חד חד ערכית" הכוונה היא שלא ייתכן שהפונקציה תתאים לשני איברים של A את אותו האיבר ב-B. כלומר – לא נוצר מצב שבו שני אנשים מנסים לשבת על אותו הכיסא באצטדיון.

כשאני אומר "על" הכוונה היא שכל איבר ב-B מותאם לאיבר כלשהו ב-A. כלומר – שכל כיסא באצטדיון נבחר על ידי אדם אחד לפחות.

זה תרגיל לא מסובך במיוחד להראות שאם קיימת פונקציה חח"ע מ-A אל B, אז קיימת פונקציה על מ-B אל A, ושאם יש פונקציה על מ-A אל B, אז קיימת פונקציה חח"ע מ-B אל A. נסו להוכיח זאת! (יש להשתמש הן בתכונה שמתקיימת – חח"ע או על – והן בתכונות המגדירות פונקציה). מכאן עולה שאפשר לדבר על "התאמה חח"ע ועל בין שתי קבוצות, בלי לציין מאיפה לאיפה. עוד תוצאה חשובה, הרבה פחות פשוטה להוכחה באופן כללי, היא שאם יש פונקציה חח"ע מ-A אל B, ופונקציה חח"ע מ-B אל A, אז קיימת התאמה חח"ע ועל בין A ו-B. התוצאה הזו מכונה משפט קנטור-שרדר-ברנשטיין.
אם קיימת התאמה חח"ע ועל בין שתי קבוצות (במקרה כזה אומרים שהן שקולות), אז אפשר לסדר את האיברים שלהן זוגות זוגות, כשבכל זוג יש איבר אחד מ-A ואיבר אחד מ-B. בבירור הדבר גורר ששתי הקבוצות הן מאותו הגודל כאשר הן סופיות; אנו בוחרים להגדיר כך שוויון עוצמות בין קבוצות אינסופיות. כאן נפרד מושג ה"עוצמה" ממושג ה"גודל" האינטואיטיבי; אתם כקוראים אינכם חייבים לקבל את ההגדרה שלי בתור "גודל". מה שלא תוכלו לעשות, גם אם אינכם מקבלים את ההגדרה, הוא להתעלם מתוצאותיה המתמטיות – למשל, שיש מספרים ממשיים שאף תוכנת מחשב בשפת ++C לא תוכל לחשב.

כדי להבין מדוע עשויים להיות קשיים בקבלת ההגדרה הזו של עוצמה, יש לשים לב להשלכות המיידיות שלה. אחת מהן היא מה שמכונה "הפרדוקס של גלילאו" (על שם גלילאו, ששם לב אליו הרבה לפני קנטור), והוא הולך בערך כך:

לכל מספר טבעי אפשר להתאים את הריבוע שלו (ל-1 מתאימים את 1, ל-2 מתאימים את 4, ל-3 את 9 וכן הלאה). ההתאמה הזו היא בבירור פונקציה, היא בבירור חד חד ערכית (כי לשני מספרים טבעיים שונים יש ריבועים שונים) והיא גם בבירור על קבוצת המספרים שיש להם שורש שלם (1,4,9,16,25 וכן הלאה). אם כן, מההגדרה של קנטור עולה שעוצמת קבוצת המספרים הטבעיים זהה לעוצמת קבוצת הריבועים.

אבל זה נראה מופרך; הרי הקבוצה של כל הריבועים היא קבוצה חלקית לקבוצת כל המספרים הטבעיים, ובפרט קיימים מספרים טבעיים רבים שאינם ריבועים! (2, 3, 5, 6, 7, 8, 10, וכן הלאה).
ואכן, ה"פרדוקס" הזה הוא פשוט התוצאה הלא אינטואיטיבית והבלתי נמנעת של השימוש בעוצמות. למעשה, אחת מההגדרות המקובלות ל"קבוצה אינסופית" היא "קבוצה ששקולה לתת קבוצה ממש של עצמה" (ה"ממש" פירושו כאן "לא שווה", שכן מבחינה פורמלית קבוצה היא תמיד גם תת קבוצה של עצמה, וגם קבוצות סופיות שקולות לעצמן, כמובן).

אבל התוצאות הלא אינטואיטיביות לא נגמרות כאן. כעת נכנסת לתמונה אחת התוצאות המבריקות של קנטור: הוא הוכיח שהמספרים הרציונליים שקולים למספרים הטבעיים – כלומר, יש להם את אותה העוצמה. זה כבר עובר מה"מוזר" אל ה"נשמע על פניו מופרך לחלוטין", שכן יש אינסוף מספרים רציונליים בין כל שני מספרים טבעיים – איך ייתכן שתהיה להם אותה הכמות?

הצעד הראשון בהוכחה הוא לזכור כיצד בנינו את המספרים הרציונליים מלכתחילה – בתור זוגות של מספרים שלמים. גם המספרים השלמים נבנו במקור בתור זוגות, במקרה הזה של מספרים טבעיים, ולכן מספיק יהיה להראות התאמה בין המספרים הטבעיים לבין זוגות של מספרים טבעיים – את שאר הפרטים תוכלו לנסות ולהשלים בעצמכם.

למרות שיש דרך פשוטה יותר לעשות זאת (באמצעות משפט קנטור-שרדר-ברנשטיין), אני אראה את ההתאמה הזו בצורה ישירה – כך יותר קל "להאמין" לה. באופן ציורי הרעיון הוא כזה: אפשר לחשוב על זוגות הטבעיים כאילו הם מסודרים בטבלה – כך למשל הזוג (3,4) יהיה בשורה השלישית של הטבלה ובעמודה הרביעית שלה (אני מדמיין את הטבלה כאילו התא השמאלי העליון שלה הוא (0,0) – כמו באקסל באנגלית). אנחנו רוצים להתאים לכל תא בטבלה מספר טבעי באופן שיהיה חח"ע ועל. מה שנעשה יהיה למספר את אברי הטבלה באופן סדרתי: ניתן לתא כלשהו את המספר 1, לתא אחריו את המספר 2, לתא אחריו את 3 וכן הלאה וכן הלאה. ברור כי זוהי פונקציה וברור כי היא חח"ע – נצטרך רק למצוא דרך לעבור סדרתית על כל התאים כדי להבטיח שהיא תהיה על.

הבעיה היא שכל שורה היא אינסופית, וכל עמודה היא אינסופית. לכן, אם ננסה למספר קודם כל את כל האיברים שבשורה מס' 1, לעולם לא נגיע לשורה מס' 2. לכן צריך למצוא דרך אחרת.

הרעיון הוא לעבור על התאים באלכסון. למרות שהטבלה אינסופית, כל האלכסונים בה שמתחילים בשורה העליונה וממשיכים למטה ולכיוון שמאל הם סופיים באורכם – ואם עוברים על כל האלכסונים, עוברים על כל התאים בטבלה בצורה כזו שמבטיחה שנגיע לכל תא בטבלה אחרי פרק זמן סופי.

כך לתא (1,1) נתאים את המספר 1, לתא (1,2) את המספר 2, לתא (2,1) את המספר 3, לתא (1,3) את המספר 4, לתאר (2,2) את המספר 5 וכן הלאה וכן הלאה. יש כאן קצת עבודה פורמלית של הגדרה והוכחה (הנקודה המרכזית לשים אליה לב היא שמסדרים את הקוארדינטות בסדר כפול; ראשית, על פי סכום הקוארדינטות שלהם, ולאחר מכן, בין כל הקוארדינטות שסכומן זהה, על פי הסדר הלקסיקוגרפי הרגיל) , אולם ההתאמה הזו עובדת, ועובדת מצויין.
משהוכחנו את התוצאה הלא אינטואיטיבית הזו, הדחף הראשון (שלי לפחות) הוא לחשוד שכל הקבוצות האינסופיות שקולות לטבעיים. אלא שקנטור הוכיח בשנת 1873 שזה לא נכון, והקבוצה שבה השתמש הייתה קבוצת המספרים הממשיים. קנטור הכיר את הקבוצה הזו היטב – אחת מההגדרות הפורמליות למספרים ממשיים, שפורסמה שנה אחת לפני כן, הייתה שלו (ההגדרה שהתבססה על סדרות קושי).

ההוכחה שהמספרים הממשיים לא שקולים לטבעיים – כלומר, שיש "הרבה יותר" ממשיים מאשר טבעיים, מכונה "האלכסון של קנטור", והיא כנראה אחת מההוכחות המפורסמות במתמטיקה (וזאת למרות שקנטור השתמש בה רק בתור דוגמה לתוצאות של טענה אחרת שלו). קנטור עצמו הכליל אותה למשפט כללי וחזק הרבה יותר, ועם זאת עדיין יש בשיטת האלכסון עניין – הן בגלל היופי שלה שבא לידי ביטוי דווקא בגלל המקרה הספציפי שאותו היא מתארת, והן בגלל שטכניקות דומות מאוד לה נמצאות בשימוש גם היום – בפרט, במדעי המחשב התיאורטיים. בפוסט הבא אעסוק בה.

איזה גודל (?)

בפוסטים קודמים דיברתי על כך שאת "רוב" המספרים הממשיים "אי אפשר לחשב", ואולי גם הבטחתי הוכחה "פשוטה" לכך. בפוסטים הבאים אני אנסה להגשים את ההבטחה הזו, ולצורך כך אני צריך לחסל את המרכאות – להסביר מהו "רוב", להגדיר מה זה "לחשב" (ולכן, גם מה זה "אי אפשר לחשב"), ולהראות הוכחה שהיא באמת פשוטה.

בכל הנוגע לחישוב ארמה קצת ואציג הגדרה לא פורמלית – משהו שניתן לחשב הוא משהו שניתן לכתוב תוכנית מחשב בשפת ++C שמחשבת אותו (כלומר – רצה בלי לקבל קלט ובסוף מוציאה אותו כפלט). מכיוון שכל מה שתוכניות מחשב עושות מוציאות כפלט הם רצפים של אפסים ואחדים (לרוב כשהם מוצגים בדרך נוחה יותר לקריאה) אני מראש מגביל את "מה אפשר לחשב" לכל מה שאפשר לקודד אותו בצורה הזו.

למרות שההגבלות הללו נראות שרירותיות, למעשה הן שקולות להגדרות הפורמליות ביותר של "חישוב". הסיבה שבחרתי ב-++C ולא, נניח ב-Ruby שאותה אני אוהב הרבה יותר, היא בגלל האנקדוטה שמנגנון ה-Templates של ++C לבדו מאפשר ביצוע חישובים כבר בזמן קומפילציה שהם מה שמכונה Turing Complete – כלומר, מסוגלים לבצע סימולציה לכל מודל חישובי אחר (ובפרט, להיכנס ללולאה אינסופית ולתקוע את הקומפיילר). כפי שנראה בהמשך, בחירת השפה לא משנה כלום, וכדי להבין את מה שאעשה בהמשך בכלל לא צריך להכיר שפות תכנות; אבל צריך לבחור שפה כלשהי ולדבוק בה.

אם כן, נעבור למושג הקשה הרבה יותר להגדרה, מושג ה"גודל". לפני כן חשוב להחליט את הגודל של מה אנחנו רוצים למדוד – ובמקרה שלנו, אלו יהיו קבוצות.

"קבוצה" היא ככל הנראה המושג הבסיסי ביותר במתמטיקה המודרנית. תורת הקבוצות היא הבסיס שבאמצעותו מתוארת רוב (כל?) המתמטיקה – אפילו הלוגיקה המתמטית (שיותר משהיא מהווה בעצמה בסיס למתמטיקה, היא משמשת ככלי לביצוע חקירה מתמטית של המתמטיקה עצמה) משתמשת בקבוצות. לכן, לפחות לכאורה, אין לצפות להגדרה מתמטית מדוייקת של המושג, שמבוססת על מושגים קיימים, אלא להגדרה אינטואיטיבית שמבוססת על שפה טבעית.

אם כן, הגדרה נאיבית לקבוצה היא כדלהלן: קבוצה היא חלוקה של כל העצמים שניתן לחשוב עליהם ל"עצמים ששייכים לקבוצה", ו"עצמים שלא שייכים לקבוצה", כך שלכל עצם מתקיימת אחת (ורק אחת) מבין האפשרויות. "עצמים" יכול להיות כל דבר: המספר 7, החתול שמיל, קבוצות אחרות, וכדומה. בפרט, חלוקה אפשרית אחת היא "כל העצמים לא שייכים לקבוצה", ואז הקבוצה שמתקבלת מכונה "הקבוצה הריקה".

למרות שמבחינת המתמטיקאי המושגים הללו פשוטים מאוד, השימוש בשפה הטבעית יכול להטעות ולגרום לבלבולים. ניהלתי פעם דיון עם ברנש חכם (לא בסרקזם) שטען שאין כזה דבר, קבוצה ריקה, שכן קבוצה היא אוסף של איברים ולכן אין משמעות לאוסף שלא מכיל אף איבר. באותה הרוח, הוא טען שקבוצה של איבר אחד היא אותו דבר כמו האיבר עצמו (כלומר, אין "קבוצה שמכילה את החתול שמיל", אלא רק "החתול שמיל"). הבעיה כאן היא שבן שיחי הורגל למושג היומיומי של "קבוצה" וסירב לקבל מתן משמעות אחרת, רחבה קצת יותר, למילה הזו. לכן חשוב להבין שזה מה שהמתמטיקה עושה לפעמים – נותנת שמות אינטואיטיביים (שלרוב מסייעים במשהו להבנה, אך לא תמיד) למושגים שמשמעותם האמיתית מעט שונה ומורכבת יותר. כך, למשל, ניתן למצוא במתמטיקה "אידאלים", במובן הרבה יותר קונקרטי.

ההגדרה הנאיבית שנתתי מובילה בסופו של דבר לבעיות ופרדוקסים (הידוע שבהם הוא "הפרדוקס של ראסל", אבל יש עוד), ולכן מבחינה מעשית לא משתמשים בה. במקום זה מפתחים את מה שמכונה "תורת הקבוצות האקסיומטית", שמגבילה במשהו את מושג הקבוצה. עם זאת, לרוב הקבוצות שמתמטיקאים משתמשים בהן (וגם אלו שעליהן אדבר) מתאימות בכל מקרה למושגים של תורת הקבוצות האקסיומטית, ולכן ההגדרה שנתתי קודם היא טובה מספיק לצרכינו (כשם שהמכניקה הניוטונית מספיקה לרבים מצרכי היום-יום למרות שהיא אינה ממש נכונה, ויש להשתמש במקומה בתורת היחסות הפרטית).

אם כן, הגענו להגדרת גודל הקבוצה. כמקודם, גם למילה "גודל" ניתן לייחס משמעויות רבות. אני אדבר מכאן ואילך על משמעות ספציפית אחת, שמכונה "עוצמה" (Cardinality), ואנסה לשכנע אתכם שזו משמעות מעניינת. בבסיסה, המשמעות הזו מנסה לתפוס את המושג האינטואיטיבי של "כמות איברים".

כיצד נמדוד את כמות האיברים של קבוצה? כשיש לנו קבוצה בחיי היום יום, אנחנו מודדים את כמות האיברים בה על ידי התאמת מספר טבעי כלשהו אליה: "יש בחנות החרסינה שלושה פילים", "יש בכיתה הזו אפס אנשים חכמים" וכדומה. זה אולי השימוש הקדום ביותר של המספרים הטבעיים – מדידת כמות.

כיצד נבצע את ההתאמה הזו בפועל? אפשר "לספור" כמו שעושים בחיי היום יום: להתחיל מכך שגודל הקבוצה הוא 0, לסלק ממנה איבר אחד, להגדיל את גודל הקבוצה ל-1, לסלק עוד איבר ולהגדיל ל-2 וכן הלאה, עד שהקבוצה מתרוקנת. לא קשה לראות שבעצם מסתתרת כאן הגדרה אינדוקטיבית:

  1. עוצמת הקבוצה הריקה היא 0.
  2. אם X היא קבוצה לא ריקה, עוצמתה היא כעוצמת X לאחר שהוסר ממנה איבר כלשהו באופן שרירותי, ועוד 1.

כך קבוצות בעלות איבר בודד יהיו מעוצמה 1 (כי אחרי שמוסר האיבר הזה קיבלנו את הקבוצה הריקה) וכן הלאה.

הבעיה מתחילה כשאנו נתקלים בקבוצות שמסרבות להיכנע להגדרה הזו. ניקח כדוגמה את קבוצת כל המספרים הטבעיים: לא משנה כמה פעמים נחזור על תהליך ההסרה של איבר, אף פעם לא נגיע לבסיס האינדוקציה (לקבוצה ריקה), שכן כדי לסלק את כל המספרים הטבעים נצטרך להסיר… זהו, אי אפשר לחמוק יותר מהמילה הזו – אינסוף איברים.

במילים אחרות, ההגדרה שסיפקתי היא בעלת ערך רק עבור קבוצות בעלות מספר סופי של איברים – כלומר, קבוצות שבאמת ניתן להתאים להן מספר טבעי שמייצג את עוצמתן. שאר הקבוצות הן יצורים משונים ומפחידים, שלא ברור מה המשמעות של "העוצמה" שלהן, ולכן אנחנו ממלמלים משהו על כך שהן "אינסופיות", לא מנסים להבין את פשר הגודל שלהן, ובכלל מעדיפים להתעסק איתן כמה שפחות. זה לפחות היה המצב במתמטיקה של המאה ה-19; המתמטיקאים עמלו קשות כדי לסלק את מושג האינסוף מהמתמטיקה, ובפרט מהחשבון האינפיניטסימלי. לאחר עבודה כבירה עלה הדבר בידם – הם החליפו את האינסוף במושג של "שאיפה לאינסוף" שהשתמש רק בגדלים סופיים, והעדיפו להתעלם כמה שניתן מהמקומות האחרים שבהם האינסוף יכול לצוץ.

ואז בא מתמטיקאי אחד ולא רק שהחזיר את האינסוף למרכז הזירה, הוא גם גילה מהן התכונות המאפיינות אותו, ובפרט את התגלית הכבירה, הבלתי נתפסת כמעט – שיש גדלים רבים (אינסוף, למעשה) של אינסוף.

למתמטיקאי הזה קראו גאורג קנטור, ועל הגישה שלו למושג האינסוף אנסה להרחיב בפוסט הבא.

צ’ומפ צ’ומפ

בתגובה לאחד מהפוסטים הקודמים הזכיר לי אלון עמית את אחת הדוגמאות האלגנטיות והיפות ביותר שאני מכיר להוכחה לא קונסטרוקטיבית, ואני סבור שהיא מתאימה מאוד לסיום העיסוק בהוכחות לא קונסטרוקטיביות (לפחות לעת עתה). כוכב הדוגמה הוא משחק מטופש ותמים ביותר בשם Chomp.

המשחק הולך כך: לוח המשחק הוא מלבן הבנוי מריבועים (ממדי המלבן יכולים להשתנות ממשחק למשחק – זה מה שלכאורה מוסיף אתגר). ישנם שני שחקנים המשחקים לסירוגין. בכל סיבוב אחד השחקנים בוחר אחת מהמשבצות, ומסיר מהלוח אותה ואת כל המשבצות שנמצאות במלבן שהיא הפינה השמאלית התחתונה שלו – במילים אחרות, כל משבצת שנמצאת לימינה או מעליה.

המשבצת השמאלית התחתונה ביותר בלוח היא "מורעלת" – מי שלוקח אותה, הפסיד. לכן, מטרת המשחק היא לגרום ליריב לקחת אותה. בכך המשחק מזכיר מעט את המשחק "נים", שגם בו המטרה היא לא להיות זה שלוקח את האובייקט האחרון.

צ’ומפ
מה שהופך את המשחק הזה למעניין היא העובדה שאפשר להוכיח (בצורה פשוטה ביותר) שהשחקן שפותח תמיד יכול לנצח במשחק (בכל לוח, ובלי תלות בשאלה מה עושה השחקן השני), אבל ההוכחה הזו אינה קונסטרוקטיבית; היא אינה מצביעה כלל על הדרך שבה השחקן הזה צריך לשחק כדי לנצח.

ההוכחה עצמה היא טריוויאלית, אבל היא מתבססת על משפט ידוע ומוכר מתורת המשחקים – משפט צרמלו. המשפט מוצג במספר וריאציות (שכולן די שונות מהנוסח המקורי של צרמלו עצמו), ואציג כאן אחת מהפשוטות שבהן, אשר ממנה נובע שב-Chomp אחד משני השחקנים בהכרח מסוגל לנצח בלי תלות במה שעושה היריב.

לפני כן כדאי לומר מילה או שתיים על המושג המתמטי של "משחק". בהגדרה מקושקשת משהו אפשר לומר ש"משחק" הוא כל סיטואציה בה משתתף אחד או יותר נוקט בסדרה של החלטות כדי להגיע לתוצאה שהיא אופטימלית בעיניו. מילת המפתח כאן היא "החלטה" – אם אין החלטות, המשחק די חסר טעם.

משחקים לשחקן יחיד לא חסרים, ושלוש הדוגמאות המוכרות של ימינו, באדיבותה של חברת מיקרוסופט, הן סוליטייר, פריסל ושולה המוקשים. עם זאת, העניין האמיתי מתעורר כאשר יש שני שחקנים או יותר – במצב זה, השחקן אינו תלוי רק בעצמו כדי לקבוע את תוצאת המשחק; הוא צריך להביא בחשבון גם את מה שהשחקנים האחרים יעשו.

כאשר רוצים לתאר משחק בצורה מתמטית, ישנן מספר דרכים לעשות זאת. גישה אחת, שנכנסת אל תוך המכניקות הפנימיות של המשחק, מתארת אותו בתור עץ מכוון שכל צומת בו מייצג סיטואציה אפשרית כלשהי במשחק (למשל, השורש שלו מייצג את המצב ההתחלתי של המשחק, והעלים את סוף המשחק) ויש קשת מצומת אחד לצומת שני אם בחירות השחקנים במצב שמגולם באב יכולות להוביל למצב שמגולם בבן (יש לשים לב כי גם לאותו מצב בלוח עשויים להיות כמה וכמה צמתים שונים בעץ, שכן צומת בעץ מייצג לא רק את המצב אלא גם את הדרך שבה הגענו אליו).

באמצעות דרך הייצוג הזו קל להוכיח את הגרסה שלנו של משפט צרמלו, שגורסת כי במשחק סופי (כזה שתמיד נגמר) לשני שחקנים שמשחקים לסירוגין, עם ידיעה גמורה, שבו התוצאות האפשריות היחידות הן ניצחון לאחד משני השחקנים (נקרא להם מעכשיו "הלבן" ו"השחור", כמו בשחמט, כדי לפשט, כאשר "הלבן" הוא זה שמתחיל), בהכרח אחד מהשחקנים מסוגל לכפות ניצחון בלי תלות במעשי השני.

המונח הבעייתי היחיד בניסוח המשפט הוא "ידיעה גמורה". משמעותו היא שבכל סיבוב השחקנים יודעים בדיוק היכן בעץ המשחק הם נמצאים, ואילו פעולות עליהם לנקוט כדי לעבור לצומת הבא. בפועל פירוש הדבר הוא שבמשחק אין מידע מוסתר (למשל, בטקטיקו מוסתרים מכל שחקן הכלים של השחקן השני, ובשולה המוקשים יש משבצות שלא ניתן לדעת את תוכנן וחייבים לנחש), ואין מימד של אקראיות (למשל, במונופול השחקנים מתקדמים על ידי הטלת קובייה). אפשר לסלק את האקראיות ולהישאר רק עם חוסר ודאות על ידי כך שחושבים על סדרת האקראיות כאילו כבר "נקבעה מראש" והיא פשוט לא ידועה, אך לא ניכנס לזה.

הדרך להוכיח שאחד משני השחקנים יכול לכפות ניצחון היא זו: ראשית, כל עלה בעץ מסמל ניצחון במשחק של אחד השחקנים (כי המשחק חייב להסתיים בניצחון). אם כן, נסמן ב-1 את העלים שמסמלים ניצחון של השחקן הלבן, וב-0 עלים שמסמלים ניצחון של השחור. כעת, באופן אינדוקטיבי, נסמן גם את שאר הצמתים בעץ במספרים: בהינתן צומת שמסמל סיטואציה במשחק בה תורו של השחקן הלבן, הסימון שבצומת יהיה פונקצית "או" של כל הבנים של הצומת (כלומר, 1 אם אחד מהם הוא 1, ו-0 אם כולם 0), ובהינתן צומת שמסמל את תורו של השחקן השחור, הפונקציה תהיה "וגם" (1 רק אם כולם 1, 0 אם אחד מהם 0).

בצורה הזו מסומן כל העץ, ובפרט השורש. אם השורש מסומן ב-1, הלבן יכול לכפות ניצחון. אם הוא מסומן ב-0, השחור יכול לכפות ניצחון.

למה? כי נניח שהשורש מסומן ב-1, וזה צומת שמסמל מהלך של הלבן (כי הלבן מתחיל). פירוש הדבר שלפחות אחד מבניו הוא 1. הוא יבחר במהלך במשחק שמביא אותו לבן הזה. עכשיו תור השחור. הוא בצומת שמסומן 1, ולכן כל בניו של הצומת הם 1, ולכן בלי קשר לשאלה מה יבחר לעשות השחקן השחור, הוא עדיין יגיע לצומת של 1. שוב תור השחקן הלבן, והוא שוב ימשיך לצומת שמסומן ב-1 וכן הלאה. האינוריאנטה נשמרת; המשחק תמיד נמצא בצומת שמסומן ב-1. מכיוון שהמשחק סופי, מתישהו יגיע הטיול בעץ לעלה, ובשל האינוריאנטה העלה יהיה מסומן ב-1 – כלומר, הלבן ניצח, בלי תלות במה שעשה השחור. החשיבות היחידה הייתה לבחירות שהלבן ביצע במהלך כל הטיול בעץ. לסדרה הכוללת של הבחירות שהיה עליו לבצע ("אם השחור ביצע את המהלך הזה, עשה כך וכך. אם השחור עשה דווקא את זה, אז עשה כך וכך וכך") קוראים אסטרטגיה.

אם השורש הוא 0, ההוכחה דומה; נסו לחשוב על הפרטים בעצמכם.

וכעת חזרה לצ'ומפ, כשאנחנו משוכנעים שאו הלבן יכול לכפות ניצחון, או השחור. אני רוצה להוכיח שבהכרח הלבן יכול לכפות ניצחון. ההוכחה היא כדלהלן:

נניח בשלילה שדווקא השחור יכול לכפות ניצחון, כלומר יש לו אסטרטגיה שמבטיחה ניצחון לכל פעולה של הלבן. בפרט, יש לו תגובה שתבטיח ניצחון למשחק של הלבן שבו הצעד הראשון הוא בחירת המשבצת הימנית העליונה בלוח.

כעת, אנחנו לא יודעים מה הצעד של השחור יהיה, ומה הוא המשך האסטרטגיה שלו, אבל אנחנו יודעים בודאות שהלבן יכול "לגנוב" אותם. איך? נניח לרגע שהמהלך של השחור מתחיל בבחירת המשבצת בקוארדינטה (2,3), ומכאן והלאה תגובה הולמת לכל מהלך של הלבן. אז הלבן יכול להתחיל את המשחק בכך שיבחר את הקוארדינטה (2,3), ומכאן והלאה יפעל על פי האסטרטגיה המנצחת של השחור.

מקור הכוח של הלבן הוא שבחירת הקוארדינטה (1,1) לא באמת משפיע על כלום. זה "מהלך סרק" – לא משנה איזה מהלך השחור יבצע כעת, הלוח בסיום המהלך הזה יהיה זהה ללוח שהלבן יכל להגיע אליו על ידי ביצוע אותו מהלך של השחור כבר בסיבוב הראשון.

אם, למשל, הלבן היה בוחר את (2,2) בסיבוב הראשון, התעלול לא היה פועל: השחור היה מסוגל לבחור משבצת כלשהי כך שהלוח אחרי בחירתה היה במצב שאליו הלבן לא מסוגל להגיע בסיבוב הראשון – נסו לחשוב על מהלך שכזה.

אם כן, הפרכנו את הטענה שלשחור יש אסטרטגיה מנצחת, ולכן על פי משפט צרמלו זהו הלבן שיש לו אסטרטגיה מנצחת, וגמרנו. רק מה? לא אמרנו שום דבר על מהי האסטרטגיה הזו – אפילו את המהלך הראשון שלה איננו יודעים. המשחק מכור מראש למרות שאין לנו מושג איך.

רק הערה כללית לסיום: משפט צרמלו שהוצג כאן תקף גם למשחקים עם תוצאת תיקו (ההכללה מיידית – תנו ערך 1 לניצחון של הלבן, 0 לתיקו ומינוס 1 לניצחון של השחור, ובחרו בצמתים פונקציות של "מקסימום" ללבן ו"מינימום" לשחור), ולכן תקף לשחמט ולדמקה. בכל הנוגע לשחמט, איש אינו יודע איזו מבין שלוש האפשרויות נכונה (האם הלבן יכול לכפות ניצחון, השחור יכול לכפות ניצחון, או כל אחד יכול לכפות תיקו) ומכיוון שעץ המשחק של שחמט הוא עצום בגודלו, גם לא סביר שפתרון יתגלה כל כך מהר, אבל דמקה כבר "פוצחה" בצורה הזו לא מזמן (או לפחות כך נטען) והוכח שכל שחקן בה מסוגל לכפות תיקו.

אני מודה שאיני יודע אם התגלית הזו משמחת או מדכאת אותי.

שורש, ההוכחה (חלק ב’)

פרוטוקול הוכחת אפס-הידע שאני עומד להציג נקרא "פרוטוקול פיאט-שמיר", על שם שני ממציאיו הישראליים – עמוס פיאט ועדי שמיר (את עדי שמיר הזכרתי כבר במובלע לפחות פעמיים בפוסטים קודמים – הוא זה שהוכיח שהוכחות אינטראקטיביות שקולות למחלקה PSPACE, והוא ה-S שבשמו של אלגוריתם ההצפנה RSA). המערכת שאני מציג הנה פרימיטיבית למדי, במונחים של ביצוע מעשי; לא אתעכב על הבעייתיות הטכנית שבה אלא רק אציין שהיא שופרה בידי אוריאל פייגה, שתיקן את הבעיה הטכנית ועשה עוד משהו נוסף, שגם אליו אתייחס בהמשך.

הבסיס של הוכחת אפס הידע הוא במספר גדול \(n\) שהוא מכפלה של שני מספרים ראשוניים גדולים. המושג "גדול" אינו מוגדר היטב, ותלוי בכוח החישוב הנוכחי של מחשבים, אבל בימינו פירוש הדבר מספר בן כמה מאות ספרות (400? 600?). הרעיון העקרוני שעומד מאחורי זה הוא שקל לייצג מספרים גדולים ולעבוד איתם (בניסוח נאיבי, צריך רק "400 בייטים" כדי לייצג מספר בן 400 ספרות, והרי בזכרונות המחשב של ימינו זוהי כמות זניחה ביותר. בפועל, צריך הרבה פחות מ-400 בייטים), אבל לא קשה לנסח בעיות שהקושי שלהן תלוי בגודל המספר (ערכו המספרי), ולא בגודל הייצוג שלו (מספר הבייטים שנדרשים לצורך כתיבתו). כדי להבין את ההבדל אעיר שמספר האטומים ביקום מוערך כמספר שאינו גדול מגוגול (\(10^{100}\), ובמילים אחרות – 1 עם מאה אפסים אחריו) וגוגול הוא יצור פיצי ומסכן לעומת מספר בן 400 ספרות.

הנה המחשה לבעייתיות שבדבר: בדיקת ראשוניות. הדרך שבה יוצרים את \(n\) היא על ידי הגרלה של שני ראשוניים גדולים (אם אנחנו רוצים ש-\(n\) יהיה בגודל 600 ספרות, נגריל ראשוניים בני 300 ספרות) והכפלתם (פעולה שכאמור – קל לבצע גם עבור מספרים גדולים שכאלו, בגלל שגודל הייצוג שלהם סביר). הבעיה היא רק כיצד להגריל שני ראשוניים דווקא, הרי ראשוניים הם לא מספרים נפוצים עד כדי כך.

דרך נאיבית היא פשוט להגריל מספרים גדולים שוב ושוב עד שיצאו ראשוניים ולקוות שזה יקרה מהר. אפשר לחשוב על כל מני אופטימיזציות טריוויאליות – למשל, להימנע מהגרלת מספריים זוגיים, אבל צוואר הבקבוק של האלגוריתם יהיה נעוץ בשאלה איך ניתן לדעת, בהינתן מספר שהגרלנו, האם הוא ראשוני או לא?

הדרך הסטנדרטית לבדיקת ראשוניות היא לעבור על כל המספרים הקטנים מהמספר שאנו בודקים ולבדוק האם הם מחלקים אותו (והמהדרין יגידו – כל המספרים הקטנים או שווים לשורש המספר שאנו בודקים). השיטה הזו, שהיא קלה מאוד לתכנות ונוחה לשימוש עבור מספרים קטנים, היא חסרת ערך עבור מספרים גדולים. גם אם המספר שלנו מיוצג עם 300 ספרות בלבד, הרי שלעבור על כל המספרים עד לשורש שלו ידרוש מאיתנו פרק זמן הגדול בהרבה מזה שחלף מאז המפץ הגדול. על כן נדרשות שיטות אחרות – וכאלו אכן יש, וייתכן שאציג אותן בעתיד.

אם כן, ייצרנו שני מספרים ראשוניים גדולים \(p,q\) כפלנו אותם וקיבלנו \(n=pq\). כעת זורקים את הראשוניים לכל הרוחות (אם מישהו ידע מה הם, הוא ידע את הפירוק של \(n\) ולכן יוכל להוציא שורש מודולו \(n\) והמערכת חסרת ערך) ומפרסמים את \(n\) לכל דורש. כעת המערכת מסוגלת להתחיל לתפקד.

אני, בתור המוכיח, רוצה להראות למערכת שאני מכיר שורש של מספר כלשהו. אם כן, אני בוחר באקראי מספר מודולו \(n\) שנכנה \(x\) (צריך לוודא גם שהוא זר ל-\(n\) כדי שיהיה איבר בחבורה הכפלית – אבל הסיכוי שניפול על איבר שאינו זר שווה לסיכוי שנצליח לפרק את \(n\) לגורמים "בטעות" – למה?), מעלה אותו בריבוע מודולו \(n\) ומקבל מספר חדש, \(y=x^2(mod n)\). מן הסתם אני צריך לבחור את \(x\) כך שהריבוע שלו יהיה גדול מ-\(n\), אחרת יהיה קל להוציא ל-\(x\) שורש (למה?)

אני מפרסם את \(y\) לכל דורש, ובפרט למערכת שרוצה לזהות אותי. יש כאן בעיה לוגיסטית כלשהי – צריך שהיא תשתכנע ש-\(y\) באמת מייצג אותי ולא איזה מתחזה, וזו יכולה להיות בעיה רצינית – אולם הפתרונות לבעיה הם לרוב לא קריפטוגרפיים, והבעיה עצמה אינה חמורה כל כך מכיוון שהיא "חד פעמית" – אחרי שפעם אחת אני "אירשם" במערכת כבעליו של המספר \(y\), לא יידרשו עוד שכנועים עתידיים. כל מה שיידרש ממני להוכיח בפני המערכת כדי להזדהות הוא שאני יודע את השורש של \(y\) – סוד שרק אני אמור לדעת, מכיוון שהוצאת שורש היא קשה.

ההוכחה הטריוויאלית של "שלח את \(x\), תן למוודא להעלות אותו בריבוע ולוודא שהוא קיבל \(y\)" לא טוב לנו מכיוון שכך \(x\) נחשף לכל מי שרוצה לצותת. ה"תיקון" שיש לבצע להוכחה הנאיבית אינו גדול, במפתיע; מה שנעשה יהיה לכפול את \(x\) במספר אקראי כלשהו, ואז לשלוח את המכפלה. מכיוון שכפלנו את \(x\) במספר אקראי ואנחנו עובדים בחבורה הכפלית מודולו \(n\) (ולכן כל מספר מודולו \(n\) ששייך לחבורה הזו הוא תוצאה אפשרית של המכפלה, תלוי מה המספר האקראי) הרי שאין במכפלה הזו שום מידע על זהותו של \(x\).

אם כן, נסכם: אנו מגרילים \(r\) אקראי מודלו \(n\), ושולחים למוודא את \(xr\). כיצד המוודא יכול לוודא שאנחנו יודעים את שורש \(y\)? אם הוא יעלה את המספר ששלחנו לו בריבוע הוא יקבל את \((xr)^2=x^2r^2=yr^2\), ולכן הוא צריך מידע נוסף – מהו \(r^2\). אם כן, נשלח לו גם את המספר הזה (בלי חשש שאפשר יהיה לגלות ממנו את \(r\), שהרי הוצאת שורש היא קשה), וכעת המוודא אכן יכול לוודא שהכל בסדר: ש-\(y\) כפול המספר השני ששלחנו לו שווה למספר הראשון בריבוע. עשינו זאת מבלי לחשוף שום מידע על \(x\) (שלחנו רק מספרים שנראים אקראיים) ולכן תם ונשלם הפרוטוקול.

האמנם?

שלמות יש ואפס ידע יש בפרוטוקול שלהלן, אבל נאותות אין בכלל. הנה הדגמה כיצד ניתן להונות את המוודא: נניח שאנחנו אמנם מכירים את \(y\) אבל אין לנו מושג מה השורש שלו. איך נבצע הונאה?

אנחנו יודעים שהמוודא מצפה לקבל שני מספרים \(a,b\) (בכוונה עברתי לאותיות אחרות) כך שמתקיים \(yb=a^2\). במילים אחרות, הוא מצפה שיתקיים \(b=\frac{a^2}{y}\). קשה לנו להוציא שורש, אולם לחלק קל, ולכן מה שנעשה יהיה להגריל את \(a\) (שכזכור, אם היינו מוכיחים "הגונים" היה המספר \(xr\), שאינו "סתם" אקראי אלא מהווה פונקציה של \(x\)), להעלות אותו בריבוע, לחלק ב-\(y\) ולחשב ממנו את \(b\) (שכזכור, אם היינו הגונים היה בכלל \(r^2\)). הצלחנו לענות בכך על כל הדרישות של המוודא, ועם זאת אין לנו שמץ של מושג מה השורש של \(x\). בעיה.

הפתרון הוא הוספת שאלה נוספת למוודא: אם שלחנו לו \(a,b\), הוא יכול לתפוס את הרמאות הזו על ידי דרישת השורש של \(b\). אם היינו הגונים, אז \(b=r^2\) ולכן כל מה שצריך הוא לשלוח את \(r\); אם רימינו ולא יצרנו את \(b\) על ידי העלאה בריבוע של מספר אקראי אלא על ידי חישוב מהסוג שהוצג לעיל – אז אין סיכוי שנדע את השורש של \(b\) (אם היינו יודעים, היינו יכולים לדעת גם את \(x\) – למה?).

מה הבעיה עכשיו? איבדנו את אפס הידע. מדוע? מכיוון שאם אנחנו הוגנים, ושלחנו למוודא את \(r^2, xr\) ועכשיו הוא דרש מאיתנו גם את \(r\), הרי שהוא מסוגל לחלק את \(xr\) ב-\(r\) ולקבל את \(x\) ישירות – וכך גם כל מי שמצותת לרשת.

הפתרון הוא לבצע פשרה. האבחנה היא שאת \(r^2\) תמיד אפשר לשלוח, אבל שתי פיסות המידע האחרות, \(r\) ו-\(xr\) לא מתיישבות זו עם זו, ושתיהן גם ממלאות פונקציות שונות: \(xr\) מראה למוודא שאנחנו אכן יודעים את \(x\), ואילו \(r\) מראה למוודא שאנחנו הגונים ובאמת יצרנו את ה-\(b\) באופן אקראי. לכן, מספיק לבחון כל אחת משתי פיסות המידע הללו לסירוגין.

הנה הפרוטוקול השלם והאמיתי: הפרוטוקול שלנו יחולק לסיבובים. בכל סיבוב, המוכיח יגריל \(r\) אקראי וישלח למוודא את \(r^2\). בשלב הזה המוודא יבצע "הטלת מטבע" ועל פיה יודיע למוכיח אם הוא רוצה לקבל את \(xr\) או את \(r\). אם הוא ביקש את \(xr\), הוא מעלה בריבוע את מה שקיבל, מחלק במספר הראשון שקיבל ובודק אם יצא \(y\). אם הוא ביקש את \(r\), הוא מעלה בריבוע את מה שקיבל ובודק האם זה שווה למספר הראשון שקיבל. אם הבדיקה נכשלה, הוא יודע שהמוכיח שקרן ומעיף אותו. אחרת, ממשיכים לסיבוב הבא.

אם המוכיח דובר אמת הוא תמיד יצליח – כלומר, יש לנו שלמות. אם המוכיח שקרן, לעומת זאת, הוא אף פעם לא יידע בו זמנית את התשובה לשתי השאלות שהמוודא עשוי לשאול – זה תלוי בצורה שבה הוא יצר את המספר הראשון ששלח למוודא. לכן הוא צריך "לנחש" מה המוודא ישאל, וההסתברות לכך היא 50:50. לכן, ההסתברות שלו לעבור את הסיבוב הראשון בשלום היא חצי, אבל ההסתברות לעבור את השני בשלום היא כבר רבע (כי גם בראשון וגם בשני הוא צריך להצליח), בשלישי שמינית וכן הלאה וכן הלאה – מהר מאוד ההסתברות של מוכיח לשקר הופכת לאפסית, ולכן יש כאן גם נאותות.

כדי להוכיח פורמלית שזו הוכחת אפס ידע יש צורך בהדגמת סימולטור. במקרה שלנו זה "סימולטור עם נבוט" – הוא מזמין מוודא "אמיתי" להשתתף בסימולציה, ואז מנסה לרמות אותו באותה צורה שבה מוודא רמאי היה פועל – מנחש מה תהיה השאלה של המוודא, ובוחר את המספר הראשון שישלח לו בהתאם לה. אם המוודא אכן בחר את השאלה שהמוכיח ניחש – מה טוב, מצלמים את התנהלות הסיבוב הזה (מוסיפים ל"תעתיק" של הפרוטוקול שהסימולטור יוצר) וכולם שמחים. אם לעומת זאת המוודא בחר את השאלה "הלא נכונה", הסימולטור מרביץ לו עם נבוט בראש (מאפס אותו כך שלא יזכור את הסיבוב הכושל הנוכחי), שורף את סרט הצילום (לא מוסיף את הסיבוב הכושל לפרוטוקול) ומתחיל סיבוב חדש. צריך להוכיח פורמלית שזה עובד – אבל זה עובד. בממוצע חצי מהסיבובים שהסימולטור מנסה לייצר ייכשלו, אבל זה לא כל כך הרבה, ולכן הסימולטור עדיין יעבוד בפרק זמן סביר, ויצליח לשכנע שהפרוטוקול שהוא ייצר "אותנטי" (ה"אותנטיות" נובעת מכך שהמוודא שהשתתף ביצירת הפרוטוקול היה אמיתי).

נשאר רק מה שהבטחתי קודם – השיפור של פייגה. כאמור, לסוגייה הטכנית אני לא הולך להיכנס אלא רק להפיכה שלו את הפרוטוקול למה שמכונה Proof of Knowledge. כפי שהוא כרגע, הפרוטוקול כן מעביר למוודא מידע כלשהו – הוא אומר לו של-\(y\) יש שורש מודולו \(n\) (דבר שאינו נכון בהכרח לכל המספרים מודולו \(n\)). לכאורה זה לא בעייתי כי ממילא ההנחה המוקדמת של כל הפרוטוקול היא שקיים למספר הזה שורש (אחרת איך אפשר להוכיח שיודעים את השורש שלו?).

השיפור מחסל גם את הדבר הזה. עדיין יש מספר \(y\), אבל מה שהמוכיח מוכיח הוא שאם קיים לו שורש, המוכיח יודע אותו; ואם לא קיים לו שורש, המוכיח יודע גם את העובדה הזו (שגם אותה קשה לבדוק), אבל הוא לא מגלה למוודא איזה משתי העובדות הללו נכונות. זוהי הצורה הקיצונית ביותר של הוכחות אפס-ידע; כאן אפילו לא ברור אם מה שהמוכיח מנסה להוכיח הוא נכון או לא, והדבר היחיד שידוע בסיום הפרוטוקול הוא שהמוכיח יודע.

וזוהי, לטעמי, אחת מהדוגמאות הנאות ביותר להוכחה לא קונסטרוקטיבית.