วิธีการของเบรนท์
ในการวิเคราะห์เชิงตัวเลขวิธีของเบรนท์เป็นอัลกอริทึมการหาค่าราก แบบผสมผสาน ที่รวมวิธีการแบ่งครึ่งวิธีการ ตัด และการประมาณค่าแบบกำลังสองผกผันเข้า ด้วย กัน วิธีนี้มีความน่าเชื่อถือเทียบเท่ากับวิธีการแบ่งครึ่ง แต่ก็สามารถทำได้อย่างรวดเร็วเช่นเดียวกับวิธีการที่มีความน่าเชื่อถือน้อยกว่า อัลกอริทึมนี้พยายามใช้วิธีการตัดหรือการประมาณค่าแบบกำลังสองผกผันซึ่งอาจลู่เข้าได้อย่างรวดเร็วหากเป็นไปได้ แต่จะกลับไปใช้วิธีการแบ่งครึ่งที่มีความน่าเชื่อถือมากกว่าหากจำเป็น วิธีของเบรนท์คิดค้นโดยริชาร์ด เบรนท์[ 1 ]และสร้างขึ้นจากอัลกอริทึมก่อนหน้านี้ของธีโอดอรัส เดกเกอร์ [ 2 ] ดังนั้นวิธีนี้จึงเป็นที่รู้จักกันในชื่อวิธีเบรนท์-เดกเกอร์ด้วย
การปรับปรุงสมัยใหม่ของวิธีการของ Brent ได้แก่ วิธีการของ Chandrupatla ซึ่งง่ายกว่าและเร็วกว่าสำหรับฟังก์ชันที่แบนราบรอบราก[ 3 ] [ 4 ]วิธีการของ Riddersซึ่งทำการประมาณค่าแบบเอกซ์โพเนนเชียลแทนการประมาณค่าแบบกำลังสอง ทำให้ได้สูตรปิดที่ง่ายกว่าสำหรับการวนซ้ำ และวิธีการ ITPซึ่งเป็นการผสมผสานระหว่าง regula-falsi และการแบ่งครึ่งที่บรรลุการรับประกันกรณีที่เลวร้ายที่สุดและเชิงอะซิมโทติกที่ดีที่สุด
วิธีของเดกเกอร์
แนวคิดในการรวมวิธีการแบ่งครึ่งเข้ากับวิธีการตัดนั้นมีที่มาจากDekker (1969 )
สมมติว่าเราต้องการแก้สมการf ( x ) = 0 b₀ ที่f ( a₀ )และf ( b₀ ) มีเครื่องหมายตรงข้ามกัน ถ้าfมีความต่อเนื่องบน [ a₀ ] ทฤษฎีบทค่ากลาง จะรับประกันการ ของคำตอบa₀และ
ในแต่ละรอบการคำนวณจะมีสามประเด็นหลักที่เกี่ยวข้อง:
- b คือ ค่าที่ได้จากการวนซ้ำในปัจจุบัน กล่าวคือ ค่าที่คาดเดาในปัจจุบันสำหรับรากของf
- a คือ "จุดตรงข้าม" กล่าวคือ จุดที่f ( a ) และf ( b ) มีเครื่องหมายตรงข้ามกัน ดังนั้นช่วง [ a , b ] จึงครอบคลุมคำตอบ นอกจากนี้ | f ( b )| ควรน้อยกว่าหรือเท่ากับ | f ( a )| ดังนั้นb จึงเป็นตัวเลือกที่ดีกว่าสำหรับคำตอบที่ไม่ทราบค่ามากกว่าa
- b คือค่าที่ได้จากการวนซ้ำครั้งก่อน (สำหรับการวนซ้ำครั้งแรก จะกำหนดให้b = a )
มีการคำนวณค่าชั่วคราวสองค่าสำหรับรอบถัดไป ค่าแรกได้มาจากการประมาณค่าเชิงเส้น หรือที่เรียกว่าวิธีซีแคนต์:
และวิธีที่สองได้มาจากการแบ่งครึ่งช่วง
ถ้าผลลัพธ์ของวิธีเซแคนต์sอยู่ตรงกลางระหว่างb และmพอดี ผลลัพธ์นั้นจะกลายเป็นค่าวนซ้ำถัดไป ( b = s ) มิเช่นนั้นจะใช้จุดกึ่งกลาง ( b = m )
จากนั้น เลือกค่าของคอนทราพอยต์ใหม่เพื่อให้f ( ak ) และf ( bk ) มีเครื่องหมายตรงข้ามกัน ถ้าf ( ak และf ( bk ) มีเครื่องหมายตรงข้ามกัน คอนทราพอยต์จะยังคงเหมือนเดิม คือak = akแต่ถ้าf ( bk ) และf ( bk มีเครื่องหมายตรงข้ามกัน คอนทราพอยต์ใหม่เป็นak = bk
สุดท้ายนี้ ถ้า | f ( a )| < | f ( b )| แล้วa น่าจะเป็นคำตอบที่คาดเดาได้ดีกว่าb ดังนั้นค่าของa และb จึงถูกสลับกัน
นี่เป็นการสิ้นสุดคำอธิบายของการทำซ้ำเพียงครั้งเดียวของวิธีการของเดกเกอร์
วิธีของเดกเกอร์ทำงานได้ดีหากฟังก์ชันfมีพฤติกรรมที่ดีพอสมควร อย่างไรก็ตาม มีบางกรณีที่การวนซ้ำทุกครั้งใช้วิธีซีแคนต์ แต่ค่าที่ได้จากการวนซ้ำb จะลู่เข้าช้ามาก (โดยเฉพาะอย่างยิ่ง | b − b | อาจมีค่าน้อยมากจนเกินจะกำหนดได้) ในกรณีนี้ วิธีของเดกเกอร์ต้องการการวนซ้ำมากกว่าวิธีแบ่งครึ่งช่วงมาก
วิธีการของเบรนท์
เบรนท์ (1973)เสนอการปรับเปลี่ยนเล็กน้อยเพื่อหลีกเลี่ยงปัญหาของวิธีการของเดกเกอร์ เขาเพิ่มการทดสอบเพิ่มเติมซึ่งต้องเป็นไปตามเงื่อนไขก่อนที่จะยอมรับผลลัพธ์ของวิธีการเซแคนต์เป็นค่าวนซ้ำถัดไป ต้องมีอสมการสองข้อที่ต้องเป็นไปตามเงื่อนไขพร้อมกัน:
เมื่อกำหนดค่าความคลาดเคลื่อนเชิงตัวเลขที่เฉพาะเจาะจงแล้วหากขั้นตอนก่อนหน้าใช้วิธีการแบ่งครึ่งช่วง ค่าอสมการจะต้องเป็นจริงเพื่อทำการประมาณค่าในช่วง มิฉะนั้นจะใช้วิธีการแบ่งครึ่งช่วงและนำผลลัพธ์ไปใช้ในการวนซ้ำครั้งถัดไป
หากขั้นตอนก่อนหน้านี้ใช้วิธีการประมาณค่าในช่วง (interpolation) แล้ว อสมการจะถูกนำมาใช้แทนในการดำเนินการถัดไป (เพื่อเลือก) ว่าจะใช้วิธีการประมาณค่าในช่วง (เมื่ออสมการเป็นจริง) หรือวิธีการแบ่งครึ่งช่วง (เมื่ออสมการไม่เป็นจริง)
นอกจากนี้ หากขั้นตอนก่อนหน้าใช้วิธีการแบ่งครึ่งช่วง (bisection method) อสมการ จะต้องเป็นจริง มิฉะนั้นจะใช้วิธีการแบ่งครึ่งช่วงอีกครั้งและนำผลลัพธ์ไปใช้ในการวนซ้ำครั้งถัดไป หากขั้นตอนก่อนหน้าใช้วิธีการประมาณค่าในช่วง (interpolation) ก็ จะใช้ อสมการ แทน
การปรับเปลี่ยนนี้ทำให้มั่นใจได้ว่าในการ วนซ้ำครั้งที่ kจะมีการดำเนินการขั้นตอนการแบ่งครึ่งช่วง (bisection) ในการวนซ้ำเพิ่มเติมอย่างมากที่สุด เนื่องจากเงื่อนไขข้างต้นบังคับให้ขนาดขั้นตอนการแทรกสอดที่ต่อเนื่องกันลดลงครึ่งหนึ่งทุกๆ สองการวนซ้ำ และหลังจากวนซ้ำอย่างมากที่สุด ขนาดขั้นตอนจะเล็กกว่า ซึ่งจะเรียกใช้ขั้นตอนการแบ่งครึ่ง ช่วงเบรนต์พิสูจน์แล้วว่าวิธีการของเขาต้องการการวนซ้ำอย่างมากที่สุดN²ครั้ง โดยที่Nแทนจำนวนการวนซ้ำสำหรับวิธีการแบ่งครึ่งช่วง หากฟังก์ชันfมีพฤติกรรมที่ดี วิธีการของเบรนต์มักจะดำเนินการโดยการแทรกสอดแบบกำลังสองผกผันหรือเชิงเส้น ซึ่งในกรณีนี้จะลู่เข้าแบบเหนือ เชิง เส้น
นอกจากนี้ วิธีของเบรนท์ใช้การประมาณค่าแบบกำลังสองผกผันแทนการประมาณค่าเชิงเส้น (ดังที่ใช้ในวิธีซีแคนท์) หากf ( b ), f ( a ) และf ( b ) แตกต่างกัน จะช่วยเพิ่มประสิทธิภาพเล็กน้อย ผลที่ตามมาคือ เงื่อนไขสำหรับการยอมรับs (ค่าที่เสนอโดยการประมาณค่าเชิงเส้นหรือการประมาณค่าแบบกำลังสองผกผัน) จะต้องเปลี่ยนแปลง: sจะต้องอยู่ระหว่าง (3 a + b ) / 4 และb
อัลกอริทึม
ป้อนค่าa , bและ (ตัวชี้ไปยัง) ฟังก์ชันสำหรับf คำนวณf ( a ) คำนวณf ( b ) ถ้าf ( a ) f ( b ) ≥ 0 แล้ว ออกจากฟังก์ชันเนื่องจากรากไม่ได้อยู่ในวงเล็บ ถ้า| f ( a ) | < | f ( b )| แล้ว สลับ ( a , b ) ถ้าc := a ตั้งค่า mflag ทำซ้ำจนกว่าf ( bหรือs ) = 0 หรือ | b − a | เล็กพอ(การลู่เข้า) ถ้าf ( a ) ≠ f ( c ) และf ( b ) ≠ f ( c ) แล้ว( การแทรกสอดกำลังสองผกผัน ) มิฉะนั้น( วิธีซีแคนต์ ) สิ้นสุด ถ้า( เงื่อนไขที่ 1) s ไม่อยู่ระหว่างและbหรือ(เงื่อนไขที่ 2) (mflag ถูกตั้งค่าและ| s − b | ≥ | b − c |/2) หรือ(เงื่อนไขที่ 3) (mflag ถูกล้างและ| s − b | ≥ | c − d |/2) หรือ(เงื่อนไขที่ 4) (mflag ถูกตั้งค่าและ| b − c | < | δ |) หรือ(เงื่อนไขที่ 5) (mflag ถูกล้างและ| c − d | < | δ |) แล้ว( วิธีแบ่งครึ่ง ) ตั้งค่า mflag มิฉะนั้นล้าง mflag สิ้นสุด ถ้า คำนวณf ( s ) d := c (d ถูกกำหนดเป็นครั้งแรกที่นี่ จะไม่ถูกใช้ด้านบนในครั้งแรก) การวนซ้ำเนื่องจาก mflag ถูกตั้งค่า) c := b ถ้าf ( a ) f ( s ) < 0 แล้วb := s มิฉะนั้นa := s สิ้นสุดเงื่อนไข ถ้า| f ( a ) | < |f ( b )| จากนั้น สลับ ( a , b ) จบเงื่อนไขจบการทำซ้ำ แสดงผลb หรือ s (คืนค่าราก)
ตัวอย่าง
สมมติว่าเรากำลังหาค่าศูนย์ของฟังก์ชันที่กำหนดโดยf ( x ) = ( x + 3)( x − 1) 2
เราใช้[ a , b ] = [ − 4, 4/3]เป็นช่วงเริ่มต้นของเรา
เรามีf ( a ) = − 25 และf ( b ) = 0.48148 (ตัวเลขทั้งหมดในส่วนนี้ถูกปัดเศษ) ดังนั้นเงื่อนไขf ( a ) f ( b ) < 0 และ | f ( b )| ≤ | f ( a )| จึงเป็นไปตามที่กำหนด

- ในการวนซ้ำครั้งแรก เราใช้การประมาณค่าเชิงเส้นระหว่าง ( b , f ( b )) = ( a , f ( a )) = ( − 4, − 25) และ ( b , f ( b )) = (1.33333, 0.48148) ซึ่งให้ค่าs = 1.23256 ค่านี้อยู่ระหว่าง (3 a + b ) / 4 และb ดังนั้นค่านี้จึงเป็นที่ยอมรับได้ ยิ่งไปกว่านั้นf (1.23256) = 0.22891 ดังนั้นเราจึงกำหนดให้a = a และb = s = 1.23256
- ในการวนซ้ำครั้งที่สอง เราใช้การประมาณค่าแบบกำลังสองผกผันระหว่าง ( a , f ( a )) = ( − 4, − 25) และ ( b , f ( b )) = (1.33333, 0.48148) และ ( b , f ( b )) = (1.23256, 0.22891) ซึ่งจะได้ค่า 1.14205 ซึ่งอยู่ระหว่าง (3 a + b ) / 4 และb ยิ่งไปกว่านั้น อสมการ |1.14205 − b | ≤ | b − b | / 2 เป็นไปตามเงื่อนไข ดังนั้นค่านี้จึงได้รับการยอมรับ นอกจากนี้f (1.14205) = 0.083582 ดังนั้นเราจึงกำหนดให้a = a และb = 1.14205
- ในการวนซ้ำครั้งที่สาม เราใช้การประมาณค่าแบบกำลังสองผกผันระหว่าง ( a , f ( a )) = ( − 4, − 25) และ ( b , f ( b )) = (1.23256, 0.22891) และ ( b , f ( b )) = (1.14205, 0.083582) ซึ่งให้ผลลัพธ์เป็น 1.09032 ซึ่งอยู่ระหว่าง (3 a + b ) / 4 และb แต่เงื่อนไขเพิ่มเติมของ Brent มีผลบังคับใช้: อสมการ |1.09032 − b | ≤ | b − b | / 2 ไม่เป็นจริง ดังนั้นค่านี้จึงถูกปฏิเสธ แทนที่จะเป็นเช่นนั้น จุดกึ่งกลางm = − 1.42897 ของช่วง [ a , b ] จะถูกคำนวณ เรามีf ( m ) = 9.26891ดังนั้นเรากำหนดa3 = a2และ =
- ในการวนซ้ำครั้งที่สี่ เราใช้การประมาณค่าแบบกำลังสองผกผันระหว่าง ( a , f ( a )) = ( − 4, − 25) และ ( b , f ( b )) = (1.14205, 0.083582) และ ( b , f ( b )) = ( − 1.42897, 9.26891) ซึ่งให้ผลลัพธ์เป็น 1.15448 ซึ่งไม่อยู่ในช่วงระหว่าง (3 a + b ) / 4 และb ) ดังนั้นจึงแทนที่ด้วยจุดกึ่งกลางm = − 2.71449 เรามีf ( m ) = 3.93934 ดังนั้นเราจึงกำหนดa = a และb = − 2.71449
- ในการวนซ้ำครั้งที่ห้า การประมาณค่าแบบกำลังสองผกผันให้ผลลัพธ์เป็น − 3.45500 ซึ่งอยู่ในช่วงที่ต้องการ อย่างไรก็ตาม การวนซ้ำครั้งก่อนหน้านี้เป็นขั้นตอนการแบ่งครึ่ง ดังนั้นอสมการ | − 3.45500 − b | ≤ | b − b | / 2 จะต้องเป็นจริง อสมการนี้เป็นเท็จ ดังนั้นเราจึงใช้จุดกึ่งกลางm = − 3.35724 เรามีf ( m ) = − 6.78239 ดังนั้นmจึงกลายเป็นจุดตรงข้ามใหม่ ( a = − 3.35724) และค่าที่ได้จากการวนซ้ำยังคงเหมือนเดิม ( b = b )
- ในการวนซ้ำครั้งที่หก เราไม่สามารถใช้การประมาณค่าแบบกำลังสองผกผันได้ เนื่องจากb = b ดังนั้น เราจึงใช้การประมาณค่าเชิงเส้นระหว่าง ( a , f ( a )) = ( − 3.35724, − 6.78239) และ ( b , f ( b )) = ( − 2.71449, 3.93934) ผลลัพธ์คือs = − 2.95064 ซึ่งตรงตามเงื่อนไขทั้งหมด แต่เนื่องจากค่าที่ได้จากการวนซ้ำไม่ได้เปลี่ยนแปลงในขั้นตอนก่อนหน้า เราจึงปฏิเสธผลลัพธ์นี้และกลับไปใช้วิธีแบ่งครึ่งช่วง เราอัปเดตsเป็น− 3.03587 และf ( s ) = − 0.58418
- ในการวนซ้ำครั้งที่เจ็ด เราสามารถใช้การประมาณค่าแบบกำลังสองผกผันได้อีกครั้ง ผลลัพธ์คือs = − 3.00219 ซึ่งตรงตามเงื่อนไขทั้งหมด ตอนนี้f ( s ) = − 0.03515 ดังนั้นเราจึงกำหนดa = b และb = − 3.00219 ( มีการสลับ a และb เพื่อให้ตรงตามเงื่อนไข | f ( b )| ≤ | f ( a )|) ( ถูกต้อง : การประมาณค่าเชิงเส้น )
- ในการวนซ้ำครั้งที่แปด เราไม่สามารถใช้การประมาณค่าแบบกำลังสองผกผันได้ เนื่องจากa = b การประมาณค่าเชิงเส้นให้ผลลัพธ์เป็นs = − 2.99994 ซึ่งยอมรับได้ ( ถูกต้อง : )
- ในการวนซ้ำครั้งต่อไป ค่ารากx = − 3 จะเข้าใกล้มากขึ้นอย่างรวดเร็ว: b = − 3 + 6·10 − 8และb = − 3 − 3·10 − 15 ( ถูกต้อง : การวนซ้ำครั้งที่ 9 : f ( s ) = −1.4 × 10 −7การวนซ้ำครั้งที่ 10 : f ( s ) = 6.96 × 10 −12 )
การนำไปใช้
- Brent (1973)ได้เผยแพร่การใช้งานAlgol 60
- Netlibมีการแปลการใช้งานนี้เป็นภาษา Fortran โดยมีการปรับเปลี่ยนเล็กน้อย
- วิธีการPARI /GP
solveดำเนินการตามวิธีการดังกล่าว - ตัวอย่างการใช้งานอัลกอริธึมนี้ในรูปแบบอื่นๆ (ภาษา C++, C และ Fortran) สามารถพบได้ในหนังสือชุดNumerical Recipes
- ไลบรารีApache Commons Math นำอัลกอริทึมนี้ไปใช้งานในภาษาJava
- โมดูล optimize ของ SciPyนำอัลกอริทึมนี้ไปใช้ในภาษา Python (ภาษาโปรแกรม)
- ไลบรารีมาตรฐานของ Modelica ได้นำอัลกอริทึมนี้ไปใช้ในModelicaแล้ว
- ฟังก์ชัน นี้
unirootใช้โปรแกรมR ในการนำอัลกอริทึมไป ใช้ - ฟังก์ชัน นี้ ใช้ MATLAB
fzeroในการนำอัลกอริทึมไปใช้ - ไลบรารีBoost (C++)นำอัลกอริทึมสองแบบที่อิงตามวิธีการของ Brent มาใช้ในC++ในชุดเครื่องมือคณิตศาสตร์:
- การหาค่าต่ำสุดของฟังก์ชันที่minima.hppพร้อมตัวอย่าง การหาค่าต่ำ สุดของฟังก์ชัน
- การค้นหารากใช้ TOMS748 เวอร์ชันใหม่กว่า ซึ่งเป็นอัลกอริธึมที่ทันสมัยและมีประสิทธิภาพมากกว่าอัลกอริธึมดั้งเดิมของ Brent ที่TOMS748และการค้นหารากของ Boost.Mathที่ใช้TOMS748 ภายในพร้อมตัวอย่าง
- แพ็ก เกจ Optim.jlเป็นแพ็กเกจที่นำอัลกอริทึมนี้มาใช้งานในภาษาโปรแกรม Julia
- ระบบพีชคณิตคอมพิวเตอร์Emmy (เขียนด้วยภาษาโปรแกรม Clojure ) นำเสนอรูปแบบหนึ่งของอัลกอริธึมที่ออกแบบมาเพื่อการหาค่าต่ำสุดของฟังก์ชันตัวแปรเดียว
- ไลบรารี Root-Finding ในภาษา C# ที่โฮสต์อยู่ในCode Project
อ่านเพิ่มเติม
- Atkinson, Kendall E. (1989). "ส่วนที่ 2.8." บทนำสู่การวิเคราะห์เชิงตัวเลข ( ฉบับที่ 2). John Wiley and Sons. ISBN 0-471-50023-2.
- Press, WH; Teukolsky, SA; Vetterling, WT; Flannery, BP (2007). "ส่วนที่ 9.3 วิธีการของ Van Wijngaarden–Dekker–Brent" . สูตรการคำนวณเชิงตัวเลข: ศิลปะแห่งการคำนวณทางวิทยาศาสตร์ ( ฉบับที่ 3). นิวยอร์ก: สำนักพิมพ์มหาวิทยาลัยเคมบริดจ์. ISBN 978-0-521-88068-8เก็บถาวรจากต้นฉบับเมื่อวันที่ 11 สิงหาคม 2554 เรียกดูเมื่อวันที่ 28 กุมภาพันธ์ 2555
- อเลเฟลด์, จีอี; โปตรา เอฟเอ; Shi, Yixun (กันยายน 1995) "อัลกอริทึม 748: การล้อมศูนย์ของฟังก์ชันต่อเนื่อง " ธุรกรรม ACM บนซอฟต์แวร์ทางคณิตศาสตร์21 (3): 327– 344. ดอย : 10.1145/210089.210111 . S2CID 207192624 .
ลิงก์ภายนอก
- zeroin.fที่Netlib
- โมดูล brent ในภาษา C++ (รวมถึง C, Fortran, Matlab) เก็บถาวรเมื่อ 2018-04-05 ที่Wayback Machineโดย John Burkardt
- การใช้งานGSL
- การใช้งานBoost ในภาษา C++
- การใช้งานPython (Scipy)