Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Guillaume Sabbagh
Modification de categories
Commits
79cc5242
Commit
79cc5242
authored
Jun 08, 2021
by
Guillaume Sabbagh
Browse files
Remaniement de catégorie aléatoire
parent
96972d7a
Changes
3
Show whitespace changes
Inline
Side-by-side
CategorieAleatoire.py
View file @
79cc5242
from
GrapheDeComposition
import
GC
,
MGC
from
Monoide
import
MonoideAleatoire
import
random
import
copy
import
itertools
...
...
@@ -8,7 +9,7 @@ class GrapheCompositionAleatoire(GC):
"""Construit un graphe de composition aléatoire."""
def
__init__
(
self
,
nb_objets
=
None
,
nb_morph
=
None
,
proba_brancher
:
float
=
1
/
100
):
"""`nb_morph` est le nombre de morphismes élémentaires à ajouter aléatoirement
, certains seront supprimés après
.
"""`nb_morph` est le nombre de morphismes élémentaires à ajouter aléatoirement.
`proba_brancher` est la probabilité de brancher lors de la création de l'arbre de composition des cycles,
Plus la probabilité est grande plus il y aura de cycles et plus la loi de composition ne sera pas triviale.
Si la probabilité est 0, tous les cycles seront des isomorphismes
...
...
@@ -22,61 +23,28 @@ class GrapheCompositionAleatoire(GC):
print
(
"Création d'une catégorie avec "
+
str
(
nb_objets
)
+
" objets et "
+
str
(
nb_morph
)
+
" morphismes"
)
for
i
in
range
(
nb_objets
):
#ajout des objets
self
|=
i
self
|=
{
i
}
for
i
in
range
(
nb_morph
):
# ajout des morphismes
source
=
random
.
randint
(
0
,
nb_objets
-
1
)
cible
=
random
.
randint
(
0
,
nb_objets
-
1
)
self
|=
MGC
(
source
,
cible
)
self
|=
{
MGC
(
source
,
cible
)
}
## on définit la loi de composition pour les cycles
for
obj
in
sorted
(
self
.
objets
):
cycles
=
sorted
(
self
.
trouver_cycles_minimaux
(
obj
,
inclure_id
=
False
))
arbre_composition
=
{
cycle
:
"a determiner"
for
cycle
in
cycles
}
# {noeud_arbre : image_cycle}
profondeur_cycle
=
{
self
.
identite
(
obj
):
0
}
#cycle: profondeur dans l'arbre de composition
for
cycle
in
cycles
:
profondeur_cycle
[
cycle
]
=
1
while
list
(
arbre_composition
.
values
()).
count
(
"a determiner"
)
>
0
:
for
cle
in
copy
.
copy
(
arbre_composition
):
if
arbre_composition
[
cle
]
==
"a determiner"
:
if
random
.
random
()
<
proba_brancher
**
(
profondeur_cycle
[
cle
]
-
(
1
if
len
(
cle
)
==
1
else
0
)):
# ici on branche, plus la profondeur est grande, plus la proba de brancher est petite
print
(
"on branche "
,
proba_brancher
**
(
profondeur_cycle
[
cle
]
-
(
1
if
len
(
cle
)
==
1
else
0
)))
arbre_composition
[
cle
]
=
None
for
cycle
in
cycles
:
arbre_composition
[
cycle
@
cle
]
=
"a determiner"
profondeur_cycle
[
cycle
@
cle
]
=
profondeur_cycle
[
cle
]
+
1
else
:
# ici on doit simplifier le cycle
print
(
"on simplifie"
)
cycles_candidats
=
[
cycle
for
cycle
in
profondeur_cycle
if
profondeur_cycle
[
cycle
]
<
profondeur_cycle
[
cle
]]
arbre_composition
[
cle
]
=
random
.
choice
(
cycles_candidats
)
for
cycle
in
arbre_composition
:
if
arbre_composition
[
cycle
]
!=
None
:
assert
(
len
(
cycle
)
!=
1
)
MGC
.
identifier_morphismes
(
cycle
,
arbre_composition
[
cycle
])
print
(
obj
,
cycles
)
print
(
"======="
)
for
cle
in
arbre_composition
:
print
(
cle
,
" : "
,
arbre_composition
[
cle
])
## On retire les doubles isomorphismes (fog = fog'= Id et gof = g'of = Id)
for
source
,
cible
in
itertools
.
product
(
self
.
objets
,
repeat
=
2
):
suppression_inverses
=
True
while
suppression_inverses
:
suppression_inverses
=
False
for
f
in
sorted
(
self
(
source
,
cible
)
-
{
self
.
identite
(
source
)}):
#on retire les identités si source == cible
inverses
=
{
g
for
g
in
self
(
cible
,
source
)
if
(
f
@
g
).
is_identite
and
(
g
@
f
).
is_identite
}
if
len
(
inverses
)
>
1
:
#on doit retirer des inverses
suppression_inverses
=
True
inverse_a_suppr
=
sorted
(
list
(
inverses
),
key
=
len
)[
0
]
if
len
(
inverse_a_suppr
)
==
1
:
print
(
"suppression inverse "
,
inverse_a_suppr
)
self
-=
inverse_a_suppr
else
:
print
(
"suppression inverse "
,
inverse_a_suppr
[
0
])
self
-=
inverse_a_suppr
[
0
]
break
for
obj
in
self
.
objets
:
cycles_minimaux
=
self
.
trouver_cycles_minimaux
(
obj
,
inclure_id
=
False
)
cycles_finaux
=
cycles_minimaux
cycles_graines
=
set
(
cycles_minimaux
)
# cycles qui ont un chance de brancher
while
len
(
cycles_graines
)
>
0
:
cycle
=
cycles_graines
.
pop
()
if
random
.
random
()
<
proba_brancher
:
#on branche
nouveaux_cycles
=
{
c
@
cycle
for
c
in
cycles_minimaux
}
cycles_finaux
|=
nouveaux_cycles
cycles_graines
|=
nouveaux_cycles
#maintenant on a tous les cycles finaux
nb_cycles
=
len
(
cycles_finaux
)
+
1
monoide_alea
=
MonoideAleatoire
()
if
PRINT_AVANCEMENT_CREATION_CAT_ALEA
:
...
...
CategorieProduit.py
View file @
79cc5242
...
...
@@ -44,7 +44,6 @@ class CategorieProduit(Categorie,tuple):
result
=
set
()
for
source
in
sources
:
for
cible
in
cibles
:
print
(
source
,
cible
)
if
len
(
source
)
!=
len
(
cible
):
raise
Exception
(
"Source et cible de taille différente "
+
str
(
source
)
+
" "
+
str
(
cible
))
for
nuplet
in
itertools
.
product
(
*
tuple
(
self
[
i
]({
source
[
i
]},{
cible
[
i
]})
for
i
in
range
(
len
(
source
)))):
...
...
Monoide.py
View file @
79cc5242
...
...
@@ -25,16 +25,16 @@ class Monoide(CategorieLibre):
- elements(self) -> set : renvoie l'ensemble des éléments du Monoïde où chaque élément est un ElementMonoide.
ces deux méthodes définissent le graphe sous-jacent avec les objets de la catégorie"""
def
__init__
(
self
,
nom
:
str
=
"Monoide"
):
CategorieLibre
.
__init__
(
self
,{
1
},
nom
)
def
__init__
(
self
,
objet
:
any
=
1
,
nom
:
str
=
"Monoide"
):
CategorieLibre
.
__init__
(
self
,{
objet
},
nom
)
def
__ior__
(
self
,
objets
:
any
):
def
__ior__
(
self
,
objets
:
set
):
if
objets
==
{
1
}:
CategorieLibre
.
__ior__
(
self
,{
1
})
return
self
raise
Exception
(
"Tentative d'ajout d'un objet à un monoide : "
+
str
(
objets
))
def
__isub__
(
self
,
objets
:
any
):
def
__isub__
(
self
,
objets
:
set
):
raise
Exception
(
"Tentative de retirer un objet à un monoide : "
+
str
(
objets
))
def
existe_morphisme
(
self
,
source
:
any
,
cible
:
any
)
->
bool
:
...
...
@@ -64,7 +64,7 @@ class MonoideGC(GrapheDeComposition,Monoide):
def
__init__
(
self
,
nom
:
str
=
"MonoïdeGC"
):
GrapheDeComposition
.
__init__
(
self
,{
1
},
nom
)
Monoide
.
__init__
(
self
,
nom
)
Monoide
.
__init__
(
self
,
nom
=
nom
)
def
identite
(
self
,
objet
:
any
=
None
)
->
ElementMonoideGC
:
return
GrapheDeComposition
.
identite
(
self
,
1
)
...
...
@@ -159,31 +159,34 @@ def facteurs_premiers(n):
yield
n
break
class
MonoideAleatoire
(
Monoide
):
class
MonoideAleatoire
(
CategorieProduit
,
Monoide
):
"""Monoïde dont la table de loi de composition interne est tirée aléatoirement.
Si le nombre d'éléments du monoïde est supérieur à 5, on créé un produit de `PetitMonoideAleatoire`.
Si le (grand) nombre d'éléments est premier ou peu décomposable, on se réserve le droit de changer
le nombre d'élément pour qu'il soit factorisable en facteurs inferieurs ou égaux à 5."""
def
__
init__
(
self
,
nb_elements
:
int
=
random
.
randint
(
1
,
20
),
nom
:
str
=
"Monoïde aléatoire"
):
def
__
new__
(
cls
,
nb_elements
:
int
=
random
.
randint
(
1
,
20
),
nom
:
str
=
"Monoïde aléatoire"
):
if
DEBUG_MONOIDE_ALEATOIRE
:
print
(
"Début de création d'un monoïde à "
+
str
(
nb_elements
)
+
" éléments"
)
while
max
(
facteurs_premiers
(
nb_elements
))
>
5
:
nb_elements
-=
1
if
DEBUG_MONOIDE_ALEATOIRE
:
print
(
"Simplification du nombre d'éléments à "
+
str
(
nb_elements
))
petits_monoides
=
[
PetitMonoideAleatoire
(
x
)
for
x
in
facteurs_premiers
(
nb_elements
)]
Monoide
.
__init__
(
self
,
nom
)
self
.
__produit
=
CategorieProduit
(
*
petits_monoides
)
petits_monoides
=
tuple
(
PetitMonoideAleatoire
(
x
)
for
x
in
facteurs_premiers
(
nb_elements
))
instance
=
super
().
__new__
(
cls
,
*
petits_monoides
)
if
DEBUG_MONOIDE_ALEATOIRE
:
print
(
"Fin de création d'un monoïde à "
+
str
(
nb_elements
)
+
" éléments"
)
return
instance
def
__init__
(
self
,
nb_elements
:
int
=
random
.
randint
(
1
,
20
),
nom
:
str
=
"Monoïde aléatoire"
):
CategorieProduit
.
__init__
(
self
,
*
self
)
Monoide
.
__init__
(
self
,
tuple
(
1
for
i
in
range
(
len
(
self
))),
nom
)
def
identite
(
self
,
objet
:
any
)
->
Morphisme
:
print
(
objet
)
return
self
.
__produit
.
identite
(
tuple
(
objet
for
i
in
range
(
len
(
self
.
__produit
))))
def
__ior__
(
self
,
objets
:
set
):
if
objets
==
{
tuple
(
1
for
i
in
range
(
len
(
self
)))}:
CategorieLibre
.
__ior__
(
self
,{
tuple
(
1
for
i
in
range
(
len
(
self
)))})
return
self
raise
Exception
(
"Tentative d'ajout d'un objet à un monoide : "
+
str
(
objets
))
def
__call__
(
self
,
sources
:
set
,
cibles
:
set
)
->
set
:
return
self
.
__produit
({
tuple
(
source
for
i
in
range
(
len
(
self
.
__produit
)))
for
source
in
sources
},
{
tuple
(
cible
for
i
in
range
(
len
(
self
.
__produit
)))
for
cible
in
cibles
})
def
test_MonoideGC
():
random
.
seed
(
22453
)
...
...
@@ -191,9 +194,9 @@ def test_MonoideGC():
mon
.
transformer_graphviz
()
mon
.
loi_de_composition_to_csv
()
mon
=
MonoideAleatoire
(
2
7
)
mon
=
MonoideAleatoire
(
7
)
mon
.
transformer_graphviz
()
mon
.
loi_de_composition_to_csv
()
mon
.
loi_de_composition_to_csv
(
destination
=
"lois de composition/monoide.csv"
)
if
__name__
==
'__main__'
:
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment