javascriptnode.jstypescriptnestjsnest

Nest can't resolve dependencies of the (?) Population


I m coded class scheduling with genetic algorithm (nest.js). My Program have geneticalgorithm.ts, data.ts ,population.ts, scheduleservice.ts schedulemodule.ts. population is called in the method I use in geneticalgorithmclass. as constructor. and I need to pass population.getSchedules().length as a number to the constructor. but I get this error. geneticalgorithm.ts population.ts and schedulemodule.ts are as follows.

error definition;

[Nest] 63732  - 11/11/2024, 6:51:23 PM     LOG [NestFactory] Starting Nest application...
[Nest] 63732  - 11/11/2024, 6:51:23 PM     LOG [InstanceLoader] AppModule dependencies initialized +54ms
[Nest] 63732  - 11/11/2024, 6:51:23 PM     LOG [Instance Loader] Type Orm Module dependencies initialized +0ms
[Nest] 63732  - 11/11/2024, 6:51:23 PM     LOG [Instance Loader] Number dependencies initialized +1ms

[Nest] 63732  - 11/11/2024, 6:51:23 PM   ERROR [Exception Handler] Nest can't resolve dependencies of the Population (?, Data). Please make sure that the argument Number at index [0] is available in the ScheduleModule context.

Potential solutions:
- Is ScheduleModule a valid NestJS module?
- If Number is a provider, is it part of the current ScheduleModule?
- If Number is exported from a separate @Module, is that module imported within ScheduleModule?
  @Module({
    imports: [ /* the Module containing Number */ ]
  })

    import { Injectable } from '@nestjs/common';
    import { Data } from './data';
    import { Population } from './population';
    import { Schedule } from './schedule';
    import { Driver } from './driver';
    
    @Injectable()
    export class GeneticAlgorithm {
      private data: Data;
    
      constructor(data: Data) {
        this.data = data;
      }
    
      public evolve(population: Population): Population {
        return this.mutatePopulation(this.crossoverPopulation(population));
      }
    
      private crossoverPopulation(population: Population): Population {
        const crossoverPopulation = new Population(population.getSchedules().length, this.data);
        for (let i = 0; i < Driver.NUMB_OF_ELITE_SCHEDULES; i++) {
          crossoverPopulation.getSchedules()[i] = population.getSchedules()[i];
        }
        for (let i = Driver.NUMB_OF_ELITE_SCHEDULES; i < population.getSchedules().length; i++) {
          if (Driver.CROSSOVER_RATE > Math.random()) {
            const schedule1 = this.selectTournamentPopulation(population).sortByFitness().getSchedules()[0];
            const schedule2 = this.selectTournamentPopulation(population).sortByFitness().getSchedules()[0];
            crossoverPopulation.getSchedules()[i] = this.crossoverSchedule(schedule1, schedule2);
          } else {
            crossoverPopulation.getSchedules()[i] = population.getSchedules()[i];
          }
        }
        return crossoverPopulation;
      }
    
      private crossoverSchedule(schedule1: Schedule, schedule2: Schedule): Schedule {
        const crossoverSchedule = new Schedule(this.data).initialize();
        for (let i = 0; i < crossoverSchedule.getClasses().length; i++) {
          if (Math.random() > 0.5) {
            crossoverSchedule.getClasses()[i] = schedule1.getClasses()[i];
          } else {
            crossoverSchedule.getClasses()[i] = schedule2.getClasses()[i];
          }
        }
        return crossoverSchedule;
      }
    
      private mutatePopulation(population: Population): Population {
        const mutatePopulation = new Population(population.getSchedules().length, this.data);
        const schedules = mutatePopulation.getSchedules();
        for (let i = 0; i < Driver.NUMB_OF_ELITE_SCHEDULES; i++) {
          schedules[i] = population.getSchedules()[i];
        }
        for (let i = Driver.NUMB_OF_ELITE_SCHEDULES; i < population.getSchedules().length; i++) {
          schedules[i] = this.mutateSchedule(population.getSchedules()[i]);
        }
        return mutatePopulation;
      }
    
      private mutateSchedule(schedule: Schedule): Schedule {
        const mutateSchedule = new Schedule(this.data).initialize();
        for (let i = 0; i < schedule.getClasses().length; i++) {
          if (Driver.MUTATION_RATE > Math.random()) {
            schedule.getClasses()[i] = mutateSchedule.getClasses()[i];
          }
        }
        return schedule;
      }
    
      private selectTournamentPopulation(population: Population): Population {
        const tournamentPopulation = new Population(Driver.TOURNAMENT_SELECTION_SIZE, this.data);
        for (let i = 0; i < Driver.TOURNAMENT_SELECTION_SIZE; i++) {
          tournamentPopulation.getSchedules()[i] = population.getSchedules()[Math.floor(Math.random() * population.getSchedules().length)];
        }
        return tournamentPopulation;
      }
    }


    import { Injectable } from '@nestjs/common';
    import { Data } from './data';
    import { Schedule } from './schedule';
    
    @Injectable()
    export class Population {
      private schedules: Schedule[];
    
      constructor(size: number, data: Data) {
        this.schedules = new Array<Schedule>(size);
        for (let i = 0; i < size; i++) {
          this.schedules[i] = new Schedule(data).initialize();
        }
      }
    
      public getSchedules(): Schedule[] {
        return this.schedules;
      }
    
      public sortByFitness(): Population {
        this.schedules.sort((schedule1, schedule2) => {
          let returnValue = 0;
          if (schedule1.getFitness() > schedule2.getFitness()) returnValue = -1;
          else if (schedule1.getFitness() < schedule2.getFitness()) returnValue = 1;
          return returnValue;
        });
        return this;
      }
    }


    import { Module } from '@nestjs/common';
    import { TypeOrmModule } from '@nestjs/typeorm';
    import { Schedule } from './schedule.entity';
    import { ScheduleService } from './schedule.service';
    import { ScheduleController } from './schedule.controller';
    import { ScheduleRepository } from './schedule.repository';
    import { Data } from './data';
    import { GeneticAlgorithm } from './genetic-algorithm';
    import { Population } from './population';
    import { Class } from './class.entity';
    import { CourseModule } from '../course/course.module';
    import { DepartmentModule } from '../department/department.module';
    import { InstructorModule } from '../instructor/instructor.module';
    import { MeetingTimeModule } from '../meeting-time/meeting-time.module';
    import { RoomModule } from '../room/room.module';
    
    @Module({
      imports: [
        TypeOrmModule.forFeature([Schedule, Class]),
        CourseModule,
        DepartmentModule,
        InstructorModule,
        MeetingTimeModule,
        RoomModule,
      ],
      providers: [ScheduleService, ScheduleRepository, Data, GeneticAlgorithm, Population],
        
    
      controllers: [ScheduleController],
    })
    export class ScheduleModule {}


Solution

  • NestJS uses constructor-based injection so as you're saying that Population is a nestjs provider, you must tell how to resolve the size and data providers as well.

    This is pretty basic stuff that you should be able to grasp by reading the docs site: https://docs.nestjs.com

    You can address that by creating custom providers and using them for those data and size parameters or adding the @Optional() parameter decorator on them to tell that they are optional providers.