public static void GeneratePrograms( bool useRed, bool useGreen, bool useBlue, IList <int> funcSlotCount, Predicate <Program> shouldStopPredicate) { Debug.Assert(funcSlotCount.Count <= 5 && !funcSlotCount.Contains(0)); List <FieldColor> availableColors = new List <FieldColor> { FieldColor.None }; if (useRed) { availableColors.Add(FieldColor.Red); } if (useGreen) { availableColors.Add(FieldColor.Green); } if (useBlue) { availableColors.Add(FieldColor.Blue); } List <ProgramAction> availableActions = new List <ProgramAction> { ProgramAction.Forward, ProgramAction.Left, ProgramAction.Right }; if (funcSlotCount.Count > 0) { availableActions.Add(ProgramAction.F1); } if (funcSlotCount.Count > 1) { availableActions.Add(ProgramAction.F2); } if (funcSlotCount.Count > 2) { availableActions.Add(ProgramAction.F3); } if (funcSlotCount.Count > 3) { availableActions.Add(ProgramAction.F4); } if (funcSlotCount.Count > 4) { availableActions.Add(ProgramAction.F5); } ProgramSlot[][] generatedCode = new ProgramSlot[funcSlotCount.Count][]; for (int i = 0; i < funcSlotCount.Count; ++i) { generatedCode[i] = new ProgramSlot[funcSlotCount[i]]; } GenerateProgramsDfs(availableColors, availableActions, 0, generatedCode, shouldStopPredicate); }
public Program ChromosomeToProgram(ProgramChromosome chromosome) { ProgramSlot[][] programCode = new ProgramSlot[this.funcSlotCount.Count][]; int index = 0; for (int i = 0; i < this.funcSlotCount.Count; ++i) { programCode[i] = new ProgramSlot[this.funcSlotCount[i]]; for (int j = 0; j < this.funcSlotCount[i]; ++j) programCode[i][j] = chromosome.GetSlot(index++); } return new Program(programCode); }
public override void Crossover(IChromosome pair) { ProgramChromosome pairCasted = (ProgramChromosome)pair; int randomPos1 = random.Next(this.slotCount); int randomPos2 = random.Next(this.slotCount); for (int i = Math.Min(randomPos1, randomPos2); i <= Math.Max(randomPos1, randomPos2); ++i) { ProgramSlot temp = pairCasted.program[i]; pairCasted.program[i] = this.program[i]; this.program[i] = temp; } }
public Program ChromosomeToProgram(ProgramChromosome chromosome) { ProgramSlot[][] programCode = new ProgramSlot[this.funcSlotCount.Count][]; int index = 0; for (int i = 0; i < this.funcSlotCount.Count; ++i) { programCode[i] = new ProgramSlot[this.funcSlotCount[i]]; for (int j = 0; j < this.funcSlotCount[i]; ++j) { programCode[i][j] = chromosome.GetSlot(index++); } } return(new Program(programCode)); }
public static void GeneratePrograms( bool useRed, bool useGreen, bool useBlue, IList<int> funcSlotCount, Predicate<Program> shouldStopPredicate) { Debug.Assert(funcSlotCount.Count <= 5 && !funcSlotCount.Contains(0)); List<FieldColor> availableColors = new List<FieldColor> { FieldColor.None }; if (useRed) availableColors.Add(FieldColor.Red); if (useGreen) availableColors.Add(FieldColor.Green); if (useBlue) availableColors.Add(FieldColor.Blue); List<ProgramAction> availableActions = new List<ProgramAction> { ProgramAction.Forward, ProgramAction.Left, ProgramAction.Right }; if (funcSlotCount.Count > 0) availableActions.Add(ProgramAction.F1); if (funcSlotCount.Count > 1) availableActions.Add(ProgramAction.F2); if (funcSlotCount.Count > 2) availableActions.Add(ProgramAction.F3); if (funcSlotCount.Count > 3) availableActions.Add(ProgramAction.F4); if (funcSlotCount.Count > 4) availableActions.Add(ProgramAction.F5); ProgramSlot[][] generatedCode = new ProgramSlot[funcSlotCount.Count][]; for (int i = 0; i < funcSlotCount.Count; ++i) generatedCode[i] = new ProgramSlot[funcSlotCount[i]]; GenerateProgramsDfs(availableColors, availableActions, 0, generatedCode, shouldStopPredicate); }
private ProgramExecutionResult CanBeSolvedWithDfs( HashSet <ProgramState> stateSet, bool[,] eatenStarsMask, ref ProgramState state, ref int starsEaten, Program program) { Debug.Assert(state.Instruction == 0); for (int instr = 0; instr < program.GetInstructionCountInFunc(state.Func); ++instr) { state.Instruction = instr; // Loop check if (stateSet.Contains(state)) { return(ProgramExecutionResult.Fail); } FieldColor currentColor = this.colors[state.Position.X, state.Position.Y]; ProgramSlot slot = program.GetProgramSlot(state.Func, state.Instruction); if (slot.Action == ProgramAction.None) { continue; } if (slot.Color != FieldColor.None && slot.Color != currentColor) { continue; } if (slot.Action == ProgramAction.Forward || slot.Action == ProgramAction.Left || slot.Action == ProgramAction.Right) { switch (slot.Action) { case ProgramAction.Left: state.Dir = (state.Dir - 1 + 4) % 4; break; case ProgramAction.Right: state.Dir = (state.Dir + 1) % 4; break; case ProgramAction.Forward: Coord newPosition = state.Position; newPosition.X += shiftX[state.Dir]; newPosition.Y += shiftY[state.Dir]; state.Position = newPosition; if (state.Position.X < 0 || state.Position.Y < 0 || state.Position.X >= this.width || state.Position.Y >= this.height) { return(ProgramExecutionResult.Fail); } if (colors[state.Position.X, state.Position.Y] == FieldColor.None) { return(ProgramExecutionResult.Fail); } // If star was eaten after this turn if (this.stars[state.Position.X, state.Position.Y] && !eatenStarsMask[state.Position.X, state.Position.Y]) { eatenStarsMask[state.Position.X, state.Position.Y] = true; starsEaten += 1; if (starsEaten == this.starsCount) { return(ProgramExecutionResult.StarsEaten); } } break; } } else if (slot.Action == ProgramAction.F1 || slot.Action == ProgramAction.F2 || slot.Action == ProgramAction.F3 || slot.Action == ProgramAction.F4 || slot.Action == ProgramAction.F5) { ProgramState stateToPass = state; stateToPass.Instruction = 0; switch (slot.Action) { case ProgramAction.F1: stateToPass.Func = 0; break; case ProgramAction.F2: stateToPass.Func = 1; break; case ProgramAction.F3: stateToPass.Func = 2; break; case ProgramAction.F4: stateToPass.Func = 3; break; case ProgramAction.F5: stateToPass.Func = 4; break; } stateSet.Add(state); ProgramExecutionResult result = CanBeSolvedWithDfs(stateSet, eatenStarsMask, ref stateToPass, ref starsEaten, program); stateSet.Remove(state); state.Position = stateToPass.Position; state.Dir = stateToPass.Dir; if (result != ProgramExecutionResult.StillWorking) { return(result); } } } return(ProgramExecutionResult.StillWorking); }
private static bool CheckIfCompleteCodeIsGood(ProgramSlot[][] programCode) { // Check if program contains any forward instructions bool forwardInstructionFound = false; foreach (ProgramSlot[] funcCode in programCode) foreach (ProgramSlot programSlot in funcCode) { if (programSlot.Action == ProgramAction.Forward) { forwardInstructionFound = true; break; } } // Program with no forward instructions is bad if (!forwardInstructionFound) return false; return true; }
private static bool SkipDueToOptimizations(ProgramSlot[] code, int funcIndex, int depth, ProgramAction action, FieldColor color) { // Rotation code optimization if ((action == ProgramAction.Left || action == ProgramAction.Right) && depth > 0) { // Do not use consequent opposite rotations with the same color if (code[depth - 1].Color == color && ((code[depth - 1].Action == ProgramAction.Left && action == ProgramAction.Right) || (code[depth - 1].Action == ProgramAction.Right && action == ProgramAction.Left))) { return true; } // Consequent rotation count optimization int i = depth - 1; int sameCount = 1; while (i >= 0 && code[i].Color == color && code[i].Action == action) { sameCount += 1; i -= 1; } // Max 2 rotations right and 1 rotation left if ((sameCount > 2 && action == ProgramAction.Right) || (sameCount > 1 && action == ProgramAction.Left)) return true; } // Recursion optimization - do not call function from itself in the first instruction if (depth == 0 && funcIndex == 0 && action == ProgramAction.F1 || depth == 0 && funcIndex == 1 && action == ProgramAction.F2 || depth == 0 && funcIndex == 2 && action == ProgramAction.F3 || depth == 0 && funcIndex == 3 && action == ProgramAction.F4 || depth == 0 && funcIndex == 4 && action == ProgramAction.F5) { return true; } return false; }
public Program(ProgramSlot[][] programCode) { this.programCode = new ProgramSlot[programCode.Length][]; for (int i = 0; i < programCode.Length; ++i) this.programCode[i] = (ProgramSlot[])programCode[i].Clone(); }
private static bool GenerateProgramsDfs( IEnumerable<FieldColor> colors, IEnumerable<ProgramAction> actions, int func, ProgramSlot[][] generatedCode, Predicate<Program> shouldStopPredicate) { if (func >= generatedCode.Length) { if (!CheckIfCompleteCodeIsGood(generatedCode)) return false; return shouldStopPredicate(new Program(generatedCode)); } Predicate<ProgramSlot[]> funcCodePredicate = ( code => { generatedCode[func] = (ProgramSlot[])code.Clone(); return GenerateProgramsDfs(colors, actions, func + 1, generatedCode, shouldStopPredicate); }); return GenerateFuncCodeDfs(func, colors, actions, 0, new ProgramSlot[generatedCode[func].Length], funcCodePredicate); }
private static bool GenerateFuncCodeDfs( int funcIndex, IEnumerable<FieldColor> colors, IEnumerable<ProgramAction> actions, int depth, ProgramSlot[] funcCode, Predicate<ProgramSlot[]> funcCodePredicate) { foreach (ProgramAction action in actions) foreach (FieldColor color in colors) { if (SkipDueToOptimizations(funcCode, funcIndex, depth, action, color)) continue; funcCode[depth].Action = action; funcCode[depth].Color = color; if (funcCodePredicate(funcCode)) return true; if (action != ProgramAction.None && depth < funcCode.Length - 1) { if (GenerateFuncCodeDfs(funcIndex, colors, actions, depth + 1, funcCode, funcCodePredicate)) return true; } funcCode[depth].Action = ProgramAction.None; funcCode[depth].Color = FieldColor.None; } return false; }