<commit_before>/*global window:false*/
import _ from 'lodash';

import {EPSILON, velocityI, velocityJ} from './const';
import {maxIterations} from './config';
import * as print from './print';

export class Simulation {

  constructor(board) {
    this.board = board;
    this.history = [];
    this.measurementHistory = [];
  }

  /**
   * Clear history and make it one-element list
   * containing initial particles state.
   */
  initialize() {
    const initialState =
      _.reduce(_.range(this.board.level.width), (accI, i) => {
        return _.reduce(_.range(this.board.level.height), (accJ, j) => {
          // Recognize generating tiles by having 'generation' method
          if (!this.board.tileMatrix[i][j].type.generation) {
            return accJ;
          }
          const emissions =
            this.board.tileMatrix[i][j].type.generation(
              this.board.tileMatrix[i][j].rotation
            );
          _.forEach(emissions, (emission) => {
            accJ.push({i:  i,
                       j:  j,
                       to: emission.to,
                       re: emission.re,
                       im: emission.im});
          });
          return accJ;
        }, accI);
      }, []);

    // debugging purpose
    window.console.log('Simulation started:');
    window.console.log(print.stateToStr(initialState));

    this.history.push(initialState);
    this.measurementHistory.push([]);
  }

  /**
   * Make one propagation step and save it in history.
   * Additionally, return it.
   */
  propagate(quantum = true) {

    const lastState = _.last(this.history);
    const displacedState = this.displace(lastState);
    let absorbed = null;
    if (quantum) {
      absorbed = this.absorb(displacedState);
    }
    let newState = this.interact(displacedState);
    if (quantum) {
      newState = this.normalize(newState);
    }

    this.history.push(newState);
    this.measurementHistory.push(absorbed);

    if (_.any(absorbed, 'measured')) {
      return [];
    } else {
      return newState;
    }

  }

  /**
   * Creates a new state basing on input state, with particles
   * moved according to their directions.
   */
  // WARNING: creating may be slower than just modifying i and j
  displace(state) {
    return _.map(state, (entry) => {
      // 'to' value = direction + polarization
      const dir = entry.to[0];
      const newI = entry.i + velocityI[dir];
      const newJ = entry.j + velocityJ[dir];
      return {i:  newI,
              j:  newJ,
              to: entry.to,
              re: entry.re,
              im: entry.im};
    });
  }

  absorb(state) {
    // Calculate all absorption probabilities.
    const bins = _.map(state, (entry) => {

      let a = entry.re * entry.re + entry.im * entry.im;
      let tile = null;

      // Check if particle is out of bound
      if (
           entry.i < 0 || entry.i >= this.board.level.width
        || entry.j < 0 || entry.j >= this.board.level.height
      ) {
        a = a * 1;
      } else {
        tile = this.board.tileMatrix[entry.i][entry.j];
        const transitionAmps = tile.transitionAmplitudes.map.get(entry.to);
        const transmitted = _.chain([...transitionAmps.values()])
          .map((change) => change.re * change.re + change.im * change.im)
          .sum()
          .value();

        a = (1 - transmitted) * a;
      }

      return {i:           entry.i,
              j:           entry.j,
              to:          entry.to,
              tile:        tile,
              probability: a,
              measured:    false};
    })
    .filter((entry) =>
      entry.probability > EPSILON
    );

    const rand = Math.random();
    let probSum = 0;

    for (let k = 0; k < bins.length; k++) {
      probSum += bins[k].probability;
      if (probSum > rand) {
        bins[k].measured = true;
      }
    }

    return bins;

  }

  /**<commit_msg>fix(simulation) no more multiple clicks<commit_after>/*global window:false*/
import _ from 'lodash';

import {EPSILON, velocityI, velocityJ} from './const';
import {maxIterations} from './config';
import * as print from './print';

export class Simulation {

  constructor(board) {
    this.board = board;
    this.history = [];
    this.measurementHistory = [];
  }

  /**
   * Clear history and make it one-element list
   * containing initial particles state.
   */
  initialize() {
    const initialState =
      _.reduce(_.range(this.board.level.width), (accI, i) => {
        return _.reduce(_.range(this.board.level.height), (accJ, j) => {
          // Recognize generating tiles by having 'generation' method
          if (!this.board.tileMatrix[i][j].type.generation) {
            return accJ;
          }
          const emissions =
            this.board.tileMatrix[i][j].type.generation(
              this.board.tileMatrix[i][j].rotation
            );
          _.forEach(emissions, (emission) => {
            accJ.push({i:  i,
                       j:  j,
                       to: emission.to,
                       re: emission.re,
                       im: emission.im});
          });
          return accJ;
        }, accI);
      }, []);

    // debugging purpose
    window.console.log('Simulation started:');
    window.console.log(print.stateToStr(initialState));

    this.history.push(initialState);
    this.measurementHistory.push([]);
  }

  /**
   * Make one propagation step and save it in history.
   * Additionally, return it.
   */
  propagate(quantum = true) {

    const lastState = _.last(this.history);
    const displacedState = this.displace(lastState);
    let absorbed = null;
    if (quantum) {
      absorbed = this.absorb(displacedState);
    }
    let newState = this.interact(displacedState);
    if (quantum) {
      newState = this.normalize(newState);
    }

    this.history.push(newState);
    this.measurementHistory.push(absorbed);

    if (_.any(absorbed, 'measured')) {
      return [];
    } else {
      return newState;
    }

  }

  /**
   * Creates a new state basing on input state, with particles
   * moved according to their directions.
   */
  // WARNING: creating may be slower than just modifying i and j
  displace(state) {
    return _.map(state, (entry) => {
      // 'to' value = direction + polarization
      const dir = entry.to[0];
      const newI = entry.i + velocityI[dir];
      const newJ = entry.j + velocityJ[dir];
      return {i:  newI,
              j:  newJ,
              to: entry.to,
              re: entry.re,
              im: entry.im};
    });
  }

  absorb(state) {
    // Calculate all absorption probabilities.
    const bins = _.map(state, (entry) => {

      let a = entry.re * entry.re + entry.im * entry.im;
      let tile = null;

      // Check if particle is out of bound
      if (
           entry.i < 0 || entry.i >= this.board.level.width
        || entry.j < 0 || entry.j >= this.board.level.height
      ) {
        a = a * 1;
      } else {
        tile = this.board.tileMatrix[entry.i][entry.j];
        const transitionAmps = tile.transitionAmplitudes.map.get(entry.to);
        const transmitted = _.chain([...transitionAmps.values()])
          .map((change) => change.re * change.re + change.im * change.im)
          .sum()
          .value();

        a = (1 - transmitted) * a;
      }

      return {i:           entry.i,
              j:           entry.j,
              to:          entry.to,
              tile:        tile,
              probability: a,
              measured:    false};
    })
    .filter((entry) =>
      entry.probability > EPSILON
    );

    const rand = Math.random();
    let probSum = 0;

    for (let k = 0; k < bins.length; k++) {
      probSum += bins[k].probability;
      if (probSum > rand) {
        bins[k].measured = true;
        break;
      }
    }

    return bins;

  }

  /**
{'fraction_non_alphanumeric': 0.1348529224500191, 'fraction_numerical': 0.0017827581815866547, 'mean_word_length': 1.7950177935943061, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1726919', 'n_tokens_mistral': 2444, 'n_tokens_neox': 2326, 'n_words': 565}