Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Calcul scientifique Python Discussion :

Pouvoir utiliser une fonction à 2 arguments pour trier une liste avec "sort" [Python 3.X]


Sujet :

Calcul scientifique Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mai 2019
    Messages : 6
    Points : 6
    Points
    6
    Par défaut Pouvoir utiliser une fonction à 2 arguments pour trier une liste avec "sort"
    Bonjour !

    Je suis actuellement sur un projet pour mes études d'informatique. Le projet consiste de trier une liste de points (x, y) (avec les x et y positif et entier) et de les comparer pour garder un maximum de points qui possèdent une distance supérieur à un diamètre donné ("r").
    J'ai donc trié la liste avec les x croissant puis en renversant une copie de la liste initial

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    l1.sort( key = operator.itemgetter(0) )
    l2 = list(l1)
    l1 = traitementPoints(l1, r)
     
    l2.reverse()
    l2 = traitementPoints(l2, r)
    Puis j'ai fais la même chose mais cette fois pour les y en remplacant "operator.itemgetter(0)" par "operator.itemgetter(1)"
    Jusque là tout va bien ^^

    A présent je voulais trier la liste grâce au produit scalaire, j'ai créé cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def produitScalaire(u, v):
    	return u[0]*v[0] + u[1]*v[1]
    Mais là où je n'arrive pas à trouver de réponse sur internet c'est pour le passage de la fonction sur la fonction "sort()"

    J'ai donc essayer d'écrire (avec (3,2) un vecteur de référence) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    l.sort( key = lambda x: produitScalaire( (3, 2), x ) )
    print(l)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    l.sort( key = produitScalaire( (3, 2) ) )
    print(l)
    Mais j'ai toujours cette erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    "print(l)
            ^
    SyntaxError: invalid syntax"
    Je vous remercie d'avance pour votre aide !
    Je suis nouveau sur ce forum (qui est mon premier forum ^^), j'espère ne pas avoir fais de faux pas sur la création du sujet ou autre , sinon j'essayerai de les corriger ^^

  2. #2
    Modérateur

    Homme Profil pro
    Architecte technique
    Inscrit en
    juin 2008
    Messages
    14 505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : juin 2008
    Messages : 14 505
    Points : 24 544
    Points
    24 544
    Par défaut
    Salut,

    En général, lorsqu'un SyntaxError arrive de nulle part, il faut s'assurer que l'instruction précédente se termine bien (en général on a oublié de compter le nombre de parenthèses ouvrantes/fermantes).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mai 2019
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Merci pour ta réponse ^^

    Je dois admettre que je suis assez confus et désolé... Car effectivement je n'ai pas fais assez attention à une parenthèse oubliée

    J'aurai juste une dernière question
    Est-ce possible d'effectuer le calcul ci-dessous plus rapidement ? Car j'ai su hier qu'il fallait mieux utiliser "operator.itemgetter" que "lambda"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    u = (3, 2)
    l.sort( key = lambda x: produitScalaire( u, x ) )
    En m'excusant encore pour l'erreur que j'ai faite et pour l'embêtement occasionné...

    Edit :

    Car lorsque j'essaye comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    l.sort( key = produitScalaire( u, ( operator.itemgetter(0), operator.itemgetter(1) ) ) )
    J'ai cette erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    return u[0]*v[0] + u[1]*v[1]
    TypeError: unsupported operand type(s) for *: 'int' and 'operator.itemgetter'

  4. #4
    Modérateur

    Homme Profil pro
    Architecte technique
    Inscrit en
    juin 2008
    Messages
    14 505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : juin 2008
    Messages : 14 505
    Points : 24 544
    Points
    24 544
    Par défaut
    Citation Envoyé par RiivaG Voir le message
    Est-ce possible d'effectuer le calcul ci-dessous plus rapidement ? Car j'ai su hier qu'il fallait mieux utiliser "operator.itemgetter" que "lambda"
    Il faut utiliser operator.itemgetter lorsque çà fait du sens... et c'est à voir au cas par cas.
    D'abord, il faut comprendre qu'operator.itemgetter(n) retourne une fonction qui prendra une séquence en argument pour en retourner le n-ième élément:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> f = operator.itemgetter(3)
    >>> f('012345')
    '3'
    >>>
    Ensuite, dans list.sort(key=...), l'argument passé à key sera une fonction qui recevra chaque élément de la liste pour retourner ce qui permettra de comparer.
    Donc avec key = produitScalaire( u, ( operator.itemgetter(0), operator.itemgetter(1) ) ), on assigne à key le retour de la fonction produitScalaire. Et pour çà elle est appelée avant même de commencer à trier avec ( c(0), operator.itemgetter(1) ) en 2nd argument.

    Et comme çà ne sait pas multiplier un entier par une fonction, çà plante.
    => pour appliquer la fonction produit_Scalaire aux différents éléments de la liste, il faudra toujours fabriquer une autre fonction appelée "fermeture" (avec ou sans lambda) qui dira comment appeler la fonction avec chaque élément.

    Et si vous voulez ajouter des operator.itemgetter la dedans, çà devrait pouvoir s'écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    l.sort( key = lambda x: produitScalaire( u, (  operator.itemgetter(0)(x),  operator.itemgetter(1)(x) ) ))
    Et comparé à:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    l.sort( key = lambda x: produitScalaire( u, x))
    passer directement le "x" plutôt que d'en créer un autre avec deux appels de fonctions sera moins performant et inutile.

    Quoique vous lisiez dans les forums, vous devez d'abord comprendre pour savoir si ce qu'on vous raconte s'applique ou pas à votre cas.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mai 2019
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Je vous remercie encore une fois pour votre réponse ! ^^

    Je comprends beaucoup mieux l'utilisation de "operator.itemgetter()".

    Donc si j'ai bien compris, dans le cas présent le mieux reste d'utiliser ce code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    l.sort( key = lambda x: produitScalaire( u, x))
    Il n'y a pas de moyen d'optimiser un peu plus le temps de traitement ?

    (Je demande ça car j'ai une liste de 10 000 points à traiter, et je travaille dessus actuellement, ça peut prendre pas mal de temps Du coup je cherche à optimiser le plus de temps possible ^^)

  6. #6
    Modérateur

    Homme Profil pro
    Architecte technique
    Inscrit en
    juin 2008
    Messages
    14 505
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : juin 2008
    Messages : 14 505
    Points : 24 544
    Points
    24 544
    Par défaut
    Salut,

    Citation Envoyé par RiivaG Voir le message
    Il n'y a pas de moyen d'optimiser un peu plus le temps de traitement ?

    (Je demande ça car j'ai une liste de 10 000 points à traiter, et je travaille dessus actuellement, ça peut prendre pas mal de temps Du coup je cherche à optimiser le plus de temps possible ^^)
    En l'état, vous pouvez juste supprimer l'appel à produitScalaire en incluant le calcul dans la définition du lambda.

    Après vous pouvez décomposer l'opération en deux:
    • calcul des produits scalaires,
    • rangement des points,

    et essayer d'utiliser numpy.dot pour les calculs (être plus efficace) ou les paralléliser (utiliser plus de ressources).

    Après il faut vous poser des questions côté conception: avez vous vraiment besoin de calculer le produit scalaire avec les 10000 points?

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Membre expérimenté

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    mars 2013
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : mars 2013
    Messages : 808
    Points : 1 604
    Points
    1 604
    Par défaut
    Citation Envoyé par RiivaG Voir le message
    Je vous remercie encore une fois pour votre réponse ! ^^

    Je comprends beaucoup mieux l'utilisation de "operator.itemgetter()".

    Donc si j'ai bien compris, dans le cas présent le mieux reste d'utiliser ce code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    l.sort( key = lambda x: produitScalaire( u, x))
    Il n'y a pas de moyen d'optimiser un peu plus le temps de traitement ?

    (Je demande ça car j'ai une liste de 10 000 points à traiter, et je travaille dessus actuellement, ça peut prendre pas mal de temps Du coup je cherche à optimiser le plus de temps possible ^^)

    1) Si vous voulez les points relativement à une certaine distance, je me demande pourquoi vous calculez le produit scalaire.... La distance entre 2 points A, et B de coordonnées respectives (xA,yA) et (xB, yB), c'est sqrt((xB-xA)²+(yB-yA)²).

    2) Si vous voulez qqch de rapide, il y a numpy qui est parfaitement adapté pour cela. 10 000 points ce sera instantanné.

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mai 2019
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    et essayer d'utiliser numpy.dot pour les calculs (être plus efficace) ou les paralléliser (utiliser plus de ressources).

    Après il faut vous poser des questions côté conception: avez vous vraiment besoin de calculer le produit scalaire avec les 10000 points?
    Je regarderai ce soir l'utilisation de "numpy.dot" ^^ C'est vrai que je me suis posé la question mais c'est compliqué de s'arrêter dans une liste sans savoir si les points après ne sont peut-être pas à une distance r mais je vais me repencher dessus tête reposé ce soir !

    Je vous remercie de nouveau pour votre aide et pour votre réponse !

    Citation Envoyé par lg_53 Voir le message
    1) Si vous voulez les points relativement à une certaine distance, je me demande pourquoi vous calculez le produit scalaire.... La distance entre 2 points A, et B de coordonnées respectives (xA,yA) et (xB, yB), c'est sqrt((xB-xA)²+(yB-yA)²).

    2) Si vous voulez qqch de rapide, il y a numpy qui est parfaitement adapté pour cela. 10 000 points ce sera instantanné.
    Pour reprendre le problème de base, je possède des fichiers de points en entrée (nombre de points, la distance r, et ensuite la série de x y des points par exemple :

    2
    10
    0 1
    10 20

    que je récupère en input au début de mon programme et à l'aide de la commande python3 tp.py <(nom de fichier)).

    Le but de mon programme est de trouver le maximum de points tout en respectant le fait que les points doivent avoir une distance entre eux supérieur à r. Du coup jusqu'à présent je prenais ma liste et je la triais soit grâce aux abscisses ou aux ordonnées qui ma permis de faire mon traitement de gauche à droite (et inversement) puis de bas en haut (et inversement). Le produit scalaire me permet de pouvoir trier la liste en "diagonale" avec un vecteur à un certain degré, pour essayer de trouver plus de points en résultat.

    Je ne sais pas si mon raisonnement n'est pas trop pratique... ^^' Mais pour l'instant je ne voyais que cette solution. J'ai commencé à réfléchir ce matin pour essayer d’entamer le traitement "dans le tas" au milieu des extrémités mais pour l'instant je ne sais pas comment je vais procéder

    Je ne sais pas si cela vous éclaire un peu plus ^^'

    Voici mon traitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def calcDistanceValide(a, b, r):
    	return ((a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1])) < (r*r)
     
    def traitementPoints(l, r):
     
    	i = 0
    	for x in l:
    		j = i+1
    		while(j<len(l)):
    			if( calcDistanceValide(x, l[j], r) ):
    				del(l[j])
    			else:
    				j+=1
    		i+=1
     
    	return l
    et une image pour illustré pour un ensemble de 100points (bleu = valide, vert = "supprimé")
    Nom : 100.jpg
Affichages : 40
Taille : 285,9 Ko

  9. #9
    Membre expérimenté

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    mars 2013
    Messages
    808
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : mars 2013
    Messages : 808
    Points : 1 604
    Points
    1 604
    Par défaut
    Votre code semble fonctionner. Si c'est la maximalité (du nombre de points restants) qui vous pose problème alors là c'est plutot un problème algorithmique (et il y a une section sur le forum pour cela), qui est indépendant de python. Car en effet cette maximalité nécéssite des algos particulier pour la garantir. J'ai bien quelques idées en tête mais je n'ai pas vraiment le temps de les pousser pour voir si elles garantissent la maximalité (ce qui est loin d'être trivial), donc je préfère me taire pour ne pas vous envoyer dans une mauvaise direction. Quoi qu'il en soit sur le forum d'algorithmique vous trouverez surement de meilleur connaisseur des algorithmes de couverture spatiale maximal.

  10. #10
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mai 2019
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Bonsoir,

    Excusez-moi du temps de réponse, j'ai un emploi du temps un peu chargé en ce moment ^^' En tout cas je vous remercie pour cette aide et ces informations précieuses !! J'ai vu rapidement pour la fonction, je verrai fin de week-end pour essayer de l'appliquer

    Citation Envoyé par lg_53 Voir le message
    Votre code semble fonctionner. Si c'est la maximalité (du nombre de points restants) qui vous pose problème alors là c'est plutot un problème algorithmique (et il y a une section sur le forum pour cela), qui est indépendant de python. Car en effet cette maximalité nécéssite des algos particulier pour la garantir. J'ai bien quelques idées en tête mais je n'ai pas vraiment le temps de les pousser pour voir si elles garantissent la maximalité (ce qui est loin d'être trivial), donc je préfère me taire pour ne pas vous envoyer dans une mauvaise direction. Quoi qu'il en soit sur le forum d'algorithmique vous trouverez surement de meilleur connaisseur des algorithmes de couverture spatiale maximal.
    D'accord ! J'irai jeter un oeil plus tard, après avoir avancé d'autres projets ^^
    En tout cas encore merci !

    En attendant, je n'ai plus trop de question sur ce sujet pour l'instant (Je recréerai un nouveau sujet si jamais j'en ai besoin ^^)
    Je passe le sujet en résolu

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Toutes versions] Pouvoir utiliser une fonction dans tous mes classeurs Excel
    Par SylvainM dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 27/03/2014, 22h10
  2. Trier une liste avec Collections.sort(liste)
    Par nakry dans le forum java.util
    Réponses: 18
    Dernier message: 25/09/2013, 16h52
  3. Réponses: 1
    Dernier message: 08/06/2008, 13h15
  4. Changer une fonction qui utilise une liste par un tableau!
    Par sara21 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 03/05/2007, 14h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo