Ramin Yahyapour

163 papers A* 1A 3B 11C 14Misc 2Journal 54Unranked 71
YearRankTypeTitle / Venue / Authors
2026 J jnl
Comput. Electron. Agric.
Jonathan Henrich, Christian Post, Maximilian Zilke, Parth Shiroya, Emma Chanut, Amir Mollazadeh Yamchi, Ramin Yahyapour, Thomas Kneib, Imke Traulsen
2026 J jnl
IEEE Trans. Netw.
Biao Hou, Song Yang, Youqi Li, Fan Li, Liehuang Zhu, Xu Chen, Ramin Yahyapour
2025 J jnl
Int. J. Intell. Syst.
Qingyang Liu, Ramin Yahyapour
2025 J jnl
CoRR
Jonathan Henrich, Christian Post, Maximilian Zilke, Parth Shiroya, Emma Chanut, Amir Mollazadeh Yamchi, Ramin Yahyapour, Thomas Kneib, Imke Traulsen
2025 Misc conf
CSR
Aytaj Badirova, Shirin Dabbaghi Varnosfaderani, Ramin Yahyapour
2025 J jnl
J. King Saud Univ. Comput. Inf. Sci.
Hao Xi, Yuanhao Xi, Chuanping Hu, Ramin Yahyapour
2025 B conf
IJCNN
Yuanhao Xi, Xiaohuan Bing, Ramin Yahyapour
2025 J jnl
CoRR
Yuanhao Xi, Xiaohuan Bing, Ramin Yahyapour
2025 B conf
NCA
Mauladi, Ramin Yahyapour
2025 conf
ICNLSP
Ramazan Ali Bahrami, Ramin Yahyapour
2025 J jnl
CoRR
Ramazan Ali Bahrami, Ramin Yahyapour
2025 B conf
COMPSAC
Aasish Kumar Sharma, Christian Boehme, Patrick Gelß, Ramin Yahyapour, Julian M. Kunkel
2025 J jnl
CoRR
Aasish Kumar Sharma, Christian Boehme, Patrick Gelß, Ramin Yahyapour, Julian M. Kunkel
2024 J jnl
Multim. Tools Appl.
Qingyang Liu, Ramin Yahyapour, Hongjiu Liu, Yanrong Hu
2024 J jnl
Inf. Sci.
Shirin Dabbaghi Varnosfaderani, Piotr Kasprzak, Aytaj Badirova, Ralph Krimmel, Christof Pohl, Ramin Yahyapour
2024 conf
LREC/COLING
Shirin Dabbaghi Varnosfaderani, Canasai Kruengkrai, Ramin Yahyapour, Junichi Yamagishi
2024 J jnl
CoRR
Shirin Dabbaghi Varnosfaderani, Canasai Kruengkrai, Ramin Yahyapour, Junichi Yamagishi
2024 conf
GIL
Jonathan Henrich, Christian Post, Thomas Kneib, Ramin Yahyapour, Sven Bingert, Imke Traulsen
2024 conf
FiCloud
Aytaj Badirova, Faraz Fatemi Moghaddam, Ramin Yahyapour
2024 J jnl
Expert Syst. Appl.
Qingyang Liu, Ramin Yahyapour
2024 J jnl
J. Supercomput.
Reza Rabieyan, Ramin Yahyapour, Patrick Jahnke
2024 J jnl
J. Grid Comput.
Reza Rabieyan, Ramin Yahyapour, Patrick Jahnke
2024 conf
Open Identity Summit
Aytaj Badirova, Bithin Alangot, Theo Dimitrakos, Ramin Yahyapour
2023 J jnl
IEEE Access
Aytaj Badirova, Shirin Dabbaghi, Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2023 conf
ICUFN
Rajeshwari Gadathas Krishna Babu, Aytaj Badirova, Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2023 conf
ICUFN
Rajeshwari Gadathas Krishna Babu, Aytaj Badirova, Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2023 conf
CoRDI
Firas Al Laban, Jan Bernoth, Michael Goedicke, Ulrike Lucke, Michael Striewe, Philipp Wieder, Ramin Yahyapour
2023 J jnl
J. Intell. Fuzzy Syst.
Qingyang Liu, Ramin Yahyapour
2023 conf
JCDL
Triet Ho Anh Doan, Sven Bingert, Ramin Yahyapour
2022 J jnl
IEEE Trans. Serv. Comput.
Song Yang, Fan Li, Ramin Yahyapour, Xiaoming Fu
2022 J jnl
IEEE Trans. Parallel Distributed Syst.
Song Yang, Lei Jiao, Ramin Yahyapour, Jiannong Cao
2022 ed.
EUNIS
Jean-François Desnos, Ramin Yahyapour, Raimund Vogl
2022 J jnl
Data Intell.
Triet Ho Anh Doan, Sven Bingert, Ramin Yahyapour
2021 conf
FiCloud
Aytaj Badirova, Shirin Dabbaghi Varnosfaderani, Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2021 J jnl
J. Netw. Comput. Appl.
Samaneh Sadegh, Kamran Zamanifar, Piotr Kasprzak, Ramin Yahyapour
2021 conf
FiCloud
Aytaj Badirova, Shirin Dabbaghi Varnosfaderani, Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2021 J jnl
IEEE Trans. Parallel Distributed Syst.
Song Yang, Fan Li, Stojan Trajanovski, Ramin Yahyapour, Xiaoming Fu
2021 conf
COINS
Shirin Dabbaghi Varnosfaderani, Piotr Kasprzak, Christof Pohl, Ramin Yahyapour
2020 J jnl
Digit. Commun. Networks
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2020 J jnl
Inform. Spektrum
Thomas Ludwig, Wolfgang E. Nagel, Ramin Yahyapour
2019 conf
CSCloud/EdgeCom
Shirin Dabbaghi Varnosfaderani, Piotr Kasprzak, Christof Pohl, Ramin Yahyapour
2019 conf
LWDA
Triet Doan, Lena Wiese, Sven Bingert, Ramin Yahyapour
2019 conf
FiCloud
Tayyebe Emadinia, Faraz Fatemi Moghaddam, Philipp Wieder, Shirin Dabbaghi Varnosfaderani, Ramin Yahyapour
2019 J jnl
J. Parallel Distributed Comput.
Fei Zhang, Guangming Liu, Bo Zhao, Piotr Kasprzak, Xiaoming Fu, Ramin Yahyapour
2019 conf
COINS
Faraz Fatemi Moghaddam, Philipp Wieder, Süleyman Berk Çemberci, Ramin Yahyapour
2019 ed.
Euro-Par
Ramin Yahyapour
2019 conf
HPCS
José Luis González-García, Ramin Yahyapour, Andrei Tchernykh
2019 conf
ICDM Workshops
Bo Zhao, Atsuhiro Takasu, Ramin Yahyapour, Xiaoming Fu
2019 J jnl
Softw. Pract. Exp.
Fei Zhang, Guangming Liu, Bo Zhao, Xiaoming Fu, Ramin Yahyapour
2018 B conf
IWQoS
Hao Wang, Haoyun Shen, Philipp Wieder, Ramin Yahyapour
2018 conf
ISPA/IUCC/BDCloud/SocialCom/SustainCom
Bo Zhao, Xiaoyan Xu, Peng Liu, Yingying Li, Rongcai Zhao, Ramin Yahyapour
2018 conf
ESOCC
Faraz Fatemi Moghaddam, Süleyman Berk Çemberci, Philipp Wieder, Ramin Yahyapour
2018 C conf
ICIS
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour, Tayyebe Emadinia
2018 conf
ICA3PP (Workshops)
Bo Zhao, Yingying Li, Lin Han, Jie Zhao, Wei Gao, Rongcai Zhao, Ramin Yahyapour
2018 conf
VTC Spring
Bo Zhao, Hong Huang, Jarder Luo, Xinggang Wang, Xiaoming Yao, Ramin Yahyapour, Zhenxuan Wang, Xiaoming Fu
2018 conf
TSP
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour, Touraj Khodadadi
2018 conf
FiCloud
Faraz Fatemi Moghaddam, Tayyebe Emadinia, Philipp Wieder, Ramin Yahyapour
2018 J jnl
IEEE Commun. Surv. Tutorials
Fei Zhang, Guangming Liu, Xiaoming Fu, Ramin Yahyapour
2018 J jnl
Int. J. High Perform. Comput. Netw.
Ali Imran Jehangiri, Ramin Yahyapour, Edwin Yaqub, Philipp Wieder
2018 J jnl
Inform. Spektrum
Ramin Yahyapour
2018 J jnl
CoRR
Ming-Chang Lee, Jia-Chun Lin, Ramin Yahyapour
2018 J jnl
IEEE Access
Song Yang, Philipp Wieder, Muzzamil Aziz, Ramin Yahyapour, Xiaoming Fu, Xu Chen
2018 J jnl
Future Gener. Comput. Syst.
Fei Zhang, Xiaoming Fu, Ramin Yahyapour
2017 conf
NAS
Fatih Berber, Ramin Yahyapour
2017 conf
FiCloud
Obinna Ethelbert, Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2017 J jnl
CoRR
Obinna Ethelbert, Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2017 conf
NOF
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2017 conf
NOF
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2017 conf
CloudNet
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2017 conf
CARLA
Luis-Angel Galaviz-Alejos, Fermin-Alberto Armenta-Cano, Andrei Tchernykh, Gleb I. Radchenko, Alexander Yu. Drozdov, Oleg Sergiyenko, Ramin Yahyapour
2017 B conf
CCGrid
Fei Zhang, Xiaoming Fu, Ramin Yahyapour
2017 conf
CAN@CoNEXT
Fei Zhang, Bo Zhao, Xiaoming Fu, Ramin Yahyapour
2017 C conf
FedCSIS
Fatih Berber, Ramin Yahyapour
2017 J jnl
Comput. Networks
Song Yang, Philipp Wieder, Ramin Yahyapour, Xiaoming Fu
2017 conf
ICUFN
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2017 B conf
IM
Song Yang, Philipp Wieder, Muzzamil Aziz, Ramin Yahyapour, Xiaoming Fu
2017 J jnl
Program. Comput. Softw.
Fermin-Alberto Armenta-Cano, Andrei Tchernykh, Jorge M. Cortés-Mendoza, Ramin Yahyapour, Alexander Yu. Drozdov, Pascal Bouvry, Dzmitry Kliazovich, Arutyun Avetisyan, Sergio Nesmachnow
2017 conf
EUROCON
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2017 J jnl
J. Inf. Secur. Appl.
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2017 J jnl
CoRR
Song Yang, Philipp Wieder, Ramin Yahyapour, Stojan Trajanovski, Xiaoming Fu
2017 J jnl
IEEE Trans. Parallel Distributed Syst.
Song Yang, Philipp Wieder, Ramin Yahyapour, Stojan Trajanovski, Xiaoming Fu
2017 C conf
IPCCC
Fatih Berber, Ramin Yahyapour
2017 conf
ICTCE
Haoyun Shen, Hao Wang, Philipp Wieder, Ramin Yahyapour
2017 conf
ICCST
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2016 conf
NAS
Fatih Berber, Philipp Wieder, Ramin Yahyapour
2016 J jnl
Future Gener. Comput. Syst.
Kuan Lu, Ramin Yahyapour, Philipp Wieder, Edwin Yaqub, Monir Abdullah, Bernd Schloer, Constantinos Kotsokalis
2016 J jnl
IEEE Trans. Parallel Distributed Syst.
Ming-Chang Lee, Jia-Chun Lin, Ramin Yahyapour
2016 J jnl
Softw. Pract. Exp.
Amin Mohebi, Saeed Reza Aghabozorgi, Ying Wah Teh, Tutut Herawan, Ramin Yahyapour
2016 B conf
MASCOTS
Fei Zhang, Xiaoming Fu, Ramin Yahyapour
2016 conf
FiCloud
Faraz Fatemi Moghaddam, Philipp Wieder, Ramin Yahyapour
2016 conf
RNDM
Song Yang, Philipp Wieder, Ramin Yahyapour
2015 J jnl
J. Supercomput.
Kamran Kianfar, Ghasem Moslehi, Ramin Yahyapour
2014 conf
IEEE CLOUD
Ali Imran Jehangiri, Ramin Yahyapour, Philipp Wieder, Edwin Yaqub, Kuan Lu
2014 Misc conf
UCC
Edwin Yaqub, Ramin Yahyapour, Philipp Wieder, Ali Imran Jehangiri, Kuan Lu, Constantinos Kotsokalis
2014 conf
IEEE SCC
Edwin Yaqub, Ramin Yahyapour, Philipp Wieder, Constantinos Kotsokalis, Kuan Lu, Ali Imran Jehangiri
2014 conf
ONDM
Siamak Azodolmolky, Martin Nordal Petersen, Anna Manolova Fagertun, Philipp Wieder, Sarah Renee Ruepp, Ramin Yahyapour
2014 conf
IEEE BigData
Jia-Chun Lin, Ming-Chang Lee, Ramin Yahyapour
2014 conf
ICTON
Siamak Azodolmolky, Philipp Wieder, Ramin Yahyapour
2013 B conf
GLOBECOM
Siamak Azodolmolky, Reza Nejabati, Maryam Pazouki, Philipp Wieder, Ramin Yahyapour, Dimitra Simeonidou
2013 J jnl
Computación y Sistemas
José Luis González-García, Ramin Yahyapour, Andrei Tchernykh
2013 J jnl
IEEE Commun. Mag.
Siamak Azodolmolky, Philipp Wieder, Ramin Yahyapour
2013 J jnl
Computación y Sistemas
Anuar Lezama Barquet, Andrei Tchernykh, Ramin Yahyapour
2013 conf
EWSDN
Siamak Azodolmolky, Philipp Wieder, Ramin Yahyapour
2013 C conf
CLOSER
Ali Imran Jehangiri, Edwin Yaqub, Ramin Yahyapour
2013 conf
IEEE CLOUD
Kuan Lu, Ramin Yahyapour, Philipp Wieder, Constantinos Kotsokalis, Edwin Yaqub, Ali Imran Jehangiri
2013 conf
Euro-Par
Zhihui Du, Ramin Yahyapour, Yuxiong He, Nectarios Koziris, Bilha Mendelson, Veronika Sonigo, Achim Streit, Andrei Tchernykh
2012 conf
GECON
Edwin Yaqub, Ramin Yahyapour, Philipp Wieder, Kuan Lu
2012 J jnl
Future Gener. Comput. Syst.
Ariel Quezada-Pina, Andrei Tchernykh, José Luis González-García, Adan Hirales-Carbajal, Juan Manuel Ramírez-Alcaraz, Uwe Schwiegelshohn, Ramin Yahyapour, Vanessa Miranda-López
2012 conf
Euro-Par Workshops
Frédéric Desprez, Domenico Talia, Ramin Yahyapour
2012 J jnl
J. Grid Comput.
Adan Hirales-Carbajal, Andrei Tchernykh, Ramin Yahyapour, José Luis González-García, Thomas Röblitz, Juan Manuel Ramírez-Alcaraz
2012 A conf
ICSOC
Kuan Lu, Ramin Yahyapour, Edwin Yaqub, Constantinos Kotsokalis
2011 conf
Euro-Par (1)
Ramin Yahyapour, Christian Pérez, Erik Elmroth, Ignacio Martín Llorente, Francesc Guim Bernat, Karsten Oberle
2011 J jnl
J. Grid Comput.
Juan Manuel Ramírez-Alcaraz, Andrei Tchernykh, Ramin Yahyapour, Uwe Schwiegelshohn, Ariel Quezada-Pina, José Luis González-García, Adan Hirales-Carbajal
2011 C conf
CloudCom
Kuan Lu, Thomas Röblitz, Ramin Yahyapour, Edwin Yaqub, Constantinos Kotsokalis
2011 conf
Future Internet Assembly
Joe Butler, Juan Lambea, Michael Nolan, Wolfgang Theilmann, Francesco Torelli, Ramin Yahyapour, Annamaria Chiasera, Marco Pistore
2010 conf
IPDPS Workshops
Adan Hirales-Carbajal, Andrei Tchernykh, Thomas Röblitz, Ramin Yahyapour
2010 J jnl
ERCIM News
Frédéric Desprez, Ottmar Krämer-Fuhrmann, Ramin Yahyapour
2010 conf
Euro-Par Workshops
Ramin Yahyapour
2010 ch.
Encyclopedia of Software Engineering
Philipp Wieder, Ramin Yahyapour
2010 ed.
CoreGRID@Euro-Par
Frédéric Desprez, Vladimir Getov, Thierry Priol, Ramin Yahyapour
2010 J jnl
J. Sched.
Andrei Tchernykh, Uwe Schwiegelshohn, Ramin Yahyapour, Nikolai Kuzjurin
2010 J jnl
Future Gener. Comput. Syst.
Uwe Schwiegelshohn, Rosa M. Badia, Marian Bubak, Marco Danelutto, Schahram Dustdar, Fabrizio Gagliardi, Alfred Geiger, Ladislav Hluchý, Dieter Kranzlmüller, Erwin Laure, Thierry Priol, Alexander Reinefeld, Michael M. Resch, Andreas Reuter, Otto Rienhoff, Thomas Rüter, Peter M. A. Sloot, Domenico Talia, Klaus Ullmann, Ramin Yahyapour
2010 J jnl
ERCIM News
Wolfgang Theilmann, Ramin Yahyapour
2010 conf
Euro-Par (1)
Ramin Yahyapour, Raffaele Perego, Frédéric Desprez, Leah Epstein, Francesc Guim Bernat
2010 ed.
ServiceWave
Elisabetta Di Nitto, Ramin Yahyapour
2009 A conf
ICWS
Marco Comuzzi, Constantinos Kotsokalis, George Spanoudakis, Ramin Yahyapour
2009 ed.
CoreGRID Workshop on Grid Middleware
Ramin Yahyapour, Domenico Talia, Norbert Meyer
2009 conf
Euro-Par
Emmanuel Jeannot, Ramin Yahyapour, Daniel Grosu, Helen D. Karatza
2009 conf
ICSOC/ServiceWave
Constantinos Kotsokalis, Ramin Yahyapour, Miguel Angel Rojas González
2008 J jnl
J. Grid Comput.
Ranieri Baraglia, Renato Ferrini, Nicola Tonellotto, Laura Ricci, Ramin Yahyapour
2008 J jnl
J. Grid Comput.
Andrea Pugliese, Domenico Talia, Ramin Yahyapour
2008 conf
ServiceWave
Wolfgang Theilmann, Ramin Yahyapour, Joe Butler
2008 A conf
IPDPS
Uwe Schwiegelshohn, Andrei Tchernykh, Ramin Yahyapour
2008 C conf
PDP
Nicola Tonellotto, Ranieri Baraglia, Renato Ferrini, Laura Ricci, Ramin Yahyapour
2008 conf
CoreGRID Integration Workshop
Christian Grimme, Joachim Lepping, Alexander Papaspyrou, Philipp Wieder, Ramin Yahyapour, Ariel Oleksiak, Oliver Wäldrich, Wolfgang Ziegler
2007 conf
Euro-Par
Jiadao Li, Kwang Mong Sim, Ramin Yahyapour
2006 conf
CoreGRID Integration Workshop
Ranieri Baraglia, Domenico Laforenza, Renato Ferrini, Nicola Tonellotto, Davide Adami, Stefano Giordano, Ramin Yahyapour
2006 J jnl
Int. Trans. Syst. Sci. Appl.
Jiadao Li, Ramin Yahyapour
2006 conf
CoreGRID Integration Workshop
Philipp Wieder, Oliver Wäldrich, Wolfgang Ziegler, Ramin Yahyapour
2006 conf
Euro-Par Workshops
Norbert Meyer, Domenico Talia, Ramin Yahyapour
2006 B conf
CCGRID
Jiadao Li, Ramin Yahyapour
2006 conf
GRID
Jiadao Li, Ramin Yahyapour
2006 C conf
GPC
Jiadao Li, Ramin Yahyapour
2006 C conf
JSSPP
Alexandru Iosup, Dick H. J. Epema, Carsten Franke, Alexander Papaspyrou, Lars Schley, Baiyi Song, Ramin Yahyapour
2005 B conf
CCGRID
Baiyi Song, Carsten Ernemann, Ramin Yahyapour
2004 conf
GRID
Carsten Ernemann, Volker Hamscher, Ramin Yahyapour
2004 conf
ARCS Workshops
Baiyi Song, Carsten Ernemann, Ramin Yahyapour
2004 C conf
JSSPP
Baiyi Song, Carsten Ernemann, Ramin Yahyapour
2004 conf
Future Generation Grids
Uwe Schwiegelshohn, Ramin Yahyapour, Philipp Wieder
2004 C conf
JSSPP
Carsten Ernemann, Martin Krogmann, Joachim Lepping, Ramin Yahyapour
2003 conf
PARCO
Ramin Yahyapour
2003 C conf
JSSPP
Carsten Ernemann, Baiyi Song, Ramin Yahyapour
2002
Ramin Yahyapour
2002 C conf
JSSPP
Carsten Ernemann, Volker Hamscher, Ramin Yahyapour
2002 conf
GRID
Carsten Ernemann, Volker Hamscher, Achim Streit, Ramin Yahyapour
2002 B conf
CCGRID
Carsten Ernemann, Volker Hamscher, Uwe Schwiegelshohn, Ramin Yahyapour, Achim Streit
2000 conf
GRID
Volker Hamscher, Uwe Schwiegelshohn, Achim Streit, Ramin Yahyapour
2000 conf
Heterogeneous Computing Workshop
Claus Bitten, Jörn Gehring, Uwe Schwiegelshohn, Ramin Yahyapour
1999 C conf
JSSPP
Jochen Krallmann, Uwe Schwiegelshohn, Ramin Yahyapour
1999 conf
HPCN Europe
Uwe Schwiegelshohn, Ramin Yahyapour
1998 A* conf
SODA
Uwe Schwiegelshohn, Ramin Yahyapour
1998 C conf
JSSPP
Uwe Schwiegelshohn, Ramin Yahyapour
1998 conf
Wide Area Networks and High Performance Computing
Uwe Schwiegelshohn, Ramin Yahyapour
redb/extractors/decompiler/bninja/analysis/cfg-old.py
← Index redb/extractors/decompiler/bninja/analysis/cfg-old.py python
from collections import deque
from enum import Enum

from binaryninja.enums import (
    BranchType,
    InstructionTextTokenType,
)

# Support both package and standalone imports
try:
    from ..utils.hashes import calculate_md5, calculate_sha256
except ImportError:
    # Fallback to absolute imports (for multiprocessing spawned processes)
    from redb.extractors.decompiler.bninja.utils.hashes import calculate_md5, calculate_sha256


class CFGAnalysis:
    def __init__(self, function):
        self.function = function

    def determine_block_type(self, block) -> str:
        """Determine the type of a basic block."""
        # Check if it's a thunk function (usually just a jump or call)
        if len(block.disassembly_text) <= 2 and any(
            "jmp" in line.tokens[0].text.lower() for line in block.disassembly_text
        ):
            return "THUNK"

        # Check if it contains only data (no valid instructions)
        if all(not line.tokens for line in block.disassembly_text):
            return "DATA"

        # Default to code
        return "CODE"

    def extract_cyclomatic_complexity(self):
        """
        Cyclomatic complexity (McCabe’s metric) measures the number of linearly independent paths
        through a function’s control flow graph (CFG).
        The standard formula is:

            M = E - N + 2

        where:
            - E = number of edges in the CFG
            - N = number of nodes (basic blocks)
            - 2 accounts for the entry and exit nodes of a single connected graph
        """
        if self.function is None:
            return 0

        # number of basic blocks
        num_blocks = len(self.function.basic_blocks)
        # number of edges in the graph
        num_edges = sum(
            len(basic_block.outgoing_edges)
            for basic_block in self.function.basic_blocks
        )
        return num_edges - num_blocks + 2

    def extract_function_cfg(self):
        """Extract information about a function CFG and return it as a dictionary."""

        function = self.function
        function_data = {
            "function_address": self.function.start,
            "blocks": [],
            "measures": {
                "cyclomatic_complexity": self.extract_cyclomatic_complexity(),
            },
        }

        if self.function is None:
            return function_data

        # Get the map of the depth associated to every block
        depths = self.get_map_depth()

        # Get the map of the positions associated to every block
        id_maps = self.get_block_id_map()

        # Extract block data with graph structure information
        for block in function.basic_blocks:
            # dominators per every block translated
            dominators = sorted(self.extract_dominators(block, id_maps))

            # post dominators
            post_dominators = sorted(self.extract_post_dominators(block, id_maps))

            # Build block instructions string
            block_instructions = "\n".join(str(line) for line in block.disassembly_text)

            # Determine block type
            block_type = self.determine_block_type(block)

            # Extract successors directly from basic block
            successor_blocks = [edge.target.start for edge in block.outgoing_edges]
            # We ensure a canonical order and we sort the edges
            successor_blocks.sort()

            # Extract predecessors directly from basic block
            predecessor_blocks = [edge.source.start for edge in block.incoming_edges]
            # We ensure a canonical order and we sort the edges
            predecessor_blocks.sort()

            # Determine branch type from outgoing edges
            branch_type = self.determine_branch_type(block)

            instructions_count = len(block.disassembly_text)

            # Create block record
            block_json = {
                "function_address": self.function.start,
                "block_start_address": block.start,
                "block_end_address": block.end,
                "block_size": block.end - block.start,
                "instructions_count": instructions_count,
                "block_instructions_hash": calculate_sha256(block_instructions),
                "predecessor_blocks": predecessor_blocks,
                "successor_blocks": successor_blocks,
                "depth": depths[block.start],
                "position": id_maps[block.start],
                "branch_type": branch_type,
                "block_type": block_type,
                "flags": self.extract_block_flags(block),
                "dominators": dominators,
                "post_dominators": post_dominators,
            }
            function_data["blocks"].append(block_json)

        return function_data

    def extract_dominators(self, bb, id_maps):
        """Extract the dominators normalized"""
        dom_idx = [id_maps[d.start] for d in bb.dominators]
        return dom_idx

    def extract_post_dominators(self, bb, id_maps):
        """Extract the post-dominators normalized"""
        post_dom_idx = [id_maps[d.start] for d in bb.post_dominators]
        return post_dom_idx

    def determine_branch_type(self, block):
        """
        Determine the type of branch at the end of a basic block.
        This combines edge type information with instruction analysis.
        """
        # If no outgoing edges, it might be a return or terminal block
        if not block.outgoing_edges:
            # Check if the last instruction is a return
            for line in reversed(list(block.disassembly_text)):
                if line.tokens and any(
                    token.text.lower() in ["ret", "retn"] for token in line.tokens
                ):
                    return "RETURN"
            return "UNKNOWN"

        # Collect branch types from all outgoing edges
        branch_types = []
        for edge in block.outgoing_edges:
            edge_type = edge.type
            # Map edge type to our branch type enum
            if isinstance(edge_type, str):
                if edge_type == "IndirectCall":
                    branch_types.append("CALL")
                else:
                    branch_types.append("UNKNOWN")
            else:
                # Use our mapping for integer/enum values
                type_mapping = {
                    BranchType.UnconditionalBranch: "DIRECT",
                    BranchType.FalseBranch: "CONDITIONAL",
                    BranchType.TrueBranch: "CONDITIONAL",
                    BranchType.CallDestination: "CALL",
                    BranchType.FunctionReturn: "RETURN",
                    BranchType.SystemCall: "CALL",
                    BranchType.IndirectBranch: "INDIRECT",
                    BranchType.ExceptionBranch: "UNKNOWN",
                    BranchType.UnresolvedBranch: "UNKNOWN",
                    BranchType.UserDefinedBranch: "UNKNOWN",
                }
                branch_types.append(type_mapping.get(edge_type, "UNKNOWN"))

        # Determine overall branch type (prioritize CALL > RETURN > CONDITIONAL > DIRECT)
        if "CALL" in branch_types:
            return "CALL"
        elif "RETURN" in branch_types:
            return "RETURN"
        elif "CONDITIONAL" in branch_types:
            return "CONDITIONAL"
        elif "DIRECT" in branch_types:
            return "DIRECT"
        elif len(block.outgoing_edges) == 1:
            return "FALLTHROUGH"

        # If edge analysis was inconclusive, fall back to instruction analysis
        last_instr = None
        for line in reversed(list(block.disassembly_text)):
            if line.tokens:
                last_instr = line
                break

        if last_instr:
            mnemonic = None
            for token in last_instr.tokens:
                if token.type == InstructionTextTokenType.InstructionToken:
                    mnemonic = token.text.lower()
                    break

            if mnemonic:
                if mnemonic == "call":
                    return "CALL"
                elif mnemonic == "jmp":
                    return "DIRECT"
                elif mnemonic.startswith("j") and mnemonic != "jmp":
                    return "CONDITIONAL"
                elif mnemonic in ["ret", "retn"]:
                    return "RETURN"

        return "UNKNOWN"

    def get_map_depth(self):
        """
        Run a BFS on the basic blocks of the function to assign a depth to every block
        """

        depths = {}
        entry = self.function.get_basic_block_at(self.function.start)

        ### Simple BFS
        q = deque()
        q.append(entry)
        depths[entry.start] = 0

        while q:
            b = q.popleft()
            b_depth = depths[b.start]
            for edge in b.outgoing_edges:
                tgt = edge.target

                if tgt is None:
                    continue

                if tgt.start not in depths:
                    depths[tgt.start] = b_depth + 1
                    q.append(tgt)

        return depths

    def get_block_id_map(self):
        """
        Assign a unique, sequential ID to each basic block of the function using a BFS starting from the entry block.
        """

        id_map = {}
        entry = self.function.get_basic_block_at(self.function.start)

        q = deque()
        q.append(entry)

        current_id = 0
        id_map[entry.start] = current_id

        while q:
            b = q.popleft()
            for edge in b.outgoing_edges:
                tgt = edge.target

                if tgt is None:
                    continue

                if tgt.start not in id_map:
                    current_id += 1
                    id_map[tgt.start] = current_id
                    q.append(tgt)

        return id_map

    def extract_block_flags(self, block):
        """
        Get the flags for every basic block. Currently, we implemented these heuristics:
            - if a basic block is the entry node for a function
            - if a basic block is the exit block for a function
            - if a basic block is part of a natural loop
        """
        flags = []

        if block.start == self.function.start:
            flags.append(BlockFlags.EntryBlock.value)

        if any(edge.type == BranchType.FunctionReturn for edge in block.outgoing_edges):
            flags.append(BlockFlags.ExitBlock.value)

        # if this block is in its dominance frontier, then it's part of a natural loop
        if block in block.dominance_frontier:
            flags.append(BlockFlags.LoopBlock.value)

        return flags


class BlockFlags(Enum):
    # generally, the basic block identifying the entry point of the function
    EntryBlock = "EntryBlock"
    # any basic blocks that makes the control flow exiting from the current function
    ExitBlock = "ExitBlock"
    # any block is in a natural loop if it is in its own dominance frontier
    LoopBlock = "LoopBlock"


class BlockType(Enum):
    THUNK = "THUNK"
    DATA = "DATA"
    PADDING = "PADDING"
    CODE = "CODE"