/* Copyright (c) [2023] [pcm] [pcm-coordinator] is licensed under Mulan PSL v2. You can use this software according to the terms and conditions of the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPaRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ package strategy import ( "errors" "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/scheduler/algorithm/providerPricing" "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/scheduler/strategy/param" "strconv" ) type PricingStrategy struct { ProviderList []*providerPricing.Provider Task *providerPricing.Task StrategyList []*providerPricing.Strategy } func NewPricingStrategy(params *param.ResourcePricingParams) *PricingStrategy { providers := params.GetProviders() task := params.GetTask() var providerList []*providerPricing.Provider var res [][]int for _, p := range providers { p.GenMaxResourceNum(task) providerList = append(providerList, p) } providerPricing.Back_trace_task(task.Replicas, 0, providerList, 0, &res, 0) var strategyList []*providerPricing.Strategy for _, r := range res { var path []int var pathlist [][]int var resourcePerProvider []int for j, p := range providerList { if r[j] > p.MaxReplicas { resourcePerProvider = append(resourcePerProvider, p.MaxReplicas) } else { resourcePerProvider = append(resourcePerProvider, r[j]) } } providerPricing.Back_trace_resource(resourcePerProvider, 0, path, &pathlist) strategy := providerPricing.NewStrategy() strategy.Tasksolution = r strategy.Resourcesolution = pathlist strategyList = append(strategyList, strategy) } return &PricingStrategy{ProviderList: providerList, Task: task, StrategyList: strategyList} } func (ps *PricingStrategy) computeMaxScore() (*providerPricing.Task, error) { maxStrategy := providerPricing.NewStrategy() var maxprofit float64 //先计算出最大的利润值 for _, strategy := range ps.StrategyList { for _, resourceSolu := range strategy.Resourcesolution { profit := providerPricing.ComputeProfit(ps.Task, strategy.Tasksolution, resourceSolu, ps.ProviderList) if profit > maxprofit { maxprofit = profit } } } for _, strategy := range ps.StrategyList { for _, resourceSolu := range strategy.Resourcesolution { profit := providerPricing.ComputeProfit(ps.Task, strategy.Tasksolution, resourceSolu, ps.ProviderList) highDegree := providerPricing.ComputeHighDegree(ps.Task, resourceSolu, ps.ProviderList) valueSum := profit/maxprofit + highDegree //将每个确定任务分配策略的最高的策略得分存储到里面 if valueSum > maxStrategy.ValueSum { strategy.Profit = profit strategy.HighDegree = highDegree } if valueSum > maxStrategy.ValueSum { maxStrategy.ValueSum = valueSum maxStrategy.Tasksolution = strategy.Tasksolution newResourceSolu := [][]int{} newResourceSolu = append(newResourceSolu, resourceSolu) maxStrategy.Resourcesolution = newResourceSolu maxStrategy.Profit = profit maxStrategy.HighDegree = highDegree } } } if len(ps.ProviderList) == 0 { return nil, errors.New("empty providers") } ps.Task.MaxscoreStrategy = maxStrategy // 记录该任务的最终分配策略 return ps.Task, nil } func (ps *PricingStrategy) produceMaxScoreStrategy() (*providerPricing.Strategy, error) { task, err := ps.computeMaxScore() if err != nil { return nil, err } //计算任务i的resourcePerTask属性 for i, _ := range ps.ProviderList { tasksolu := task.MaxscoreStrategy.Tasksolution[i] // 第j个提供商分到的任务数 resourcesolu := task.MaxscoreStrategy.Resourcesolution[0][i] // 第j个提供商分到的资源数 // 在第j个云提供商处声明一个长度为资源数的链表 resourcePerTaskPerProviders := make([]int, resourcesolu) if tasksolu > 0 { for tasksolu > 0 { for j := 0; j < resourcesolu; j++ { resourcePerTaskPerProviders[j] += 1 tasksolu -= 1 } } } else if tasksolu == 0 { resourcePerTaskPerProviders = []int{0} } task.ResourcePerTask = append(task.ResourcePerTask, resourcePerTaskPerProviders) } return task.MaxscoreStrategy, nil } func (ps *PricingStrategy) Schedule() ([]*AssignedCluster, error) { strategy, err := ps.produceMaxScoreStrategy() if err != nil { return nil, err } if len(strategy.Tasksolution) == 0 { return nil, errors.New("调度失败, 未能获取调度结果") } var results []*AssignedCluster for i, e := range strategy.Tasksolution { if e == 0 { continue } cluster := &AssignedCluster{ClusterId: strconv.FormatInt(ps.ProviderList[i].Pid, 10), Replicas: int32(e)} results = append(results, cluster) } if len(results) == 0 { return nil, errors.New("可用集群为空") } return results, nil }