পাইথনে মডুলার গুণিত বিপরীত ফাংশন


110

কিছু মানক পাইথন মডিউলটিতে গণনা করার জন্য কোনও ফাংশন রয়েছে মডুলার গুণনশীল বিপরীত একটি সংখ্যা, অর্থাত্ একটি সংখ্যা y = invmod(x, p)যেমন যে x*y == 1 (mod p)? গুগল এ সম্পর্কে কোনও ভাল ইঙ্গিত দেবে বলে মনে হয় না।

অবশ্যই, কেউ বাড়ানো ইউক্যালিডিয়ান অ্যালগোরিদমের 10-লাইনার ব্রেড নিয়ে আসতে পারেন তবে কেন চাকাটিকে পুনরায় উদ্ভাবন করতে হবে।

উদাহরণস্বরূপ, জাভার BigIntegerহয়েছে modInverseপদ্ধতি। পাইথনের কি তেমন কিছু নেই?


18
বিল্ট-ইন পাইথন 3.8 ইন (কারণে এই বছরের শেষের দিকে মুক্তি পেতে), আপনি ব্যবহার করতে সক্ষম হবেন powএই জন্য ফাংশন: y = pow(x, -1, p)Bugs.python.org/issue36027 দেখুন । স্ট্যান্ডার্ড লাইব্রেরিতে উপস্থিত একটি সমাধানের জন্য জিজ্ঞাসা করা প্রশ্ন থেকে এটি 8.5 বছর সময় নিয়েছে!
মার্ক ডিকিনসন

4
আমি @ মার্কডিকিনসনকে নম্রভাবে অবহেলা করতে দেখছি যে এই খুব দরকারী বর্ধনের লেখক, তাই আমি করব will এই কাজের জন্য ধন্যবাদ, মার্ক, এটি দুর্দান্ত দেখাচ্ছে!
ডন হ্যাচ

উত্তর:


128

হতে পারে যে কেউ এই দরকারী ( উইকিবুকগুলি থেকে ) পাবেন:

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)

def modinv(a, m):
    g, x, y = egcd(a, m)
    if g != 1:
        raise Exception('modular inverse does not exist')
    else:
        return x % m

1
এই অ্যালগরিদমটি ব্যবহার করে নেতিবাচক সংখ্যা নিয়ে আমার সমস্যা ছিল। modinv (-3, 11) কাজ করে না। আমি এই পিডিএফের দ্বিতীয় পৃষ্ঠায় এএসসিডি প্রতিস্থাপনের মাধ্যমে এটি সংশোধন করেছি: anh.cs.luc.edu/331/notes/xgcd.pdf আশা করি এটি সাহায্য করে!
কাজাজ

@ কাজ আপনি এইটিকে মোডিনভ (-3, 11) == মোডিনভ (-3 + 11, 11) == মোডিনভ (8, 11) এটিকে ইতিবাচক করতে কেবল -3 মডুলো 11 হ্রাস করতে পারবেন। এটি সম্ভবত আপনার পিডিএফের অ্যালগরিদমটি কিছু সময়ে ঘটবে।
থমাস

1
আপনি যদি ব্যবহার করে যাচ্ছেন sympy, তবে x, _, g = sympy.numbers.igcdex(a, m)কৌশলটি করে।
লিন

59

যদি আপনার মডুলাসটি প্রধান হয় (আপনি এটি কল করেন p) তবে আপনি কেবল গণনা করতে পারেন:

y = x**(p-2) mod p  # Pseudocode

বা পাইথনে যথাযথ:

y = pow(x, p-2, p)

এখানে এমন একজন যিনি পাইথনে কয়েকটি সংখ্যা তত্ত্বের ক্ষমতা প্রয়োগ করেছেন: http://www.math.umbc.edu/~campbell/Computers/Python/numbthy.html

এখানে প্রম্পটে একটি উদাহরণ দেওয়া হল:

m = 1000000007
x = 1234567
y = pow(x,m-2,m)
y
989145189L
x*y
1221166008548163L
x*y % m
1L

1
1000000007 বলার মতো কোনও যুক্তিসঙ্গত বড় মানের জন্য সময় (এবং স্মৃতি) সীমাবদ্ধতার কারণে
নিষ্কলুষ ক্ষুদ্রাকৃতির

16
মডুলার এক্সপেনসিয়েনশনটি সর্বাধিক এন * 2 গুণ দ্বারা সম্পন্ন হয় যেখানে এন বাহ্যকারের বিটের সংখ্যা। 2 ** 63-1 এর মডুলাস ব্যবহার করে বিপরীতটি প্রম্পটে গণনা করা যায় এবং তত্ক্ষণাত্ ফল দেয়।
phkahler

3
চমৎকার. আমি দ্রুত ক্ষয়ক্ষতি সম্পর্কে সচেতন, আমি কেবল সচেতন ছিলাম না যে পাও () ফাংশনটি তৃতীয় যুক্তি গ্রহণ করতে পারে যা এটিকে মডুলার বিস্ফোরণে পরিণত করে।
ডোরসার্গ

5
এজন্য আপনি পাইথনটি সঠিকভাবে ব্যবহার করছেন? কারণ এটি দুর্দান্ত :-)
phkahler

2
যাইহোক এটি কাজ করে কারণ ফার্মেটের থেকে সামান্য উপপাদ্য পাও (x, m-1, m) হতে হবে ১। m-2, m) হল x (মোড মি) এর বিপরীতমুখী।
পাইওটর ডাবকোভস্কি

21

আপনি জিএমপি মডিউলটিও দেখতে চাইতে পারেন । এটি পাইথন এবং GMP একাধিক-যথার্থ লাইব্রেরির মধ্যে একটি ইন্টারফেস। জিএমপি একটি বিপরীতমুখী ফাংশন সরবরাহ করে যা আপনার প্রয়োজনের মতো করে:

>>> import gmpy
>>> gmpy.invert(1234567, 1000000007)
mpz(989145189)

আপডেট উত্তর

@ হাই দ্বারা উল্লিখিত হিসাবে, gmpy.invert()বিপরীতটি বিদ্যমান না থাকলে 0 প্রদান করে। এটি জিএমপির mpz_invert()ফাংশনের আচরণের সাথে মেলে । gmpy.divm(a, b, m)এর একটি সাধারণ সমাধান সরবরাহ করে a=bx (mod m)

>>> gmpy.divm(1, 1234567, 1000000007)
mpz(989145189)
>>> gmpy.divm(1, 0, 5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: not invertible
>>> gmpy.divm(1, 4, 8)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: not invertible
>>> gmpy.divm(1, 4, 9)
mpz(7)

divm() যখন একটি সমাধান ফিরে আসবে gcd(b,m) == 1মাল্টিপ্লেসিটিভ ইনভার্সের অস্তিত্ব না থাকলে যখন এবং ব্যতিক্রম উত্থাপন করে।

দাবি অস্বীকার: আমি জিএমপি লাইব্রেরির বর্তমান রক্ষণাবেক্ষণকারী।

আপডেট উত্তর 2

বিপরীত উপস্থিত না থাকলে gmpy2 এখন সঠিকভাবে একটি ব্যতিক্রম উত্থাপন করে:

>>> import gmpy2

>>> gmpy2.invert(0,5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: invert() no inverse exists

gmpy.invert(0,5) = mpz(0)ত্রুটি বাড়ানোর পরিবর্তে আমি খুঁজে না পাওয়া পর্যন্ত এটি দুর্দান্ত ...
h__

@ কেন আপনি জিম্পির হোম পেজে এটিকে সমস্যা হিসাবে রিপোর্ট করতে পারেন? সমস্যাগুলি প্রতিবেদন করা হলে এটি সর্বদা প্রশংসাযোগ্য।
কেসভিএইচ

বিটিডাব্লু, এই gmpyপ্যাকেজে কোনও মডুলার গুণ রয়েছে ? (অর্থাত্ কিছু ফাংশন যার সমান মান রয়েছে তবে এর চেয়ে দ্রুততর (a * b)% p?)
h__

এটি আগে প্রস্তাবিত হয়েছিল এবং আমি বিভিন্ন পদ্ধতি নিয়ে পরীক্ষা-নিরীক্ষা করছি। ফাংশনটিতে কেবল গণনা করার সহজ পদ্ধিতি পাইথনের (a * b) % pমূল্যায়নের চেয়ে দ্রুত নয় (a * b) % p। ফাংশন কলের জন্য ওভারহেড এক্সপ্রেশন মূল্যায়নের ব্যয়ের চেয়ে বেশি is আরও তথ্যের জন্য কোড. google.com/p/gmpy/issues/detail?id=61 দেখুন ।
কেসভিএইচ

2
দুর্দান্ত জিনিসটি এটি নন-প্রাইম মডুলিগুলির জন্যও কাজ করে।
সিনেকডোচে

13

3.8 হিসাবে পাইথন পাও () ফাংশনটি একটি মডুলাস এবং negativeণাত্মক পূর্ণসংখ্যার নিতে পারে। এখানে দেখুন । এটি কীভাবে ব্যবহার করা যায় সে সম্পর্কে তাদের কেস

>>> pow(38, -1, 97)
23
>>> 23 * 38 % 97 == 1
True

8

কোডফাইটের জন্য এখানে একটি ওয়ান-লাইনার রয়েছে ; এটি সংক্ষিপ্ত সমাধানগুলির মধ্যে একটি:

MMI = lambda A, n,s=1,t=0,N=0: (n < 2 and t%N or MMI(n, A%n, t, s-A//n*t, N or n),-1)[n<1]

-1যদি Aকোনও গুণক বিপরীতমুখী না থাকে তবে এটি ফিরে আসবে n

ব্যবহার:

MMI(23, 99) # returns 56
MMI(18, 24) # return -1

সমাধানটি বর্ধিত ইউক্লিডিয়ান অ্যালগোরিদম ব্যবহার করে ।


6

সিম্পি , প্রতীকী গণিতের একটি অজগর মডিউল, আপনি যদি নিজের নিজস্ব প্রয়োগ করতে না চান (বা আপনি যদি ইতিমধ্যে সিম্পি ব্যবহার করছেন) তবে একটি অন্তর্নির্মিত মডুলার ইনভার্স ফাংশন রয়েছে:

from sympy import mod_inverse

mod_inverse(11, 35) # returns 16
mod_inverse(15, 35) # raises ValueError: 'inverse of 15 (mod 35) does not exist'

এটি সিম্পি ওয়েবসাইটে নথিবদ্ধ বলে মনে হচ্ছে না, তবে এখানে ডক্টর্টিং রয়েছে: গিথুবে সিম্পি মোড_আন্ট্রাস্ট ডক্ট্রিং


2

এখানে আমার কোড, এটি ম্লান হতে পারে তবে এটি আমার পক্ষে যেভাবে কাজ করবে বলে মনে হচ্ছে।

# a is the number you want the inverse for
# b is the modulus

def mod_inverse(a, b):
    r = -1
    B = b
    A = a
    eq_set = []
    full_set = []
    mod_set = []

    #euclid's algorithm
    while r!=1 and r!=0:
        r = b%a
        q = b//a
        eq_set = [r, b, a, q*-1]
        b = a
        a = r
        full_set.append(eq_set)

    for i in range(0, 4):
        mod_set.append(full_set[-1][i])

    mod_set.insert(2, 1)
    counter = 0

    #extended euclid's algorithm
    for i in range(1, len(full_set)):
        if counter%2 == 0:
            mod_set[2] = full_set[-1*(i+1)][3]*mod_set[4]+mod_set[2]
            mod_set[3] = full_set[-1*(i+1)][1]

        elif counter%2 != 0:
            mod_set[4] = full_set[-1*(i+1)][3]*mod_set[2]+mod_set[4]
            mod_set[1] = full_set[-1*(i+1)][1]

        counter += 1

    if mod_set[3] == B:
        return mod_set[2]%B
    return mod_set[4]%B

2

উপরের কোডটি পাইথন 3 তে চলবে না এবং জিসিডি ভেরিয়েন্টের তুলনায় কম দক্ষ is তবে এই কোডটি খুব স্বচ্ছ। এটি আরও কমপ্যাক্ট সংস্করণ তৈরি করতে আমাকে ট্রিগার করেছিল:

def imod(a, n):
 c = 1
 while (c % a > 0):
     c += n
 return c // a

1
এটি বাচ্চাদের এবং কখন কখন তা ব্যাখ্যা করা ঠিক n == 7। তবে অন্যথায় এটি এই "অ্যালগরিদম" এর সমতুল্য:for i in range(2, n): if i * a % n == 1: return i
টমসজ গ্যান্ডোর

2

এখানে একটি সংক্ষিপ্ত 1-লাইনার যা কোনও বাহ্যিক গ্রন্থাগার ব্যবহার না করে এটি করে।

# Given 0<a<b, returns the unique c such that 0<c<b and a*c == gcd(a,b) (mod b).
# In particular, if a,b are relatively prime, returns the inverse of a modulo b.
def invmod(a,b): return 0 if a==0 else 1 if b%a==0 else b - invmod(b%a,a)*b//a

মনে রাখবেন যে এটি সত্যই কেবল এসসিডি, কেবলমাত্র একক সুদের আগ্রহের জন্য প্রবাহিত।


1

মডিউলার গুণক বিপরীতটি বের করার জন্য আমি বর্ধিত ইউক্লিডিয়ান অ্যালগোরিদমকে এভাবে ব্যবহার করার পরামর্শ দিই:

def multiplicative_inverse(a, b):
    origA = a
    X = 0
    prevX = 1
    Y = 1
    prevY = 0
    while b != 0:
        temp = b
        quotient = a/b
        b = a%b
        a = temp
        temp = X
        a = prevX - quotient * X
        prevX = temp
        temp = Y
        Y = prevY - quotient * Y
        prevY = temp

    return origA + prevY

এই কোডে একটি বাগ উপস্থিত হতে পারে: a = prevX - quotient * Xহওয়া উচিত X = prevX - quotient * X, এবং এটি ফেরত পাঠাবেন prevX। এফডাব্লুআইডাব্লু, এই প্রয়োগটি মের্ট বখোফের উত্তরের মন্তব্যে কাজলের লিঙ্কের অনুরূপ ।
প্রধানমন্ত্রী 2 রিং

1

আমি এই থ্রেড থেকে বিভিন্ন সমাধান চেষ্টা করি এবং শেষ পর্যন্ত আমি এটি ব্যবহার করি:

def egcd(a, b):
    lastremainder, remainder = abs(a), abs(b)
    x, lastx, y, lasty = 0, 1, 1, 0
    while remainder:
        lastremainder, (quotient, remainder) = remainder, divmod(lastremainder, remainder)
        x, lastx = lastx - quotient*x, x
        y, lasty = lasty - quotient*y, y
    return lastremainder, lastx * (-1 if a < 0 else 1), lasty * (-1 if b < 0 else 1)


def modinv(a, m):
    g, x, y = self.egcd(a, m)
    if g != 1:
        raise ValueError('modinv for {} does not exist'.format(a))
    return x % m

পাইথনে মডুলার_আনভারস


1
এই কোডটি অবৈধ। returnegcd এ ভুল উপায়ে চাপ দেওয়া হয়
ph4r05

0

ঠিক আছে, পাইথনে আমার কোনও ফাংশন নেই তবে আমার সিতে একটি ফাংশন রয়েছে যা আপনি সহজেই পাইথনে রূপান্তর করতে পারেন, নীচের সি ফাংশনে বর্ধিত ইউক্লিডিয়ান অ্যালগরিদম বিপরীত মোড গণনা করতে ব্যবহৃত হয়।

int imod(int a,int n){
int c,i=1;
while(1){
    c = n * i + 1;
    if(c%a==0){
        c = c/a;
        break;
    }
    i++;
}
return c;}

পাইথন ফাংশন

def imod(a,n):
  i=1
  while True:
    c = n * i + 1;
    if(c%a==0):
      c = c/a
      break;
    i = i+1

  return c

দুটি তুলনামূলকভাবে মৌলিক সংখ্যার মডিউলার গুণক বিপরীতমুখীকরণের জন্য নীচের লিঙ্ক সি প্রোগ্রাম থেকে উপরের সি কার্যকারিতাটির রেফারেন্স নেওয়া হয়েছে


0

সিপিথন বাস্তবায়ন উত্স কোড থেকে :

def invmod(a, n):
    b, c = 1, 0
    while n:
        q, r = divmod(a, n)
        a, b, c, n = n, c, b - q*c, r
    # at this point a is the gcd of the original inputs
    if a == 1:
        return b
    raise ValueError("Not invertible")

এই কোডটির উপরের মতামত অনুসারে, এটি ছোট নেতিবাচক মানগুলি ফিরিয়ে আনতে পারে, যাতে আপনি সম্ভাব্যভাবে নেতিবাচক কিনা তা পরীক্ষা করে দেখতে পারেন এবং খ ফেরত দেওয়ার আগে নেতিবাচক হলে এন যুক্ত করতে পারেন।


"সুতরাং আপনি সম্ভবত নেতিবাচক কিনা তা পরীক্ষা করে দেখতে পারেন এবং খ ফেরত দেওয়ার আগে নেতিবাচক হলে এন যোগ করতে পারেন"। দুর্ভাগ্যক্রমে n এ 0 হয়। (আপনাকে এন এর আসল মান সংরক্ষণ করতে এবং ব্যবহার করতে হবে)
ডন হ্যাচ

-2

উপরের লিঙ্কগুলির অনেকগুলি 1/23/2017 হিসাবে ভাঙ্গা। আমি এই প্রয়োগটি পেয়েছি: https://courses.csail.mit.edu/6.857/2016/files/ffield.py


শুধুমাত্র উত্তরগুলি লিঙ্ক এড়িয়ে চলুন। আপনি যেমন আপনার ইমেলের কথা বলেছেন, লিঙ্কগুলি বিরতি পেতে পারে।
জেফ

সেই মডিউলটির লেখক এমিন মার্টিনিয়ান এটিকে পাইপি.পাইথন.আর.পি.পি.পি.পি.ফিনটাইম
ড্যান ডি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.