Veri ering av forskningsresultat gällande antal lösningar för linjära

2013:12
Veriering av forskningsresultat gällande
antal lösningar för linjära kongruenssystem
Uno Sörensson
Master Thesis in Mathematics, 30 credits
Dec 2013
Blekinge Institute of Technology
School of Engineering
Deparment of Mathematics and Science
Supervisor: Robert Nyqvist
Innehåll
1 Uppdrag och bakgrund
2
1.1
Sammanfattning
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
1.2
Introduktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
1.3
Linjära kongruenser . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.4
System av linjära kongruenser . . . . . . . . . . . . . . . . . . . . .
8
2 Genomförande
9
2.1
Inledning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2
Arbetsgång
2.3
Bestämning av antal lösningar
2.4
Lösning av linjära kongruenssystem med två och tre obekanta
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
η.
. . . . . . . . . . . . . . . . . . .
. . .
3 Avslutning
3.1
3.2
3.3
9
9
10
13
21
Sammanfattning och resultat av genomförda test
. . . . . . . . . .
21
3.1.1
Sammanfattning av test
. . . . . . . . . . . . . . . . . . . .
21
3.1.2
Resultat . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
3.2.1
CountSolutions.java . . . . . . . . . . . . . . . . . . . . . . .
22
3.2.2
OneSolution.java
28
3.2.3
CountWithGamma.java
3.2.4
CountSolCorr.java
. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
32
. . . . . . . . . . . . . . . . . . . . . . .
41
. . . . . . . . . . . . . . . . . . . .
53
3.3.1
Exempel på programkörningar.
ResCountSolutions.txt
. . . . . . . . . . . . . . . . . . . . .
53
3.3.2
ResOneSolution.txt . . . . . . . . . . . . . . . . . . . . . . .
54
3.3.3
ResCountWithGamma.txt . . . . . . . . . . . . . . . . . . .
56
3.3.4
ResCountSolCorr.txt . . . . . . . . . . . . . . . . . . . . . .
56
Litteraturförteckning
58
1
1
Uppdrag och bakgrund
1.1
Sammanfattning
Kongruenser har använts praktiskt sedan lång tid, men det var först på 1800talet som matematiker som Gauss, Fermat och Euler systematiskt studerade och
utvecklade kongruensteorin. Sedan dess har kongruensteori varit en viktig del av
talteorin.
Nilsson och Nyqvist [1] har teoretiskt visat att för system av linjära kongruenser
med
n
obekanta
Ax ≡ b (mod pk )
n × n-matris med heltalselement samt x och b vektorer med n help ett primtal och k ett heltal, gäller att antalet lösningar är
nk
η = sgd(det(A), p ), under förutsättning att p inte delar det(A). Vår uppgift har
varit att för den homogena ekvationen (b = 0) veriera formeln för η för n = 2
och n = 3. Vi har gjort detta med hjälp av dator och program i programspråket
där A är en
talskomponenter,
Java.
1.2
Introduktion
Teorin för kongruenser utvecklades i början av artonhundratalet av den tyske matematikern Karl Friedrich Gauss, en av historiens mest berömda matematiker.
Även andra matematiker, som Fermat och Euler har arbetat med kongruensteori.
Kongruenser förekommer i vardagslivet. Klockan t.ex arbetar modulo
för timmar och modulo
60
12
eller
24
7
för minuter och sekunder. Almanackan har modulo
för veckodagarna och modulo
12
för månaderna.
Denition: Låt m vara ett positivt heltal. Om a och b är heltal, säger vi att a är
kongruent med
kongruent med
b modulo m om m delar (a − b),
b modulo m, skriver vi
vilket skrivs
m | (a − b).
Om
a
är
a ≡ b (mod m).
Exempel 1.
22 ≡ 4 (mod 9), för 9 | (22 − 4). På samma sätt gäller
att 3 ≡ −6 (mod 9), eftersom 9 | (3 − (−6)), men det gäller att 13 6≡ 5 (mod 9),
eftersom 9 - (13 − 5).
Det gäller att
2
När vi arbetar med kongruenser, behöver vi ibland översätta dem till likheter.
Följande sats hjälper oss att göra detta.
Sats 1.
Om
ett heltal
k,
a
och
så att
b är heltal, så
a = b + km.
är
a ≡ b (mod m)
om och endast om det nns
a ≡ b (mod m), så gäller att m | (a − b). Detta betyder att det nns
k med km = a − b, så att a = b + km. Omvänt gäller att om det nns
k med a = b + km, så gäller att km = a − b, och följaktligen, a ≡ b
Bevis. Om
ett heltal
ett heltal
(mod m).
Sats 2.
Låt m vara ett heltal. Kongruenser modulo m har följande egenskaper.
1. Reexiv: Om
a
är ett heltal så gäller att
2. Symmetrisk: Om
a
och
b
a ≡ a (mod m).
är heltal sådana att
a ≡ b (mod m),
så gäller att
b ≡ a (mod m).
a, b, och c är heltal
a ≡ c (mod m).
3. Transitiv: Om
så gäller att
med
a ≡ b (mod m)
och
b ≡ c (mod m),
Bevis.
1. Vi ser att
a ≡ a (mod m),
eftersom
a−a=0
och
m | 0.
a ≡ b (mod m), så gäller att m | (a − b). Detta betyder att det nns ett
heltal k med km = a − b. Detta visar att (−km) = b − a, så att m | (b − a).
Följaktligen gäller att b ≡ a (mod m).
2. Om
a ≡ b (mod m) och b ≡ c (mod m), så gäller att m | (a − b) och
m | (b − c). Då nns det heltal k och l sådana att km = a − b och lm = b − c.
Av detta fås a − c = (a − b) + (b − c) = km + lm = (k + l)m, vilket ger att
m|(a − c) och a ≡ c (mod m).
3. Om
Sats
2
medför att heltalen delas upp i
m
disjunkta delmängder (partitioner), ek-
vivalensklasser. För kongruens är benämningen kongruensklasser.
3
Låt m vara ett positivt heltal. Enligt divisionsalgoritmen kan alla heltal a skrivas
på formen a
≡
mq
+r
där
0 <=
r
<
m och där kvoten q
och r är entydigt
bestämda.
Exempel 2.
Om t.ex. m
≡ 4,
så tillhör varje heltal a exakt en av de fyra kongru-
ensklasserna modulo 4
· · · ≡ −8 ≡ −4 ≡ 0 ≡ 4 ≡ 8 ≡ · · · (mod 4)
· · · ≡ −7 ≡ −3 ≡ 1 ≡ 5 ≡ 9 ≡ · · · (mod 4)
· · · ≡ −6 ≡ −2 ≡ 2 ≡ 6 ≡ 10 ≡ · · · (mod 4)
· · · ≡ −5 ≡ −1 ≡ 3 ≡ 7 ≡ 11 ≡ · · · (mod 4).
Man utför ofta aritmetik med kongruenser. Detta kallas moduloaritmetik. Kongruenser har många av de egenskaper som likheter har.
Sats 3.
Addition, subtraktion och multiplikation bevarar kongruensen. Om
c
är heltal, med
och
m
m > 0,
1.
a + c ≡ b + c (mod m)
2.
a − c ≡ b − c (mod m)
3.
ac ≡ bc (mod m).
sådana att
a ≡ b (mod m),
a, b ,
så gäller att
Bevis.
1.
a ≡ b (mod m) ger som vi vet att m | (a − b).
(a − b), innebär att m | ((a + c) − (b + c)).
2. följer av att
3.
Identiteten
(a + c) − (b + c) =
(a − c) − (b − c) = a − b.
ac − bc = c(a − b) och eftersom m | (a − b), föjer att m | (c(a − b)) och ac ≡ bc
(mod m).
Denition: Låt a och b vara heltal, varav minst ett av dem är skilt från 0. Det
största heltal som delar både
b, och betecknas
sgd(a, b).
a
och
b
kallas största gemensamma delare till a och
Vi denierar
sgd(0, 0) = 0.
4
Följande sats, som är mer generell än föregående sats, är också användbar
Sats 4.
Om
(mod m),
a, b , c , d
och
m
är heltal, med
m > 0, a ≡ b (mod m),
och
c≡d
så gäller att
1.
a + c ≡ b + d (mod m)
2.
a − c ≡ b − d (mod m)
3.
ac ≡ bd (mod m).
Bevis.
1.
a ≡ b (mod m)
c ≡ d (mod m), ger att m | (a − b) och m | (c − d).
Då nns det heltal k och l med km = (a − b) och lm = (c − d). Detta ger
(a + c) − (b + d) = (a − b) + (c − d) = km + lm = (k + l)m. Därför gäller att
m | [((a + c) − (b + d)], det vill säga (a + c) ≡ (b + d) (mod m).
2.
(a − c) − (b − d) = (a − b) − (c − d) = km − lm = (k − l)m,
m | [((a − c) − (b − d)], så att (a − c) ≡ (b − d) (mod m).
3.
ac − bd = ac − bc + bc − bd = c(a − b) + b(c − d) = ckm + blm = m(ck + bl).
Därför gäller att m | (ac − bd) och ac ≡ bd (mod m).
och
därför gäller att
Följande sats och lemma behövs i den följande framställningen
Sats 5. Om a, b, m och n är heltal, och om c | a och c | b, så gäller att c | (ma+nb).
c | a och c | b, så nns det heltal e och f sådana att a = ce
b = cf . Följaktligen, ma + nb = mce + ncf = c(me + nf ). Alltså gäller att
c | (ma + nb).
Bevis. Eftersom
och
Lemma 1.
Om
a, b , c
är positiva heltal och
sgd(a, b) = 1
och
a | bc
så gäller att
a | c.
sgd(a, b) = 1, så nns det heltal x och y sådana att ax + by = 1.
Enligt Sats 5 gäller att a | (acx + bcy) eftersom acx + bcy är en linjär kombination
av a och bc, vilka båda delas av a. Alltså gäller att a | c.
Bevis. Eftersom
5
För att kongruensen skall bevaras vid division, måste följande villkor uppfyllas.
Sats 6
. Om a, b, c och m är heltal sådana
ac ≡ bc (mod m), så gäller att a ≡ b (mod m/d).
(Divisionsregeln)
sgd(c, m)
och
att
m > 0, d =
ac ≡ bc (mod m), vet vi att m | (ac − bc) = c(a − b).Därför nns
k sådant att c(a − b) = km. Om vi dividerar båda sidor med d, får
vi (c/d)(a − b) = k(m/d). Eftersom sgd(m/d, c/d) = 1, fås enligt Lemma 1, att
m/d | (a − b). Därför gäller att a ≡ b (mod m/d).
Bevis. Om
det ett heltal
Denition: Det minsta positiva heltal m sådant att a|m och b|m kallas för minsta
gemensamma multipel för a och b, där a och b är heltal, betecknas
mgm(a, b).
Sats 7.
positiva. Om
a, b, m1 , m2 , . . . , mk vara heltal med m1 , m2 , · · · , mk
a ≡ b (mod m1 ),a ≡ b (mod m2 ),. . . , a ≡ b (mod mk ),så gäller att
Låt
a ≡ b (mod [m1 , m2 , · · · , mk ])
m = [m1 , m2 , . . . , mk ], det vill säga minsta gemensamma multipeln för heltalen
m1 , m2 , . . . , mk
där
Denition: Två heltal a och b sägs vara relativt prima om det gäller att sgd(a, b) =
1.
Följdsats 1.
är heltal och
a ≡ b (mod m1 ), a ≡ b (mod m2 ),. . . ,a ≡ b (mod mk ), där a,b
m1 , m2 , . . . , mk är parvis relativt prima positiva heltal, så gäller att
Om
a≡b
eftersom
1.3
Låt
(mod m1 m2 . . . mk )
[m1 , m2 , . . . , mk ] = m1 m2 . . . mk
i detta fall.
Linjära kongruenser
a, b
och
m
vara heltal, där
m > 1.
En kongruens på formen
ax ≡ b (mod m)
kallas en linjär kongruens i en obekant
x.
Att studera linjära kongruenser är nära
förknippat med studier av linjära diofantiska ekvationer med två variabler. Vi
x = x0 är en lösning till kongruensen ax ≡ b (mod m), och
om x1 ≡ x0 (mod m), så är ax1 ≡ ax0 ≡ b (mod m), dvs x1 är också en lösning.
Följaktligen, om en medlem av en kongruensklass modulo m är en lösning, så är
noterar först att om
alla medlemmar i denna klass också lösningar. Därför kan vi fråga hur många av
6
de
m
kongruensklasserna modulo
m
som ger lösningar. Detta är detsamma som
att fråga hur många inkongruenta lösningar modulo
m
det nns. Följande sats
talar om för oss när en linjär kongruens i en variabel har lösningar, och om så är
fallet, ger den oss exakt antalet inkongruenta lösningar modulo
Sats 8.
m.
a, b och m vara heltal, sådana att m > 0 och sgd(a, m) = d. Om
d inte delar b, så har ax ≡ b (mod m) inga lösningar. Om d | b, så har ax ≡ b
(mod m) exakt d inkongruenta lösningar modulo m. Om x0 är en lösning, så nns
det exakt sgd(a, m) inkongruenta lösningar och dessa ges av
Låt
x = x0 +
där
m
·k
sgd(a, m)
k = 0, 1, . . . , sgd(a, m) − 1
ax ≡ b (mod m)är ekvivalent med den linjära
diofantiska ekvationen i två variabler ax − my = b. Heltalet x är en lösning till
ax ≡ b (mod m) om och endast om det nns ett heltal y sådant att ax − my = b.
Man kan visa att om d = sgd(a, m) inte delar b så nns inga lösningar, men om
d|b har ax − my = b oändligt många lösningar. Dessa lösningar ges av samtliga
kongruensklasser modulo d. För varje kongruensklass gäller att x = x0 + (m/d)t,
t = 0, 1, . . . , sgd(a, m) − 1. För det fullständiga beviset se Rosen [2].
Bevisskiss. Den linjära kongruensen
Följdsats 2.
Om
a
och
m
är relativt prima heltal med
så gäller att den linjära kongruensen
ax ≡ b (mod m)
m>0
och
b
är ett heltal,
har exakt en lösning.
sgd(a, m) = 1, vet vi att sgd(a, m) | b. Av sats 8 följer då
ax ≡ b (mod m) har exakt sgd(a, m) = 1 inkongruenta lösningar modulo m.
Bevis. Eftersom
att
Exempel 3. Vi vill nna alla lösningar till 9x ≡ 12 (mod 15). Eftersom sgd(9, 15) =
3 och 3 | 12 nns det exakt tre inkongruenta lösningar. Vi kan nna dessa lösningar
genom att först nna en speciell lösning och sedan addera lämpliga multiplar av
15/3 = 5.
För att nna en speciell lösning, betraktar vi den linjära diofantiska ekvationen
9x − 15y = 12.
Euklides algoritm visar att
15 = 9 · 1 + 6
9=6·1+3
6=3·2+0
3 = 9 − 6 · 1 = 9 − (15 − 9 · 1) · 1 = 9 · 2 − 15. Härav följer att 9 · 8 − 15 · 4 = 12,
och en speciell lösning ges av x0 = 8 och y0 = 4.
Totala antalet inkongruenta lösningar är tre. Dessa är x = x0 ≡ 8 (mod 15),
x = x0 + 5 ≡ 13 (mod 15), och x = x0 + 5 · 2 ≡ 18 ≡ 3 (mod 15).
så att
7
Denition: ax ≡ 1 (mod m) har exakt en lösning, om sgd(a, m) = 1. Lösningen
betecknas
a−1
och kallas för den multiplikativa inversen för
a är den multiplikativa inversen
ax ≡ b (mod m), ges av x ≡ a−1 · b (mod m).
nitionen följer att
till
1.4
modulo
a modulo m. Av dem till a−1 . Lösningen
System av linjära kongruenser
System av linjära kongruenser är system med mer än en kongruens, och som innehåller samma antal obekanta som antalet kongruenser. Alla kongruenser har
samma modulus. Låt
m
och
n
vara positiva heltal, med
m > 1
och
n > 1.
Ett
system av linjära kongruenser har det generella utseendet


a11 x1 + a12 x2 + . . . + a1n xn ≡ b1 (mod m)



a21 x1 + a22 x2 + . . . + a2n xn ≡ b2 (mod m)
.
.

.



a x + a x + . . . + a x ≡ b (mod m)
n1 1
n2 2
nn n
n
där alla
aij
och
bi
är heltal. I litteraturen beskrivs olika metoder för att lösa system
av linjära kongruenser. Dessa metoder påminner om metoder som används för att
lösa linjära ekvationssystem inom linjär algebra, som Gauss elimineringsmetod och
Cramers regel.
(Jfr.: Kinesiska restklassatsen med vars hjälp man under vissa villkor kan lösa
system av kongruenser med olika modulus.)
8
2
Genomförande
2.1
Inledning
Nilsson och Nyqvist [1] har i inledningen till sin forskningsrapport Number of
Solutions of Linear Congruence Systems angett syftet med sitt arbete och tidigare
forskning inom området. Författarna har bland annat teoretiskt visat att antalet
lösningar
η för ett system av linjära kongruenser med n obekanta Ax ≡ 0 (mod m)
det(A) och m.
under vissa förutsättningar är en funktion av
Vår uppgift har varit att manuellt och med hjälp av datorprogram veriera
denna del av resultaten i rapporten. I rapporten behandlas modulus som utgörs av
k
primtal p, eller potenser av primtal p , där k är ett godtyckligt positivt heltal. Detta
eftersom varje heltal
i > 2, som inte är ett primtal, kan delas upp i primtalsfaktorer.
I rapporten behandlas både homogena och inhomogena linjära kongruenser
med
n
obekanta, med
n > 1.
I vårt uppdrag ingår endast att undersöka homo-
gena linjära system av kongruenser med
n = 2 och
= sgd(det(A), pk ),
skriver att om
ηp k
att
n = 2
och
n = 3.
Nilsson och Nyqvist
p gäller
nk
att ηpnk = sgd(det(A), p ).
nk−γ
i rapporten, ηγ = p
, där
någon koecient i A är relativt prima med
för övriga system gäller
Ytterligare en formel för beräkning av
η
presenters
γ = l0 + l1 + l2 . γ
beräknas med hjälp av Gauss-eliminering. Nilsson och Nyqvist
nk−γ
beskriver formeln ηγ = p
för det allmänna fallet i avsnitt 3 i sin rapport. En
detaljerad beskrivning av beräkning av
η
för
n = 2 och n = 3 ges
i avsnitt
2.3.
All
programmering har skett i programspråket Java.
2.2
Arbetsgång
Vi inleder arbetet med att ta fram alla lösningar för ett system med
n=2
n = 3
Resultaten
och samtidigt räkna lösningarna, samt beräknar
ηp k
och
ηpnk .
eller
sparas på en textl. Program: CountSolutions.java. Detta program är dock så
krävande avseende datorkraft och minne att man endast kan välja relativt små
värden (mindre än
10)
på
p
och
k
för att inte orimligt långa exekveringstider
skall erhållas. För att kunna testa med större värden på
lösningar
η
för ett specikt system för
p
och
k
räknar vi antalet
n = 2 eller n = 3 och beräknar ηpk och ηpnk .
ηγ på ett specikt system med n = 3.
Program: OneSolution.java. Vi testar sedan
Program: CountWithGamma.java. Slutligen genererar vi slumpmässigt ett valfritt
antal system och för varje system räknas antalet lösningar
ηγ
η,
och
ηpk , ηpnk
och
beräknas. Antalet rätta värden för vardera formeln summeras och presenteras
tillsammans med siran på antalet räknade lösningar (= rätt antal lösningar). Alla
resultat sparas på en textl. Program: CountSolCorr.java.
9
2.3
Bestämning av antal lösningar
η.
Algoritm.
η.
A. Icke-selektiv algoritm för att räkna antal lösningar
1. Läs in ett värde på antal obekanta
2. Läs in värde på
p
och
n, 2
eller
3.
k.
3. Öppna en textl.
Zpk = {0, 1, . . . , pk − 1}
4. För varje matris A med element ur
(a) Sätt räknare för lösningar
η=0
x i Znpk
k
Om Ax ≡ 0 (mod p ), sätt η = η + 1.
Skriv ut koecienterna för A samt x
(b) För varje
i.
ii.
(c) Beräkna
det(A), ηpk = sgd(det(A), pk )
(d) Skriv ut
η , det(A), ηpk
och
ηpnk
och
ηpnk = sgd(det(A), pnk )
på textlen.
5. Stäng textlen när alla matriser A har behandlats.
Programmet för att icke-selektivt räkna antal lösningar, CountSolutions.java nns
i avsnitt
3.1.1.
B. Selektiv algoritm för att räkna antal lösningar
1. Läs in ett värde på
2. Läs in värde på
p
n
och
(antal obekanta: 2 eller 3).
k.
3. Läs in värden på koecienterna
4. Beräkna
ai,j
i
n × n-matrisen
(a) Sätt räknare för lösningar
Zpk = {0, 1, . . . , pk − 1}.
η=0
x i Znpk
k
Om Ax ≡ 0 (mod p ), sätt η = η + 1.
(b) För varje
(c) Beräkna antalet lösningar
6. Skriv ut
A.
det(A).
5. För den inlästa matrisen A med element ur
i.
η.
det(A),η , ηpk ,
och
ηp k
och
ηpnk .
10
ηpnk .
Programmet för att selektivt räkna antal lösningar, OneSolution.java nns i avsnitt
3.1.2.
C. Selektiv algoritm för att räkna antal lösningar med
1. Läs in en
3 × 3-matris
A, samt värden på
2. Om samtliga element är delbara med
e
från A och reducera modulo med p 0 .
3. Beräkna l0
4. Sätt
pe 0
p
ηγ .
och
k.
, där
e0
Algoritm för
n = 3.
är ett heltal, bryt ut
pe0
= k − e0 .
γ = l0 .
5. Finn en koecient
aij ,
sådan att
sgd(aij , pk ) = 1.
6. Placera denna koecient i rad och kolonn
1
i matrisen, med eventuella rad-
och kolonnbyten.
7. Bestäm den multiplikativa inversen
a−1
ij
till
aij .
−1
8. Multiplicera rad 1 med aij och ai,1 samt addera till rad
−1
k
gäller att aij · aij ≡ 1 (mod p ).
9. Vi kan nu betrakta de fyra koecienterna på rad
3
som en
2×2
3
och
där
i = 2, 3.
Det
2
och
samt kolonn
-matris, låt oss kalla den R.
10. Om samtliga element rij i R är delbara med
e
e
ut p 1 från R och reducera modulo med p 1 .
11. Beräkna l1
2
i,
pe1
, där
e1
är ett heltal, bryt
= l0 − e1 .
12. Finn en koecient
rij ,
sådan att
sgd(rij , pk ) = 1.
13. Placera denna koecient i rad och kolonn
1
i matrisen, med eventuella rad-
och kolonnbyten.
14. Bestäm den multiplikativa inversen
−1
15. Multiplicera rad 1 med rij och
−1
k
gäller att rij · rij ≡ 1 (mod p ).
−1
rij
ri,1
till
rij .
samt addera till rad
16. Efter omformningen av matrisen R, så har vi i rad
1
skild från 0, låt oss kalla den r22 .
17. Skapa l2 på
e2 = 0.
1
r22
:
1
r22
= 0, sätt e2 = k − l0 − l1 .
1
1
delar r22 , sätt e2 = r22 /p.
Om
Om Om p
11
2
i,
där
i = 2.
Det
endast en koecient
Om
1
sgd(r22
, p) = 1,
sätt
18. Bilda
γ = l0 + l1 + l2 .
19. Beräkna antal lösningar =
pnk−γ .
Programmet för att beräkna antalet lösningar för linjära kongruenssystem med tre
obekanta, med
ηγ
CountWithGamma.java nns i avsnitt
3.1.3.
ηpk , ηpnk
(n = 3).
D. Algoritm för att testa formlerna för beräkning av
antal system med slumpgenererade koecienter
och
ηγ
på ett bestämt
1. Läs in ett värde på antal system som skall genereras
2. Läs in värde på
p
och
k.
3. Öppna en textl.
(a) Räkna antal system som genereras.
(b) För varje genererad matris A med element ur
det(A).
ηγ (Se algoritmen C).
η , ηpk och ηpnk (Se algoritmen
Zpk = {0, 1, . . . , pk − 1}
i. Beräkna
ii. Bestäm
iii. Bestäm
B).
iv. Skriv ut värdena på textlen
(c) Summera antal korrekta värden för
ηpk , ηpnk
och
ηγ .
4. Skriv ut de summerade värdena på textlen.
5. Stäng textlen.
Programmet för att testa formlerna för beräkning av
ηpk , ηpnk
och
ηγ
på ett bestämt
antal system med slumpgenererade koecienter CountSolCorr.java nns i avsnitt
3.1.4.
12
2.4
Lösning av linjära kongruenssystem med två och tre
obekanta
n = 2 och
n = 3 görs
Nedan beskriver vi en metod för att lösa linjära kongruenssystem med
n = 3.
Metoden bygger på Gausseliminering från linjär algebra. För
en reducering av systemet till
n = 2,
lösande av detta system, samt återgång till
n = 3, där lösningen av systemet med n = 2 används för att få fram värden på den
tredje obekanta variabeln. Vid lösning med dator används en algoritm som följer
denna metod. Vi önskar lösa följande system av linjära kongruenser:

a11 x1 + a12 x2 + a13 x3 ≡ 0
a21 x1 + a22 x2 + a23 x3 ≡ 0

a31 x1 + a32 x2 + a33 x3 ≡ 0
där
ai,j
och
k
är heltal, samt
(mod pk )
(mod pk )
(mod pk ),
p
är ett godtyckligt primtal. I stället för att arbeta i
t
systemet direkt arbetar vi med det i matrisform. Sätt A = (ai,j ),
= (x1 , x2 , x3 )
t
och
= (0, 0, 0). Då kan systemet skrivas i matrisform på följande sätt:
x
0
Ax ≡ 0 (mod pk )
där

a11 a12 a13
A = a21 a22 a23  .
a31 a32 a33

13
A. Metod för lösning för hand.
n = 3,
1. För ett givet system med
2. Vi kontrollerar om
sgd(aij , pk )
skriver vi upp matrisen A.
=
1
aij .
för något
element för vilket detta gäller måste vi bryta ut
påverkar lösningen av systemet. Se Exempel
(Om vi inte nner något
pl ,
där
0 < l < k.
Detta
6).
3. Genom omyttningar, som vi dokumenterar, byter vi eventuellt
a11
mot det
funna elementet.
−1
4. Vi tar nu fram den multiplikativa inversen a11 till vårt nya
k
plicerar första raden med denna modulo p .
a11 ,
och multi-
5. Efter omyttningar och bearbetningar betecknar vi matriselementen
varablerna
0
0
x1 , x2
och
0
x3
vi i matrisens andra rad har eliminerat
0
0
a22
pk ,
så att
och i rad tre har eliminerat
0
a31
a32 .
7. I rad tre i systemet har vi nu
0
k
8. Om det gäller att sgd(a33 , p )
0
k
sgd(a33 , p ) lösningar.
0
0
a33 x3 ≡ 0 (mod pk ).
= 1,
har
0
x3
9. Genom att lösa den diofantiska ekvationen
lösning på
0
x3 ,
nämligen
10. Övriga lösningar är
sats
och
.
6. Vi tillämpar nu Gausseliminering med hänsyn tagen till modulus
och
0
aij
0
endast lösningen
0
a33 x3 − (pk )y = 0
annars nns
får vi fram en
x3 = x0 .
0
x3 = x0 +
6.
pk
0
k
k,
k
=
0,
1,
.
.
.
,
sgd(a
0
33 , p ) − 1.
sgd(a33 , pk )
11. Insättning av det funna värdet/värdena på
eller era värden på
0
0,
0
0
x3
Se
i rad två i systemet ger ett
x2 .
12. Insättning av dessa värden i rad ett i systemet och omyttning till ursprungsordningen och bestämning av
x1
ger slutresultatet.
14
Exempel 5. Vi vill lösa följande linjära kongruenssystem (n = 3, p = 3, k = 3).

3

3x1 + 26x2 + 2x3 ≡ 0 (mod 3 )
15x1 + 23x2 + 1x3 ≡ 0 (mod 33 )


24x1 + 17x2 + 4x3 ≡ 0 (mod 33 ).
Vi skriver om systemet på formen
x ≡ 0 (mod pk )
A
och får


3 26 2
A = 15 23 1
24 17 4
Vi låter kolonn
1
och
3
byta plats för att
matrisen blir
2
är relativt prima med
27.
Den nya


2 26 3
B = 1 23 15
4 17 24
Vi tar nu fram den multiplikativa inversen till
2x ≡ 1
Vi multiplicerar rad
1
med
(mod 27)
14
ger
2
x ≡ 14
(mod 27).
och får matrisen


1 13 15
C = 1 23 15
4 17 24
1 från rad 2 och rad 3 så att matrisen får följande


1 13 15
0
D = 0 10
0 19 18
Vi subtraherar multiplar av rad
utseende
Vi får nu ett specialfall, eftersom andra koecienten i rad
lösa ut
3
är
0.
Vi kan direkt
x2 .
10x2 ≡ 0
Rad
1
(mod 27)
och
sgd(10, 27) = 1
ger att
x2 ≡ 0
ger
18x1 ≡ 0
(mod 27)
och
15
η = sgd(18, 27) = 9.
(mod 27).
1 och 3.
x1 ≡ 0 (mod 27), resterande lösningar ges av
27
k, k = 0, 1, 2, . . . , sgd(18, 27) − 1.
x1 = 0 +
sgd(18, 27)
rad 1 i matrisen A ger
Observera att vi bytte plats på kolonn
En lösning är
Insättning i
2x3 ≡ −3x1
x3 ≡ 14 · 24x1
Insättning av lösningarna för
x1
3x1 + 0 + 2x3 ≡ 0 (mod 27)
(mod 27) ≡ 24x1 (mod 27)
(mod 27) ≡ 12x1 (mod 27)
ger
x3 ≡ 12 · 0
x3 ≡ 12 · 3 (mod 27) ≡ 36
x3 ≡ 12 · 6 (mod 27) ≡ 72
x3 ≡ 12 · 9 (mod 27) ≡ 108
x3 ≡ 12 · 12 (mod 27) ≡ 144
x3 ≡ 12 · 15 (mod 27) ≡ 180
x3 ≡ 12 · 18 (mod 27) ≡ 216
x3 ≡ 12 · 21 (mod 27) ≡ 252
x3 ≡ 12 · 24 (mod 27) ≡ 288
Lösningarna för
x3
(mod 27) ≡ 0
(mod 27) ≡ 9
(mod 27) ≡ 18
(mod 27) ≡ 0
(mod 27) ≡ 9
(mod 27) ≡ 18
(mod 27) ≡ 0
(mod 27) ≡ 9
(mod 27) ≡ 18
är:
x3 ≡ 0 (mod 27)
x3 ≡ 9 (mod 27)
x3 ≡ 18 (mod 27)
Lösningarna för det givna systemet är:
x1
x2
x3
0
0
0
3
0
9
6
0
18
9
0
0
12
0
9
15
0
18
18
0
0
21
0
9
24
0
18
16
(mod
(mod
(mod
(mod
(mod
(mod
(mod
(mod
(mod
27)
27)
27)
27)
27)
27)
27)
27)
27)
Exempel 6. Vi vill lösa följande linjära kongruenssystem (n = 3, p = 3, k = 2).


6x1 + 6x2 + 3x3 ≡ 0
3x1 + 6x2 + 3x3 ≡ 0


3x1 + 3x2 + 3x3 ≡ 0
(mod 32 )
(mod 32 )
(mod 32 ).
Vi skriver om systemet på formen
x ≡ 0 (mod pk )
A
och får


6 6 3
A = 3 6 3
3 3 3
Vi ser genast att ingen koecient är relativt prima med
9.
Vi bryter ut
3,
och får
en ny matris


2 2 1
B = 1 2 1
1 1 1
Vi låter rad
1
och rad
och en gång till rad
3
3
byta plats, samt adderar nya rad
1
två gånger till rad
2
och får matrisen


1 1 1
0
C = 0 1
0 0 22
Motsvarande kongruenssystem är


x 1 + x 2 + x 3
x2


2x3
≡0
≡0
≡0
(mod 3)
(mod 3)
(mod 3).
Vi får
x2 = 0 ∈ Z3
och x3 = 0 ∈ Z3 ,
ef tersom sgd(1, 3) = 1 och sgd(2, 3) = 1.
Vi måste nu lyfta dessa värden till
värdena
0, 3
och
6
i
Z9 .
Z9 .
17
Det gäller att
0
i
Z3
svarar mot de tre
Möjliga lösningar
(., 0, 0), (., 0, 3), (., 0, 6)
(., 3, 0), (., 3, 3), (., 3, 6)
(., 6, 0), (., 6, 3), (., 6, 6)
där punkten svarar mot värden på
x1 ,
som vi ska nna.
Vi skriver om första raden i det ursprungliga kongruenssystemet
6x1 ≡ −6x2 − 3x3
Vi har att
sgd(6, 9) = 3,
(mod 32 ) ≡ 3x2 + 6x3
det vill säga att varje parentes i Möjliga lösningar ovan
ger upphov till tre lösningar.
(., 0, 0)
ger
6x1 ≡ 3 · 0 + 6 · 0 (mod 32 ) ≡ 0 (mod 32 )
6 · 0 ≡ (mod 32 )ger(0, 0, 0)
6 · 3 ≡ (mod 32 )ger(3, 0, 0)
6 · 6 ≡ (mod 32 )ger(6, 0, 0)
(., 3, 0)
ger
(mod 32 ).
6x1 ≡ 3 · 3 + 6 · 0 (mod 32 ) ≡ 0 (mod 32 )
6 · 0 ≡ (mod 32 )ger(0, 3, 0)
6 · 3 ≡ (mod 32 )ger(3, 3, 0)
6 · 6 ≡ (mod 32 )ger(6, 3, 0)
På samma sätt fås de övriga lösningarna.
18
Lösningarna för det givna systemet är:
x1
x2
x3
0
0
0
0
0
3
0
0
6
0
3
0
0
3
3
0
3
6
0
6
0
0
6
3
0
6
6
3
0
0
3
0
3
3
0
6
3
3
0
3
3
3
3
3
6
3
6
0
3
6
3
3
6
6
6
0
0
6
0
3
6
0
6
6
3
0
6
3
3
6
3
6
6
6
0
6
6
3
6
6
6
19
B. Programmering och testkörning
I projektet ingår att ta reda på och visa rätt värde på antalet lösningar, samt att
testa formler för beräkning av värden på antalet lösningar. I programmen CountSolutions.java och OneSolution.java visas också lösningarna. I 3.3 visas exempel på
resultat från testkörningar.
20
3
Avslutning
3.1
Sammanfattning och resultat av genomförda test
3.1.1 Sammanfattning av test
Fyra olika test har genomförts med hjälp av datorprogram.
1. För samtliga linjära kongruenssystem med
n=2
och
n=3
har vi räknat
antal lösningar där både koecienter och värden på de obekanta tillåts anta
k
alla värden i mängden {0, 1, . . . , p − 1}. För varje system beräknas antalet
k
nk
lösningar med formlerna ηpk = sgd(det(A), p ) och ηpnk = sgd(det(A), p ).
Alla resultat sparas på en textl. På grund av att antalet data som testas
snabbt ökar med stigande värde på
för små värden på
p
och
k
p
och
k,
kan metoden endast användas
(mindre än10). Program: CountSolutions.java.
2. För att kunna testa med större värden på
p och k görs ett test där man räknar
antalet lösningar för ett linjärt kongruenssystem med två eller tre obekanta
(valbart i programmet), där de obekanta tillåts anta alla värden i mängden
{0, 1, . . . , pk −1} för en uppsättning koecienter i mängden {0, 1, . . . , pk −1},
som läses in från tangentbordet. Program: OneSolution.java.
3. Beräkning av antalet lösningar för ett linjärt kongruenssystem med tre obenk−γ
kanta med ηγ = p
, där γ = l0 + l1 + l2 . γ beräknas med hjälp av Gaussk
eliminering. Systemets koecienter som tillåts ligga i mängden {0, 1, . . . , p −
1}
samt
p
och
k
läses in från tangentbordet. Program: CountWithGam-
ma.java.
4. I programmet CountSolCorr.java slumpgenererar vi
matriser för tre obekanta.
m
m
stycken koecient-
läses in från tangentbordet. Vi bestämmer för
varje matris rätt antal lösningar och beräknar sedan antalet lösningar med
k
nk
nk−γ
formlerna ηpk = sgd(det(A), p ), ηpnk = sgd(det(A), p ), samt ηγ = p
,
där
γ = l0 + l1 + l2 .
Resultatet läggs i en textl.
γ
beräknas med hjälp av
Gauss-eliminering. Program: CountSolCorr.java.
3.1.2 Resultat
1. När
det(A) 6= 0
ger både
2. När
det(A) = 0
blir
ηγ
ηpk , ηpnk
rätt,
ηpnk
och
ηγ
fel, och
21
rätt värde på antal lösningar.
ηpk
blir rätt när
sgd(A, p) = 1.
3.2
Program
3.2.1 CountSolutions.java
import java.util.*;
import java.io.*;
import java.lang.*;
public class CountSolutions {
// Program:CountSolutions.java
/*
För varje system (matris A), testar vi alla kombinationer
av x och y och räknar antalet lösningar(count_solutions).
För varje matris som ger lösning skriver vi ut matrisen A
(n=2: koeff. a,b,c,d; n=3: koeff. abcdefgho) och värdena på
variablerna(x,y),determinanten för A och count_solutions =
rätt antal lösningar för A samt de beräknade värdena för
antalet lösningar eta_pk = sgd(detA,(int)Math.pow(p,k)) och
eta_pnk = sgd(detA,(int)Math.pow(p,(n*k))) på en textfil
respk.txt. Testen kan göras för n = 2 och n = 3.
*/
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
int n = 0; //systemstorlek
int p = 0; //primtal
int k = 0; //exponent -"22
int
int
int
int
int
int
int
int
x = 0; //systemvariabel
y = 0; // -"z = 0; // -"_
detA = 0;
eta_pk = 0;
eta_pnk = 0;
count_solutions = 0; //antal lösningar för ett system
total_solutions = 0; //totalt antal lösningar
System.out.print("Ange storleken n (2 eller 3)");
System.out.println(" på system-matrisen A: ");
n = keyboard.nextInt();
int[][] a = new int[n][n];
System.out.print("Skriv ett primtal p: ");
p = keyboard.nextInt();
System.out.print("Skriv ett heltal k: ");
k = keyboard.nextInt();
keyboard.nextLine(); //töm bufferten
System.out.println ("Skriv ett filnamn: ");
String fileName = keyboard.nextLine();
if(n == 2)
{
try
{
PrintWriter out = new PrintWriter(fileName);
//rubrik på textfilen resnpk.txt
out.println("Resultatfil resnpk.txt, skapad");
out.println("med n = "+n+", p = "+p+" och k = "+k);
out.println("Program: CountSolutions.java");
out.println();
23
out.println(" a,
b, c,
d, x, y");
out.println("_____________________________");
out.println();
for(a[0][0]=0;a[0][0]<(int)Math.pow(p,k);a[0][0]++)
for(a[0][1]=0;a[0][1]<(int)Math.pow(p,k);a[0][1]++)
for(a[1][0]=0;a[1][0]<(int)Math.pow(p,k);a[1][0]++)
for(a[1][1]=0;a[1][1]<(int)Math.pow(p,k);a[1][1]++)
{
count_solutions = 0;
detA = det_a(a,n);
eta_pk = sgd(detA,(int)Math.pow(p,k));
eta_pnk = sgd(detA,(int)Math.pow(p,(n*k)));
for( x = 0; x < Math.pow(p,k); x++)
for( y = 0; y < Math.pow(p,k); y++)
if((((a[0][0]*x +a[0][1] *y) % Math.pow(p,k))== 0)
&& (((a[1][0]*x + a[1][1]*y)% Math.pow(p,k))== 0))
{
count_solutions++;
String param = ("a= "+a[0][0]+" b= "+a[0][1]
+" c= "+a[1][0]+" d= "+a[1][1]
+" x= "+x+" y= "+y);
out.println(param);
}
String result = ("Antal lösningar = "
+count_solutions+", det(A)= "+detA
+", eta_pk = "+eta_pk+", eta_pnk = "+eta_pnk);
out.println(result);
}
total_solutions = total_solutions + count_solutions;
out.println("Totalt antal lösningar för p = "+p
+" och k = "+k+": "+total_solutions);
24
//stäng filen
out.close();
}
catch(Exception w)
{
System.out.println("Kunde inte spara filen");
w.printStackTrace();
}
}
if(n == 3)
{
try
{
PrintWriter out = new PrintWriter(fileName);
//rubrik på textfilen resnpk.txt
out.println("Resultatfil resnpk.txt, skapad");
out.println("med n = "+n+", p = "+p+" och k = "+k);
out.println("Program: CountSolutions.java");
out.println();
out.println(" a,
b, c,
d,
e,
f,
g,
h,
o,
x, y");
out.println("__________________________________________________________");
out.println();
for(a[0][0] = 0;a[0][0]<(int)Math.pow(p,k);a[0][0]++)
for(a[0][1]=0;a[0][1]<(int)Math.pow(p,k);a[0][1]++)
for(a[0][2]=0;a[0][2]<(int)Math.pow(p,k);a[0][2]++)
for(a[1][0]=0;a[1][0]<(int)Math.pow(p,k);a[1][0]++)
for(a[1][1]=0;a[1][1]<(int)Math.pow(p,k);a[1][1]++)
for(a[1][2]=0;a[1][2]<(int)Math.pow(p,k);a[1][2]++)
for(a[2][0]=0;a[2][0]<(int)Math.pow(p,k);a[2][0]++)
for(a[2][1]=0;a[2][1]<(int)Math.pow(p,k);a[2][1]++)
for(a[2][2]=0;a[2][2]<(int)Math.pow(p,k);a[2][2]++)
{
count_solutions = 0;
25
detA = det_a(a,n);
eta_pk = sgd(detA,(int)Math.pow(p,k));
eta_pnk = sgd(detA,(int)Math.pow(p,(n*k)));
for( x = 0; x < Math.pow(p,k); x++)
for( y = 0; y < Math.pow(p,k); y++)
for( z = 0; z < Math.pow(p,k); z++)
if((((a[0][0]*x +a[0][1] *y + a[0][2]*z) % Math.pow(p,k))== 0)
&& (((a[1][0]*x + a[1][1]*y + a[1][2]*z)% Math.pow(p,k))== 0)
&& (((a[2][0]*x + a[2][1]*y + a[2][2]*z)% Math.pow(p,k))== 0))
{
count_solutions++;
String param = ("a= "+a[0][0]+" b= "+a[0][1]+" c= "+a[0][2]
+" d= "+a[1][0]+" e= "+a[1][1]+" f= "+a[1][2]+" g= "+a[2][0]
+" h= "+a[2][1]+" o= "+a[2][2]+" x= "+x+" y= "+y+" z= "+z);
out.println(param);
}
String result = ("Antal lösningar = "
+count_solutions+", det(A)= "+detA
+", eta_pk = "+eta_pk+", eta_pnk = "+eta_pnk);
out.println(result);
}
total_solutions = total_solutions + count_solutions;
out.println("Totalt antal lösningar för p = "+p
+" och k = "+k+": "+total_solutions);
//stäng filen
out.close();
}
catch(Exception e)
{
System.out.println("Kunde inte spara filen");
e.printStackTrace();
26
}
}
}
public static int det_a(int [][] m, int q)
{
int s = 0;;
if(q == 2)
{
s = (m[0][0]*m[1][1] - m[1][0]*m[0][1]);
}
if(q == 3)
{
s = (m[0][0]*m[1][1]*m[2][2]+m[1][0]*m[2][1]*m[0][2]
+m[2][0]*m[0][1]*m[1][2]-m[2][0]*m[1][1]*m[0][2]
-m[0][0]*m[2][1]*m[1][2]-m[1][0]*m[0][1]*m[2][2]);
}
return s;
}
public static int sgd(int m, int n)
{
if (m == 0)
{
return n;
}
else
{
m = Math.abs(m);
while (m != n)
{
27
if (m > n)
{
m -= n;
}
else
{
n -= m;
}
}
}
return m;
}
}
3.2.2 OneSolution.java
import java.util.*;
import java.io.*;
import java.lang.*;
public class OneSolution
{
// Program: OneSolution.java
/*Program som ger antalet lösningar för ett homogent kongruenssystem
med n = 2 eller 3 variabler om p och k samt en motsvarande system-matris
A(modulo p upphöjt till k) matas in. Formlerna eta_pk och eta_pnk för att
beräkna antalet lösningar testas. */
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
28
int
int
int
int
int
int
int
int
int
n = 0;
p = 0;
k = 0;
s = 0;
t = 0;
antlosn = 0;
count_solutions = 0;
eta_pk = 0; //beräknat värde på antal lösn.
eta_pnk = 0;//
-"-
System.out.print("Ange storleken n (2 eller 3)");
System.out.println(" på system-matrisen A: ");
n = keyboard.nextInt();
int[][] a = new int[n][n];
System.out.print("Skriv ett primtal p: ");
p = keyboard.nextInt();
System.out.print("Skriv en exponent k: ");
k = keyboard.nextInt();
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
System.out.println("Skriv ett heltal < "+
(int)Math.pow(p,k) + " : ");
a[i][j] = keyboard.nextInt();
}
keyboard.nextLine(); //töm bufferten
int detA = det_a(a,n);
System.out.println("det(A) = "+ detA);
29
if (n == 2)
{
for(int x = 0; x < Math.pow(p,k); x++)
for(int y = 0; y < Math.pow(p,k); y++)
if(((a[0][0]*x +a[0][1] *y) % Math.pow(p,k)== 0)
&& ((a[1][0]*x + a[1][1]*y)% Math.pow(p,k)== 0))
{
count_solutions++;
}
}
if(n == 3)
{
for(int x = 0; x < Math.pow(p,k); x++)
for(int y = 0; y < Math.pow(p,k); y++)
for(int z = 0; z < Math.pow(p,k); z++)
if((((a[0][0]*x +a[0][1] *y + a[0][2]*z) % Math.pow(p,k))== 0)
&& (((a[1][0]*x + a[1][1]*y + a[1][2]*z)% Math.pow(p,k))== 0)
&& (((a[2][0]*x + a[2][1]*y + a[2][2]*z)% Math.pow(p,k))== 0))
{
count_solutions++;
}
}
eta_pk = sgd(detA, (int)Math.pow(p,k));
eta_pnk = sgd(detA, (int)Math.pow(p,(n*k)));
System.out.println("Antal lösningar(progr) = "+count_solutions);
System.out.print("Antal lösningar m formeln ");
System.out.println("sgd(detA,(int)Math.pow(p,k))= " + eta_pk );
System.out.print("Antal lösningar m formeln ");
System.out.println("sgd(detA,(int)Math.pow(p,(n*k)))= "+ eta_pnk);
public static int det_a(int [][] m, int q)
{
30
int s = 0;;
if(q == 2)
{
s = (m[0][0]*m[1][1] - m[1][0]*m[0][1]);
}
if(q == 3)
{
s = (m[0][0]*m[1][1]*m[2][2]+m[1][0]*m[2][1]*m[0][2]
+m[2][0]*m[0][1]*m[1][2]-m[2][0]*m[1][1]*m[0][2]
-m[0][0]*m[2][1]*m[1][2]-m[1][0]*m[0][1]*m[2][2]);
}
return s;
}
public static int sgd(int m, int n)
{
if (m == 0)
{
return n;
}
else
{
m = Math.abs(m);
while (m != n)
{
if (m > n)
{
m -= n;
}
else
{
n -= m;
}
}
}
return m;
31
}
}
3.2.3 CountWithGamma.java
import java.util.*;
import java.io.*;
import java.lang.*;
public class CountWithGamma {
public static void main(String[] args) {
//Program för beräkning av antal lösningar för ett homogent linjärt
//kongruenssystem med 3 variabler med "gammaformeln".
//Antal lösningar = p^(n*k-gamma), gamma = l_0 + l_1 + l_2, se nedan.
//Program: CountWithfGamma.java
Scanner keyboard = new Scanner(System.in);
int i = 0;
int j = 0;
int n = 0;
int p = 0;
int k = 0;
int l_0 = 0;
int l_1 = 0;
int l_2 = 0;
int antlosn = 0;
int e_0 = 0;
int e_1 = 0;
int e_2 = 0;
32
int
int
int
int
int
int
int
int
int
d_0 = 0;
d_1 = 0;
d_2 = 0;
t = 0;
r = 0;
s = 0;
u = 0;
v = 0;
gamma = 0;
System.out.println("Storleken n på system-matrisen A är 3");
//programmet är skrivet för n=3
n = 3;
//matrisen F = kopia av A-matrisen
//B = R-matrisen
int[][] a = new int[n][n];
//int[][] d = new int[n][n];
int[][] f = new int[n][n];
int[][] b = new int[n-1][n-1];
int[][] temp1 = new int[n][n];
int[][] temp2 = new int[n-1][n-1];
//c används för att spara ordningen mellan variablerna
int[]c = new int[n];
for( i = 0; i < n; i++)
{
c[i] = i+1; //c[0]=1,c[1]=2,c[3]=3;
}
System.out.print("Skriv ett primtal p: ");
p = keyboard.nextInt();
System.out.print("Skriv en exponent k: ");
k = keyboard.nextInt();
//inläsning av matrisen
for( i = 0; i < n; i++)
33
for( j = 0; j < n; j++)
{
System.out.println("Skriv ett heltal < "
+ (int)Math.pow(p,k) + " : ");
a[i][j] = keyboard.nextInt();
}
keyboard.nextLine(); //töm bufferten
int detA = det_a(a,n);
System.out.print("Testar gamma-formeln på inlästa system med n = 3, p = "+p);
System.out.println(" och k = "+k);
System.out.println();
System.out.println("det(A) = "+ detA);
System.out.println("Ursprunglig "+ n +"x"+n+"-matris.");
printMatr(a,n);
//beräkning av d0 och gamma för den ursprungliga matrisen.
e_0 = create_e(a,p,k,n);
d_0 = (int)Math.pow(p,e_0);
l_0 = k - e_0;
gamma = l_0;
copyFromAToF(d_0,a,f,n); //här bryter man ut p^(e_0)
changeColAndRow(d_0, f, c, p, k, n, n);
findAndUseInv(d_0,f,p,k,n); //omforma hela nxn-matrisen
//R-matrisen en del av A-matrisen
copyFromFToB(f,b,n);
34
// utbrytning, samt beräkning av d1 och gamma för B
e_1 = create_e(b,p,k,n-1);
d_1 = (int)Math.pow(p,e_1);
l_1 = l_0 - e_1;
gamma = l_0 + l_1;
//här bryter man ut p^e_1
for( i = 0; i < (n-1); i++)
for( j = 0; j < (n-1); j++)
{
temp2[i][j] = b[i][j]/(int)Math.pow(p,e_1);
b[i][j] = temp2[i][j];
}
changeColAndRow(d_0*d_1, b, c, p, k, n, n-1);
//omforma hela n-1xn-1-matrisen
findAndUseInv(d_0*d_1,b, p, k, n-1);
//beräkning av d_2 och gamma för r[1][1] = b[1][1]].
e_2 = create_e2(e_0, e_1, b[1][1], p, k);
d_2 = (int)Math.pow(p,e_2);
l_2 = l_1 - e_2;
gamma = gamma + l_2;
35
System.out.println("Gammaformeln ger antalet lösningar = "
+(int)Math.pow(p,(n*k-gamma)));
public static int det_a(int [][] m, int q)
{
int s = 0;;
if(q == 2)
{
s = (m[0][0]*m[1][1] - m[1][0]*m[0][1]);
}
if(q == 3)
{
s = (m[0][0]*m[1][1]*m[2][2]+m[1][0]*m[2][1]*m[0][2]
+m[2][0]*m[0][1]*m[1][2]-m[2][0]*m[1][1]*m[0][2]
-m[0][0]*m[2][1]*m[1][2]-m[1][0]*m[0][1]*m[2][2]);
}
return s;
}
public static int sgd(int m, int n)
{
if (m == 0)
{
return n;
}
else
{
m = Math.abs(m);
while (m != n)
{
if (m > n)
{
m -= n;
}
else
36
{
}
}
n -= m;
}
return m;
}
public static void changeColAndRow(int d, int [][]m, int [] n,int p,
int k,int t,int q)
{
int i = 0; int j = 0; int temp = 0; int v = 0; int g = 1000;
while(g > 1 && i < q)
{
for(j = 0; j < q; j++)
{
g = sgd(m[i][j],(int)Math.pow(p,k)/d);
if(g == 1)
break;
}
if(g == 1 || i == q-1)
break;
else
i++;
}
for(int r = 0; r < q; r++)//rad[0] och rad[i] byter plats
{
temp = m[i][r];
m[i][r] = m[0][r];
m[0][r] = temp;
}
if(sgd(m[0][0],(int)Math.pow(p,k)/d) != 1)
for( int r = 0; r < q; r++)//kol[0] och kol[j] byter plats
{
temp = m[r][j];
m[r][j] = m[r][0];
m[r][0] = temp;
37
}
}
public static void findAndUseInv(int d, int [][]m, int p, int k,int q)
//anpassat till om utbrytning skett eller ej
{
int i,j,r,s = 0;
int ainv = findInv(d,m,p,k);
for( j = 0; j < q; j++)
{
//mul. 1:a raden m. ainv
r = (int)Math.pow(p,k);
s = (int)r/d;
m[0][j] = (m[0][j]*ainv)% s;
}
for( i = 1; i < q; i++)
{
int temp = m[i][0];
for( j = 0; j < q; j++)
{
m[i][j] = (m[i][j]- temp*m[0][j])% s;
if(m[i][j] < 0)
m[i][j] = m[i][j] + s;
}
}
}
public
{
static int findInv(int d, int [][]m, int p, int k)//anpassat t.utbrytn
int r,s = 0;
int j = 0;
r = (int)Math.pow(p,k);
s = (int)(r/d);
for(int i = 0; i < ((int)Math.pow(p,k)); i++)
{
if(((m[0][0]*i) % s) == 1)
{
38
j = i;
}
if(j != 0)
break;
}
return j;
}
public static void copyFromFToB(int[][]m,int[][]p,int q)
{
for(int i = 1; i < q; i++)
for(int j = 1; j < q; j++)
{
p[i-1][j-1] = m[i][j];
}
}
public static void copyFromAToF(int d, int[][]m,int[][]p,int q)
{
for(int i = 0; i < q; i++)
for(int j = 0; j < q; j++)
{
p[i][j] = m[i][j]/d;
}
}
public static void printIndex(int []u, int q)
{
for(int i = 0; i < q ; i++)
System.out.print(u[i]+" ");
System.out.println();
}
public static void printMatr(int [][]m, int q)
{
int i,j = 0;
39
for( i = 0; i < q; i++)
{
for( j = 0; j < q; j++)
{
System.out.print(m[i][j]+" ");
}
System.out.println();
}
System.out.println();
}
public static int create_e(int m[][],int p,int k,int q)
{
int e = 0; int l = 0;int i = 0; int j = 0;
int[][] temp = new int[q][q];
for( i=0; i<q;i++)
{
for( j=0;j<q;j++)
{
temp[i][j] = m[i][j];
}
}
for( i=0; i<q;i++)
{
for( j=0;j<q;j++)
{
if(temp[i][j]%p == 0)
l++;
}
}
if(l%(int)Math.pow(q,2)== 0)
e = (int)l/(int)Math.pow(q,2);
else
e = 0;
return e;
}
public static int create_e2(int u, int v, int t, int p, int k)
40
{
int e = 0;
int s = t;
if(s == 0)
e = k - u - v;
if(sgd(s,p) == 1)
e = 0;
if((s % p == 0)&& (s > 0))
{
do
{
e++;
s = (int)s/p;
}
while((s % p== 0)&& (s > 0));
}
return e;
}
}
3.2.4 CountSolCorr.java
import java.util.*;
import java.io.*;
import java.lang.*;
public class CountSolCorr {
public static void main(String[] args) {
/*
*
Programmet ger värdet på antalet lösningar för ett antal(läses in)
slumpmässigt skapade matriser. Antalet lösningar beräknas sedan
41
*
*
med de tre formlerna(eta_pk, eta_pnk och eta_gamma) varefter dessa värden
jämförs med de värden som programmet gett (eta_prog = rätt värde). n = 3.
Program: CountSolCorr.java */
Scanner
int i =
int j =
int k =
int l =
int m =
int n =
int p =
int q =
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
keyboard = new Scanner(System.in);
0;
0;
0;
0;
0;
0;
0;
0;
l_0 = 0;
l_1 = 0;
l_2 = 0;
antlosn = 0;
e_0 = 0;
e_1 = 0;
e_2 = 0;
d_0 = 0;
d_1 = 0;
d_2 = 0;
t = 0;
eta_pnk = 0;
r = 0;
s = 0;
eta_pk = 0;
u = 0;
v = 0;
ant_syst = 0; //antal testade system
gamma = 0;
eta_gamma = 0;
count_solutions = 0;
pk = 0;
pnk = 0;
42
int nk_gamma = 0;
String param = "";
System.out.println("Storleken n på system-matrisen A är 3");
System.out.println();
//programmet är skrivet för n=3
n = 3;
System.out.println("Ange hur många system vill du testa: ");
ant_syst = keyboard.nextInt();
//matrisen F = kopia av A-matrisen
//B = R-matrisen
int[][] a = new int[n][n];
int[][] d = new int[n][n];
int[][] f = new int[n][n];
int[][] b = new int[n-1][n-1];
int[][] temp1 = new int[n][n];
int[][] temp2 = new int[n-1][n-1];
System.out.print("Skriv ett primtal p: ");
p = keyboard.nextInt();
System.out.print("Skriv en exponent k: ");
k = keyboard.nextInt();
keyboard.nextLine();
System.out.println("Skriv ett filnamn: ");
String fileName = keyboard.nextLine();
try
{
PrintWriter out = new PrintWriter(fileName);
//a_11 osv matriselement, detA = determinanten för A,
//eta_prog = rätt antal lösningar(fås av programmet)
//eta_pk = sgd(detA,(int)Math.pow(p,k)),
//eta_pnk = sgd(detA,(int)Math.pow(p,n*k))
43
//eta_gamma = sgd(detA,(int)Math.pow(p,n*k-gamma))
//rubrik på textfilen resnpk.txt
out.println("Resultatfil respk.txt, skapad");
out.println("med n = "+n+", p = "+p+" och k = "+k);
out.println("Program: CountSolCorr.java");
out.println();
out.print("a_11,a_12,a_13,a_21,a_22,a_23,a_31,a_32,a_33");
out.println(",detA,eta_prog,eta_pk,eta_pnk,eta_gamma");
//Vi skapar och testar ant_syst system
for(l = 1;l < ant_syst+1; l++ )
{
//c används för att spara ordningen mellan variablerna
int[]c = new int[n];
for( i = 0; i < n; i++)
{
c[i] = i+1; //c[0]=1,c[1]=2,c[3]=3;
}
//Matrisen A slumpgenereras
for( i = 0; i < n; i++)
for( j = 0; j < n; j++)
{
q = (int)(Math.random()* (int)Math.pow(p,k) );
a[i][j] = q;
}
//Determinanten för A beräknas och skrivs ut
int detA = det_a(a,n);
System.out.println("Den slumpgenererade "+ n +"x"+n+"-matrisen.");
printMatr(a,n);
44
copyFromAToD(a,d,n);
//beräkning av d0 och gamma för den utsprungliga matrisen.
e_0 = create_e(a,p,k,n);
d_0 = (int)Math.pow(p,e_0);
l_0 = k - e_0;
gamma = l_0;
copyFromAToF(d_0,a,f,n);
changeColAndRow(d_0, f, c, p, k, n, n);
findAndUseInv(d_0,f,p,k,n); //omforma hela nxn-matrisen
//R-matrisen en del av A-matrisen
copyFromFToB(f,b,n);
e_1 = create_e(b,p,k,n-1);
d_1 = (int)Math.pow(p,e_1);
l_1 = l_0 - e_1;
gamma = l_0 + l_1;
for( i = 0; i < (n-1); i++)
for( j = 0; j < (n-1); j++)
{
temp2[i][j] = b[i][j]/(int)Math.pow(p,e_1);
b[i][j] = temp2[i][j];
45
}
changeColAndRow( d_1, b, c, p, k, n, n-1);
findAndUseInv(d_1,b, p, k, n-1);
e_2 = create_e2(e_0, e_1, b[1][1], p, k);
d_2 = (int)Math.pow(p,e_2);
l_2 = l_1 - e_2;
gamma = gamma + l_2;
eta_pk = sgd(detA, (int)Math.pow(p,k));
eta_pnk = sgd(detA, (int)Math.pow(p,(n*k)));
eta_gamma = (int)Math.pow(p,(n*k-gamma));
for(int x = 0; x < Math.pow(p,k); x++)
for(int y = 0; y < Math.pow(p,k); y++)
for(int z = 0; z < Math.pow(p,k); z++)
if((((d[0][0]*x +d[0][1] *y + d[0][2]*z) % Math.pow(p,k))== 0)
&& (((d[1][0]*x + d[1][1]*y + d[1][2]*z)% Math.pow(p,k))== 0)
&& (((d[2][0]*x + d[2][1]*y + d[2][2]*z)% Math.pow(p,k))== 0))
{
count_solutions++;
param = (d[0][0]+"
"+d[0][1]+"
"+d[0][2]+"
"+d[1][0]+"
"+d[1][1]
+"
"+d[1][2]+"
"+d[2][0]+"
"+d[2][1]+" "+d[2][2]+"
"
+detA+"
"+count_solutions+"
"+eta_pk+"
"+eta_pnk
+"
"+eta_gamma);
}
out.println(param);
if(eta_pk == count_solutions)
46
pk++;
if(eta_pnk == count_solutions)
pnk++;
if(eta_gamma == count_solutions)
nk_gamma++;
count_solutions = 0;
}
out.println();
out.println("n = "+n+" p = "+p+" k = "+k);
out.println("Antal testade system = "+ant_syst);
out.print("Antal rätta lösningar m formeln ");
out.println("sgd(detA,(int)Math.pow(p,k))= " + pk );
out.print("Antal rätta lösningar m formeln ");
out.println("sgd(detA,(int)Math.pow(p,n*k))= "+ pnk);
out.println("Antal rätta lösningar med gammaformeln = "+nk_gamma);
out.close();
}
catch(Exception e)
{
System.out.println("Kunde inte spara filen");
e.printStackTrace();
}
System.out.println("n = "+n+" p = "+p+" k = "+k);
System.out.println("Antal testade system = "+ant_syst);
System.out.print("Antal rätta lösningar m formeln ");
System.out.println("sgd(detA,(int)Math.pow(p,k))= " + pk );
System.out.print("Antal rätta lösningar m formeln ");
System.out.println("sgd(detA,(int)Math.pow(p,(n*k)))= "+ pnk);
System.out.println("Antal rätta lösningar med gammaformeln = "+nk_gamma);
}
public static int det_a(int [][] m, int q)
{
47
int s = 0;;
if(q == 2)
{
s = (m[0][0]*m[1][1] - m[1][0]*m[0][1]);
}
if(q == 3)
{
s = (m[0][0]*m[1][1]*m[2][2]+m[1][0]*m[2][1]*m[0][2]
+m[2][0]*m[0][1]*m[1][2]-m[2][0]*m[1][1]*m[0][2]
-m[0][0]*m[2][1]*m[1][2]-m[1][0]*m[0][1]*m[2][2]);
}
return s;
}
public static int sgd(int m, int n)
{
if (m == 0)
{
return n;
}
else
{
m = Math.abs(m);
while (m != n)
{
if (m > n)
{
m -= n;
}
else
{
n -= m;
}
}
}
return m;
48
}
//p en kopia av den inlästa matrisen m
public static void copyFromAToD(int[][]m,int[][]p,int q)
{
for(int i = 0; i < q; i++)
for(int j = 0; j < q; j++)
{
p[i][j] = m[i][j];
}
}
public static void changeColAndRow(int d, int [][]m, int [] n,int p,
int k,int t,int q)
{
int i = 0; int j = 0; int temp = 0; int v = 0; int g = 1000;
while(g > 1 && i < q)
{
for(j = 0; j < q; j++)
{
g = sgd(m[i][j],(int)Math.pow(p,k)/d);
if(g == 1)
break;
}
if(g == 1 || i == q-1)
break;
else
i++;
}
for(int r = 0; r < q; r++)//rad[0] och rad[i] byter plats
{
temp = m[i][r];
m[i][r] = m[0][r];
m[0][r] = temp;
}
if(sgd(m[0][0],(int)Math.pow(p,k)/d) != 1)
for( int r = 0; r < q; r++)//kol[0] och kol[j] byter plats
{
temp = m[r][j];
49
m[r][j] = m[r][0];
m[r][0] = temp;
}
}
public static void findAndUseInv(int d, int [][]m, int p, int k,int q)
//anpassat till om utbrytning skett eller ej
{
int i,j,r,s = 0;
int ainv = findInv(d,m,p,k);
for( j = 0; j < q; j++)
{
//mul. 1:a raden m. ainv
r = (int)Math.pow(p,k);
s = (int)r/d;
m[0][j] = (m[0][j]*ainv)% s;
}
for( i = 1; i < q; i++)
{
int temp = m[i][0];
for( j = 0; j < q; j++)
{
m[i][j] = (m[i][j]- temp*m[0][j])% s;
if(m[i][j] < 0)
m[i][j] = m[i][j] + s;
}
}
}
public
{
static int findInv(int d, int [][]m, int p, int k)//anpassat t. utbrytn
int r,s = 0;
int j = 0;
r = (int)Math.pow(p,k);
s = (int)(r/d);
for(int i = 0; i < ((int)Math.pow(p,k)); i++)
50
{
if(((m[0][0]*i) % s) == 1)
{
j = i;
}
if(j != 0)
break;
}
return j;
}
public static void copyFromFToB(int[][]m,int[][]p,int q)
{
for(int i = 1; i < q; i++)
for(int j = 1; j < q; j++)
{
p[i-1][j-1] = m[i][j];
}
}
//p en kopia av den inlästa matrisen m,d>1 om vi i föreg.steg brutit ut mult.av p
public static void copyFromAToF(int d, int[][]m,int[][]p,int q)
{
for(int i = 0; i < q; i++)
for(int j = 0; j < q; j++)
{
p[i][j] = m[i][j]/d;
}
}
public static void printMatr(int [][]m, int q)
{
int i,j = 0;
for( i = 0; i < q; i++)
{
for( j = 0; j < q; j++)
{
System.out.print(m[i][j]+" ");
51
}
System.out.println();
}
System.out.println();
}
public static int create_e(int m[][],int p,int k,int q)
{
int e = 0; int l = 0;int i = 0; int j = 0;
int[][] temp = new int[q][q];
for( i=0; i<q; i++)
{
for( j=0; j<q; j++)
{
temp[i][j] = m[i][j];
}
}
for( i=0; i<q; i++)
{
for( j=0; j<q; j++)
{
if(temp[i][j]%p == 0)
{
l++;
}
}
}
if(l%(int)Math.pow(q,2)== 0)
e = (int)l/(int)Math.pow(q,2);
else
e = 0;
return e;
}
public static int create_e2(int u, int v, int t, int p, int k)
{
int e = 0;
int s = t;
52
if(s == 0)
e = k - u - v;
if(sgd(s,p) == 1)
e = 0;
if((s % p == 0)&& (s > 0))
{
do
{
e++;
s = (int)s/p;
}
while((s % p== 0)&& (s > 0));
}
return e;
}
}
3.3
Exempel på programkörningar.
3.3.1 ResCountSolutions.txt
Resultatfil resnpk.txt, skapad
med n = 2, p = 2 och k = 1
Program: CountSolutions.java
a, b,
c, d,
x, y
_____________________________
a= 0 b= 0 c= 0 d=
a= 0 b= 0 c= 0 d=
a= 0 b= 0 c= 0 d=
a= 0 b= 0 c= 0 d=
Antal lösningar =
a= 0 b= 0 c= 0 d=
a= 0 b= 0 c= 0 d=
0 x= 0 y= 0
0 x= 0 y= 1
0 x= 1 y= 0
0 x= 1 y= 1
4, det(A)= 0, eta_pk = 2, eta_pnk = 4
1 x= 0 y= 0
1 x= 1 y= 0
53
Antal lösningar = 2, det(A)= 0, eta_pk = 2, eta_pnk = 4
a= 0 b= 0 c= 1 d= 0 x= 0 y= 0
a= 0 b= 0 c= 1 d= 0 x= 0 y= 1
Antal lösningar = 2, det(A)= 0, eta_pk = 2, eta_pnk = 4
a= 0 b= 0 c= 1 d= 1 x= 0 y= 0
a= 0 b= 0 c= 1 d= 1 x= 1 y= 1
Antal lösningar = 2, det(A)= 0, eta_pk = 2, eta_pnk = 4
a= 0 b= 1 c= 0 d= 0 x= 0 y= 0
a= 0 b= 1 c= 0 d= 0 x= 1 y= 0
Antal lösningar = 2, det(A)= 0, eta_pk = 2, eta_pnk = 4
a= 0 b= 1 c= 0 d= 1 x= 0 y= 0
a= 0 b= 1 c= 0 d= 1 x= 1 y= 0
Antal lösningar = 2, det(A)= 0, eta_pk = 2, eta_pnk = 4
a= 0 b= 1 c= 1 d= 0 x= 0 y= 0
Antal lösningar = 1, det(A)= -1, eta_pk = 1, eta_pnk = 1
a= 0 b= 1 c= 1 d= 1 x= 0 y= 0
Antal lösningar = 1, det(A)= -1, eta_pk = 1, eta_pnk = 1
a= 1 b= 0 c= 0 d= 0 x= 0 y= 0
a= 1 b= 0 c= 0 d= 0 x= 0 y= 1
Antal lösningar = 2, det(A)= 0, eta_pk = 2, eta_pnk = 4
a= 1 b= 0 c= 0 d= 1 x= 0 y= 0
Antal lösningar = 1, det(A)= 1, eta_pk = 1, eta_pnk = 1
a= 1 b= 0 c= 1 d= 0 x= 0 y= 0
a= 1 b= 0 c= 1 d= 0 x= 0 y= 1
Antal lösningar = 2, det(A)= 0, eta_pk = 2, eta_pnk = 4
a= 1 b= 0 c= 1 d= 1 x= 0 y= 0
Antal lösningar = 1, det(A)= 1, eta_pk = 1, eta_pnk = 1
a= 1 b= 1 c= 0 d= 0 x= 0 y= 0
a= 1 b= 1 c= 0 d= 0 x= 1 y= 1
Antal lösningar = 2, det(A)= 0, eta_pk = 2, eta_pnk = 4
a= 1 b= 1 c= 0 d= 1 x= 0 y= 0
Antal lösningar = 1, det(A)= 1, eta_pk = 1, eta_pnk = 1
a= 1 b= 1 c= 1 d= 0 x= 0 y= 0
Antal lösningar = 1, det(A)= -1, eta_pk = 1, eta_pnk = 1
a= 1 b= 1 c= 1 d= 1 x= 0 y= 0
a= 1 b= 1 c= 1 d= 1 x= 1 y= 1
Antal lösningar = 2, det(A)= 0, eta_pk = 2, eta_pnk = 4
Totalt antal lösningar för p = 2 och k = 1: 28
3.3.2 ResOneSolution.txt
54
Körning med OneSolution.java :
Ange storleken n (2 eller 3) på system-matrisen A:
3
Skriv ett primtal p: 3
Skriv en exponent k: 3
Skriv ett heltal < 27 :
3
Skriv ett heltal < 27 :
26
Skriv ett heltal < 27 :
2
Skriv ett heltal < 27 :
15
Skriv ett heltal < 27 :
23
Skriv ett heltal < 27 :
1
Skriv ett heltal < 27 :
24
Skriv ett heltal < 27 :
17
Skriv ett heltal < 27 :
4
Matrisen A =
3 26 2
15 23 1
24 17 4
det(A) = -1305
Lösningarna:
x= 0 y= 0 z= 0
x= 3 y= 0 z= 9
x= 6 y= 0 z= 18
x= 9 y= 0 z= 0
x= 12 y= 0 z= 9
x= 15 y= 0 z= 18
x= 18 y= 0 z= 0
x= 21 y= 0 z= 9
55
x= 24 y= 0 z= 18
Rätt antal lösningar = 9
Antal lösningar m formeln sgd(detA,(int)Math.pow(p,k))= 9
Antal lösningar m formeln sgd(detA,(int)Math.pow(p,(n*k)))= 9
3.3.3 ResCountWithGamma.txt
Körning med CountWithGamma.java :
Storleken n på system-matrisen A är 3
Skriv ett primtal p: 3
Skriv en exponent k: 3
Skriv ett heltal < 27 :
3
Skriv ett heltal < 27 :
26
Skriv ett heltal < 27 :
2
Skriv ett heltal < 27 :
15
Skriv ett heltal < 27 :
23
Skriv ett heltal < 27 :
1
Skriv ett heltal < 27 :
24
Skriv ett heltal < 27 :
17
Skriv ett heltal < 27 :
4
Testar gamma-formeln på inlästa system med n = 3, p = 3 och k = 3
det(A) = -1305
Ursprunglig 3x3-matris.
3 26 2
15 23 1
24 17 4
Gammaformeln ger antalet lösningar = 9
3.3.4 ResCountSolCorr.txt
56
Resultatfil respk.txt, skapad
med n = 3, p = 3 och k = 3
Program: CountSolCorr.java
a_11,a_12,a_13,a_21,a_22,a_23,a_31,a_32,a_33,detA,eta_prog,eta_pk,eta_pnk,eta_gamma
9 14
3
11
11
11
17
13 22
-11
1
1
1
1
17 3
9
24
10
21
16
6 4
-886
1
1
1
1
9 20
3
15
2
9
2
16 3
-1074
3
3
3
3
23 4
26
16
3
5
19
9 11
1662
3
3
3
3
16 15
4
2
10
15
20
18 17
1734
3
3
3
3
5 4
11
20
8
23
25
25 18
2005
1
1
1
1
0 11
13
3
23
7
14
4 4
-3084
3
3
3
3
0 18
25
24
23
21
19
19 14
1609
1
1
1
1
7 21
25
11
7
5
25
18 12
386
1
1
1
1
25 21
26
25
9
19
10
12 5
2250
9
9
9
9
n = 3
Antal
Antal
Antal
Antal
p = 3 k = 3
testade system = 10
rätta lösningar m formeln sgd(detA,(int)Math.pow(p,k))= 10
rätta lösningar m formeln sgd(detA,(int)Math.pow(p,n*k))= 10
rätta lösningar med gammaformeln = 10
57
Litteraturförteckning
[1] Marcus Nilsson och Robert Nyqvist, Number of Solutions of Linear Congruence
Systems,
Forskningsrapport, BTH Karlskrona och Linnéuniversitetet Växjö,
2012-08-24.
[2] Ivan Niven, Herbert S. Zuckerman och Hugh l. Montgomery, An Introduction
to the Theory of numbers, New York: John Wiley & Sons, 5th ed., 1991.
[3] Robert Nyqvist, Kryptering och talteori, MA1119, kompendium, BTH Karlskrona, 2010.
[4] Lars Nystedt, På tal om tal. En läsebok i matematik, Lars Nystedt och INSTANT MATHEMATICS, Uppsala 1993. Andra genomsedda upplagan 1995.
[5] Oystein Ore, Invitation to Number Theory, The Mathematical Association of
America, 6th printing, 1975.
[6] Kenneth H. Rosen, Elementary Number Theory And Its Applications,
Boston: Pearson Addison Wesley, 6th ed., 2011.
58