How do you do an inner product with ruby NArray? - ruby

I'm looking for something like the inner method in numpy.
I have a 4 dimensional array called 'labels' and a one dimensional array (a vector) called 'discounts'. In numpy I can do numpy.inner(labels, discounts) and this will do the inner product between discounts and each row of the last dimension of labels returning a 3 dimensional array. I can not figure out how to do the same thing with NArray in ruby.

$ irb -rnarray
irb(main):001:0> a=NArray.float(3,2,2).indgen
=> NArray.float(3,2,2):
[ [ [ 0.0, 1.0, 2.0 ],
[ 3.0, 4.0, 5.0 ] ],
[ [ 6.0, 7.0, 8.0 ],
[ 9.0, 10.0, 11.0 ] ] ]
irb(main):002:0> b=NArray[1..3]
=> NArray.int(3):
[ 1, 2, 3 ]
irb(main):003:0> a*b
=> NArray.float(3,2,2):
[ [ [ 0.0, 2.0, 6.0 ],
[ 3.0, 8.0, 15.0 ] ],
[ [ 6.0, 14.0, 24.0 ],
[ 9.0, 20.0, 33.0 ] ] ]
irb(main):004:0> (a*b).sum(0)
=> NArray.float(2,2):
[ [ 8.0, 26.0 ],
[ 44.0, 62.0 ] ]
irb(main):005:0> a.mul_add(b,0)
=> NArray.float(2,2):
[ [ 8.0, 26.0 ],
[ 44.0, 62.0 ] ]

Related

Bucket prediction given an integer?

If I have a dictionary of integers where the value is an array of two integers sorted, with the two values being the largest value, and the smallest value out of k values present in bucket n, how can I predict/estimate which bucket a given number would appear.
An example of said dictionary is:
{
1: [
541247,
14771
],
15: [
9789,
9621
],
22: [
8984,
8923
],
64: [
7278,
7263
],
93: [
6846,
6804
],
126: [
5789,
5765
],
139: [
5484,
5462
],
208: [
4326,
4314
],
285: [
3788,
3783
],
322: [
3634,
3631
],
337: [
3586,
3582
],
356: [
3517,
3513
],
448: [
3232,
3229
],
459: [
3199,
3196
],
539: [
2990,
2989
],
581: [
2891,
2890
],
596: [
2858,
2856
],
640: [
2770,
2768
],
675: [
2704,
2702
],
679: [
2697,
2695
],
686: [
2684,
2682
],
733: [
2602,
2600
],
879: [
2387,
2386
],
961: [
2283,
2282
],
980: [
2261,
2260
],
995: [
2244,
2243
],
1000: [
2238,
2237
],
1169: [
2064,
2063
],
1175: [
2058,
2057
],
1236: [
2005,
2004
],
1259: [
1985,
1984
],
1281: [
1967,
1966
],
1348: [
1913,
1912
],
1424: [
1855,
1855
],
1429: [
1852,
1851
],
1514: [
1796,
1795
],
1564: [
1764,
1764
],
1596: [
1744,
1744
],
1625: [
1726,
1726
],
1661: [
1704,
1703
],
1695: [
1683,
1682
],
1710: [
1675,
1674
],
1713: [
1673,
1673
],
1720: [
1669,
1669
],
1835: [
1609,
1608
],
1846: [
1603,
1602
],
1861: [
1594,
1594
],
1864: [
1593,
1592
],
1916: [
1562,
1561
],
2093: [
1462,
1462
],
2159: [
1424,
1423
],
2175: [
1414,
1413
],
2189: [
1405,
1405
],
2209: [
1394,
1393
],
2266: [
1359,
1358
],
2319: [
1327,
1326
],
2352: [
1306,
1306
],
2429: [
1260,
1260
],
2512: [
1214,
1214
],
2629: [
1141,
1141
],
2704: [
1088,
1088
],
2736: [
1064,
1063
],
2745: [
1057,
1057
],
2766: [
1042,
1042
],
2779: [
1033,
1032
],
2790: [
1025,
1024
],
2798: [
1019,
1018
],
2880: [
964,
964
],
2945: [
928,
927
],
3032: [
885,
884
],
3115: [
838,
837
],
3120: [
835,
834
],
3140: [
823,
822
],
3169: [
806,
805
],
3235: [
770,
770
],
3252: [
762,
762
],
3258: [
759,
758
],
3366: [
715,
714
],
3414: [
690,
690
],
3444: [
675,
674
],
3507: [
645,
644
],
3543: [
630,
629
],
3758: [
516,
515
],
3764: [
512,
511
],
3770: [
509,
508
],
3931: [
446,
446
],
4013: [
416,
415
],
4055: [
390,
390
],
4116: [
378,
377
],
4255: [
370,
370
],
4286: [
362,
361
],
4325: [
360,
360
],
4337: [
355,
355
],
4349: [
347,
347
],
4355: [
344,
343
],
4366: [
339,
339
],
4379: [
333,
333
],
4460: [
312,
311
],
4474: [
309,
309
],
4487: [
308,
308
],
4545: [
259,
257
],
4555: [
242,
241
]
}
If I am searching for the bucket containing 2672 how would I go about doing this? The bucket data is gathered from web scraping so I know that bucket 692 contains 2672, but I am looking for a more general solution that would allow me to only have to scrape x number of buckets before I have enough data to predict which bucket would hold any value. I will add that the first and last entries in the dict are guaranteed to hold both the largest and smallest searchable values.
Is this a known problem already? If so what is it called?
My current solution is below:
def bucket_search(buckets, n):
start_idx = None
end_idx = None
bucket_keys = list(buckets.keys())
bucket_values = list(buckets.values())
for idx, bv in enumerate(bucket_values):
high,low = bv
if n > low and n < high:
start_idx = idx
end_idx = idx
break
elif high < n:
end_idx = idx
break
if (end_idx != start_idx):
continue_search = True
tmp_start_idx = end_idx - 1
while continue_search:
high, low = bucket_values[tmp_start_idx]
if (low > n):
continue_search = False
elif (low < n and high < n):
tmp_start_idx -= 1
start_idx = tmp_start_idx
start_bucket_value = bucket_keys[start_idx]
end_bucket_value = bucket_keys[end_idx]
start_value = bucket_values[start_idx][1]
end_value = bucket_values[end_idx][0]
bucket_value_difference = end_bucket_value - start_bucket_value
value_difference = start_value - end_value
increment_amount = bucket_value_difference / value_difference
tmp_value = start_value
tmp_bucket_value = start_bucket_value
for i in range(bucket_value_difference):
tmp_value -= increment_amount
tmp_bucket_value += 1
if (n > tmp_value):
break
return tmp_bucket_value
else:
return bucket_keys[start_idx]
Currently bucket_search(data, 2672) (where data is the example data provided above) returns 704. That is close to 692 but I would think that there is a better, more accurate/precise solution.
While I used python, answers of any language are fine as long as the answer can be rewritten in another language, i.e. please don't use any niche libraries.
If there is already an answered SO question that solves this problem, I apologize as I am unsure what to call this kind of problem.

Magento 2 rest api doesn't update salable quantity

I use rest api to create a simple product on my magento. All works correctly except quantity column that is correctly update on "Quantity" column but not on the salable quantity.
Rest call: "www.mysite.com/V1/products"
Array data
$data = [
"product" => [
"sku" => $sku,
"name" => $product_title,
"attribute_set_id" => 4,
"price" => $price,
"status" => 1,
"visibility" => 4,
"type_id" => "simple",
"weight" => "1",
"extension_attributes" => [
"category_links" => [
[
"position" => 0,
"category_id" => "53"
]
],
"stock_item" => [
"qty" => $qty,
"is_in_stock" => true
]
],
"custom_attributes" => [
[
"attribute_code" => "special_price",
"value" => $salable_price
],
[
"attribute_code" => "special_from_date",
"value" => "2021-02-07 00:00:00"
],
[
"attribute_code" => "special_to_date",
"value" => "2091-02-07 00:00:00"
],
[
"attribute_code" => "cost",
"value" => $salable_price
],
[
"attribute_code" => "description",
"value" => $description
],
[
"attribute_code" => "short_description",
"value" => $short_description
]
]
]
];
As you see, qty has been correctly update on qty column but not on the salable quantity. What is my mistake?
Please try this:
"stockItem": {
"is_in_stock": 1,
"qty": 10,
"manage_stock": true,
"use_config_manage_stock": 1
}

Unrecognized option to $bucket: $group

getting the above error when i run $bucket with $group in mongodb laravel.
input collection:
{
"id": "n54qllhzwdlxqvy",
"season_id": "vl7oqdehzjxr510",
"status_id": 8,
"venue_id": "",
"referee_id": "",
"neutral": 1,
"note": "",
"home_scores": [0, 0, 0, 0, 0, 0, 0],
"away_scores": [1, 0, 0, 0, 0, 0, 0],
"home_position": "",
"away_position": "",
"coverage": {
"mlive": 0,
"lineup": 0
},
"round": {
"stage_id": "ednm9whz7xoryox",
"round_num": 0,
"group_num": 3
},
"updated_at": "2021-05-03 16:53:52",
"competition_id": "gpxwrxlhdgryk0j",
"competition_name": "Chinese U18 Women's National Games",
"home_team_id": "2y8m4zh8xwjql07",
"home_team_name": "Fujian U18 Women ",
"away_team_id": "8yomo4hvxg2q0j6",
"away_team_name": "Shandong U18 Women",
"match_time": "2021-05-03 15:00:00",
"match_tsp": 1620025200,
"created_at": "2021-05-04 14:33:05"
}
$data = DB::connection('mongodb_football')->collection('match_list')->raw(function ($collection) {
return $collection->aggregate([
[
'$bucket' => [
'groupBy' => '$competition_id',
'boundaries' => ["4zp5rzgh3nq82w1","4zp5rzghjjgq82w", "4zp5rzghkzq82w1","4zp5rzghpvnq82w","4zp5rzghx38q82w","4zp5rzghx5q82w1"],
'default' => "Other",
'output' => [
"data" => [
'$push' => [
"season_id" => '$season_id'
]
]
]
]
]
]);
});
output:
need to group all data based on competition_id and need all the data.
Remove $ prefix from groupBy, boundaries, default, and output.
The $bucket 'groupBy' field must be defined as a $-prefixed path or an expression
It says group by field required reference field that should be prefix by $, but you have assigned it in array bracket [].
Try below syntax, i have not tested yet but it would be,
$data = DB::connection('mongodb_football')->collection('match_list')->raw(function ($collection) {
return $collection->aggregate([
[
'$bucket' => [
'groupBy' => '$competition_id',
'boundaries' => ["4zp5rzgh3nq82w1","4zp5rzghjjgq82w", "4zp5rzghkzq82w1","4zp5rzghpvnq82w","4zp5rzghx38q82w","4zp5rzghx5q82w1"],
'default' => "Other",
'output' => [
"data" => [
'$push' => [
"season_id" => '$season_id'
]
]
]
]
]
]);
});
Playground
Solution
$data = DB::connection('mongodb_football')->collection('match_list')->raw(function ($collection) {
return $collection->aggregate([
[
'$bucket' => [
'groupBy' => '$competition_id',
'boundaries' => ["4zp5rzgh3nq82w1","4zp5rzghjjgq82w", "4zp5rzghkzq82w1","4zp5rzghpvnq82w","4zp5rzghx38q82w","4zp5rzghx5q82w1"],
'default' => "Other",
'output' => [
"data" => [
'$push' => [
"season_id" => '$season_id'
]
]
]
]
]
]);
});

Elasticsearch query for simple category search, sorting by price and getting records by range

I want to write query with following condition :
search by category (like category = 'cat1')
and with price range (and price between 100 to 500)
and sort by price (low to high)
I tried:
$params = [
'index' => 'my_index',
'type' => 'product',
'body' => [
//"from" => 0, "size" => 2,
"sort" => [
["default_product_low_price.sale_price" => ["order" => "asc"]]
],
'query'=> $query,
"aggs" => [
"default_product_low_price" => [
"nested" => [
"path" => "default_product_low_price"
],
"aggs" => [
"range" => ["default_product_low_price.sale_price" => [ "gte" => '790',
"lte" => '1000' ]],
//"max_price" => ["max" => [ "field" => "default_product_low_price.sale_price" ]]
],
]
]
]
];
But I am getting an error
Bad Request 400 Exception in GuzzleConnection.php line 277: error.
Please guide me where I am wrong? What is the right query?
I think this should be your query :
$params = [
'index' => 'my_index',
'type' => 'product',
'body' => [
"sort" =>[
["default_product_low_price.sale_price" => ["order" => "asc"]]
],
"query"=> [
"filtered"=> [
"query"=> [
"match_all"=> []
],
"query"=>[
"term"=> [
"category.name"=> "jeans"
]
],
"filter"=> [
"nested"=> [
"path"=> "default_product_low_price",
"filter"=> [
"bool"=> [
"must"=> [
[
"range"=> [
"default_product_low_price.sale_price"=> [
"gte"=> 100,
"lte"=> 200,
]
]
]
]
]
]
]
]
]
]
]
];

How find all overlapping circles from radius of central circle?

How to do an intersection or overlap query in mongo shell - what circles overlap my search region? Within relate only to the center position but doesn't include radius of the other circles in searched scope.
Mongo:
# My bad conception:
var search = [[30, 30], 10]
db.places.find({circle : {"$within" : {"$center" : [search]}}})
Now I can obtain only this circles within central point lies in searched area of circle:
Ruby:
# field :circle, type: Circle # eg. [ [ 30, 30 ], 10 ]
field :radius, type: Integer
field :location, :type => Array, :spatial => true
spatial_index :location
Places.within_circle(location: [ [ 30, 30 ], 10 ])
# {"$query"=>{"location"=>{"$within"=>{"$center"=>[[30, 30], 10]}}}
I created example data with additional location (special index) and radius instead circle because circle isn't supported by mongodb geo index:
{ "_id" : 1, "name" : "a", "circle" : [ [ 5, 5 ], 40 ], "latlng" : [ 5, 5 ], "radius" : 40 }
{ "_id" : 2, "name" : "b", "circle" : [ [ 10, 10 ], 5 ], "latlng" : [ 10, 10 ], "radius" : 5 }
{ "_id" : 3, "name" : "c", "circle" : [ [ 20, 20 ], 5 ], "latlng" : [ 20, 20 ], "radius" : 5 }
{ "_id" : 4, "name" : "d", "circle" : [ [ 30, 30 ], 50 ], "latlng" : [ 30, 30 ], "radius" : 50}
{ "_id" : 5, "name" : "e", "circle" : [ [ 80, 80 ], 30 ], "latlng" : [ 80, 80 ], "radius" : 30}
{ "_id" : 6, "name" : "f", "circle" : [ [ 80, 80 ], 20 ], "latlng" : [ 80, 80 ], "radius" : 20}
Desired query result:
{ "_id" : 1, "name" : "a", "circle" : [ [ 5, 5 ], 40 ], "latlng" : [ 5, 5 ], "radius" : 40 }
{ "_id" : 3, "name" : "c", "circle" : [ [ 20, 20 ], 5 ], "latlng" : [ 20, 20 ], "radius" : 5 }
{ "_id" : 4, "name" : "d", "circle" : [ [ 30, 30 ], 50 ], "latlng" : [ 30, 30 ], "radius" : 50}
{ "_id" : 5, "name" : "e", "circle" : [ [ 80, 80 ], 30 ], "latlng" : [ 80, 80 ], "radius" : 30}
Solution below assumes that I get all rows and then filter on the ruby side my radius but it returns only:
{ "_id" : 4, "name" : "d", "circle" : [ [ 30, 30 ], 50 ], "latlng" : [ 30, 30 ], "radius" : 50}
I'm not familiar with mongodb but I assume that in [[x, y], r] values mean
x: value of the center on the axis x.
y: value of the center on the axis y.
r: circle radius.
Say you have circle S which is your search and a random circle A. Then you could calcule the distance between both circles' center (S.center and A.center) and see if it is inferior to those both circles radius added (S.r + A.r).
def distance_between(a, b)
((b.first - a.first)**2 + (b.last - a.last)**2)**0.5
end
elements = [{ _id: 1, name: "a", circle: [ [ 5, 5 ], 40 ] },
{ _id: 2, name: "b", circle: [ [ 10, 10 ], 5 ] },
{ _id: 3, name: "c", circle: [ [ 20, 20 ], 5 ] },
{ _id: 4, name: "d", circle: [ [ 30, 30 ], 50 ] },
{ _id: 5, name: "e", circle: [ [ 80, 80 ], 30 ] },
{ _id: 6, name: "f", circle: [ [ 80, 80 ], 20 ] }]
search = [[30, 30], 10]
elements.select do |elem| circle = elem[:circle]
distance_between(circle.first, search.first) <= circle.last + search.last
end
#{:_id=>1, :name=>"a", :circle=>[[5, 5], 40]}
#{:_id=>3, :name=>"c", :circle=>[[20, 20], 5]}
#{:_id=>4, :name=>"d", :circle=>[[30, 30], 50]}
Unfortunately there is currently no capability in mongo to directly query about overlapping objects, only points within objects.
#oldergod's answer describes the algorithm to calculate whether two circles overlap.
Here is a work-around in the shell based on that calculation:
function distance(a, b) {
return Math.pow(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2), 0.5);
}
On your sample data inserted into collection 'circle':
> db.circle.find().forEach(
function(c) {
if ( (distance(c.latlng, search.latlng) < c.radius + search.radius) )
{
print(c.name);
}
} )
a
c
d
>

Resources