import networkx as nx
import dimod 
import matplotlib.pyplot as plt
import dwave_networkx as dnx
from dwave.embedding import pegasus
import neal, dwave.system

# Define target Pegasus Graph

M = 16 # Defines number of qubits in Pegasus graph : 24M(M-1)
P_M = dnx.pegasus_graph(M, data = True) # allow the use of pegasus indizes

# Define source complete graph

a = 12*(M-1) # See section 3.1 in Next Generation Topologies White Paper
K_a = nx.complete_graph(a)
a

# Embedding K_a into P_M
embedding = pegasus.find_clique_embedding(K_a, target_graph=P_M)

"""
Alternative:
from minorminer import find_embedding
# Embedding K_a into P_M
timeout = 60
tries = 50
embedding = find_embedding(K_a, P_M, timeout = timeout, tries = tries)
"""

if embedding:
    print("Found Embedding")

print(f"P_a has : Nodes {P_M.number_of_nodes()}   Connections {P_M.number_of_edges()}")
from collections import Counter
degree_ct = Counter()
for node, degree in dict(P_M.degree()).items():
    degree_ct[degree] += 1
degree_ct

chain_ct = Counter()
for node, chainlist in embedding.items():
    chain_ct[len(chainlist)] += 1
print(f"The embedding has {len(embedding.keys())} nodes")
chain_ct

structured_sampler = dimod.StructureComposite(neal.SimulatedAnnealingSampler(), P_M.nodes, P_M.edges)
sampler = dwave.system.FixedEmbeddingComposite(structured_sampler, embedding = embedding)
num_reads = 500
max_clique_size_avg = 0
for i in range(num_reads):
    max_clique_size_avg += dnx.clique_number(K_a, sampler=sampler)
    
max_clique_size_avg = max_clique_size_avg / num_reads

# to run this line 95 in clique.py (dwave-networkx - algorithms) must be commented out
# the decorator checks if sampler is properly implemented can be skipped...

print(f'Found {max_clique_size_avg = }. We wanted {a}. So {a - max_clique_size_avg :.4} are missing')