unhashable type: 'BinaryQuadraticModel'

Hello everyone!

I was trying to solve QUBO problem via bqm and in defining objective function I wanted to add lambda (vector as regularization) as follows:

bqm = sum([lambdaic*(a_lic(i) - c_lic)*x[i] for i in range(r)] 

however when I run it shows following error:

unhashable type: 'BinaryQuadraticModel' I will be happy if you give a hint to solve it!

0

Comments

8 comments
  • Hello,

    Are you able to post a bit more of your code?
    It's a little difficult to tell which parts contain a BinaryQuadraticModel, and what the lambda function is doing.

    Could you also please give a little more context as to how you are formulating or using the BQM?

    0
    Comment actions Permalink
  • Hello,here is my code:

    lambdaic = np.random.rand(60)

    def a_IC(i):
        if i>= 0 and i <= 14:
            return -2*sum([math.cos(m1(i)*np.pi*i1/X)*phi(i1) for i1 in X1])
        if i>= 30 and i <= 44:
            return -2*sum([math.sin(m1(i)*np.pi*i1/X)*phi(i1) for i1 in X1])
        else:
            return 0

    x = [dimod.Binary(f'x_{i}') for i in range(60)]

    bqm = sum([lambdaic*a_IC(i)*x[i] for i in range(60)])

    sampler = LeapHybridSampler()

    sampleset = sampler.sample(bqm)

    and after running the code it shows that 

    TypeError: unhashable type: 'BinaryQuadraticModel'
    0
    Comment actions Permalink
  • Hello,

    Is the provided code exactly the same as the code you ran on your machine? I don't see the reference to the variable upper case X. I don't think that is the issue, but I see there are missing pieces of code. 
    Rather than providing all of the code, if you are able to reduce the code example to a minimal example that can be copied into an interpreter and run, reproducing the behaviour, it would very be helpful. 
    Please also provide the import statements you used.

    I was able to run a reduced version of the above code:

    import dimod 
    x = [dimod.Binary(f'x_{i}') for i in range(60)]
    sum([5*x[i] for i in range(60)])

    So far I am not able to reproduce the issue locally using the provided code. 
    Are you able to run the following code?

    import dimod 
    x = [dimod.Binary(f'x_{i}') for i in range(60)]
    f={}
    f[x[0]] = 5

    This code gives me the same error that you are seeing.
    The BinaryQuadraticModel instance is being used as the value for for a dictionary key.
    The key is hashed in the process, which produces the error, due to the nature of the BinaryQuadraticModel class.
    This might not be the same instance as what is happening in your code, however.

    Please also provide the complete stack trace of the error, as it gives a trail back to the source of the error.

    0
    Comment actions Permalink
  • Hello!

    Here is my complete code on my machine:

    from dimod import  BinaryQuadraticModel as BQM, quicksum
    from dwave.system import LeapHybridSampler
    from dimod import Binary, SampleSet
    import dimod
    import numpy as np

    X = 5

    X1 = list(range(0,X+1))

    #creating random vector
    lambdaic = np.random.rand(60)

    def a_IC(i):
        if i>= 0 and i <= 14:
            return -2*sum([np.cos(i1/X) for i1 in X1])
        if i>= 30 and i <= 44:
            return -2*sum([np.sin(i1/X) for i1 in X1])
        else:
            return 0

    x = [dimod.Binary(f'x_{i}') for i in range(60)]

    bqm = sum([lambdaic*a_IC(i)*x[i] for i in range(60)])

    from dwave.system.samplers import DWaveSampler

    sampler = LeapHybridSampler()

    sampleset = sampler.sample(bqm)

    and the following error appears:

    TypeError                                 Traceback (most recent call last)
    <ipython-input-20-88bb6c7e7e08> in <module>
    ----> 1 sampleset = sampler.sample(bqm)
    
    ~\anaconda3\lib\site-packages\dwave\system\samplers\leap_hybrid_sampler.py in sample(self, bqm, time_limit, **kwargs)
        223         """
        224         if not isinstance(bqm, BQM):
    --> 225             bqm = BQM(bqm)
        226 
        227         num_vars = bqm.num_variables
    
    ~\anaconda3\lib\site-packages\dimod\binary\binary_quadratic_model.py in __init__(self, offset, vartype, dtype, *args)
        176                 self._init_bqm(args[0], vartype=args[0].vartype, dtype=dtype)
        177             else:
    --> 178                 self._init_empty(vartype=args[0], dtype=dtype)
        179         elif len(args) == 2:
        180             # BQM(bqm, vartype), BQM(n, vartype) or BQM(M, vartype)
    
    ~\anaconda3\lib\site-packages\dimod\binary\binary_quadratic_model.py in _init_empty(self, vartype, dtype)
        271     def _init_empty(self, vartype, dtype):
        272         dtype = self.DEFAULT_DTYPE if dtype is None else dtype
    --> 273         self.data = type(self)._DATA_CLASSES[np.dtype(dtype)](vartype)
        274 
        275     def __init_subclass__(cls, default_dtype=np.float64, **kwargs):
    
    ~\anaconda3\lib\site-packages\dimod\binary\cybqm\cybqm_template.pyx.pxi in dimod.binary.cybqm.cybqm_float64.cyBQM_template.__init__()
    
    ~\anaconda3\lib\site-packages\dimod\binary\cybqm\cybqm_template.pyx.pxi in dimod.binary.cybqm.cybqm_float64.cyBQM_template.change_vartype()
    
    ~\anaconda3\lib\site-packages\dimod\vartypes.py in as_vartype(vartype, extended)
        193     elif isinstance(vartype, Iterable):  # not frozenset or str
        194         try:
    --> 195             vartype = Vartype(frozenset(vartype))
        196         except ValueError:
        197             raise _vartype_miss(vartype, extended) from None
    
    TypeError: unhashable type: 'BinaryQuadraticModel'
    0
    Comment actions Permalink
  • Hello,

    It looks like you are creating a number of BQM instances in a list. 

    I can imagine that maybe the intention was to create one BQM instance?

    If not then you would need to combine BQMs or call sample on each BQM. 

    In this case the BQMs are fairly small so I am guessing that they were meant to be all in one big BQM.

    It sounds like you are able to formulate this problem as a QUBO. 
    What you will want to do is add the variables to the BQM after formulating the QUBO.
    You can determine the variables' linear and quadratic terms and then add them to the BQM.
    This link shows a very simple example with two linear terms and one quadratic term with named variables:
    https://docs.ocean.dwavesys.com/en/stable/overview/formulation.html#example-bqm-for-a-boolean-circuit

    Can you possibly describe what the following step should do? It might be an issue of notation that is producing a different problem formulation than expected.
    bqm = sum([lambdaic*a_IC(i)*x[i] for i in range(60)])

    The following screenshot shows what is produced by the above line:

    Each row represents a different problem.

    Running a for loop and sampling each one would produce a different solution set for each.

    What was the output of BQM meant to look like? Can you show us a QUBO formulation of a simplified version? 
    Thanks for your patience and efforts.

    0
    Comment actions Permalink
  • Hello!

    Thank you for your reply!

    Yes my aim is to create one BQM instance.

    I have formulated my problem as QUBO problem and it works.

    However multiplying lambdaic to x[i] creates an issue for me. I would like to add lambdaic as Lagrange multiplier and check its effect.

     

    0
    Comment actions Permalink
  • Hello,

    So it might be helpful to write out a 3x3 matrix and go through exactly what you are expecting to get back from each function to make sure you have the problem in the correct form.

    This line for example is made up of several parts:

    bqm = sum([lambdaic*a_IC(i)*x[i] for i in range(60)])

    It would be helpful to check the output between each line and make sure that it is in the form you are expecting.

    For example, what do the lines of the bqm represent? 

    Note that each line contains a value for the variables x_0, x_1, etc.
    Should these values be added together?
    Should these values actually have different variable names?

    The output for [lambdaic*a_IC(i)*x[i] for i in range(60)] is:

    Note again, it's made up of arrays of all the same variable. Is this what you were expecting?

    Each one of these BinaryQuadraticModels is its own 1x1 QUBO with linear terms.

    The output of the sum function combines these individual QUBOs into a larger one with linear terms for each variable name. But the output of the sum function is a list of QUBOs with a number of liner terms each.

    You could sum twice and end up with one matrix, but it is not clear whether this is what you are aiming to do. It would very much depend on the problem.

    bqm = sum(sum([lambdaic*a_IC(i)*x[i] for i in range(60)]))

    The best way to tackle debugging this issue is by drawing a small 2x2 or 3x3 matrix, writing out all of the operations by hand, and then implementing each step and verifying the output. 
    If you can provide a simple example of how you would produce a small problem like this by hand, it will be easier to help assist with your understanding of the code libraries.

    One way you could implement Lagrange parameters is by creating the different BQMs (BinaryQuadraticModel objects), multiplying them each by different values, and then combining them.
    The combining step could vary between different models but there are a number of ways to do this, but you could use the BQM update method to combine multiple BQMs.

    Another way is to do all of the desired operations in numpy, and then convert the matrix to a BQM format. You can try using the BQM from_numpy_vectors method.

    It is worth looking at the available BQM methods.

    0
    Comment actions Permalink
  • Dear Johnson, 

    Thank you for your reply!

    I will take into account all your comments and advices regarding solving this problem.

    Best regards,

    Aigerim 

    0
    Comment actions Permalink

Please sign in to leave a comment.

Didn't find what you were looking for?

New post