I would like to create a basic genetic algorithm in order to output a set of input to enter in an emulator. Basically, what it does is :
Generate an input sheet
List item
Run said input
slightly modify it
Run it
See whichever input set performed better and "fork" it and repeat until the problem is solved
So : here is my code to generate the first set of inputs :
(* RNG initialization
* unit *)
Random.self_init();;
(* Generating a starting input file
* array
* 500 inputs long *)
let first_input =
let first_array = Array.make 500 "START" in
for i = 1 to 499 do
let input =
match Random.int(5) with
| 0 -> "A "
| 1 -> "B "
| 2 -> "DOWN "
| 3 -> "LEFT "
| 4 -> "RIGHT "
| _ -> "START " in
first_array.(i) <- input
done;
first_array;;
And here is my "mutation" function that randomly alters some inputs :
(* Mutating input_file
* Rate : in percent, must be positive and <= 100
* a must be an array of strings *)
let mutation a n=
let mutation_rate = n in
for i = 0 to ((Array.length(a) * mutation_rate / 100) - 1) do
let input =
match Random.int(5) with
| 0 -> "A "
| 1 -> "B "
| 2 -> "DOWN "
| 3 -> "LEFT "
| 4 -> "RIGHT "
| _ -> "START " in
a.( Random.int(498) + 1) <- input
done;;
However, I don't feel like my function is efficient because I had to paste the pattern matching part in the mutation function and I think there has to be a smarter way to proceed. If I define my "input" function as a global function, then it is only evaluated once (let's say as "RIGHT" and all occurrences of "input" will return "RIGHT" which is not really useful.
Thanks.
There isn't anything wrong with putting that into it's own function. What you are missing is an argument to make the function deal with the side-effect of Random.int. Since you are not using this argument, it's often/always the case people use unit.
let random_input () = match Random.int 5 with
| 0 -> "A "
| 1 -> "B "
| 2 -> "DOWN "
| 3 -> "LEFT "
| 4 -> "RIGHT "
| _ -> "START "
What you are doing here is pattern matching the argument, and since there is only one constructor this matching is exhaustive. But technically, you can replace the () above with an _. This will match anything making the function polymorphic against it's argument, 'a -> string. In this case it's bad form since it may lead to confusion as to what the parameter is for.
Related
I was trying out some of the exercises in a dune build. I think my issue is due to the semicolons but I'm not really sure. When running the following code:
let somelist = [1;2;3;4] in
(* last element in a list *)
match (last somelist) with
| Some (v) ->
print_endline "last value of list:" ;
print_int v;
| None -> () ;
print_newline ();
(* last 2 elements in a list *)
match (last_two somelist) with
| Some (a::b) ->
print_endline "last 2 elements in list: \n";
print_int a;
print_int (List.hd b);
| None -> () ;
| Some ([]) -> () ;;
print_newline () ;;
it only prints out:
last value of list:
4
instead of continuing and printing out the last 2 elements in the list afterwards. I tested out the other 2 functions, last and last_two in utop and they seem to work.
I wanted it to print out:
last value of list:
4
last 2 elements in list:
3 4
Each branch of a match contains a list of expressions separated by ; (or at least this is one way to describe the syntax). So your second match is contained within just one of the branches of the first match. I.e., it executes only if last somelist is None.
The usual way to solve this is by enclosing the first match in begin / end or parentheses. Here's one way to do this:
begin
match (last somelist) with
| Some (v) ->
print_endline "last value of list:" ;
print_int v;
| None -> ()
end;
print_newline ();
match (last_two somelist) with
. . .
For a better understanding, I try to rewrite this code without "... with" but I struggle:
let rec blast list =
list with
| x :: y :: [] -> x
| hd :: tl -> blast tl
| _ -> fail "not enough";;
Any ideas? Thanks!
Sure we could "manually" try to match each pattern.
The first applies when there is exactly 2 elements, the second when there is more than 1 (but not 2) and the third in all other cases (0 elements).
The second case can be folded into the last case (As when there is 1 element, the recursive call just fails).
So now we have 3 cases: exactly 2, more than 2 and less than 2.
Perfect for List.compare_length_with: 'a list -> int -> int:
let rec beforelast list =
let cmp = List.compare_length_with list 2 in
if cmp = 0 then (* Exactly 2 elements *)
List.hd list
else if cmp > 0 then (* More than 2 elements *)
beforelast (List.tl list)
else (* 1 or 0 elements *)
failwith "not enough"
Though note that you are still pattern matching under the hood, because that's what OCaml data types are made for. For example, List.hd might be implemented like:
let hd = function
| head :: _ -> head
| [] -> raise (Failure "hd")
So the match ... with way should be the way that leads to a better understanding.
As I was typing up some code in OCaml, I wanted to match two cases at once (since the function I'm writing is commutative):
type something =
| Two of int * int
| One of int
let my_function p q =
match p, q with
| Two (_, _) as two, One (x)
| One (x), Two (_, _) as two -> (* some value *)
| _ -> (* some other value *)
;;
I'm getting the following error:
Error: Variable two must occur on both sides of this | pattern
The problem doesn't occur when I remove the as statement, but I need it for the logic purposes. Why can't I do it like this? Will I have to resort to rewriting the logic twice?
as has lower precedence than ,. Hence you should put parenthesis around Two (_,_) as two.
I am attempting to do some evaluation of the relative rates of different algorithms in the C# and F# realms using WekaSharp and one of the algorithms I was interested in was Markov Chains. I know Weka has an HMM application but I have not been able to implement this into WekaSharp and was wondering if there was a way to modify the J48 Algorithm to suit this purpose. I know there is some similarity between J48 and first order Markov chains but am trying to determine what needs to be modified and if this is a reasonable thing to do. Here is the J48 as implemented in Yin Zhu's WekaSharp:
type J48() =
static member DefaultPara = "-C 0.25 -M 2"
static member MakePara(?binarySplits, ?confidenceFactor, ?minNumObj, ?unpruned, ?useLaplace) =
let binarySplitsStr =
let b = match binarySplits with
| Some (v) -> v
| None -> false
if not b then "-B" else ""
let confidenceFactorStr =
let c = match confidenceFactor with
| Some (v) -> v
| None -> 0.25 // default confi
"-C " + c.ToString()
let minNumObjStr =
let m = match minNumObj with
| Some (v) -> v
| None -> 2
"-M " + m.ToString()
let unprunedStr =
let u = match unpruned with
| Some (v) -> v
| None -> false
if u then "-U" else ""
let useLaplaceStr =
let u = match useLaplace with
| Some (v) -> v
| None -> false
if u then "-A" else ""
binarySplitsStr + " " + confidenceFactorStr + " " + minNumObjStr + " " + unprunedStr + " " + useLaplaceStr
Thank you very much.
J48 is just an implementation of the C4.5 algorithm that learns decision trees by considering the entropy of each attribute (dimension) and taking the attribute that has maximum entropy as root of the current subtree. This algorithm does not need reinforcement.
I guess that by Markov Chains you mean Hidden Markov Model that is used in reinforcement learning.
You should take a look to HMMWeka.
A related question is:
What is the equivalent for a Hidden Markov Model in the WEKA toolkit?
I'm learning. This is something I found strange:
let test_treeways x = match x with
| _ when x < 0 -> -1
| _ when x > 0 -> 1
| _ -> 0;;
If I then call it like this:
test_threeways -10;;
I will get type mismatch error (because, as far as I understand, it interprets unary minus as if it was partial function application, so it considers the type of the expression to be int -> int. However, this:
test_threeways (-10);;
acts as expected (though this actually calculates the value, as I could understand, it doesn't pass a constant "minus ten" to the function.
So, how do you write constant negative numbers in OCaml?
You need to enclose it in order to avoid parsing amiguity. "test_threeways -10" could also mean: substract 10 from test_threeways.
And there is no function application involved. Just redefine the unary minus, to see the difference:
#let (~-) = (+) 2 ;; (* See documentation of pervarsives *)
val ( ~- ) : int -> int = <fun>
# let t = -2 ;;
val t : int = -2 (* no function application, constant negative number *)
# -t ;;
- : int = 0 (* function application *)
You can use ~- and ~-. directly (as hinted in the other answer), they are both explicitly prefix operators so parsing them is not ambiguous.
However I prefer using parentheses.