Post Reply 
Little explorations with HP calculators (no Prime)
03-30-2017, 08:30 AM (This post was last modified: 03-30-2017 08:39 AM by pier4r.)
Post: #74
RE: Little explorations with the HP calculators
My Hp 50g is actually computing since 10+ hours (and I dread that it will take days to finish) so I cannot readily try the suggestions of Han.

The code, that maybe is extra unoptimized (note: I do not like to just optimize the code, it has to be also readable if I want to expand it in the future, without remembering much about it. So also readability is a factor) is the following - me trying the DIR END structure but before applying the idea of compiled local variables :


(It still has to go through some modifications, I decided to collect the results for the round robin format but, after testing for 2 repetitions, I could not imagine such lengthy process and I cannot estimate when it will finish too. So it may finish in the next minute. This is a clear example why my low quality batteries last few hours. Holy usb chargers directly from the power outlet!

If you have any tip by chance [the file is long and ugly, but it works], I'm listening Smile

Further versions, if any, will be stored here )
Code:

%%HP: T(0)A(D)F(.);
@ You may edit the T(0)A(D)F(.) parts.
@ The earlier parts of the line are used by Debug4x.

@ in npp, just select language "normal" to get rid of the highlight.

@ Objective:
@ - We want to compare the expected performances of teams of a certain
@   average strength in some types of tournaments to determine
@   what is the one that determines the best team.
@   Assuming that the best team is the one to which is given higher strength
@   a priori. Of course the simulation of the tournaments
@   should be done some times to determine the percentage of winning for each team.
@   1. round robin. Every team meets everyone else, at least twice.
@      (it could be extended with four times, six and so on)
@      Often used in long tournaments.
@      This is assumed as the best format and will be used as reference.
@   2. swiss tournament
@      Random pairings, and then teams with high score meet other teams
@      with high score, if possible avoiding pairings already done.
@      The minimum is that teams meet once.
@      Often used in chess, short but maybe effective.
@   3. knockout tournaments. Random pairing at the start and then
@      the ones that wins proceed.
@      Often used in "show tournaments", short but maybe not so effective.
@   4. only one match against all the others (like half of a round robin)
@      Often used in show tournaments. Short but maybe not so effective.

@ Remarks: the comments try to give an idea, the values in the comments may
@ be different from the actual code though.

@TODO: to pass variables between programs, try to use the compiled local variables.
@ so one does not have persistent variables after the execution.
@ Although it is not so bad to have global variables and modifying them for the next
@ trial. It is like using inputs, without having to type them on the stack.

DIR
  main    
  \<<
    0 @tmpV to use for short time, value can be changed in other functions!
    0 @tmpV2
    0 @rrResArr
    0 @rrResList (not sure what I'll use)
    \->
    @external inputs
    @local var
    tmpV
    tmpV2
    
    rrResArr
    rrResList
    \<<
      @creating/updating global variables
      @to use among programs without too much passing
      @of values
      'n*25+1200' 'n' 1 16 1 SEQ 'listTeams' STO
        @ list of teams with a priori strength score
      listTeams SIZE 'numTeams' STO
      '0' 'n' 1 numTeams 1 SEQ 'finalTournResList' STO
      
      creMatrVarProb
        @Eval not needed when calling globals
        
      1 maxTournRepV
      FOR counter      
        rrFunc
        DUP @leaving a copy of the final list of rrFunc
        
        @using the list returned by rrFunc
        updWinList
      NEXT
      
      finalTournResList
    \>>
  \>>
  
  @####################
  @creating/updating global variables
  @to use among programs without too much passing
  @of values
  
  @remark: to recall and put in local var only when speed is needed.
  
  @flag for team A winning
  uFteamAwon
  10
  
  @temp flag, not possible to expect to persist
  @in different block executions
  uFtmp
  20
  
  @flag for finding a probability
  uFmatchingProbFound
  30
  
  listTeams
  { 0 }
  
  numTeams
  0
  
  @max cumulative probability
  maxSumProbV
  0
  
  @number of possible choices or probabilties
  numProbV
  0
  
  @column for cumulative probability values
  colSumProb
  1
  
  @column for single probabilities
  colProb  
  2
  
  @column for variance result
  colVar  
  3
  
  @final matrix with cumulative probability, probability, variance results.
  mVarProb
  0
  
  @points assigned for a win
  pointsForWin
  1
  
  @repeating the same tournament type to get the winners.
  maxTournRepV
  1000
  
  finalTournResList
  0
  
  @end globals
  @####################
  
  creMatrVarProb
  \<<
    @createMatrixWithVarianceAndProbability
  
    0 @tmpV
    0 @tmpV2
    \->
    @external inputs
    @local var
    tmpV
    tmpV2
    \<<
      @ creating the matrix containing the probability of the points. Variance
      @ between -400 points and +400 points
      
      @ every drop or increment of the base strength is made in 25 points.
      @ those points have a probability. So I assign "probability tokens" at every
      @ change. For example.
      @ -400  has 25 prob tokens. -375 has 50, -350 has 75 and so on, until the
      @ base value then goes back. +25 has 400 tokens, +50 has 375 and so on.
      @ so I want to model those tokens.
      'n' 'n' 25 400 25 SEQ
      425 +
        @ expanding the previous list with 425
      'n' 'n' 400 25 -25 SEQ
        @ Or REVLIST could have been used.
      + 'tmpV' STO
        @ storing the list
        @ the complete list now goes from 25 to 425 and back to 25.
      
      @ Now we want to create the sum of all those tokens,
      @ one value for each token, We can use STREAM but we need to recall
      @ objects from the tack. I do not like stack operations because
      @ they are unreadable but when they are a few it is ok.
      @ otherwise one should comment the actions that they do.
      1 'tmpV2' STO
        @ counter, it needs to start from 1.
      tmpV 
      \<<
        @ having 25 50 75 100
        @ STREAM  25  2 Pick 25 + 25 STREAM 25 Pick 2 25 + 25  STREAM 25  Pick 2 25   + 25 
        @         50         50   75        75        75   75         75         75     75
        @                    25             75        75   150        150        150    150
        @                                             75              100        100    250
        @                                                                        150    
        2 PICK
        +
        1 'tmpV2' STO+
          @we need to count the objects that we leave on the stack. Plus 1 added at the start.
      \>>
      STREAM
        @now we have the list with all the sums
      @before making a vector out of it we save the last value that is the maximum value.  
      DUP 'maxSumProbV' STO
      @we continue      
      tmpV2
        @ the number of objects.
      \->ARRY    
        @ transformed in a vector
      
      tmpV
        @ the first list
      OBJ\->
        @ exploded
      @before saving it as vector I save the number of elements or
      @probility tokens (equals to variances)
      DUP 'numProbV' STO
      \->ARRY    
        @ transformed in a vector
        
      'n' 'n' -400 -25 25 SEQ
      0 +
      'n' 'n' 25 400 +25 SEQ
      + OBJ\->
        @ added and then exploded
      \->ARRY    
        @ transformed in a vector
      
      3 COL\-> 'mVarProb' STO
        @final matrix with columns: sum of probability tokens, probability tokens for variance, variance in points.
      
      @#########
      @output      
    \>>
  \>>

  getVarFunc
  \<<
    @program to extract the variance out of the built matrix
  
    @output, the variance of the strength points out of the matrix

    0 @curProbV
    0 @tmpV
    \->
    @external inputs
    @local var
    curProbV
    tmpV
    \<<
      maxSumProbV RAND * 1 + IP 'curProbV' STO
        @ we get a random vnumber that has to be compared with the probability sums
      
      1 'tmpV' STO
        @with tmpV we will use it as a counter
      uFmatchingProbFound CF
      WHILE
        uFmatchingProbFound FC?
        tmpV numProbV \<=
        
        AND
      REPEAT
        IF
          curProbV 'mVarProb(tmpV, colSumProb)' EVAL \<=
            @accessing the matrix in algebraic mode, slower but more readable.
            @ than the messy RPN (RPN is not always less readable, but in some cases)
            @maintenance and debug use resources as well that often are more valuable.
        THEN
          @ found a probability sum bigger than the actual random value.
          uFmatchingProbFound SF
        ELSE
          1 'tmpV' STO+
        END
      END
      
      'mVarProb(tmpV, colVar)' EVAL
    \>>
  \>>

  matchResFunc
  \<<
    @program to compute the result of a match based on the variance and probability of it.
    @ should be used by all the tournaments.
  
    0 @teamAtmpV
    0 @teamBtmpV
    \->
    @external inputs
    teamAstrV
    teamBstrV
    @local var
    teamAtmpV
    teamBtmpV
    \<<
      @In input are expected the strength of the two teams 
      @ and a user flag for the result
      @as for of variables already existing.
      @teamA
      @teamB
      @userFlagNumber
      
      @in output a flag is set
      @if teamA won, otherwise teamB
      
      uFteamAwon CF
      
      @ teamA streangth modified
      teamAstrV getVarFunc
      + 'teamAtmpV' STO
      
      @ teamB streangth modified
      teamBstrV getVarFunc
      + 'teamBtmpV' STO
      
      @there is no draw possible, at least for now.
      IF
        teamAtmpV teamBtmpV >
      THEN
        @teamA won.
        uFteamAwon SF
      ELSE
        @ teamA with lower or equal strength
        IF
          teamAtmpV teamBtmpV <
        THEN
          @teamA lost
          uFteamAwon CF
        ELSE
          @ same strength
          @ coin toss
          IF
            RAND 10 * IP
            5 <
          THEN
            @teamA won
            uFteamAwon SF
          ELSE
            @teamA lost
            uFteamAwon CF
          END
        END
      END
    \>>
  \>>

  IncListElFunc
  \<<
    @ program to increase the value of element in a list
  
    @ input on the stack see variables
    @ see the following, that if I keep adding variables on the main
    @ program it gets too unreadable.
    
    @output, the list in input, modified, on the stack
    \->
    @external inputs
    lList 
      @list
    lPosV 
      @position of the element
    lincV 
      @increase
    @local var
    \<<
      lList lPosV
        @placing list and position on the stack
        @for storing, later.
      lList lPosV GET
      lincV +
        @getting the value and increasing it
      PUT
        @putting the increasing value back
    \>>
  \>>
  
  updWinList
  \<<
    @program that updates the winner list given the
    @last tournament result list
    
    0 @maxV
    0 @tmpV
    0 @tmpList
    \->
    lastTresList
    maxV
    tmpV
    tmpList
    \<<
      uFtmp CF
        @we use it to determine if we are done
      
      lastTresList SORT REVLIST 'tmpList' STO
        @to find the maximum quickly
      
      WHILE
        uFtmp FC?
      REPEAT
        tmpList HEAD 'tmpV' STO
        
        IF
          tmpV maxV \>=
        THEN
          @valid new max
          tmpV 'maxV' STO
          
          @make tmpList smaller.
          tmpList TAIL 'tmpList' STO
          
          @increase the value in the position of the team with highest value
          @ and saving.
          finalTournResList 
          lastTresList maxV POS 
          1
          IncListElFunc
          'finalTournResList' STO
        ELSE
          @we are done
          uFtmp SF
        END
      END
    \>>
  \>>

  rrFunc
  \<<
    @program to compute a round robin tournament 
    
    0 @rrResList
    0 @teamAstrV
    0 @teamBstrV
    \->
    @external inputs
    @numTeams
    @listTeams
    @pointsForWin
    @uFteamAwon
    @local var
    rrResList
    teamAstrV
    teamBstrV
    \<<
       @program to compute a round robin tournament 
       
       @ given a list of teams with their strength and other
       @already named and set variables.
       
       @output, the list of teams with final points.
       
       '0' 'n' 1 numTeams 1
       SEQ 'rrResList' STO
         @saving the result list that at the start is just zeroes
       
       1 
       numTeams 1 -
       FOR teamPosA
         listTeams teamPosA GET 'teamAstrV' STO
           @get first team
         
         teamPosA 1 + 
         numTeams
         FOR teamPosB
           listTeams teamPosB GET 'teamBstrV' STO
             @get second team team
             
           @compute the result of a match. twice
           @as round robin requirement.
           1 2
           FOR counter
             teamAstrV teamBstrV
             matchResFunc
           
             IF
               uFteamAwon FS?
             THEN
               @update results
               rrResList teamPosA pointsForWin 
               IncListElFunc 
               'rrResList' STO
             ELSE
               @update results
               rrResList teamPosB pointsForWin
               IncListElFunc 
               'rrResList' STO
             END
           NEXT
         NEXT
       NEXT
       
       rrResList
    \>>
  \>>

@directory end
@###############################################################################​
END

@ log {
@   20:59 29.03.2017 {
@     After the discovery of the DIR END structure, I'm going to refactor the program.
@   }
@   12:05 29.03.2017{
@     Generating list of 16 teams between 1200 and 1600 strength points
@     'n*25+1200' 'n' 1 16 1 SEQ
@   }
@ }

Wikis are great, Contribute :)
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
RE: Little explorations with the HP calculators - pier4r - 03-30-2017 08:30 AM



User(s) browsing this thread: 5 Guest(s)