13 #ifndef XACC_ALGORITHM_DDCL_STRATEGIES_MMD_LOSS_HPP_ 14 #define XACC_ALGORITHM_DDCL_STRATEGIES_MMD_LOSS_HPP_ 20 #include <Eigen/Dense> 21 #include "InstructionIterator.hpp" 29 Eigen::MatrixXd mix_rbf_kernel(std::vector<int> x,std::vector<int> y,
30 std::vector<double> sigma_list,
int num_bit){
32 std::vector<int> temp_x(x.size());
33 std::vector<int> temp_y(y.size());
34 Eigen::MatrixXd dx2 = Eigen::MatrixXd::Zero(x.size(), x.size());
35 for(
int i = 0; i < num_bit; i++){
36 for(
int j = 0; j < x.size(); j++){
37 temp_x[j] = (x[j]>>i)&1;
38 temp_y[j] = (y[j] >>i)&1;
40 for(
int k = 0; k < x.size(); k++){
41 for(
int l = 0; l < x.size(); l++){
42 dx2(k,l) += (temp_x[k] != temp_y[l]);
47 return _mix_rbf_kernel_d(dx2, sigma_list);
52 Eigen::MatrixXd _mix_rbf_kernel_d(Eigen::MatrixXd dx2, std::vector<double> sigma_list){
53 Eigen::MatrixXd K = Eigen::MatrixXd::Zero(dx2.rows(), dx2.cols());
54 Eigen::MatrixXd _dx2 = dx2;
55 for(
auto &sigma : sigma_list){
56 double gamma = 1.0/(2*sigma);
57 for(
int i = 0; i < dx2.rows(); i++){
58 for(
int j = 0; j < dx2.cols(); j++){
59 _dx2(i,j) = std::exp(-gamma*dx2(i,j));
67 double kernel_expect(Eigen::MatrixXd K,
68 std::vector<double> px,
69 std::vector<double> py){
72 Eigen::VectorXd P = Eigen::Map<Eigen::VectorXd, Eigen::Unaligned>(px.data(), px.size());
73 Eigen::VectorXd Q = Eigen::Map<Eigen::VectorXd, Eigen::Unaligned>(py.data(), py.size());
76 double expectation = P.dot(temp);
83 std::pair<double, std::vector<double>>
86 for (
auto &x : counts) {
92 std::vector<double> q(target.size());
93 for (
auto &x : counts) {
94 int idx = std::stoi(x.first,
nullptr, 2);
95 q[idx] = (double)x.second / shots;
99 std::vector<double> pxy(q.size());
100 for(
int i = 0; i < q.size(); i++)
102 pxy[i] = std::abs(target[i] - q[i]);
110 int num_bit = (int)log2(target.size());
112 std::vector<int> basis(pow(2,num_bit));
113 for(
int i = 0; i < pow(2,num_bit); i++){
117 std::vector<double> sigma_list = {0.25};
118 Eigen::MatrixXd K = mix_rbf_kernel(basis, basis, sigma_list, num_bit);
119 auto mmd = kernel_expect(K, pxy, pxy);
121 return std::make_pair(mmd, q);
125 bool isValidGradientStrategy(
const std::string &gradientStrategy)
override {
131 const std::string
name()
const override {
return "mmd"; }
142 std::vector<double> currentParameterSet;
144 double kernel_expect(Eigen::MatrixXd K,
145 std::vector<double> px,
146 std::vector<double> py){
150 Eigen::VectorXd P = Eigen::Map<Eigen::VectorXd, Eigen::Unaligned>(px.data(), px.size());
151 Eigen::VectorXd Q = Eigen::Map<Eigen::VectorXd, Eigen::Unaligned>(py.data(), py.size());
153 double expectation = P.dot(K*Q);
159 Eigen::MatrixXd mix_rbf_kernel(std::vector<int> x,std::vector<int> y,
160 std::vector<double> sigma_list,
int num_bit){
162 std::vector<int> temp_x(x.size());
163 std::vector<int> temp_y(y.size());
164 Eigen::MatrixXd dx2 = Eigen::MatrixXd::Zero(x.size(), x.size());
165 for(
int i = 0; i < num_bit; i++){
166 for(
int j = 0; j < x.size(); j++){
167 temp_x[j] = (x[j]>>i)&1;
168 temp_y[j] = (y[j] >>i)&1;
170 for(
int k = 0; k < x.size(); k++){
171 for(
int l = 0; l < x.size(); l++){
172 dx2(k,l) += (temp_x[k] != temp_y[l]);
176 return _mix_rbf_kernel_d(dx2, sigma_list);
179 Eigen::MatrixXd _mix_rbf_kernel_d(Eigen::MatrixXd dx2, std::vector<double> sigma_list){
180 Eigen::MatrixXd K = Eigen::MatrixXd::Zero(dx2.rows(), dx2.cols());
181 Eigen::MatrixXd _dx2 = dx2;
182 for(
auto &sigma : sigma_list){
183 double gamma = 1.0/(2*sigma);
184 for(
int i = 0; i < dx2.rows(); i++){
185 for(
int j = 0; j < dx2.cols(); j++){
186 _dx2(i,j) = std::exp(-gamma*dx2(i,j));
196 getCircuitExecutions(Circuit circuit,
const std::vector<double> &x)
override {
197 currentParameterSet = x;
198 std::set<std::size_t> uniqueBits = circuit->uniqueBits();
199 std::vector<Circuit> grad_circuits;
200 auto provider = xacc::getIRProvider(
"quantum");
201 for (
int i = 0; (i < x.size()); i++) {
203 auto xplus = x[i] + xacc::constants::pi / 2.;
204 auto xminus = x[i] - xacc::constants::pi / 2.;
205 std::vector<double> tmpx_plus = x, tmpx_minus = x;
206 tmpx_plus[i] = xplus;
207 tmpx_minus[i] = xminus;
209 auto xplus_circuit = circuit->operator()(tmpx_plus);
210 auto xminus_circuit = circuit->operator()(tmpx_minus);
212 for (std::size_t i = 0; i < xplus_circuit->nLogicalBits(); i++) {
214 provider->createInstruction(
"Measure", std::vector<std::size_t>{i});
215 xplus_circuit->addInstruction(m);
218 for (std::size_t i = 0; i < xminus_circuit->nLogicalBits(); i++) {
220 provider->createInstruction(
"Measure", std::vector<std::size_t>{i});
221 xminus_circuit->addInstruction(m);
225 grad_circuits.push_back(xplus_circuit);
226 grad_circuits.push_back(xminus_circuit);
228 return grad_circuits;
230 void compute(std::vector<double> &grad, std::vector<std::shared_ptr<AcceleratorBuffer>> results,
231 const std::vector<double> &q_dist,
232 const std::vector<double> &target_dist)
override {
233 assert(2*grad.size() == results.size());
237 for (
auto &x : results[0]->getMeasurementCounts()) {
243 std::vector<std::vector<double>> qplus_theta, qminus_theta;
244 for (
int i = 0; i < results.size(); i += 2) {
246 std::vector<double> qp(q_dist.size()), qm(q_dist.size());
247 for (
auto &x : results[i]->getMeasurementCounts()) {
248 int idx = std::stoi(x.first,
nullptr, 2);
249 qp[idx] = (double)x.second / shots;
251 for (
auto &x : results[i + 1]->getMeasurementCounts()) {
252 int idx = std::stoi(x.first,
nullptr, 2);
253 qm[idx] = (double)x.second / shots;
255 std::vector<double> shiftedp = currentParameterSet;
256 std::vector<double> shiftedm = currentParameterSet;
257 auto xplus = currentParameterSet[counter] + xacc::constants::pi / 2;
258 auto xminus = currentParameterSet[counter] - xacc::constants::pi / 2;
260 shiftedp[counter] = xplus;
261 shiftedm[counter] = xminus;
264 results[i]->addExtraInfo(
"gradient-index", counter);
265 results[i+1]->addExtraInfo(
"gradient-index", counter);
267 results[i]->addExtraInfo(
"shift-direction",
"plus");
268 results[i+1]->addExtraInfo(
"shift-direction",
"minus");
270 results[i]->addExtraInfo(
"qdist", qp);
271 results[i+1]->addExtraInfo(
"qdist", qm);
273 results[i]->addExtraInfo(
"gradient-parameters", shiftedp);
274 results[i+1]->addExtraInfo(
"gradient-parameters", shiftedm);
276 qplus_theta.push_back(qp);
277 qminus_theta.push_back(qm);
283 std::vector<double> sigma_list = {0.1};
284 int num_bit = (int) log2(q_dist.size());
285 std::vector<int> basis(pow(2,num_bit));
286 for(
int i = 0; i < pow(2,num_bit); i++){
289 Eigen::MatrixXd K = mix_rbf_kernel(basis, basis, sigma_list, num_bit);
291 std::vector<double> grad_pos(counter);
292 std::vector<double> grad_neg(counter);
293 std::vector<double> grad_pos_targ(counter);
294 std::vector<double> grad_neg_targ(counter);
296 for(
int i = 0; i < counter; i++){
297 grad_pos[i] = kernel_expect(K, qplus_theta[i], q_dist);
298 grad_neg[i] = kernel_expect(K, qminus_theta[i], q_dist);
299 grad_pos_targ[i] = kernel_expect(K, qplus_theta[i], target_dist);
300 grad_neg_targ[i] = kernel_expect(K, qminus_theta[i], target_dist);
301 grad[i] = grad_pos[i]-grad_pos_targ[i]-grad_neg[i]+grad_neg_targ[i];
305 const std::string
name()
const override {
return "mmd-parameter-shift"; }
const std::string description() const override
Definition: mmd.hpp:306
Definition: Accelerator.hpp:25
const std::string name() const override
Definition: mmd.hpp:305
const std::string name() const override
Definition: mmd.hpp:131
Definition: heterogeneous.hpp:45
std::pair< double, std::vector< double > > compute(Counts &counts, const std::vector< double > &target, const HeterogeneousMap &={}) override
Definition: mmd.hpp:84
const std::string description() const override
Definition: mmd.hpp:132