Skip to content

Commit

Permalink
More macro work
Browse files Browse the repository at this point in the history
  • Loading branch information
ekoutanov committed Dec 24, 2023
1 parent b4a8cd6 commit bdf661b
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 55 deletions.
25 changes: 9 additions & 16 deletions brumby-soccer/src/fit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use brumby::opt::{
use brumby::probs::SliceExt;

use crate::domain::{Offer, OfferType, OutcomeType, Player, Side};
use crate::domain::OfferType::{AnytimeAssist, FirstGoalscorer};
use crate::domain::Player::Named;
use crate::interval::{
BivariateProbs, Config, explore, PlayerProbs, PruneThresholds, TeamProbs,
Expand Down Expand Up @@ -296,7 +295,7 @@ pub fn fit_first_goalscorer_all<'a>(
Player::Other => unreachable!(),
};
let init_estimate = first_goalscorer.market.probs[index] / side_ratio;
// let start = Instant::now();
// let per_start = Instant::now();
let player_search_outcome = fit_first_goalscorer_one(
h1_probs,
h2_probs,
Expand All @@ -306,7 +305,7 @@ pub fn fit_first_goalscorer_all<'a>(
intervals,
max_total_goals
);
// println!("first goal for player {player:?}, {player_search_outcome:?}, sample prob. {}, init_estimate: {init_estimate}, took {:?}", first_goalscorer.market.probs[index], start.elapsed());
// println!("first goal for player {player:?}, {player_search_outcome:?}, sample prob. {}, init_estimate: {init_estimate}, took {:?}", first_goalscorer.market.probs[index], per_start.elapsed());
(player.clone(), player_search_outcome.optimal_value)
}
_ => unreachable!(),
Expand All @@ -332,10 +331,7 @@ fn fit_first_goalscorer_one(
team_probs: TeamProbs {
h1_goals: h1_goals.clone(),
h2_goals: h2_goals.clone(),
assists: UnivariateProbs {
home: 1.0,
away: 1.0,
},
assists: UnivariateProbs::default(),
},
player_probs: vec![(
player.clone(),
Expand All @@ -348,14 +344,14 @@ fn fit_first_goalscorer_one(
max_total_goals,
min_prob: GOALSCORER_MIN_PROB,
},
expansions: requirements(&FirstGoalscorer),
expansions: requirements(&OfferType::FirstGoalscorer),
};
let outcome_type = OutcomeType::Player(player.clone());
univariate_descent(
&UnivariateDescentConfig {
init_value: init_estimate,
init_step: init_estimate * 0.1,
min_step: init_estimate * 0.001,
min_step: init_estimate * 0.0001,
max_steps: 100,
acceptable_residual: 1e-9,
},
Expand Down Expand Up @@ -438,10 +434,7 @@ fn fit_anytime_goalscorer_one(
team_probs: TeamProbs {
h1_goals: h1_goals.clone(),
h2_goals: h2_goals.clone(),
assists: UnivariateProbs {
home: 1.0,
away: 1.0,
},
assists: UnivariateProbs::default(),
},
player_probs: vec![(
player.clone(),
Expand All @@ -461,7 +454,7 @@ fn fit_anytime_goalscorer_one(
&UnivariateDescentConfig {
init_value: init_estimate,
init_step: init_estimate * 0.1,
min_step: init_estimate * 0.001,
min_step: init_estimate * 0.0001,
max_steps: 100,
acceptable_residual: 1e-9,
},
Expand Down Expand Up @@ -559,14 +552,14 @@ fn fit_anytime_assist_one(
max_total_goals,
min_prob: GOALSCORER_MIN_PROB,
},
expansions: requirements(&AnytimeAssist),
expansions: requirements(&OfferType::AnytimeAssist),
};
let outcome_type = OutcomeType::Player(player.clone());
univariate_descent(
&UnivariateDescentConfig {
init_value: init_estimate,
init_step: init_estimate * 0.1,
min_step: init_estimate * 0.001,
min_step: init_estimate * 0.0001,
max_steps: 100,
acceptable_residual: 1e-9,
},
Expand Down
7 changes: 2 additions & 5 deletions brumby-soccer/src/interval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use rustc_hash::FxHashMap;

use brumby::hash_lookup::HashLookup;
use brumby::stack_vec::StackVec;
use brumby::sv;

use crate::domain::{Player, Score, Side};

Expand All @@ -22,11 +23,7 @@ pub struct Prospect {
}
impl Prospect {
fn init(players: usize) -> Prospect {
// let stats = vec![PlayerStats::default(); players];
let mut stats = StackVec::default();
for _ in 0..players {
stats.push(PlayerStats::default());
}
let stats = sv![PlayerStats::default(); players];
Prospect {
ht_score: Score::nil_all(),
ft_score: Score::nil_all(),
Expand Down
1 change: 1 addition & 0 deletions brumby-soccer/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ impl Model {
);
probs.push(prob);
}
debug!("... normalizing: {} -> {}", probs.sum(), stub.normal);
probs.normalise(stub.normal);
let market = Market::frame(&stub.overround, probs, price_bounds);
(
Expand Down
115 changes: 81 additions & 34 deletions brumby/src/stack_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,41 @@ impl<T, const C: usize> StackVec<T, C> {

#[inline]
pub fn push(&mut self, value: T) {
self.array[self.len] = Some(value);
self.len += 1;
self.try_push(value).unwrap_or_else(|err| panic!("{}", err))
}

#[inline]
pub fn try_push(&mut self, value: T) -> Result<(), CapacityExceeded> {
if self.len < C {
self.array[self.len] = Some(value);
self.len += 1;
Ok(())
} else {
Err(CapacityExceeded { target_capacity: C })
}
}

#[inline]
pub fn push_repeat(&mut self, value: T, times: usize)
where
T: Clone,
{
self.try_push_repeat(value, times)
.unwrap_or_else(|err| panic!("{}", err))
}

#[inline]
pub fn try_push_repeat(&mut self, value: T, times: usize) -> Result<(), CapacityExceeded>
where
T: Clone,
{
for _ in 1..times {
self.try_push(value.clone())?;
}
if times > 0 {
self.try_push(value)?;
}
Ok(())
}

pub fn iter(&self) -> Iter<T, C> {
Expand All @@ -34,14 +67,8 @@ impl<T, const C: usize> StackVec<T, C> {
self.array.fill_with(|| None);
self.len = 0;
}

#[inline]
pub fn capacity(&self) -> usize {
C
}
}


impl<T: PartialEq, const C: usize> PartialEq for StackVec<T, C> {
#[inline]
fn eq(&self, other: &Self) -> bool {
Expand All @@ -52,7 +79,7 @@ impl<T: PartialEq, const C: usize> PartialEq for StackVec<T, C> {
for index in 0..self.len {
let self_item = &self.array[index];
let other_item = &other.array[index];
if self_item.ne(other_item) {
if self_item != other_item {
return false;
}
}
Expand All @@ -61,7 +88,6 @@ impl<T: PartialEq, const C: usize> PartialEq for StackVec<T, C> {
}
}


impl<T: Hash, const C: usize> Hash for StackVec<T, C> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
Expand All @@ -87,21 +113,17 @@ impl<T: Debug, const C: usize> Debug for StackVec<T, C> {
}

#[derive(Debug, Error, PartialEq, Eq)]
#[error("source array len {source_len} exceeds target len {target_len}")]
pub struct ArrayOverflow {
source_len: usize,
target_len: usize,
#[error("exceeds capacity ({target_capacity})")]
pub struct CapacityExceeded {
target_capacity: usize,
}

impl<T, const B: usize, const C: usize> TryFrom<[T; B]> for StackVec<T, C> {
type Error = ArrayOverflow;
type Error = CapacityExceeded;

fn try_from(source: [T; B]) -> Result<Self, Self::Error> {
if B > C {
return Err(ArrayOverflow {
source_len: B,
target_len: C,
});
return Err(CapacityExceeded { target_capacity: C });
}

let mut array: [Option<T>; C] = std::array::from_fn(|_| None);
Expand All @@ -120,22 +142,42 @@ impl<T, const B: usize, const C: usize> TryFrom<[T; B]> for StackVec<T, C> {
// sv
// }

pub mod __macro_support {
use crate::stack_vec::StackVec;

pub fn sv_repeat<T: Clone, const C: usize>(value: T, times: usize) -> StackVec<T, C> {
let mut sv = StackVec::default();
sv.push_repeat(value, times);
sv
}
}

#[macro_export]
macro_rules! sv {
() => (
StackVec::default()
$crate::__rust_force_expr!($crate::stack_vec::StackVec::default())
);
($elem:expr; $n:expr) => (
$crate::__rust_force_expr!($crate::stack_vec::__macro_support::sv_repeat($elem, $n))
);
( $( $x:expr ),* ) => {
($($elem:expr), *) => {
{
let mut sv = StackVec::default();
let mut sv = $crate::stack_vec::StackVec::default();
$(
sv.push($x);
$crate::__rust_force_expr!(sv.push($elem));
)*
sv
}
};
}

#[macro_export]
macro_rules! __rust_force_expr {
($e:expr) => {
$e
};
}

impl<T, const C: usize> Default for StackVec<T, C> {
#[inline]
fn default() -> Self {
Expand Down Expand Up @@ -239,15 +281,14 @@ mod tests {
#[test]
fn init() {
let sv = StackVec::<(), 4>::default();
assert_eq!(4, sv.capacity());
assert!(sv.is_empty());
assert_eq!(0, sv.len());
assert_eq!(None, sv.iter().next());
assert_eq!(None, sv.into_iter().next());
}

#[test]
fn debug() {
fn macro_and_debug() {
{
let sv: StackVec<(), 0> = sv![];
assert_eq!("[]", format!("{sv:?}"));
Expand All @@ -264,6 +305,18 @@ mod tests {
let sv: StackVec<_, 3> = sv!["zero", "one", "two"];
assert_eq!(r#"["zero", "one", "two"]"#, format!("{sv:?}"));
}
{
let sv: StackVec<_, 2> = sv!["zero"; 0];
assert_eq!(r#"[]"#, format!("{sv:?}"));
}
{
let sv: StackVec<_, 2> = sv!["zero"; 1];
assert_eq!(r#"["zero"]"#, format!("{sv:?}"));
}
{
let sv: StackVec<_, 2> = sv!["zero"; 2];
assert_eq!(r#"["zero", "zero"]"#, format!("{sv:?}"));
}
}

#[test]
Expand All @@ -279,7 +332,7 @@ mod tests {
}

#[test]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
#[should_panic(expected = "exceeds capacity (2)")]
fn push_with_overflow() {
let mut sv = StackVec::<_, 2>::default();
sv.push("zero");
Expand Down Expand Up @@ -329,13 +382,7 @@ mod tests {
#[test]
fn from_array_overflow() {
let result = StackVec::<_, 2>::try_from(["zero", "one", "two"]);
assert_eq!(
ArrayOverflow {
source_len: 3,
target_len: 2
},
result.unwrap_err()
);
assert_eq!(CapacityExceeded { target_capacity: 2 }, result.unwrap_err());
}

#[test]
Expand Down Expand Up @@ -376,7 +423,7 @@ mod tests {
}

#[test]
#[should_panic(expected = "the len is 2 but the index is 2")]
#[should_panic(expected = "exceeds capacity (2)")]
fn sv_overflow() {
let _: StackVec<_, 2> = sv!["0", "1", "2"];
}
Expand Down

0 comments on commit bdf661b

Please sign in to comment.