Commit a85bd1cd authored by Delvallez Delvallez's avatar Delvallez Delvallez

Ajout générateur de l'annexe

parent 1d28f958
# Walnut
Automata\ Library/
Command\ Files/
Custom\ Bases/
Result/
Word\ Automata\ Library/
*-checkpoint.ipynb
**/.idea
**/.ipynb_checkpoints
# VSCode
.vscode/
# Latex
*.acn
*.acr
*.alg
*.aux
*.bak
*.bbl
*.bcf
*.blg
*.brf
*.bst
*.dvi
*.fdb_latexmk
*.fls
*.glg
*.glo
*.gls
*.idx
*.ilg
*.ind
*.ist
*.lof
*.log
*.lol
*.lot
*.maf
*.mtc
*.mtc1
*.nav
*.nlo
*.nls
*.out
*.pdf
*.pyg
*.run.xml
*.snm
*.synctex.gz
*.tex.backup
*.tex~
*.thm
*.toc
*.vrb
*.xdy
*.xml
*blx.bib
.bak
.mtc
build/
\ No newline at end of file
{
"cells": [
{
"cell_type": "markdown",
"id": "903c0b48-e1d7-41ad-a618-cf44884a6c71",
"metadata": {},
"source": [
"# Complexité en Facteur de Fibonacci\n",
"\n",
"## Construction du système de de numération\n",
"\n",
"On défini la substitution, le système de numération et le point fixe\n",
"associé."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ac92f76b",
"metadata": {},
"outputs": [],
"source": [
"%%python\n",
"from licofage.kit import *\n",
"import os\n",
"setparams(False, False, os.environ[\"WALNUT_HOME\"])\n",
"\n",
"s = subst('a->ab, b->a')\n",
"ns = address(s, \"fib\")\n",
"ns.gen_ns()\n",
"ns.gen_word_automaton()"
]
},
{
"cell_type": "markdown",
"id": "83012dc6-56d6-4730-b15c-813bcb78f865",
"metadata": {},
"source": [
"## Prédicats de base\n",
"\n",
"`feq_fib(i,j,n)` : accepte (i,j,n) si les facteurs (i,n) et (j,n) sont\n",
"égaux \n",
"`first_fib(i,n)` : accepte (i,n) si c’est un facteur nouveau \n",
"`last_fib(i,n)` : accepte (i,n) si c’est un facteur nouveau et qu’aucun\n",
"facteur nouveau ne se situe après lui"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0cab4152",
"metadata": {},
"outputs": [],
"source": [
"def cut_fib \"?msd_fib i<=u & j<=v & u+j=v+i & u<n+i & v<n+j\":\n",
"def feq_fib \"?msd_fib ~(Eu,v $cut_fib(i,j,n,u,v) & Fib[u]!=Fib[v])\":\n",
"def first_fib \"?msd_fib Aj $feq_fib(i,j,n) => i<=j\":\n",
"def last_fib \"?msd_fib $first_fib(i,n) & Ak k>i => ~$first_fib(k,n)\": "
]
},
{
"cell_type": "markdown",
"id": "033f12cb-c963-47de-b6fe-37c36bb21e32",
"metadata": {},
"source": [
"## Construction de la complexité en facteur par itération\n",
"\n",
"`next_block_fib(i,j,n)` : (i,n) est un facteur non nouveau et (j,n) est\n",
"le premier facteur nouveau qui suit. Si un tel facteur (j,n) n’existe\n",
"pas, j=i \n",
"`block_max_right_fib(i,j,n,l)` : il y a un bloc de l facteurs nouveau\n",
"entre (i,n) et (j,n) et il est maximal à droite \n",
"Suite d’automate / prédicat (j entier non nul) `compte_j_fib(e,n,p)` :\n",
"entre (0,n) et (e,n), il y a p facteurs nouveau répartis dans j blocs ou\n",
"moins \n",
"`compl_fact_fib_V1(n,p)` : complexité en facteur synchronisée"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c2b6bbc6",
"metadata": {},
"outputs": [],
"source": [
"%%python\n",
"script = []\n",
"\n",
"script.append(f'def last_fib \"?msd_fib $first_fib(i,n) & Ak k>i => ~$first_fib(k,n)\";')\n",
"script.append(f'''def block_max_right_fib \"?msd_fib (~$first_fib(i,n) & k=0 & j=i) \n",
" | ($first_fib(i,n) \n",
" & (Ap (i<=p & p<=j) => $first_fib(p,n)) \n",
" & ~$first_fib(j+1,n) \n",
" & (i+k = j+1))\";''') \n",
"script.append(f'''def next_block_fib \"?msd_fib (i<j & ~$first_fib(i,n) & $first_fib(j,n) & \n",
" (Ap (i<p & p<j) => ~$first_fib(p,n)))\n",
" | (Ek $last_fib(k,n) & k<i & i=j)\";''') \n",
"script.append(f'def compte_0_fib \"?msd_fib $block_max_right_fib(0,e,p,n)\":')\n",
"script.append(f'def compte_1_fib \"?msd_fib Es,q $compte_0_fib(s,n,q)&(($next_block_fib(s+1,s+1,n) & p=q & s+1=e+1)|(Ek s+1<k & $next_block_fib(s+1,k,n) & El $block_max_right_fib(k,e,l,n) & p=q+l))\";')\n",
"script.append('eval test_egal_fib \"?msd_fib Ae,n,p $compte_1_fib(e,n,p) <=> $compte_0_fib(e,n,p)\";')\n",
"j=1\n",
"\n",
"writefile(f\"factcompl_via_iter\", \"\\n\".join(script))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "85979588",
"metadata": {},
"outputs": [],
"source": [
"load factcompl_via_iter.txt;"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4dd48ba5",
"metadata": {},
"outputs": [],
"source": [
"%%python\n",
"script = []\n",
"\n",
"p_test = P(os.environ[\"WALNUT_HOME\"])/\"Result\"/\"test_egal_fib.txt\"\n",
"flag = 0\n",
"with p_test.open(\"r\") as f_test:\n",
" res = f_test.read()\n",
" if \"false\" in res :\n",
" flag = 1\n",
" elif \"true\" in res:\n",
" flag = 2\n",
" else :\n",
" print(\"Un problème est survenu\")\n",
"if flag == 1: \n",
" j+=1\n",
" script.append(f'def compte_{j}_fib \"?msd_fib Es,q $compte_{j-1}_fib(s,n,q)&(($next_block_fib(s+1,s+1,n) & p=q & s+1=e+1)|(Ek s+1<k & $next_block_fib(s+1,k,n) & El $block_max_right_fib(k,e,l,n) & p=q+l))\";')\n",
" script.append(f'eval test_egal_fib \"?msd_fib Ae,n,p $compte_{j-1}_fib(e,n,p) <=> $compte_{j}_fib(e,n,p)\";')\n",
" print(\"Exécutez les deux dernières cellules une fois de plus.\")\n",
"elif flag == 2 :\n",
" script.append(f'def compl_fact_fib_V1 \"?msd_fib Ee $compte_{j}_fib(e,n,p)\";')\n",
" print(\"OK\")\n",
"writefile(f\"factcompl_via_iter\", \"\\n\".join(script))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "34d91852",
"metadata": {},
"outputs": [],
"source": [
"load factcompl_via_iter.txt;"
]
},
{
"cell_type": "markdown",
"id": "989b265a-9bb9-4c60-8306-12ee3f90b1b3",
"metadata": {},
"source": [
"## Vérification inductive de l’automate\n",
"\n",
"`new_first_fib(i,n)` : accepte le facteur (i,n) si il est nouvellement\n",
"nouveau \n",
"`NEW_fib[n]` : nombre de facteur nouvellement nouveau de longueur n+1"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "446d68d1",
"metadata": {},
"outputs": [],
"source": [
"def new_first_fib n \"?msd_fib ~$first_fib(i,n) & $first_fib(i,n+1)\":"
]
},
{
"cell_type": "markdown",
"id": "417b7181-924b-48e0-9d7f-08b4645e09e1",
"metadata": {},
"source": [
"On applique le semigroup-trick."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2105468f",
"metadata": {},
"outputs": [],
"source": [
"%SGT new_first_fib fib NEW_fib"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "20288bcd",
"metadata": {},
"outputs": [],
"source": [
"eval check_zero \"?msd_fib $compl_fact_fib_V1(0,1)\":\n",
"eval check_rec \"?msd_fib An,p,q ($compl_fact_fib_V1(n,p) & $compl_fact_fib_V1(n+1,q)) => p+NEW_fib[n] = q\":"
]
},
{
"cell_type": "markdown",
"id": "b197d43b-2176-4cfe-bbf3-0392c49d58dc",
"metadata": {},
"source": [
"## Construction de la complexité en facteur à l’aide de NEW\n",
"\n",
"### Récupérer le morphisme associé à NEW"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ee9bc9bc",
"metadata": {},
"outputs": [],
"source": [
"%%python\n",
"\n",
"from pathlib import Path as P\n",
"import os\n",
"from licofage.kit import subst, address\n",
"\n",
"def readDFAO(f):\n",
" # lecture de tous les états, de leurs transitions et sortie\n",
" l = f.readline()\n",
" dfa = dict()\n",
" outputs = dict()\n",
" while l != '':\n",
" etat_data = l.split()\n",
" etat = int(etat_data[0].strip()) #on récupère le nom de l'etat\n",
" outputs[etat] = int(etat_data[1].strip())\n",
" transition = dict()\n",
" l = f.readline()\n",
" while \"->\" in l:\n",
" tr = l.split(\"->\")\n",
" transition[int(tr[0].strip())] = int(tr[1].strip())\n",
" l = f.readline()\n",
" dfa[etat] = transition\n",
" l = f.readline()\n",
"\n",
" return (dfa,outputs)\n",
"\n",
"def DFAtoSubst(dfa):\n",
" subst = \"\"\n",
" for etat in sorted(dfa.keys()):\n",
" subst += chr(etat+97)+\" -> \"\n",
" for lect in sorted(dfa[etat].keys()):\n",
" subst += chr(dfa[etat][lect]+97)\n",
" subst += \" , \"\n",
" return subst[:-2] ## pour la virgule ajoutée en trop\n",
"\n",
"def DFAOtoMorph(dfa,outputs):\n",
" subst = DFAtoSubst(dfa)\n",
" w = dict()\n",
" for key in outputs.keys():\n",
" w[chr(key+97)] = outputs[key]\n",
" return subst, w\n",
"\n",
"def getSubst(p:P):\n",
" with p.open('r') as f:\n",
" # atteindre le premier état\n",
" l = f.readline()\n",
" while l != '\\n':\n",
" l = f.readline()\n",
" (dfa, outputs) = readDFAO(f)\n",
" return DFAOtoMorph(dfa, outputs)"
]
},
{
"cell_type": "markdown",
"id": "f02a83fe-6804-4ac7-9a0e-537342b6f5b6",
"metadata": {},
"source": [
"### Calculer la complexité en facteur à l’aide de NEW\n",
"\n",
"`sumNEW(n,s)` : s est la somme des n-1 premières valeurs de NEW\n",
"\\`compl_fact_fib_V2(n,p) : complexité en facteur synchronisée (obtenue à\n",
"l’aide de NEW)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a16c49f",
"metadata": {},
"outputs": [],
"source": [
"%%python\n",
"\n",
"new_subst, w = getSubst(P(os.environ[\"WALNUT_HOME\"])/\"Word Automata Library\"/\"NEW_fib.txt\")\n",
"new = subst(new_subst)\n",
"new_w = address(new, 'fib',**w)\n",
"(new_w-ns).gen_dfa(\"sumNEW_fib\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f85b742e",
"metadata": {},
"outputs": [],
"source": [
"def compl_fact_fib_V2 \"?msd_fib Eq $sumNEW_fib(n,q) & p=q+1\":"
]
},
{
"cell_type": "markdown",
"id": "adac0b03-ccf8-4a9b-a195-652bed38d403",
"metadata": {},
"source": [
"### Vérification du résultat\n",
"\n",
"`compl_fact_fib_V2` est calculée à l’aide de `NEW`. On ne peut pas\n",
"utiliser la technique précédente pour vérifier notre prédicat. Par\n",
"contre, on peut confronter `compl_fact_fib_V1` et compl_fact_fib_V2 car\n",
"elle sont issues de deux méthodes différentes."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b1e42908",
"metadata": {},
"outputs": [],
"source": [
"eval check_V2 \"?msd_fib An,p $compl_fact_fib_V1(n,p) <=> $compl_fact_fib_V2(n,p)\":"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Walnut",
"language": "walnut",
"name": "walnut"
},
"language_info": {
"codemirror_mode": "null",
"file_extension": ".walnut",
"language": "walnut",
"mimetype": "text/x-walnut",
"name": "walnut",
"version": "0.3.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
---
title: Complexité en Facteur de Fibonacci
date: '2025-06-16'
format:
html:
code-fold: false
embed-resources: true
toc: true
toc-location: left
number-sections: true
syntax-definitions:
- walnut.xml
ipynb: default
execute:
cache: true
keep-ipynb: true
allow_errors: true
jupyter: walnut
---
## Construction du système de de numération
On défini la substitution, le système de numération et le point fixe associé.
```{walnut}
%%python
from licofage.kit import *
import os
setparams(False, False, os.environ["WALNUT_HOME"])
s = subst('a->ab, b->a')
ns = address(s, "fib")
ns.gen_ns()
ns.gen_word_automaton()
```
## Prédicats de base
`feq_fib(i,j,n)` : accepte (i,j,n) si les facteurs (i,n) et (j,n)
sont égaux
`first_fib(i,n)` : accepte (i,n) si c'est un facteur nouveau
`last_fib(i,n)` : accepte (i,n) si c'est un facteur nouveau et qu'aucun facteur nouveau ne se situe après lui
```{walnut}
def cut_fib "?msd_fib i<=u & j<=v & u+j=v+i & u<n+i & v<n+j":
def feq_fib "?msd_fib ~(Eu,v $cut_fib(i,j,n,u,v) & Fib[u]!=Fib[v])":
def first_fib "?msd_fib Aj $feq_fib(i,j,n) => i<=j":
def last_fib "?msd_fib $first_fib(i,n) & Ak k>i => ~$first_fib(k,n)":
```
## Construction de la complexité en facteur par itération
`next_block_fib(i,j,n)` : (i,n) est un facteur non nouveau et (j,n) est le premier facteur nouveau qui suit. Si un tel facteur (j,n) n'existe pas, j=i
`block_max_right_fib(i,j,n,l)` : il y a un bloc de l facteurs nouveau entre (i,n) et (j,n) et il est maximal à droite
Suite d'automate / prédicat (j entier non nul) `compte_j_fib(e,n,p)` : entre (0,n) et (e,n), il y a p facteurs nouveau répartis dans j blocs ou moins
`compl_fact_fib_V1(n,p)` : complexité en facteur synchronisée
```{walnut}
%%python
script = []
script.append(f'def last_fib "?msd_fib $first_fib(i,n) & Ak k>i => ~$first_fib(k,n)";')
script.append(f'''def block_max_right_fib "?msd_fib (~$first_fib(i,n) & k=0 & j=i)
| ($first_fib(i,n)
& (Ap (i<=p & p<=j) => $first_fib(p,n))
& ~$first_fib(j+1,n)
& (i+k = j+1))";''')
script.append(f'''def next_block_fib "?msd_fib (i<j & ~$first_fib(i,n) & $first_fib(j,n) &
(Ap (i<p & p<j) => ~$first_fib(p,n)))
| (Ek $last_fib(k,n) & k<i & i=j)";''')
script.append(f'def compte_0_fib "?msd_fib $block_max_right_fib(0,e,p,n)":')
script.append(f'def compte_1_fib "?msd_fib Es,q $compte_0_fib(s,n,q)&(($next_block_fib(s+1,s+1,n) & p=q & s+1=e+1)|(Ek s+1<k & $next_block_fib(s+1,k,n) & El $block_max_right_fib(k,e,l,n) & p=q+l))";')
script.append('eval test_egal_fib "?msd_fib Ae,n,p $compte_1_fib(e,n,p) <=> $compte_0_fib(e,n,p)";')
j=1
writefile(f"factcompl_via_iter", "\n".join(script))
```
```{walnut}
load factcompl_via_iter.txt;
```
```{walnut}
%%python
script = []
p_test = P(os.environ["WALNUT_HOME"])/"Result"/"test_egal_fib.txt"
flag = 0
with p_test.open("r") as f_test:
res = f_test.read()
if "false" in res :
flag = 1
elif "true" in res:
flag = 2
else :
print("Un problème est survenu")
if flag == 1:
j+=1
script.append(f'def compte_{j}_fib "?msd_fib Es,q $compte_{j-1}_fib(s,n,q)&(($next_block_fib(s+1,s+1,n) & p=q & s+1=e+1)|(Ek s+1<k & $next_block_fib(s+1,k,n) & El $block_max_right_fib(k,e,l,n) & p=q+l))";')
script.append(f'eval test_egal_fib "?msd_fib Ae,n,p $compte_{j-1}_fib(e,n,p) <=> $compte_{j}_fib(e,n,p)";')
print("Exécutez les deux dernières cellules une fois de plus.")
elif flag == 2 :
script.append(f'def compl_fact_fib_V1 "?msd_fib Ee $compte_{j}_fib(e,n,p)";')
print("OK")
writefile(f"factcompl_via_iter", "\n".join(script))
```
```{walnut}
load factcompl_via_iter.txt;
```
## Vérification inductive de l'automate
`new_first_fib(i,n)` : accepte le facteur (i,n) si il est nouvellement nouveau
`NEW_fib[n]` : nombre de facteur nouvellement nouveau de longueur n+1
```{walnut}
def new_first_fib n "?msd_fib ~$first_fib(i,n) & $first_fib(i,n+1)":
```
On applique le semigroup-trick.
```{walnut}
%SGT new_first_fib fib NEW_fib
```
```{walnut}
eval check_zero "?msd_fib $compl_fact_fib_V1(0,1)":
eval check_rec "?msd_fib An,p,q ($compl_fact_fib_V1(n,p) & $compl_fact_fib_V1(n+1,q)) => p+NEW_fib[n] = q":
```
## Construction de la complexité en facteur à l'aide de NEW
### Récupérer le morphisme associé à NEW
```{walnut}
%%python
from pathlib import Path as P
import os
from licofage.kit import subst, address
def readDFAO(f):
# lecture de tous les états, de leurs transitions et sortie
l = f.readline()
dfa = dict()
outputs = dict()
while l != '':
etat_data = l.split()
etat = int(etat_data[0].strip()) #on récupère le nom de l'etat
outputs[etat] = int(etat_data[1].strip())
transition = dict()
l = f.readline()
while "->" in l:
tr = l.split("->")
transition[int(tr[0].strip())] = int(tr[1].strip())
l = f.readline()
dfa[etat] = transition
l = f.readline()
return (dfa,outputs)
def DFAtoSubst(dfa):
subst = ""
for etat in sorted(dfa.keys()):
subst += chr(etat+97)+" -> "
for lect in sorted(dfa[etat].keys()):
subst += chr(dfa[etat][lect]+97)
subst += " , "
return subst[:-2] ## pour la virgule ajoutée en trop
def DFAOtoMorph(dfa,outputs):
subst = DFAtoSubst(dfa)
w = dict()
for key in outputs.keys():
w[chr(key+97)] = outputs[key]
return subst, w
def getSubst(p:P):
with p.open('r') as f:
# atteindre le premier état
l = f.readline()
while l != '\n':
l = f.readline()
(dfa, outputs) = readDFAO(f)
return DFAOtoMorph(dfa, outputs)
```
### Calculer la complexité en facteur à l'aide de NEW
`sumNEW(n,s)` : s est la somme des n-1 premières valeurs de NEW
`compl_fact_fib_V2(n,p) : complexité en facteur synchronisée (obtenue à l'aide de NEW)
```{walnut}
%%python
new_subst, w = getSubst(P(os.environ["WALNUT_HOME"])/"Word Automata Library"/"NEW_fib.txt")
new = subst(new_subst)
new_w = address(new, 'fib',**w)
(new_w-ns).gen_dfa("sumNEW_fib")
```
```{walnut}
def compl_fact_fib_V2 "?msd_fib Eq $sumNEW_fib(n,q) & p=q+1":
```
### Vérification du résultat
`compl_fact_fib_V2` est calculée à l'aide de `NEW`. On ne peut pas utiliser la technique précédente pour vérifier notre prédicat. Par contre, on peut confronter `compl_fact_fib_V1` et compl_fact_fib_V2 car elle sont issues de deux méthodes différentes.
```{walnut}
eval check_V2 "?msd_fib An,p $compl_fact_fib_V1(n,p) <=> $compl_fact_fib_V2(n,p)":
```
% Options for packages loaded elsewhere
% Options for packages loaded elsewhere
\PassOptionsToPackage{unicode}{hyperref}
\PassOptionsToPackage{hyphens}{url}
\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor}
%
\documentclass[
letterpaper,
DIV=11,
numbers=noendperiod]{scrartcl}
\usepackage{xcolor}
\usepackage{amsmath,amssymb}
\setcounter{secnumdepth}{-\maxdimen} % remove section numbering
\usepackage{iftex}
\ifPDFTeX
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{textcomp} % provide euro and other symbols
\else % if luatex or xetex
\usepackage{unicode-math} % this also loads fontspec
\defaultfontfeatures{Scale=MatchLowercase}
\defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
\fi
\usepackage{lmodern}
\ifPDFTeX\else
% xetex/luatex font selection
\fi
% Use upquote if available, for straight quotes in verbatim environments
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
\IfFileExists{microtype.sty}{% use microtype if available
\usepackage[]{microtype}
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
}{}
\makeatletter
\@ifundefined{KOMAClassName}{% if non-KOMA class
\IfFileExists{parskip.sty}{%
\usepackage{parskip}
}{% else
\setlength{\parindent}{0pt}
\setlength{\parskip}{6pt plus 2pt minus 1pt}}
}{% if KOMA class
\KOMAoptions{parskip=half}}
\makeatother
% Make \paragraph and \subparagraph free-standing
\makeatletter
\ifx\paragraph\undefined\else
\let\oldparagraph\paragraph
\renewcommand{\paragraph}{
\@ifstar
\xxxParagraphStar
\xxxParagraphNoStar
}
\newcommand{\xxxParagraphStar}[1]{\oldparagraph*{#1}\mbox{}}
\newcommand{\xxxParagraphNoStar}[1]{\oldparagraph{#1}\mbox{}}
\fi
\ifx\subparagraph\undefined\else
\let\oldsubparagraph\subparagraph
\renewcommand{\subparagraph}{
\@ifstar
\xxxSubParagraphStar
\xxxSubParagraphNoStar
}
\newcommand{\xxxSubParagraphStar}[1]{\oldsubparagraph*{#1}\mbox{}}
\newcommand{\xxxSubParagraphNoStar}[1]{\oldsubparagraph{#1}\mbox{}}
\fi
\makeatother
\usepackage{color}
\usepackage{fancyvrb}
\newcommand{\VerbBar}{|}
\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
% Add ',fontsize=\small' for more characters per line
\usepackage{framed}
\definecolor{shadecolor}{RGB}{241,243,245}
\newenvironment{Shaded}{\begin{snugshade}}{\end{snugshade}}
\newcommand{\AlertTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}}
\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}}
\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.40,0.45,0.13}{#1}}
\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}}
\newcommand{\BuiltInTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}}
\newcommand{\CharTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}}
\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}}
\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}}
\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{#1}}
\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{\textbf{#1}}}
\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}}
\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}}
\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}}
\newcommand{\ErrorTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}}
\newcommand{\ExtensionTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}}
\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}}
\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.28,0.35,0.67}{#1}}
\newcommand{\ImportTok}[1]{\textcolor[rgb]{0.00,0.46,0.62}{#1}}
\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}}
\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{\textbf{#1}}}
\newcommand{\NormalTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}}
\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}}
\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}}
\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}}
\newcommand{\RegionMarkerTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}}
\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}}
\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}}
\newcommand{\StringTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}}
\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.07,0.07,0.07}{#1}}
\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}}
\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}}
\usepackage{longtable,booktabs,array}
\usepackage{calc} % for calculating minipage widths
% Correct order of tables after \paragraph or \subparagraph
\usepackage{etoolbox}
\makeatletter
\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}
\makeatother
% Allow footnotes in longtable head/foot
\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}}
\makesavenoteenv{longtable}
\usepackage{graphicx}
\makeatletter
\newsavebox\pandoc@box
\newcommand*\pandocbounded[1]{% scales image to fit in text height/width
\sbox\pandoc@box{#1}%
\Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%
\Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%
\ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both
\ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%
\else\usebox{\pandoc@box}%
\fi%
}
% Set default figure placement to htbp
\def\fps@figure{htbp}
\makeatother
\setlength{\emergencystretch}{3em} % prevent overfull lines
\providecommand{\tightlist}{%
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\KOMAoption{captions}{tableheading}
\makeatletter
\@ifpackageloaded{caption}{}{\usepackage{caption}}
\AtBeginDocument{%
\ifdefined\contentsname
\renewcommand*\contentsname{Table of contents}
\else
\newcommand\contentsname{Table of contents}
\fi
\ifdefined\listfigurename
\renewcommand*\listfigurename{List of Figures}
\else
\newcommand\listfigurename{List of Figures}
\fi
\ifdefined\listtablename
\renewcommand*\listtablename{List of Tables}
\else
\newcommand\listtablename{List of Tables}
\fi
\ifdefined\figurename
\renewcommand*\figurename{Figure}
\else
\newcommand\figurename{Figure}
\fi
\ifdefined\tablename
\renewcommand*\tablename{Table}
\else
\newcommand\tablename{Table}
\fi
}
\@ifpackageloaded{float}{}{\usepackage{float}}
\floatstyle{ruled}
\@ifundefined{c@chapter}{\newfloat{codelisting}{h}{lop}}{\newfloat{codelisting}{h}{lop}[chapter]}
\floatname{codelisting}{Listing}
\newcommand*\listoflistings{\listof{codelisting}{List of Listings}}
\makeatother
\makeatletter
\makeatother
\makeatletter
\@ifpackageloaded{caption}{}{\usepackage{caption}}
\@ifpackageloaded{subcaption}{}{\usepackage{subcaption}}
\makeatother
\usepackage{bookmark}
\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
\urlstyle{same}
\hypersetup{
pdftitle={Complexité en Facteur de Fibonacci},
colorlinks=true,
linkcolor={blue},
filecolor={Maroon},
citecolor={Blue},
urlcolor={Blue},
pdfcreator={LaTeX via pandoc}}
\title{Complexité en Facteur de Fibonacci}
\author{}
\date{2025-06-16}
\begin{document}
\maketitle
\subsection{Construction du système de de
numération}\label{construction-du-systuxe8me-de-de-numuxe9ration}
On défini la substitution, le système de numération et le point fixe
associé.
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{\%\%python}
\NormalTok{from licofage.kit import *}
\NormalTok{import os}
\NormalTok{setparams(False, False, os.environ["WALNUT\_HOME"])}
\NormalTok{s = subst(\textquotesingle{}a{-}\textgreater{}ab, b{-}\textgreater{}a\textquotesingle{})}
\NormalTok{ns = address(s, "fib")}
\NormalTok{ns.gen\_ns()}
\NormalTok{ns.gen\_word\_automaton()}
\end{Highlighting}
\end{Shaded}
\subsection{Prédicats de base}\label{pruxe9dicats-de-base}
\texttt{feq\_fib(i,j,n)} : accepte (i,j,n) si les facteurs (i,n) et
(j,n) sont égaux\\
\texttt{first\_fib(i,n)} : accepte (i,n) si c'est un facteur nouveau\\
\texttt{last\_fib(i,n)} : accepte (i,n) si c'est un facteur nouveau et
qu'aucun facteur nouveau ne se situe après lui
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{def cut\_fib "?msd\_fib i\textless{}=u \& j\textless{}=v \& u+j=v+i \& u\textless{}n+i \& v\textless{}n+j":}
\NormalTok{def feq\_fib "?msd\_fib \textasciitilde{}(Eu,v $cut\_fib(i,j,n,u,v) \& Fib[u]!=Fib[v])":}
\NormalTok{def first\_fib "?msd\_fib Aj $feq\_fib(i,j,n) =\textgreater{} i\textless{}=j":}
\NormalTok{def last\_fib "?msd\_fib $first\_fib(i,n) \& Ak k\textgreater{}i =\textgreater{} \textasciitilde{}$first\_fib(k,n)": }
\end{Highlighting}
\end{Shaded}
\subsection{Construction de la complexité en facteur par
itération}\label{construction-de-la-complexituxe9-en-facteur-par-ituxe9ration}
\texttt{next\_block\_fib(i,j,n)} : (i,n) est un facteur non nouveau et
(j,n) est le premier facteur nouveau qui suit. Si un tel facteur (j,n)
n'existe pas, j=i\\
\texttt{block\_max\_right\_fib(i,j,n,l)} : il y a un bloc de l facteurs
nouveau entre (i,n) et (j,n) et il est maximal à droite\\
Suite d'automate / prédicat (j entier non nul)
\texttt{compte\_j\_fib(e,n,p)} : entre (0,n) et (e,n), il y a p facteurs
nouveau répartis dans j blocs ou moins\\
\texttt{compl\_fact\_fib\_V1(n,p)} : complexité en facteur synchronisée
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{\%\%python}
\NormalTok{script = []}
\NormalTok{script.append(f\textquotesingle{}def last\_fib "?msd\_fib $first\_fib(i,n) \& Ak k\textgreater{}i =\textgreater{} \textasciitilde{}$first\_fib(k,n)";\textquotesingle{})}
\NormalTok{script.append(f\textquotesingle{}\textquotesingle{}\textquotesingle{}def block\_max\_right\_fib "?msd\_fib (\textasciitilde{}$first\_fib(i,n) \& k=0 \& j=i) }
\NormalTok{ | ($first\_fib(i,n) }
\NormalTok{ \& (Ap (i\textless{}=p \& p\textless{}=j) =\textgreater{} $first\_fib(p,n)) }
\NormalTok{ \& \textasciitilde{}$first\_fib(j+1,n) }
\NormalTok{ \& (i+k = j+1))";\textquotesingle{}\textquotesingle{}\textquotesingle{}) }
\NormalTok{script.append(f\textquotesingle{}\textquotesingle{}\textquotesingle{}def next\_block\_fib "?msd\_fib (i\textless{}j \& \textasciitilde{}$first\_fib(i,n) \& $first\_fib(j,n) \& }
\NormalTok{ (Ap (i\textless{}p \& p\textless{}j) =\textgreater{} \textasciitilde{}$first\_fib(p,n)))}
\NormalTok{ | (Ek $last\_fib(k,n) \& k\textless{}i \& i=j)";\textquotesingle{}\textquotesingle{}\textquotesingle{}) }
\NormalTok{script.append(f\textquotesingle{}def compte\_0\_fib "?msd\_fib $block\_max\_right\_fib(0,e,p,n)":\textquotesingle{})}
\NormalTok{script.append(f\textquotesingle{}def compte\_1\_fib "?msd\_fib Es,q $compte\_0\_fib(s,n,q)\&(($next\_block\_fib(s+1,s+1,n) \& p=q \& s+1=e+1)|(Ek s+1\textless{}k \& $next\_block\_fib(s+1,k,n) \& El $block\_max\_right\_fib(k,e,l,n) \& p=q+l))";\textquotesingle{})}
\NormalTok{script.append(\textquotesingle{}eval test\_egal\_fib "?msd\_fib Ae,n,p $compte\_1\_fib(e,n,p) \textless{}=\textgreater{} $compte\_0\_fib(e,n,p)";\textquotesingle{})}
\NormalTok{j=1}
\NormalTok{writefile(f"factcompl\_via\_iter", "\textbackslash{}n".join(script))}
\end{Highlighting}
\end{Shaded}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{load factcompl\_via\_iter.txt;}
\end{Highlighting}
\end{Shaded}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{\%\%python}
\NormalTok{script = []}
\NormalTok{p\_test = P(os.environ["WALNUT\_HOME"])/"Result"/"test\_egal\_fib.txt"}
\NormalTok{flag = 0}
\NormalTok{with p\_test.open("r") as f\_test:}
\NormalTok{ res = f\_test.read()}
\NormalTok{ if "false" in res :}
\NormalTok{ flag = 1}
\NormalTok{ elif "true" in res:}
\NormalTok{ flag = 2}
\NormalTok{ else :}
\NormalTok{ print("Un problème est survenu")}
\NormalTok{if flag == 1: }
\NormalTok{ j+=1}
\NormalTok{ script.append(f\textquotesingle{}def compte\_\{j\}\_fib "?msd\_fib Es,q $compte\_\{j{-}1\}\_fib(s,n,q)\&(($next\_block\_fib(s+1,s+1,n) \& p=q \& s+1=e+1)|(Ek s+1\textless{}k \& $next\_block\_fib(s+1,k,n) \& El $block\_max\_right\_fib(k,e,l,n) \& p=q+l))";\textquotesingle{})}
\NormalTok{ script.append(f\textquotesingle{}eval test\_egal\_fib "?msd\_fib Ae,n,p $compte\_\{j{-}1\}\_fib(e,n,p) \textless{}=\textgreater{} $compte\_\{j\}\_fib(e,n,p)";\textquotesingle{})}
\NormalTok{ print("Exécutez les deux dernières cellules une fois de plus.")}
\NormalTok{elif flag == 2 :}
\NormalTok{ script.append(f\textquotesingle{}def compl\_fact\_fib\_V1 "?msd\_fib Ee $compte\_\{j\}\_fib(e,n,p)";\textquotesingle{})}
\NormalTok{ print("OK")}
\NormalTok{writefile(f"factcompl\_via\_iter", "\textbackslash{}n".join(script))}
\end{Highlighting}
\end{Shaded}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{load factcompl\_via\_iter.txt;}
\end{Highlighting}
\end{Shaded}
\subsection{Vérification inductive de
l'automate}\label{vuxe9rification-inductive-de-lautomate}
\texttt{new\_first\_fib(i,n)} : accepte le facteur (i,n) si il est
nouvellement nouveau\\
\texttt{NEW\_fib{[}n{]}} : nombre de facteur nouvellement nouveau de
longueur n+1
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{def new\_first\_fib n "?msd\_fib \textasciitilde{}$first\_fib(i,n) \& $first\_fib(i,n+1)":}
\end{Highlighting}
\end{Shaded}
On applique le semigroup-trick.
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{\%SGT new\_first\_fib fib NEW\_fib}
\end{Highlighting}
\end{Shaded}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{eval check\_zero "?msd\_fib $compl\_fact\_fib\_V1(0,1)":}
\NormalTok{eval check\_rec "?msd\_fib An,p,q ($compl\_fact\_fib\_V1(n,p) \& $compl\_fact\_fib\_V1(n+1,q)) =\textgreater{} p+NEW\_fib[n] = q":}
\end{Highlighting}
\end{Shaded}
\subsection{Construction de la complexité en facteur à l'aide de
NEW}\label{construction-de-la-complexituxe9-en-facteur-uxe0-laide-de-new}
\subsubsection{Récupérer le morphisme associé à
NEW}\label{ruxe9cupuxe9rer-le-morphisme-associuxe9-uxe0-new}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{\%\%python}
\NormalTok{from pathlib import Path as P}
\NormalTok{import os}
\NormalTok{from licofage.kit import subst, address}
\NormalTok{def readDFAO(f):}
\NormalTok{ \# lecture de tous les états, de leurs transitions et sortie}
\NormalTok{ l = f.readline()}
\NormalTok{ dfa = dict()}
\NormalTok{ outputs = dict()}
\NormalTok{ while l != \textquotesingle{}\textquotesingle{}:}
\NormalTok{ etat\_data = l.split()}
\NormalTok{ etat = int(etat\_data[0].strip()) \#on récupère le nom de l\textquotesingle{}etat}
\NormalTok{ outputs[etat] = int(etat\_data[1].strip())}
\NormalTok{ transition = dict()}
\NormalTok{ l = f.readline()}
\NormalTok{ while "{-}\textgreater{}" in l:}
\NormalTok{ tr = l.split("{-}\textgreater{}")}
\NormalTok{ transition[int(tr[0].strip())] = int(tr[1].strip())}
\NormalTok{ l = f.readline()}
\NormalTok{ dfa[etat] = transition}
\NormalTok{ l = f.readline()}
\NormalTok{ return (dfa,outputs)}
\NormalTok{def DFAtoSubst(dfa):}
\NormalTok{ subst = ""}
\NormalTok{ for etat in sorted(dfa.keys()):}
\NormalTok{ subst += chr(etat+97)+" {-}\textgreater{} "}
\NormalTok{ for lect in sorted(dfa[etat].keys()):}
\NormalTok{ subst += chr(dfa[etat][lect]+97)}
\NormalTok{ subst += " , "}
\NormalTok{ return subst[:{-}2] \#\# pour la virgule ajoutée en trop}
\NormalTok{def DFAOtoMorph(dfa,outputs):}
\NormalTok{ subst = DFAtoSubst(dfa)}
\NormalTok{ w = dict()}
\NormalTok{ for key in outputs.keys():}
\NormalTok{ w[chr(key+97)] = outputs[key]}
\NormalTok{ return subst, w}
\NormalTok{def getSubst(p:P):}
\NormalTok{ with p.open(\textquotesingle{}r\textquotesingle{}) as f:}
\NormalTok{ \# atteindre le premier état}
\NormalTok{ l = f.readline()}
\NormalTok{ while l != \textquotesingle{}\textbackslash{}n\textquotesingle{}:}
\NormalTok{ l = f.readline()}
\NormalTok{ (dfa, outputs) = readDFAO(f)}
\NormalTok{ return DFAOtoMorph(dfa, outputs)}
\end{Highlighting}
\end{Shaded}
\subsubsection{Calculer la complexité en facteur à l'aide de
NEW}\label{calculer-la-complexituxe9-en-facteur-uxe0-laide-de-new}
\texttt{sumNEW(n,s)} : s est la somme des n-1 premières valeurs de NEW
`compl\_fact\_fib\_V2(n,p) : complexité en facteur synchronisée (obtenue
à l'aide de NEW)
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{\%\%python}
\NormalTok{new\_subst, w = getSubst(P(os.environ["WALNUT\_HOME"])/"Word Automata Library"/"NEW\_fib.txt")}
\NormalTok{new = subst(new\_subst)}
\NormalTok{new\_w = address(new, \textquotesingle{}fib\textquotesingle{},**w)}
\NormalTok{(new\_w{-}ns).gen\_dfa("sumNEW\_fib")}
\end{Highlighting}
\end{Shaded}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{def compl\_fact\_fib\_V2 "?msd\_fib Eq $sumNEW\_fib(n,q) \& p=q+1":}
\end{Highlighting}
\end{Shaded}
\subsubsection{Vérification du
résultat}\label{vuxe9rification-du-ruxe9sultat}
\texttt{compl\_fact\_fib\_V2} est calculée à l'aide de \texttt{NEW}. On
ne peut pas utiliser la technique précédente pour vérifier notre
prédicat. Par contre, on peut confronter \texttt{compl\_fact\_fib\_V1}
et compl\_fact\_fib\_V2 car elle sont issues de deux méthodes
différentes.
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{eval check\_V2 "?msd\_fib An,p $compl\_fact\_fib\_V1(n,p) \textless{}=\textgreater{} $compl\_fact\_fib\_V2(n,p)":}
\end{Highlighting}
\end{Shaded}
\end{document}
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12,<3.13"
# dependencies = [
# "licofage",
# ]
# ///
import stat
from argparse import ArgumentParser, FileType
from licofage.argmisc import Formatter
from licofage.kit import *
from os import environ
import datetime
from pathlib import Path as P
from tempfile import TemporaryDirectory
from shutil import make_archive, copy
today = datetime.date.today().strftime("%Y-%m-%d")
parser = ArgumentParser(
prog="gen_factcomplmultway",
description="""Générateur de Complexité en Facteur
Génère un document .qmd pour calculer la complexité en facteur d'une substitution donnée.
La substitution est supposée Pisot. Le calcul utilise l'outil Walnut.
Utilisation: $ ./gen_factcomplmultfact tri '01/02/0'""",
formatter_class=Formatter,
)
parser.add_argument(
"-o",
"--output",
type=FileType("w"),
default=None,
help="output file (default to [name].qmd)",
)
# parser.add_argument(
# "-z",
# "--zip",
# action="store_true",
# help="create zipped Walnut instance instead of notebook",
# )
# parser.add_argument(
# "-u", "--unroll", action="store_true", help="unroll Walnut scripts"
# )
parser.add_argument(
"-v", "--verbose", action="store_true", help="display more messages"
)
parser.add_argument(
"-S", "--stats", action="store_true", help="display statistics about computations"
)
parser.add_argument("name", help="numeration system and fixpoint naming")
parser.add_argument("subst", help="substitution considered")
parser.add_argument("fullname", help="full name of the studied sequence (for the title)", default=None
)
args = parser.parse_args()
if args.zip:
tmpdir = TemporaryDirectory()
basedir = P(tmpdir.name) / args.name
basedir.mkdir()
walnutdir = basedir / "Walnut"
walnutdir.mkdir()
for s in "Result,Command Files,Custom Bases,Automata Library,Word Automata Library".split(
","
):
(walnutdir / s).mkdir()
walnut_out = open(walnutdir / "Command Files" / "gen_factcomp1.txt", "w")
py_out = open(basedir / "prelim.py", "w")
goscr = basedir / "go"
goscr_out = open(goscr,"w")
if not args.zip and args.output is None:
args.output = open(f"{args.name}.qmd", "w")
if args.fullname is None:
args.fullname = args.name.title()
out = args.output
def to_md(s):
# Injecte dans le .qmd du texte en Markdown
if not args.zip:
out.write(s)
def to_py(s):
# Injecte dans le .qmd du code python
# ou l'ajoute dans le script python du zip
if args.zip:
py_out.write(s)
py_out.write("\n")
else:
out.write(f"""
```{walnut}
%%python
{s}
```
""")
genv = dict()
def do_py(s, ss=None):
# Execute et écrit dans le .qmd ou le script du zip le code python {s} et {ss}
global genv
if args.unroll:
exec(s, genv)
to_py(f"{s}\n{ss}" if ss is not None else s)
def to_wal(s):
# Injecte le texte sous forme de cellule walnut dans le .qmd
# ou l'ajoute au code walnut du zip
if args.zip:
walnut_out.write(s)
walnut_out.write("\n")
else:
out.write(f"""
```{walnut}
{s}
```
""")
def to_pyscript(sname, py):
# Injecte dans le .qmd du code python qui génère un script de walnut et ajoute une cellule de walnut pour appeler le code qui sera généré
# éventuellement execute le code générateur et insère directement le code dans une cellule Walnut
global genv
if args.unroll:
genv["script"] = []
exec(py, genv)
to_wal("\\n".join(genv["script"]))
else:
to_py(f"""script = []
{py}
writefile(f"{sname}", "\\n".join(script))""")
to_wal(f"""load {sname}.txt;""")
if args.zip:
goscr_out.write("""#!/bin/sh
export WALNUT_MEM=64g
export WALNUT_HOME=$(pwd)/Walnut
uv run --python 3.12 --with licofage prelim.py
cd $WALNUT_HOME
echo "load gen_factcomp1.txt;" | java -Xmx$WALNUT_MEM -jar $WALNUT_JAR
""")
to_md(f"""---
title: Complexité en Facteur de {args.fullname}
date: '{today}'
format:
html:
code-fold: false
embed-resources: true
toc: true
toc-location: left
number-sections: true
syntax-definitions:
- walnut.xml
ipynb: default
execute:
cache: true
keep-ipynb: true
allow_errors: true
jupyter: walnut
---
""")
walnut = "{walnut}"
name = args.name
base = f"msd_{name}"
word = name.title()
to_md(f"""
## Construction du système de numération
On défini la substitution, le système de numération et le point fixe associé.
""")
do_py(f"""from licofage.kit import *
import os
setparams({repr(args.verbose)}, {repr(args.stats)}, os.environ["WALNUT_HOME"])
s = subst({repr(args.subst)})
ns = address(s, "{name}")""",
"""ns.gen_ns()
ns.gen_word_automaton()""")
to_md(f"""
## Prédicats de base
`feq_{name}(i,j,n)` : accepte (i,j,n) si les facteurs (i,n) et (j,n)
sont égaux
`first_{name}(i,n)` : accepte (i,n) si c'est un facteur nouveau
`last_{name}(i,n)` : accepte (i,n) si c'est un facteur nouveau et qu'aucun facteur nouveau ne se situe après lui
""")
to_wal(f"""def cut_{name} "?{base} i<=u & j<=v & u+j=v+i & u<n+i & v<n+j":
def feq_{name} "?{base} ~(Eu,v $cut_{name}(i,j,n,u,v) & {word}[u]!={word}[v])":
def first_{name} "?{base} Aj $feq_{name}(i,j,n) => i<=j":
def last_{name} "?{base} $first_{name}(i,n) & Ak k>i => ~$first_{name}(k,n)": """)
to_md(f"""
## Construction de la complexité en facteur par itération
`next_block_{name}(i,j,n)` : (i,n) est un facteur non nouveau et (j,n) est le premier facteur nouveau qui suit. Si un tel facteur (j,n) n'existe pas, j=i
`block_max_right_{name}(i,j,n,l)` : il y a un bloc de l facteurs nouveau entre (i,n) et (j,n) et il est maximal à droite
Suite d'automate / prédicat (j entier non nul) `compte_j_{name}(e,n,p)` : entre (0,n) et (e,n), il y a p facteurs nouveau répartis dans j blocs ou moins
`compl_fact_{name}_V1(n,p)` : complexité en facteur synchronisée
""")
to_pyscript("factcompl_via_iter",f"""
script.append(f'def last_{name} "?{base} $first_{name}(i,n) & Ak k>i => ~$first_{name}(k,n)";')
script.append(f'''def block_max_right_{name} "?{base} (~$first_{name}(i,n) & k=0 & j=i)
| ($first_{name}(i,n)
& (Ap (i<=p & p<=j) => $first_{name}(p,n))
& ~$first_{name}(j+1,n)
& (i+k = j+1))";''')
script.append(f'''def next_block_{name} "?{base} (i<j & ~$first_{name}(i,n) & $first_{name}(j,n) &
(Ap (i<p & p<j) => ~$first_{name}(p,n)))
| (Ek $last_{name}(k,n) & k<i & i=j)";''')
script.append(f'def compte_0_{name} "?{base} $block_max_right_{name}(0,e,p,n)":')
script.append(f'def compte_1_{name} "?{base} Es,q $compte_0_{name}(s,n,q)&(($next_block_{name}(s+1,s+1,n) & p=q & s+1=e+1)|(Ek s+1<k & $next_block_{name}(s+1,k,n) & El $block_max_right_{name}(k,e,l,n) & p=q+l))";')
script.append('eval test_egal_{name} "?{base} Ae,n,p $compte_1_{name}(e,n,p) <=> $compte_0_{name}(e,n,p)";')
j=1
""")
to_pyscript("factcompl_via_iter", f"""
p_test = P(os.environ["WALNUT_HOME"])/"Result"/"test_egal_{name}.txt"
flag = 0
with p_test.open("r") as f_test:
res = f_test.read()
if "false" in res :
flag = 1
elif "true" in res:
flag = 2
else :
print("Un problème est survenu")
if flag == 1:
j+=1
script.append(f'def compte_{{j}}_{name} "?{base} Es,q $compte_{{j-1}}_{name}(s,n,q)&(($next_block_{name}(s+1,s+1,n) & p=q & s+1=e+1)|(Ek s+1<k & $next_block_{name}(s+1,k,n) & El $block_max_right_{name}(k,e,l,n) & p=q+l))";')
script.append(f'eval test_egal_{name} "?{base} Ae,n,p $compte_{{j-1}}_{name}(e,n,p) <=> $compte_{{j}}_{name}(e,n,p)";')
print("Exécutez les deux dernières cellules une fois de plus.")
elif flag == 2 :
script.append(f'def compl_fact_{name}_V1 "?{base} Ee $compte_{{j}}_{name}(e,n,p)";')
print("OK")""")
to_md(f"""
## Vérification inductive de l'automate
`new_first_{name}(i,n)` : accepte le facteur (i,n) si il est nouvellement nouveau
`NEW_{name}[n]` : nombre de facteur nouvellement nouveau de longueur n+1
""")
to_wal(f"""
def new_first_{name} n "?{base} ~$first_{name}(i,n) & $first_{name}(i,n+1)":
""")
to_md(f"""
On applique le semigroup-trick.
```{walnut}
%SGT new_first_{name} {name} NEW_{name}
```
""")
to_wal(f"""
eval check_zero "?{base} $compl_fact_{name}_V1(0,1)":
eval check_rec "?{base} An,p,q ($compl_fact_{name}_V1(n,p) & $compl_fact_{name}_V1(n+1,q)) => p+NEW_{name}[n] = q":
""")
to_md(f"""
## Construction de la complexité en facteur à l'aide de NEW
### Récupérer le morphisme associé à NEW
""")
do_py("""
from pathlib import Path as P
import os
from licofage.kit import subst, address
def readDFAO(f):
# lecture de tous les états, de leurs transitions et sortie
l = f.readline()
dfa = dict()
outputs = dict()
while l != '':
etat_data = l.split()
etat = int(etat_data[0].strip()) #on récupère le nom de l'etat
outputs[etat] = int(etat_data[1].strip())
transition = dict()
l = f.readline()
while "->" in l:
tr = l.split("->")
transition[int(tr[0].strip())] = int(tr[1].strip())
l = f.readline()
dfa[etat] = transition
l = f.readline()
return (dfa,outputs)
def DFAtoSubst(dfa):
subst = ""
for etat in sorted(dfa.keys()):
subst += chr(etat+97)+" -> "
for lect in sorted(dfa[etat].keys()):
subst += chr(dfa[etat][lect]+97)
subst += " , "
return subst[:-2] ## pour la virgule ajoutée en trop
def DFAOtoMorph(dfa,outputs):
subst = DFAtoSubst(dfa)
w = dict()
for key in outputs.keys():
w[chr(key+97)] = outputs[key]
return subst, w
def getSubst(p:P):
with p.open('r') as f:
# atteindre le premier état
l = f.readline()
while l != '\\n':
l = f.readline()
(dfa, outputs) = readDFAO(f)
return DFAOtoMorph(dfa, outputs)
""")
to_md(f"""
### Calculer la complexité en facteur à l'aide de NEW
`sumNEW(n,s)` : s est la somme des n-1 premières valeurs de NEW
`compl_fact_{name}_V2(n,p) : complexité en facteur synchronisée (obtenue à l'aide de NEW)
""")
do_py(f"""
new_subst, w = getSubst(P(os.environ["WALNUT_HOME"])/"Word Automata Library"/"NEW_{name}.txt")
new = subst(new_subst)
new_w = address(new, '{name}',**w)
(new_w-ns).gen_dfa("sumNEW_{name}")
""")
to_wal(f"""
def compl_fact_{name}_V2 "?{base} Eq $sumNEW_{name}(n,q) & p=q+1":
""")
to_md(f"""
### Vérification du résultat
`compl_fact_{name}_V2` est calculée à l'aide de `NEW`. On ne peut pas utiliser la technique précédente pour vérifier notre prédicat. Par contre, on peut confronter `compl_fact_{name}_V1` et compl_fact_{name}_V2 car elle sont issues de deux méthodes différentes.
""")
to_wal(f"""
eval check_V2 "?{base} An,p $compl_fact_{name}_V1(n,p) <=> $compl_fact_{name}_V2(n,p)":
""")
if args.zip:
goscr_out.write(f"""cat << EOF | tr '\\n' '\\0' | tar cvzf ../factcompl.tar.gz --null -T -
Custom Bases/{base}.txt
Custom Bases/{base}_addition.txt
Word Automata Library/{word}.txt
Automata Library/feq_{name}.txt
Automata Library/first_{name}.txt
Result/new_first_{name}.mpl
Word Automata Library/compl_{name}.txt
EOF\n""")
goscr.chmod(goscr.stat().st_mode | stat.S_IEXEC)
walnut_out.close()
py_out.close()
goscr_out.close()
make_archive(f"{args.name}", "zip", tmpdir.name, args.name)
tmpdir.cleanup()
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment