2025, Oct 18 10:31
SymPy में Abs(cos(x))/sqrt(cos(x)**2) 1 क्यों नहीं बनता और समाधान
SymPy में Abs(cos(x))/sqrt(cos(x)**2) 1 क्यों नहीं बनता, जानें। parse_expr के local_dict, सही assumptions (real/positive) और अभिव्यक्ति-आधारित subs से समाधान पाएं.
जब प्रतीकात्मक गणित की लाइब्रेरीज़ "बहुत शाब्दिक" ढंग से काम करती हैं, तो वजह अक्सर खोई हुई मान्यताओं (assumptions) या मेल न खाते प्रतीकों तक सिमट जाती है। SymPy में एक आम स्थिति है: उम्मीद रहती है कि Abs(cos(x))/sqrt(cos(x)**2) सरल होकर 1 बन जाएगा, पर परिणाम वही मूल अभिव्यक्ति लौट आती है। असल कारण और समाधान दोनों ही सीधे हैं—बस पता होना चाहिए कि ध्यान कहाँ देना है।
समस्या को पुनः उत्पन्न करना
नीचे दिया गया स्निपेट मान्यताओं सहित एक प्रतीक बनाता है और फिर स्ट्रिंग अभिव्यक्ति को पार्स करता है। उम्मीद 1 देखने की रहती है, मगर अभिव्यक्ति सरल नहीं होती और स्ट्रिंग के रूप में सीधा प्रतिस्थापन भी बेअसर रहता है।
from sympy import Symbol, parse_expr, simplify
ang = Symbol('ang', positive=True, real=True)
src = '1*Abs(cos(ang))/sqrt(cos(ang)**2)'
expr = parse_expr(src)
failed = expr.subs("Abs(cos(ang))/sqrt(cos(ang)**2)", "1")
# expr अभी भी Abs(cos(ang))/sqrt(cos(ang)**2) जैसा ही दिखता है
# failed अप्रभावित है, कोई प्रतिस्थापन नहीं हुआ
सरलीकरण क्यों नहीं होता
मुख्य बात यह है कि parse_expr तब तक आपके पहले से घोषित प्रतीक के बारे में नहीं जानता जब तक आप उसे बता न दें। वह स्ट्रिंग में ang नाम देखता है और चुपचाप बिना किसी मान्यता के नया Symbol("ang") बना देता है। यह नया प्रतीक डिफ़ॉल्ट रूप से वास्तविक (real) नहीं होता, और मान्यताएँ न होने पर Abs(cos(ang))/sqrt(cos(ang)**2) को 1 में घटाया नहीं जा सकता। इसके उलट, x/x जटिल (complex) x के लिए भी सरल हो जाता है, इसलिए वह मामला अलग तरह से व्यवहार करता है।
प्रतिस्थापन कॉल में दूसरी मुश्किल भी है। जब subs को पहला तर्क स्ट्रिंग मिलता है, तो वह उसे एक एकल प्रतीक में बदल देता है, अभिव्यक्ति-वृक्ष में नहीं। आपकी अभिव्यक्ति में ऐसा कोई एकल प्रतीक है ही नहीं, इसलिए कुछ भी नहीं बदला जाता। बेहतर है कि subs को SymPy अभिव्यक्तियाँ या संख्याएँ दी जाएँ।
दो संबंधित टिप्पणियाँ इस व्यवहार को स्पष्ट करती हैं। पहली, sqrt(x**2) == Abs(x) की समानता तभी मान्य है जब x वास्तविक हो; सामान्य जटिल प्रतीकों के साथ यह बराबरी मान्य नहीं रहती, क्योंकि sqrt में शाखा-कट (branch cut) का मुद्दा आता है। दूसरी, डिफ़ॉल्ट रूप से SymPy के प्रतीक complex माने जाते हैं, जब तक आप real=True या positive=True जैसी मान्यताएँ न दें; इसलिए वे सरलीकरण, जो वास्तविकता पर निर्भर हैं, अपने आप नहीं चलेंगे।
समाधान: अपने मौजूदा प्रतीक को पार्सर से बाँधें
parse_expr को local_dict दें ताकि वह पहले से घोषित प्रतीक को उसकी मान्यताओं सहित पुनः उपयोग करे। ऐसा करते ही अभिव्यक्ति अपेक्षित रूप से 1 बन जाती है। साथ ही, प्रतिस्थापन स्ट्रिंग्स नहीं, अभिव्यक्तियों के जरिए करें।
from sympy import Symbol, parse_expr
ang = Symbol('ang', positive=True, real=True)
src = '1*Abs(cos(ang))/sqrt(cos(ang)**2)'
expr_ok = parse_expr(src, local_dict={'ang': ang})
# expr_ok का मान 1 है
# यदि आप खास तौर पर प्रतिस्थापन-पैटर्न चाहते हैं, तो स्ट्रिंग्स नहीं, अभिव्यक्तियाँ पास करें
pattern = parse_expr('Abs(cos(ang))/sqrt(cos(ang)**2)', local_dict={'ang': ang})
replaced = expr_ok.subs(pattern, 1)
# replaced का मान 1 है
यदि किसी कारण पार्सिंग के दौरान स्वत: मूल्यांकन से बचना हो, तो parse_expr को evaluate=False के साथ बुलाया जा सकता है, हालांकि ऊपर बताए समाधान के लिए यह आवश्यक नहीं है।
यह बारीकी क्यों मायने रखती है
बीजगणितीय समकक्षता-जाँच, नियम-आधारित परिवर्तन और स्वचालित सरलीकरण—ये सब संगत प्रतीकों और सही डोमेन-मान्यताओं पर टिके होते हैं। यदि पार्सर बिना मान्यताओं के नया प्रतीक गढ़ दे, तो वास्तविक-विषयक पहचानें लागू नहीं होंगी और समकक्षता-जाँच चुपचाप विफल हो सकती है। उसी तरह, subs में स्ट्रिंग्स मिलाने से ऐसे प्लेसहोल्डर बनते हैं जो दिखने में समान लगते हैं, पर कभी मेल ही नहीं खाते।
मुख्य बातें
पार्सिंग के समय नामों को स्पष्ट रूप से बाँधें ताकि बनी हुई अभिव्यक्ति आपके मौजूदा प्रतीकों और उनकी मान्यताओं का पुन: उपयोग करे। जब आप केवल वास्तविक संख्याओं पर मान्य पहचानों पर निर्भर हों, तो प्रतीकों को real या positive घोषित करें। संरचनात्मक मिलान सुनिश्चित करने के लिए subs में स्ट्रिंग्स नहीं, SymPy अभिव्यक्तियाँ दें। इन सावधानियों के साथ, Abs(cos(x))/sqrt(cos(x)**2) जैसी अभिव्यक्तियाँ ठीक उसी समय 1 में सरल होती हैं जब उन्हें होना चाहिए, और आपका प्रतीकात्मक कार्यप्रवाह अनुमानित बना रहता है।