ทุกปัญหา NP-hard คำนวณได้หรือไม่?


คำตอบ:


15

ไม่ฮาร์ดไม่จำเป็นต้องคำนวณ คำจำกัดความค่อนข้างสมบูรณ์: ปัญหาคือ -hard หากปัญหาที่มีวิธีการแก้ปัญหาโพลีเวลาหมายถึงทุกปัญหาในNPมีวิธีการแก้ปัญหาแบบโพลีเวลา (นั่นคือการลดลงถึงLมีอยู่สำหรับทุกปัญหาในNP )L N P N P L N PNPLNPNPLNP

ปัญหาที่ไม่สามารถคำนวณได้นั้นยากอย่างไม่มีเหตุผล: สมมติว่าเราสามารถแก้ปัญหาได้ในเวลาพหุนาม จากนั้นเราใช้หลักฐานที่ไม่สามารถคำนวณได้ว่าเป็นทั้งความสามารถในการคำนวณและไม่สามารถโต้แย้งได้ จากความผิดพลาดนี้เราสามารถได้รับทุกสิ่งกล่าวคือมีอัลกอริธึมเวลาพหุนามสำหรับปัญหาNPใด ๆ ที่NPเรากำลังดู

ตัวอย่างเช่นพิจารณาลังเลปัญหาHเราสามารถลดการใด ๆภาษาเพื่อดังต่อไปนี้สมมติว่าเรามีการตรวจสอบ polytimeซึ่งการตรวจสอบถ้าคือใบรับรองสำหรับ :N P A H f ( s , c ) c s AHNPAHf(s,c)csA

  • ได้รับการป้อนข้อมูลs
  • สร้าง ( แต่ทำไม่ทำงาน) ทัวริงเครื่องซึ่งจะมีการป้อนข้อมูลพยายามทุกใบรับรองและหยุดถ้าคือใบรับรองการตรวจสอบว่าAx s MxccsA
  • Return (นั่นคือส่งคืน true iffหยุดการทำงานของอินพุต )M xH(M,x)Mx

ดังนั้นด้วยการเรียกใช้อัลกอริทึมแบบโพลีเวลาเดียวเพื่อแก้ไขปัญหาการหยุดชะงักเราสามารถแก้ปัญหาใด ๆในเวลาพหุนามNP

การลดลงดังกล่าวไม่ได้มีประโยชน์เพราะทั้งหมดจะมีการบอกว่า "ถ้าเป็นเท็จแล้วมีบางอย่าง" เรารู้อยู่แล้วว่าไม่มีอัลกอริทึม polytime สำหรับปัญหาที่ไม่สามารถคำนวณได้


7
"คำจำกัดความค่อนข้างสมบูรณ์" แต่ไม่ใช่สิ่งที่ตามมาในคำตอบของคุณ

ฉันมีคำถามเกี่ยวกับเรื่องนี้ ฉันสามารถจินตนาการถึงฟังก์ชั่นที่แก้ปัญหาการหยุดชะงักสำหรับชุดโปรแกรมที่ใหญ่ที่สุดเท่าที่จะเป็นไปได้ภายใต้ข้อ จำกัด ที่เหมาะสม แต่ฉันสามารถจินตนาการว่าฟังก์ชั่นนี้ยังไม่สามารถคำนวณได้ (ในแง่ที่ว่าเราจะไม่พบมัน . แต่ถ้าพวกเราก็ไม่ได้มีวิธีการแก้มันก็ไม่ได้ชัดเจนกับผมว่ามันควรจะแก้ปัญหา NP-หนักจำเป็นต้อง ดังนั้นตรรกะในคำตอบนี้จึงไม่เป็นไปตาม (หมายถึง undecidable! = ไม่สามารถคำนวณได้) หรือเหตุผลของฉันมีข้อบกพร่อง (น่าจะเป็น) ดังนั้นข้อบกพร่องคืออะไร?
Mehrdad

12
คำตอบนี้ส่วนใหญ่ไม่ถูกต้องรวมถึงคำจำกัดความของคุณของ NP ยาก: ปัญหา A เป็นปัญหายากถ้า "สำหรับทุกปัญหา NP B มีการลดเวลาโพลีเป็น B ถึง A" นั่นไม่เหมือนกับ "ถ้า A คือโพลีเวลาดังนั้น P = NP" (หลังเป็นผลมาจากอดีต แต่ไม่ใช่ในทางกลับกัน) โดยเฉพาะอย่างยิ่งมีปัญหาที่ไม่สามารถคำนวณได้เกือบแน่นอนที่ล้มเหลวในการเป็นปัญหา NP ฉันไม่ได้ลงรายละเอียด แต่ปัญหาของการเป็นสมาชิกในชุดทั่วไปที่เพียงพอ (ในแง่ของการบังคับ) ควรทำเคล็ดลับ ชุดหยุดโดยเฉพาะอย่างยิ่งคือ NP-hard อย่างไรก็ตามจากการลดลงของคุณ

7
คิดเกี่ยวกับการลดเวลาโพลีจาก A ถึง B เช่นนี้มันเป็นโปรแกรมที่ทำงานในเวลาพหุนาม แต่มันมีความสามารถพิเศษในการสืบค้นในขั้นตอนเดียว oracle ที่ตอบคำถามของปัญหา B. โดยไม่คำนึงว่า มีอัลกอริธึมแบบโพลี - เวลาสำหรับ B หรือแม้กระทั่งว่า B คำนวณได้มันยังคงเหมาะสมที่จะถามคำถามต่อไปนี้: สมมติว่า oracle ตอบคำถามที่ถูกต้องอย่างถูกต้อง (ในขั้นตอนเดียว) โปรแกรมที่เป็นปัญหา ทำงานในเวลาพหุนามและแก้ปัญหากรณี A ได้อย่างถูกต้อง?

2
@MikeHaskel การเปรียบเทียบ oracle ของคุณนั้นถูกต้องเฉพาะเมื่อหลังจากการสอบถาม oracle โปรแกรมจะต้องหยุดด้วยคำตอบเดียวกับ oracle นั้น มิฉะนั้น co-SAT จะลดเหลือ SAT: สอบถามออราเคิลและปฏิเสธ ในแนวคิดการลดบางอย่างเช่นการลดทัวริงสิ่งนี้จะเป็นที่ยอมรับ แต่ในการลดเวลามาตรฐานโพลีหรือแม้กระทั่งในการลดแบบหลายคนก็ไม่ได้
Chi

16

ดูเหมือนจะมีความสับสนอย่างมากในชุมชนนี้เกี่ยวกับคำถามนี้ ฉันจะให้คำตอบโดยละเอียดโดยหวังว่าจะได้ล้างน้ำและส่องความสัมพันธ์ระหว่างการคำนวณและความแข็งของ NP

ครั้งแรกฉันเชื่อว่าการมีความชัดเจนและชัดเจนเกี่ยวกับคำจำกัดความต่าง ๆ ที่เกี่ยวข้องจะแก้ไขความสับสนมากมาย

สตริงเป็นลำดับ จำกัด ของตัวละครจากบางตัวอักษรคง จำกัด

ปัญหาการตัดสินใจเป็นชุดของสตริง (โดยทั่วไปชุดนี้จะไม่มีที่สิ้นสุด) ให้นึกถึงปัญหาการตัดสินใจในการทดสอบสตริงสำหรับคุณสมบัติบางอย่าง: สตริงที่มีคุณสมบัติอยู่ในชุดและสตริงที่ไม่มีคุณสมบัตินั้นไม่ใช่

สมมติว่าเรามีปัญหาทั้งสองตัดสินใจและB Say เป็นพหุนามเวลาซึ้งปรับปรุงเพื่อBถ้ามีบางพหุนามP ( x )และขั้นตอนวิธีการบางขั้นตอนวิธีMดังกล่าวว่าสำหรับสตริงทั้งหมดs ,ABABp(x)Ms

  • ถ้าคุณให้มีการป้อนข้อมูลs , Mหยุดน้อยกว่าP ( | s | )ขั้นตอน (ที่| s |คือความยาวของสตริงs ) และผลสตริงM ( s )MsMp(|s|)|s|sM(s)
  • อยู่ในถ้าหาก M ( s )อยู่ในBsAM(s)B

ปัญหาการตัดสินใจเป็นNP-ยากถ้าทุก NP ตัดสินใจปัญหา, เป็นพหุนามเวลาออกซิเจนBBAAB

ปัญหาการตัดสินใจคือคำนวณถ้ามีขั้นตอนวิธี , ว่าสำหรับสตริงทั้งหมดs ,Ms

  • ถ้าคุณให้มีการป้อนข้อมูลs , Mหยุดและเอาท์พุททั้ง "ใช่" หรือ "ไม่"MsM
  • เอาต์พุตคือ "ใช่" ถ้าอยู่ในAและ "no"sA

ด้วยคำจำกัดความข้างต้นเราสามารถชี้แจงสิ่งที่ฉันคิดว่าอาจเป็นความสับสนในคำถามของคุณได้ทันที: ไม่มีสิ่งใดในคำจำกัดความของปัญหาการตัดสินใจการลดลงหรือความกระด้าง NP ต้องมีปัญหาในการตัดสินใจ คำจำกัดความทำให้รู้สึกที่สมบูรณ์แบบของการตัดสินใจปัญหาเป็นชุดของข้อ จำกัด และชุดเหล่านี้สามารถน่ารังเกียจมากแน่นอน


นั่นเป็นคำถามสองข้อบนโต๊ะ:

  1. คำจำกัดความเปิดทิ้งไว้เป็นไปได้ว่าฟังก์ชั่นที่ไม่สามารถคำนวณได้อาจเป็น NP-hard มีจริงไม่ใช่คำนวณฟังก์ชั่นรุ่น NP-ยาก?
  2. มีปรีชาญาณว่าการบอกปัญหาคือ NP-hard กำลังบอกว่าเป็นการยากที่จะแก้ไข การบอกว่าไม่สามารถคำนวณได้ก็เหมือนกับการพูดว่า "ยากมาก" ในการแก้ปัญหา ดังนั้นปัญหาที่คำนวณไม่ได้ทั้งหมดเป็นปัญหา NP-hard หรือไม่

คำถามที่ 1 ตอบได้ง่ายกว่า มีสองวิธีที่สำคัญโดยเฉพาะอย่างยิ่งในการค้นหาปัญหาการตัดสินใจที่ไม่คำนวณซึ่งเป็นปัญหาที่ยาก ที่แรกก็คือลังเลปัญหา: ลังเลปัญหา, มีทรัพย์สินที่ทุกคำนวณปัญหาการตัดสินใจเป็นพหุนามเวลาออกซิเจนH เนื่องจากปัญหา NP นั้นคำนวณได้ทุกปัญหา NP คือพหุนามเวลาที่ลดลงถึงHดังนั้นHจึงเป็น NP-hardHHHH

อีกวิธีที่สำคัญในการสร้างปัญหา NP-hard ที่คำนวณไม่ได้คือการสังเกตว่าเราสามารถรวมปัญหา NP-hard ใด ๆ ที่รู้จักกับปัญหาที่ไม่คำนวณได้ ให้เป็น NP-hard และBไม่สามารถคำนวณได้ สร้างปัญหาการตัดสินใจA Bดังต่อไปนี้A Bมีสตริงเหล่านั้นของแบบฟอร์ม "0 ตามด้วยสตริงในA " และของฟอร์ม "1 ตามด้วยสตริงในB " Bเป็น NP-ยากเพราะเราสามารถเปิดลดใด ๆ (ของปัญหาใด ๆ ) เพื่อเข้าลดลงไปBABABABABABAAB: เพียงแค่ปรับแต่งอัลกอริทึมในการส่งออก "0" พิเศษที่ด้านหน้าของสตริงเอาต์พุต ไม่สามารถคำนวณได้เนื่องจากการคำนวณA Bต้องตัดสินใจว่าสตริงใดที่ขึ้นต้นด้วย "1" อยู่ในชุด สิ่งนี้เป็นไปไม่ได้เนื่องจากBไม่สามารถคำนวณได้ABABB


คำถามที่ 2 มีเล่ห์เหลี่ยมมาก แต่ในความเป็นจริงมีปัญหาการตัดสินใจไม่คำนวณที่ไม่ใช่ปัญหายาก (สมมติว่า P NP) คำตอบที่ดีของ Yuval สร้างปัญหาการตัดสินใจอย่างชัดเจน (สำหรับนักทฤษฎีการคำนวณใด ๆ ในห้อง "โคเฮนΠ 0 1 -generic" ใด ๆจะทำเคล็ดลับเช่นกัน) ฉันจะแยกแยะว่าทำไมปรีชาว่า "ปัญหา NP-hard นั้นยากไม่ใช่ปัญหาที่คำนวณได้ยาก " มันผิด.Π10

ความแข็งของ NP และความไม่สามารถคำนวณได้บอกว่าปัญหาคือ "ยาก" ในความหมายทั่วไป แต่มันแตกต่างกันมากและไม่ควรรวมเข้าด้วยกันเป็นปรากฏการณ์ชนิดเดียวกัน โดยเฉพาะอย่างยิ่งความแข็งของ NP เป็นคุณสมบัติ "บวก": ปัญหา NP-hard นั้นยากในแง่ที่ว่าเมื่อมีการเข้าถึงแผ่นโกงสำหรับAคุณสามารถแก้ปัญหาระดับยากAAได้ บนมืออื่น ๆ ที่ไม่ใช่การคำนวณเป็นที่พัก "เชิงลบ" เป็นปัญหาที่ไม่ได้คำนวณอย่างหนักในความรู้สึกที่คุณไม่สามารถแก้AAกับระดับที่กำหนดของทรัพยากร

("บังคับ" โดยวิธีเป็นเทคนิคที่ใช้ในการผลิต "โคเฮนทั่วไป" ที่ฉันกล่าวถึงจะคลุมเครือมากบังคับเป็นวิธีทั่วไปในการผลิตสิ่งที่ "ทั่วไป" ในสิ่งที่พวกเขามี ไม่มีคุณสมบัติที่เป็นบวกและทุกคุณสมบัติเชิงลบนั่นคือสาเหตุที่การบังคับให้สร้างปัญหาโดยตรงที่ไม่สามารถคำนวณได้หรือปัญหา NP-hard)Π10


2
คุณไม่สามารถสร้างภาษาที่ไม่สามารถตัดสินใจได้ซึ่งไม่ใช่ปัญหายากเย็นแสนเข็ญโดยการทำให้เส้นทแยงมุม? ทแยงมุมกับตัวเลือกทั้งหมดและการลดค่าโพลีไทม์ทั้งหมดจาก SAT
Yuval Filmus

1
@YuvalFilmus นั่นอาจจะใช้ได้ใช่ ฉันคิดว่าการเขียนรายละเอียดเกี่ยวกับสาเหตุที่การลดเส้นทแยงมุมเทียบกับการลดลงของค่าโพลีไทม์จาก SAT เป็นจำนวนเงินที่เป็นไปได้คล้ายกันในการแสดงให้เห็นว่าการบังคับใช้งานได้ดังนั้นฉันจึงไม่ได้คิดถึง

1
@YuvalFilmus ฉันได้เพิ่มความกระจ่างในตอนนี้ว่าคุณต้องถือว่า P NP: มีขั้นตอนหนึ่งในการพิสูจน์ของฉันที่อ่านว่า "มีปัญหาใน NP แต่ไม่ใช่ใน P"

1
@aelguindy ฉันไม่แน่ใจว่าวิธีที่เข้าถึงได้มากที่สุดเพื่อพิสูจน์ว่ามันคืออะไร ฉันพูดถึงเทคนิคการบังคับซึ่งเป็นเรื่องทั่วไปและทรงพลัง ฉันเรียนรู้จากคนไม่ใช่ตำราดังนั้นฉันไม่รู้เป็นการอ้างอิงที่ดีเกี่ยวกับการบังคับ ดังที่ยูวาลชี้ให้เห็นอย่างไรก็ตามการบังคับใช้อาจเกินความเป็นจริง: การโต้แย้งโดยตรงที่เกี่ยวข้องกับแนวทแยงอาจใช้งานได้ "ชุดและองศาที่นับซ้ำได้" ของ Soare เป็นหนังสือเรียนที่ครอบคลุมรูปแบบการโต้เถียงมากมายหากคุณต้องการทำความคุ้นเคย อีกครั้งส่วนใหญ่อาจ overkill แม้ว่า ...

1
@aelguindy นอกจากนี้หากคุณคิดว่าชุดของปัญหาการตัดสินใจเป็นพื้นที่ทอพอโลยีคุณสามารถนวดทฤษฎีบทหมวด Baireเพื่อสร้างหลักฐาน ทฤษฎีนี้เกี่ยวข้องกับการบังคับอย่างใกล้ชิด แต่เก่ากว่าและตรงไปตรงมามากขึ้น

11

Nope NP-Hard หมายความว่ามันยากหรือยากกว่าปัญหา NP ที่ยากที่สุด การที่ไม่สามารถคำนวณได้จะทำให้ยากยิ่งกว่า NP

วิกิพีเดีย:

มีปัญหาการตัดสินใจที่เป็นปัญหา แต่ไม่สมบูรณ์เช่นปัญหาการหยุดชะงัก

ทุกคนรู้ว่าไม่สามารถคำนวณได้


4
โปรดทราบว่าในขณะที่ปัญหาที่ไม่สามารถคำนวณได้บางอย่าง (เช่นปัญหาการหยุดพัก) คือ NP-hard ซึ่งไม่ได้หมายความว่าปัญหาที่ไม่คำนวณได้ทั้งหมดคือ NP-hard ดูความคิดเห็นของฉันเกี่ยวกับคำตอบของ jmite NP-hardness เป็นคุณสมบัติเชิงบวก: มันบอกว่าคำตอบสำหรับปัญหาของคุณสามารถช่วยแก้ปัญหา NP ได้ การเป็น NP-hard แสดงว่าปัญหาคือระดับยาก ไม่ใช่ปัญหาที่ยากทั้งหมดคือ NP-hard

@MikeHaskel: ถือวิธีการแก้ปัญหาที่ลังเลจะช่วยลดปัญหาทั้งหมดที่ P * ยากลำบากในการลังเลปัญหา ..
โจชัว

1
@Joshua: นั่นไม่เข้าท่าเลย มันเหมือนส่วนที่ไม่ใช่ข้อพิสูจน์ คุณหมายถึงอะไรสำหรับปัญหาที่มีจำนวน จำกัด บิตในการแก้ปัญหาและทำไมคุณคิดว่าสิ่งนี้ใช้กับปัญหาที่ไม่สามารถคำนวณได้ทั้งหมด คุณหมายถึงอะไรโดย "P * หยุด" ส่วนที่เหลือของ "ลดผ่านบิตที่ n ของ ... " คืออะไร
user2357112 รองรับ Monica

1
@ โจชัว: ดูเหมือนว่าปัญหาหลักคือการที่คุณสมมติว่าทุกปัญหาสอดคล้องกับเครื่องทัวริง ไม่ใช่ทุกปัญหาที่สอดคล้องกับเครื่องทัวริง ไม่มีproblem()ฟังก์ชั่นที่เราสามารถเรียกได้
user2357112 รองรับ Monica

1
คุณควรย้ายสิ่งนี้ไปที่การแชทหรืออะไรบางอย่าง
เลมอนที่ถูกทำลาย

9

เพื่อความสมบูรณ์ขอให้เราพิสูจน์ทฤษฎีบทต่อไปนี้:

มีภาษาที่ไม่สามารถคำนวณได้ซึ่งไม่ใช่ภาษา NP-hard ถ้าหาก P NP

ถ้า P = NP นั้นไม่ใช่ภาษาที่ไม่สำคัญ (ซึ่งแตกต่างจาก ) คือ NP-hard (แบบฝึกหัด) และโดยเฉพาะอย่างยิ่งภาษาที่ไม่สามารถนับได้คือ NP-hard,{0,1}

ตอนนี้สมมติว่า P NP ให้T ฉันเป็นการนับจำนวนเครื่องจักรทัวริงทั้งหมด เราจะสร้างภาษาL ที่จำเป็นในแต่ละขั้นตอน ในแต่ละขั้นตอนเราจะเก็บ{ 0 , 1 , ? }สีของ{ 0 , 1 } ซึ่งเราแทนด้วยL ; ที่นี่0หมายความว่าเราได้ตัดสินใจแล้วว่าสตริงไม่ได้อยู่ในL , 1หมายความว่าเราได้ตัดสินใจว่าสตริงนั้นอยู่ในLและ?TiL{0,1,?}{0,1}L0L1L?หมายความว่าเรายังไม่ได้ตัดสินใจ ทั้งหมด แต่อย่าง จำกัด จำนวนมากจะเป็นสี.?

ในขั้นตอนที่เราคิดว่าT iเป็นเครื่องที่รับอินพุตของมันปฏิเสธหรือไม่หยุด ถ้าT ฉันหยุดไม่ได้แล้วเราจะไม่ทำอะไรเลย ถ้าT ฉันหยุดแล้วเราจะพบสตริงxซึ่งL ( x ) = ? และตั้งL ( x ) : = 0ถ้าT ฉัน ( x )ยอมรับและL ( x ) : = 1ถ้าT2iTiTiTixL(x)=?L(x):=0Ti(x)L(x):=1ปฏิเสธTi(x)

ในขั้นตอนที่เราคิดว่าT iเป็นเครื่องคำนวณฟังก์ชั่นบางส่วน (อาจ) ของอินพุต ถ้าT ฉันไม่ได้ทั้งหมดหรือถ้ามันเป็นทั้งหมด แต่ไม่ได้ทำงานในเวลาพหุนามหรือถ้ามันเป็นทั้งหมด แต่ช่วงที่มี จำกัด เราจะไม่ทำอะไรเลย ถ้าT ฉันเป็นผลรวมวิ่งในเวลาพหุนามและมีช่วงที่ไม่มีที่สิ้นสุดแล้วเราจะพบสตริงxเช่นที่L ( T i ( x ) ) = ? . ถ้าx S A T (นั่นคือถ้าx2i+1TiTiTixL(Ti(x))=?xSATxเข้ารหัสพอใจ CNF) แล้วเราตั้งและมิฉะนั้นเราชุดL ( x ) : = 1L(x):=0L(x):=1

หลังจากขั้นตอนหลายอย่างมากมายที่เราได้รับระบายสีของ{ 0 , 1 } ซึ่งเราใช้ภาษาที่แท้จริงในลักษณะที่กำหนดเอง{0,1,?}{0,1}

ภาษาที่เป็นผลลัพธ์ไม่สามารถคำนวณได้: ขั้นตอนที่2 ฉันรับรองว่าT ฉันไม่คำนวณ มันไม่ได้เป็นปัญหาแบบแข็ง ๆ แต่นี่คือเหตุผลที่ละเอียดอ่อนกว่านี้เล็กน้อย สมมติว่าT ฉันคือการลด polytime จาก SAT เพื่อL ถ้าช่วงของT ฉันมี จำกัด แล้วเราสามารถเปิดT ฉันเป็นเครื่อง polytime ตัดสินใจ SAT, โดยรายชื่อตารางความจริงของLในช่วงของTฉัน สิ่งนี้เป็นไปไม่ได้โดยสมมติฐาน P NP ดังนั้นT ฉันมีช่วงที่ไม่มีที่สิ้นสุด แต่แล้วขั้นตอนที่2 ฉันL2iTiTiLTiTiLTiTiกฎออกเป็นลดลงจาก SAT ไปของL2i+1L


3

ภาษาคือ NP-ยากถ้าทุกL 'N PเรามีL 'เป็นพหุนามเวลาออกซิเจนL ปัญหาการยอมรับสำหรับเครื่องทัวริงที่กำหนดไว้ล่วงหน้าLLNPLL

ANTM={M,wM is a nondeterministic Turing machine that accepts w}

undecidable และเป็น NP-hard สำหรับการพิจารณา P L ถูกตัดสินโดยเครื่องจักรทัวริง nondeterministic M ′ ที่มีความซับซ้อนของเวลาพหุนาม การลดลงของโพลีเวลาจากL 'เพื่อN T Mจะได้รับจากLNPLMfLANTM

f(x)=M,x

3

I think what causes people to think there is no uncomputable NP-hard problem is that they miss the point that NP-hardness is a lower bound on the hardness of a problem, not an upper bound on their hardness like P or NP.

A language L being NP-hard means that it is above language in NP and that is. Now if you understand this what need is to show that there are arbitrary harder problem.

Let A be a language. Consider algorithms augmented with a black-box that they can use to deciding membership in A. Let's denote them by CA. It is easy to see that the halting problem for CA, HaltCA is not in CA.

In computablity theory this is called jump of A and is denoted by A. So A<A strictly. And nothing stops us from repeating this: A<A<A<A<...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.