Dirichlet Convolution


20

La convolution de Dirichlet est un type spécial de convolution qui apparaît comme un outil très utile dans la théorie des nombres. Il opère sur l'ensemble des fonctions arithmétiques .

Défi

Étant donné deux fonctions arithmétiques f,g (c'est-à-dire les fonctions ), calculer la convolution de Dirichlet comme défini ci-dessous.f,g:NR ( f g ) : NR (fg):NR

Détails

  • On utilise la convention 0N={1,2,3,} .
  • La convolution de Dirichlet fg de deux fonctions arithmétiques f,g est à nouveau une fonction arithmétique, et elle est définie comme
    (fg)(n)=d|nf(nd)g(d)=ij=nf(i)g(j).
    (Les deux sommes sont équivalentes. L'expressiond|nsignifie quedNdivisen, donc la somme est sur lesdiviseursnaturelsde n. De même, nous pouvons substitueri=ndN,j=dNet nous obtenons la deuxième formulation équivalente. Si vous n'êtes pas habitué à cette notation, il y a un exemple étape par étape ci-dessous.) Juste pour élaborer (ce n'est pas directement pertinent pour ce défi): La définition vient du calcul du produit de lasérie Dirichlet:
    (nNf(n)ns)(nNg(n)ns)=nN(fg)(n)ns
  • L'entrée est donnée sous forme de deux fonctions de boîte noire . Alternativement, vous pouvez également utiliser une liste infinie, un générateur, un flux ou quelque chose de similaire qui pourrait produire un nombre illimité de valeurs.
  • Il existe deux méthodes de sortie: Soit une fonction fg est retournée, soit vous pouvez prendre une entrée supplémentaire nN et renvoyer (fg)(n) directement.
  • Pour simplifier, vous pouvez supposer que chaque élément de N peut être représenté avec, par exemple, un entier 32 bits positif.
  • Pour simplifier, vous pouvez également supposer que chaque entrée R peut être représentée par exemple par un seul nombre réel à virgule flottante.

Exemples

Définissons d'abord quelques fonctions. Notez que la liste des nombres sous chaque définition représente les premières valeurs de cette fonction.

  • l'identité multiplicative ( A000007 )
    ϵ(n)={1n=10n>1
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
  • la fonction d'unité constante ( A000012 )
    1(n)=1n
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
  • la fonction d'identité ( A000027 )
    id(n)=nn
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, ...
  • la fonction de Möbius ( A008683 )
    μ(n)={(1)k if n is squarefree and k is the number of Primefactors of n0 otherwise 
    1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, ...
  • la fonction de totient d'Euler ( A000010 )
    φ(n)=np|n(11p)
    1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8, ...
  • la fonction de Liouville ( A008836 )
    λ(n)=(1)k
    k est le nombre de facteurs premiers de n comptés avec multiplicité 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, ...
  • la fonction de somme des diviseurs ( A000203 )
    σ(n)=d|nd
    1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, 24, 31, 18, 39, 20, ...
  • la fonction de comptage des diviseurs ( A000005 )
    τ(n)=d|n1
    1, 2, 2, 3, 2, 4, 2, 4, 3, 4, 2, 6, 2, 4, 4, 5, 2, 6, 2, 6, 4, 4, 2, 8, ...
  • la fonction caractéristique des nombres carrés ( A010052 )
    sq(n)={1 if n is a square number0otherwise
    1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, ...

Ensuite, nous avons les exemples suivants:

  • ϵ=1μ
  • f=ϵff
  • ϵ=λ|μ|
  • σ=φτ
  • id=σμ etσ=id1
  • sq=λ1 et λ=μsq
  • τ=11 et 1=τμ
  • id=φ1 et φ=idμ

Les derniers pour sont une conséquence de l' inversion de Möbius : pour tout f,g l'équation g=f1 est équivalente à f=gμ .

Exemple étape par étape

Il s'agit d'un exemple calculé étape par étape pour ceux qui ne connaissent pas la notation utilisée dans la définition. Considérons les fonctions f=μ et g=σ . Nous allons maintenant évaluer leur convolution μσ à n=12 . Leurs premiers termes sont répertoriés dans le tableau ci-dessous.

ff(1)f(2)f(3)f(4)f(5)f(6)f(7)f(8)f(9)f(10)f(11)f(12)μ111011100110σ134761281513181228

La somme itère sur tous les nombres naturels dN qui divisent n=12 , donc d suppose tous les diviseurs naturels de n=12=223 . Ce sont d=1,2,3,4,6,12 . Dans chaque somme, nous évaluons g=σ en d et le multiplions parf=μ évalué ennd . Nous pouvons maintenant conclure

(μσ)(12)=μ(12)σ(1)+μ(6)σ(2)+μ(4)σ(3)+μ(3)σ(4)+μ(2)σ(6)+μ(1)σ(12)=01+13+04+(1)7+(1)12+128=0+310712+28=12=id(12)

Réponses:


5

Lean , 108 100 95 78 75 octets

def d(f g:_->int)(n):=(list.iota n).foldr(λd s,ite(n%d=0)(s+f d*g(n/d))s)0

Essayez-le en ligne!

Plus de tests avec toutes les fonctions.


est lambda vraiment plus cher que quatre octets fun ?
Mario Carneiro

lambda est de trois octets, je suppose
Leaky Nun

Je pense que c'est deux en UTF8 (le grec est unicode assez bas)
Mario Carneiro

Tu as raison. J'ai également joué à l'importation
Leaky Nun

J'ai également utilisé condpour économiser 5 octets
Leaky Nun

4

Haskell , 46 octets

(f!g)n=sum[f i*g(div n i)|i<-[1..n],mod n i<1]

Essayez-le en ligne!

Merci à flawr pour -6 octets et un grand défi! Et merci à H.PWiz pour un autre -6!


Plus simple est plus court ici
H.PWiz

@ H.PWiz C'est assez intelligent - je n'ai même pas pensé à le faire de cette façon!
Mego

3

Python 3 , 59 octets

lambda f,g,n:sum(f(d)*g(n//d)for d in range(1,n+1)if 1>n%d)

Essayez-le en ligne!


Est-ce //vraiment nécessaire au lieu de /?
M. Xcoder

/produirait des flotteurs à droite?
Leaky Nun

Parce que dc'est un diviseur de npar définition, la partie fractionnaire de n/dest zéro, donc il ne devrait pas y avoir de problème avec l'arithmétique à virgule flottante. Les flottants avec une partie fractionnaire nulle sont assez proches des ints à des fins Pythoniques, et la sortie de la fonction est un nombre réel, donc faire n/dau lieu de n//ddevrait être bien.
Mego


2

Ajouter ++ , 51 octets

D,g,@~,$z€¦~¦*
D,f,@@@,@b[VdF#B]dbRzGb]$dbL$@*z€g¦+

Essayez-le en ligne!

Prend deux fonctions prédéfinies comme arguments, plus net sorties (Fg)(n)

Comment ça fonctionne

D,g,		; Define a helper function, $g
	@~,	; $g takes a single argument, an array, and splats that array to the stack
		; $g takes the argument e.g. [[τ(x) φ(x)] [3 4]]
		; STACK : 			[[τ(x) φ(x)] [3 4]]
	$z	; Swap and zip:			[[3 τ(x)] [4 φ(x)]]
	€¦~	; Reduce each by execution:	[[τ(3) φ(4)]]
	¦*	; Take the product and return:	τ(3)⋅φ(4) = 4

D,f,		; Define the main function, $f
	@@@,	; $f takes three arguments: φ(x), τ(x) and n (Let n = 12)
		; STACK:			[φ(x) τ(x) 12]
	@	; Reverse the stack:		[12 τ(x) φ(x)]
	b[V	; Pair and save:		[12]			Saved: [τ(x) φ(x)]
	dF#B]	; List of factors:		[[1 2 3 4 6 12]]
	dbR	; Copy and reverse:		[[1 2 3 4 6 12] [12 6 4 3 2 1]]
	z	; Zip together:			[[[1 12] [2 6] [3 4] [4 3] [6 2] [12 1]]]
	Gb]	; Push Saved:			[[[1 12] [2 6] [3 4] [4 3] [6 2] [12 1]] [[τ(x) φ(x)]]]
	$dbL	; Number of dividors:		[[[τ(x) φ(x)]] [[1 12] [2 6] [3 4] [4 3] [6 2] [12 1]] 6]
	$@*	; Repeat:			[[[1 12] [2 6] [3 4] [4 3] [6 2] [12 1]] [[τ(x) φ(x)] [τ(x) φ(x)] [τ(x) φ(x)] [τ(x) φ(x)] [τ(x) φ(x)] [τ(x) φ(x)]]]
	z	; Zip:				[[[τ(x) φ(x)] [1 12]] [[τ(x) φ(x)] [2 6]] [[τ(x) φ(x)] [3 4]] [[τ(x) φ(x)] [4 3]] [[τ(x) φ(x)] [6 2]] [[τ(x) φ(x)] [12 1]]]
	€g	; Run $g over each subarray:	[[4 4 4 6 4 6]]
	¦+	; Take the sum and return:	28

2

R , 58 octets

function(n,f,g){for(i in (1:n)[!n%%1:n])F=F+f(i)*g(n/i)
F}

Essayez-le en ligne!

Prend n, fet g. Heureusement, le numberspaquet a déjà un certain nombre de fonctions implémentées.

Si des versions vectorisées étaient disponibles, ce qui est possible en enveloppant chacune Vectorize , la version suivante de 45 octets est possible:

R , 45 octets

function(n,f,g,x=1:n,i=x[!n%%x])f(i)%*%g(n/i)

Essayez-le en ligne!


2

APL (Dyalog Classic) , 20 octets

{(⍺⍺¨∘⌽+.×⍵⍵¨)∪⍵∨⍳⍵}

avec ⎕IO←1

Essayez-le en ligne!

Facile à résoudre, difficile à tester - généralement pas mon type de défi. Pourtant, j'ai beaucoup apprécié celui-ci!

{ }définit un opérateur dyadique dont les opérandes ⍺⍺et ⍵⍵les deux fonctions sont convolués; est l'argument numérique

∪⍵∨⍳⍵sont les diviseurs de dans l'ordre croissant, c'est-à-dire unique ( ) des LCM ( ) de avec tous les nombres naturels jusqu'à ( )

⍵⍵¨ appliquer l'opérande droit à chaque

⍺⍺¨∘⌽ appliquer l'opérande gauche à chacun en sens inverse

+.× produit intérieur - multiplier les éléments correspondants et additionner


La même chose dans ngn / apl semble meilleure en raison des identificateurs Unicode, mais prend 2 octets supplémentaires en raison de l'indexation 1.


Je suis sûr que cela prend 27 octets supplémentaires dans ngn / apl ...
Erik the Outgolfer



1

JavaScript (ES6), 47 octets

Prend l'entrée comme (f)(g)(n).

f=>g=>h=(n,d=n)=>d&&!(n%d)*f(n/d)*g(d)+h(n,d-1)

Essayez-le en ligne!

Exemples

liouville =
n => (-1) ** (D = (n, k = 2) => k > n ? 0 : (n % k ? D(n, k + 1) : 1 + D(n / k, k)))(n)

mobius =
n => (M = (n, k = 1) => n % ++k ? k > n || M(n, k) : n / k % k && -M(n / k, k))(n)

sq =
n => +!((n ** 0.5) % 1)

identity =
n => 1

// sq = liouville * identity
console.log([...Array(25)].map((_, n) => F(liouville)(identity)(n + 1)))

// liouville = mobius * sq
console.log([...Array(20)].map((_, n) => F(mobius)(sq)(n + 1)))

1

C (gcc) , 108 octets

#define F float
F c(F(*f)(int),F(*g)(int),int n){F s=0;for(int d=0;d++<n;)if(n%d<1)s+=f(n/d)*g(d);return s;}

Implémentation simple, volée sans vergogne à la réponse Python de Leaky Nun .

Non golfé:

float c(float (*f)(int), float (*g)(int), int n) {
    float s = 0;
    for(int d = 1; d <= n;++d) {
        if(n % d == 0) {
            s += f(n / d) * g(d);
        }
    }
    return s;
}

Essayez-le en ligne!


1

F #, 72 octets

let x f g n=Seq.filter(fun d->n%d=0){1..n}|>Seq.sumBy(fun d->f(n/d)*g d)

Prend les deux fonctions fet get un nombre naturel n. Filtre les valeurs dqui ne se divisent pas naturellement n. Ensuite, les évalue f(n/d) et les g(d)multiplie et résume les résultats.



0

APL (NARS), 47 caractères, 94 octets

{(m⍵[1])×n⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}

où m et n sont la fonction que l'on doit utiliser (ceci parce que je ne sais pas comment appeler un tableau de fonction dans une fonction dans APL). En utilisant l'exemple ci-dessus, la multiplication de la fonction Mobius (ici, c'est 12π) et la fonction somme des diviseurs (ici, c'est 11π) pour la valeur 12, cette multiplication serait:

  {(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}12
12

si l'on doit calculer une autre valeur:

  {(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}1002
1002
  {(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}1001
1001
  {(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}20000x
20000 

On peut voir si par exemple le premier nombre 2000 le résultat de la fonction est l'identité

  (⍳2000)≡{(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}¨⍳2000
1
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.