-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ported DQM code to C++ #781
base: main
Are you sure you want to change the base?
Conversation
|
||
self.bqm_.set_quadratic(cu, cv, bias) | ||
self.dqm_.connect_variables(u,v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arcondello I put this line of code only for a test case to pass, I think I should remove it and modify the test case, instead
350 dqm.set_quadratic('a', 'b', {})
351
352 self.assertEqual(dqm.get_quadratic('a', 'b'), {})
since if we serialize this dqm, and de-serialize differences will arise, as connections among variables are recreated based on actual connections among cases. I can fix it in this PR or in a different PR (since this changes the original behaviour of the code, so far it just imitates)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I know I told you the old behavior was a bug, but I think it is in fact meaningful for dqm.set_quadratic(u, v, {})
to set the interaction, but not biases. I know it's weird, but I suppose I can imagine a case where I populate the structure of the DQM before setting the biases where I would want to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I will keep it as it is, but we could always end up making at test case that fails due to this issue. We serialize with redundant connection, and the connection is not present in the deserialized one.
@arcondello This is ready for review, I guess we need some co-ordination to get it merged. I think merging will be better than rebasing in this case. |
dimod/include/dimod/adjvectordqm.h
Outdated
|
||
AdjVectorDQM() { case_starts_.push_back(0); } | ||
|
||
explicit AdjVectorDQM(const AdjVectorDQM &dqm) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably a basic C++ question, but will this handle DQMs that are not of the same template type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to dig deeper into it. I followed the AdjVectorBQM, which does use a template over here, but in the cppbqm.pxd file it has only the declaration for something like AdjVectorBQM(cons AdjVectorBQM & bqm), we are not passing a template parameter for specifying the type of the other BQM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Templated it the way adjvectorbqm copy constructor is templated.
dimod/include/dimod/adjvectordqm.h
Outdated
} | ||
|
||
template <class io_variable_type, class io_bias_type> | ||
void extract_data(io_variable_type *case_starts, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think to_coo
or something like that would be a better name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, since this is just reading the DQM, I think it makes sense to leave this code in cython.
return connected; | ||
} | ||
|
||
void connect_variables(variable_type u, variable_type v) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be private and/or protected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it private initially but the problem is for the bug I mentioned above this is needed, to create the connection in cython.
return false; | ||
} | ||
|
||
bool connection_present(variable_type u, variable_type v) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be private and/or protected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be used inside cython, to raise value error, when no connection is present.
dimod/include/dimod/adjvectordqm.h
Outdated
return v; | ||
} | ||
|
||
bias_type get_linear_case(variable_type v, variable_type case_v) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the bqm I am switching to bias_type& linear(v)
and I think bias_type& linear_case(u, v)
would also be preferable to get/set.
Note that for setting to work with cython, you need some trickery. E.g.
cdef bias_type *b = &(self.cppbqm.linear(v))
b[0] = bias
In python there isn't really a notion of a reference/proxy object in the same way. So we'll want to keep get/set.
dimod/include/dimod/adjvectordqm.h
Outdated
} | ||
|
||
template <class io_variable_type, class io_bias_type> | ||
void get_energies(io_variable_type *samples, int num_samples, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it makes sense to just have a single method, bias_type energy(Iter sample_start)
. The user can then parallelize it themselves if they like.
} | ||
|
||
template <class io_bias_type> | ||
bool set_quadratic(variable_type u, variable_type v, io_bias_type *biases) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather accept an iterator than a pointer (applies other places). Let me know if you disagree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we pass in an iterator while passing a pointer we are sort of hiding the real information, we can always use the pointer as an iterator. The thing is we might end up doing pointer arithmetic which does not look too good on an iterator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it seems to me that the iterator is the more general object. Specifically here we mean a random access iterator, since as you say we might end up doing arithmetic. But using an iterator instead would allow us to use strided arrays for instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me think about it a bit, this is also coming up in the BQM case.
|
||
self.bqm_.set_quadratic(cu, cv, bias) | ||
self.dqm_.connect_variables(u,v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I know I told you the old behavior was a bug, but I think it is in fact meaningful for dqm.set_quadratic(u, v, {})
to set the interaction, but not biases. I know it's weird, but I suppose I can imagine a case where I populate the structure of the DQM before setting the biases where I would want to do that.
dimod/include/dimod/adjvectordqm.h
Outdated
#ifndef DIMOD_ADJVECTORDQM_H_ | ||
#define DIMOD_ADJVECTORDQM_H_ | ||
|
||
#include <stdio.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
Codecov Report
@@ Coverage Diff @@
## main #781 +/- ##
=======================================
Coverage 91.81% 91.81%
=======================================
Files 63 63
Lines 4667 4667
=======================================
Hits 4285 4285
Misses 382 382 Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed the review comments, regarding taking to_coo (previously extract_data) , if we want to parallelize it, it will be a lot of code, so I think its better to keep inside c++ instead of cython.
|
||
self.bqm_.set_quadratic(cu, cv, bias) | ||
self.dqm_.connect_variables(u,v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I will keep it as it is, but we could always end up making at test case that fails due to this issue. We serialize with redundant connection, and the connection is not present in the deserialized one.
dimod/include/dimod/adjvectordqm.h
Outdated
|
||
AdjVectorDQM() { case_starts_.push_back(0); } | ||
|
||
explicit AdjVectorDQM(const AdjVectorDQM &dqm) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to dig deeper into it. I followed the AdjVectorBQM, which does use a template over here, but in the cppbqm.pxd file it has only the declaration for something like AdjVectorBQM(cons AdjVectorBQM & bqm), we are not passing a template parameter for specifying the type of the other BQM.
return false; | ||
} | ||
|
||
bool connection_present(variable_type u, variable_type v) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be used inside cython, to raise value error, when no connection is present.
return connected; | ||
} | ||
|
||
void connect_variables(variable_type u, variable_type v) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it private initially but the problem is for the bug I mentioned above this is needed, to create the connection in cython.
} | ||
|
||
template <class io_bias_type> | ||
bool set_quadratic(variable_type u, variable_type v, io_bias_type *biases) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we pass in an iterator while passing a pointer we are sort of hiding the real information, we can always use the pointer as an iterator. The thing is we might end up doing pointer arithmetic which does not look too good on an iterator.
Ported all the dqm code to C++. Not making any attempt to rebase with upstream/main since there is a lot of divergence now.