Skip to content
This repository has been archived by the owner on Oct 31, 2023. It is now read-only.

fix math of calculating scaled price for marketplace #3976

Merged
merged 2 commits into from
Mar 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion golem/marketplace/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .offerpool import Offer, OfferPool # noqa pylint: disable=unused-import
from .offerpool import scale_price, Offer, OfferPool # noqa pylint: disable=unused-import
8 changes: 8 additions & 0 deletions golem/marketplace/offerpool.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
import logging
from typing import List, Dict, ClassVar, Tuple

Expand All @@ -9,6 +10,13 @@
logger = logging.getLogger(__name__)


def scale_price(task_price: float, offered_price: float) -> float:
if offered_price == 0:
# using float('inf') breaks math in order_providers, when alpha < 1
return sys.float_info.max
return task_price / offered_price


class Offer:
def __init__(
self,
Expand Down
8 changes: 2 additions & 6 deletions golem/task/tasksession.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from golem.core import variables
from golem.docker.environment import DockerEnvironment
from golem.docker.image import DockerImage
from golem.marketplace import Offer, OfferPool
from golem.marketplace import scale_price, Offer, OfferPool
from golem.model import Actor
from golem.network import history
from golem.network.concent import helpers as concent_helpers
Expand Down Expand Up @@ -623,11 +623,7 @@ def _offer_chosen(is_chosen: bool) -> None:

task = self.task_manager.tasks[msg.task_id]
offer = Offer(
scaled_price=(
msg.price / task.header.max_price
etam marked this conversation as resolved.
Show resolved Hide resolved
if task.header.max_price > 0
else float('inf')
),
scaled_price=scale_price(task.header.max_price, msg.price),
reputation=get_provider_efficiency(self.key_id),
quality=get_provider_efficacy(self.key_id).vector,
)
Expand Down
16 changes: 14 additions & 2 deletions rust/golem/src/marketplace.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::f64;

// Price sensitivity factor. 0 <= ALPHA <= 1
const ALPHA: f64 = 0.67;
// Distrust factor. 1 <= D
Expand Down Expand Up @@ -82,16 +84,26 @@ mod tests {
r: 0.0,
},
},
Offer {
scaled_price: f64::MAX,
reputation: 15.0,
quality: Quality {
s: 0.0,
t: 0.0,
f: 0.0,
r: 0.0,
},
},
];
}
#[test]
fn order_providers_price_preference() {
let offers = gen_offers();
assert_eq!(order_providers_impl(offers, 1.0, PSI, D), vec![3, 1, 0, 2]);
assert_eq!(order_providers_impl(offers, 1.0, PSI, D), vec![4, 3, 1, 0, 2]);
}
#[test]
fn order_providers_reputation_preference() {
let offers = gen_offers();
assert_eq!(order_providers_impl(offers, 0.0, PSI, D), vec![1, 2, 3, 0]);
assert_eq!(order_providers_impl(offers, 0.0, PSI, D), vec![1, 2, 4, 3, 0]);
}
}
11 changes: 10 additions & 1 deletion tests/golem/marketplace/test_offerpool.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import sys
from unittest import TestCase
from unittest.mock import Mock, patch, ANY

from golem.marketplace import Offer, OfferPool
from golem.marketplace import scale_price, Offer, OfferPool


class TestScalePrice(TestCase):
def test_basic(self):
assert scale_price(5, 2) == 2.5

def test_zero(self):
assert scale_price(5, 0) == sys.float_info.max


@patch('golem.marketplace.offerpool.task.deferLater')
Expand Down
8 changes: 5 additions & 3 deletions tests/golem/marketplace/test_rust.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from golem.marketplace import Offer
from golem.marketplace import scale_price, Offer
from golem.marketplace.rust import order_providers


def test_order_providers():
offer0 = Offer(scaled_price=2., reputation=1., quality=(1., 1., 6., 1.))
offer1 = Offer(scaled_price=3., reputation=5., quality=(1., 3., 1., 4.))
offer2 = Offer(scaled_price=4., reputation=2., quality=(2., 1., 1., 3.))
res = order_providers([offer0, offer1, offer2])
offer3 = Offer(scaled_price=scale_price(5, 0), reputation=3.,
quality=(1., 2., 3., 4.))
res = order_providers([offer0, offer1, offer2, offer3])
# Actual order is not important, just that it is a permutation
assert sorted(res) == list(range(3))
assert sorted(res) == list(range(4))