""" Version 1.0 Date 27/03/2025 Auteur : Stéphan Peccini Ce script met à jour les valeurs ihh en fonction des données de part de marché des pays où des acteurs. https://fr.wikipedia.org/wiki/Indice_de_Herfindahl-Hirschmann Important : ----------------------- Pour faciliter le travail, tout est fait avec un graphe NetworkX et ensuite sauvé au format DOT sans aucune structure hiérarchique. Il suffit alors de passer le fichier résultat dans beautify.py pour avoir un fichier DOT conforme aux attentes. """ import networkx as nx from networkx.drawing.nx_pydot import write_dot import sys import re def calcul_ihh(graphe, depart, arrivee): ihh = 0 for noeud in arrivee: if depart in noeud: # Gestion simplifiée de l'intégration des Connexes if arrivee not in list(graphe.successors(depart)): depart = list(graphe.predecessors(noeud))[0] relation = graphe.get_edge_data(depart, noeud) ihh += int(int(relation['label'].strip("%"))**2) ihh = int(round(ihh/100)) return ihh def mettre_a_jour_ihh(graph, noeuds): for noeud in noeuds: sous_graphe = nx.DiGraph() try: for chemin in nx.edge_bfs(graph, source=noeud): sous_graphe.add_edge(*chemin) # Ajouter les attributs des nœuds for node in sous_graphe.nodes(): if node in graph.nodes(): sous_graphe.nodes[node].update(graph.nodes[node]) # Ajouter les attributs des arêtes for edge in sous_graphe.edges(): if edge in graph.edges(): sous_graphe.edges[edge].update(graph.edges[edge]) niveaux_ihh = nx.get_node_attributes(sous_graphe, "niveau") operation = noeud.split('_')[0] # La hiérarchie Traitement est particulière. En effet, les acteurs du traitement se fournissent # auprès des acteurs de l'extraction. Il y a une relations entre chaque acteur de traitement # et les pays auprès desquels il se fournit en minerai. if "Traitement" in operation: noeuds_pays_ihh = [n for n, v in niveaux_ihh.items() if (v == "11" or v == "1011") and operation in n] noeuds_acteurs_ihh = [n for n, v in niveaux_ihh.items() if (v == "12" or v == "1012" and operation in list(sous_graphe.predecessors(n))[0]] else: noeuds_pays_ihh = [n for n, v in niveaux_ihh.items() if (v == "11" or v == "1011")] noeuds_acteurs_ihh = [n for n, v in niveaux_ihh.items() if (v == "12" or v == "1012")] # Le calcul de l'indice de Herfindahl-Hirschmann se fait normalement au niveau d'une entreprise. # Toutefois, il se fait au niveau des pays et au niveau des acteurs pour l'opération qui est menée. ihh_pays = calcul_ihh(sous_graphe, noeud, noeuds_pays_ihh) nx.set_node_attributes(graph, {noeud: {"ihh_pays": f"{ihh_pays}"}}) ihh_acteurs = calcul_ihh(sous_graphe, noeud, noeuds_acteurs_ihh) nx.set_node_attributes(graph, {noeud: {"ihh_acteurs": f"{ihh_acteurs}"}}) except nx.NetworkXNoPath: pass # Ignore les chemins inexistants return graph def mettre_a_jour_ihh_reserves(graph, noeuds): for noeud in noeuds: sous_graphe = nx.DiGraph() try: for chemin in nx.edge_bfs(graph, source=noeud): sous_graphe.add_edge(*chemin) # Ajouter les attributs des nœuds for node in sous_graphe.nodes(): if node in graph.nodes(): sous_graphe.nodes[node].update(graph.nodes[node]) # Ajouter les attributs des arêtes for edge in sous_graphe.edges(): if edge in graph.edges(): sous_graphe.edges[edge].update(graph.edges[edge]) niveaux_ihh = nx.get_node_attributes(sous_graphe, "niveau") noeuds_pays_ihh = [n for n, v in niveaux_ihh.items() if (v == "11" or v == "1011")] # Le calcul de l'indice de Herfindahl-Hirschmann se fait normalement au niveau d'une entreprise. # Toutefois, il se fait au niveau des pays et au niveau des acteurs pour l'opération qui est menée. ihh_pays = calcul_ihh(sous_graphe, noeud, noeuds_pays_ihh) nx.set_node_attributes(graph, {noeud: {"ihh_pays": f"{ihh_pays}"}}) except nx.NetworkXNoPath: pass # Ignore les chemins inexistants return graph def main(): """ Fonction principale pour interagir avec l'utilisateur. """ if len(sys.argv) != 3: print("Usage: python ihh.py fichier_en_entree.dot fichier_en_sortie.dot") return fichier_en_entree = sys.argv[1] fichier_en_sortie = sys.argv[2] graph = nx.DiGraph(nx.nx_agraph.read_dot(fichier_en_entree)) niveaux = nx.get_node_attributes(graph, "niveau") noeuds_niveau_10 = [n for n, v in niveaux.items() if (v == "10" or v == "1010") and not re.search(r'Reserves', n)] noeuds_niveau_10.sort() graphe = mettre_a_jour_ihh(graph, noeuds_niveau_10) noeuds_niveau_10 = [n for n, v in niveaux.items() if (v == "10" or v == "1010") and re.search(r'Reserves', n)] noeuds_niveau_10.sort() graphe = mettre_a_jour_ihh_reserves(graphe, noeuds_niveau_10) write_dot(graphe, fichier_en_sortie) if __name__ == "__main__": main()