<commit_before>use hand::BJHand;
use bjaction::BJAction;
use bjaction::HIT;
use bjaction::STAND;
use bjaction::DOUBLE;
use bjaction::SURRENDER;
use bjaction::SPLIT;
use cards::card::Card;
use cards::value::VALUES;
use cards::value::ACE;
use cards::value::KING;
use cards::value::QUEEN;
use cards::value::JACK;
use cards::value::TEN;
use rules::BJRules;
use shoe::shoe::DirectShoe;
use shoe::randomshoe::SuitPicker;

pub trait ActionCalculator {
    fn expected_value(&self, h: &mut BJHand, dealer_up_card: &Card,
                      d: &mut DirectShoe, action: BJAction,
                      rules: &BJRules) -> Option<f64>;
    fn expected_with_dealer(&self, player_hand: &BJHand,
                            dealer_hand: &mut BJHand, d: &mut DirectShoe,
                            rules: &BJRules) -> Option<f64>;
    fn expected_value_best_action(&self, hand: &mut BJHand,
                                  dealer_up_card: &Card, d: &mut DirectShoe,
                                  rules: &BJRules) -> f64;
}

pub struct ActionCalculatorImpl;

impl ActionCalculator for ActionCalculatorImpl {
    fn expected_value_best_action(&self, hand: &mut BJHand,
                                  dealer_up_card: &Card, d: &mut DirectShoe,
                                  rules: &BJRules) -> f64 {
        if hand.score() > 21 {
            // Bust... loose bet
            return -1.0;
        }
        let actions = vec![HIT, DOUBLE, SPLIT, SURRENDER];
        let mut best_result = match self.expected_value(
                hand, dealer_up_card, d, STAND, rules) {
            Some(s) => s,
            None => panic!("You should always be able to stand"),
        };
        for &a in actions.iter() {
            match self.expected_value(hand, dealer_up_card, d, a, rules) {
                Some(r) => {
                    if best_result < r {
                        best_result = r;
                    }
                }
                _ => {}
            }
        }
        return best_result;
    }
    fn expected_value(&self, hand: &mut BJHand, dealer_up_card: &Card,
                      d: &mut DirectShoe, action: BJAction,
                      rules: &BJRules) -> Option<f64> {
        return match action {
            HIT => {
                match rules.can_hit(hand) {
                    false => None,
                    true => {
                        let mut final_result = 0.0;
                        for &v in VALUES.iter() {
                            let count_of_val = d.count(&v);
                            if count_of_val > 0 {
                                let odds_of_value = count_of_val as f64 / d.len() as f64;
                                let card_from_deck = match d.remove(&v) {
                                    Some(c) => c,
                                    None => {
                                        panic!("Count positive, but couldn't remove!");
                                    }
                                };
                                hand.add_card(card_from_deck);
                                let ev_with_value = self.expected_value_best_action(
                                    hand, dealer_up_card, d, rules);
                                final_result += odds_of_value * ev_with_value;
                                hand.remove_card(card_from_deck);
                                d.insert(&card_from_deck);
                            }
                        }
                        Some(final_result)
                    }
                }
            }
            STAND => {
                // I guess you can always stand
                let mut dealer_hand = BJHand::new();
                dealer_hand.add_card(*dealer_up_card);
                self.expected_with_dealer(hand, &mut dealer_hand, d, rules)
            }
            DOUBLE => {
                match rules.can_double(hand) {
                    false => None,
                    true => {
                        let mut final_result = 0.0;
                        for &v in VALUES.iter() {
                            let count_of_val = d.count(&v);
                            if count_of_val > 0 {
                                let odds_of_value = count_of_val as f64 / d.len() as f64;
                                let card_from_deck = match d.remove(&v) {
                                    Some(c) => c,
                                    None => {
                                        panic!("Count positive, but couldn't remove!");
                                    }
                                };
                                hand.add_card(card_from_deck);
                                hand.add_double_count();
                                let ev_with_value = 2.0 * self.expected_value_best_action(
                                    hand, dealer_up_card, d, rules);
                                final_result += odds_of_value * ev_with_value;
                                hand.remove_card(card_from_deck);
                                hand.subtract_double_count();
                                d.insert(&card_from_deck);
                            }
                        }
                        Some(final_result)
                    }
                }
            }
            SPLIT => {
                match rules.can_split(hand) {
                    false => None,
                    true => Some(-1.0),
                }
            }
            SURRENDER => {
                match rules.can_surrender(hand) {
                    false => None,
                    true => Some(-0.5),
                }
            }
        }
    }
    fn expected_with_dealer(&self, player_hand: &BJHand,
                            dealer_hand: &mut BJHand, d: &mut DirectShoe,
                            rules: &BJRules) -> Option<f64> {
        if !rules.should_hit_dealer_hand(dealer_hand) {
            let dealer_score = dealer_hand.score();
            let player_score = player_hand.score();
            assert!(player_score <= 21);
            if dealer_score > 21 {
                return Some(1.0);
            } else  if dealer_score > player_score {
                return Some(-1.0);
            } else if dealer_score < player_score {
                return Some(1.0);
            } else {
                return Some(0.0);
            }
        } else {
            // The dealer hits ... takes a random card
            let mut final_result = 0.0;
            let number_of_valid_cards = {
                if rules.dealer_blackjack_after_hand() || dealer_hand.len() != 1 {
                    d.len()
                } else {
                    match dealer_hand.score() {
                        10 => d.len() - d.count(&ACE),
                        11 => d.len() - d.count(&TEN) - d.count(&JACK) - d.count(&QUEEN) -
                           d.count(&KING),
                        _ => d.len()
                    }
                }
            };
            for &v in VALUES.iter() {
                let count_of_val = d.count(&v);
                if count_of_val > 0 {
                    let odds_of_value = count_of_val as f64 / number_of_valid_cards as f64;
                    let card_from_deck = match d.remove(&v) {
                        Some(c) => c,
                        None => {
                            panic!("Count positive, but couldn't remove!");
                        }
                    };
                    assert_eq!(card_from_deck.value().desc(), v.desc());
                    dealer_hand.add_card(card_from_deck);
                    if rules.is_blackjack(dealer_hand) &&
                        !rules.dealer_blackjack_after_hand() {
                            // ignore
                    } else {
                        let ev_with_value = match self.expected_with_dealer(
                            player_hand, dealer_hand, d, rules) {
                                Some(c) => c,
                                None => return None,
                        };
                        final_result += odds_of_value * ev_with_value;
                    }

                    dealer_hand.remove_card(card_from_deck);
                    d.insert(&card_from_deck);
                }
            }
            return Some(final_result);
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use action_calculator::ActionCalculatorImpl;
    use action_calculator::ActionCalculator;
    use self::test::Bencher;
    use cards::value::Value;
    use shoe::shoe::DirectShoe;
    use hand::BJHand;
    use std::num::Float;
    use cards::value;
    use rules::BJRules;

    fn check_value(dealer_cards: &Vec<Value>, player_cards: &Vec<Value>, expected: f64) {
        use shoe::randomshoe::new_infinite_shoe;
        use rules::BJRules;
        let a = ActionCalculatorImpl;
        let rules = BJRules::new();
        let mut shoe = new_infinite_shoe();
        let expansion = 1000000.0f64;
        assert_eq!(
            (a.expected_with_dealer(
                &BJHand::new_from_deck(&mut shoe, player_cards).unwrap(),
                &mut BJHand::new_from_deck(&mut shoe, dealer_cards).unwrap(),
                &mut shoe,
                &rules).unwrap() * expansion).round() as int,
            (expected * expansion) as int);
    }

    fn check_best_value(dealer_up_card: &Value, player_cards: &Vec<Value>, expected: f64) {
        let rules = BJRules::new();
        check_best_value_rules(dealer_up_card, player_cards, expected, &rules);
    }

    fn check_best_value_rules(dealer_up_card: &Value, player_cards: &Vec<Value>, expected: f64,
                             rules: &BJRules) {
        use shoe::randomshoe::new_infinite_shoe;
        let a = ActionCalculatorImpl;
        let mut shoe = new_infinite_shoe();
        let expansion = 1000000.0f64;
        assert_eq!(
            (a.expected_value_best_action(
                &mut BJHand::new_from_deck(&mut shoe, player_cards).unwrap(),
                &shoe.remove(dealer_up_card).unwrap(),
                &mut shoe,
                rules) * expansion).round() as int,
            (expected * expansion) as int);
    }

    #[test]
    fn test_expected_infinite_deck() {
        // Numbers checked against http://wizardofodds.com/games/blackjack/appendix/1/
        check_value(&vec![value::FOUR],  &vec![value::TEN, value::EIGHT]           ,  0.175854);
        check_value(&vec![value::SIX],   &vec![value::TEN, value::SIX]             , -0.153699);
        check_value(&vec![value::SEVEN], &vec![value::TEN, value::TEN]             ,  0.773227);
        check_value(&vec![value::SEVEN], &vec![value::TEN, value::SEVEN]           , -0.106809);
        check_value(&vec![value::NINE],  &vec![value::TEN, value::FIVE]            , -0.543150);
        check_value(&vec![value::TEN],   &vec![value::TEN, value::TEN]             ,  0.554538);
        check_value(&vec![value::TEN],   &vec![value::TEN, value::FIVE, value::SIX],  0.962624);
        check_value(&vec![value::TEN],   &vec![value::TEN, value::SEVEN]           , -0.419721);
        check_value(&vec![value::ACE],   &vec![value::TEN, value::SIX]             , -0.666951);
        check_value(&vec![value::ACE],   &vec![value::TEN, value::EIGHT]           , -0.100199);
    }

    #[test]
    fn test_expected_best_value_surr_16_a() {
        let rules = BJRules::new_complex(true);
        check_best_value_rules(&value::ACE,   &vec![value::TEN, value::SIX], -0.5, &rules);
    }

    #[test]
    fn test_expected_best_value_11_6() {
        check_best_value(&value::SIX,   &vec![value::FIVE, value::SIX], 0.667380);
    }

    #[test]
    fn test_expected_best_value_s18_9() {
        check_best_value(&value::NINE,   &vec![value::ACE, value::SEVEN], -0.100744);
    }

    #[test]
    fn test_expected_best_value_9_2() {
        // HIT
        check_best_value(&value::TWO,   &vec![value::FIVE, value::FOUR], 0.074446);
    }

    #[test]
    fn test_expected_best_value_9_3() {
        // DOUBLE
        check_best_value(&value::THREE,   &vec![value::FIVE, value::FOUR], 0.120816);
    }

    #[test]
    fn test_expected_best_value_18_a() {
        check_best_value(&value::ACE,    &vec![value::TEN, value::EIGHT]           , -0.100199);
    }

    #[test]
    fn test_expected_best_value_21_2() {
        check_value(&vec![value::TWO],   &vec![value::TEN, value::FIVE, value::SIX],  0.882007);
        check_value(&vec![value::TWO],   &vec![value::TEN, value::TEN]             ,  0.639987);
    }

    #[test]
    fn test_expected_best_value_15_9() {
        check_best_value(&value::NINE,  &vec![value::TEN, value::FIVE]             , -0.471578);
    }

    #[test]
    fn test_expected_best_value_16_7() {
        check_best_value(&value::SEVEN,  &vec![value::TEN, value::SIX]             , -0.414779);
    }

    #[test]
    fn test_expected_best_value_20_10() {
        check_value(&vec![value::TEN],   &vec![value::TEN, value::TEN]             ,  0.554538);
    }

    #[bench]
    fn bench_with_calc(b: &mut Bencher) {
        use cards::value;
        b.iter(|| {
            check_best_value(&value::SEVEN,  &vec![value::TEN, value::SIX]             , -0.414779);
        });
    }
}
<commit_msg>Support latest<commit_after>use hand::BJHand;
use bjaction::BJAction;
use bjaction::BJAction::HIT;
use bjaction::BJAction::STAND;
use bjaction::BJAction::DOUBLE;
use bjaction::BJAction::SURRENDER;
use bjaction::BJAction::SPLIT;
use cards::card::Card;
use cards::value::VALUES;
use cards::value::ACE;
use cards::value::KING;
use cards::value::QUEEN;
use cards::value::JACK;
use cards::value::TEN;
use rules::BJRules;
use shoe::shoe::DirectShoe;
use shoe::randomshoe::SuitPicker;

pub trait ActionCalculator {
    fn expected_value(&self, h: &mut BJHand, dealer_up_card: &Card,
                      d: &mut DirectShoe, action: BJAction,
                      rules: &BJRules) -> Option<f64>;
    fn expected_with_dealer(&self, player_hand: &BJHand,
                            dealer_hand: &mut BJHand, d: &mut DirectShoe,
                            rules: &BJRules) -> Option<f64>;
    fn expected_value_best_action(&self, hand: &mut BJHand,
                                  dealer_up_card: &Card, d: &mut DirectShoe,
                                  rules: &BJRules) -> f64;
}

pub struct ActionCalculatorImpl;

impl ActionCalculator for ActionCalculatorImpl {
    fn expected_value_best_action(&self, hand: &mut BJHand,
                                  dealer_up_card: &Card, d: &mut DirectShoe,
                                  rules: &BJRules) -> f64 {
        if hand.score() > 21 {
            // Bust... loose bet
            return -1.0;
        }
        let actions = vec![HIT, DOUBLE, SPLIT, SURRENDER];
        let mut best_result = match self.expected_value(
                hand, dealer_up_card, d, STAND, rules) {
            Some(s) => s,
            None => panic!("You should always be able to stand"),
        };
        for &a in actions.iter() {
            match self.expected_value(hand, dealer_up_card, d, a, rules) {
                Some(r) => {
                    if best_result < r {
                        best_result = r;
                    }
                }
                _ => {}
            }
        }
        return best_result;
    }
    fn expected_value(&self, hand: &mut BJHand, dealer_up_card: &Card,
                      d: &mut DirectShoe, action: BJAction,
                      rules: &BJRules) -> Option<f64> {
        return match action {
            HIT => {
                match rules.can_hit(hand) {
                    false => None,
                    true => {
                        let mut final_result = 0.0;
                        for &v in VALUES.iter() {
                            let count_of_val = d.count(&v);
                            if count_of_val > 0 {
                                let odds_of_value = count_of_val as f64 / d.len() as f64;
                                let card_from_deck = match d.remove(&v) {
                                    Some(c) => c,
                                    None => {
                                        panic!("Count positive, but couldn't remove!");
                                    }
                                };
                                hand.add_card(card_from_deck);
                                let ev_with_value = self.expected_value_best_action(
                                    hand, dealer_up_card, d, rules);
                                final_result += odds_of_value * ev_with_value;
                                hand.remove_card(card_from_deck);
                                d.insert(&card_from_deck);
                            }
                        }
                        Some(final_result)
                    }
                }
            }
            STAND => {
                // I guess you can always stand
                let mut dealer_hand = BJHand::new();
                dealer_hand.add_card(*dealer_up_card);
                self.expected_with_dealer(hand, &mut dealer_hand, d, rules)
            }
            DOUBLE => {
                match rules.can_double(hand) {
                    false => None,
                    true => {
                        let mut final_result = 0.0;
                        for &v in VALUES.iter() {
                            let count_of_val = d.count(&v);
                            if count_of_val > 0 {
                                let odds_of_value = count_of_val as f64 / d.len() as f64;
                                let card_from_deck = match d.remove(&v) {
                                    Some(c) => c,
                                    None => {
                                        panic!("Count positive, but couldn't remove!");
                                    }
                                };
                                hand.add_card(card_from_deck);
                                hand.add_double_count();
                                let ev_with_value = 2.0 * self.expected_value_best_action(
                                    hand, dealer_up_card, d, rules);
                                final_result += odds_of_value * ev_with_value;
                                hand.remove_card(card_from_deck);
                                hand.subtract_double_count();
                                d.insert(&card_from_deck);
                            }
                        }
                        Some(final_result)
                    }
                }
            }
            SPLIT => {
                match rules.can_split(hand) {
                    false => None,
                    true => Some(-1.0),
                }
            }
            SURRENDER => {
                match rules.can_surrender(hand) {
                    false => None,
                    true => Some(-0.5),
                }
            }
        }
    }
    fn expected_with_dealer(&self, player_hand: &BJHand,
                            dealer_hand: &mut BJHand, d: &mut DirectShoe,
                            rules: &BJRules) -> Option<f64> {
        if !rules.should_hit_dealer_hand(dealer_hand) {
            let dealer_score = dealer_hand.score();
            let player_score = player_hand.score();
            assert!(player_score <= 21);
            if dealer_score > 21 {
                return Some(1.0);
            } else  if dealer_score > player_score {
                return Some(-1.0);
            } else if dealer_score < player_score {
                return Some(1.0);
            } else {
                return Some(0.0);
            }
        } else {
            // The dealer hits ... takes a random card
            let mut final_result = 0.0;
            let number_of_valid_cards = {
                if rules.dealer_blackjack_after_hand() || dealer_hand.len() != 1 {
                    d.len()
                } else {
                    match dealer_hand.score() {
                        10 => d.len() - d.count(&ACE),
                        11 => d.len() - d.count(&TEN) - d.count(&JACK) - d.count(&QUEEN) -
                           d.count(&KING),
                        _ => d.len()
                    }
                }
            };
            for &v in VALUES.iter() {
                let count_of_val = d.count(&v);
                if count_of_val > 0 {
                    let odds_of_value = count_of_val as f64 / number_of_valid_cards as f64;
                    let card_from_deck = match d.remove(&v) {
                        Some(c) => c,
                        None => {
                            panic!("Count positive, but couldn't remove!");
                        }
                    };
                    assert_eq!(card_from_deck.value().desc(), v.desc());
                    dealer_hand.add_card(card_from_deck);
                    if rules.is_blackjack(dealer_hand) &&
                        !rules.dealer_blackjack_after_hand() {
                            // ignore
                    } else {
                        let ev_with_value = match self.expected_with_dealer(
                            player_hand, dealer_hand, d, rules) {
                                Some(c) => c,
                                None => return None,
                        };
                        final_result += odds_of_value * ev_with_value;
                    }

                    dealer_hand.remove_card(card_from_deck);
                    d.insert(&card_from_deck);
                }
            }
            return Some(final_result);
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use action_calculator::ActionCalculatorImpl;
    use action_calculator::ActionCalculator;
    use self::test::Bencher;
    use cards::value::Value;
    use shoe::shoe::DirectShoe;
    use hand::BJHand;
    use std::num::Float;
    use cards::value;
    use rules::BJRules;

    fn check_value(dealer_cards: &Vec<Value>, player_cards: &Vec<Value>, expected: f64) {
        use shoe::randomshoe::new_infinite_shoe;
        use rules::BJRules;
        let a = ActionCalculatorImpl;
        let rules = BJRules::new();
        let mut shoe = new_infinite_shoe();
        let expansion = 1000000.0f64;
        assert_eq!(
            (a.expected_with_dealer(
                &BJHand::new_from_deck(&mut shoe, player_cards).unwrap(),
                &mut BJHand::new_from_deck(&mut shoe, dealer_cards).unwrap(),
                &mut shoe,
                &rules).unwrap() * expansion).round() as int,
            (expected * expansion) as int);
    }

    fn check_best_value(dealer_up_card: &Value, player_cards: &Vec<Value>, expected: f64) {
        let rules = BJRules::new();
        check_best_value_rules(dealer_up_card, player_cards, expected, &rules);
    }

    fn check_best_value_rules(dealer_up_card: &Value, player_cards: &Vec<Value>, expected: f64,
                             rules: &BJRules) {
        use shoe::randomshoe::new_infinite_shoe;
        let a = ActionCalculatorImpl;
        let mut shoe = new_infinite_shoe();
        let expansion = 1000000.0f64;
        assert_eq!(
            (a.expected_value_best_action(
                &mut BJHand::new_from_deck(&mut shoe, player_cards).unwrap(),
                &shoe.remove(dealer_up_card).unwrap(),
                &mut shoe,
                rules) * expansion).round() as int,
            (expected * expansion) as int);
    }

    #[test]
    fn test_expected_infinite_deck() {
        // Numbers checked against http://wizardofodds.com/games/blackjack/appendix/1/
        check_value(&vec![value::FOUR],  &vec![value::TEN, value::EIGHT]           ,  0.175854);
        check_value(&vec![value::SIX],   &vec![value::TEN, value::SIX]             , -0.153699);
        check_value(&vec![value::SEVEN], &vec![value::TEN, value::TEN]             ,  0.773227);
        check_value(&vec![value::SEVEN], &vec![value::TEN, value::SEVEN]           , -0.106809);
        check_value(&vec![value::NINE],  &vec![value::TEN, value::FIVE]            , -0.543150);
        check_value(&vec![value::TEN],   &vec![value::TEN, value::TEN]             ,  0.554538);
        check_value(&vec![value::TEN],   &vec![value::TEN, value::FIVE, value::SIX],  0.962624);
        check_value(&vec![value::TEN],   &vec![value::TEN, value::SEVEN]           , -0.419721);
        check_value(&vec![value::ACE],   &vec![value::TEN, value::SIX]             , -0.666951);
        check_value(&vec![value::ACE],   &vec![value::TEN, value::EIGHT]           , -0.100199);
    }

    #[test]
    fn test_expected_best_value_surr_16_a() {
        let rules = BJRules::new_complex(true);
        check_best_value_rules(&value::ACE,   &vec![value::TEN, value::SIX], -0.5, &rules);
    }

    #[test]
    fn test_expected_best_value_11_6() {
        check_best_value(&value::SIX,   &vec![value::FIVE, value::SIX], 0.667380);
    }

    #[test]
    fn test_expected_best_value_s18_9() {
        check_best_value(&value::NINE,   &vec![value::ACE, value::SEVEN], -0.100744);
    }

    #[test]
    fn test_expected_best_value_9_2() {
        // HIT
        check_best_value(&value::TWO,   &vec![value::FIVE, value::FOUR], 0.074446);
    }

    #[test]
    fn test_expected_best_value_9_3() {
        // DOUBLE
        check_best_value(&value::THREE,   &vec![value::FIVE, value::FOUR], 0.120816);
    }

    #[test]
    fn test_expected_best_value_18_a() {
        check_best_value(&value::ACE,    &vec![value::TEN, value::EIGHT]           , -0.100199);
    }

    #[test]
    fn test_expected_best_value_21_2() {
        check_value(&vec![value::TWO],   &vec![value::TEN, value::FIVE, value::SIX],  0.882007);
        check_value(&vec![value::TWO],   &vec![value::TEN, value::TEN]             ,  0.639987);
    }

    #[test]
    fn test_expected_best_value_15_9() {
        check_best_value(&value::NINE,  &vec![value::TEN, value::FIVE]             , -0.471578);
    }

    #[test]
    fn test_expected_best_value_16_7() {
        check_best_value(&value::SEVEN,  &vec![value::TEN, value::SIX]             , -0.414779);
    }

    #[test]
    fn test_expected_best_value_20_10() {
        check_value(&vec![value::TEN],   &vec![value::TEN, value::TEN]             ,  0.554538);
    }

    #[bench]
    fn bench_with_calc(b: &mut Bencher) {
        use cards::value;
        b.iter(|| {
            check_best_value(&value::SEVEN,  &vec![value::TEN, value::SIX]             , -0.414779);
        });
    }
}
<|endoftext|>


<commit_before>//! Implements `Multipv`.

use std::cmp::{min, max};
use std::time::Duration;
use std::sync::{Arc, RwLock};
use std::sync::mpsc::TryRecvError;
use uci::{SetOption, OptionDescription};
use moves::Move;
use value::*;
use depth::*;
use hash_table::*;
use evaluator::Evaluator;
use search_node::SearchNode;
use search_executor::{SearchParams, SearchReport, SearchExecutor};
use time_manager::RemainingTime;
use super::{bogus_params, contains_dups};
use super::aspiration::Aspiration;

/// Executes mulit-PV searches with aspiration windows.
///
/// The final progress report will contain the `searchmoves` vector
/// sorted by descending move strength.
pub struct Multipv<T: SearchExecutor> {
    tt: Arc<T::HashTable>,
    params: SearchParams<T::SearchNode>,
    search_is_terminated: bool,
    previously_searched_nodes: u64,

    // The real work will be handed over to `searcher`.
    searcher: Aspiration<T>,

    // The number of best lines of play that are being calculated.
    variation_count: usize,

    // Whether all legal moves in the root position are considered.
    all_moves_are_considered: bool,

    // The index in `self.params.searchmoves` of the currently
    // considered move.
    current_move_index: usize,

    // The values for the corresponding moves in `self.params.searchmoves`.
    values: Vec<Value>,
}

impl<T: SearchExecutor> SearchExecutor for Multipv<T> {
    type HashTable = T::HashTable;

    type SearchNode = T::SearchNode;

    type ReportData = Vec<Move>;

    fn new(tt: Arc<Self::HashTable>) -> Multipv<T> {
        Multipv {
            tt: tt.clone(),
            params: bogus_params(),
            search_is_terminated: false,
            previously_searched_nodes: 0,
            searcher: Aspiration::new(tt),
            variation_count: 1,
            all_moves_are_considered: true,
            current_move_index: 0,
            values: vec![VALUE_MIN],
        }
    }

    fn start_search(&mut self, params: SearchParams<T::SearchNode>, _: Option<&RemainingTime>) {
        debug_assert!(params.depth > 0);
        debug_assert!(params.depth <= DEPTH_MAX);
        debug_assert!(params.lower_bound >= VALUE_MIN);
        debug_assert!(params.upper_bound <= VALUE_MAX);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(!contains_dups(&params.searchmoves));

        let n = params.searchmoves.len();
        self.variation_count = min(n, *VARIATION_COUNT.read().unwrap());
        self.all_moves_are_considered = n == params.position.legal_moves().len();
        if n == 0 || self.variation_count == 1 && self.all_moves_are_considered {
            // An aspiration-only search.
            debug_assert!(self.variation_count <= 1);
            self.searcher.lmr_mode = false;
            self.searcher.start_search(params, None);
        } else {
            // A genuine multi-PV search.
            debug_assert!(self.variation_count >= 1);
            self.searcher.lmr_mode = true;
            self.params = params;
            self.search_is_terminated = false;
            self.previously_searched_nodes = 0;
            self.current_move_index = 0;
            self.values = vec![VALUE_MIN; n];
            self.search_current_move();
        }
    }

    fn try_recv_report(&mut self) -> Result<SearchReport<Self::ReportData>, TryRecvError> {
        if self.genuine_multipv() {
            let SearchReport { searched_nodes, value, done, .. } = try!(self.searcher
                                                                            .try_recv_report());
            let mut report = SearchReport {
                search_id: self.params.search_id,
                searched_nodes: self.previously_searched_nodes + searched_nodes,
                depth: 0,
                value: VALUE_UNKNOWN,
                data: vec![],
                done: done,
            };
            if done && !self.search_is_terminated {
                self.previously_searched_nodes = report.searched_nodes;
                self.params.position.undo_last_move();
                self.change_current_move(-value);
                if self.search_current_move() {
                    report.done = false;
                } else {
                    report.depth = self.params.depth;
                    report.value = self.values[0];
                    report.data = self.params.searchmoves.clone();
                }
            }
            Ok(report)
        } else {
            self.searcher.try_recv_report()
        }
    }

    fn wait_report(&self, duration: Duration) {
        self.searcher.wait_report(duration);
    }

    fn terminate_search(&mut self) {
        self.search_is_terminated = true;
        self.searcher.terminate_search();
    }
}

impl<T: SearchExecutor> SetOption for Multipv<T> {
    fn options() -> Vec<(String, OptionDescription)> {
        let mut options = vec![
            ("MultiPV".to_string(), OptionDescription::Spin { min: 1, max: 500, default: 1 }),
        ];
        options.extend(Aspiration::<T>::options());
        options
    }

    fn set_option(name: &str, value: &str) {
        if name == "MultiPV" {
            *VARIATION_COUNT.write().unwrap() = max(value.parse::<usize>().unwrap_or(0), 1);
        }
        Aspiration::<T>::set_option(name, value)
    }
}

impl<T: SearchExecutor> Multipv<T> {
    /// Returns the number of best lines of play that are being
    /// calculated.
    #[inline]
    pub fn variation_count(&self) -> usize {
        self.variation_count
    }

    /// Returns if the current search is a genuine multi-PV search.
    ///
    /// A search is not a genuine multi-PV search if all legal moves
    /// in the root position are being considered, and the number of
    /// best lines of play that are being calculated is zero or one.
    #[inline]
    pub fn genuine_multipv(&self) -> bool {
        self.searcher.lmr_mode
    }

    fn search_current_move(&mut self) -> bool {
        if self.current_move_index < self.params.searchmoves.len() {
            let alpha = self.values[self.variation_count - 1];
            if alpha < self.params.upper_bound {
                assert!(self.params
                            .position
                            .do_move(self.params.searchmoves[self.current_move_index]));
                self.previously_searched_nodes += 1;
                self.searcher.start_search(SearchParams {
                                               search_id: 0,
                                               depth: self.params.depth - 1,
                                               lower_bound: -self.params.upper_bound,
                                               upper_bound: -max(alpha, self.params.lower_bound),
                                               searchmoves: self.params.position.legal_moves(),
                                               ..self.params.clone()
                                           },
                                           None);
                return true;
            }
        }
        self.write_reslut_to_tt();
        false
    }

    fn write_reslut_to_tt(&self) {
        let best_move = self.params.searchmoves[0];
        let value = self.values[0];
        let bound = match value {
            v if v <= self.params.lower_bound && !self.all_moves_are_considered => BOUND_NONE,
            v if v <= self.params.lower_bound => BOUND_UPPER,
            v if v >= self.params.upper_bound || !self.all_moves_are_considered => BOUND_LOWER,
            _ => BOUND_EXACT,
        };
        let p = &self.params.position;
        let static_eval = p.evaluator().evaluate(p.board());
        self.tt.store(p.hash(), <T::HashTable as HashTable>::Entry::with_static_eval(
                value, bound, self.params.depth, best_move.digest(), static_eval));
    }

    fn change_current_move(&mut self, v: Value) {
        debug_assert!(v >= self.values[self.current_move_index]);
        let mut i = self.current_move_index;
        self.current_move_index += 1;

        // Update `self.values`, making sure that it remains sorted.
        self.values[i] = v;
        while i > 0 && v > self.values[i - 1] {
            self.values.swap(i, i - 1);
            self.params.searchmoves.swap(i, i - 1);
            i -= 1;
        }
    }
}

lazy_static! {
    static ref VARIATION_COUNT: RwLock<usize> = RwLock::new(1);
}
<commit_msg>improve Multipv::write_result_to_tt()<commit_after>//! Implements `Multipv`.

use std::cmp::{min, max};
use std::time::Duration;
use std::sync::{Arc, RwLock};
use std::sync::mpsc::TryRecvError;
use uci::{SetOption, OptionDescription};
use moves::Move;
use value::*;
use depth::*;
use hash_table::*;
use evaluator::Evaluator;
use search_node::SearchNode;
use search_executor::{SearchParams, SearchReport, SearchExecutor};
use time_manager::RemainingTime;
use super::{bogus_params, contains_dups};
use super::aspiration::Aspiration;

/// Executes mulit-PV searches with aspiration windows.
///
/// The final progress report will contain the `searchmoves` vector
/// sorted by descending move strength.
pub struct Multipv<T: SearchExecutor> {
    tt: Arc<T::HashTable>,
    params: SearchParams<T::SearchNode>,
    search_is_terminated: bool,
    previously_searched_nodes: u64,

    // The real work will be handed over to `searcher`.
    searcher: Aspiration<T>,

    // The number of best lines of play that are being calculated.
    variation_count: usize,

    // Whether all legal moves in the root position are considered.
    all_moves_are_considered: bool,

    // The index in `self.params.searchmoves` of the currently
    // considered move.
    current_move_index: usize,

    // The values for the corresponding moves in `self.params.searchmoves`.
    values: Vec<Value>,
}

impl<T: SearchExecutor> SearchExecutor for Multipv<T> {
    type HashTable = T::HashTable;

    type SearchNode = T::SearchNode;

    type ReportData = Vec<Move>;

    fn new(tt: Arc<Self::HashTable>) -> Multipv<T> {
        Multipv {
            tt: tt.clone(),
            params: bogus_params(),
            search_is_terminated: false,
            previously_searched_nodes: 0,
            searcher: Aspiration::new(tt),
            variation_count: 1,
            all_moves_are_considered: true,
            current_move_index: 0,
            values: vec![VALUE_MIN],
        }
    }

    fn start_search(&mut self, params: SearchParams<T::SearchNode>, _: Option<&RemainingTime>) {
        debug_assert!(params.depth > 0);
        debug_assert!(params.depth <= DEPTH_MAX);
        debug_assert!(params.lower_bound >= VALUE_MIN);
        debug_assert!(params.upper_bound <= VALUE_MAX);
        debug_assert!(params.lower_bound < params.upper_bound);
        debug_assert!(!contains_dups(&params.searchmoves));

        let n = params.searchmoves.len();
        self.variation_count = min(n, *VARIATION_COUNT.read().unwrap());
        self.all_moves_are_considered = n == params.position.legal_moves().len();
        if n == 0 || self.variation_count == 1 && self.all_moves_are_considered {
            // An aspiration-only search.
            debug_assert!(self.variation_count <= 1);
            self.searcher.lmr_mode = false;
            self.searcher.start_search(params, None);
        } else {
            // A genuine multi-PV search.
            debug_assert!(self.variation_count >= 1);
            self.searcher.lmr_mode = true;
            self.params = params;
            self.search_is_terminated = false;
            self.previously_searched_nodes = 0;
            self.current_move_index = 0;
            self.values = vec![VALUE_MIN; n];
            self.search_current_move();
        }
    }

    fn try_recv_report(&mut self) -> Result<SearchReport<Self::ReportData>, TryRecvError> {
        if self.genuine_multipv() {
            let SearchReport { searched_nodes, value, done, .. } = try!(self.searcher
                                                                            .try_recv_report());
            let mut report = SearchReport {
                search_id: self.params.search_id,
                searched_nodes: self.previously_searched_nodes + searched_nodes,
                depth: 0,
                value: VALUE_UNKNOWN,
                data: vec![],
                done: done,
            };
            if done && !self.search_is_terminated {
                self.previously_searched_nodes = report.searched_nodes;
                self.params.position.undo_last_move();
                self.change_current_move(-value);
                if self.search_current_move() {
                    report.done = false;
                } else {
                    report.depth = self.params.depth;
                    report.value = self.values[0];
                    report.data = self.params.searchmoves.clone();
                }
            }
            Ok(report)
        } else {
            self.searcher.try_recv_report()
        }
    }

    fn wait_report(&self, duration: Duration) {
        self.searcher.wait_report(duration);
    }

    fn terminate_search(&mut self) {
        self.search_is_terminated = true;
        self.searcher.terminate_search();
    }
}

impl<T: SearchExecutor> SetOption for Multipv<T> {
    fn options() -> Vec<(String, OptionDescription)> {
        let mut options = vec![
            ("MultiPV".to_string(), OptionDescription::Spin { min: 1, max: 500, default: 1 }),
        ];
        options.extend(Aspiration::<T>::options());
        options
    }

    fn set_option(name: &str, value: &str) {
        if name == "MultiPV" {
            *VARIATION_COUNT.write().unwrap() = max(value.parse::<usize>().unwrap_or(0), 1);
        }
        Aspiration::<T>::set_option(name, value)
    }
}

impl<T: SearchExecutor> Multipv<T> {
    /// Returns the number of best lines of play that are being
    /// calculated.
    #[inline]
    pub fn variation_count(&self) -> usize {
        self.variation_count
    }

    /// Returns if the current search is a genuine multi-PV search.
    ///
    /// A search is not a genuine multi-PV search if all legal moves
    /// in the root position are being considered, and the number of
    /// best lines of play that are being calculated is zero or one.
    #[inline]
    pub fn genuine_multipv(&self) -> bool {
        self.searcher.lmr_mode
    }

    fn search_current_move(&mut self) -> bool {
        if self.current_move_index < self.params.searchmoves.len() {
            let alpha = self.values[self.variation_count - 1];
            if alpha < self.params.upper_bound {
                assert!(self.params
                            .position
                            .do_move(self.params.searchmoves[self.current_move_index]));
                self.previously_searched_nodes += 1;
                self.searcher.start_search(SearchParams {
                                               search_id: 0,
                                               depth: self.params.depth - 1,
                                               lower_bound: -self.params.upper_bound,
                                               upper_bound: -max(alpha, self.params.lower_bound),
                                               searchmoves: self.params.position.legal_moves(),
                                               ..self.params.clone()
                                           },
                                           None);
                return true;
            }
        }
        self.write_reslut_to_tt();
        false
    }

    fn write_reslut_to_tt(&self) {
        if self.all_moves_are_considered {
            let p = &self.params.position;
            let value = self.values[0];
            let bound = match value {
                v if v <= self.params.lower_bound => BOUND_UPPER,
                v if v >= self.params.upper_bound => BOUND_LOWER,
                _ => BOUND_EXACT,
            };
            let best_move = self.params.searchmoves[0];
            let static_eval = p.evaluator().evaluate(p.board());
            self.tt.store(p.hash(), <T::HashTable as HashTable>::Entry::with_static_eval(
                value, bound, self.params.depth, best_move.digest(), static_eval));
        }
    }

    fn change_current_move(&mut self, v: Value) {
        debug_assert!(v >= self.values[self.current_move_index]);
        let mut i = self.current_move_index;
        self.current_move_index += 1;

        // Update `self.values`, making sure that it remains sorted.
        self.values[i] = v;
        while i > 0 && v > self.values[i - 1] {
            self.values.swap(i, i - 1);
            self.params.searchmoves.swap(i, i - 1);
            i -= 1;
        }
    }
}

lazy_static! {
    static ref VARIATION_COUNT: RwLock<usize> = RwLock::new(1);
}
<|endoftext|>


<commit_before>use std::sync::{Mutex, MutexGuard};
use std::hash::{Hash, SipHasher, Hasher};

pub struct ShardMutex {
    mutex: Vec<Mutex<()>>,
    size: usize,
}

impl ShardMutex {
    pub fn new(size: usize) -> ShardMutex {
        ShardMutex {
            mutex: (0..size).map(|_| Mutex::new(())).collect(),
            size: size,
        }
    }

    pub fn lock<H>(&self, keys: &[H]) -> Vec<MutexGuard<()>>
        where H: Hash
    {
        let mut indices: Vec<usize> = keys.iter().map(|x| self.shard_index(x)).collect();
        indices.sort();
        indices.dedup();
        indices.iter().map(|&i| self.mutex[i].lock().unwrap()).collect()
    }

    fn shard_index<H>(&self, key: &H) -> usize
        where H: Hash
    {
        let mut s = SipHasher::new();
        key.hash(&mut s);
        (s.finish() as usize) % self.size
    }
}
<commit_msg>storage/txn: add test for ShardMutex<commit_after>use std::sync::{Mutex, MutexGuard};
use std::hash::{Hash, SipHasher, Hasher};

pub struct ShardMutex {
    mutex: Vec<Mutex<()>>,
    size: usize,
}

impl ShardMutex {
    pub fn new(size: usize) -> ShardMutex {
        ShardMutex {
            mutex: (0..size).map(|_| Mutex::new(())).collect(),
            size: size,
        }
    }

    pub fn lock<H>(&self, keys: &[H]) -> Vec<MutexGuard<()>>
        where H: Hash
    {
        let mut indices: Vec<usize> = keys.iter().map(|x| self.shard_index(x)).collect();
        indices.sort();
        indices.dedup();
        indices.iter().map(|&i| self.mutex[i].lock().unwrap()).collect()
    }

    fn shard_index<H>(&self, key: &H) -> usize
        where H: Hash
    {
        let mut s = SipHasher::new();
        key.hash(&mut s);
        (s.finish() as usize) % self.size
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use std::thread;
    use std::time::Duration;
    use rand;
    use super::*;

    #[test]
    fn test_shard_mutex_deadlock() {
        const MUTEX_SIZE: usize = 10;
        const THREAD_NUM: usize = 10;
        const VALUE_NUM: usize = 10;
        const VALUE_RANGE: usize = 30;

        let sm = Arc::new(ShardMutex::new(MUTEX_SIZE));
        let mut children = vec![];
        for _ in 0..THREAD_NUM {
            let sm = sm.clone();
            children.push(thread::spawn(move || {
                let values: Vec<i32> = (0..VALUE_NUM)
                                           .map(|_| rand::random::<i32>() % VALUE_RANGE as i32)
                                           .collect();
                let _guard = sm.lock(&values);
                thread::sleep(Duration::from_millis(1));
            }));
        }
        for t in children {
            t.join().unwrap();
        }
    }
}
<|endoftext|>


<commit_before>// run-pass
// compile-flags: -Z no-landing-pads -C codegen-units=1
// ignore-emscripten no threads support

use std::thread;

static mut HIT: bool = false;

struct A;

impl Drop for A {
    fn drop(&mut self) {
        unsafe { HIT = true; }
    }
}

fn main() {
    thread::spawn(move|| -> () {
        let _a = A;
        panic!();
    }).join().unwrap_err();
    assert!(unsafe { !HIT });
}
<commit_msg>Ignore broken no-landing-pads test<commit_after>// run-pass
// compile-flags: -Z no-landing-pads -C codegen-units=1
// ignore-emscripten no threads support
// ignore-test fails because catch_unwind doesn't work with no-landing-pads

use std::thread;

static mut HIT: bool = false;

struct A;

impl Drop for A {
    fn drop(&mut self) {
        unsafe { HIT = true; }
    }
}

fn main() {
    thread::spawn(move|| -> () {
        let _a = A;
        panic!();
    }).join().unwrap_err();
    assert!(unsafe { !HIT });
}
<|endoftext|>


<commit_before>
use geometry::Point;
use core::rand::RngUtil;
use core::float::pow;
mod geometry;

//
// Cellule
//

struct Cell {
    center: Point,
    id: uint,
    radius: f64,
    velocity: Point,
    acc: Point,
    generation: uint,
    age: uint
}

pub impl Cell {
    fn new(ident: uint) -> Cell {
        let radius = 1.0;
        //let r=rand::random::<float>();
        //io::println(fmt!("%f\n", r));
        let center : Point =rand::random();

        Cell{ center: center, id: ident, radius: radius, velocity: Point::new(), acc: Point::new(), generation: 0, age:0}
    }

    fn move(&mut self, tumeur: &Crowd, dt: f64) {
        let old_acc = copy self.acc;

        // Nouvelle position
        self.center+=self.velocity+self.acc*(0.5*float::pow(dt,2.0) as f64);

        // Force aléatoire
        let mut F_alea: Point=rand::random();
        F_alea-=0.5 as f64;
        self.acc=self.calc_rep_force(tumeur)+F_alea*(0.05 as f64);

        // Nouvelle vitesse
        let lambda : f64=5.0;
        let denom : f64 = 1.0/(1.0+lambda*dt/2.0);
        self.velocity=(self.velocity*(1.0-lambda*dt/2.0)+(self.acc+old_acc)*dt/(2.0 as f64))*denom;

    }

    fn replicate(&mut self, tumeur: &Crowd, dt: f64) {
        io::println(fmt!("%d @ %f\n",tumeur.size() as int, dt as float));

        self.age+=1;
    }

    fn calc_rep_force(&self, tumeur: &Crowd) -> Point {
        let seuil=3.0*self.radius;
        let mut force = Point::new();
        for tumeur.cells.each |&cell| {
            if(cell.id != self.id) {
                let dist_cells=(self.dist(cell)+2.0*self.radius)/seuil;
                let factor = 1.0/pow(dist_cells,3.0)*1e-5 as f64;
                force += (self.center-cell.center)*factor;
            }
        }
        force
    }

    #[inline(always)]
    fn x(&self) -> f64 {
        self.center.x
    }

    #[inline(always)]
    fn y(&self) -> f64 {
        self.center.y
    }

    fn dist(&self, other: &Cell) -> f64 {
        self.center.dist(&other.center)
    }

}

impl ToStr for Cell {
    fn to_str(&self) -> ~str {
        fmt!("%d @ (%f, %f)", self.id as int, self.center.x as float, self.center.y as float)
    }
}

#[test]
fn test_new() {
    let cell1=Cell::new(0);
    let cell2=Cell::new(1);
    assert!(cell1.center != cell2.center);
}

//
// Population
//

struct Crowd {
    cells : ~[@mut Cell],
    time : float
}

pub impl Crowd {
    fn new(init_pop : uint) -> Crowd {

        let mut pop : ~[@mut Cell]=~[];
        for uint::range(1,init_pop+1) |num| {
            let lonely_one = @mut Cell::new(num);
            pop.push(copy lonely_one);
        }
        Crowd{ cells : pop, time: 0.0}
    }

    fn size(&self) -> uint {
        self.cells.len()
    }

    fn evolve(&self, dt: f64) {
        for self.cells.each |cell| {
            cell.move(self, dt);
        }
    }
}

impl ToStr for Crowd {
    fn to_str(&self) -> ~str {
        let mut desc =~"";
        for self.cells.each |cell| {
            let mut lcell_desc=~"";
            lcell_desc.push_str(cell.to_str()); lcell_desc.push_str("\n");
             desc.push_str(lcell_desc);
        }
        desc
    }
}

#[test]
fn test_size() {
    let crowd=Crowd::new(13);
    assert!(crowd.size()==13);
}
<commit_msg>Calcul des forces : attraction + répulsion<commit_after>
use geometry::Point;
use core::rand::RngUtil;
use core::float::pow;
mod geometry;

//
// Cellule
//

struct Cell {
    center: Point,
    id: uint,
    radius: f64,
    velocity: Point,
    acc: Point,
    generation: uint,
    age: uint
}

pub impl Cell {
    fn new(ident: uint) -> Cell {
        let radius = 1.0;
        //let r=rand::random::<float>();
        //io::println(fmt!("%f\n", r));
        let center : Point =rand::random();

        Cell{ center: center, id: ident, radius: radius, velocity: Point::new(), acc: Point::new(), generation: 0, age:0}
    }

    fn move(&mut self, tumeur: &Crowd, dt: f64) {
        let old_acc = copy self.acc;

        // Nouvelle position
        self.center+=self.velocity+self.acc*(0.5*pow(dt,2.0) as f64);

        // Force aléatoire
        let F_alea= Point::new_dir();

        // Nouvelle accélération
        self.acc=self.calc_forces(tumeur)+F_alea*0.01f64;

        // Nouvelle vitesse ( + frottement)
        let lambda : f64=10.0;
        let denom : f64 = 1.0/(1.0+lambda*dt/2.0);
        self.velocity=(self.velocity*(1.0-lambda*dt/2.0)+(self.acc+old_acc)*dt/(2.0 as f64))*denom;

    }

    fn replicate(&mut self, tumeur: &Crowd, dt: f64) -> Option<@mut Cell> {
        //io::println(fmt!("%d @ %f\n",tumeur.size() as int, dt as float));
        self.age+=1;
        // if((self.age==50) && (rand::random::<f64>() > 0.9f64)) {
        //     let new_center=self.center + Point::new_dir()*0.001f64;
        //     self.age=0;
        //     Some(@mut Cell{center: new_center, id: tumeur.size()+1, radius: self.radius, velocity: self.velocity*-1.0f64, acc: self.acc, generation: self.generation+1, age:0 })
        // }
        // else {
            None
        // }
    }

    fn calc_forces(&self, tumeur: &Crowd) -> Point {
        let seuil=3.0*self.radius;
        let mut force = Point::new();
        for tumeur.cells.each |&cell| {
            if(cell.id != self.id) {
                let dist_cells=(self.dist(cell)-2.0*self.radius);
                let factor_rep = 1.0/pow(dist_cells/seuil,3.0)*1e-2f64;
                let factor_attract = -1.0/pow(dist_cells/(3.0*seuil),2.0)*1e-4f64;
                force += (self.center-cell.center)*(factor_rep+factor_attract);
            }
        }
        force
    }

    #[inline(always)]
    fn x(&self) -> f64 {
        self.center.x
    }

    #[inline(always)]
    fn y(&self) -> f64 {
        self.center.y
    }

    fn dist(&self, other: &Cell) -> f64 {
        self.center.dist(&other.center)
    }

}

impl ToStr for Cell {
    fn to_str(&self) -> ~str {
        fmt!("%d @ (%f, %f)", self.id as int, self.center.x as float, self.center.y as float)
    }
}

#[test]
fn test_new() {
    let cell1=Cell::new(0);
    let cell2=Cell::new(1);
    assert!(cell1.center != cell2.center);
}

//
// Population
//

struct Crowd {
    cells : ~[@mut Cell],
    time : float
}

pub impl Crowd {
    fn new(init_pop : uint) -> Crowd {

        let mut pop : ~[@mut Cell]=~[];
        for uint::range(1,init_pop+1) |num| {
            let lonely_one = @mut Cell::new(num);
            pop.push(copy lonely_one);
        }
        Crowd{ cells : pop, time: 0.0}
    }

    fn size(&self) -> uint {
        self.cells.len()
    }

    fn evolve(&mut self, dt: f64) {
        let mut new_cells : ~[@mut Cell] = ~[];
        for self.cells.each |cell| {
            cell.move(self, dt);
            match cell.replicate(self, dt) {
                None => (),
                Some(new_born) => new_cells.push(new_born)
            }
        }
        self.cells.push_all(new_cells);
    }
}

impl ToStr for Crowd {
    fn to_str(&self) -> ~str {
        let mut desc =~"";
        for self.cells.each |cell| {
            let mut lcell_desc=~"";
            lcell_desc.push_str(cell.to_str()); lcell_desc.push_str("\n");
            desc.push_str(lcell_desc);
        }
        desc
    }
}

#[test]
fn test_size() {
    let crowd=Crowd::new(13);
    assert!(crowd.size()==13);
}
<|endoftext|>


<commit_before>use graph_edge_evolution::{EdgeOperation, GraphBuilder, NthEdgeF};
use triadic_census::OptDenseDigraph;
use std::collections::BTreeMap;

defops!{EdgeOp;
    Dup,
    Split,
    Loop,
    Merge,
    Next,
    Parent,
    Reverse,
    Save,
    Restore
}

pub fn edgeops_to_graph(edgeops: &[(EdgeOp, f32)]) -> OptDenseDigraph<(), ()> {
    let mut builder: GraphBuilder<f32, ()> = GraphBuilder::new();
    for &(op, f) in edgeops {
        let graph_op = match op {
            EdgeOp::Dup => EdgeOperation::Duplicate { weight: f },
            EdgeOp::Split => EdgeOperation::Split { weight: f },
            EdgeOp::Loop => EdgeOperation::Loop { weight: f },
            EdgeOp::Merge => EdgeOperation::Merge { n: NthEdgeF(f) },
            EdgeOp::Next => EdgeOperation::Next { n: NthEdgeF(f) },
            EdgeOp::Parent => EdgeOperation::Parent { n: NthEdgeF(f) },
            EdgeOp::Reverse => EdgeOperation::Reverse,
            EdgeOp::Save => EdgeOperation::Save,
            EdgeOp::Restore => EdgeOperation::Restore,
        };
        builder.apply_operation(graph_op);
    }

    let mut g: OptDenseDigraph<(), ()> = OptDenseDigraph::new(builder.total_number_of_nodes()); // XXX: rename to real_number

    // maps node_idx to index used within the graph.
    let mut node_map: BTreeMap<usize, usize> = BTreeMap::new(); // XXX: with_capacity

    builder.visit_nodes(|node_idx, _| {
        let graph_idx = g.add_node();
        node_map.insert(node_idx, graph_idx);
    });

    builder.visit_edges(|(a, b), _| {
        g.add_edge(node_map[&a], node_map[&b]);
    });

    return g;
}
<commit_msg>Fix bug. NthEdgeF must be in range [0, 1)<commit_after>use graph_edge_evolution::{EdgeOperation, GraphBuilder, NthEdgeF};
use triadic_census::OptDenseDigraph;
use std::collections::BTreeMap;

defops!{EdgeOp;
    Dup,
    Split,
    Loop,
    Merge,
    Next,
    Parent,
    Reverse,
    Save,
    Restore
}

pub fn edgeops_to_graph(edgeops: &[(EdgeOp, f32)]) -> OptDenseDigraph<(), ()> {
    let mut builder: GraphBuilder<f32, ()> = GraphBuilder::new();
    for &(op, f) in edgeops {
        let graph_op = match op {
            EdgeOp::Dup => EdgeOperation::Duplicate { weight: f },
            EdgeOp::Split => EdgeOperation::Split { weight: f },
            EdgeOp::Loop => EdgeOperation::Loop { weight: f },
            EdgeOp::Merge => EdgeOperation::Merge { n: NthEdgeF(f.abs().fract()) },
            EdgeOp::Next => EdgeOperation::Next { n: NthEdgeF(f.abs().fract()) },
            EdgeOp::Parent => EdgeOperation::Parent { n: NthEdgeF(f.abs().fract()) },
            EdgeOp::Reverse => EdgeOperation::Reverse,
            EdgeOp::Save => EdgeOperation::Save,
            EdgeOp::Restore => EdgeOperation::Restore,
        };
        builder.apply_operation(graph_op);
    }

    let mut g: OptDenseDigraph<(), ()> = OptDenseDigraph::new(builder.total_number_of_nodes()); // XXX: rename to real_number

    // maps node_idx to index used within the graph.
    let mut node_map: BTreeMap<usize, usize> = BTreeMap::new(); // XXX: with_capacity

    builder.visit_nodes(|node_idx, _| {
        let graph_idx = g.add_node();
        node_map.insert(node_idx, graph_idx);
    });

    builder.visit_edges(|(a, b), _| {
        g.add_edge(node_map[&a], node_map[&b]);
    });

    return g;
}
<|endoftext|>


<commit_before>use crate::io::{Decode, DecodeError, DecodeWithDiscriminant, Encode};
use crate::visit::Visit;
use std::convert::TryFrom;

impl Encode for u8 {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        std::slice::from_ref(self).encode(w)
    }
}

impl Encode for [u8] {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        w.write_all(self)
    }
}

impl Decode for u8 {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        let mut dest = 0;
        r.read_exact(std::slice::from_mut(&mut dest))?;
        Ok(dest)
    }
}

impl Decode for Option<u8> {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        let mut dest = 0;
        loop {
            return match r.read(std::slice::from_mut(&mut dest)) {
                Ok(0) => Ok(None),
                Ok(_) => Ok(Some(dest)),
                Err(err) if err.kind() == std::io::ErrorKind::Interrupted => continue,
                Err(err) => Err(DecodeError::Io(err)),
            };
        }
    }
}

impl DecodeWithDiscriminant for u8 {
    fn maybe_decode_with_discriminant(
        discriminant: u8,
        _r: &mut impl std::io::Read,
    ) -> std::result::Result<std::option::Option<Self>, DecodeError> {
        Ok(Some(discriminant))
    }
}

impl Decode for Vec<u8> {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        let mut dest = Vec::new();
        r.read_to_end(&mut dest)?;
        Ok(dest)
    }
}

impl Visit for u8 {}

macro_rules! def_integer {
    ($ty:ident, $leb128_method:ident) => {
        impl Encode for $ty {
            fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
                leb128::write::$leb128_method(w, (*self).into()).map(|_| ())
            }
        }

        impl Decode for $ty {
            fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
                const LIMIT: u64 = (std::mem::size_of::<$ty>() * 8 / 7) as u64 + 1;

                let mut r = std::io::Read::take(r, LIMIT);
                let as_64 = leb128::read::$leb128_method(&mut r)?;
                let res = Self::try_from(as_64)
                    .map_err(|_| DecodeError::Leb128(leb128::read::Error::Overflow))?;

                Ok(res)
            }
        }

        impl Visit for $ty {}
    };
}

def_integer!(u32, unsigned);
def_integer!(i32, signed);
def_integer!(u64, unsigned);
def_integer!(i64, signed);

impl Encode for usize {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        match u32::try_from(*self) {
            Ok(v) => v.encode(w),
            Err(err) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, err)),
        }
    }
}

impl Decode for usize {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        usize::try_from(u32::decode(r)?)
            .map_err(|_| DecodeError::Leb128(leb128::read::Error::Overflow))
    }
}

impl Visit for usize {}
<commit_msg>Remove now-unused DecodeWithDiscriminant for u8<commit_after>use crate::io::{Decode, DecodeError, Encode};
use crate::visit::Visit;
use std::convert::TryFrom;

impl Encode for u8 {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        std::slice::from_ref(self).encode(w)
    }
}

impl Encode for [u8] {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        w.write_all(self)
    }
}

impl Decode for u8 {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        let mut dest = 0;
        r.read_exact(std::slice::from_mut(&mut dest))?;
        Ok(dest)
    }
}

impl Decode for Option<u8> {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        let mut dest = 0;
        loop {
            return match r.read(std::slice::from_mut(&mut dest)) {
                Ok(0) => Ok(None),
                Ok(_) => Ok(Some(dest)),
                Err(err) if err.kind() == std::io::ErrorKind::Interrupted => continue,
                Err(err) => Err(DecodeError::Io(err)),
            };
        }
    }
}

impl Decode for Vec<u8> {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        let mut dest = Vec::new();
        r.read_to_end(&mut dest)?;
        Ok(dest)
    }
}

impl Visit for u8 {}

macro_rules! def_integer {
    ($ty:ident, $leb128_method:ident) => {
        impl Encode for $ty {
            fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
                leb128::write::$leb128_method(w, (*self).into()).map(|_| ())
            }
        }

        impl Decode for $ty {
            fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
                const LIMIT: u64 = (std::mem::size_of::<$ty>() * 8 / 7) as u64 + 1;

                let mut r = std::io::Read::take(r, LIMIT);
                let as_64 = leb128::read::$leb128_method(&mut r)?;
                let res = Self::try_from(as_64)
                    .map_err(|_| DecodeError::Leb128(leb128::read::Error::Overflow))?;

                Ok(res)
            }
        }

        impl Visit for $ty {}
    };
}

def_integer!(u32, unsigned);
def_integer!(i32, signed);
def_integer!(u64, unsigned);
def_integer!(i64, signed);

impl Encode for usize {
    fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
        match u32::try_from(*self) {
            Ok(v) => v.encode(w),
            Err(err) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, err)),
        }
    }
}

impl Decode for usize {
    fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
        usize::try_from(u32::decode(r)?)
            .map_err(|_| DecodeError::Leb128(leb128::read::Error::Overflow))
    }
}

impl Visit for usize {}
<|endoftext|>


<commit_before>#![feature(associated_type_defaults)]
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;

use macros::* ;
use adapton_sigs::* ;
use quickcheck::Arbitrary;
use quickcheck::Gen;
use std::num::Zero;
use rand::{Rng,Rand};

pub trait ListT<A:Adapton,Elm> : Debug+Clone+Hash+PartialEq+Eq {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Elm, Self::List) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::List) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    fn elim<Res,Nil,Cons,Name> (&mut A, Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, Elm, Self::List) -> Res
        ,    Name:FnOnce(&mut A, A::Name, Self::List) -> Res ;

    fn elim_move<Arg,Res,Nil,Cons,Name> (&mut A, Self::List, Arg, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A, Arg) -> Res
        ,    Cons:FnOnce(&mut A, Elm, Self::List, Arg) -> Res
        ,    Name:FnOnce(&mut A, A::Name, Self::List, Arg) -> Res ;

    // Derived from `cons` and `nil` above:
    fn singleton (st:&mut A, hd:Elm) -> Self::List {
        let nil = Self::nil(st);
        Self::cons(st, hd, nil)
    }

    // Derived from `elim` above:
    fn is_empty (st:&mut A, list:Self::List) -> bool {
        Self::elim(st, list,
                   |_|       true,
                   |_,_,_|   false,
                   |st,_,tl| Self::is_empty(st,tl))
    }
}

/// Just like ListT, except with an additional constructor: `tree`
pub trait TreeListT<A:Adapton,Elm,T:TreeT<A,Elm>> : ListT<A,Elm> {
  fn tree (&mut A, T::Tree, Dir2, Self::List) -> Self::List ;

  fn next_leaf (&mut A, T::Tree, Dir2) -> Option<(Elm,Self::List)> ;

  fn next_leaf_rec (&mut A, T::Tree, Dir2, Self::List) -> Option<(Elm, Self::List)> ;

  fn tree_elim_move<Arg,Res,Tree,Nil,Cons,Name>
    (&mut A, Self::List, Arg, Tree, Nil, Cons, Name) -> Res
    where Tree:FnOnce(&mut A, T::Tree, Dir2, Self::List, Arg) -> Res
    ,      Nil:FnOnce(&mut A, Arg) -> Res
    ,     Cons:FnOnce(&mut A, Elm, Self::List, Arg) -> Res
    ,     Name:FnOnce(&mut A, A::Name, Self::List, Arg) -> Res
    ;
}

pub trait TreeT<A:Adapton,Leaf> : Debug+Hash+PartialEq+Eq+Clone {
    type Lev  : Debug+Hash+PartialEq+Eq+Clone ;
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn lev<X:Hash>(&X) -> Self::Lev ;
    fn lev_of_tree (&mut A, &Self::Tree) -> Self::Lev ;
    fn lev_bits () -> Self::Lev ;
    fn lev_zero () -> Self::Lev ;
    fn lev_inc (&Self::Lev) -> Self::Lev ;
    fn lev_add (&Self::Lev, &Self::Lev) -> Self::Lev ;
    fn lev_lte (&Self::Lev, &Self::Lev) -> bool ;
    fn lev_max_val () -> Self::Lev ;

    fn lev_max (a:&Self::Lev, b:&Self::Lev) -> Self::Lev {
        if Self::lev_lte(a, b) { b.clone() } else { a.clone() }
    }

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Self::Lev, Self::Tree, Self::Tree) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::Lev, Self::Tree, Self::Tree) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;
    fn rc   (&mut A, Rc<Self::Tree>) -> Self::Tree ;

    fn elim<Res,NilC,LeafC,BinC,NameC>
        (&mut A, Self::Tree, NilC, LeafC, BinC, NameC) -> Res
        where NilC  : FnOnce(&mut A) -> Res
        ,     LeafC : FnOnce(&mut A, Leaf) -> Res
        ,     BinC  : FnOnce(&mut A, Self::Lev,  Self::Tree, Self::Tree) -> Res
        ,     NameC : FnOnce(&mut A, A::Name, Self::Lev, Self::Tree, Self::Tree) -> Res
        ;

    fn elim_ref<Res,NilC,LeafC,BinC,NameC>
        (&mut A, &Self::Tree, NilC, LeafC, BinC, NameC) -> Res
        where NilC  : FnOnce(&mut A) -> Res
        ,     LeafC : FnOnce(&mut A, &Leaf) -> Res
        ,     BinC  : FnOnce(&mut A, &Self::Lev,  &Self::Tree, &Self::Tree) -> Res
        ,     NameC : FnOnce(&mut A, &A::Name, &Self::Lev, &Self::Tree, &Self::Tree) -> Res
        ;

    fn elim_move<Arg,Res,NilC,LeafC,BinC,NameC>
        (&mut A, Self::Tree, Arg, NilC, LeafC, BinC, NameC) -> Res
        where NilC  : FnOnce(&mut A, Arg) -> Res
        ,     LeafC : FnOnce(&mut A, Leaf, Arg) -> Res
        ,     BinC  : FnOnce(&mut A, Self::Lev,  Self::Tree, Self::Tree, Arg) -> Res
        ,     NameC : FnOnce(&mut A, A::Name, Self::Lev, Self::Tree, Self::Tree, Arg) -> Res
        ;

    fn fold_lr<Res:Hash+Debug+Eq+Clone,LeafC,BinC,NameC>
        (st:&mut A, tree:Self::Tree, res:Res, leaf:&LeafC, bin:&BinC, name:&NameC) -> Res
        where LeafC:Fn(&mut A, Leaf,    Res ) -> Res
        ,      BinC:Fn(&mut A, Self::Lev,     Res ) -> Res
        ,     NameC:Fn(&mut A, A::Name, Self::Lev, Res ) -> Res
    {
        Self::elim_move
            (st, tree, res,
             |_,res| res,
             |st,x,res| leaf(st, x, res),
             |st,x,l,r,res| {
                 let res = Self::fold_lr(st, l, res, leaf, bin, name);
                 let res = bin(st, x, res);
                 let res = Self::fold_lr(st, r, res, leaf, bin, name);
                 res
             },
             |st,n,x,l,r,res| {
                 let (n1,n2,n3) = st.name_fork3(n.clone());
                 let res = memo!(st, n1 =>> Self::fold_lr, tree:l, res:res ;; leaf:leaf, bin:bin, name:name);
                 let res = name(st, n2, x, res);
                 let res = memo!(st, n3 =>> Self::fold_lr, tree:r, res:res ;; leaf:leaf, bin:bin, name:name);
                 res
             }
             )
    }

    fn fold_rl<Res:Hash+Debug+Eq+Clone,LeafC,BinC,NameC>
        (st:&mut A, tree:Self::Tree, res:Res, leaf:&LeafC, bin:&BinC, name:&NameC) -> Res
        where LeafC:Fn(&mut A, Leaf,    Res ) -> Res
        ,      BinC:Fn(&mut A, Self::Lev,     Res ) -> Res
        ,     NameC:Fn(&mut A, A::Name, Self::Lev, Res ) -> Res
    {
        Self::elim_move
            (st, tree, res,
             |_,res| res,
             |st,x,res| leaf(st, x, res),
             |st,x,l,r,res| {
                 let res = Self::fold_rl(st, r, res, leaf, bin, name);
                 let res = bin(st, x, res);
                 let res = Self::fold_rl(st, l, res, leaf, bin, name);
                 res
             },
             |st,n,x,l,r,res| {
                 let (n1,n2,n3) = st.name_fork3(n);
                 let res = memo!(st, n1 =>> Self::fold_rl, tree:r, res:res ;; leaf:leaf, bin:bin, name:name);
                 let res = name(st, n2, x, res);
                 let res = memo!(st, n3 =>> Self::fold_rl, tree:l, res:res ;; leaf:leaf, bin:bin, name:name);
                 res
             }
             )
    }

    fn fold_up<Res:Hash+Debug+Eq+Clone,NilC,LeafC,BinC,NameC>
        (st:&mut A, tree:Self::Tree, nil:&NilC, leaf:&LeafC, bin:&BinC, name:&NameC) -> Res
        where  NilC:Fn(&mut A) -> Res
        ,     LeafC:Fn(&mut A, Leaf              ) -> Res
        ,      BinC:Fn(&mut A, Self::Lev,     Res, Res ) -> Res
        ,     NameC:Fn(&mut A, A::Name, Self::Lev, Res, Res ) -> Res
    {
        Self::elim
            (st, tree,
             |st| nil(st),
             |st,x| leaf(st, x),
             |st,x,l,r| {
                 let resl = Self::fold_up(st, l, nil, leaf, bin, name);
                 let resr = Self::fold_up(st, r, nil, leaf, bin, name);
                 let res = bin(st, x, resl, resr);
                 res
             },
             |st,n,x,l,r| {
                 let (n1,n2,n3) = st.name_fork3(n);
                 let resl = memo!(st, n1 =>> Self::fold_up, tree:l ;; nil:nil, leaf:leaf, bin:bin, name:name);
                 let resr = memo!(st, n2 =>> Self::fold_up, tree:r ;; nil:nil, leaf:leaf, bin:bin, name:name);
                 let res = name(st, n3, x, resl, resr);
                 res
             }
             )
    }
}

pub trait SetT
    <A:Adapton
    ,Elm:Hash+Clone>
{
    type Set;

    // Intro forms:
    fn empty(st:&mut A);

    fn update_elm<Update,Res>
        (st:&mut A, set:Self::Set, elm:Elm,
         update:&Update)
         -> (Self::Set, Res)
        where Update:FnOnce(&mut A, Option<Elm>, Elm) -> (Option<Elm>, Res)
        ;

    // Elim forms:
    fn elim_move<Arg,Res,NilC,ElmC,UnionC>
        (st:&mut A, set:Self::Set, arg:Arg,
         nil:&NilC, elm:&ElmC, union:&UnionC)
         -> Res
        where NilC:FnOnce(&mut A, Arg) -> Res
        ,     ElmC:FnOnce(&mut A, Elm, Arg) -> Res
        ,   UnionC:FnOnce(&mut A, Self::Set, Self::Set, Arg) -> Res
        ;

    fn is_mem(st:&mut A, set:Self::Set, elm:Elm) -> bool; // TODO: Write based on update, above.
    fn is_empty(st:&mut A, set:Self::Set) -> bool; // TODO: Write based on elim_with, above.
}

pub trait MapT
    <A:Adapton
    ,Dom:Hash+Clone
    ,Cod:Hash+Clone>
{
    type Map;

    // Intro forms:
    fn empty(st:&mut A);

    fn update_pt<Update,Res>
        (st:&mut A, map:Self::Map,
         pt:Dom, cod:Option<Cod>, update:&Update) -> (Self::Map, Res)
        where Update:FnOnce(&mut A, Option<Cod>, Option<Cod>) -> (Option<Cod>, Res)
        ;

    // General elim form:
    fn elim_move<Arg,Res,NilC,ElmC,UnionC>
        (st:&mut A, map:Self::Map, arg:Arg,
         nil:&NilC, elm:&ElmC, union:&UnionC)
        where NilC:FnOnce(&mut A, Arg) -> Res
        ,     ElmC:FnOnce(&mut A, Dom, Option<Cod>) -> Res
        ,   UnionC:FnOnce(&mut A, Self::Map, Self::Map, Arg) -> Res
        ;

    // Special, convenient update_pts:
    fn rem(st:&mut A, map:Self::Map, x:Dom) -> (Option<Cod>, Self::Map); // TODO: Implement with update_pt
    fn get(st:&mut A, set:Self::Map, x:Dom) -> Option<Cod>; // TODO: Implement with update_pt
}

pub trait GraphT
    <A:Adapton
    ,Node:Hash+Eq+Clone+Debug
    ,NodeSet:SetT<A,Node>+Clone+Hash
    ,NodeMap:MapT<A,Node,NodeSet>>
{
    type Graph : Hash+Eq+Clone+Debug;

    // Intro forms:
    fn empty(st:&mut A);
    fn add_node(st:&mut A, graph:Self::Graph, node:Node) -> Self::Graph;
    fn add_edge(st:&mut A, graph:Self::Graph, src:Node, tgt:Node) -> Self::Graph;
    fn add_succs(st: &mut A, graph:Self::Graph, node:Node, succs:NodeSet) -> Self::Graph;

    // Query forms:
    fn get_succs(st: &mut A, graph:Self::Graph, node:Node) -> NodeSet;

    // Other forms:
    // fn rem_node(st:&mut A, graph:Self::Graph, node:NodeLab) -> Self::Graph;
    // fn rem_edge(st:&mut A, graph:Self::Graph, edge:Self::Edge) -> Self::Graph;
}

/// Lists are one-dimensional structures; movement admits two possible directions.
#[derive(Debug,Hash,PartialEq,Eq,Clone)]
pub enum Dir2 { Left, Right }
impl Dir2 {
    pub fn opp(&self) -> Dir2 {
        match *self {
            Dir2::Left => {Dir2::Right}
            Dir2::Right => {Dir2::Left}
        }
    }
}

impl Rand for Dir2 {
    fn rand<R: Rng>(rng: &mut R) -> Dir2 {
        if rng.gen_weighted_bool(2) { Dir2::Left } else { Dir2::Right }
    }
}

impl Arbitrary for Dir2 {
    fn arbitrary<G:Gen> (g: &mut G) -> Self {
        if g.gen() { Dir2::Left  }
        else       { Dir2::Right }
    }
    fn shrink(&self) -> Box<Iterator<Item=Self>> {
        match *self {
            Dir2::Right => Box::new(Some(Dir2::Left).into_iter()),
            Dir2::Left  => Box::new(None.into_iter())
        }
    }
}
<commit_msg>new naming policy: output names are not forked in tree folds<commit_after>#![feature(associated_type_defaults)]
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;

use macros::* ;
use adapton_sigs::* ;
use quickcheck::Arbitrary;
use quickcheck::Gen;
use std::num::Zero;
use rand::{Rng,Rand};

pub trait ListT<A:Adapton,Elm> : Debug+Clone+Hash+PartialEq+Eq {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Elm, Self::List) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::List) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    fn elim<Res,Nil,Cons,Name> (&mut A, Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, Elm, Self::List) -> Res
        ,    Name:FnOnce(&mut A, A::Name, Self::List) -> Res ;

    fn elim_move<Arg,Res,Nil,Cons,Name> (&mut A, Self::List, Arg, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A, Arg) -> Res
        ,    Cons:FnOnce(&mut A, Elm, Self::List, Arg) -> Res
        ,    Name:FnOnce(&mut A, A::Name, Self::List, Arg) -> Res ;

    // Derived from `cons` and `nil` above:
    fn singleton (st:&mut A, hd:Elm) -> Self::List {
        let nil = Self::nil(st);
        Self::cons(st, hd, nil)
    }

    // Derived from `elim` above:
    fn is_empty (st:&mut A, list:Self::List) -> bool {
        Self::elim(st, list,
                   |_|       true,
                   |_,_,_|   false,
                   |st,_,tl| Self::is_empty(st,tl))
    }
}

/// Just like ListT, except with an additional constructor: `tree`
pub trait TreeListT<A:Adapton,Elm,T:TreeT<A,Elm>> : ListT<A,Elm> {
  fn tree (&mut A, T::Tree, Dir2, Self::List) -> Self::List ;

  fn next_leaf (&mut A, T::Tree, Dir2) -> Option<(Elm,Self::List)> ;

  fn next_leaf_rec (&mut A, T::Tree, Dir2, Self::List) -> Option<(Elm, Self::List)> ;

  fn tree_elim_move<Arg,Res,Tree,Nil,Cons,Name>
    (&mut A, Self::List, Arg, Tree, Nil, Cons, Name) -> Res
    where Tree:FnOnce(&mut A, T::Tree, Dir2, Self::List, Arg) -> Res
    ,      Nil:FnOnce(&mut A, Arg) -> Res
    ,     Cons:FnOnce(&mut A, Elm, Self::List, Arg) -> Res
    ,     Name:FnOnce(&mut A, A::Name, Self::List, Arg) -> Res
    ;
}

pub trait TreeT<A:Adapton,Leaf> : Debug+Hash+PartialEq+Eq+Clone {
    type Lev  : Debug+Hash+PartialEq+Eq+Clone ;
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn lev<X:Hash>(&X) -> Self::Lev ;
    fn lev_of_tree (&mut A, &Self::Tree) -> Self::Lev ;
    fn lev_bits () -> Self::Lev ;
    fn lev_zero () -> Self::Lev ;
    fn lev_inc (&Self::Lev) -> Self::Lev ;
    fn lev_add (&Self::Lev, &Self::Lev) -> Self::Lev ;
    fn lev_lte (&Self::Lev, &Self::Lev) -> bool ;
    fn lev_max_val () -> Self::Lev ;

    fn lev_max (a:&Self::Lev, b:&Self::Lev) -> Self::Lev {
        if Self::lev_lte(a, b) { b.clone() } else { a.clone() }
    }

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Self::Lev, Self::Tree, Self::Tree) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::Lev, Self::Tree, Self::Tree) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;
    fn rc   (&mut A, Rc<Self::Tree>) -> Self::Tree ;

    fn elim<Res,NilC,LeafC,BinC,NameC>
        (&mut A, Self::Tree, NilC, LeafC, BinC, NameC) -> Res
        where NilC  : FnOnce(&mut A) -> Res
        ,     LeafC : FnOnce(&mut A, Leaf) -> Res
        ,     BinC  : FnOnce(&mut A, Self::Lev,  Self::Tree, Self::Tree) -> Res
        ,     NameC : FnOnce(&mut A, A::Name, Self::Lev, Self::Tree, Self::Tree) -> Res
        ;

    fn elim_ref<Res,NilC,LeafC,BinC,NameC>
        (&mut A, &Self::Tree, NilC, LeafC, BinC, NameC) -> Res
        where NilC  : FnOnce(&mut A) -> Res
        ,     LeafC : FnOnce(&mut A, &Leaf) -> Res
        ,     BinC  : FnOnce(&mut A, &Self::Lev,  &Self::Tree, &Self::Tree) -> Res
        ,     NameC : FnOnce(&mut A, &A::Name, &Self::Lev, &Self::Tree, &Self::Tree) -> Res
        ;

    fn elim_move<Arg,Res,NilC,LeafC,BinC,NameC>
        (&mut A, Self::Tree, Arg, NilC, LeafC, BinC, NameC) -> Res
        where NilC  : FnOnce(&mut A, Arg) -> Res
        ,     LeafC : FnOnce(&mut A, Leaf, Arg) -> Res
        ,     BinC  : FnOnce(&mut A, Self::Lev,  Self::Tree, Self::Tree, Arg) -> Res
        ,     NameC : FnOnce(&mut A, A::Name, Self::Lev, Self::Tree, Self::Tree, Arg) -> Res
        ;

    fn fold_lr<Res:Hash+Debug+Eq+Clone,LeafC,BinC,NameC>
        (st:&mut A, tree:Self::Tree, res:Res, leaf:&LeafC, bin:&BinC, name:&NameC) -> Res
        where LeafC:Fn(&mut A, Leaf,    Res ) -> Res
        ,      BinC:Fn(&mut A, Self::Lev,     Res ) -> Res
        ,     NameC:Fn(&mut A, A::Name, Self::Lev, Res ) -> Res
    {
        Self::elim_move
            (st, tree, res,
             |_,res| res,
             |st,x,res| leaf(st, x, res),
             |st,x,l,r,res| {
                 let res = Self::fold_lr(st, l, res, leaf, bin, name);
                 let res = bin(st, x, res);
                 let res = Self::fold_lr(st, r, res, leaf, bin, name);
                 res
             },
             |st,n,x,l,r,res| {
                 let (n1,n2) = st.name_fork(n.clone());
                 let res = memo!(st, n1 =>> Self::fold_lr, tree:l, res:res ;; leaf:leaf, bin:bin, name:name);
                 let res = name(st, n, x, res);
                 let res = memo!(st, n2 =>> Self::fold_lr, tree:r, res:res ;; leaf:leaf, bin:bin, name:name);
                 res
             }
             )
    }

    fn fold_rl<Res:Hash+Debug+Eq+Clone,LeafC,BinC,NameC>
        (st:&mut A, tree:Self::Tree, res:Res, leaf:&LeafC, bin:&BinC, name:&NameC) -> Res
        where LeafC:Fn(&mut A, Leaf,    Res ) -> Res
        ,      BinC:Fn(&mut A, Self::Lev,     Res ) -> Res
        ,     NameC:Fn(&mut A, A::Name, Self::Lev, Res ) -> Res
    {
        Self::elim_move
            (st, tree, res,
             |_,res| res,
             |st,x,res| leaf(st, x, res),
             |st,x,l,r,res| {
                 let res = Self::fold_rl(st, r, res, leaf, bin, name);
                 let res = bin(st, x, res);
                 let res = Self::fold_rl(st, l, res, leaf, bin, name);
                 res
             },
             |st,n,x,l,r,res| {
                 let (n1,n2) = st.name_fork(n.clone());
                 let res = memo!(st, n1 =>> Self::fold_rl, tree:r, res:res ;; leaf:leaf, bin:bin, name:name);
                 let res = name(st, n, x, res);
                 let res = memo!(st, n2 =>> Self::fold_rl, tree:l, res:res ;; leaf:leaf, bin:bin, name:name);
                 res
             }
             )
    }

    fn fold_up<Res:Hash+Debug+Eq+Clone,NilC,LeafC,BinC,NameC>
        (st:&mut A, tree:Self::Tree, nil:&NilC, leaf:&LeafC, bin:&BinC, name:&NameC) -> Res
        where  NilC:Fn(&mut A) -> Res
        ,     LeafC:Fn(&mut A, Leaf              ) -> Res
        ,      BinC:Fn(&mut A, Self::Lev,     Res, Res ) -> Res
        ,     NameC:Fn(&mut A, A::Name, Self::Lev, Res, Res ) -> Res
    {
        Self::elim
            (st, tree,
             |st| nil(st),
             |st,x| leaf(st, x),
             |st,x,l,r| {
                 let resl = Self::fold_up(st, l, nil, leaf, bin, name);
                 let resr = Self::fold_up(st, r, nil, leaf, bin, name);
                 let res = bin(st, x, resl, resr);
                 res
             },
             |st,n,x,l,r| {
                 let (n1,n2) = st.name_fork(n.clone());
                 let resl = memo!(st, n1 =>> Self::fold_up, tree:l ;; nil:nil, leaf:leaf, bin:bin, name:name);
                 let resr = memo!(st, n2 =>> Self::fold_up, tree:r ;; nil:nil, leaf:leaf, bin:bin, name:name);
                 let res = name(st, n, x, resl, resr);
                 res
             }
             )
    }
}

pub trait SetT
    <A:Adapton
    ,Elm:Hash+Clone>
{
    type Set;

    // Intro forms:
    fn empty(st:&mut A);

    fn update_elm<Update,Res>
        (st:&mut A, set:Self::Set, elm:Elm,
         update:&Update)
         -> (Self::Set, Res)
        where Update:FnOnce(&mut A, Option<Elm>, Elm) -> (Option<Elm>, Res)
        ;

    // Elim forms:
    fn elim_move<Arg,Res,NilC,ElmC,UnionC>
        (st:&mut A, set:Self::Set, arg:Arg,
         nil:&NilC, elm:&ElmC, union:&UnionC)
         -> Res
        where NilC:FnOnce(&mut A, Arg) -> Res
        ,     ElmC:FnOnce(&mut A, Elm, Arg) -> Res
        ,   UnionC:FnOnce(&mut A, Self::Set, Self::Set, Arg) -> Res
        ;

    fn is_mem(st:&mut A, set:Self::Set, elm:Elm) -> bool; // TODO: Write based on update, above.
    fn is_empty(st:&mut A, set:Self::Set) -> bool; // TODO: Write based on elim_with, above.
}

pub trait MapT
    <A:Adapton
    ,Dom:Hash+Clone
    ,Cod:Hash+Clone>
{
    type Map;

    // Intro forms:
    fn empty(st:&mut A);

    fn update_pt<Update,Res>
        (st:&mut A, map:Self::Map,
         pt:Dom, cod:Option<Cod>, update:&Update) -> (Self::Map, Res)
        where Update:FnOnce(&mut A, Option<Cod>, Option<Cod>) -> (Option<Cod>, Res)
        ;

    // General elim form:
    fn elim_move<Arg,Res,NilC,ElmC,UnionC>
        (st:&mut A, map:Self::Map, arg:Arg,
         nil:&NilC, elm:&ElmC, union:&UnionC)
        where NilC:FnOnce(&mut A, Arg) -> Res
        ,     ElmC:FnOnce(&mut A, Dom, Option<Cod>) -> Res
        ,   UnionC:FnOnce(&mut A, Self::Map, Self::Map, Arg) -> Res
        ;

    // Special, convenient update_pts:
    fn rem(st:&mut A, map:Self::Map, x:Dom) -> (Option<Cod>, Self::Map); // TODO: Implement with update_pt
    fn get(st:&mut A, set:Self::Map, x:Dom) -> Option<Cod>; // TODO: Implement with update_pt
}

pub trait GraphT
    <A:Adapton
    ,Node:Hash+Eq+Clone+Debug
    ,NodeSet:SetT<A,Node>+Clone+Hash
    ,NodeMap:MapT<A,Node,NodeSet>>
{
    type Graph : Hash+Eq+Clone+Debug;

    // Intro forms:
    fn empty(st:&mut A);
    fn add_node(st:&mut A, graph:Self::Graph, node:Node) -> Self::Graph;
    fn add_edge(st:&mut A, graph:Self::Graph, src:Node, tgt:Node) -> Self::Graph;
    fn add_succs(st: &mut A, graph:Self::Graph, node:Node, succs:NodeSet) -> Self::Graph;

    // Query forms:
    fn get_succs(st: &mut A, graph:Self::Graph, node:Node) -> NodeSet;

    // Other forms:
    // fn rem_node(st:&mut A, graph:Self::Graph, node:NodeLab) -> Self::Graph;
    // fn rem_edge(st:&mut A, graph:Self::Graph, edge:Self::Edge) -> Self::Graph;
}

/// Lists are one-dimensional structures; movement admits two possible directions.
#[derive(Debug,Hash,PartialEq,Eq,Clone)]
pub enum Dir2 { Left, Right }
impl Dir2 {
    pub fn opp(&self) -> Dir2 {
        match *self {
            Dir2::Left => {Dir2::Right}
            Dir2::Right => {Dir2::Left}
        }
    }
}

impl Rand for Dir2 {
    fn rand<R: Rng>(rng: &mut R) -> Dir2 {
        if rng.gen_weighted_bool(2) { Dir2::Left } else { Dir2::Right }
    }
}

impl Arbitrary for Dir2 {
    fn arbitrary<G:Gen> (g: &mut G) -> Self {
        if g.gen() { Dir2::Left  }
        else       { Dir2::Right }
    }
    fn shrink(&self) -> Box<Iterator<Item=Self>> {
        match *self {
            Dir2::Right => Box::new(Some(Dir2::Left).into_iter()),
            Dir2::Left  => Box::new(None.into_iter())
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>perf: Handle restarts better in take_until_byte{,s,2,3}<commit_after><|endoftext|>


<commit_before><commit_msg>feat(tmux/config.rs) Need to know Config opts<commit_after><|endoftext|>