diff --git a/.gitignore b/.gitignore index 463ee22..53e1ec5 100644 --- a/.gitignore +++ b/.gitignore @@ -112,6 +112,7 @@ compile_commands.json ### Kdevelop # *.kdev4 +*.kate-swp ### C++ # diff --git a/.gitmodules b/.gitmodules index a23063c..0fe9420 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,3 +11,7 @@ path = contrib/mongoc/mongo-c-driver url = https://github.com/mongodb/mongo-c-driver.git branch = r1.13 +[submodule "contrib/qubosolver/qbscxx"] + path = contrib/qubosolver/qbscxx + url = ssh://git@sargas.org:2240/Tom/qbscxx.git + branch = develop diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..5b07662 --- /dev/null +++ b/Pipfile @@ -0,0 +1,19 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +dwave-system = "*" +tqdm = "*" +matplotlib = "*" +seaborn = "*" +dwave-qbsolv = "*" +mysql-connector = "*" +pymongo = "*" +dwave-ocean-sdk = "*" + +[requires] +python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..e426923 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,603 @@ +{ + "_meta": { + "hash": { + "sha256": "9f0d26b8f9c9b5a77ba3ea91076a083016ccd4f0f8d19e66489c3fd39fb3a126" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.6" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "certifi": { + "hashes": [ + "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", + "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae" + ], + "version": "==2019.3.9" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "click": { + "hashes": [ + "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", + "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + ], + "version": "==7.0" + }, + "cycler": { + "hashes": [ + "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d", + "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8" + ], + "version": "==0.10.0" + }, + "decorator": { + "hashes": [ + "sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de", + "sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6" + ], + "version": "==4.4.0" + }, + "dimod": { + "hashes": [ + "sha256:1251f1c85034b6dc91f97f82b89f944c76231f5cb8ade13b3bfb652dfc130547", + "sha256:291777a168980fd642bf7fe885231bd230b66d93b6fd1b3f12b4ff795fd4eb7b", + "sha256:32e02098a23a83ec68783179246a94110bc6897b560dbd1a32660c9852f72801", + "sha256:3535cc12e7e158b865c78186dd1f042de4624f994bd8dfc13e9f4bb055186b5a", + "sha256:44567d308e04ce1d296a76ddcaa60af36c8b20ade66a71d88cec8ee05fef4374", + "sha256:48c5a662867d366955a85c39cbd75dd0388c83ef65ce586f4ed54d1b9d1e2db9", + "sha256:4aab893daf9c12430ea2d402656d401bee7edff91a5d1469d5457a3242c5ab2e", + "sha256:4f40704988a4ce4a90d7c0fff08d34e5fd6aadf2a01293d47be0ad11be03cfd9", + "sha256:60871983b9e8a8c560e117a9c74c9232860f026c4e7b9e8f90274421b15e22eb", + "sha256:66a2ce78d7f69de90e8aeb348366231c4f9f614254af3fdefcd091adeed22a99", + "sha256:687e706bc3b1fc542704d624e33c168b9fab70578dd67199525ffba1f632d98e", + "sha256:6b044300cb404adbe71960e377e0009518e3cf71a57f22eca322da8d04dae5ef", + "sha256:877b9c142197ab8085205365f3c5b2a37477e122f46c33189ca6352d73f84f8d", + "sha256:89ca80fdeffbca37d086d56b8617472709b0b8ae5f818a4a839479260b9c90f9", + "sha256:8e1f92e778fe1c3f55da7482bcd1d960d3473f4db740ba5d0c3a4fdc84b49501", + "sha256:9a85f7c420855d70e088e54578e8612f0395c049a647d7e1d8507b1ae529bc2b", + "sha256:9ff4a7d7570e5d41b9c77ad8bf869c778b8e7f0b45ec22d1e392990458c3e7aa", + "sha256:a9b2005140bbf2dd889dfd9153e18d18893851d725cde22743d3d617b233eca6", + "sha256:abeeb39c0edf573d9aa840d89926c0863977f2fc1ddc34019ac125587c189206", + "sha256:ac79a8ca12a88160984a996bd0a89ac49bc6ee77902067f7ed7b3ef451b1d6d1", + "sha256:bb0b377f0b97cab34829df0bd06f34eeaa1d8f1f2414f337f44bd8aa58ea86f6", + "sha256:c248eec112b9ac20a2133b08089928610ee206fa0b4bdac6cda38c2ce163e69b", + "sha256:c5e9da8c04f414f35933551d129ddf58e053d53226d1e55061dac9dae04676ea", + "sha256:cf6d921451ad7b31a0bd0abe4c91317881f9ac93f25cfe3241a21ca75971166b", + "sha256:d4643e2752fe4ca5e55db295ec0392ea2ec2598bfa83293d0fca6a0511cfa334", + "sha256:e26e11b86d97f1e625cfafbc47474bbe4ce968d8b8ca388efc8b4478486f6a62", + "sha256:e41c9236e9190f9aadbd7f4740817776c1d29ad1ef577826791e3bc8c864ff0f", + "sha256:ffb15a31b33f1741db95c3d8c133f29f349729beea118c0286311bacf30a2aeb" + ], + "version": "==0.8.7" + }, + "dwave-cloud-client": { + "hashes": [ + "sha256:1f03e6f46b2f4cdab1aa5bf9319ddfab196f5888fc6af8ba02e93fe08f3c8af3", + "sha256:f303cd45c9831dde7ccd3a8d59e5e2dd4a12d84b9e9836df18ceb081fdaa104a" + ], + "version": "==0.5.3" + }, + "dwave-neal": { + "hashes": [ + "sha256:04c91c39ad68d3401a938d5f882ef42ade80aeb84fd196071fb5337a01292a16", + "sha256:25c2d092b30f7a867ed0c6585d5b55934d3d1d90361fbe5e3086f3893ec75d14", + "sha256:2a08eff97bfddce8f1b4a90c843438ca9d2a6617665c6bae97f56ea1dd0f4c45", + "sha256:4125e1dc6523d20f696a1d916a21d2ea1741977074966bc8467a4ec8e645aa2a", + "sha256:5b0d69f304ddb74b2da4926dc93807d366b80765ec39c6cc535bf7fada6947a9", + "sha256:6188c69b0a2b3393b4af7a5ed35ab5cf34074b86b75a3bbf68f47a042cf437f1", + "sha256:654337da6db99d500f6cbdfa87ef7899d4e53cd58c85ff557bd922810f71e393", + "sha256:75386a1242f6b097785b3492775ba91180a3499d8d8234721563781e8cea66d2", + "sha256:7db19160eed27897e5946cb2f45926847492b0f83ba5216878bcc50deadcfb53", + "sha256:81a17ab3f5da90ccd53461dde3f65df271afa3ab4910a0c45c65ea4ef44f166d", + "sha256:83981e626abcf709df1ee47fcb716058d9d8d948172ce67d135c7b107fb6373f", + "sha256:87529e09788722ed9fc7b6fef7907a4b2242147c4681de72e5e596b4d66c020a", + "sha256:897bb6fc961f0f7f857f5fa87b04baa838661ca9edd1fe3cf51d6783514cf0ac", + "sha256:8a105a488ce01481119d61a0dd4687da8b9fdff088865d03355f650628011af1", + "sha256:8f99b343b43708bd99538e0c08871c42f95166cf5ae0db344ebc619e1387d498", + "sha256:9645c43316fa2583e466ded47f5eec99d8c070f0af15b7f33cda43573879f3af", + "sha256:97b659c021060e36149cc0889e0f3b641ce9220e901c3d2399ce8946a047f76d", + "sha256:9be849dcb5912778d86154e5e3f37827cfe31089a94cbabdea65f87e91ef3203", + "sha256:9d4b0a89d6a1a96fd7d56ac8deee2745c8924e976ca43f07cbbe549dc4947618", + "sha256:9d68f26cf2d17219ee1c86929622736f7b6da534f4ba36eb48873b45cbf5a21b", + "sha256:a64ad785b58d2e6914bc2f586b46137124b340296b6a5ce3970ef7c21e593676", + "sha256:ac048b54e294c0ba10650217849cc0c413e655d09e71fa0a0bf813124acda1c6", + "sha256:b05b50bb11dda853081f5485493ffd5c1d514705e25a8ad6765fa777e3544772", + "sha256:bad4d816afe10805b640e6d6521ffbca51d08f6d9172f08bb071a13921d9d8a4", + "sha256:be9d63fc4d8a299c0f6efa30f10f79e01ea73ff9bf7fcc443d69f811f8c66298", + "sha256:cca1dd1d8e0ce394e4cdbfe58cd7e1c85063da4cfb228bbefed29438cd709a3f", + "sha256:f0163884d0b88e15c857a53c9b2c14d20bc0193948ecf342de655e172608c151", + "sha256:fae95c4d74d4a23218cf125dce65820610919127bd738e0c7f2f7bc2ae33e2bc" + ], + "version": "==0.4.5" + }, + "dwave-networkx": { + "hashes": [ + "sha256:9205e09a6a5ba34679cab9f474255cc10addc493d06cb6fedd6ac5e7bb4d8849", + "sha256:bfb15364d798f9c608f67a7755f55a7ec2330d0c8034738ab805b499cf75f83e" + ], + "version": "==0.7.1" + }, + "dwave-ocean-sdk": { + "hashes": [ + "sha256:1932fb7dd9b963afc691b48422c3e765ae9a67513407d9d86009f65faf933051", + "sha256:68ae002a3777a6c7ac2db9bfaa70e0b0726f2d4bd4b3eee270081a5b0891c9bb" + ], + "index": "pypi", + "version": "==1.2.0" + }, + "dwave-qbsolv": { + "hashes": [ + "sha256:01af1a45f272a3b721ce01bc51175386231bf7ef5c7e8e46f5eeb87fd202d100", + "sha256:0db5e043eaea0aedea1bcade3f006c122f48a109dbec5e1a2e32a583bd2b3988", + "sha256:10a3ed3250ad5ef205c187a521708cde5cd50a1cc08e85daea4e96592e5f200c", + "sha256:1493e8d5537035cd3f27e6340878764bf622247ff75267ffb441acc222f2abd0", + "sha256:1ca6ecc8a34ba342c732dd335537efca03597ce7f1b7d998251d8d5f5622e8b6", + "sha256:2698f070fc7ae7fd5fb4465667ea9b78652646baacb0d6c9ce69f987184e301d", + "sha256:2713b85163c9398a15fb8316afa5bd6e1d1d9cf7ac37d1f63cc68d8930cb99f3", + "sha256:46152caf74aee623c49fff895bc0f3b4963e07658276dde9c560d1b1b8273391", + "sha256:49d70f31099376d83dd1a1ac9e6c6200d6bd17bc530a4db0a157cff4ff3cb6f2", + "sha256:51239ade1ac9d5cb01c87f5f222cbd1245a33c79bebba37fcbbdc522fc343b1f", + "sha256:5535a331b465b66409b6c8006eabb0448e0a25af7de80e4e5f375c371c46c1ba", + "sha256:62c89eb0888db398e073f17df2468cadc6bc618fd34700ef7fd8e087392fb39f", + "sha256:7a2d3c2e0c3326d61bdf13d23c318594267a847ca0b52efd058a98ad209df635", + "sha256:965858d1228f85ec3a411c4a5283bc98feb8135cac4b50aafca3cc38c18331b1", + "sha256:9de37d2296ddcf18a36be5306c03a2805c84a28bb92850aa39cb4f802789d90e", + "sha256:b1b08ec54c12bb12ea12960f432c38889e94002aec2c44e4f47b3eda9fcfb2f2", + "sha256:b3ba9aea9021d00947cc88a2eb482ac4d9d7ea8f0df7091e5385806d0814251d", + "sha256:becaf7ce0ce724f2ca3cfe7c5d45e74f8e1e5820d6387b21d1b5a32f4039a2a6", + "sha256:db22470cd8fed80217d31a9a490055df4c54970203606d4d5141b1abdcf8abce", + "sha256:dee031f2cbdab41fa5bcebcdd8d9ba77759bc02650fa4b343746d70f17f397d5", + "sha256:e113ca5c2ccac8675244c54e19d6e0dd26387ba2655d7c28287978b33e9b75a0", + "sha256:e64c3761d051a9f8916f109ef874af66eac327822cc5b4bf929074d222809fa7", + "sha256:ead56aa186e3001f3b5a210e991865997d306cf95d2d7a872ff06804ed21a9c5", + "sha256:ecc96e49f121e3f91f380b13fabc6089b6c9f740d03c59cdf9d478fad78931d9", + "sha256:ed243bfdacf04746d0ad9448792f0e12ba965c543ba55f08729248430f1125e7", + "sha256:f82a1810cf15ea5fd9579dc12f3bcf3c3bf4722dcd2a96a628f29e1973c71339", + "sha256:fbbc155a9b4fe2273b678edf54e58d51a8e871deb80eeceec8cad7a31b44788d", + "sha256:fbd26caaf180949de1b228b57c539ac19a750836b0f55c29ed0a271585e34d0e" + ], + "index": "pypi", + "version": "==0.2.10" + }, + "dwave-system": { + "hashes": [ + "sha256:220167bf1c440f89f4a5ec69d08f80dc1359d3a37b7be69ba367be637feaa63a", + "sha256:42a1f73b19676493cb14481218057c25275d27c2251effea9a2ad567c1f1f428" + ], + "index": "pypi", + "version": "==0.7.2" + }, + "dwave-tabu": { + "hashes": [ + "sha256:052222fe3e4052d0793630935ffdfb9a8d9a0888782282d6a112a580843e325d", + "sha256:07edf3e754f663b35c44ae822aadc9c6fdb3c780fdbf65f50314b9fe067382bc", + "sha256:12b6067b1d9e020cd95614adc3eec76d9be535a825613ac4a780229307ce532f", + "sha256:274b1107e9a490a090127663e38fb39b975d2fd47a3f1f9f18150564ed6fc7c4", + "sha256:28985eb5e8cd7b4566863447e160259456f85475489cc09ae257b662ff2e7463", + "sha256:36a2956dea091881c289fdb174a59cad9aafde822cf8b455c9c427ce1aaca544", + "sha256:41b475a1b963e0b458e693084b82e55118b0719d83c62bd28f04c5f70074e9c5", + "sha256:4c6a1d18d0f9b8c3a659a11b0ef73cf11c9202f5d63f9d4cb917787a48d387d1", + "sha256:5c2e5163cebb90db2737ec1470317f01ddfc4b6e60f70f541e83e0ab8da49b45", + "sha256:79e8ac1315d28e31b66d048c26cae0f58024e1781e5114f2678944c23b64abbd", + "sha256:82ef07ab9ed43175579a4689e0f7d58e43d520b12963b71a9d2343b950a3fbbd", + "sha256:85ed984a3d7617476d64b3698a540b87ac54ca523e5642c786a21c92f1b9cfc2", + "sha256:878cb9e095c933e56c9f4031f09ff2eddadeda89621b9951b616cc308d49a594", + "sha256:93218dc788de47f07e06a436d773c1d6755ec42071f7cdef3c88e72e89d9c559", + "sha256:99d2e89ed58d92a0de72cab8eb7bd442d0456f6488973a234d0b1832cd63b1c8", + "sha256:a444486c0a1041b84de9f6a6496071c1a1e2cb2f0da245adb65998f77fc7e95f", + "sha256:aa46cd1f13798a1b05e53a95e63167aa2c02b02d34a307ca1445bfe1d435b00d", + "sha256:afaab2a6916ea1fa1f925c21c123fdc534b759f890e1acf67ce8f5cc53ae1086", + "sha256:b597d03569e2c8400de940b40d2292849bb6e97a54ebdf3d438b8a9c1cf1782b", + "sha256:ceeaea71a6cdb5f9a34d4261604f9ebea3a07837c943f4fa6b99581203c7d975", + "sha256:d89cf7262d86fe841c32432702f9ed8c42fe4a2aeb5871b87c6a0a7dbd3a82de", + "sha256:dc3efa5ab9e663ddf171bf032fdd260850cfdfe08e225a7148adbcb64eea10bc", + "sha256:eaf120fff7e6830b917556e19b4365bacb0ce256bac78948c947248146dcbb4a", + "sha256:eb41e0d334d0f1174ae0c829ac9db502ffeb26a083cd23d3eca4fa537d01ef5c", + "sha256:ec214104b1850c815f75e9d7c70d41bda2b9d27095ee0dff8751a393000c13f6", + "sha256:ecc539093ff253a8213b1493384099e25a4f147fb2c359fb723161b63c42a2d6", + "sha256:ecd59bedc60fc5b2620bd6db2201b9b416a3a1447fd9b3579a2274d67081946f", + "sha256:fbc1f733a4cba71c2d85a2cb05166b1d72d4935c3da7cedb94e7890a81d74280" + ], + "version": "==0.1.3" + }, + "dwavebinarycsp": { + "extras": [ + "mip" + ], + "hashes": [ + "sha256:6ca0fb6363ec31f4daf5f7bdca6506df90bd1d61783ad6252a877f4f2d3bee38", + "sha256:b13327965ca5207c5896919ad934d24307cc91bea4ced42ee37a9cf4ce58c158" + ], + "markers": "(platform_machine == 'x86_64' or platform_machine == 'amd64' or platform_machine == 'AMD64') and python_version != '3.4'", + "version": "==0.0.10" + }, + "homebase": { + "hashes": [ + "sha256:9ee008df4298b420852d815e6df488822229c4bd8d571bcd0a454e04232c635e", + "sha256:d64c97f60a8ddd94ce8702bac65ed5d1996aca01a17d1e53e6ad5149e2f8b5b5" + ], + "version": "==1.0.1" + }, + "idna": { + "hashes": [ + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + ], + "version": "==2.8" + }, + "jsonschema": { + "hashes": [ + "sha256:000e68abd33c972a5248544925a0cae7d1125f9bf6c58280d37546b946769a08", + "sha256:6ff5f3180870836cae40f06fa10419f557208175f13ad7bc26caa77beb1f6e02" + ], + "version": "==2.6.0" + }, + "kiwisolver": { + "hashes": [ + "sha256:0ee4ed8b3ae8f5f712b0aa9ebd2858b5b232f1b9a96b0943dceb34df2a223bc3", + "sha256:0f7f532f3c94e99545a29f4c3f05637f4d2713e7fd91b4dd8abfc18340b86cd5", + "sha256:1a078f5dd7e99317098f0e0d490257fd0349d79363e8c923d5bb76428f318421", + "sha256:1aa0b55a0eb1bd3fa82e704f44fb8f16e26702af1a073cc5030eea399e617b56", + "sha256:2874060b91e131ceeff00574b7c2140749c9355817a4ed498e82a4ffa308ecbc", + "sha256:379d97783ba8d2934d52221c833407f20ca287b36d949b4bba6c75274bcf6363", + "sha256:3b791ddf2aefc56382aadc26ea5b352e86a2921e4e85c31c1f770f527eb06ce4", + "sha256:4329008a167fac233e398e8a600d1b91539dc33c5a3eadee84c0d4b04d4494fa", + "sha256:45813e0873bbb679334a161b28cb9606d9665e70561fd6caa8863e279b5e464b", + "sha256:53a5b27e6b5717bdc0125338a822605084054c80f382051fb945d2c0e6899a20", + "sha256:574f24b9805cb1c72d02b9f7749aa0cc0b81aa82571be5201aa1453190390ae5", + "sha256:66f82819ff47fa67a11540da96966fb9245504b7f496034f534b81cacf333861", + "sha256:79e5fe3ccd5144ae80777e12973027bd2f4f5e3ae8eb286cabe787bed9780138", + "sha256:83410258eb886f3456714eea4d4304db3a1fc8624623fc3f38a487ab36c0f653", + "sha256:8b6a7b596ce1d2a6d93c3562f1178ebd3b7bb445b3b0dd33b09f9255e312a965", + "sha256:9576cb63897fbfa69df60f994082c3f4b8e6adb49cccb60efb2a80a208e6f996", + "sha256:95a25d9f3449046ecbe9065be8f8380c03c56081bc5d41fe0fb964aaa30b2195", + "sha256:a424f048bebc4476620e77f3e4d1f282920cef9bc376ba16d0b8fe97eec87cde", + "sha256:aaec1cfd94f4f3e9a25e144d5b0ed1eb8a9596ec36d7318a504d813412563a85", + "sha256:acb673eecbae089ea3be3dcf75bfe45fc8d4dcdc951e27d8691887963cf421c7", + "sha256:b15bc8d2c2848a4a7c04f76c9b3dc3561e95d4dabc6b4f24bfabe5fd81a0b14f", + "sha256:b1c240d565e977d80c0083404c01e4d59c5772c977fae2c483f100567f50847b", + "sha256:c595693de998461bcd49b8d20568c8870b3209b8ea323b2a7b0ea86d85864694", + "sha256:ce3be5d520b4d2c3e5eeb4cd2ef62b9b9ab8ac6b6fedbaa0e39cdb6f50644278", + "sha256:e0f910f84b35c36a3513b96d816e6442ae138862257ae18a0019d2fc67b041dc", + "sha256:ea36e19ac0a483eea239320aef0bd40702404ff8c7e42179a2d9d36c5afcb55c", + "sha256:efabbcd4f406b532206b8801058c8bab9e79645b9880329253ae3322b7b02cd5", + "sha256:f923406e6b32c86309261b8195e24e18b6a8801df0cfc7814ac44017bfcb3939" + ], + "version": "==1.0.1" + }, + "matplotlib": { + "hashes": [ + "sha256:1ae6549976b6ceb6ee426272a28c0fc9715b3e3669694d560c8f661c5b39e2c5", + "sha256:4d4250bf508dd07cca3b43888097f873cadb66eec6ac63dbbfb798798ec07af2", + "sha256:53af2e01d7f1700ed2b64a9091bc865360c9c4032f625451c4589a826854c787", + "sha256:63e498067d32d627111cd1162cae1621f1221f9d4c6a9745dd7233f29de581b6", + "sha256:7169a34971e398dd58e87e173f97366fd88a3fa80852704530433eb224a8ca57", + "sha256:91c54d6bb9eeaaff965656c5ea6cbdcbf780bad8462ac99b30b451548194746f", + "sha256:aeef177647bb3fccfe09065481989d7dfc5ac59e9367d6a00a3481062cf651e4", + "sha256:cf8ae10559a78aee0409ede1e9d4fda03895433eeafe609dd9ed67e45f552db0", + "sha256:d51d0889d1c4d51c51a9822265c0494ea3e70a52bdd88358e0863daca46fa23a", + "sha256:de5ccd3500247f85fe4f9fad90f80a8bd397e4f110a4c33fabf95f07403e8372", + "sha256:e1d33589e32f482d0a7d1957bf473d43341115d40d33f578dad44432e47df7b7", + "sha256:e8d1939262aa6b36d0c51f50a50a43a04b9618d20db31e6c0192b1463067aeef", + "sha256:e918d51b1fda82a65fdf52d2f3914b2246481cc2a9cd10e223e6be6078916ff3" + ], + "index": "pypi", + "version": "==3.0.3" + }, + "minorminer": { + "hashes": [ + "sha256:00ada9e164362d9b7985563007cf551eaf3f26e7ab7a382abb930b8b5d9f0d80", + "sha256:24f2853e14c2c82c15fbc915d44a1790b850e3a80b5e8b0f840f698f75604f2c", + "sha256:37bce55d19f93376d50828c7b85b63dfe71a3e9d47210eeeae550f284b426cc1", + "sha256:4c955007dd815427b118af460a4aec66989b40fe6434025c070ac07e9897a9cb", + "sha256:501035af68d3980fc9199fa68e8fdc361468aa7cf67debdf933ff075d2fc86f2", + "sha256:5fb9eb0ac4eb7bd1f1c53d5a0aa4ed487295356595fac15b0b75226b402b7f43", + "sha256:642879ac513e15743ccfff124b30937ee519a37ffb7828fbc88786e02b8bb92d", + "sha256:65ebfb7079cd310f59ed95c2b3f36657fe0072ba9b48d824d6636ff41267b234", + "sha256:b870c36d1191000dda15a8a492dc289b4132e78d16f86ab86b0b213fd83f20c6", + "sha256:bb25c1bcad570fc2cee3f63beec78e8ad0ef1377aec9127c102a229f1a63567a", + "sha256:c52974ec605eb3c7b83570182e4cc04f992389025c4e265fde9e30cb9642e67e", + "sha256:cbb3f18218895ac84ac8a827c12aff71ff172173b2b151777697117a162454d0", + "sha256:d05705c15a1ed4387ffb7dfe5d418c7666dfa1620598736100ecf5a429abb514", + "sha256:e52470a487186fdbc8413beb2a368d82889bfbc25b6779500de2f9cfabfe7fb3", + "sha256:e8a0eff82322b143a1f1b622b3c60f116154ca9e28dc3fc7ae753ec8743b6f0d", + "sha256:ee3c0ef4e10e77e740ecd3d2066b7ffaee3a9c91c2410edb2983f0e758c6c07c" + ], + "version": "==0.1.8" + }, + "mysql-connector": { + "hashes": [ + "sha256:d5b95b8de234873563855e288f0c9ef85b119c0a862287cbcee7d6654cf60467" + ], + "index": "pypi", + "version": "==2.1.6" + }, + "networkx": { + "hashes": [ + "sha256:45e56f7ab6fe81652fb4bc9f44faddb0e9025f469f602df14e3b2551c2ea5c8b" + ], + "version": "==2.2" + }, + "numpy": { + "hashes": [ + "sha256:0df89ca13c25eaa1621a3f09af4c8ba20da849692dcae184cb55e80952c453fb", + "sha256:154c35f195fd3e1fad2569930ca51907057ae35e03938f89a8aedae91dd1b7c7", + "sha256:18e84323cdb8de3325e741a7a8dd4a82db74fde363dce32b625324c7b32aa6d7", + "sha256:1e8956c37fc138d65ded2d96ab3949bd49038cc6e8a4494b1515b0ba88c91565", + "sha256:23557bdbca3ccbde3abaa12a6e82299bc92d2b9139011f8c16ca1bb8c75d1e95", + "sha256:24fd645a5e5d224aa6e39d93e4a722fafa9160154f296fd5ef9580191c755053", + "sha256:36e36b6868e4440760d4b9b44587ea1dc1f06532858d10abba98e851e154ca70", + "sha256:3d734559db35aa3697dadcea492a423118c5c55d176da2f3be9c98d4803fc2a7", + "sha256:416a2070acf3a2b5d586f9a6507bb97e33574df5bd7508ea970bbf4fc563fa52", + "sha256:4a22dc3f5221a644dfe4a63bf990052cc674ef12a157b1056969079985c92816", + "sha256:4d8d3e5aa6087490912c14a3c10fbdd380b40b421c13920ff468163bc50e016f", + "sha256:4f41fd159fba1245e1958a99d349df49c616b133636e0cf668f169bce2aeac2d", + "sha256:561ef098c50f91fbac2cc9305b68c915e9eb915a74d9038ecf8af274d748f76f", + "sha256:56994e14b386b5c0a9b875a76d22d707b315fa037affc7819cda08b6d0489756", + "sha256:73a1f2a529604c50c262179fcca59c87a05ff4614fe8a15c186934d84d09d9a5", + "sha256:7da99445fd890206bfcc7419f79871ba8e73d9d9e6b82fe09980bc5bb4efc35f", + "sha256:99d59e0bcadac4aa3280616591fb7bcd560e2218f5e31d5223a2e12a1425d495", + "sha256:a4cc09489843c70b22e8373ca3dfa52b3fab778b57cf81462f1203b0852e95e3", + "sha256:a61dc29cfca9831a03442a21d4b5fd77e3067beca4b5f81f1a89a04a71cf93fa", + "sha256:b1853df739b32fa913cc59ad9137caa9cc3d97ff871e2bbd89c2a2a1d4a69451", + "sha256:b1f44c335532c0581b77491b7715a871d0dd72e97487ac0f57337ccf3ab3469b", + "sha256:b261e0cb0d6faa8fd6863af26d30351fd2ffdb15b82e51e81e96b9e9e2e7ba16", + "sha256:c857ae5dba375ea26a6228f98c195fec0898a0fd91bcf0e8a0cae6d9faf3eca7", + "sha256:cf5bb4a7d53a71bb6a0144d31df784a973b36d8687d615ef6a7e9b1809917a9b", + "sha256:db9814ff0457b46f2e1d494c1efa4111ca089e08c8b983635ebffb9c1573361f", + "sha256:df04f4bad8a359daa2ff74f8108ea051670cafbca533bb2636c58b16e962989e", + "sha256:ecf81720934a0e18526177e645cbd6a8a21bb0ddc887ff9738de07a1df5c6b61", + "sha256:edfa6fba9157e0e3be0f40168eb142511012683ac3dc82420bee4a3f3981b30e" + ], + "version": "==1.15.4" + }, + "ortools": { + "hashes": [ + "sha256:4ccb87b18f771adcbcdb4d580f23faab3f69ecc6b44a77502f229a0a207d104a", + "sha256:514f1ecfdd90372caba9d7e6e910ee0e530ca0aeee3fdeac0ea2648c2f3ed3be", + "sha256:5536de9892729b6ffbf55ad7a1bdc92c599c17bd6ebe31fff02f981c18c8db7b", + "sha256:6f45cf972a4194350566c141761fba21ab0d4ee88ecf47f1f46d0c6465263e3b", + "sha256:7090a9b368c090cb6bde35d4b04f4a755c25005ab7b577949868efdc90edc4ab", + "sha256:71c318bdac89bbeae83ec81ded3e7e82ae4597398efecf38cd69672feec2580d", + "sha256:7a83ea7254a4d8371d0a0c99f479297ec9db9927cec2cc81ba6c896b3b963591", + "sha256:84c9af9014720c2257e7b68123a14f63464bcf558143f673113679a8a14b9534", + "sha256:882cfeedd78908e0ee4419834c73f444c412b4f0ac987057b1b2bce35a383b9a", + "sha256:8ebd542cec43184aa49a8836105d0f16b877907930f061d646e5e010aa985ca5", + "sha256:a1e5dbecdd98207582e2ed5152028affa00531c60c940c616ca2edb832407c07", + "sha256:e2e61054bbe87e9a67466610a60371c22a438cbc37fefbc7309fb93756de79cb" + ], + "version": "==6.10.6025" + }, + "pandas": { + "hashes": [ + "sha256:071e42b89b57baa17031af8c6b6bbd2e9a5c68c595bc6bf9adabd7a9ed125d3b", + "sha256:17450e25ae69e2e6b303817bdf26b2cd57f69595d8550a77c308be0cd0fd58fa", + "sha256:17916d818592c9ec891cbef2e90f98cc85e0f1e89ed0924c9b5220dc3209c846", + "sha256:2538f099ab0e9f9c9d09bbcd94b47fd889bad06dc7ae96b1ed583f1dc1a7a822", + "sha256:366f30710172cb45a6b4f43b66c220653b1ea50303fbbd94e50571637ffb9167", + "sha256:42e5ad741a0d09232efbc7fc648226ed93306551772fc8aecc6dce9f0e676794", + "sha256:4e718e7f395ba5bfe8b6f6aaf2ff1c65a09bb77a36af6394621434e7cc813204", + "sha256:4f919f409c433577a501e023943e582c57355d50a724c589e78bc1d551a535a2", + "sha256:4fe0d7e6438212e839fc5010c78b822664f1a824c0d263fd858f44131d9166e2", + "sha256:5149a6db3e74f23dc3f5a216c2c9ae2e12920aa2d4a5b77e44e5b804a5f93248", + "sha256:627594338d6dd995cfc0bacd8e654cd9e1252d2a7c959449228df6740d737eb8", + "sha256:83c702615052f2a0a7fb1dd289726e29ec87a27272d775cb77affe749cca28f8", + "sha256:8c872f7fdf3018b7891e1e3e86c55b190e6c5cee70cab771e8f246c855001296", + "sha256:90f116086063934afd51e61a802a943826d2aac572b2f7d55caaac51c13db5b5", + "sha256:a3352bacac12e1fc646213b998bce586f965c9d431773d9e91db27c7c48a1f7d", + "sha256:bcdd06007cca02d51350f96debe51331dec429ac8f93930a43eb8fb5639e3eb5", + "sha256:c1bd07ebc15285535f61ddd8c0c75d0d6293e80e1ee6d9a8d73f3f36954342d0", + "sha256:c9a4b7c55115eb278c19aa14b34fcf5920c8fe7797a09b7b053ddd6195ea89b3", + "sha256:cc8fc0c7a8d5951dc738f1c1447f71c43734244453616f32b8aa0ef6013a5dfb", + "sha256:d7b460bc316064540ce0c41c1438c416a40746fd8a4fb2999668bf18f3c4acf1" + ], + "version": "==0.24.2" + }, + "penaltymodel": { + "hashes": [ + "sha256:376c74a93b190e05161c353bead40b73089a9432668229bde5d1f97c7eec68ca", + "sha256:5102cf0437b6306599abd60dad5950b709c0307c5a71f352cf0525de79857a90" + ], + "version": "==0.15.4" + }, + "penaltymodel-cache": { + "hashes": [ + "sha256:4ff796642d0afb6d48ea31bac614cdbfa76429b4fe8cf4986bcce4b06bc51473", + "sha256:d3c8c1ab762d72c3999a96525c546666ea9f9a8cbed743e35b34c5b059a20d6d" + ], + "version": "==0.3.3" + }, + "penaltymodel-mip": { + "hashes": [ + "sha256:66f373851486169e5356e866b1acf0e855cf21e1f7d7af6200301046ce9a0aaf", + "sha256:d65ca314af9a42593ffdb9fa0fc33e01c35b330383ca20368b7391409c2c24d7" + ], + "version": "==0.1.4" + }, + "plucky": { + "hashes": [ + "sha256:5bc75d43ae6b40f1b7ba42000b37e4934fa6bd2d6a6cd4e47461f803a404c194", + "sha256:a358878f3e45b5e51d0b4e5b5c89d704422a72c2cf8ee9aaf9acedfa53f89105" + ], + "version": "==0.4.3" + }, + "protobuf": { + "hashes": [ + "sha256:03666634d038e35d90155756914bc3a6316e8bcc0d300f3ee539e586889436b9", + "sha256:049d5900e442d4cc0fd2afd146786b429151e2b29adebed28e6376026ab0ee0b", + "sha256:0eb9e62a48cc818b1719b5035042310c7e4f57b01f5283b32998c68c2f1c6a7c", + "sha256:255d10c2c9059964f6ebb5c900a830fc8a089731dda94a5cc873f673193d208b", + "sha256:358cc59e4e02a15d3725f204f2eb5777fc10595e2d9a9c4c8d82292f49af6d41", + "sha256:41f1b737d5f97f1e2af23d16fac6c0b8572f9c7ea73054f1258ca57f4f97cb80", + "sha256:6a5129576a2cf925cd100e06ead5f9ae4c86db70a854fb91cedb8d680112734a", + "sha256:80722b0d56dcb7ca8f75f99d8dadd7c7efd0d2265714d68f871ed437c32d82b3", + "sha256:88a960e949ec356f7016d84f8262dcff2b842fca5355b4c1be759f5c103b19b3", + "sha256:97872686223f47d95e914881cb0ca46e1bc622562600043da9edddcb54f2fe1e", + "sha256:a1df9d22433ab44b7c7e0bd33817134832ae8a8f3d93d9b9719fc032c5b20e96", + "sha256:ad385fbb9754023d17be14dd5aa67efff07f43c5df7f93118aef3c20e635ea19", + "sha256:b2d5ee7ba5c03b735c02e6ae75fd4ff8c831133e7ca078f2963408dc7beac428", + "sha256:c8c07cd8635d45b28ec53ee695e5ac8b0f9d9a4ae488a8d8ee168fe8fc75ba43", + "sha256:d44ebc9838b183e8237e7507885d52e8d08c48fdc953fd4a7ee3e56cb9d20977", + "sha256:dff97b0ee9256f0afdfc9eaa430736cdcdc18899d9a666658f161afd137cf93d", + "sha256:e47d248d614c68e4b029442de212bdd4f6ae02ae36821de319ae90314ea2578c", + "sha256:e650b521b429fed3d525428b1401a40051097a5a92c30076c91f36b31717e087" + ], + "version": "==3.7.0" + }, + "pymongo": { + "hashes": [ + "sha256:025f94fc1e1364f00e50badc88c47f98af20012f23317234e51a11333ef986e6", + "sha256:02aa7fb282606331aefbc0586e2cf540e9dbe5e343493295e7f390936ad2738e", + "sha256:057210e831573e932702cf332012ed39da78edf0f02d24a3f0b213264a87a397", + "sha256:0d946b79c56187fe139276d4c8ed612a27a616966c8b9779d6b79e2053587c8b", + "sha256:104790893b928d310aae8a955e0bdbaa442fb0ac0a33d1bbb0741c791a407778", + "sha256:15527ef218d95a8717486106553b0d54ff2641e795b65668754e17ab9ca6e381", + "sha256:1826527a0b032f6e20e7ac7f72d7c26dd476a5e5aa82c04aa1c7088a59fded7d", + "sha256:22e3aa4ce1c3eebc7f70f9ca7fd4ce1ea33e8bdb7b61996806cd312f08f84a3a", + "sha256:244e1101e9a48615b9a16cbd194f73c115fdfefc96894803158608115f703b26", + "sha256:24b8c04fdb633a84829d03909752c385faef249c06114cc8d8e1700b95aae5c8", + "sha256:2c276696350785d3104412cbe3ac70ab1e3a10c408e7b20599ee41403a3ed630", + "sha256:2d8474dc833b1182b651b184ace997a7bd83de0f51244de988d3c30e49f07de3", + "sha256:3119b57fe1d964781e91a53e81532c85ed1701baaddec592e22f6b77a9fdf3df", + "sha256:3bee8e7e0709b0fcdaa498a3e513bde9ffc7cd09dbceb11e425bd91c89dbd5b6", + "sha256:436c071e01a464753d30dbfc8768dd93aecf2a8e378e5314d130b95e77b4d612", + "sha256:46635e3f19ad04d5a7d7cf23d232388ddbfccf46d9a3b7436b6abadda4e84813", + "sha256:4772e0b679717e7ac4608d996f57b6f380748a919b457cb05bb941467b888b22", + "sha256:4e2cd80e16f481a62c3175b607373200e714ed29025f21559ebf7524f295689f", + "sha256:52732960efa0e003ca1c092dc0a3c65276e897681287a788a01ca78dda3b41f0", + "sha256:55a7de51ec7d1731b2431886d0349146645f2816e5b8eb982d7c49f89472c9f3", + "sha256:5f8ed5934197a2d4b2087646e98de3e099a237099dcf498b9e38dd3465f74ef4", + "sha256:64b064124fcbc8eb04a155117dc4d9a336e3cda3f069958fbc44fe70c3c3d1e9", + "sha256:65958b8e4319f992e85dad59d8081888b97fcdbde5f0d14bc28f2848b92d3ef1", + "sha256:7683428862e20c6a790c19e64f8ccf487f613fbc83d47e3d532df9c81668d451", + "sha256:78566d5570c75a127c2491e343dc006798a384f06be588fe9b0cbe5595711559", + "sha256:7d1cb00c093dbf1d0b16ccf123e79dee3b82608e4a2a88947695f0460eef13ff", + "sha256:8c74e2a9b594f7962c62cef7680a4cb92a96b4e6e3c2f970790da67cc0213a7e", + "sha256:8e60aa7699170f55f4b0f56ee6f8415229777ac7e4b4b1aa41fc61eec08c1f1d", + "sha256:9447b561529576d89d3bf973e5241a88cf76e45bd101963f5236888713dea774", + "sha256:970055bfeb0be373f2f5299a3db8432444bad3bc2f198753ee6c2a3a781e0959", + "sha256:a6344b8542e584e140dc3c651d68bde51270e79490aa9320f9e708f9b2c39bd5", + "sha256:ce309ca470d747b02ba6069d286a17b7df8e9c94d10d727d9cf3a64e51d85184", + "sha256:cfbd86ed4c2b2ac71bbdbcea6669bf295def7152e3722ddd9dda94ac7981f33d", + "sha256:d7929c513732dff093481f4a0954ed5ff16816365842136b17caa0b4992e49d3" + ], + "index": "pypi", + "version": "==3.7.2" + }, + "pyparsing": { + "hashes": [ + "sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a", + "sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3" + ], + "version": "==2.3.1" + }, + "pysocks": { + "hashes": [ + "sha256:3fe52c55890a248676fd69dc9e3c4e811718b777834bcaab7a8125cf9deac672" + ], + "version": "==1.6.8" + }, + "python-dateutil": { + "hashes": [ + "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", + "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" + ], + "version": "==2.8.0" + }, + "pytz": { + "hashes": [ + "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", + "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" + ], + "version": "==2018.9" + }, + "requests": { + "extras": [ + "socks" + ], + "hashes": [ + "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", + "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" + ], + "version": "==2.21.0" + }, + "scipy": { + "hashes": [ + "sha256:014cb900c003b5ac81a53f2403294e8ecf37aedc315b59a6b9370dce0aa7627a", + "sha256:281a34da34a5e0de42d26aed692ab710141cad9d5d218b20643a9cb538ace976", + "sha256:588f9cc4bfab04c45fbd19c1354b5ade377a8124d6151d511c83730a9b6b2338", + "sha256:5a10661accd36b6e2e8855addcf3d675d6222006a15795420a39c040362def66", + "sha256:628f60be272512ca1123524969649a8cb5ae8b31cca349f7c6f8903daf9034d7", + "sha256:6dcc43a88e25b815c2dea1c6fac7339779fc988f5df8396e1de01610604a7c38", + "sha256:70e37cec0ac0fe95c85b74ca4e0620169590fd5d3f44765f3c3a532cedb0e5fd", + "sha256:7274735fb6fb5d67d3789ddec2cd53ed6362539b41aa6cc0d33a06c003aaa390", + "sha256:78e12972e144da47326958ac40c2bd1c1cca908edc8b01c26a36f9ffd3dce466", + "sha256:790cbd3c8d09f3a6d9c47c4558841e25bac34eb7a0864a9def8f26be0b8706af", + "sha256:79792c8fe8e9d06ebc50fe23266522c8c89f20aa94ac8e80472917ecdce1e5ba", + "sha256:865afedf35aaef6df6344bee0de391ee5e99d6e802950a237f9fb9b13e441f91", + "sha256:870fd401ec7b64a895cff8e206ee16569158db00254b2f7157b4c9a5db72c722", + "sha256:963815c226b29b0176d5e3d37fc9de46e2778ce4636a5a7af11a48122ef2577c", + "sha256:9726791484f08e394af0b59eb80489ad94d0a53bbb58ab1837dcad4d58489863", + "sha256:9de84a71bb7979aa8c089c4fb0ea0e2ed3917df3fb2a287a41aaea54bbad7f5d", + "sha256:b2c324ddc5d6dbd3f13680ad16a29425841876a84a1de23a984236d1afff4fa6", + "sha256:b86ae13c597fca087cb8c193870507c8916cefb21e52e1897da320b5a35075e5", + "sha256:ba0488d4dbba2af5bf9596b849873102d612e49a118c512d9d302ceafa36e01a", + "sha256:d78702af4102a3a4e23bb7372cec283e78f32f5573d92091aa6aaba870370fe1", + "sha256:def0e5d681dd3eb562b059d355ae8bebe27f5cc455ab7c2b6655586b63d3a8ea", + "sha256:e085d1babcb419bbe58e2e805ac61924dac4ca45a07c9fa081144739e500aa3c", + "sha256:e2cfcbab37c082a5087aba5ff00209999053260441caadd4f0e8f4c2d6b72088", + "sha256:e742f1f5dcaf222e8471c37ee3d1fd561568a16bb52e031c25674ff1cf9702d5", + "sha256:f06819b028b8ef9010281e74c59cb35483933583043091ed6b261bb1540f11cc", + "sha256:f15f2d60a11c306de7700ee9f65df7e9e463848dbea9c8051e293b704038da60", + "sha256:f31338ee269d201abe76083a990905473987371ff6f3fdb76a3f9073a361cf37", + "sha256:f6b88c8d302c3dac8dff7766955e38d670c82e0d79edfc7eae47d6bb2c186594" + ], + "version": "==1.2.1" + }, + "seaborn": { + "hashes": [ + "sha256:42e627b24e849c2d3bbfd059e00005f6afbc4a76e4895baf44ae23fe8a4b09a5", + "sha256:76c83f794ca320fb6b23a7c6192d5e185a5fcf4758966a0c0a54baee46d41e2f" + ], + "index": "pypi", + "version": "==0.9.0" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "version": "==1.12.0" + }, + "tqdm": { + "hashes": [ + "sha256:d385c95361699e5cf7622485d9b9eae2d4864b21cd5a2374a9c381ffed701021", + "sha256:e22977e3ebe961f72362f6ddfb9197cc531c9737aaf5f607ef09740c849ecd05" + ], + "index": "pypi", + "version": "==4.31.1" + }, + "urllib3": { + "hashes": [ + "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", + "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" + ], + "version": "==1.24.1" + } + }, + "develop": {} +} diff --git a/SConstruct b/SConstruct index 4fb3b68..c83460c 100644 --- a/SConstruct +++ b/SConstruct @@ -10,6 +10,8 @@ globalEnv['BUILDPATH'] = os.path.join(basicBuildPath, 'release') globalEnv['CONTRIBPATH'] = os.path.join(globalEnv['ROOTPATH'], 'contrib') globalEnv['MONGOCPATH'] = os.path.join(globalEnv['CONTRIBPATH'], 'mongoc') globalEnv['MONGOCXXPATH'] = os.path.join(globalEnv['CONTRIBPATH'], 'mongocxx') +globalEnv['QBSCXXPATH'] = os.path.join(globalEnv['CONTRIBPATH'], 'qubosolver') + globalEnv["INIHSRC"] = os.path.join( os.path.join(globalEnv["CONTRIBPATH"], "iniParser"), @@ -19,14 +21,29 @@ globalEnv["MINISATSRC"] = os.path.join( os.path.join(globalEnv["CONTRIBPATH"], "minisat"), "src") +globalEnv["QBSCXXSRC"] = os.path.join( + os.path.join( + os.path.join(globalEnv["CONTRIBPATH"], + "qubosolver"), + "qbscxx"), + "src") +globalEnv["QBSCXX_INCLUDE"] = os.path.join( + os.path.join( + os.path.join(globalEnv["CONTRIBPATH"], + "qubosolver"), + "qbscxx"), + "include") #compiler option AddOption('--dbg', action='store_true', dest='DEBUG') +globalEnv["BUILD_TYPE"] = "Release" + if GetOption('DEBUG'): - globalEnv.Append(CCFLAGS="-g") - globalEnv['BUILDPATH'] = os.path.join(basicBuildPath, 'debug') + globalEnv["BUILD_TYPE"] = "Debug" + globalEnv.Append(CCFLAGS="-g") + globalEnv['BUILDPATH'] = os.path.join(basicBuildPath, 'debug') globalEnv.Append(CXXFLAGS='-std=c++11') AddOption("--init", action="store_true", dest="INIT") @@ -59,6 +76,18 @@ if GetOption("INIT"): variant_dir=globalEnv["MONGOCXX_LIB_PATH"], duplicate=0, exports="globalEnv") + +#build qbscxx +globalEnv["QBSCXX_LIB_PATH"] = os.path.join(globalEnv["LIB_BUILD_PATH"], "qbscxx") + +if GetOption("INIT"): + globalEnv.SConscript(os.path.join( + os.path.join(globalEnv["CONTRIBPATH"], + "qubosolver"), + "SConscript"), + variant_dir=globalEnv["QBSCXX_LIB_PATH"], + duplicate=0, + exports="globalEnv") #build inih globalEnv["INIH_LIB_PATH"] = os.path.join(globalEnv["LIB_BUILD_PATH"], "inih") @@ -96,7 +125,7 @@ bsoncxxIncludeDir = os.path.join( "include"), "bsoncxx"), "v_noabi") - + inihIncludeDir = globalEnv["INIHSRC"] inihcppIncludeDir = globalEnv["INIHCPPSRC"] @@ -106,11 +135,15 @@ globalEnv.Append(CPPPATH=[mongocxxIncludeDir, bsoncxxIncludeDir, inihIncludeDir, inihcppIncludeDir, - minisatIncludeDir]) + minisatIncludeDir, + globalEnv["QBSCXXSRC"], + globalEnv["QBSCXX_INCLUDE"]]) + globalEnv.Append(LIBPATH=[os.path.join(globalEnv["MONGOCXX_LIB_PATH"], "lib"), globalEnv["INIH_LIB_PATH"], - globalEnv["MINISAT_LIB_PATH"]]) + globalEnv["MINISAT_LIB_PATH"], + globalEnv["QBSCXX_LIB_PATH"]]) #build runMinisat diff --git a/collect_variable_degrees.py b/collect_variable_degrees.py new file mode 100755 index 0000000..574f369 --- /dev/null +++ b/collect_variable_degrees.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +import util.script as script +import mysql.connector +from util.kSAT import kSAT + +def main(): + + edb = script.connect_to_experimetns_db("database.config") + idb = script.connect_to_instance_pool("database.config")["experiments"] + + cursor = edb.cursor() + + insert_row = ("INSERT INTO degree_of_variables " + "(instance, variable, degree) " + "VALUES (%s, %s, %s)") + + for instance in idb["instances"].find(): + sat = kSAT() + + for clause in instance["clauses"]: + sat.addClause(clause) + + for variable, degree in sat.getDegreesOfVariables().items(): + cursor.execute(insert_row, (str(instance["_id"]), variable, degree)) + + edb.commit() + + cursor.close() + edb.close() + + + +if __name__ == "__main__": + main() + diff --git a/contrib/qubosolver/SConscript b/contrib/qubosolver/SConscript new file mode 100644 index 0000000..90803d7 --- /dev/null +++ b/contrib/qubosolver/SConscript @@ -0,0 +1,35 @@ +import os + +Import("globalEnv") + +env = globalEnv.Clone() + +env["QBSCXX_SRC"] = os.path.join(env["QBSCXXPATH"], "qbscxx") + +cmake_build_path = os.path.join(env["QBSCXX_LIB_PATH"], "cmake_build") + +if not os.path.exists(cmake_build_path): + os.makedirs(cmake_build_path) + +if not os.path.exists(env["QBSCXX_LIB_PATH"]): + os.makedirs(env["QBSCXX_LIB_PATH"]) + +cwd = os.getcwd() + +os.chdir(cmake_build_path) + +cmakeCall = "cmake -DCMAKE_BUILD_TYPE={} ".format(env["BUILD_TYPE"]) +#cmakeCall += "-DCMAKE_INSTALL_PREFIX=" + env["QBSCXX_LIB_PATH"] + " " +cmakeCall += env["QBSCXX_SRC"] + +os.system(cmakeCall) + +os.system("make") + +#os.system("make install") + +env.Install(env["QBSCXX_LIB_PATH"], [os.path.join("cmake_build", "libqbsolv.a")]) + +os.chdir(cwd) + + diff --git a/contrib/qubosolver/qbscxx b/contrib/qubosolver/qbscxx new file mode 160000 index 0000000..a409dad --- /dev/null +++ b/contrib/qubosolver/qbscxx @@ -0,0 +1 @@ +Subproject commit a409dadcf62546c950bb09fa44d06830e0740faf diff --git a/create_WMIS_QUBOS.py b/create_WMIS_QUBOS.py new file mode 100755 index 0000000..42c905e --- /dev/null +++ b/create_WMIS_QUBOS.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +from util.kSAT import kSAT +from util import SAT2QUBO +import util.script as scriptUtils +import pymongo +import ssl +import json + +def main(): + args = __parseArguments() + + dbContext = scriptUtils.getDBContext(args["dbConfigPath"]) + + __createQubos(dbContext, args["experimentScope"]) + +def __parseArguments(): + parser = scriptUtils.ArgParser() + + parser.addArg(alias="experimentScope", shortFlag="s", longFlag="scope", + help="the experiment experiment scope of interest", type=str) + + parser.addArg(alias="dbConfigPath", shortFlag="d", longFlag="db_config", + help="path to the database config file", type=str, + default="database.config") + + + return parser.parse() + + +def __createQubos(dbContext, experimentScope): + instances = __queryInstancs(dbContext["db"], experimentScope) + + for instance in instances: + sat = kSAT() + + for clause in instance["clauses"]: + sat.addClause(clause); + + qubo = SAT2QUBO.WMISdictQUBO(sat) + + doc = {} + + doc["instance"] = instance["_id"] + doc["description"] = {"": "", + "": " | | \"\"", + "": "", + "": "", + "": "", + "": "", + "": "", + "": ""} + doc["qubo"] = __qubo2JSON(qubo) + + dbContext["db"]["wmis_qubos"].insert_one(doc) + +def __qubo2JSON(qubo): + quboJSON = [] + + for coupler, value in qubo.items(): + quboJSON.append([coupler, float(value)]) + + return quboJSON + +def __queryInstancs(db, experimentScope): + return db["experiment_scopes"].aggregate([ + { + "$match": {"_id": experimentScope} + }, + { + "$unwind": "$instances" + }, + { + "$lookup": + { + "from": "instances", + "localField": "instances", + "foreignField": "_id", + "as": "instance" + } + }, + { + "$unwind": "$instance" + }, + { + "$replaceRoot": {"newRoot": "$instance"} + } + ]) + + +if __name__ == "__main__": + main() diff --git a/generateRandomKsatDataSet_db.py b/generateRandomKsatDataSet_db.py index b06bb35..b493897 100755 --- a/generateRandomKsatDataSet_db.py +++ b/generateRandomKsatDataSet_db.py @@ -9,7 +9,7 @@ import ssl def main(): args = __parseArguments() - dbContext = __getDBContext(args["dbConfigPath"]) + dbContext = scriptUtils.getDBContext(args["dbConfigPath"]) __generateExperiment(args, dbContext) @@ -33,41 +33,6 @@ def __generateExperiment(args, dbContext): def __packDocument(instance): doc = instance.writeJSONLike(); - doc["degrees_of_variables"] = __packDegreesOfVariables(instance) - - doc["conflicts"] = __packConflicts(instance) - - return doc - -def __packDegreesOfVariables(instance): - doc = [] - - for var, degree in instance.getDegreesOfVariables().items(): - doc.append({"var": var, "deg": degree}) - - return doc - -def __packConflicts(instance): - doc = [{"var": i + 1, - "clauses": { - "pos_lit": [], - "neg_lit": []}} for i in range(instance.getNumberOfVariables())] - - for conflict in instance.getConflicts(): - - for binding in conflict: - clause = binding[0] - lit = binding[1] - varIndex = abs(lit) - 1 - - if lit > 0: - if clause not in doc[varIndex]["clauses"]["pos_lit"]: - doc[varIndex]["clauses"]["pos_lit"].append(clause) - else: - if clause not in doc[varIndex]["clauses"]["neg_lit"]: - doc[varIndex]["clauses"]["neg_lit"].append(clause) - - return doc def __prepareExperimentScope(args): @@ -88,31 +53,6 @@ def __prepareExperimentScope(args): return experimentScope -def __getDBClient(dbConfigPath): - dbConf = scriptUtils.readConfig(dbConfigPath) - dbConf["CONNECTION"] - - return pymongo.MongoClient( - "mongodb://%s:%s@%s:%s/%s" - % ( dbConf["CONNECTION"]["user"], - dbConf["CONNECTION"]["pw"], - dbConf["CONNECTION"]["url"], - dbConf["CONNECTION"]["port"], - dbConf["CONNECTION"]["database"]), - ssl=True, - ssl_cert_reqs=ssl.CERT_NONE) - - -def __getDBContext(dbConfigPath): - dbContext = {} - - dbContext["client"] = __getDBClient(dbConfigPath) - dbContext["db"] = dbContext["client"]["experiments"] - dbContext["instances"] = dbContext["db"]["instances"] - dbContext["experimentScopes"] = dbContext["db"]["experiment_scopes"] - - return dbContext - def __parseArguments(): parser = scriptUtils.ArgParser() diff --git a/queryInstancesFromScope.js b/queryInstancesFromScope.js new file mode 100644 index 0000000..3152642 --- /dev/null +++ b/queryInstancesFromScope.js @@ -0,0 +1,23 @@ +db.getCollection("experiment_scopes").aggregate([ +{ + $match: {_id: "test"} +}, +{ + $unwind : "$instances" +}, +{ + $lookup: + { + from: "instances", + localField: "instances", + foreignField: "_id", + as: "instance" + } +}, +{ + $unwind: "$instance" +}, +{ + $replaceRoot: {newRoot: "$instance"} +} +]) \ No newline at end of file diff --git a/query_req_data_for_solving.js b/query_req_data_for_solving.js new file mode 100644 index 0000000..e1ae0a0 --- /dev/null +++ b/query_req_data_for_solving.js @@ -0,0 +1,77 @@ +db.getCollection('experiment_scopes').aggregate( +[ +{ + $match: {_id: "c50_v[5, 50]_1"} +}, +{ + $unwind: "$instances" +}, +{ + $project: {"instance_id": "$instances"} +}, +{ + $lookup: + { + from: "wmis_qubos", + localField: "instance_id", + foreignField: "instance", + as: "wmis_qubo" + } +}, +{ + $unwind: "$wmis_qubo" +}, +{ + $lookup: + { + from: "embeddings", + let: + { + qubo_id: "$wmis_qubo._id", + solver_graph_id: ObjectId("5c9e13168c6fe628c16eb361") + }, + pipeline: + [ + { + $match: + { + $expr: + { + $and: + [ + {$eq: ["$qubo", "$$qubo_id"]}, + {$eq: ["$solver_graph", "$$solver_graph_id"]} + ] + } + } + }, + { + $project: + { + /*_id: false, + qubo: false, + solver_graph: false, + description: false*/ + embeddings: true + } + } + ], + as: "embeddings" + } +}, +{ + $match: {embeddings: {$exists: true, $not: {$size: 0}}} +}, +{ + $unwind: "$embeddings" +}, +{ + $project: + { + _id: false, + instance_id: true, + wmis_qubo: true, + embeddings: "$embeddings.embeddings" + } +} +]) \ No newline at end of file diff --git a/src/SConscript b/src/SConscript index 3a3f3cf..2a8cff8 100644 --- a/src/SConscript +++ b/src/SConscript @@ -4,16 +4,24 @@ Import('globalEnv') env = globalEnv.Clone() -files = Glob(os.path.join(".","*.cpp")) -files.append(Glob(os.path.join("util", "*.cpp"))) +utilFiles = Glob(os.path.join("util","*.cpp")) + +## runMinisat ## targetName = 'runMinisat' -libs = ["mongocxx", "bsoncxx", "inihcpp", "minisat"] +libs = ["mongocxx", "bsoncxx", "inihcpp", "minisat", "qbsolv"] env.Append(CPPPATH=os.path.join(env["ROOTPATH"], "src")) -env.Program(target=targetName, source=files, LIBS=libs) +env.Program(target=targetName, + source=[utilFiles, "runMinisat.cpp"], + LIBS=libs) + +## runMinisat ## +env.Program(target="runQbsolv", + source=[utilFiles, "runQbsolv.cpp"], + LIBS=libs) ## create start script # @@ -27,6 +35,17 @@ with open(startScriptName, "w") as startScript: .format(os.path.join(env["MONGOCXX_LIB_PATH"], "lib"))) startScript.write("{}\n".format(os.path.join(env["BUILDPATH"], targetName))) + + +startScriptName = "{}.sh".format("runQbsolv") + +with open(startScriptName, "w") as startScript: + startScript.write("#!/bin/bash\n") + + startScript.write("export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:{}\n" + .format(os.path.join(env["MONGOCXX_LIB_PATH"], "lib"))) + + startScript.write("{}\n".format(os.path.join(env["BUILDPATH"], "runQbsolv"))) #env.Install(env["BUILDPATH"], [startScriptName]) diff --git a/src/runMinisat.cpp b/src/runMinisat.cpp index 591c366..5b9807d 100644 --- a/src/runMinisat.cpp +++ b/src/runMinisat.cpp @@ -36,15 +36,14 @@ int main(int argc, char** argv) mongocxx::collection instances = db["instances"]; + bsoncxx::builder::stream::document result; for(auto sat : satlab::MongoDBExperimentScope(db, getScopeName())) { satlab::MinisatSolver solver(sat); solver.solve(); - auto result = satlab::convert( - solver.getResult() - ); + satlab::convert<>(result, solver.getResult()); db["minisat_runs"].insert_one(result.view()); } diff --git a/src/runQbsolv.cpp b/src/runQbsolv.cpp new file mode 100644 index 0000000..3458184 --- /dev/null +++ b/src/runQbsolv.cpp @@ -0,0 +1,161 @@ +#include + +#include "solver_cxx.h" +#include "util/conversions.h" + +#include "mongocxx/instance.hpp" +#include "mongocxx/client.hpp" +#include "mongocxx/database.hpp" +#include "mongocxx/collection.hpp" +#include "mongocxx/cursor.hpp" + +#include "INIReader.h" + +#include "util/wmis_qubo.h" + +std::string getDbConfigFilePath(); +std::string getScopeName(); +std::string getDBUrl(); +mongocxx::client connectToDatabase(); +void print(const qbscxx::SOLUTION& solution, const satlab::wmis_qubo& qubo); + +int main(int argc, char** argv) +{ + mongocxx::instance inst{}; + + mongocxx::client conn = connectToDatabase(); + + mongocxx::database db = conn["experiments"]; + + mongocxx::collection wmis_qubos = db["wmis_qubos"]; + + + std::cout << "runQbsolv" << std::endl; + + satlab::wmis_qubo wmis_qubo; + + for(auto& el : wmis_qubos.find({})) + { + satlab::types::convert(wmis_qubo, el); + + qbscxx::Solver solver(wmis_qubo.get_qubo()); + + solver.set_goal(qbscxx::Solver::GOAL::MAXIMUM); + solver.set_verbosity(-1); + + solver.solve(); + + print(solver.get_solution(), wmis_qubo); + + std::cout << std::endl; + + } + + return 0; +} + + +mongocxx::client connectToDatabase() +{ + mongocxx::options::ssl sslOptions; + sslOptions.allow_invalid_certificates(true); + + mongocxx::options::client clientOptions{}; + clientOptions.ssl_opts(sslOptions); + + return mongocxx::client{mongocxx::uri{getDBUrl()}, clientOptions}; +} + +std::string getDBUrl() +{ + INIReader iniReader(getDbConfigFilePath()); + + std::string connUrl("mongodb://"); + connUrl.append(iniReader.Get("CONNECTION", "user", "NA") + ":"); + connUrl.append(iniReader.Get("CONNECTION", "pw", "NA") + "@"); + connUrl.append(iniReader.Get("CONNECTION", "url", "NA") + ":"); + connUrl.append(iniReader.Get("CONNECTION", "port", "NA") + "/"); + connUrl.append(iniReader.Get("CONNECTION", "database", "NA")); + connUrl.append("?ssl=true"); + + return connUrl; +} + +std::string getDbConfigFilePath() +{ + std::cout << "Database config file: "; + + std::string path; + + std::cin >> path; + + return path; +} + +std::string getScopeName() +{ + std::cout << "Experiment scope: "; + + std::string scope; + + std::cin >> scope; + + return scope; +} + +void print(const qbscxx::SOLUTION& solution, const satlab::wmis_qubo& qubo) +{ + qbscxx::ENERGY_T resulution_energy = 0; + for(int val : solution) + { + resulution_energy += val; + + std::cout << val; + } + + std::cout << " " << resulution_energy << std::endl; + + std::vector model; + int conflicts = 0; + for(int i = 0; i < solution.size(); i++) + { + auto node = qubo.node_at(i); + int lit = std::get<1>(node); + size_t var = std::abs(lit); + + bool newVar = false; + if(model.size() < var) + { + newVar = true; + model.resize(var); + } + + bool binding; + if(solution[i] == 0) + { + binding = lit < 0 ? true : false; + } + else + { + binding = lit < 0 ? false : true; + } + + if(!newVar && binding != model[var - 1]) + { + conflicts++; + } + + model[var - 1] = binding; + } + + + for(int i=0; i < model.size(); i++) + { + int var = i + 1; + std::cout << (model[i] ? var : -1 * var) << " "; + } + + std::cout << std::endl; +} + + diff --git a/src/util/bson2ksatClauseConverter.h b/src/util/bson2ksatClauseConverter.h index 23ff911..05cfa73 100644 --- a/src/util/bson2ksatClauseConverter.h +++ b/src/util/bson2ksatClauseConverter.h @@ -16,16 +16,14 @@ namespace types { template -KSATinstance::CLAUSE convert(const bsoncxx::array::element& docView) +void convert(KSATinstance::CLAUSE& clause, const bsoncxx::array::element& docView) { - KSATinstance::CLAUSE clause; + clause = KSATinstance::CLAUSE(); for(auto lit : static_cast(docView.get_array())) { clause.push_back(lit.get_int32()); } - - return clause; } } diff --git a/src/util/bson2ksatConverter.h b/src/util/bson2ksatConverter.h index 98d0522..4267358 100644 --- a/src/util/bson2ksatConverter.h +++ b/src/util/bson2ksatConverter.h @@ -16,23 +16,24 @@ namespace types { template -KSATinstance convert(const bsoncxx::document::view& docView) +void convert(KSATinstance& ksat, const bsoncxx::document::view& docView) { using CLAUSE = KSATinstance::CLAUSE; using CLAUSE_DOC = const bsoncxx::array::element&; - KSATinstance ksat; + ksat = KSATinstance(); bsoncxx::array::view clauses = docView["clauses"].get_array(); - for(auto clause : clauses) + KSATinstance::CLAUSE clause; + for(auto clauseDoc : clauses) { - ksat.addClause(convert(clause)); + convert<>(clause, clauseDoc); + + ksat.addClause(clause); } ksat.setId(docView["_id"].get_oid().value.to_string()); - - return ksat; } } diff --git a/src/util/bson2quboMtrx.h b/src/util/bson2quboMtrx.h new file mode 100644 index 0000000..8c57413 --- /dev/null +++ b/src/util/bson2quboMtrx.h @@ -0,0 +1,85 @@ +#ifndef BSON2QBUO_MTRX_H +#define BSON2QBUO_MTRX_H + +#include "bsoncxx/document/view.hpp" +#include "bsoncxx/array/view.hpp" +#include "bsoncxx/types.hpp" + +#include "util/convert.h" +#include "solver_cxx.h" + +#include +#include "bsoncxx/json.hpp" + +#include +#include + +#include + +namespace satlab +{ + +namespace types +{ + +template +void convert(qbscxx::QUBO& qubo, const bsoncxx::document::view& docView) +{ + using NODE = std::tuple; + using NODE_INDEX_DICT = std::map; + + //qubo = qbscxx::QUBO(); + + NODE_INDEX_DICT nodeIndexDict; + + NODE node1; + size_t nodeIndex = 0; + for(auto& entry : docView["qubo"].get_array().value) + { + for(auto& nodeView : entry[0].get_array().value) + { + node1 = NODE(nodeView[0].get_int32().value, + nodeView[1].get_int32().value); + + if(nodeIndexDict.find( node1 ) == nodeIndexDict.end()) + { + nodeIndexDict.emplace(node1, nodeIndex); + nodeIndex++; + } + } + } + + qubo.resize(nodeIndexDict.size()); + for(int i=0; i < nodeIndexDict.size(); i++) + { + qubo[i].resize(nodeIndexDict.size()); + } + + NODE node2; + for(auto& entry : docView["qubo"].get_array().value) + { + auto coupler = entry[0]; + auto node1doc = coupler[0]; + auto node2doc = coupler[1]; + + node1 = NODE(node1doc[0].get_int32().value, + node1doc[1].get_int32().value); + + node2 = NODE(node2doc[0].get_int32().value, + node2doc[1].get_int32().value); + + size_t nodeIndex1 = nodeIndexDict.at(node1); + size_t nodeIndex2 = nodeIndexDict.at(node2); + qbscxx::ENERGY_T energy = entry[1].get_double().value; + + qubo[nodeIndex1][nodeIndex2] = energy; + } + + nodeIndexDict.clear(); +} + +} + +} + +#endif // BSON2QBUO_MTRX_H diff --git a/src/util/bson_2_qubo_coupler.h b/src/util/bson_2_qubo_coupler.h new file mode 100644 index 0000000..0c09286 --- /dev/null +++ b/src/util/bson_2_qubo_coupler.h @@ -0,0 +1,43 @@ +#ifndef BSON_2_QUBO_COUPLER_H +#define BSON_2_QUBO_COUPLER_H + +#include "bsoncxx/document/view.hpp" +#include "bsoncxx/array/view.hpp" +#include "bsoncxx/types.hpp" + +#include "util/convert.h" + +#include +#include + +#include + +#include "util/wmis_qubo.h" + +namespace satlab +{ + +namespace types +{ + +template +void convert(wmis_qubo::COUPLER& coupler, const bsoncxx::array::view& docView) +{ + auto nodes = docView[0].get_array().value; + + wmis_qubo::NODE node1(nodes[0][0].get_int32().value, + nodes[0][1].get_int32().value); + + wmis_qubo::NODE node2(nodes[1][0].get_int32().value, + nodes[1][1].get_int32().value); + + qbscxx::ENERGY_T energy = docView[1].get_double().value; + + coupler = wmis_qubo::COUPLER(node1, node2, energy); +} + +} + +} + +#endif // BSON_2_QUBO_COUPLER_H diff --git a/src/util/bson_2_wmis_qubo.h b/src/util/bson_2_wmis_qubo.h new file mode 100644 index 0000000..f4b5747 --- /dev/null +++ b/src/util/bson_2_wmis_qubo.h @@ -0,0 +1,47 @@ +#ifndef BSON_2_WMIS_QUBO_H +#define BSON_2_WMIS_QUBO_H + +#include "bsoncxx/document/view.hpp" +#include "bsoncxx/array/view.hpp" +#include "bsoncxx/types.hpp" + +#include "util/convert.h" + +#include +#include "bsoncxx/json.hpp" + +#include +#include + +#include + +#include "util/wmis_qubo.h" +#include "util/bson_2_qubo_coupler.h" +namespace satlab +{ + +namespace types +{ + +template +void convert(wmis_qubo& qubo, const bsoncxx::document::view& docView) +{ + qubo = wmis_qubo(); + + for(auto& entry : docView["qubo"].get_array().value) + { + + wmis_qubo::COUPLER coupler; + + convert(coupler, entry.get_array().value); + + qubo.add(coupler); + } +} + + +} + +} + +#endif // BSON_2_WMIS_QUBO_H diff --git a/src/util/conversions.h b/src/util/conversions.h index faf6ec6..b494f07 100644 --- a/src/util/conversions.h +++ b/src/util/conversions.h @@ -7,5 +7,7 @@ #include "util/minisatStats2bson.h" #include "util/minisatResult2bson.h" #include "util/ksatModel2bson.h" +#include "util/bson2quboMtrx.h" +#include "util/bson_2_wmis_qubo.h" #endif //CONVERSIONS_H diff --git a/src/util/convert.h b/src/util/convert.h index 8a65c16..7a37598 100644 --- a/src/util/convert.h +++ b/src/util/convert.h @@ -7,11 +7,11 @@ namespace satlab namespace types { -template -TARGET_T convert(const SOURCE_T& source); +// template +// TARGET_T convert(const SOURCE_T& source); template -void convertRef(TARGET_T&, const SOURCE_T& source); +void convert(TARGET_T&, const SOURCE_T& source); } } diff --git a/src/util/ksatClause2ministaClause.h b/src/util/ksatClause2ministaClause.h index ec1e85e..4d41fc3 100644 --- a/src/util/ksatClause2ministaClause.h +++ b/src/util/ksatClause2ministaClause.h @@ -14,8 +14,8 @@ namespace types { template, typename = KSATinstance::CLAUSE> -void convertRef(Minisat::vec& clauseVec, - const KSATinstance::CLAUSE& clause) +void convert(Minisat::vec& clauseVec, + const KSATinstance::CLAUSE& clause) { clauseVec.clear(); diff --git a/src/util/ksatModel2bson.h b/src/util/ksatModel2bson.h index 136860b..6464908 100644 --- a/src/util/ksatModel2bson.h +++ b/src/util/ksatModel2bson.h @@ -11,16 +11,14 @@ namespace satlab { template -bsoncxx::builder::stream::array convert(const KSATinstance::MODEL& model) +void convert(bsoncxx::builder::stream::array& builder, const KSATinstance::MODEL& model) { - bsoncxx::builder::stream::array builder; + builder = bsoncxx::builder::stream::array(); for(auto& lit : model) { builder << lit; } - - return builder; } } diff --git a/src/util/minisatResult2bson.h b/src/util/minisatResult2bson.h index 2c8fb67..99d5152 100644 --- a/src/util/minisatResult2bson.h +++ b/src/util/minisatResult2bson.h @@ -13,19 +13,23 @@ namespace satlab { template -bsoncxx::builder::stream::document convert(const MinisatResult& result) +void convert(bsoncxx::builder::stream::document& builder, const MinisatResult& result) { using ARRAY_BUILDER = bsoncxx::builder::stream::array; using DOCUMENT_BUILDER = bsoncxx::builder::stream::document; - DOCUMENT_BUILDER builder; + builder = DOCUMENT_BUILDER(); + + ARRAY_BUILDER model; + DOCUMENT_BUILDER stats; + + convert<>(model, result.getModel()); + convert<>(stats, result.getStats()); builder << "satisfiable" << result.getSatisfiable() - << "model" << convert(result.getModel()).view() - << "stats" << convert(result.getStats()).view() + << "model" << model.view() + << "stats" << stats.view() << "instance" << bsoncxx::oid(result.getInstanceId()); - - return builder; } diff --git a/src/util/minisatStats2bson.h b/src/util/minisatStats2bson.h index 45efeff..5de31f3 100644 --- a/src/util/minisatStats2bson.h +++ b/src/util/minisatStats2bson.h @@ -11,9 +11,9 @@ namespace satlab { template -bsoncxx::builder::stream::document convert(const MinisatStats& stats) +void convert(bsoncxx::builder::stream::document& builder, const MinisatStats& stats) { - bsoncxx::builder::stream::document builder; + builder = bsoncxx::builder::stream::document(); builder << "solves" << static_cast(stats.getSolves()) << "starts" << static_cast(stats.getStarts()) @@ -26,8 +26,6 @@ bsoncxx::builder::stream::document convert(const MinisatStats& stats) << "learnts_literals" << static_cast(stats.getLearntsLiterals()) << "max_literals" << static_cast(stats.getMaxLiterals()) << "tot_literals" << static_cast(stats.getTotLiterals()); - - return builder; } diff --git a/src/util/minisatsolver.cpp b/src/util/minisatsolver.cpp index 05b4204..51e7048 100644 --- a/src/util/minisatsolver.cpp +++ b/src/util/minisatsolver.cpp @@ -38,7 +38,7 @@ void MinisatSolver::addClause(const KSATinstance::CLAUSE& clause) { Minisat::vec clauseVec; - types::convertRef<>(clauseVec, clause); + types::convert<>(clauseVec, clause); addMissingVars(clauseVec); diff --git a/src/util/mongodbexperimentscope.cpp b/src/util/mongodbexperimentscope.cpp index 34190fc..f59c752 100644 --- a/src/util/mongodbexperimentscope.cpp +++ b/src/util/mongodbexperimentscope.cpp @@ -35,7 +35,7 @@ void MongoDBExperimentScope::InstanceIncrementer::updateInstance() return; } - instance = KSATinstance(types::convert(*cursorIt)); + types::convert(instance, *cursorIt); instanceIsUpdated = true; } diff --git a/src/util/wmis_qubo.cpp b/src/util/wmis_qubo.cpp new file mode 100644 index 0000000..ad1dc35 --- /dev/null +++ b/src/util/wmis_qubo.cpp @@ -0,0 +1,79 @@ +#include "util/wmis_qubo.h" +#include + +namespace satlab +{ + +void wmis_qubo::add(const COUPLER& coupler) +{ + const NODE& node1 = std::get<0>(coupler); + const NODE& node2 = std::get<1>(coupler); + qbscxx::ENERGY_T energy = std::get<2>(coupler); + + size_t index_node1 = add(node1); + size_t index_node2 = add(node2); + + fit_qubo(std::max(index_node1, index_node2)); + + qubo[index_node1][index_node2] = energy; + qubo[index_node2][index_node1] = energy; +} + +size_t wmis_qubo::add(const NODE& node) +{ + size_t index; + + if(node_to_index.find(node) == node_to_index.end()) + { + index_to_node.push_back(node); + index = index_to_node.size() - 1; + + node_to_index.emplace(node, index); + } + else + { + index = index_of(node); + } + + return index; +} + +void wmis_qubo::fit_qubo(const size_t node_index) +{ + size_t required_size = node_index + 1; + + if(qubo.size() >= required_size) + { + return; + } + + size_t old_size = qubo.size(); + + qubo.resize(required_size); + for(size_t i=0; i < required_size; i++) + { + qubo[i].resize(required_size); + + std::fill(qubo[i].begin() + old_size, qubo[i].end(), 0.0); + } +} + + +size_t wmis_qubo::index_of(const NODE& node) const +{ + return node_to_index.at(node); +} + +const satlab::wmis_qubo::NODE& wmis_qubo::node_at(size_t index) const +{ + return index_to_node.at(index); +} + +const qbscxx::QUBO& wmis_qubo::get_qubo() const +{ + return qubo; +} + + + +} diff --git a/src/util/wmis_qubo.h b/src/util/wmis_qubo.h new file mode 100644 index 0000000..948860c --- /dev/null +++ b/src/util/wmis_qubo.h @@ -0,0 +1,52 @@ +#ifndef WMIS_QUBO_H +#define WMIS_QUBO_H + +#include "types.h" +#include +#include +#include + +namespace satlab +{ + +/** + * @todo write docs + */ +class wmis_qubo +{ +public: + using NODE = std::tuple; + using COUPLER = std::tuple; + + using INDEX_TO_NODE = std::vector; + using NODE_TO_INDEX = std::map; + + wmis_qubo() = default; + virtual ~wmis_qubo() = default; + + wmis_qubo(const wmis_qubo& other) = default; + wmis_qubo(wmis_qubo&& other) = default; + + wmis_qubo& operator=(const wmis_qubo& other) = default; + wmis_qubo& operator=(wmis_qubo&& other) = default; + + + void add(const COUPLER& coupler); + + const NODE& node_at(size_t index) const; + size_t index_of(const NODE& node) const; + + const qbscxx::QUBO& get_qubo() const; +private: + size_t add(const NODE& node); + void fit_qubo(const size_t node_index); + + qbscxx::QUBO qubo; + INDEX_TO_NODE index_to_node; + NODE_TO_INDEX node_to_index; +}; + +} + +#endif // WMIS_QUBO_H + diff --git a/testRandomSat.py b/testRandomSat.py index 10e78c8..9187b47 100755 --- a/testRandomSat.py +++ b/testRandomSat.py @@ -1,23 +1,59 @@ #!/usr/bin/env python3 from util import randomSAT as rdSAT +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np -kSATInstance = rdSAT.generateRandomKSAT(5, 4, 3) +def test1(): + kSATInstance = rdSAT.generateRandomKSAT(5, 4, 3) -print(kSATInstance.toString()) + print(kSATInstance.toString()) -print("conflicts:") + print("conflicts:") -for conflict in kSATInstance.getConflicts(): - conflictVerified = False + for conflict in kSATInstance.getConflicts(): + conflictVerified = False + + clause1 = kSATInstance.getClause(conflict[0][0]) + clause2 = kSATInstance.getClause(conflict[1][0]) + + for binding in clause2: + if binding == conflict[0][1] * -1: + conflictVerified = True + + print(conflict[0], conflict[1], conflictVerified) - clause1 = kSATInstance.getClause(conflict[0][0]) - clause2 = kSATInstance.getClause(conflict[1][0]) +def test2(): + data = {} - for binding in clause2: - if binding == conflict[0][1] * -1: - conflictVerified = True + data["clause"] = [] + data["num"] = [] + data["labels"] = [] + + for i in range(10000): + sat = rdSAT.generateRandomKSAT(7, 6, 3) + + for ci in range(sat.getNumberOfClauses()): + clause = sat.getClause(ci) + clause = list(np.sort(clause)) - print(conflict[0], conflict[1], conflictVerified) + if clause in data["clause"]: + clauseIndex = data["clause"].index(clause) + data["num"][clauseIndex] += 1 + else: + data["clause"].append(clause) + data["labels"].append("[{}, {}, {}]".format(clause[0], clause[1], clause[2])) + data["num"].append(1) + + + print("done ({}) unique clauses".format(len(data["clause"]))) + + sns.set() + + sns.barplot(x=data["labels"], y=data["num"]) + + plt.show() +test2() diff --git a/testSAT2QUBO.py b/testSAT2QUBO.py index 2637da0..a63c2e6 100755 --- a/testSAT2QUBO.py +++ b/testSAT2QUBO.py @@ -3,11 +3,401 @@ from util import SAT2QUBO as s2q from util import randomSAT as rs -ksatInstance = rs.generateRandomKSAT(2, 4, 3) +import networkx as nx +import dwave_networkx as dnx +import minorminer +from dwave_qbsolv import QBSolv -qubo = s2q.WMISdictQUBO(ksatInstance) +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np +import re -print(ksatInstance.toString()) -for label in qubo: - print(label, qubo[label]) +def frange(start, stop, steps): + while start < stop: + yield start + start += steps + +def test_kv_range(): + + k = 75 + + data = { + "p_node_counts" : [], + "wmis_node_counts" : [], + + "p_conn_counts" : [], + "wmis_conn_counts" : [], + + "a_arr" : [], + + "k_arr" : [] + } + + target = dnx.chimera_graph(25, 25, 4) + + print(target.number_of_nodes()) + + for r in range(2): + #for k in range(50, 5001, 50): + for a in frange(3.5, 5.5, 0.1): + #v = int(k/4) + #a = k/v + + v = int(k/a) + + print("k={} v={} k/v={}".format(k, v, k/v)) + + ksatInstance = rs.generateRandomKSAT(k, v, 3) + + p_qubo = s2q.primitiveQUBO(ksatInstance) + + wmis_qubo = s2q.WMISdictQUBO(ksatInstance) + + qg = nx.Graph() + + for coupler, energy in wmis_qubo.items(): + if coupler[0] != coupler[1]: + qg.add_edge(coupler[0], coupler[1], weight=energy) + + + ig = nx.Graph() + for coupler, energy in p_qubo.items(): + if coupler[0] != coupler[1]: + ig.add_edge(coupler[0], coupler[1], weight=energy) + + qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True, threads=8) + print("wmis emb. found: {}".format(qemb[1])) + iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True, threads=8) + print("primitive emb. found: {}".format(iemb[1])) + + if qemb[1] == 0 or iemb[1] == 0: + print() + continue + + p_node_count = 0; + p_conn_count = 0; + + used_nodes = [] + for var, chain in iemb[0].items(): + used_nodes.extend(chain) + + p_node_count = len(np.unique(used_nodes)) + + wmis_node_count = 0; + wmis_conn_count = 0; + + used_nodes = [] + for var, chain in qemb[0].items(): + used_nodes.extend(chain) + + wmis_node_count = len(np.unique(used_nodes)) + + + #print("p_qubo: nodes={} connections={}".format(p_node_count, p_conn_count)) + + #print("wmis_qubo: nodes={} connections={}".format(wmis_node_count, wmis_conn_count)) + + print("p_qubo nodes= {}".format(p_node_count)); + print("wwmis qubo nodes= {}".format(wmis_node_count)); + + print("nodes= {}".format(p_node_count / wmis_node_count)); + #print("conns= {}".format(p_conn_count / wmis_conn_count)); + + + data["p_node_counts"].append(p_node_count) + data["wmis_node_counts"].append(wmis_node_count) + + data["p_conn_counts"].append(p_conn_count) + data["wmis_conn_counts"].append(wmis_conn_count) + + data["a_arr"].append(k/v) + data["k_arr"].append(k) + + print() + + sns.set() + + ax = sns.scatterplot(x="a_arr", y="p_node_counts", data=data, label="p_qubo") + ax.set(xlabel='k/v', ylabel='used verticies after embedding') + ax = sns.scatterplot(x="a_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo") + plt.show() + +def test_k_range(): + + k = 75 + + data = { + "p_node_counts" : [], + "wmis_node_counts" : [], + + "p_conn_counts" : [], + "wmis_conn_counts" : [], + + "a_arr" : [], + + "k_arr" : [] + } + + target = dnx.chimera_graph(25, 25, 4) + + print(target.number_of_nodes()) + + for r in range(2): + for k in range(15, 76, 1): + v = int(k/4) + + + print("k={} v={} k/v={}".format(k, v, k/v)) + + ksatInstance = rs.generateRandomKSAT(k, v, 3) + + p_qubo = s2q.primitiveQUBO(ksatInstance) + + wmis_qubo = s2q.WMISdictQUBO(ksatInstance) + + qg = nx.Graph() + + for coupler, energy in wmis_qubo.items(): + if coupler[0] != coupler[1]: + qg.add_edge(coupler[0], coupler[1], weight=energy) + + + ig = nx.Graph() + for coupler, energy in p_qubo.items(): + if coupler[0] != coupler[1]: + ig.add_edge(coupler[0], coupler[1], weight=energy) + + qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True, threads=8) + print("wmis emb. found: {}".format(qemb[1])) + iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True, threads=8) + print("primitive emb. found: {}".format(iemb[1])) + + if qemb[1] == 0 or iemb[1] == 0: + print() + continue + + p_node_count = 0; + p_conn_count = 0; + + used_nodes = [] + for var, chain in iemb[0].items(): + used_nodes.extend(chain) + + p_node_count = len(np.unique(used_nodes)) + + wmis_node_count = 0; + wmis_conn_count = 0; + + used_nodes = [] + for var, chain in qemb[0].items(): + used_nodes.extend(chain) + + wmis_node_count = len(np.unique(used_nodes)) + + + #print("p_qubo: nodes={} connections={}".format(p_node_count, p_conn_count)) + + #print("wmis_qubo: nodes={} connections={}".format(wmis_node_count, wmis_conn_count)) + + print("p_qubo nodes= {}".format(p_node_count)); + print("wwmis qubo nodes= {}".format(wmis_node_count)); + + print("nodes= {}".format(p_node_count / wmis_node_count)); + #print("conns= {}".format(p_conn_count / wmis_conn_count)); + + + data["p_node_counts"].append(p_node_count) + data["wmis_node_counts"].append(wmis_node_count) + + data["p_conn_counts"].append(p_conn_count) + data["wmis_conn_counts"].append(wmis_conn_count) + + data["a_arr"].append(k/v) + data["k_arr"].append(k) + + print() + + sns.set() + + ax = sns.scatterplot(x="k_arr", y="p_node_counts", data=data, label="p_qubo") + ax.set(xlabel='k', + ylabel='used verticies after embedding') + ax = sns.scatterplot(x="k_arr", y="wmis_node_counts", data=data, ax=ax, label="wmis_qubo") + plt.show() + +def medianChainLength(emb): + chl = [] + + for chain in emb.values(): + chl.append(len(chain)) + + return np.median(chl) + + +def test2(): + sat = rs.generateRandomKSAT(15, 4, 3) + + print(sat.toString()) + + qubo = s2q.WMISdictQUBO(sat) + ising = s2q.primitiveQUBO(sat) + + qg = nx.Graph() + + for coupler, energy in qubo.items(): + if coupler[0] != coupler[1]: + qg.add_edge(coupler[0], coupler[1], weight=energy) + + + ig = nx.Graph() + for coupler, energy in ising.items(): + if coupler[0] != coupler[1]: + ig.add_edge(coupler[0], coupler[1], weight=energy) + + #plt.ion() + + print(qg.number_of_nodes(), qg.number_of_edges()) + print(ig.number_of_nodes(), ig.number_of_edges()) + + target = dnx.chimera_graph(9, 9, 4) + #nx.draw_shell(qg, with_labels=True, node_size=50) + #nx.draw_shell(ig, with_labels=True, node_size=50) + + eg = ig + + emb = minorminer.find_embedding(eg.edges(), target.edges(), return_overlap=True, + threads=8) + + print("median chain length = {}".format(medianChainLength(emb[0]))) + + print(emb[1]) + + dnx.draw_chimera_embedding(G=target, emb=emb[0], embedded_graph=eg, show_labels=True) + + plt.show() + +def test3(): + sat = rs.generateRandomKSAT(15, 4, 3) + + print(sat.toString()) + + ising = s2q.primitiveQUBO(sat) + + h = {} + J = {} + + for coupler, energy in ising.items(): + if coupler[0] == coupler[1]: + h[coupler[0]] = energy + else: + J[coupler] = energy + + res = QBSolv().sample_ising(h, J, find_max=False) + + sample = list(res.samples())[0] + + extracted = {} + + r = re.compile("c\d+_l-?\d*") + + for label, assignment in sample.items(): + if r.fullmatch(label): + + extracted[tuple(re.split(r"\_l", label[1:]))] = assignment + + model = [True for i in range(len(extracted))] + + assignments = {} + + for label, assignment in extracted.items(): + clause = int(label[0]) + lit = int(label[1]) + var = abs(lit) + + if lit < 0: + assignment *= -1 + + if var in assignments: + assignments[var].append(assignment) + else: + assignments[var] = [assignment] + + + conflicts = False + for var, a in assignments.items(): + if abs(np.sum(a)) != len(a): + conflicts = True + print("conflicts - no solution found") + print(var, np.sort(a)) + + if conflicts: + return + + model = [True for i in range(sat.getNumberOfVariables())] + + for var, assignment in assignments.items(): + model[var - 1] = True if assignment[0] > 0 else False + + print(model, sat.checkAssignment(model)) + + +def test4(): + sat = rs.generateRandomKSAT(50, 13, 3) + + print(sat.toString()) + + qubo = s2q.WMISdictQUBO(sat) + ising = s2q.primitiveQUBO(sat) + + qg = nx.Graph() + + for coupler, energy in qubo.items(): + if coupler[0] != coupler[1]: + qg.add_edge(coupler[0], coupler[1], weight=energy) + + + ig = nx.Graph() + for coupler, energy in ising.items(): + if coupler[0] != coupler[1]: + ig.add_edge(coupler[0], coupler[1], weight=energy) + + #plt.ion() + + print(qg.number_of_nodes(), qg.number_of_edges()) + print(ig.number_of_nodes(), ig.number_of_edges()) + + target = dnx.chimera_graph(12, 12, 4) + #nx.draw_shell(qg, with_labels=True, node_size=50) + #nx.draw_shell(ig, with_labels=True, node_size=50) + + print() + print("wmis:") + qemb = minorminer.find_embedding(qg.edges(), target.edges(), return_overlap=True) + print(qemb[1]) + print("median chain length = {}".format(medianChainLength(qemb[0]))) + + used_nodes = [] + for var, chain in qemb[0].items(): + used_nodes.extend(chain) + + used_nodes = np.unique(used_nodes) + print("used nodes (embedding) = {}".format(len(used_nodes))) + + + print() + print("primitves:") + iemb = minorminer.find_embedding(ig.edges(), target.edges(), return_overlap=True) + print(iemb[1]) + print("median chain length = {}".format(medianChainLength(iemb[0]))) + + used_nodes = [] + for var, chain in iemb[0].items(): + used_nodes.extend(chain) + + used_nodes = np.unique(used_nodes) + print("used nodes (embedding) = {}".format(len(used_nodes))) + + +test_k_range() diff --git a/test_alpha_generation.py b/test_alpha_generation.py new file mode 100755 index 0000000..4eb5558 --- /dev/null +++ b/test_alpha_generation.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np + +import random + +from util.script import frange + +from collections import Counter + + +def main(): + #alpha_range = frange(0.5, 10, 0.1) + #k = 50 + + #alphas = _get_bins(k, alpha_range) + + + alphas = [] + + k = 25 + + for v in range(5, 50): + alphas.append(round(k/v, 2)) + + + num_bins =len(np.unique(alphas)) + + print(num_bins) + + sns.set() + plt.hist(alphas, bins=num_bins) + plt.show() + +def _get_bins(k, alpha_range): + bins = {} + + alphas = [] + + for a in alpha_range: + v = int(k/a) + real_alpha = (k / v) + + alphas.append(round(real_alpha, 2)) + + return alphas + +if __name__ == "__main__": + main() diff --git a/test_sat_to_qubo_workflow.py b/test_sat_to_qubo_workflow.py new file mode 100755 index 0000000..972e4b9 --- /dev/null +++ b/test_sat_to_qubo_workflow.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 + +from util.kSAT import kSAT +import util.randomSAT as rand_sat +import util.SAT2QUBO as SAT2QUBO +import util.script as script +import util.queries as queries + +from dwave.system.composites import FixedEmbeddingComposite +import dimod +from neal import SimulatedAnnealingSampler +import minorminer +import networkx as nx +import dwave_networkx as dnx +import dwave.embedding + +from dwave_qbsolv import QBSolv + +import numpy as np +import random + +from tqdm import tqdm + +def main(): + #__wmis() + #__pqubo() + __wmis3() + + +def __qubo_to_nx_graph(qubo): + graph = nx.Graph() + + for coupler, energy in qubo.items(): + if coupler[0] != coupler[1]: + graph.add_edge(coupler[0], coupler[1], weight=energy) + + return graph + +def __wmis2(): + db = script.connect_to_instance_pool("dbc") + target_graph = dnx.chimera_graph(16, 16, 4) + target_graph_id = queries.get_id_of_solver_graph(db["solver_graphs"], + nx.node_link_data(target_graph)) + instance_id = "5c9ccb998c6fe61926458351" + qubo, wmis_id = queries.load_WMIS_qubo_of_instance(db["wmis_qubos"], instance_id) + + emb = queries.load_embedding(db["embeddings"], wmis_id, target_graph_id) + + chimera_sampler = dimod.StructureComposite(SimulatedAnnealingSampler(), + target_graph.nodes(), + target_graph.edges()) + + sampler = FixedEmbeddingComposite(chimera_sampler, emb) + + res = sampler.sample_qubo(__negate_qubo(qubo)) + + print(res.first) + +def __wmis3(): + db = script.connect_to_instance_pool("dbc") + target_graph = dnx.chimera_graph(16, 16, 4) + target_graph_id = queries.get_id_of_solver_graph(db["solver_graphs"], + nx.node_link_data(target_graph)) + + solver_input_query = queries.WMIS_solver_input_scope_query(db) + solver_input_query.query("c50_v[5, 50]_1", target_graph_id) + + base_sampler = SimulatedAnnealingSampler() + chimera_sampler = dimod.StructureComposite(base_sampler, + target_graph.nodes(), + target_graph.edges()) + + for solver_input in tqdm(solver_input_query): + sampler = FixedEmbeddingComposite(chimera_sampler, solver_input["embeddings"][0]) + + res = sampler.sample_qubo(__negate_qubo(solver_input["qubo"])) + + script.save_simulated_annealing_result(db["wmis_siman_results"], + res, + solver_input, + 0) + + +def __wmis(): + sat = rand_sat.generateRandomKSAT(25, 6, 3) + qubo = __negate_qubo(SAT2QUBO.WMISdictQUBO(sat)) + #qubo = SAT2QUBO.WMISdictQUBO(sat) + nx_qubo = __qubo_to_nx_graph(qubo) + + target_graph = dnx.chimera_graph(16, 16, 4) + + emb = minorminer.find_embedding(nx_qubo.edges(), + target_graph.edges(), + return_overlap=True) + + if emb[1] != 1: + print("no embedding found") + return + + print(emb[0]) + + chimera_sampler = dimod.StructureComposite(SimulatedAnnealingSampler(), + target_graph.nodes(), + target_graph.edges()) + + + + sampler = FixedEmbeddingComposite(chimera_sampler, emb[0]) + + + res = sampler.sample_qubo(qubo) + #res = SimulatedAnnealingSampler().sample_qubo(qubo) + + #dwave.embedding.chain_breaks.majority_vote(res, emb[0]) + + first = res.first + + print("chain_break_fraction={}".format(first.chain_break_fraction)) + for lit, spin in first.sample.items(): + print(lit, spin) + print("true count: {}".format(np.count_nonzero(list(first.sample.values())))) + + assignments = {} + + for coupler, energy in first.sample.items(): + + var = abs(coupler[1]) + + if var not in assignments: + assignments[var] = {"all": []} + + if energy == 1: + assignments[var]["all"].append(1 if coupler[1] > 0 else 0) + + __majority_vote(assignments) + + #for var, a in assignments.items(): + ##print(var, np.sort(a["all"]), __majority_percentage(a["all"])) + #print(var, a) + final = __extract_assignment(assignments) + print(final) + print("satisfies sat: {}".format(sat.checkAssignment(final))) + +def __optimize_assignment(sat, assignment, consistencies): + rnd = random.Random() + + max_steps = 4000 + steps = 0 + + while not sat.checkAssignment(assignment) and steps < max_steps: + steps += 1 + + for i in range(len(assignment)): + if 0.9 * rnd.random() > consistencies[i]: + assignment[i] = (1 + assignment[i]) % 2 + consistencies[i] = 1 - consistencies[i] + + print("steps: {}".format(steps)) + + return assignment + +def __random_assignment(number_of_variables): + rnd = random.Random() + assignment = [rnd.choice([0, 1]) for i in range(number_of_variables)] + consistencies = [0.5 for i in range(number_of_variables)] + + return assignment, consistencies + + +def __extract_assignment(assignments): + assignment = [0 for i in range(len(assignments))] + + for var, a in assignments.items(): + assignment[var - 1] = a["major"] + + return assignment + +def __extract_consistencies(assignments) : + consistencies = [0.0 for i in range(len(assignments))] + + for var, a in assignments.items(): + consistencies[var - 1] = a["consistency"] + + return consistencies + +def __majority_vote(assignments): + for var, a in assignments.items(): + assignments[var]["major"] = 1 if __true_percentage(a["all"]) >= 0.5 else 0 + assignments[var]["consistency"] = __majority_percentage(a["all"]) + +def __true_percentage(a): + if len(a) == 0: + return 0 + + return np.count_nonzero(a) / len(a) + +def __majority_percentage(a): + true_perc = __true_percentage(a) + + return true_perc if true_perc >= 0.5 else 1 - true_perc + +def __pqubo(): + sat = rand_sat.generateRandomKSAT(25, 6, 3) + ising = SAT2QUBO.primitiveQUBO(sat) + nx_qubo = __qubo_to_nx_graph(ising) + + target_graph = dnx.chimera_graph(16, 16, 4) + + emb = minorminer.find_embedding(nx_qubo.edges(), + target_graph.edges(), + return_overlap=True) + + if emb[1] != 1: + print("no embedding found") + return + + chimera_sampler = dimod.StructureComposite(SimulatedAnnealingSampler(), + target_graph.nodes(), + target_graph.edges()) + + sampler = FixedEmbeddingComposite(chimera_sampler, emb[0]) + + h, J = __split_ising(ising) + + res = sampler.sample_ising(h, J) + #res = QBSolv().sample_qubo(qubo, find_max=True) + + print(res.first) + +def __split_ising(ising): + h = {} + J = {} + + for coupler, energy in ising.items(): + if coupler[0] == coupler[1]: + h[coupler[0]] = energy + else: + J[coupler] = energy + + return h, J + + +def __negate_qubo(qubo): + negative_qubo = {} + + for coupler, energy in qubo.items(): + negative_qubo[coupler] = -1 * energy + + return negative_qubo + +if __name__ == "__main__": + main() diff --git a/util/SAT2QUBO.py b/util/SAT2QUBO.py index 79ff267..ff8c240 100644 --- a/util/SAT2QUBO.py +++ b/util/SAT2QUBO.py @@ -11,7 +11,7 @@ __EDGE_WEIGHT__ = -2 def WMISdictQUBO(kSATInstance): quboInstance = {} - for clauseIndex in tqdm(range(kSATInstance.getNumberOfClauses())): + for clauseIndex in range(kSATInstance.getNumberOfClauses()): clause = kSATInstance.getClause(clauseIndex) # build triangles @@ -31,6 +31,76 @@ def WMISdictQUBO(kSATInstance): quboInstance[(conflict[0], conflict[1])] = __EDGE_WEIGHT__ return quboInstance + +# only 3sat +def primitiveQUBO(sat): + quboInstance = {} + + chains = {} + + + for clauseIndex in range(sat.getNumberOfClauses()): + clause = sat.getClause(clauseIndex); + + #build clause primitives + + lit1 = "c{}_l{}".format(clauseIndex, clause[0]) + lit2 = "c{}_l{}".format(clauseIndex, clause[1]) + lit3 = "c{}_l{}".format(clauseIndex, clause[2]) + aux1 = "a{}_{}".format(clauseIndex, 1) + aux2 = "a{}_{}".format(clauseIndex, 2) + aux3 = "a{}_{}".format(clauseIndex, 3) + aux4 = "a{}_{}".format(clauseIndex, 4) + + quboInstance[(lit1, lit1)] = 1; + quboInstance[(lit2, lit2)] = 1; + quboInstance[(lit3, lit3)] = 1; + quboInstance[(aux1, aux1)] = -2; + quboInstance[(aux2, aux2)] = 1; + quboInstance[(aux3, aux3)] = -2; + quboInstance[(aux4, aux4)] = -2; + + quboInstance[(lit1, lit2)] = 1; + quboInstance[(lit1, aux1)] = -2; + quboInstance[(lit2, aux1)] = -2; + quboInstance[(aux1, aux2)] = -2; + quboInstance[(aux2, aux3)] = -2; + quboInstance[(aux2, lit3)] = 1; + quboInstance[(lit3, aux3)] = -2; + quboInstance[(aux3, aux4)] = -2; + + if clause[0] in chains: + chains[clause[0]].append(lit1) + else: + chains[clause[0]] = [lit1] + + if clause[1] in chains: + chains[clause[1]].append(lit2) + else: + chains[clause[1]] = [lit2] + + if clause[2] in chains: + chains[clause[2]].append(lit3) + else: + chains[clause[2]] = [lit3] + + #build chains + longestChain = 0; + for lit, nodes in chains.items(): + if len(nodes) > longestChain: + longestChain = len(nodes) + + if lit > 0 and -1 * lit in chains: + quboInstance[(chains[lit][0], chains[-1*lit][0])] = 2 + + print("longest chain = {}".format(longestChain)) + + for nodes in chains.values(): + while len(nodes) > 1: + quboInstance[(nodes[0], nodes[1])] = -2; + nodes.pop(0) + + return quboInstance class QuboWriter: def __init__(self, qubo): diff --git a/util/graph.py b/util/graph.py new file mode 100644 index 0000000..6bd33ab --- /dev/null +++ b/util/graph.py @@ -0,0 +1,18 @@ +import networkx as nx + +def qubo_to_nx_graph(qubo): + graph = nx.Graph() + + for coupler, energy in qubo.items(): + if coupler[0] != coupler[1]: + graph.add_edge(coupler[0], coupler[1], weight=energy) + + return graph + +def negate_qubo(qubo): + negative_qubo = {} + + for coupler, energy in qubo.items(): + negative_qubo[coupler] = -1 * energy + + return negative_qubo diff --git a/util/kSAT.py b/util/kSAT.py index a8faaea..ae2f497 100644 --- a/util/kSAT.py +++ b/util/kSAT.py @@ -154,8 +154,16 @@ class kSAT: def writeJSONLike(self): jsonLike = {} - jsonLike["clauses"] = self.__clauses - + jsonLike["clauses"] = [] + + for clause in self.__clauses: + tmpClause = [] + + for literal in clause: + tmpClause.append(int(literal)) + + jsonLike["clauses"].append(tmpClause) + return jsonLike def readJSONLike(self, jsonLike): diff --git a/util/queries.py b/util/queries.py new file mode 100644 index 0000000..4e4fa75 --- /dev/null +++ b/util/queries.py @@ -0,0 +1,264 @@ +from .kSAT import kSAT +import bson + +class Instance_scope_query: + + def __init__(self, database): + self.__database = database + self.__query = None + + def query(self, scope): + self.__query = self.__database["experiment_scopes"].aggregate([ + { + "$match": {"_id": scope} + }, + { + "$unwind": "$instances" + }, + { + "$lookup": + { + "from": "instances", + "localField": "instances", + "foreignField": "_id", + "as": "instance" + } + }, + { + "$unwind": "$instance" + }, + { + "$replaceRoot": {"newRoot": "$instance"} + } + ]) + + def __iter__(self): + return self + + def __next__(self): + document = self.__query.next() + + return self.__document_to_sat(document) + + def __document_to_sat(self, document): + sat = kSAT() + + for clause in document["clauses"]: + sat.addClause(clause); + + return sat, document["_id"] + +class WMIS_scope_query_raw: + + def __init__(self, database): + self.__database = database + self.__query = None + + def query(self, scope): + self.__query = self.__database["experiment_scopes"].aggregate([ + { + "$match": {"_id": scope} + }, + { + "$unwind": "$instances" + }, + { + "$lookup": + { + "from": "wmis_qubos", + "localField": "instances", + "foreignField": "instance", + "as": "qubo" + } + }, + { + "$unwind": "$qubo" + }, + { + "$replaceRoot": {"newRoot": "$qubo"} + } + ]) + + def __iter__(self): + return self + + def __next__(self): + return self.__query.next() + +class WMIS_scope_query (WMIS_scope_query_raw): + + def __next__(self): + doc = super(WMIS_scope_query, self).__next__() + + + return read_raw_qubo(doc["qubo"]), doc["_id"] + +class WMIS_solver_input_scope_query_raw: + + def __init__(self, database): + self.__database = database + self.__query = None + + def query(self, scope, solver_graph_id): + self.__query = self.__database["experiment_scopes"].aggregate([ + { + "$match": {"_id": scope} + }, + { + "$unwind": "$instances" + }, + { + "$project": {"instance_id": "$instances"} + }, + { + "$lookup": + { + "from": "wmis_qubos", + "localField": "instance_id", + "foreignField": "instance", + "as": "wmis_qubo" + } + }, + { + "$unwind": "$wmis_qubo" + }, + { + "$lookup": + { + "from": "embeddings", + "let": + { + "qubo_id": "$wmis_qubo._id", + "solver_graph_id": bson.ObjectId(solver_graph_id) + }, + "pipeline": + [ + { + "$match": + { + "$expr": + { + "$and": + [ + {"$eq": ["$qubo", "$$qubo_id"]}, + {"$eq": ["$solver_graph", "$$solver_graph_id"]} + ] + } + } + }, + { + "$project": { "list": "$embeddings" } + } + ], + "as": "embeddings" + } + }, + { + "$match": {"embeddings": {"$exists": True, "$not": {"$size": 0}}} + }, + { + "$unwind": "$embeddings" + }, + { + "$project": + { + "_id": False, + "instance_id": True, + "wmis_qubo": True, + "embeddings": True + } + } + ]) + + def __iter__(self): + return self + + def __next__(self): + return self.__query.next() + +class WMIS_solver_input_scope_query (WMIS_solver_input_scope_query_raw): + + def __next__(self): + doc = super(WMIS_solver_input_scope_query, self).__next__() + + data = {} + + data["instance_id"] = doc["instance_id"] + + data["qubo_id"] = doc["wmis_qubo"]["_id"] + data["qubo"] = read_raw_qubo(doc["wmis_qubo"]["qubo"]) + + data["embeddings_id"] = doc["embeddings"]["_id"] + + data["embeddings"] = [] + for raw_emb in doc["embeddings"]["list"]: + data["embeddings"].append(read_raw_embedding(raw_emb)) + + return data + +def load_embedding(collection, qubo_id, solver_graph_id): + doc = collection.find_one( + { + "qubo": bson.ObjectId(qubo_id), + "solver_graph": bson.ObjectId(solver_graph_id) + } + ) + + if doc == None: + return None + + if doc["embeddings"] == None: + return None + + if len(doc["embeddings"]) == 0: + return None + + return read_raw_embedding(doc["embeddings"][0]) + +def get_id_of_solver_graph(collection, nx_graph_data): + doc = collection.find_one({"data": nx_graph_data}) + + if doc == None: + return None + + return doc["_id"] + +def load_WMIS_qubo_of_instance(collection, instance_id): + doc = load_WMIS_qubo_of_instance_raw(collection, instance_id) + + if doc == None: + return None + + return read_raw_qubo(doc["qubo"]), doc["_id"] + +def get_WMIS_qubo_id_of_instance(collection, instance_id): + doc = load_WMIS_qubo_of_instance_raw(collection, instance_id) + + if doc == None: + return None + + return doc["_id"] + +def load_WMIS_qubo_of_instance_raw(collection, instance_id): + return collection.find_one({"instance": bson.ObjectId(instance_id)}) + +def read_raw_qubo(raw_qubo): + qubo = {} + + for entry in raw_qubo: + energy = entry[1] + raw_coupler = entry[0] + node1 = tuple(raw_coupler[0]) + node2 = tuple(raw_coupler[1]) + + qubo[(node1, node2)] = energy + + return qubo + +def read_raw_embedding(raw_embedding): + emb = {} + + for entry in raw_embedding: + emb[tuple(entry[0])] = entry[1] + + return emb diff --git a/util/randomSAT.py b/util/randomSAT.py index 6a7d625..d3cf0b7 100644 --- a/util/randomSAT.py +++ b/util/randomSAT.py @@ -3,6 +3,7 @@ import numpy as np import random from . import kSAT +import math def generateRandomKSAT(numberOfClauses, numberOfVariables, @@ -24,7 +25,7 @@ def generateRandomKSAT(numberOfClauses, clauses[clauseIndex].append(varIndex + 1) #fill in the missing bindings - for clause in clauses: + for clauseIndex, clause in enumerate(clauses): tmpClause = [] clauseIsUnique = False @@ -44,9 +45,13 @@ def generateRandomKSAT(numberOfClauses, for i in range(len(tmpClause)): tmpClause[i] *= random.choice([-1, 1]) + tmpClause = list(np.sort(tmpClause)) + if tmpClause not in clauses: clauseIsUnique = True + clauses[clauseIndex] = tmpClause + instance.addClause(tmpClause) return instance @@ -64,3 +69,23 @@ def __getVariablesNotYetInClause(clause, numberOfTotalVars): missingVariables += list(range(prevVar, numberOfTotalVars + 1)) return missingVariables + +def number_of_possible_clauses(number_of_variables, variables_per_clause): + return int(__binom(number_of_variables, variables_per_clause) + * __number_of_sign_placements(variables_per_clause)) + +def __binom(n, k): + if n == k: + return 1 + elif k == 1: + return n + else: + return math.factorial(n) / (math.factorial(k) * math.factorial(n - k)) + +def __number_of_sign_placements(variables_per_clause): + result = 0; + + for i in range(variables_per_clause + 1): + result += __binom(variables_per_clause, i) + + return result diff --git a/util/random_instance_pool.py b/util/random_instance_pool.py new file mode 100644 index 0000000..0dd23dd --- /dev/null +++ b/util/random_instance_pool.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 + +from . import randomSAT + +class Random_instance_pool: + + def __init__(self, parameter_range): + self.__parameter_range = parameter_range + + def __iter__(self): + return self + + def __next__(self): + params = self.__parameter_range.next() + + return randomSAT.generateRandomKSAT(params.number_of_clauses, + params.number_of_variables, + params.variables_per_clause) + + +class Instance_parameters: + + def __init__(self, + number_of_clauses, + number_of_variables, + variables_per_clause = 3): + + self.number_of_clauses = number_of_clauses + self.number_of_variables = number_of_variables + self.variables_per_clause = variables_per_clause + + def __str__(self): + return ("number of clauses: {}\n" + "number of variables: {}\n" + "variables per clause: {}").format(self.number_of_clauses, + self.number_of_variables, + self.variables_per_clause) + +class Instance_parameter_variable_range: + + def __init__(self, start_parameter, variable_range): + self.start_parameter = start_parameter + self.__variable_range = variable_range + + def __iter__(self): + return self + + def __next__(self): + self.start_parameter.number_of_variables = self.__variable_range.next() + + return self.start_parameter + + def next(self): + return self.__next__() + + +class Manual_range: + + def __init__(self, start, stop, step = 1): + self.start = start + self.stop = stop + self.step = step + + self.__current = start + + def __iter__(self): + return self + + def __next__(self): + if self.__current >= self.stop: + raise StopIteration + + self.__current += self.step + + return self.__current + + def next(self): + return self.__next__() + + + diff --git a/util/script.py b/util/script.py index 18f80b7..78dad0e 100644 --- a/util/script.py +++ b/util/script.py @@ -1,6 +1,15 @@ import configparser import os import argparse +import pymongo +import ssl +import mysql.connector +import networkx as nx +from . import queries +from . import graph +import minorminer +from tqdm import tqdm + def readConfig(configFilePath): config = configparser.ConfigParser() @@ -84,4 +93,177 @@ class ArgParser: return tmpValue + +def getDBContext(dbConfigPath): + dbContext = {} + + dbContext["client"] = connect_to_instance_pool(dbConfigPath) + dbContext["db"] = dbContext["client"]["experiments"] + dbContext["instances"] = dbContext["db"]["instances"] + dbContext["experimentScopes"] = dbContext["db"]["experiment_scopes"] + + return dbContext + +def connect_to_instance_pool(dbConfigPath): + dbConf = readConfig(dbConfigPath) + + client = pymongo.MongoClient( + "mongodb://%s:%s@%s:%s/%s" + % ( dbConf["INSTANCE_POOL"]["user"], + dbConf["INSTANCE_POOL"]["pw"], + dbConf["INSTANCE_POOL"]["url"], + dbConf["INSTANCE_POOL"]["port"], + dbConf["INSTANCE_POOL"]["database"]), + ssl=True, + ssl_cert_reqs=ssl.CERT_NONE) + return client[dbConf["INSTANCE_POOL"]["database"]] + +def connect_to_experimetns_db(dbConfigPath): + dbConfig = readConfig(dbConfigPath) + + return mysql.connector.connect( + host=dbConfig["EXPERIMENT_DB"]["url"], + port=dbConfig["EXPERIMENT_DB"]["port"], + user=dbConfig["EXPERIMENT_DB"]["user"], + password=dbConfig["EXPERIMENT_DB"]["pw"], + database=dbConfig["EXPERIMENT_DB"]["database"] + ) + +def frange(start, stop, steps): + while start < stop: + yield start + start += steps + +def create_experiment_scope(db, description, name): + experimentScope = {} + experimentScope["instances"] = [] + + experimentScope["description"] = description + + experimentScope["_id"] = name.strip() + + db["experiment_scopes"].insert_one(experimentScope) + +def write_instance_to_pool_db(db, instance): + instance_document = instance.writeJSONLike() + + result = db["instances"].insert_one(instance_document) + + return result.inserted_id + +def add_instance_to_experiment_scope(db, scope_name, instance_id): + db["experiment_scopes"].update_one( + {"_id": scope_name}, + {"$push": {"instances": instance_id}} + ) + +def write_qubo_to_pool_db(collection, qubo, sat_instance_id): + doc = {} + + doc["instance"] = sat_instance_id + doc["description"] = {"": "", + "": " | | \"\"", + "": "", + "": "", + "": "", + "": "", + "": "", + "": ""} + + doc["qubo"] = __qubo_to_JSON(qubo) + + collection.insert_one(doc) + +def __qubo_to_JSON(qubo): + quboJSON = [] + + for coupler, value in qubo.items(): + quboJSON.append([coupler, float(value)]) + + return quboJSON + +def write_wmis_embedding_to_pool_db(collection, qubo_id, solver_graph_id, embedding): + if not __embedding_entry_exists(collection, qubo_id, solver_graph_id): + __prepare_new_wmis_embedding_entry(collection, qubo_id, solver_graph_id) + + collection.update_one( + {"qubo": qubo_id, "solver_graph": solver_graph_id}, + {"$push": {"embeddings": __embedding_to_array(embedding)}} + ) + +def __embedding_entry_exists(collection, qubo_id, solver_graph_id): + filter = {"qubo": qubo_id, "solver_graph": solver_graph_id} + + if collection.count_documents(filter) > 0: + return True + + return False + +def __prepare_new_wmis_embedding_entry(collection, qubo_id, solver_graph_id): + doc = {} + + doc["qubo"] = qubo_id + doc["solver_graph"] = solver_graph_id + doc["description"] = {"": "", + "": " | \"\"", + "" : "", + "": " | \"\""} + doc["embeddings"] = [] + + collection.insert_one(doc) + +def __embedding_to_array(embedding): + emb_arr = [] + + for node, chain in embedding.items(): + emb_arr.append([node, chain]) + + return emb_arr + +def write_solver_graph_to_pool_db(collection, graph): + data = nx.node_link_data(graph) + + id = queries.get_id_of_solver_graph(collection, data) + + if id != None: + return id + + doc = {} + doc["data"] = data + + return collection.insert_one(doc).inserted_id + +def find_wmis_embeddings_for_scope(db, scope, solver_graph): + solver_graph_id = write_solver_graph_to_pool_db(db["solver_graphs"], + solver_graph) + + qubos = queries.WMIS_scope_query(db) + qubos.query(scope) + + for qubo, qubo_id in tqdm(qubos): + if not __embedding_entry_exists(db["embeddings"], qubo_id, solver_graph_id): + nx_qubo = graph.qubo_to_nx_graph(qubo) + + emb = minorminer.find_embedding(nx_qubo.edges(), + solver_graph.edges(), + return_overlap=True) + + if emb[1] == 1: + write_wmis_embedding_to_pool_db(db["embeddings"], + qubo_id, + solver_graph_id, + emb[0]) + +def save_simulated_annealing_result(collection, result, solver_input, emb_list_index): + doc = {} + + doc["data"] = result.to_serializable() + doc["instance"] = solver_input["instance_id"] + doc["embedding"] = { + "embedding_id": solver_input["embeddings_id"], + "list_index": emb_list_index + } + + collection.insert_one(doc) +