Coder Social home page Coder Social logo

dwavesystems / dwave-neal Goto Github PK

View Code? Open in Web Editor NEW
49.0 49.0 46.0 460 KB

An implementation of a simulated annealing sampler for general Ising model graphs in C++ with a dimod Python wrapper.

Home Page: https://docs.ocean.dwavesys.com/projects/neal/en/latest

License: Apache License 2.0

C++ 20.17% Python 72.35% Cython 7.49%

dwave-neal's People

Contributors

arcondello avatar jackraymond avatar joelpasvolsky avatar randomir avatar wbernoudy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dwave-neal's Issues

SimulatedAnnealingSampler.sample method return type incorrectly documented

Description
The return type of the SimulatedAnnealingSampler.sample method is said to be "a dimod Response object" in the docs, a class which is nowhere documented in the neal or dimod docs.

To Reproduce
View here.

Expected Behaviour
The documentation should be changed to reflect that actual return type of SimulatedAnnealingSampler.sample, namely SampleSet.

Environment:
N/A

More info in returned SampleSet

Problem

  1. SampleSet returned by neal has no timing info analogous to DWaveSampler().sample(...).info['timing']
  2. Other useful bits of info like
    num_sweeps_per_beta = max(1, num_sweeps // 1000.0), num_betas = int(math.ceil(num_sweeps / num_sweeps_per_beta)) are missing

Context

  1. Useful for accurate and consistent timings, and
  2. For noting the discrepancy between actual number of sweeps vs input number of sweeps (and thus schedule)

Assume `initial_states` uses the same vartype as BQM, and convert appropriately

SampleSet for initial states (#53) will be the ultimate resolution of the #54 bug / ill-defined behaviour.

However, for backwards-compatibility reasons, a reasonable first step is to support the existing format of initial_state (tuple(ndarray, dict)), but to interpret values in the matching BQM vartype.

When we implement #54, we can deprecate the old format (but still support it for a while).

Accept SampleSet for initial_states

Since neal.SimulatedAnnealingSampler.sample is returning a dimod.SampleSet, it should also be able to accept it for initial_states parameter (instead of ndarray + labels map).

Doesn't build

Description
sphinx-build barfing

To Reproduce

  1. First problem
    make html
    Exception occurred:
    File "conf.py", line 65, in
    from neal.package_info import version
    ImportError: No module named neal.package_info

  2. I update conf.py to
    import os
    import sys
    sys.path.insert(0, os.path.abspath('.'))
    sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(file))))
    .. Now try again
    make html
    Exception occurred:
    File "/home/jpasvolsky/Work/MyVirtualEnvironments/neal/dwave-neal/neal/sampler.py", line 32, in
    import neal.simulated_annealing as sa
    ImportError: No module named simulated_annealing

Expected behavior
Should build

Environment:

  • OS: Ubuntu 16.0x and Windows
  • Python version: 2.7

Additional context
Latest change to make interruptable seems to have updated file locations but not paths to the files

Adjust `initial_states` to `num_reads`

Currently, if a non-null value for initial_states is given (to .sample()), the number of states provided has to match the number of reads requested.

To simplify a few common use cases, we can extrapolate (or cut) the list of provided initial states to match num_reads.

There are a few ways to do that, so it seems reasonable to provide an additional parameter, e.g. initial_states_mapper so users can control it:

  • exact: states provided must match the number of reads requested, otherwise we fail (current behaviour)
  • tile: if a shorter list of states is provided, the missing ones will be derived by tiling / repeating the provided ones, as many times as necessary. If a longer list is provided, it will be truncated.
  • random: if a shorter list if provided, the missing states will be set to random samples, and if longer is provided it will be truncated.

Feature: Have semantics of neal match DWaveSampler

Current Problem
When I write code for DWaveSampler, I have to modify the code to use neal instead. For example, no matter which of these I write, the code that follows should never have to change.

sampler = DWaveSampler()
sampler = neal.SimulatedAnnealingSampler()

Proposed Solution
Have the inputs and outputs of neal match those of DWaveSampler. For example, the argument "anneal_schedule=" should be silently ignored. The output in response.data() should be aggregated like it is in DWaveSampler.

Alternatives Considered
If I want the same code to work with both neal and DWaveSampler, then I would need to make my own wrapper around these. That is a layer of abstraction I would very much like to avoid.

Pass some context to user-supplied interrupt callback

Currently, the interrupt callback function is called after each sample (read), but it receives no context, like last sample or energy. Furthermore, it's not even possible to capture references to sample/energy arrays in closure because they are created in cython code and returned to python on the very end of sampling (i.e. after interrupted).

So, providing references to sample/energy numpy arrays (semi-filled) on each call of interrupt callback would enable user to stop sampling when energy threshold is reached, for example.

Windows compiler version mismatch

command "python setup.py build_ext --inplace" produces the following output:

Compiling ./neal/src/simulated_annealing.pyx because it changed.
[1/1] Cythonizing ./neal/src/simulated_annealing.pyx
running build_ext
building 'neal.src.simulated_annealing' extension
error: Microsoft Visual C++ 9.0 is required. Get it from http://aka.ms/vcpython27

After installing MS VC 9, rerunning the command gives warning on "cl : Command line warning D9002 : ignoring unknown option '/std:c++14'" for the setup.conf line

    'msvc': ['/std:c++14'],
    'unix': ['-std=c++11'],```

Potential dependency conflicts between dwave-neal and numpy

Hi, as shown in the following full dependency graph of dwave-neal, dwave-neal requires numpy >=1.14.0,<2.0.0, dwave-neal requires dimod >=0.7.7 (dimod 0.9.1 will be installed, i.e., the newest version satisfying the version constraint), and directed dependency dimod 0.9.1 transitively introduces numpy >=1.16.0,<2.0.0.
Obviously, there are multiple version constraints set for numpy in this project. However, according to pip's “first found wins” installation strategy, numpy 1.18.4 (i.e., the newest version satisfying constraint >=1.14.0,<2.0.0) is the actually installed version.
Although the first found package version numpy 1.18.4 just satisfies the later dependency constraint (numpy >=1.16.0,<2.0.0), such installed version is very close to the upper bound of the version constraint of Numpy specified by dimod 0.9.1 .
Once dimod upgrades,its newest version will be installed, as dwave-neal does not specify the upper bound of version constraint for dimod. Therefore, it will easily cause a dependency conflict (build failure), if the upgraded dimod version introduces a higher version of Numpy, violating its another version constraint >=1.14.0,<2.0.0.
According to the release history of dimod, it habitually upgrates Numpy in its recent releases. For instance, dimod 0.7.0 upgrated Numpy’s constraint from >=1.11.3,<2.0.0 to >=1.14.0,<2.0.0, dimod 0.8.5 upgrated Numpy’s constraint from >=1.14.0,<2.0.0 to >=1.15.0,<2.0.0, and dimod 0.9.0.dev6 upgrated Numpy’s constraint from >=1.15.0,<2.0.0 to >=1.16.0,<2.0.0.
As such, it is a warm warning of a potential dependency conflict issue for dwave-neal.

Dependency tree

dwave-neal - 0.5.4
| +- dimod(install version:0.9.1 version range:>=0.7.7)
| | +- numpy(install version:1.18.4 version range:>=1.16.0,<2.0.0)
| | +- six(install version:1.14.0 version range:>=1.10.0,<2.0.0)
| +- numpy(install version:1.18.4 version range:>=1.14.0,<2.0.0)
| +- six(install version:1.14.0 version range:>=1.11.0,<2.0.0) 

Thanks for your help.
Best,
Neolith

Initial states only accepted in Ising type

It is undocumented, and unexpected, for initial_states to be required to be given in Ising/SPIN type only - independently of the BQM's type.

If undefined/None, random initial states are generated in Ising space, but initial states given are not converted to Ising. Since they are given via an array, their type is unknown, but automatic conversion can be done if they are given as a SampleSet (see #53).

Neal on GPU

Current Problem
Can Neal run on GPU?

Proposed Solution
??

Alternatives Considered
??

Additional context
??

Documentation check and/or refactor needed

I do not know why readthedocs is pointing at out of date documentation. Selecting 'stable' will point to the correct documentation. I will wait a few days for it to resolve itself, but if it doesn't I will update all of the links.

Bug: divide by zero in beta schedule calc

Description
Division by zero occurring during beta_range calculation for some edge-case BQMs.

To Reproduce

import dimod
from neal import SimulatedAnnealingSampler

bqm = dimod.BinaryQuadraticModel({'a': 1}, {}, 0, dimod.SPIN)
print(SimulatedAnnealingSampler().sample(bqm))

output:

/home/radomir/work/dwave-hybrid/env/lib/python3.5/site-packages/neal/sampler.py:335: RuntimeWarning: divide by zero encountered in double_scalars
  hot_beta = np.log(2) / max_delta_energy
/home/radomir/work/dwave-hybrid/env/lib/python3.5/site-packages/numpy/core/function_base.py:348: RuntimeWarning: invalid value encountered in double_scalars
  stop = stop + (start - start)
Response(rec.array([([-1], -1., 1), ([-1], -1., 1), ([-1], -1., 1), ([-1], -1., 1),
           ([-1], -1., 1), ([-1], -1., 1), ([-1], -1., 1), ([-1], -1., 1),
           ([-1], -1., 1), ([-1], -1., 1)],
          dtype=[('sample', 'i1', (1,)), ('energy', '<f8'), ('num_occurrences', '<i8')]), ['a'], {'beta_schedule_type': 'geometric', 'beta_range': [inf, 4.605170185988092]}, 'SPIN')

Note inf in beta_range due to max_delta_energy = 0.

Additional context
Looks like the bug was introduced in the latest version, v0.4.3, with pull request #42, or more precisely in commit #12f176, in process of tightening the bound for max_delta_energy.

Default beta range can produce poor results for certain problems

Description
The method that chooses a beta range when none is provided in a sample call will choose a very poor range for some basic problems.

To Reproduce
It's easy to see the bad behavior with h only problems. The beta picking method always chooses 0.1 for the initial beta, so if we choose h with values smaller than this, we get quite bad results.

>>> h = {v: 0.001*np.random.choice((-1, 1)) for v in range(100)}
>>> np.mean(sampler.sample_ising(h, {}, num_reads=1000).record.energy)
0.00016000000000000015

Less damning but still important to note is the behavior with h = +/-0.5:

>>> h = {v: np.random.choice((-0.5, 0.5)) for v in range(100)}
>>> np.mean(sampler.sample_ising(h, {}, num_reads=1000).record.energy)
-23.082

Expected behavior
neal should give back reasonably low energy results without providing a beta range, especially on very easy problems.

`simulated_annealing` calls from different threads block each other

Looks like GIL is not released when entering the native/C function.

problem = ...

num_threads = 3

with ThreadPoolExecutor(max_workers=num_threads) as executor:

    with tictoc() as sequential:
        for _ in range(num_threads):
            wait([executor.submit(simulated_annealing, *problem)])

    with tictoc() as parallel:
        wait([executor.submit(simulated_annealing, *problem) for _ in range(num_threads)])

speedup = sequential.duration / parallel.duration

# speedup is ~ 1, but it should be around num_threads

python version issue (may be user error)

Description

Works on python 2.7, getting the following error on 3


AttributeError Traceback (most recent call last)
in ()
4 h = {0:1.0,1:1.0}
5 J = {(0,1):2.0}
----> 6 logical_sa_solutions = sa_sampler.sample_ising(h,J)

/opt/conda/lib/python3.6/site-packages/dimod/core/sampler.py in sample_ising(self, h, J, **parameters)
202 """
203 bqm = BinaryQuadraticModel.from_ising(h, J)
--> 204 response = self.sample(bqm, **parameters)
205 return response
206

/opt/conda/lib/python3.6/site-packages/dimod/decorators.py in _index_label(sampler, bqm, **kwargs)
44 # if already index-labelled, just continue
45 if all(v in linear for v in range(len(bqm))):
---> 46 return f(sampler, bqm, **kwargs)
47
48 try:

/opt/conda/lib/python3.6/site-packages/neal/sampler.py in sample(self, bqm, beta_range, num_reads, sweeps, beta_schedule_type, seed)
228 seed)
229 off = bqm.spin.offset
--> 230 response = dimod.Response.from_matrix(samples, {'energy': [en + off for en in energies]}, vartype=dimod.SPIN)
231
232 return response.change_vartype(bqm.vartype, inplace=True)

AttributeError: type object 'Response' has no attribute 'from_matrix'

To Reproduce

h = {0:1.0,1:1.0}
J = {(0,1):2.0}
logical_sa_solutions = sa_sampler.sample_ising(h,J)

Environment:

  • OS: Ubuntu 16.04
  • Python version: 3.6

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.