What statistical technique would be appropriate for optimising the weights? - optimization

Background:
For example I have the following data
headings = {
:heading1 => { :weight => 25, :views => 0, :conversions => 0}
:heading2 => { :weight => 25, :views => 0, :conversions => 0}
:heading3 => { :weight => 25, :views => 0, :conversions => 0}
:heading4 => { :weight => 25, :views => 0, :conversions => 0}
}
total_views = 0
I got to serve these headings based on their weightages. Every time a heading is served its views is incremented by one and total_views also incremented. And whenever a user clicks on a served heading its conversions is incremented by one. I've written a program (in Ruby) which is performing this well.
Question:
I need to Auto Optimize best converting heading. Consider the following views and conversions for all headings:
heading1: views => 50, conversions => 30
heading2: views => 50, conversions => 10
heading3: views => 50, conversions => 15
heading4: views => 50, conversions => 5
I need to automatically increase the weightage of heading(s) which is/are converting more and vice versa. The sum of weightage will always be 100.
Is there any standard algorithm/formula/technique to do this? There might be some other parameters that need to predefined before making these calculations. But I am not getting it through.
Pleas advise.
Thanks,
Imran

Well, a simple percentage calculation would do that.
30+10+15+5=60
30/60*100=50
10/60*100=17 (rounded)
15/60*100=25
5/60*100=8 (rounded)
So you get weightings of 50,17,25 and 8. You may or may not nead to watch out for rounding errors.

Related

yii2: what is maximum value of Pagination-Per-Page into RESTful Web Service API

I tried to send the parameter per-page:100 but it seems like that the returned result is maximum number of items is 50 , how to change it
i used the following code for serilizer
public $serializer = [ 'class' => 'yii\rest\Serializer','collectionEnvelope' => 'items'];
is there a way to change the maximum value from 50 , it works for all the values less that 50 .
It depends on DataProvider configuration. You can change it by passing this in DataProvider:
// ...
'pagination' => [
'defaultPageSize' => 20,
'pageSizeLimit' => [1, 50]
],

Yii CMaskedTextField with one or two digits 0-99 (quantity)

I'm trying to make CMaskedTextField as quantity input field with base quantity = 0, and maximum = 99.
Can't figure out the mask and/or charMap.
I've tried:
$this->widget('CMaskedTextField', array(
'model' => $position,
'attribute' => 'Quantity',
'mask' => '99',
'value' => $currentQuantity,
'htmlOptions' => array('size' => 2, 'maxlength'=>2, 'minlength'=>1)
), true);
but this mask means there must be only 2 digits
Optional (i guess js will do the work if cmaskedtextfield not): when user clears input it should converts to '0'.
Mask might be set thru regex:
\d{1,2}
In model rules() you might define:
array('attributeName', 'match', 'pattern' => '/\d{1,2}/',
'message' => '{attribute} can only contain digits from 0 to 99'),
There is no convertion to 0 but the explicit message for user.

Magento bundle products - selection_id cannot be null?

I am trying to create a bundled product programmatically, and setting the options via this:
$new_options[$count] = array(
'required' => 0,
'position' => 1,
'parent_id' => $parentProduct->getId(),
'type' => 'select',
'title' => $product->getName(),
'default_title' => $product->getName()
);
$new_selections[$count] = array(array(
'product_id' => $product->getEntityId(),
'selection_qty' => $child['qty'],
'selection_can_change_qty' => 0,
'position' => 0,
'is_default' => 1,
'selection_price_type' => 0,
'selection_price_value' => 0.0
));
...
$parentProduct->setBundleOptionsData($new_options);
$parentProduct->setBundleSelectionsData($new_selections);
Which looks correct (as described in https://stackoverflow.com/a/4415800/494643). However, it is not working - I get an SQL exception complaining that Column 'selection_id' cannot be null'. How do I get around this? The selection id is an auto_increment column, so I can't get it until it is created, but it looks like it cannot be created?
The solution lies in the _beforeSave function of the Mage_Bundle_Model_Selection model.
This causes it to attempt to write the selection_id to the catalog_product_bundle_selection_price table, before it has saved the selection object - and therefore before it has generated a selection_id. The answer therefore is to force it to generate an id before it saves, so looking again at the _beforeSave function, we can see that it only saves the price if the store is not 0.
Specifically, this part:
$storeId = Mage::registry('product')->getStoreId();
if (!Mage::helper('catalog')->isPriceGlobal() && $storeId) {
which means that if we set the store id of the registry product to 0 first, we can cause it to save the selection, without saving the price. We would then need to reset the store to the previous value, and save again, to record the price - although only after having reloaded the object to get the newly generated selection id.

ElasticSearch Tire two field conditional filter

I'm doing a mutli-index query With Tire and rails 3 and I want to filter out Venues who have approved => false so I need some sort of combo filter.
Here is the query
query = params[:q]
from = params.delete(:from)
size = params[:size] || 25
Tire.search(
[Venue.index_name,
Performer.index_name, User.index_name], load: true) do |s|
s.query do
string(query, fields: [:_all, :name, :title], use_dis_max: true)
end
s.from from if from
s.size size if size
end.results.to_a
This line removes all Performers and Users because they don't have an :approved field.
s.filter(:term, :approved => true )
And this line obviously removes all non-venues which is no good.
s.filter(:term, { :approved => true, :index_name => 'venues'} )
Any ideas besides adding an approved: true field to all Users and Performers? I think something like this is what I want conceptually:
s.filter(:term, :approved => true, :if => {:index_name => 'venues'} )
EDIT Thanks to Mallox I was able to find the Should construct but I'm still struggling to implement it Tire. It seems like the below code should work but it return no results on any query. I also remove the "{:terms => { :index_name => ["performers", "users"]}}," to make sure it wasn't my use of index name or multiple lines of query that was the problem and still no luck. Can anybody shed some light on how to do this in Tire?
s.filter(:bool, :should => [
{:terms => { :index_name => ["performers", "users"]}},
{:term => { :approved => true}},
] )
So i have little knowledge about Ruby and Tire, but the ElasticSearch query that you want to build would be based on a bool filter, that contains some "should" entries (which would translate into inclusive OR).
So in your case something along the lines of:
"filter" : {
"bool" : {
"should" : [
{
"terms" : { "_type" : ["Performers","Users"] }
},
{
"term" : { "approved" : true }
}
]
}
}
Take a look at the documentation here, maybe that'll help:
:http://www.elasticsearch.org/guide/reference/query-dsl/bool-filter/

complex search with thinking sphinx

I'd like to do a complex search with thinking sphinx:
Search for users which:
-> live in a city (city_id attribute)
-> or has hability to move to a city (mobile_cities association)
-> or live at a maximum distance from a lat/long point, the maximum distance is different for each user and set in a mobility_distance attribute.
For now I did that with 3 differents search, I volontary set a big per_page number, then i merge the 3 results on a single array, an then paginate this array :
#users living in the #city
search_set_living = search_set.merge({:city_id => #city.id })
users_living = User.search :with => search_set_living.dup,
:page => 1, :per_page => 1000
#users declaring hability to move to the #city
search_set_mobile = search_set.merge({:mobile_cities_ids => #city.id })
users_mobile = User.search :with => search_set_mobile.dup, :page => 1, :per_page => 1000
#users living at a maximum distance from the origin point(custom distance for each user, max 30km)
search_set_around = search_set.merge({"#geodist" => 0.0..30_000.0})
users_around = User.search :geo => [#search_latitude * Math::PI / 180 , #search_longitude * Math::PI / 180],
:with => search_set_around.dup,
:page => 1, :per_page => 1000
users_around_filtered = users_around.dup.delete_if{|user| (user.mobility_distance * 1000 )< user.sphinx_attributes['#geodist'] }
#merge the 3 results in a array
all_users = (users_mobile.flatten + users_around_filtered.flatten).uniq
#look for facets and paginate the array
#facets = User.facets :with => {:user_id => all_users.map(&:id)}
#users_to_display = all_users.paginate(:page => params[:page], :per_page => 10)
This is working fine but i'm not satisfied:
-performance are not so good,
-I want the ability to sort on multiple attributes like this :order => "created_at DESC, #relevance DESC"
I want to do the exact same search but in a single sphinx's search.
I know that I should use the "OR Logic with Attribute Filters" from the docs but I don't know how to mix it with a geo_search call...
I really have no idea how to do that,
can you guys help me ?
Many thanks,
The :sphinx_select option is definitely your friend here, as you've guessed. Let's piece it together bit by bit:
logic = [
"city_id = #{#city.id}",
"IN(mobile_cities_ids, #{#city.id}",
"GEODIST(lat, lng, #{lat}, #{lng}) < (mobility_distance * 1000)"
]
User.search :sphinx_select => "*, #{logic.join(" OR ")}) AS valid",
:with => {:valid => true}
Add pagination as you like, tweak the attribute names if needed (maybe your lat/lng attributes are named something else). I don't think you need the IF call around that custom attribute like in the docs, but if things aren't working when they should be, maybe give it a shot. Should be good in a facets call too.
Great ! Thank you so much. I just needed to correct a little your syntax (some parenthesis missing) in order to get it work.
I had to add per_page and page arguments too, don't know really why.
logic = ["city_id = #{#city.id}",
"IN(mobile_cities_ids, #{#city.id})",
"GEODIST(latitude, longitude, #{#search_latitude * Math::PI / 180}, #{#search_longitude * Math::PI / 180}) < (mobility_distance * 1000)"]
search_set_logic = search_set.merge({:valid => true})
#users_to_display = User.search :sphinx_select => "*, (#{logic.join(" OR ")}) AS valid",
:with => search_set_logic.dup,
:sort_mode => :extended,
:order => "visibility DESC, last_login_at DESC",
:page => params[:page], :per_page => 10