Show / Hide Table of Contents

    Create the Model-class

    Prerequisites

    • The Instantiation of Business Objects

    Create the Model-class

    In this example a Sudoku is solved. The constraints are, that in each column and row the numbers from 1-9 occur exactly once. Additionally the board of size 9x9 is divided into 9 sections of size 3x3, which are created by splitting the board into thirds vertically and horizontally. In these sections the numbers 1-9 must occur only once.

    Model Generator Class

    SudokuModel.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Sudoku
    {
        using OPTANO.Modeling.Optimization;
        using OPTANO.Modeling.Optimization.Enums;
        using OPTANO.Modeling.Optimization.Operators;
        /// <summary>
        /// A Sudoku Model
        /// </summary>
        class SudokuModel
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="SudokuModel"/> class and initializes all fields
            /// </summary>
            /// <param name="size">
            /// the size of the Sudoku
            /// </param>
            /// <param name="section">
            /// the sections of the Sudoku
            /// </param>
            /// <param name="game">
            /// the initial setting for the Sudoku
            /// </param>
            public SudokuModel(List<int> size, IEnumerable<IGrouping<int,int>> section, int?[,] game)
            {
                this.Size = size;
                this.Section = section;
                this.Game = game;
    
                this.Model = new Model();
    
                // Variable for setting remaining values in the game
                this.field = new VariableCollection<int, int, int>(
                                this.Model,
                                this.Size,
                                this.Size,
                                this.Size,
                                "Value",
                                (col, row, number) => $"col{col}, row{row}: {number}",
                                (col, row, number) => 0,
                                (col, row, number) => 1,
                                (col, row, number) => VariableType.Binary);
    
                // Create Constraints
    
                // Only one number per field
                foreach (var row in this.Size)
                {
                    foreach (var col in this.Size)
                    {
                        this.Model.AddConstraint(
                            Expression.Sum(this.Size.Select(value => this.field[col, row, value])) == 1,
                            string.Format($"Limit_row{row}_col{col}"));
                    }
                }
    
    
                // Each number once in every row
                foreach (var row in this.Size)
                {
                    foreach (var value in this.Size)
                    {
                        this.Model.AddConstraint(
                            Expression.Sum(this.Size.Select(col => this.field[col, row, value])) == 1,
                            string.Format($"Limit_row{row}_value{value}"));
                    }
                }
    
                // Each number once in every column
                foreach (var col in this.Size)
                {
                    foreach (var value in this.Size)
                    {
                        this.Model.AddConstraint(
                            Expression.Sum(this.Size.Select(row => this.field[col, row, value])) == 1,
                            string.Format($"Limit_col{col}_value{value}"));
                    }
                }
    
                foreach (var colSection in this.Section)
                {
                    foreach (var rowSection in this.Section)
                    {
                        foreach (var value in this.Size)
                        {
                            this.Model.AddConstraint(
                                Expression.Sum(colSection.SelectMany(col => rowSection.Select(row => this.field[col, row, value]))) == 1,
                                string.Format($"$Limit_colSection{colSection.Key}_rowSection{rowSection.Key}_value{value}"));
                        }
                    }
                }
    
    
                foreach (var col in this.Size)
                {
                    foreach (var row in this.Size)
                    {
                        if (this.Game[row, col] != null)
                        {
                            var value = this.Game[row, col].Value - 1;
    
                            this.Model.AddConstraint(
                                this.field[col, row, value] == 1,
                                string.Format($"Game_row{row}_col{col}_Value{value}"));
                        }
                    }
                }
    
                // Note: this model does not need an objective function since it is a pure constraint problem
            }
            /// <summary>
            /// Gets the Model instance
            /// </summary>
            public Model Model;
    
            /// <summary>
            /// Gets the size of the Sudoku
            /// </summary>
            public List<int> Size;
    
            /// <summary>
            /// Gets the different sections
            /// </summary>
            public IEnumerable<IGrouping<int,int>> Section;
    
            /// <summary>
            /// Gets the pre-set game (already set fields)
            /// </summary>
            public int?[,] Game;
    
            /// <summary>
            /// Gets the collection of decision variables (x,y,z) is there a value of z on field (x,y)
            /// if yes -> 1 if not -> 0
            /// </summary>
            public VariableCollection<int, int, int> field;
        }
    }
    

    Next Step

    • Retrieve the Solution
    Back to top Copyright © OPTANO GmbH generated with DocFX
    Privacy Policy | Impressum – Legal Notice