Déterminer une relation de récurrence

Discutez d'informatique ici !
asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 03 Mai 2019, 23:16

Merci pour la rectification ! tu est vraiment très calé c'est impressionnant ! Mais j'apprend énormément donc c'est cool :)

C'est exactement ce à quoi je pensais ! Mais je ne sais pas pourquoi, je bloque avec la récursivité, c'est comme si je ne savais plus codé en python ... désolé

Du coup je me retrouve avec cette algorithme :

https://i.postimg.cc/zBfJhK10/Capture.png

Petite précision, je n'arrive pas à déterminer comment tester si la somme V[i] que je suis en train de calculé sera présente dans mon tableau. Il faut que je fasse un appel récursif afin de déterminer qu'elle valeur V[i] il faut que je trouve à l'indice "i" non ?

Merci par avance,



Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

Re: Déterminer une relation de récurrence

par fatal_error » 03 Mai 2019, 23:57

ne prendre que l'indice i pour track m'a l'air un peu douteux...
sauf si tu as fait des justifications préalables que j'ai pas vues sur ce fil.

par exemple
si tu as la chaine de symboles
FFGGGFFF
avec A =1 et B ==-1
supposons la suite
13531555
tu visites le premier 1 (donc now lastVisited==F)
tu visites 3
tu visites 5
tu visites 3
tu veux maintenant calculer V(4) (correspondant à 1555), sachant que ton dernier symbole est G
tu peux donc visiter 1 (vu que meme symbole: G) puis apres visiter 555 (dont la somme > 0)
donc dans ton approche tu stockes V(4) = 1-5+5+5=11

maintenant supposons que tu visites pas les symbole G
tu visites 1,3, ton dernier symbole est donc F en arrivant sur T(4)==1
SI tu decides de prendre 1 tu te paies -1, et apres tu te paies encore -5+5+5 ce qui n'est pas interessant
SI tu decides de pas prendre 1, alors tu prends 5+5+5 (qui sont tous de symbole F) == 15!! (et non 11)

donc t'as interet à dans ton cache ne pas associer i->une somme, mais (i, lastSymbole)->une somme

---
concernant la réponse très basique à ta question [...era présente dans mon tableau]:
tu initialises track avec des 1e7, et tu
if track[i]<1e7
retourner track[i]..
//some computation
track[i]=res

En python tu peux te permettre de stocker n'importe quoi dans tes tableaux faiblement typés donc t'as qu'à initialiser track[i] à None
Modifié en dernier par fatal_error le 04 Mai 2019, 00:06, modifié 1 fois.
Raison: conjuguezon
la vie est une fête :)

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 04 Mai 2019, 10:30

J'ai décidé d'utiliser un dictionnaire, avec un tuple (i, lastvisited) comme clé, associée à une valeur qui sera la somme V[i].

J'initialise mon dictionnaire de la sorte :

https://i.postimg.cc/BQ8T4MMp/Capture.png

J'obtiens donc le code suivant :

https://i.postimg.cc/ZqL7pwk3/Capture.png

Merci de ton aide, j'apprécie que tu ne me donne pas la réponse, ça me permet de chercher par moi même tout en comprenant ;)

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

Re: Déterminer une relation de récurrence

par fatal_error » 04 Mai 2019, 11:29

vu que t'as probablement fini ton exo?
quelques remarques plus d'ordre logiciel:

1)
dans ton ecriture:
Code: Tout sélectionner
    if ..
        return A
    else
        return B

généralement tu as deux ecoles:
Code: Tout sélectionner
    if ..
        res = A
    else ..
        res = B
    return res

(c'est un flamewar donc t'auras les pros&cons sur le net. Grossierement:
comme tu as qu'un seul return, tu es sûr (par exemple avec ton cache, de pas rater une instruction, alors qu'avec ton approche tu duppliques une ligne)

ou
Code: Tout sélectionner
    if ..
        return A
    return B

ici tu t'évites des indentations inutiles mais par exemple avec ton cache t'es obligé de l'écrire dans le if et apres

donc de pref choisis l'un ou l'autre, mais un return dans un if et un return dans un else... c'est cumuler les inconvénients des deux!


2) dans l'implementation (c'est un peu de ma faute aussi) tu vois que tu as que des i+1 partout (sauf la condition d'arret ou i = len(c)-1

donc au final c'est comme si t'avais que des i, et que t'appelais ta fonction avec iInitial+1 (au lieu de iInitial) idem 0 au lieu de -1

C'est mieux pour plusieurs raisons:
- tu evites une etourderie en oubliant un +1 qqpart
- ton contrat de fonction est plus naturel: tu appel rectopdown(0) avec 0 directement l'index (c'est un peu plus intuitif...)

3) tjs avec contrat de fonction, rectopdown appartient à une classe. donc quitte à avoir une classe, autant la construire avec a,b,t,c et track
et simplifier rectopdown avec juste en argument (i, lastVisited)

4) plutot d'ordre algorithmique:
si tu as la suite de symboles (donc tous différents)
ABCDFEG
si tu visites A,B tu calcules rectopdown(2, 'B')
si tu visites A, skip B, tu vas aussi calculer rectopdown(2,'A')
et tu auras storé dans ton cache (2,'B') et (2,'A') alors que la somme est forcément la meme.
donc c'est un peu dommage, pe vois-tu comment faire mieux?

5) en etant "factorisant au max", on peut ecrire
Code: Tout sélectionner
if ..in track
    return ..

nopickup = rectoprown(i, lastvisited)
rec_pickup = rectoprown(i, c(i))
if c(i)==lastvisited
    pickup = rec_pickup + self.A*T(i)
else
    pickup = rec_pickup + self.B*T(i)

maxi = max(nopickup, pickup)
track[(..)] = maxi
return maxi

ce qui te fait quelques ligne de moins à taper (et surtout moins de pblms liés au copier coller)
et soit dit en passant te fait respecter la marge des 80c
la vie est une fête :)

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 04 Mai 2019, 12:22

Je n'ai pas du tout fini mon exercice LOL .. :/ Il me reste du bottom Up ensuite à implémenter. Mais je n'i toujours pas la bonne somme V[i] avec la mémoïsation :/

J'ai rectifier tout ça au niveau des "i +1" c’est bien plus claire effectivement ! il me reste plus que les "i + 1" pour les appels récursifs !

Tout a fait ! j'organiserais tout les attributs de ma classe à la fin ;) Ca sera encore plus évident au premier coup d’œil

En ce qui concerne mon blocage voici mon code actuellement , j'ai l'impression qu'aucune valeur V[i] s'ajoute dans mon dictionnaire track :/


Initialisation de track :

Code: Tout sélectionner
track = {(2000000, 2000000): 2000000}

            total = self.topdown.rectopdown(t, c, a, b, track)

code :

Code: Tout sélectionner
    def rectopdown(self, t, c, a, b, track,  i=0, lastvisited=-170):

        if i == len(c):
            return 0

        if (i, lastvisited) in track:
            return track.get((i, lastvisited), "fail")

        if c[i] == lastvisited:

            maxi = max(self.rectopdown(t, c, a, b, track, i + 1, lastvisited), a * t[i] + self.rectopdown(t, c, a, b, track, i + 1, lastvisited))
        else:
            maxi = max(self.rectopdown(t, c, a, b, track, i + 1, lastvisited), b * t[i] + self.rectopdown(t, c, a, b, track, i + 1, lastvisited))

        track[i, lastvisited] = maxi
        return maxi


En affichant un print(maxi), je m'apercoit que "maxi = 0" dans tous les cas de figure ... Mais pourquoi maxi ne prend pas la valeur du "max(....)" associé ...

Merci par avance
Modifié en dernier par asse211 le 04 Mai 2019, 13:18, modifié 1 fois.

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

Re: Déterminer une relation de récurrence

par fatal_error » 04 Mai 2019, 13:08

edit: je perds la boule avec toutes les images que tu as postées...
vraiment si tu peux mettre ton code sous format texte c'est mieux..

concernant maxi, je ne sais pas, prends un petit T, genre T=1 ou T=1 2 et regarde ce qui se passe et ce à quoi tu t'attends
la vie est une fête :)

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 04 Mai 2019, 13:25

J'ai édité mon message au dessus ça sera plus claire.

Si je prend T = [3, 9, 2] et C = [2, 2, 5] avec A = 2 et B = -5

mes print de la sorte :

Code: Tout sélectionner
        if c[i] == lastvisited:

            maxi = max(self.rectopdown(t, c, a, b, track, i + 1, lastvisited), a * t[i] + self.rectopdown(t, c, a, b, track, i + 1, lastvisited))
            print(maxi)
        else:
            maxi = max(self.rectopdown(t, c, a, b, track, i + 1, lastvisited), b * t[i] + self.rectopdown(t, c, a, b, track, i + 1, lastvisited))
            print(maxi)


Je devrais obtenir des valeurs au moins, or seulement 3 "0" s'affichent en console.

Soit je n'ai rien compris aux appels récursifs, soit je deviens fou ^^

Merci par avance

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

Re: Déterminer une relation de récurrence

par fatal_error » 04 Mai 2019, 13:38

edit: pour l'application manuelle:
T=3 9 2
C=2 2 5
B=-5, A=2
le premier elem tu passes dans le else: soit tu prends rien et tu recurses avec lastvisited==-170, soit tu prends et tu recurses avec lastvisited==2
donc dans ta fonction tu peux ecrire qqch comme
if i==1
print(lastvisited)
pour vérifier par exemple que tes deux symboles précédents possibles aient été "exploré"

maintenant, t'as fait typiquement l'erreur que tu aurais pu éviter en ecrivant du code concis:
dans ton else, tu recurse avec lastvisited alors que ca devrait etre c(i) (l'elem que tu as pris a par définition une valeur différente de lastvisited...)
la vie est une fête :)

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 04 Mai 2019, 13:47

Rhoo je m'en veux ! un sale copier coller du code que j'avais mis plus bas en commentaire :/

C'est rageant :/ Sorry pour la perte de temps ^^

Mais il y avait une autre erreur finalement : A chaque cas je ne retournais pas "maxi", donc forcément que ça ne pouvait pas marcher !

En ce qui concerne la complexité de ce nouvel algo', il est simplifié en terme de temps, mais je garde toujours la complexité logarithmique à cause des 2 appels récursifs dans le max(...) non ?

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 04 Mai 2019, 19:14

Je fait actuellement l'approche Bottom Up, pour raccourcir encore plus le temps d’exécution.

Je me permet de reposer ma question au sujet de la complexité :

En ce qui concerne la complexité de ce nouvel algo', il est simplifié en terme de temps, mais je garde toujours la complexité logarithmique à cause des 2 appels récursifs dans le max(...) non ?


Merci par avance

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

Re: Déterminer une relation de récurrence

par fatal_error » 04 Mai 2019, 19:41

oui ta question m'a un peu séché mais j'en suis venu à bout:

sans mémo c'est 2^n

avec mémo, on obtient du o(n^2log(n))
voici à quoi je parviens:

on peut écrire une table de vérité
000
001
010
011

on lit de gauche à droite comme si on parcourait T
0 ca veut dire qu'on ignore l'elem.
1 ca veut dire qu'on le visite
evidemment si on a trois nombres, on a nos 2^3 possibilités.
le but c'est de simplifier les lignes non explorées parce qu'on utilise le cache

sur deux nombres
00
01
10
11
on a testé 4 sommes

on remarque notamment que derriere le groupe de 1, (10,11) on connait la somme maximale (indépendamment de tout ce qu'on peut foutre devant)
qu'on note s(2): autrement dit si on visite le premier nombre, on sait que quoi qu'il arrive la somme maximale est cachée dans s(2)

on pourrait donc simplifier en
Code: Tout sélectionner
00
01
s2

si on rajoute un nouveau nombre, on a
Code: Tout sélectionner
000
001
010 <---
011 <---s2, mais on connait pas encore donc il faut explorer avant de cacher
100 <<il s'agit d'un nouveau symbole donc obliger de calculer les sommes
101
110 <---
111 <---s2, donc une seule explo (utilisation du cache)


ici on peut représenter des blocs genre
Code: Tout sélectionner
        0
        0
        0 P(2)
P(3) =  0
        100
        101
        110
        111

le nombre d'appel de fonction sur la partie 0, ben c'est juste P(2)+1

le nombre d'appel de fonction sur la partie "1" de P(3) peut être représenté par le nombre de noeuds de l'arbre:

Code: Tout sélectionner
1 -> s2
  -> 0 -> 0
       -> 1

si on représente P(4) on obtient
Code: Tout sélectionner
        0
        ..
        0 P(3)
P(4) =  0
        10
        10...P(2)
        10
        100
        101
        110
        111

et pareil:
Code: Tout sélectionner
1 -> s3
  -> 0 -> s2
       -> 0 -> 0
            -> 1

cqu'on voit c'est qu'on a juste ajouté deux noeuds.

au final, le nombre de call de fonction T(n) c'est donc

T(n) = T(n-1)+1 + nbNodes(n)

avec T(1) = 2 (un call initial + un call pour pour piocher 0)

avec nbNodes(n) = nbNodes(n-1)+2 et nbNodes(1) = 1
idem nbNodes(n) == 1+2*(n-1)==2n-1

et donc T(n) = T(n-1)+2n
par téléscopage? T(n) = 2n + 2(n-1) + 2(n-2) + ... + 1 = 2(()) +1 = 2(sum(k=0, n)k)+1 = n(n+1)+1

Il y a donc n(n+1)+1 appel de fonction, avec (n-1)n+1 lecture de cache et donc la complexité de ton algo est de l'ordre de
o(n^2log(n)) où log(n) représente la complexité de ton dic en lecture
la vie est une fête :)

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 04 Mai 2019, 22:14

Ouff !! D'accord bon et bien tu ma séché en retour ^^

J'ai essayé de suivre ta justification et c'est très visuel de faire comme ça !
Je trouve aussi une complexité logarithmique donc tout va bien ^^

Allez demain je m'attaque au Bottom Up ! Encore merci

Je te tiens au courant quand j'ai tout fini ;)

Bonne soirée !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

Re: Déterminer une relation de récurrence

par fatal_error » 04 Mai 2019, 23:10

c'est pas logarithmique:
sans memo c'est expo et avec memo le nom est plus proche de polynomiale n^2<n^2log(n)<n^3
en regardant https://fr.wikipedia.org/wiki/Analyse_d ... lgorithmes on aurait envie de dire complexité quadrarithmique (mais pas sur que le terme existe :D )
la vie est une fête :)

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 05 Mai 2019, 00:37

J'opterais pour dire que c'est une complexité quadratique ;) ^^

Mais bien vu pour le mélange des 2 en soit tu na pas tord !

PS: tu me mets le doute pour la complexité sans la mémo ... je trouva ça moi :

T(n)= Θ(n^(log_1 (2)))


Et j'en déduis que c'est plutôt logarithmique ... mais effectivement ça serait plutôt exponentielle nan ?

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

Re: Déterminer une relation de récurrence

par fatal_error » 05 Mai 2019, 08:09

hi,

pas sûr de comprendre ta notation pour log_1(2)
log_3(x) ca vaut 1 si x==3, log_4(x) ca vaut 1 si x==4 et on s'attendra à log_1(x)==1 si x vaut 1 sauf que log_..(1)=0

sans mémo tu as pas de cache, donc c'est juste T(n)=2T(n-1) //tu pioches ou pas
et evidemment T(n)=2T(n-1) ~2^n==exp(nln(2))
la vie est une fête :)

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 05 Mai 2019, 08:37

Slt,

En gros Tout ça : "log_1(2)" est en exposant du "n" : n^log_1(2)
En sachant que c'est "log_de_petit_1(2)"

Donc c'est bien de la complexité exponentielle vu que c'est "n" à la puissance de log()
? Je peu peut-être simplifier cette écriture : "n^log_1(2)" aussi pour que ce soit plus visuel non ?

Ha oui je vois ce que tu veux dire sans mémo, c'est a dire que j'ai fait un aglo glouton auparavant qui pioche ou non exacte ! ça complexité est belle est bien de T(n)=2T(n-1)

Merci

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 05 Mai 2019, 21:32

Je me permet de te relancer, la date du rendu approche ^^

Malheureusement grosse galère sur l'algorithme Bottom Up ... je ne comprends pas trop comment l'implémenter:

- Il faut remplir le tableau track dans le sens inverse de la mémoïsation ... or ça signifie qu'il faut partir de l'autre coté de la liste ?? c'est impossible dans ce problème mathématique, non ?

-Il faut aussi que j'implémente un second tableau, par exemple "keep[]" de la même taille que "track[]" qui lui stockera les valeurs V[i] max a chaque étape .. enfin je ne comprends pas l'utilité d'un second tableau ...

Merci par avance,

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

Re: Déterminer une relation de récurrence

par fatal_error » 05 Mai 2019, 23:19

On sait que a la fin de lalgo, on aura appelé V avec tous les couple (i, C(j)) possibles (pour i donné, plus precisement cest les j<i)
Lidee de partir du bas cest genre: vu que de toute favon V(3,j) va appeler V(4,..) si on a deja calculé V(4,j) pour tout j, alors cest gagné vu quil est dans le cache.

Donc si tu pars de la fin tu calcules tous les V(n,j) et mettons tu les mets ds un tableau v. ensuite tu calcules les V(n-1, j) et pour un j donné soit tu prends lelem et dc tu cherche dans v la valeur de C(n-1)soit tu prends pas et tu cherches dans v la valeur pour le symbole j.
Du coup tu prux mettre a jour v (qui contient maintenant les valeurs max associées à tous les symboles jusqua n-1) et tu remontes petit a petit.
la vie est une fête :)

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 06 Mai 2019, 00:03

D accord donc si j'ai bien compris il suffit passer les appels récursifs en "i - 1" ? afin de parcourir les possibilités dans le sens inverse ;)

Dans mon cours il est question d'un tableau track[], celui si très bien je l'est, or pour la méthode bottom up il est question d'un tableau supplémentaire nommé "keep[]". Je ne vois pas très bien à quoi pourrait servir un tableau supplémentaire dans mon cas ...

Merci! bonne nuit ^^

asse211
Membre Naturel
Messages: 47
Enregistré le: 01 Mai 2019, 10:05

Re: Déterminer une relation de récurrence

par asse211 » 06 Mai 2019, 09:57

[edit] Autre précision que je viens apporter et que je vient de comprendre à l'instant ...

- On ne doit pas utiliser d'appels récursifs dans une approche Bottom Up, d'ou les 2 tableaux :

-track[]
-keep[]

Mais je ne comprend pas comment on peut éviter d'utiliser de la récursions juste avec 2 tableaux ...

Merci par avance,

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 5 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite