/// <summary> /// or-toolsの検証 /// 小さいサイズの問題を解けるかどうか試しにやってみる /// </summary> public void SolvSmallProblemByOrTools() { // フィールドとスタンプの生成 int field_size = 64; // 今回の例では正方形なので縦横共通 string field_str = Shape.star; int stamp_size = 4; // 今回の例では正方形なので縦横共通 string stamp_str = stamp_size.ToString() + ";" + stamp_size.ToString() + ";" + "1111" + "0101" + "0110" + "1110"; Field field = new Field(); field.SetTargetField(field_str); Stamp stamp = new Stamp(0, stamp_str); // CpModelに変数を追加 CpModel model = new CpModel(); Dictionary <Tuple <int, int>, IntVar> stamp_variables = new Dictionary <Tuple <int, int>, IntVar>(); Dictionary <Tuple <int, int>, IntVar> field_variables = new Dictionary <Tuple <int, int>, IntVar>(); // スタンプ変数 for (int y = (stamp_size - 1) * (-1); y < field_size; ++y) { for (int x = (stamp_size - 1) * (-1); x < field_size; ++x) { string name = "stamp_" + y.ToString() + "_" + x.ToString(); stamp_variables[new Tuple <int, int>(y, x)] = model.NewBoolVar(name); } } // フィールド変数 for (int y = 0; y < field_size; ++y) { for (int x = 0; x < field_size; ++x) { string name = "field" + y.ToString() + "_" + x.ToString(); field_variables[new Tuple <int, int>(y, x)] = model.NewBoolVar(name); } } List <Tuple <short, short> > field_black_cell_coordinates = field.GetBlackCellCoordinates(); foreach (var field_cell in field_black_cell_coordinates) { List <IntVar> var_take_xors = new List <IntVar>(); List <Tuple <short, short> > stamp_black_cell_coordinates = stamp.GetBlackCellCoordinate(); foreach (var stamp_cell in stamp_black_cell_coordinates) { int y_ind = field_cell.Item1 - stamp_cell.Item1; int x_ind = field_cell.Item2 - stamp_cell.Item2; var_take_xors.Add(stamp_variables[new Tuple <int, int>(y_ind, x_ind)]); } model.AddBoolXor(var_take_xors); } List <Tuple <short, short> > field_white_cell_coordinates = field.GetWhiteCellCoordinates(); foreach (var field_cell in field_white_cell_coordinates) { List <IntVar> var_take_xors = new List <IntVar>(); List <Tuple <short, short> > stamp_black_cell_coordinates = stamp.GetBlackCellCoordinate(); foreach (var stamp_cell in stamp_black_cell_coordinates) { int y_ind = field_cell.Item1 - stamp_cell.Item1; int x_ind = field_cell.Item2 - stamp_cell.Item2; var_take_xors.Add(stamp_variables[new Tuple <int, int>(y_ind, x_ind)]); } // target fieldの情報を制約に追加. List <IntVar> field_variable = new List <IntVar>(); field_variable.Add(field_variables[new Tuple <int, int>(field_cell.Item1, field_cell.Item2)]); model.AddBoolAnd(field_variable); var_take_xors.Add(field_variables[new Tuple <int, int>(field_cell.Item1, field_cell.Item2)]); model.AddBoolXor(var_take_xors); } // 求解 CpSolver solver = new CpSolver(); solver.StringParameters = "max_time_in_seconds:5.0"; Console.WriteLine("start!!\n"); CpSolverStatus status = solver.Solve(model); // 解の検証 Console.WriteLine("Pressing stamp is:"); if (status == CpSolverStatus.Feasible) { for (int y = (stamp_size - 1) * (-1); y < field_size; ++y) { for (int x = (stamp_size - 1) * (-1); x < field_size; ++x) { Tuple <int, int> cur_pos = new Tuple <int, int>(y, x); if (solver.Value(stamp_variables[cur_pos]) == 1) { field.PressStamp(stamp, (short)x, (short)y); Console.Write("1"); } else { Console.Write("0"); } } Console.WriteLine(); } Console.WriteLine("\nmy_field is :"); field.PrintMyself(); Console.WriteLine("\ntarget_field is :"); field.PrintTargetField(); } }